Skip to content

Commit 41d169b

Browse files
authored
update: supabase edge functions tutorial (#492)
1 parent 65fedf4 commit 41d169b

File tree

1 file changed

+132
-83
lines changed

1 file changed

+132
-83
lines changed

src/content/docs/tutorials/drizzle-on-the-edge/drizzle-with-supabase-edge-functions.mdx

Lines changed: 132 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,63 @@
11
---
22
title: "Drizzle with Supabase Edge Functions"
33
date: "2024-05-03"
4-
svgs: ['<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="9.63139" height="40.8516" rx="4.8157" transform="matrix(0.873028 0.48767 -0.497212 0.867629 43.4805 67.3037)" fill="currentColor"></rect><rect width="9.63139" height="40.8516" rx="4.8157" transform="matrix(0.873028 0.48767 -0.497212 0.867629 76.9395 46.5342)" fill="currentColor"></rect><rect width="9.63139" height="40.8516" rx="4.8157" transform="matrix(0.873028 0.48767 -0.497212 0.867629 128.424 46.5352)" fill="currentColor"></rect><rect width="9.63139" height="40.8516" rx="4.8157" transform="matrix(0.873028 0.48767 -0.497212 0.867629 94.957 67.3037)" fill="currentColor"></rect></svg>', <svg width="24" height="25" viewBox="0 0 24 25" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M13.3501 21.1611C12.9303 21.6898 12.079 21.4002 12.0689 20.7251L11.921 10.8511H18.5603C19.7628 10.8511 20.4335 12.24 19.6857 13.1818L13.3501 21.1611Z" /><path d="M10.6499 5.27307C11.0697 4.7443 11.921 5.03403 11.9311 5.70913L11.996 15.5831H5.43981C4.23723 15.5831 3.56652 14.1942 4.31432 13.2524L10.6499 5.27307Z"/></svg>]
54
---
65

76
import Prerequisites from "@mdx/Prerequisites.astro";
87
import Npm from '@mdx/Npm.astro';
98
import Steps from '@mdx/Steps.astro';
109
import Section from "@mdx/Section.astro";
10+
import Callout from '@mdx/Callout.astro';
1111

1212
This tutorial demonstrates how to use Drizzle ORM with [Supabase Edge Functions](https://supabase.com/docs/guides/functions).
1313

1414
<Prerequisites>
1515
- You should have the latest version of [Supabase CLI](https://supabase.com/docs/guides/cli/getting-started#installing-the-supabase-cli) installed.
16-
- You should have installed Drizzle ORM and [Drizzle kit](/docs/kit-overview). You can do this by running the following command:
16+
- You should have installed Drizzle ORM and [Drizzle kit](https://orm.drizzle.team/kit-docs/overview). You can do this by running the following command:
1717
<Npm>
1818
drizzle-orm
1919
-D drizzle-kit
2020
</Npm>
2121
- You should have installed Docker Desktop. It is a prerequisite for local development. Follow the official [docs](https://docs.docker.com/desktop) to install.
2222
</Prerequisites>
2323

24-
2524
To learn how to create a basic Edge Function on your local machine and then deploy it, see the [Edge Functions Quickstart](https://supabase.com/docs/guides/functions/quickstart).
2625

2726
<Steps>
27+
#### Create a table
28+
29+
Create a `schema.ts` file in your `src` directory and declare a table schema:
30+
31+
```typescript copy filename="src/schema.ts"
32+
import { pgTable, serial, text, integer } from "drizzle-orm/pg-core";
33+
34+
export const usersTable = pgTable('users_table', {
35+
id: serial('id').primaryKey(),
36+
name: text('name').notNull(),
37+
age: integer('age').notNull()
38+
})
39+
```
40+
41+
This file will be used to generate migrations for your database.
42+
43+
#### Setup Drizzle config file
44+
45+
**Drizzle config** - a configuration file that is used by [Drizzle Kit](https://orm.drizzle.team/kit-docs/overview) and contains all the information about your database connection, migration folder and schema files.
46+
47+
Create a `drizzle.config.ts` file in the root of your project and add the following content:
48+
49+
```typescript copy filename="drizzle.config.ts"
50+
import { defineConfig } from "drizzle-kit";
51+
52+
export default defineConfig({
53+
schema: "./src/schema.ts",
54+
out: "./supabase/migrations",
55+
dialect: "postgresql",
56+
});
57+
```
58+
59+
In this tutorial we will use Drizzle kit to generate migrations for our schema.
60+
2861
#### Initialize a new Supabase project
2962

3063
Create a new Supabase project in a folder on your local machine:
@@ -42,6 +75,36 @@ It will create `supabase` folder with `config.toml` file:
4275

4376
If you are using Visual Studio Code, follow the [Supabase documentation](https://supabase.com/docs/guides/functions/local-development#deno-with-visual-studio-code) to setup settings for Deno.
4477

78+
#### Generate migrations
79+
80+
Run the `drizzle-kit generate` command to generate migrations:
81+
82+
```bash copy
83+
npx drizzle-kit generate
84+
```
85+
86+
It will create a new migration file in the `supabase/migrations` directory:
87+
88+
#### Apply migrations
89+
90+
To start the Supabase local development stack, run the following command:
91+
92+
```bash copy
93+
supabase start
94+
```
95+
96+
To apply migrations, run the following command:
97+
98+
```bash copy
99+
supabase migration up
100+
```
101+
102+
You can read more about Supabase migrations in the [documentation](https://supabase.com/docs/guides/deployment/database-migrations).
103+
104+
<Callout type="warning">Don't forget to run Docker</Callout>
105+
106+
Alternatively, you can apply migrations using the `drizzle-kit migrate` command. Learn more about this migration process in the [documentation](https://orm.drizzle.team/docs/migrations).
107+
45108
#### Create a new Edge Function
46109

47110
Run the `supabase functions new [FUNCTION_NAME]` command to create a new Edge Function:
@@ -56,115 +119,101 @@ It will create a new folder with the function name in the `supabase/functions` d
56119
└── supabase
57120
└── functions
58121
│ └── drizzle-tutorial
122+
│ │ ├── .npmrc ## Function-specific npm configuration (if needed)
123+
│ │ ├── deno.json ## Function-specific Deno configuration
59124
│ │ └── index.ts ## Your function code
60125
```
61126

127+
When you create a new Edge Function, it will use TypeScript by default. However, it is possible write Edge Function in JavaScript. Learn more about it in the [documentation](https://supabase.com/docs/guides/functions/quickstart#not-using-typescript).
128+
62129
#### Setup imports
63130

64-
Create a `import_map.json` file in the `supabase/functions` directory and add import for Drizzle ORM:
131+
Add the following imports to the `deno.json` file in the `supabase/functions/drizzle-tutorial` directory:
65132

66-
```json copy filename="supabase/functions/import_map.json"
133+
```json copy filename="supabase/functions/drizzle-tutorial/deno.json"
67134
{
68135
"imports": {
69-
"drizzle-orm": "npm:drizzle-orm@0.30.10",
70-
"drizzle-orm/": "npm:/[email protected]/"
136+
"drizzle-orm/": "npm:/drizzle-orm/",
137+
"postgres": "npm:postgres"
71138
}
72139
}
73140
```
74141

75-
Learn more in the [documentation](https://supabase.com/docs/guides/functions/import-maps).
142+
You can read more about managing dependencies [here](https://supabase.com/docs/guides/functions/dependencies#managing-dependencies).
76143

77-
#### Create a table
144+
#### Copy your schema to the functions directory
78145

79-
Create a `schema.ts` file in the `supabase/functions/common` directory and declare a table schema:
146+
Copy the code that you will use in your edge function from `src/schema.ts` file to the `supabase/functions/drizzle-tutorial/index.ts` file:
80147

81-
```typescript copy filename="supabase/functions/common/schema.ts"
148+
```typescript copy filename="supabase/functions/drizzle-tutorial/index.ts"
149+
// Setup type definitions for built-in Supabase Runtime APIs
150+
import "jsr:@supabase/functions-js/edge-runtime.d.ts"
82151
import { pgTable, serial, text, integer } from "drizzle-orm/pg-core";
83152

84-
export const usersTable = pgTable('users_table', {
153+
const usersTable = pgTable('users_table', {
85154
id: serial('id').primaryKey(),
86155
name: text('name').notNull(),
87-
age: integer('age').notNull(),
88-
email: text('email').notNull().unique(),
156+
age: integer('age').notNull()
89157
})
90-
```
91-
92-
#### Setup Drizzle config file
93-
94-
**Drizzle config** - a configuration file that is used by [Drizzle Kit](/docs/kit-overview) and contains all the information about your database connection, migration folder and schema files.
95-
96-
Create a `drizzle.config.ts` file in the root of your project and add the following content:
97-
98-
```typescript copy filename="drizzle.config.ts"
99-
import { defineConfig } from "drizzle-kit";
100-
101-
export default defineConfig({
102-
schema: "./supabase/functions/common/schema.ts",
103-
out: "./supabase/migrations",
104-
dialect: "postgresql",
105-
});
106-
```
107-
108-
In this tutorial we will use Drizzle kit to generate migrations for our schema.
109-
110-
#### Generate migrations
111-
112-
Run the `drizzle-kit generate` command to generate migrations:
113158

114-
```bash copy
115-
npx drizzle-kit generate
116-
```
117-
118-
It will create a new migration file in the `supabase/migrations` directory:
119-
120-
#### Apply migrations
121-
122-
To apply migrations and start the Supabase local development stack, run the following command:
159+
Deno.serve(async (req) => {
160+
const { name } = await req.json()
161+
const data = {
162+
message: `Hello ${name}!`,
163+
}
123164

124-
```bash copy
125-
supabase start
165+
return new Response(
166+
JSON.stringify(data),
167+
{ headers: { "Content-Type": "application/json" } },
168+
)
169+
})
126170
```
127171

128-
Alternatively, you can apply migrations using the `migrate()` helper, available for every supported driver. Learn more about this migration process in the [documentation](/docs/migrations).
172+
<Callout type="warning">
173+
In the Deno ecosystem, each function should be treated as an independent project with its own set of dependencies and configurations.
174+
For these reasons, Supabase recommend maintaining separate configuration files (`deno.json`, `.npmrc`, or `import_map.json`) within each function's directory, even if it means duplicating some configurations. Read more [here](https://supabase.com/docs/guides/functions/dependencies#managing-dependencies).
175+
</Callout>
129176

130177
#### Connect Drizzle ORM to your database
131178

132-
Create a `db.ts` file in the `supabase/common` directory and set up your database configuration:
179+
Update your edge function code with your database configuration:
133180

134-
```typescript copy filename="supabase/functions/common/db.ts"
135-
import postgres from "npm:postgres";
181+
```typescript copy filename="supabase/functions/drizzle-tutorial/index.ts" {14,17,18}
182+
// Setup type definitions for built-in Supabase Runtime APIs
183+
import { integer, pgTable, serial, text } from "drizzle-orm/pg-core";
136184
import { drizzle } from "drizzle-orm/postgres-js";
185+
import "jsr:@supabase/functions-js/edge-runtime.d.ts";
186+
import postgres from "postgres";
137187

138-
const connectionString = Deno.env.get("SUPABASE_DB_URL")!;
139-
140-
// Disable prefetch as it is not supported for "Transaction" pool mode
141-
const client = postgres(connectionString, { prepare: false });
142-
export const db = drizzle({ client });
143-
```
144-
145-
`SUPABASE_DB_URL` is default environment variable for the direct database connection. Learn more about managing environment variables in Supabase Edge Functions in the [documentation](https://supabase.com/docs/guides/functions/secrets).
188+
const usersTable = pgTable('users_table', {
189+
id: serial('id').primaryKey(),
190+
name: text('name').notNull(),
191+
age: integer('age').notNull()
192+
})
146193

147-
#### Test your code locally
194+
Deno.serve(async () => {
195+
const connectionString = Deno.env.get("SUPABASE_DB_URL")!;
148196

149-
```typescript copy filename="supabase/functions/drizzle-tutorial/index.ts"
150-
import { db } from "../common/db.ts";
151-
import { usersTable } from "../common/schema.ts";
197+
// Disable prefetch as it is not supported for "Transaction" pool mode
198+
const client = postgres(connectionString, { prepare: false });
199+
const db = drizzle({ client });
152200

153-
Deno.serve(async (req) => {
154201
await db.insert(usersTable).values({
155202
name: "Alice",
156-
email: "email",
157203
age: 25
158204
})
159205
const data = await db.select().from(usersTable);
160206

161207
return new Response(
162-
JSON.stringify(data),
163-
{ headers: { "Content-Type": "application/json" } },
164-
);
165-
});
208+
JSON.stringify(data)
209+
)
210+
})
166211
```
167212

213+
`SUPABASE_DB_URL` is default environment variable for the direct database connection. Learn more about managing environment variables in Supabase Edge Functions in the [documentation](https://supabase.com/docs/guides/functions/secrets).
214+
215+
#### Test your code locally
216+
168217
Run the following command to test your function locally:
169218

170219
```bash copy
@@ -178,8 +227,7 @@ Navigate to the route `(e.g. /drizzle-tutorial)` in your browser:
178227
{
179228
"id": 1,
180229
"name": "Alice",
181-
"age": 25,
182-
"email": "email"
230+
"age": 25
183231
}
184232
]
185233
```
@@ -188,10 +236,10 @@ Navigate to the route `(e.g. /drizzle-tutorial)` in your browser:
188236

189237
You can create new Supabase project in the [dashboard](https://supabase.com/dashboard) or by following this [link](https://database.new/).
190238

191-
Copy the `Reference ID` and use it to link your local development project to a hosted Supabase project by running the following command:
239+
Copy the `Reference ID` from project settings and use it to link your local development project to a hosted Supabase project by running the following command:
192240

193241
```bash copy
194-
supabase link --project-ref <REFERENCE_ID>
242+
supabase link --project-ref=<REFERENCE_ID>
195243
```
196244

197245
Push your schema changes to the hosted Supabase project by running the following command:
@@ -202,26 +250,27 @@ supabase db push
202250

203251
#### Setup environment variables
204252

205-
Navigate to [Database Settings](https://supabase.com/dashboard/project/_/settings/database) and copy the URI from the `Connection String` section. Make sure to use `connection pooling` and `Transaction` mode to connect to your database. Remember to replace the password placeholder with your actual database password.
253+
You can find `Project connect details` by clicking **Connect** in the top bar of the dashboard and copy the URI from the `Transaction pooler` section. Remember to replace the password placeholder with your actual database password.
206254

207255
Read more about Connection Pooler in the [documentation](https://supabase.com/docs/guides/database/connecting-to-postgres#connection-pooler).
208256

209-
Run the following command to set the environment variable:
210-
211-
```bash copy
212-
supabase secrets set DATABASE_URL=<CONNECTION_STRING>
213-
```
214-
215-
Update the `db.ts` file in the `supabase/functions/common` directory to use the `DATABASE_URL` environment variable:
257+
Update your edge function code to use the `DATABASE_URL` environment variable instead of `SUPABASE_DB_URL`:
216258

217-
```typescript copy filename="supabase/functions/common/db.ts"
259+
```typescript copy filename="supabase/functions/drizzle-tutorial/index.ts"
218260
// imports
219261

262+
// const connectionString = Deno.env.get("SUPABASE_DB_URL")!;
220263
const connectionString = Deno.env.get("DATABASE_URL")!;
221264

222265
// code
223266
```
224267

268+
Run the following command to set the environment variable:
269+
270+
```bash copy
271+
supabase secrets set DATABASE_URL=<CONNECTION_STRING>
272+
```
273+
225274
Learn more about managing environment variables in Supabase Edge Functions in the [documentation](https://supabase.com/docs/guides/functions/secrets).
226275

227276
#### Deploy your function

0 commit comments

Comments
 (0)