@floatingpixels/supabase-nuxt 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +272 -62
- package/dist/module.d.mts +28 -3
- package/dist/module.d.ts +28 -3
- package/dist/module.json +1 -1
- package/dist/module.mjs +25 -2
- package/dist/runtime/plugins/supabase.client.mjs +17 -3
- package/dist/runtime/plugins/supabase.server.mjs +10 -3
- package/dist/runtime/server/services/supabaseServerClient.d.ts +1 -1
- package/dist/runtime/server/services/supabaseServerClient.mjs +3 -2
- package/dist/runtime/server/services/supabaseServiceRole.d.ts +1 -1
- package/dist/runtime/server/services/supabaseServiceRole.mjs +10 -3
- package/dist/runtime/types/index.d.ts +28 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,94 +1,304 @@
|
|
|
1
|
-
|
|
2
|
-
Get your module up and running quickly.
|
|
1
|
+
# Supabase Nuxt
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
-
|
|
6
|
-
- Package name: my-module
|
|
7
|
-
- Description: My new Nuxt module
|
|
8
|
-
-->
|
|
3
|
+

|
|
4
|
+

|
|
9
5
|
|
|
10
|
-
|
|
6
|
+
## Features
|
|
11
7
|
|
|
12
|
-
[
|
|
13
|
-
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
14
|
-
[![License][license-src]][license-href]
|
|
15
|
-
[![Nuxt][nuxt-src]][nuxt-href]
|
|
8
|
+
[@floatingpixels/supabase-nuxt](https://github.com/nuxt-modules/supabase) is a Nuxt module for first class integration with Supabase. It makes it easy to use Supabase authentication, database and realtime features in your Nuxt 3 application. Especially when using server-side rendering SSR, using Supabase can be tricky, this module takes care of the intricacies and lets you simply use the power of Supabase!
|
|
16
9
|
|
|
17
|
-
|
|
10
|
+
Checkout the [Nuxt 3](https://v3.nuxtjs.org) documentation and [Supabase](https://supabase.com) to learn more.
|
|
18
11
|
|
|
19
|
-
|
|
20
|
-
<!-- - [🏀 Online playground](https://stackblitz.com/github/your-org/my-module?file=playground%2Fapp.vue) -->
|
|
21
|
-
<!-- - [📖 Documentation](https://example.com) -->
|
|
12
|
+
## Installation
|
|
22
13
|
|
|
23
|
-
|
|
14
|
+
Add `@floatingpixels/supabase-nuxt` dev dependency to your project:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add -D @floatingpixels/supabase-nuxt
|
|
24
18
|
|
|
25
|
-
|
|
26
|
-
- ⛰ Foo
|
|
27
|
-
- 🚠 Bar
|
|
28
|
-
- 🌲 Baz
|
|
19
|
+
yarn add --dev @floatingpixels/supabase-nuxt
|
|
29
20
|
|
|
30
|
-
|
|
21
|
+
npm install @floatingpixels/supabase-nuxt --save-dev
|
|
31
22
|
|
|
32
|
-
|
|
23
|
+
bun add -D @floatingpixels/supabase-nuxt
|
|
24
|
+
```
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
# Using pnpm
|
|
36
|
-
pnpm add -D my-module
|
|
26
|
+
Add `@floatingpixels/supabase-nuxt` to the `modules` section of `nuxt.config.ts`:
|
|
37
27
|
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
```ts
|
|
29
|
+
export default defineNuxtConfig({
|
|
30
|
+
modules: ['@floatingpixels/supabase-nuxt'],
|
|
31
|
+
})
|
|
32
|
+
```
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
Add `SUPABASE_URL` and `SUPABASE_KEY` to the `.env`:
|
|
35
|
+
|
|
36
|
+
```zsh
|
|
37
|
+
SUPABASE_URL="https://example.supabase.co"
|
|
38
|
+
SUPABASE_KEY="<your_key>"
|
|
43
39
|
```
|
|
44
40
|
|
|
45
|
-
|
|
41
|
+
Alternatively, you can prefix the env variables with `NUXT_PUBLIC_` in order to use runtimeConfig.
|
|
42
|
+
|
|
43
|
+
## Options
|
|
44
|
+
|
|
45
|
+
You can configure the supabase module by using the `supabase` key in `nuxt.config`:
|
|
46
46
|
|
|
47
|
-
```
|
|
47
|
+
```ts [nuxt.config.ts]
|
|
48
48
|
export default defineNuxtConfig({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
// ...
|
|
50
|
+
supabase: {
|
|
51
|
+
// Options
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### `url`
|
|
57
|
+
|
|
58
|
+
Default: `process.env.SUPABASE_URL` (ex: `https://example.supabase.co`)
|
|
59
|
+
|
|
60
|
+
The unique Supabase URL which is supplied when you create a new project in your project dashboard.
|
|
61
|
+
|
|
62
|
+
### `key`
|
|
63
|
+
|
|
64
|
+
Default: `process.env.SUPABASE_KEY`
|
|
65
|
+
|
|
66
|
+
Supabase 'anon key', used to bypass the Supabase API gateway and interact with your Supabase database making use of user JWT to apply RLS Policies.
|
|
67
|
+
|
|
68
|
+
### `serviceKey`
|
|
69
|
+
|
|
70
|
+
Default: `process.env.SUPABASE_SERVICE_KEY`
|
|
71
|
+
|
|
72
|
+
Supabase 'service role key', has super admin rights and can bypass your Row Level Security.
|
|
73
|
+
|
|
74
|
+
### `redirect`
|
|
75
|
+
|
|
76
|
+
Default: `false`
|
|
77
|
+
|
|
78
|
+
Redirect automatically to the configured login page if a non authenticated user is navigating to a page. When set to `true` a global middleware is used to check for a logged-in supabase use on all non-excluded routes.
|
|
79
|
+
|
|
80
|
+
### `redirectOptions`
|
|
81
|
+
|
|
82
|
+
Default:
|
|
83
|
+
|
|
84
|
+
```ts [nuxt.config.ts]
|
|
85
|
+
redirectOptions: {
|
|
86
|
+
login: '/login',
|
|
87
|
+
exclude: [],
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- `login`: User will be redirected to this route if not authenticated or after logout.
|
|
92
|
+
- `exclude`: Routes to exclude from the redirect. `['/foo', '/bar/*']` will exclude the `foo` page and all pages in your `bar` folder.
|
|
93
|
+
|
|
94
|
+
### cookieOptions
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
cookieOptions: {
|
|
98
|
+
maxAge: 60 * 60 * 8,
|
|
99
|
+
sameSite: 'lax',
|
|
100
|
+
secure: true
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Options for cookies used for authentication and session management, 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.
|
|
105
|
+
|
|
106
|
+
### `clientOptions`
|
|
107
|
+
|
|
108
|
+
Default:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
clientOptions: {
|
|
112
|
+
auth: {
|
|
113
|
+
flowType: 'pkce',
|
|
114
|
+
detectSessionInUrl: true,
|
|
115
|
+
persistSession: true,
|
|
116
|
+
autoRefreshToken: true
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
A documentation of Supabase client options is [available here](https://supabase.com/docs/reference/javascript/initializing#parameters).
|
|
122
|
+
|
|
123
|
+
## Authentication
|
|
124
|
+
|
|
125
|
+
The module makes it easy to use [Supabase Auth](https://supabase.com/docs/guides/auth) in your application. In most use-cases for Supabase you'll want users to be authenticated, so you can leverage row-level security (RLS) in the database. Supabase Auth is designed to work perfectly with [RLS](https://supabase.com/docs/guides/auth/row-level-security).
|
|
126
|
+
|
|
127
|
+
All you need to do is to create a login page, when using the default module settings that's `login.vue` in the `pages` folder. On the log-in page you initiate log-in method(s) you choose from the [available authorization methods](https://supabase.com/docs/reference/javascript/auth-signinwithpassword) provided by Supabase, below is a simple example for e-mail authentication:
|
|
128
|
+
|
|
129
|
+
```vue
|
|
130
|
+
<script setup lang="ts">
|
|
131
|
+
const supabase = useSupabaseClient()
|
|
132
|
+
const email = ref('')
|
|
133
|
+
|
|
134
|
+
const signInWithOtp = async () => {
|
|
135
|
+
const { error } = await supabase.auth.signInWithOtp({
|
|
136
|
+
email: email.value,
|
|
137
|
+
options: {
|
|
138
|
+
emailRedirectTo: 'http://localhost:3000/confirm',
|
|
139
|
+
},
|
|
140
|
+
})
|
|
141
|
+
if (error) console.log(error)
|
|
142
|
+
}
|
|
143
|
+
</script>
|
|
144
|
+
<template>
|
|
145
|
+
<div>
|
|
146
|
+
<button @click="signInWithOtp">Sign In with E-Mail</button>
|
|
147
|
+
<input
|
|
148
|
+
v-model="email"
|
|
149
|
+
type="email"
|
|
150
|
+
/>
|
|
151
|
+
</div>
|
|
152
|
+
</template>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
> ⚠️ Ensure to activate and configure the authentication providers you want to use in the Supabase Dashboard under `Authentication -> Providers`.
|
|
156
|
+
|
|
157
|
+
Once the authorization flow is triggered using the `auth` wrapper of the `useSupabaseClient` composable, the session management is handled automatically.
|
|
158
|
+
|
|
159
|
+
If `redirect` is set to `true` in the module options, users will be automatically routed to this page when they are not authenticated. Each time a user is trying to access a page, they will automatically be redirected to the log-in page. If you want to allow access to "public" pages, you just need to add them in the `exclude` `redirect` option.
|
|
160
|
+
|
|
161
|
+
## Composables
|
|
162
|
+
|
|
163
|
+
### useSupabaseClient
|
|
164
|
+
|
|
165
|
+
This composable can be used to make requests to the Supabase API. It's autoimported and ready to use in your components. It's using [supabase-js](https://github.com/supabase/supabase-js/) under the hood, it gives access to the [Supabase client](https://supabase.com/docs/reference/javascript/initializing) and all of its features.
|
|
166
|
+
|
|
167
|
+
## Database Request
|
|
168
|
+
|
|
169
|
+
Please check [Supabase](https://supabase.com/docs/reference/javascript/select) documentation on how to fully use the Supabase client.
|
|
170
|
+
|
|
171
|
+
Here is an example of fetching from the database using the Supabase client's `select` method with Nuxt 3 [useAsyncData](https://nuxt.com/docs/getting-started/data-fetching#useasyncdata).
|
|
172
|
+
|
|
173
|
+
```vue
|
|
174
|
+
<script setup lang="ts">
|
|
175
|
+
const client = useSupabaseClient()
|
|
176
|
+
|
|
177
|
+
const { data: restaurant } = await useAsyncData('restaurant', async () => {
|
|
178
|
+
const { data } = await client.from('restaurants').select('name, location').eq('name', 'My Restaurant Name').single()
|
|
179
|
+
|
|
180
|
+
return data
|
|
52
181
|
})
|
|
182
|
+
</script>
|
|
53
183
|
```
|
|
54
184
|
|
|
55
|
-
|
|
185
|
+
## Realtime
|
|
56
186
|
|
|
57
|
-
|
|
187
|
+
Based on [Supabase Realtime](https://github.com/supabase/realtime), listen to changes in your PostgreSQL Database and broadcasts them over WebSockets.
|
|
58
188
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
189
|
+
To enable it, make sure you have turned on the [Realtime API](https://supabase.com/docs/guides/api#realtime-api) for your table.
|
|
190
|
+
|
|
191
|
+
Then, listen to changes directly in your vue page / component:
|
|
192
|
+
|
|
193
|
+
```vue
|
|
194
|
+
<script setup lang="ts">
|
|
195
|
+
import type { RealtimeChannel } from '@supabase/supabase-js'
|
|
196
|
+
|
|
197
|
+
const client = useSupabaseClient()
|
|
198
|
+
|
|
199
|
+
let realtimeChannel: RealtimeChannel
|
|
200
|
+
|
|
201
|
+
// Fetch collaborators and get the refresh method provided by useAsyncData
|
|
202
|
+
const { data: collaborators, refresh: refreshCollaborators } = await useAsyncData('collaborators', async () => {
|
|
203
|
+
const { data } = await client.from('collaborators').select('name')
|
|
204
|
+
return data
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
// Once page is mounted, listen to changes on the `collaborators` table and refresh collaborators when receiving event
|
|
208
|
+
onMounted(() => {
|
|
209
|
+
// Real time listener for new workouts
|
|
210
|
+
realtimeChannel = client
|
|
211
|
+
.channel('public:collaborators')
|
|
212
|
+
.on('postgres_changes', { event: '*', schema: 'public', table: 'collaborators' }, () => refreshCollaborators())
|
|
213
|
+
|
|
214
|
+
realtimeChannel.subscribe()
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
// Don't forget to unsubscribe when user left the page
|
|
218
|
+
onUnmounted(() => {
|
|
219
|
+
client.removeChannel(realtimeChannel)
|
|
220
|
+
})
|
|
221
|
+
</script>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Typescript
|
|
225
|
+
|
|
226
|
+
You can pass Database typings to the client. Check Supabase [documentation](https://supabase.com/docs/reference/javascript/release-notes#typescript-support) for further information.
|
|
62
227
|
|
|
63
|
-
|
|
64
|
-
|
|
228
|
+
```vue
|
|
229
|
+
<script setup lang="ts">
|
|
230
|
+
import type { Database } from '~/types'
|
|
231
|
+
const client = useSupabaseClient<Database>()
|
|
232
|
+
</script>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Authentication
|
|
65
236
|
|
|
66
|
-
|
|
67
|
-
npm run dev
|
|
237
|
+
The useSupabaseClient composable is providing all methods to manage authorization under `useSupabaseClient().auth`. For more details please see the [supabase-js auth documentation](https://supabase.com/docs/reference/javascript/auth-api). Here is an example for signing in and out:
|
|
68
238
|
|
|
69
|
-
|
|
70
|
-
npm run dev:build
|
|
239
|
+
> ⚠️ If you want a full explanation on how to handle the authentication process, please read this [section](#authentication).
|
|
71
240
|
|
|
72
|
-
|
|
73
|
-
|
|
241
|
+
```ts
|
|
242
|
+
<script setup lang="ts">
|
|
243
|
+
const supabase = useSupabaseClient()
|
|
74
244
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
245
|
+
const signInWithOAuth = async () => {
|
|
246
|
+
const { error } = await supabase.auth.signInWithOAuth({
|
|
247
|
+
provider: 'github',
|
|
248
|
+
options: {
|
|
249
|
+
redirectTo: 'http://localhost:3000/confirm',
|
|
250
|
+
},
|
|
251
|
+
})
|
|
252
|
+
if (error) console.log(error)
|
|
253
|
+
}
|
|
78
254
|
|
|
79
|
-
|
|
80
|
-
|
|
255
|
+
const signOut = async () => {
|
|
256
|
+
const { error } = await supabase.auth.signOut()
|
|
257
|
+
if (error) console.log(error)
|
|
258
|
+
}
|
|
259
|
+
</script>
|
|
81
260
|
```
|
|
82
261
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
262
|
+
## Server Side Services
|
|
263
|
+
|
|
264
|
+
### supabaseServerClient
|
|
86
265
|
|
|
87
|
-
[
|
|
88
|
-
[npm-downloads-href]: https://npmjs.com/package/my-module
|
|
266
|
+
Make requests to the Supabase API on server side with the supabaseServerClient service. It provides the same functionality as the `useSupabaseClient` composable, but it is designed to be used on [server routes](https://nuxt.com/docs/guide/directory-structure/server#server-routes).
|
|
89
267
|
|
|
90
|
-
|
|
91
|
-
|
|
268
|
+
On your server route import the `supabaseServerClient` from `#supabase/server`. Please note that `supabaseServerClient` is returning a promise.
|
|
269
|
+
|
|
270
|
+
```ts [server/api/libraries.ts]
|
|
271
|
+
import { supabaseServerClient } from '#supabase/server'
|
|
272
|
+
|
|
273
|
+
export default eventHandler(async event => {
|
|
274
|
+
const client = await supabaseServerClient(event)
|
|
275
|
+
|
|
276
|
+
const { data } = await client.from('libraries').select('*')
|
|
277
|
+
|
|
278
|
+
return { libraries: data }
|
|
279
|
+
})
|
|
280
|
+
```
|
|
92
281
|
|
|
93
|
-
|
|
94
|
-
|
|
282
|
+
### supabaseServiceRole
|
|
283
|
+
|
|
284
|
+
Make requests with super admin rights to the Supabase API with the `supabaseServiceRole` service. This function is designed to work only in [server routes](https://nuxt.com/docs/guide/directory-structure/server#server-routes), there is no vue composable equivalent.
|
|
285
|
+
|
|
286
|
+
It provides similar functionality as the `supabaseServerClient` but it provides a client with super admin rights that can bypass your [Row Level Security](https://supabase.com/docs/guides/auth/row-level-security).
|
|
287
|
+
|
|
288
|
+
The client is initialized with the `SUPABASE_SERVICE_KEY` you must have in your `.env` file. Checkout the doc if you want to know more about [Supabase keys](https://supabase.com/docs/learn/auth-deep-dive/auth-deep-dive-jwts#jwts-in-supabase).
|
|
289
|
+
|
|
290
|
+
> ⚠️ The service key gives admin access to your database, be careful to not expose it in your client side code or in your git repository.
|
|
291
|
+
|
|
292
|
+
In your server route use the `supabaseServiceRole` from `#supabase/server`.
|
|
293
|
+
|
|
294
|
+
```ts [server/api/bypass-rls.ts]
|
|
295
|
+
import { supabaseServiceRole } from '#supabase/server'
|
|
296
|
+
|
|
297
|
+
export default eventHandler(async event => {
|
|
298
|
+
const client = supabaseServiceRole(event)
|
|
299
|
+
|
|
300
|
+
const { data } = await client.from('rls-protected-table').select()
|
|
301
|
+
|
|
302
|
+
return { sensitiveData: data }
|
|
303
|
+
})
|
|
304
|
+
```
|
package/dist/module.d.mts
CHANGED
|
@@ -36,16 +36,41 @@ interface ModuleOptions {
|
|
|
36
36
|
redirect?: boolean
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* Redirection options, set routes for login and
|
|
39
|
+
* Redirection options, set routes for login and specify pages to exclude from redirection
|
|
40
40
|
* @default
|
|
41
41
|
* {
|
|
42
42
|
login: '/login',
|
|
43
|
-
callback: '/confirm',
|
|
44
43
|
exclude: [],
|
|
45
44
|
}
|
|
46
45
|
* @type RedirectOptions
|
|
47
46
|
*/
|
|
48
47
|
redirectOptions?: RedirectOptions
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Cookie options
|
|
51
|
+
* @default {
|
|
52
|
+
maxAge: 60 * 60 * 8,
|
|
53
|
+
sameSite: 'lax',
|
|
54
|
+
secure: true,
|
|
55
|
+
}
|
|
56
|
+
* @type CookieOptions
|
|
57
|
+
* @docs https://nuxt.com/docs/api/composables/use-cookie#options
|
|
58
|
+
*/
|
|
59
|
+
cookieOptions?: CookieOptions
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Supabase Client options
|
|
63
|
+
* @default {
|
|
64
|
+
auth: {
|
|
65
|
+
flowType: 'pkce',
|
|
66
|
+
detectSessionInUrl: true,
|
|
67
|
+
persistSession: true,
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
* @type object
|
|
71
|
+
* @docs https://supabase.com/docs/reference/javascript/initializing#parameters
|
|
72
|
+
*/
|
|
73
|
+
clientOptions?: SupabaseClientOptions<string>
|
|
49
74
|
}
|
|
50
75
|
|
|
51
76
|
interface RedirectOptions {
|
|
@@ -56,7 +81,7 @@ interface RedirectOptions {
|
|
|
56
81
|
*/
|
|
57
82
|
login?: string
|
|
58
83
|
/**
|
|
59
|
-
*
|
|
84
|
+
* Routes to exclude from redirection
|
|
60
85
|
* @default []
|
|
61
86
|
* @type string[]
|
|
62
87
|
*/
|
package/dist/module.d.ts
CHANGED
|
@@ -36,16 +36,41 @@ interface ModuleOptions {
|
|
|
36
36
|
redirect?: boolean
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* Redirection options, set routes for login and
|
|
39
|
+
* Redirection options, set routes for login and specify pages to exclude from redirection
|
|
40
40
|
* @default
|
|
41
41
|
* {
|
|
42
42
|
login: '/login',
|
|
43
|
-
callback: '/confirm',
|
|
44
43
|
exclude: [],
|
|
45
44
|
}
|
|
46
45
|
* @type RedirectOptions
|
|
47
46
|
*/
|
|
48
47
|
redirectOptions?: RedirectOptions
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Cookie options
|
|
51
|
+
* @default {
|
|
52
|
+
maxAge: 60 * 60 * 8,
|
|
53
|
+
sameSite: 'lax',
|
|
54
|
+
secure: true,
|
|
55
|
+
}
|
|
56
|
+
* @type CookieOptions
|
|
57
|
+
* @docs https://nuxt.com/docs/api/composables/use-cookie#options
|
|
58
|
+
*/
|
|
59
|
+
cookieOptions?: CookieOptions
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Supabase Client options
|
|
63
|
+
* @default {
|
|
64
|
+
auth: {
|
|
65
|
+
flowType: 'pkce',
|
|
66
|
+
detectSessionInUrl: true,
|
|
67
|
+
persistSession: true,
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
* @type object
|
|
71
|
+
* @docs https://supabase.com/docs/reference/javascript/initializing#parameters
|
|
72
|
+
*/
|
|
73
|
+
clientOptions?: SupabaseClientOptions<string>
|
|
49
74
|
}
|
|
50
75
|
|
|
51
76
|
interface RedirectOptions {
|
|
@@ -56,7 +81,7 @@ interface RedirectOptions {
|
|
|
56
81
|
*/
|
|
57
82
|
login?: string
|
|
58
83
|
/**
|
|
59
|
-
*
|
|
84
|
+
* Routes to exclude from redirection
|
|
60
85
|
* @default []
|
|
61
86
|
* @type string[]
|
|
62
87
|
*/
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -18,6 +18,19 @@ const module = defineNuxtModule({
|
|
|
18
18
|
redirectOptions: {
|
|
19
19
|
login: "/login",
|
|
20
20
|
exclude: []
|
|
21
|
+
},
|
|
22
|
+
cookieOptions: {
|
|
23
|
+
maxAge: 60 * 60 * 8,
|
|
24
|
+
sameSite: "lax",
|
|
25
|
+
secure: true
|
|
26
|
+
},
|
|
27
|
+
clientOptions: {
|
|
28
|
+
auth: {
|
|
29
|
+
flowType: "pkce",
|
|
30
|
+
detectSessionInUrl: true,
|
|
31
|
+
persistSession: true,
|
|
32
|
+
autoRefreshToken: true
|
|
33
|
+
}
|
|
21
34
|
}
|
|
22
35
|
},
|
|
23
36
|
setup(options, nuxt) {
|
|
@@ -33,7 +46,9 @@ const module = defineNuxtModule({
|
|
|
33
46
|
url: options.url,
|
|
34
47
|
key: options.key,
|
|
35
48
|
redirect: options.redirect,
|
|
36
|
-
redirectOptions: options.redirectOptions
|
|
49
|
+
redirectOptions: options.redirectOptions,
|
|
50
|
+
cookieOptions: options.cookieOptions,
|
|
51
|
+
clientOptions: options.clientOptions
|
|
37
52
|
});
|
|
38
53
|
nuxt.options.runtimeConfig.supabase = defu(nuxt.options.runtimeConfig.supabase, {
|
|
39
54
|
serviceKey: options.serviceKey
|
|
@@ -74,7 +89,15 @@ const module = defineNuxtModule({
|
|
|
74
89
|
config.optimizeDeps = config.optimizeDeps || {};
|
|
75
90
|
config.optimizeDeps.include = config.optimizeDeps.include || [];
|
|
76
91
|
config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
|
|
77
|
-
config.optimizeDeps.include.push(
|
|
92
|
+
config.optimizeDeps.include.push(
|
|
93
|
+
"@supabase/functions-js",
|
|
94
|
+
"@supabase/gotrue-js",
|
|
95
|
+
"@supabase/postgrest-js",
|
|
96
|
+
"@supabase/realtime-js",
|
|
97
|
+
"@supabase/storage-js",
|
|
98
|
+
"@supabase/supabase-js",
|
|
99
|
+
"@supabase/ssr"
|
|
100
|
+
);
|
|
78
101
|
});
|
|
79
102
|
}
|
|
80
103
|
});
|
|
@@ -1,12 +1,26 @@
|
|
|
1
|
-
import { defineNuxtPlugin, useRuntimeConfig } from "#imports";
|
|
1
|
+
import { defineNuxtPlugin, useRuntimeConfig, useCookie } from "#imports";
|
|
2
2
|
import { createBrowserClient } from "@supabase/ssr";
|
|
3
3
|
export default defineNuxtPlugin({
|
|
4
4
|
name: "supabase",
|
|
5
5
|
enforce: "pre",
|
|
6
6
|
async setup() {
|
|
7
7
|
const config = useRuntimeConfig().public.supabase;
|
|
8
|
-
const { url, key } = config;
|
|
9
|
-
const supabaseBrowserClient = createBrowserClient(url, key
|
|
8
|
+
const { url, key, cookieOptions } = config;
|
|
9
|
+
const supabaseBrowserClient = createBrowserClient(url, key, {
|
|
10
|
+
cookies: {
|
|
11
|
+
get(name) {
|
|
12
|
+
return useCookie(name).value;
|
|
13
|
+
},
|
|
14
|
+
set(name, value) {
|
|
15
|
+
useCookie(name, cookieOptions).value = value;
|
|
16
|
+
},
|
|
17
|
+
remove(key2, options) {
|
|
18
|
+
useCookie(key2, { ...options, expires: 0 }).value = "";
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
cookieOptions,
|
|
22
|
+
isSingleton: true
|
|
23
|
+
});
|
|
10
24
|
return {
|
|
11
25
|
provide: {
|
|
12
26
|
supabase: {
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
import { defineNuxtPlugin, useRuntimeConfig, useRequestEvent } from "#imports";
|
|
2
2
|
import { createServerClient } from "@supabase/ssr";
|
|
3
|
-
import { getCookie } from "h3";
|
|
3
|
+
import { getCookie, setCookie } from "h3";
|
|
4
4
|
export default defineNuxtPlugin({
|
|
5
5
|
name: "supabase",
|
|
6
6
|
enforce: "pre",
|
|
7
7
|
async setup() {
|
|
8
|
-
const { url, key } = useRuntimeConfig().public.supabase;
|
|
8
|
+
const { url, key, cookieOptions } = useRuntimeConfig().public.supabase;
|
|
9
9
|
const event = useRequestEvent();
|
|
10
10
|
const supabaseServerClient = createServerClient(url, key, {
|
|
11
11
|
cookies: {
|
|
12
12
|
get(name) {
|
|
13
13
|
return getCookie(event, name);
|
|
14
|
+
},
|
|
15
|
+
set(name, value) {
|
|
16
|
+
setCookie(event, name, value, cookieOptions);
|
|
17
|
+
},
|
|
18
|
+
remove(key2, options) {
|
|
19
|
+
setCookie(event, key2, "", { ...options, expires: 0 });
|
|
14
20
|
}
|
|
15
|
-
}
|
|
21
|
+
},
|
|
22
|
+
cookieOptions
|
|
16
23
|
});
|
|
17
24
|
return {
|
|
18
25
|
provide: {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
-
import
|
|
2
|
+
import { H3Event } from 'h3';
|
|
3
3
|
export declare const supabaseServerClient: <T>(event: H3Event) => Promise<SupabaseClient<T, "public" extends keyof T ? keyof T & "public" : string & keyof T, T["public" extends keyof T ? keyof T & "public" : string & keyof T] extends import("@supabase/supabase-js/dist/module/lib/types").GenericSchema ? T["public" extends keyof T ? keyof T & "public" : string & keyof T] : any>>;
|
|
@@ -3,7 +3,7 @@ import { getCookie, setCookie } from "h3";
|
|
|
3
3
|
import { useRuntimeConfig } from "#imports";
|
|
4
4
|
export const supabaseServerClient = async (event) => {
|
|
5
5
|
const {
|
|
6
|
-
supabase: { url, key }
|
|
6
|
+
supabase: { url, key, cookieOptions }
|
|
7
7
|
} = useRuntimeConfig(event).public;
|
|
8
8
|
let supabaseClient = event.context._supabaseClient;
|
|
9
9
|
if (!supabaseClient) {
|
|
@@ -18,7 +18,8 @@ export const supabaseServerClient = async (event) => {
|
|
|
18
18
|
remove(key2, options) {
|
|
19
19
|
setCookie(event, key2, "", { ...options, expires: 0 });
|
|
20
20
|
}
|
|
21
|
-
}
|
|
21
|
+
},
|
|
22
|
+
cookieOptions
|
|
22
23
|
});
|
|
23
24
|
event.context._supabaseClient = supabaseClient;
|
|
24
25
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
-
import
|
|
2
|
+
import { H3Event } from 'h3';
|
|
3
3
|
export declare const supabaseServiceRole: <T>(event: H3Event) => Promise<SupabaseClient<T, "public" extends keyof T ? keyof T & "public" : string & keyof T, T["public" extends keyof T ? keyof T & "public" : string & keyof T] extends import("@supabase/supabase-js/dist/module/lib/types").GenericSchema ? T["public" extends keyof T ? keyof T & "public" : string & keyof T] : any>>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createServerClient } from "@supabase/ssr";
|
|
2
|
-
import { getCookie } from "h3";
|
|
2
|
+
import { getCookie, setCookie } from "h3";
|
|
3
3
|
import { useRuntimeConfig } from "#imports";
|
|
4
4
|
export const supabaseServiceRole = async (event) => {
|
|
5
5
|
const {
|
|
6
6
|
supabase: { serviceKey },
|
|
7
7
|
public: {
|
|
8
|
-
supabase: { url }
|
|
8
|
+
supabase: { url, cookieOptions }
|
|
9
9
|
}
|
|
10
10
|
} = useRuntimeConfig(event);
|
|
11
11
|
if (!serviceKey) {
|
|
@@ -17,8 +17,15 @@ export const supabaseServiceRole = async (event) => {
|
|
|
17
17
|
cookies: {
|
|
18
18
|
get(name) {
|
|
19
19
|
return getCookie(event, name);
|
|
20
|
+
},
|
|
21
|
+
set(name, value) {
|
|
22
|
+
setCookie(event, name, value);
|
|
23
|
+
},
|
|
24
|
+
remove(key, options) {
|
|
25
|
+
setCookie(event, key, "", { ...options, expires: 0 });
|
|
20
26
|
}
|
|
21
|
-
}
|
|
27
|
+
},
|
|
28
|
+
cookieOptions
|
|
22
29
|
});
|
|
23
30
|
event.context._supabaseServiceRole = supabaseClient;
|
|
24
31
|
}
|
|
@@ -34,16 +34,41 @@ export interface ModuleOptions {
|
|
|
34
34
|
redirect?: boolean
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* Redirection options, set routes for login and
|
|
37
|
+
* Redirection options, set routes for login and specify pages to exclude from redirection
|
|
38
38
|
* @default
|
|
39
39
|
* {
|
|
40
40
|
login: '/login',
|
|
41
|
-
callback: '/confirm',
|
|
42
41
|
exclude: [],
|
|
43
42
|
}
|
|
44
43
|
* @type RedirectOptions
|
|
45
44
|
*/
|
|
46
45
|
redirectOptions?: RedirectOptions
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Cookie options
|
|
49
|
+
* @default {
|
|
50
|
+
maxAge: 60 * 60 * 8,
|
|
51
|
+
sameSite: 'lax',
|
|
52
|
+
secure: true,
|
|
53
|
+
}
|
|
54
|
+
* @type CookieOptions
|
|
55
|
+
* @docs https://nuxt.com/docs/api/composables/use-cookie#options
|
|
56
|
+
*/
|
|
57
|
+
cookieOptions?: CookieOptions
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Supabase Client options
|
|
61
|
+
* @default {
|
|
62
|
+
auth: {
|
|
63
|
+
flowType: 'pkce',
|
|
64
|
+
detectSessionInUrl: true,
|
|
65
|
+
persistSession: true,
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
* @type object
|
|
69
|
+
* @docs https://supabase.com/docs/reference/javascript/initializing#parameters
|
|
70
|
+
*/
|
|
71
|
+
clientOptions?: SupabaseClientOptions<string>
|
|
47
72
|
}
|
|
48
73
|
|
|
49
74
|
export interface RedirectOptions {
|
|
@@ -54,7 +79,7 @@ export interface RedirectOptions {
|
|
|
54
79
|
*/
|
|
55
80
|
login?: string
|
|
56
81
|
/**
|
|
57
|
-
*
|
|
82
|
+
* Routes to exclude from redirection
|
|
58
83
|
* @default []
|
|
59
84
|
* @type string[]
|
|
60
85
|
*/
|