Skip to content

Commit 132307a

Browse files
authoredJul 5, 2024··
feat(types): automatically pass database typings to clients (#366)
1 parent 23b0b40 commit 132307a

File tree

9 files changed

+64
-7
lines changed

9 files changed

+64
-7
lines changed
 

‎docs/content/2.get-started.md

+18
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,24 @@ Cookie name used for storing the redirect path when using the `redirect` option,
113113
114114
Options for cookies used to share tokens between server and client, refer to [cookieOptions](https://nuxt.com/docs/api/composables/use-cookie#options) for available settings. Please note that the lifetime set here does not determine the Supabase session lifetime.
115115
116+
### `types`
117+
118+
Default: `./types/database.types.ts`
119+
120+
The path for the generated Supabase TypeScript definitions. The database definitions will be automatically passed to all clients: `useSupabaseClient`, `serverSupabaseClient` and `serverSupabaseServiceRole`.
121+
122+
```shell
123+
## Generate types from live database
124+
supabase gen types typescript --project-id YourProjectId > types/database.types.ts
125+
126+
## Generate types when using local environment
127+
supabase gen types typescript --local > types/database.types.ts
128+
```
129+
130+
Set to `false` to disable.
131+
132+
Check Supabase [documentation](https://supabase.com/docs/reference/javascript/release-notes#typescript-support) for further information.
133+
116134
### `clientOptions`
117135
118136
Default:

‎docs/content/4.usage/composables/useSupabaseClient.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,17 @@ onUnmounted(() => {
101101

102102
## Typescript
103103

104-
You can pass Database typings to the client. Check Supabase [documentation](https://supabase.com/docs/reference/javascript/release-notes#typescript-support) for further information.
104+
Database typings are passed to the client out of the box if the database generated types are found at `./types/database.types.ts` or [your configured types path](/get-started#types). Check Supabase [documentation](https://supabase.com/docs/reference/javascript/release-notes#typescript-support) for further information.
105+
106+
```shell
107+
## Generate types from live database
108+
supabase gen types typescript --project-id YourProjectId > types/database.types.ts
109+
110+
## Generate types when using local environment
111+
supabase gen types typescript --local > types/database.types.ts
112+
```
113+
114+
You can also pass Database typings to the client manually:
105115

106116
```vue
107117
<script setup lang="ts">

‎playground/server/api/test.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { createError } from 'h3'
22
import { serverSupabaseClient, serverSupabaseUser, serverSupabaseSession } from '#supabase/server'
3+
import type { Database } from '#build/types/supabase-database'
34

45
export default defineEventHandler(async (event) => {
5-
const supabase = await serverSupabaseClient(event)
6+
const supabase = await serverSupabaseClient<Database>(event)
7+
68
if (!supabase) {
79
throw createError({ statusMessage: 'Supabase client not found' })
810
}

‎playground/tsconfig.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "./.nuxt/tsconfig.json"
3+
}

‎src/module.ts

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { fileURLToPath } from 'node:url'
2+
import fs from 'node:fs'
23
import { defu } from 'defu'
34
import { defineNuxtModule, addPlugin, createResolver, addTemplate, resolveModule, extendViteConfig } from '@nuxt/kit'
45
import type { CookieOptions } from 'nuxt/app'
@@ -74,6 +75,13 @@ export interface ModuleOptions {
7475
*/
7576
cookieOptions?: CookieOptions
7677

78+
/**
79+
* Path to Supabase database type definitions file
80+
* @default '~/types/database.types.ts'
81+
* @type string
82+
*/
83+
types?: string | false
84+
7785
/**
7886
* Supabase client options (overrides default options from `@supabase/ssr`)
7987
* @default { }
@@ -108,10 +116,11 @@ export default defineNuxtModule<ModuleOptions>({
108116
sameSite: 'lax',
109117
secure: true,
110118
} as CookieOptions,
119+
types: '~/types/database.types.ts',
111120
clientOptions: {} as SupabaseClientOptions<string>,
112121
},
113122
setup(options, nuxt) {
114-
const { resolve } = createResolver(import.meta.url)
123+
const { resolve, resolvePath } = createResolver(import.meta.url)
115124
const resolveRuntimeModule = (path: string) => resolveModule(path, { paths: resolve('./runtime') })
116125

117126
// Public runtimeConfig
@@ -191,7 +200,18 @@ export default defineNuxtModule<ModuleOptions>({
191200
].join('\n'),
192201
})
193202

194-
nuxt.hook('prepare:types', (options) => {
203+
addTemplate({
204+
filename: 'types/supabase-database.d.ts',
205+
getContents: async () => {
206+
if (!!options.types && fs.existsSync(await resolvePath(options.types))) {
207+
return `export * from '${await resolvePath(options.types)}'`
208+
}
209+
210+
return `export type Database = unknown`
211+
},
212+
})
213+
214+
nuxt.hook('prepare:types', async (options) => {
195215
options.references.push({ path: resolve(nuxt.options.buildDir, 'types/supabase.d.ts') })
196216
})
197217

Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { SupabaseClient } from '@supabase/supabase-js'
22
import { useNuxtApp } from '#imports'
3+
import type { Database } from '#build/types/supabase-database'
34

4-
export const useSupabaseClient = <T>() => {
5+
export const useSupabaseClient = <T = Database>() => {
56
return useNuxtApp().$supabase?.client as SupabaseClient<T>
67
}

‎src/runtime/server/services/serverSupabaseClient.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import type { SupabaseClient } from '@supabase/supabase-js'
22
import { createServerClient, parseCookieHeader, type CookieOptions } from '@supabase/ssr'
33
import { getHeader, setCookie, type H3Event } from 'h3'
44
import { useRuntimeConfig } from '#imports'
5+
import type { Database } from '#build/types/supabase-database'
56

6-
export const serverSupabaseClient = async <T>(event: H3Event): Promise<SupabaseClient<T>> => {
7+
export const serverSupabaseClient = async <T = Database>(event: H3Event): Promise<SupabaseClient<T>> => {
78
// No need to recreate client if exists in request context
89
if (!event.context._supabaseClient) {
910
// get settings from runtime config

‎src/runtime/server/services/serverSupabaseServiceRole.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import type { SupabaseClient } from '@supabase/supabase-js'
22
import { createClient } from '@supabase/supabase-js'
33
import type { H3Event } from 'h3'
44
import { useRuntimeConfig } from '#imports'
5+
import type { Database } from '#build/types/supabase-database'
56

6-
export const serverSupabaseServiceRole = <T>(event: H3Event): SupabaseClient<T> => {
7+
export const serverSupabaseServiceRole = <T = Database>(event: H3Event): SupabaseClient<T> => {
78
const {
89
supabase: { serviceKey },
910
public: {

‎src/types/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ declare module '@nuxt/schema' {
1010
redirectOptions: RedirectOptions
1111
cookieName: string
1212
cookieOptions: CookieOptions
13+
types: string | false
1314
clientOptions: SupabaseClientOptions<string>
1415
}
1516
}

0 commit comments

Comments
 (0)
Please sign in to comment.