@floatingpixels/supabase-nuxt 0.5.11 → 0.6.0

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 CHANGED
@@ -11,6 +11,10 @@
11
11
 
12
12
  Checkout the [Nuxt 3](https://v3.nuxtjs.org) documentation and [Supabase](https://supabase.com) to learn more.
13
13
 
14
+ ## Testing
15
+
16
+ Test setup and command behavior are documented in [docs/testing.md](./docs/testing.md).
17
+
14
18
  ## Installation
15
19
 
16
20
  Add `@floatingpixels/supabase-nuxt` dev dependency to your project:
package/dist/module.d.mts CHANGED
@@ -1,7 +1,12 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
+ import { NitroConfig, HookResult } from '@nuxt/schema';
2
3
  import { SupabaseClientOptions } from '@supabase/supabase-js';
3
4
 
4
5
  declare module '@nuxt/schema' {
6
+ interface NuxtHooks {
7
+ 'nitro:config': (nitroConfig: NitroConfig) => HookResult
8
+ }
9
+
5
10
  interface RuntimeConfig {
6
11
  supabase: {
7
12
  serviceRoleKey?: string
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">3.0.0"
6
6
  },
7
- "version": "0.5.11",
7
+ "version": "0.6.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
@@ -1,4 +1,15 @@
1
+ import type { User, AuthError } from '@supabase/supabase-js';
2
+ export interface SupabaseAuthUser {
3
+ id: string;
4
+ email?: string;
5
+ phone?: string;
6
+ role?: string;
7
+ aud?: string;
8
+ app_metadata: User['app_metadata'];
9
+ user_metadata: User['user_metadata'];
10
+ claims: Record<string, unknown>;
11
+ }
1
12
  export declare const useSupabaseUser: () => Promise<{
2
- data: import("@supabase/supabase-js").JwtPayload | undefined;
3
- error: import("@supabase/supabase-js").AuthError | null;
13
+ data: SupabaseAuthUser | null;
14
+ error: AuthError | null;
4
15
  }>;
@@ -1,6 +1,48 @@
1
1
  import { useSupabaseClient } from "./useSupabaseClient.js";
2
+ const isRecord = (value) => {
3
+ return typeof value === "object" && value !== null;
4
+ };
5
+ const normalizeUser = ({
6
+ claims,
7
+ user
8
+ }) => {
9
+ const claimUserId = typeof claims.sub === "string" ? claims.sub : void 0;
10
+ const userId = user?.id ?? claimUserId;
11
+ if (!userId) {
12
+ return null;
13
+ }
14
+ const claimAppMetadata = isRecord(claims.app_metadata) ? claims.app_metadata : {};
15
+ const claimUserMetadata = isRecord(claims.user_metadata) ? claims.user_metadata : {};
16
+ return {
17
+ id: userId,
18
+ email: user?.email ?? (typeof claims.email === "string" ? claims.email : void 0),
19
+ phone: user?.phone ?? (typeof claims.phone === "string" ? claims.phone : void 0),
20
+ role: user?.role ?? (typeof claims.role === "string" ? claims.role : void 0),
21
+ aud: user?.aud ?? (typeof claims.aud === "string" ? claims.aud : void 0),
22
+ app_metadata: user?.app_metadata ?? claimAppMetadata,
23
+ user_metadata: user?.user_metadata ?? claimUserMetadata,
24
+ claims
25
+ };
26
+ };
27
+ const needsUserFallback = (claims) => {
28
+ return !isRecord(claims.app_metadata) || !isRecord(claims.user_metadata) || typeof claims.email !== "string";
29
+ };
2
30
  export const useSupabaseUser = async () => {
3
31
  const supabase = useSupabaseClient();
4
- const { data, error } = await supabase.auth.getClaims();
5
- return { data: data?.claims, error };
32
+ const { data: claimsData, error: claimsError } = await supabase.auth.getClaims();
33
+ if (claimsError) {
34
+ return { data: null, error: claimsError };
35
+ }
36
+ const claims = claimsData?.claims;
37
+ if (!claims || !isRecord(claims)) {
38
+ return { data: null, error: null };
39
+ }
40
+ if (!needsUserFallback(claims)) {
41
+ return { data: normalizeUser({ claims }), error: null };
42
+ }
43
+ const { data: userData, error: userError } = await supabase.auth.getUser();
44
+ if (userError) {
45
+ return { data: null, error: userError };
46
+ }
47
+ return { data: normalizeUser({ claims, user: userData.user }), error: null };
6
48
  };
@@ -1,2 +1,2 @@
1
- declare const _default: any;
1
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
2
2
  export default _default;
@@ -14,7 +14,7 @@ export default defineNuxtPlugin({
14
14
  if (isExcluded) return;
15
15
  const { data: user, error } = await useSupabaseUser();
16
16
  if (error || !user) {
17
- return navigateTo("/login", { redirectCode: 302 });
17
+ return navigateTo(login || "/login", { redirectCode: 302 });
18
18
  }
19
19
  }),
20
20
  { global: true }
@@ -4,8 +4,12 @@ export default defineNuxtPlugin({
4
4
  name: "supabase",
5
5
  enforce: "pre",
6
6
  async setup() {
7
- const { url, publishableKey } = useRuntimeConfig().public.supabase;
8
- const supabaseBrowserClient = createBrowserClient(url, publishableKey);
7
+ const { url, publishableKey, clientOptions } = useRuntimeConfig().public.supabase;
8
+ const supabaseBrowserClient = createBrowserClient(
9
+ url,
10
+ publishableKey,
11
+ clientOptions
12
+ );
9
13
  return {
10
14
  provide: {
11
15
  supabase: {
@@ -5,12 +5,13 @@ export default defineNuxtPlugin({
5
5
  name: "supabase",
6
6
  enforce: "pre",
7
7
  async setup() {
8
- const { url, publishableKey } = useRuntimeConfig().public.supabase;
8
+ const { url, publishableKey, clientOptions } = useRuntimeConfig().public.supabase;
9
9
  const event = useRequestEvent();
10
10
  if (!event) {
11
11
  throw new Error("No request event found");
12
12
  }
13
- const supabaseServerClient = createServerClient(url, publishableKey, {
13
+ const serverClientOptions = {
14
+ ...clientOptions,
14
15
  cookies: {
15
16
  getAll: () => {
16
17
  const cookie_records = parseCookies(event);
@@ -29,7 +30,12 @@ export default defineNuxtPlugin({
29
30
  }
30
31
  }
31
32
  }
32
- });
33
+ };
34
+ const supabaseServerClient = createServerClient(
35
+ url,
36
+ publishableKey,
37
+ serverClientOptions
38
+ );
33
39
  return {
34
40
  provide: {
35
41
  supabase: {
@@ -3,11 +3,13 @@ import { setCookie, parseCookies } from "h3";
3
3
  import { useRuntimeConfig } from "#imports";
4
4
  export const supabaseServerClient = async (event) => {
5
5
  const {
6
- supabase: { url, publishableKey }
6
+ supabase: { url, publishableKey, clientOptions }
7
7
  } = useRuntimeConfig().public;
8
8
  let supabaseClient = event.context._supabaseClient;
9
+ const createTypedServerClient = createServerClient;
9
10
  if (!supabaseClient) {
10
- supabaseClient = createServerClient(url, publishableKey, {
11
+ const serverClientOptions = {
12
+ ...clientOptions,
11
13
  cookies: {
12
14
  getAll: () => {
13
15
  const cookie_records = parseCookies(event);
@@ -26,7 +28,12 @@ export const supabaseServerClient = async (event) => {
26
28
  }
27
29
  }
28
30
  }
29
- });
31
+ };
32
+ supabaseClient = createTypedServerClient(
33
+ url,
34
+ publishableKey,
35
+ serverClientOptions
36
+ );
30
37
  event.context._supabaseClient = supabaseClient;
31
38
  }
32
39
  return supabaseClient;
@@ -5,15 +5,17 @@ export const supabaseServiceRole = async (event) => {
5
5
  const {
6
6
  supabase: { serviceRoleKey },
7
7
  public: {
8
- supabase: { url }
8
+ supabase: { url, clientOptions }
9
9
  }
10
10
  } = useRuntimeConfig();
11
11
  if (!serviceRoleKey) {
12
12
  throw new Error("Missing `SUPABASE_SERVICE_ROLE_KEY` in `.env`");
13
13
  }
14
14
  let supabaseClient = event.context._supabaseServiceRole;
15
+ const createTypedServerClient = createServerClient;
15
16
  if (!supabaseClient) {
16
- supabaseClient = createServerClient(url, serviceRoleKey, {
17
+ const serverClientOptions = {
18
+ ...clientOptions,
17
19
  cookies: {
18
20
  getAll: () => {
19
21
  const cookie_records = parseCookies(event);
@@ -32,7 +34,12 @@ export const supabaseServiceRole = async (event) => {
32
34
  }
33
35
  }
34
36
  }
35
- });
37
+ };
38
+ supabaseClient = createTypedServerClient(
39
+ url,
40
+ serviceRoleKey,
41
+ serverClientOptions
42
+ );
36
43
  event.context._supabaseServiceRole = supabaseClient;
37
44
  }
38
45
  return supabaseClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floatingpixels/supabase-nuxt",
3
- "version": "0.5.11",
3
+ "version": "0.6.0",
4
4
  "description": "Supabase module for Nuxt",
5
5
  "repository": "floatingpixels/supabase-nuxt",
6
6
  "license": "MIT",
@@ -38,7 +38,7 @@
38
38
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
39
39
  "release": "pnpm run lint && pnpm run prepack && release-it",
40
40
  "lint": "eslint .",
41
- "test": "nuxi prepare playground && pnpm vitest",
41
+ "test": "nuxi prepare playground && pnpm exec tsc --noEmit --pretty false && pnpm vitest",
42
42
  "test:watch": "vitest watch",
43
43
  "test:pw": "playwright test test/playwright/",
44
44
  "test:e2e": "pnpm run --silent db:start && pnpm run --silent db:reset && pnpm run --silent test:pw && pnpm run --silent db:stop",
@@ -58,37 +58,37 @@
58
58
  "cleanup": "pnpm nuxi cleanup && rm -rf node_modules pnpm-lock.yaml && pnpm i"
59
59
  },
60
60
  "dependencies": {
61
- "@supabase/ssr": "^0.8.0",
62
- "@supabase/supabase-js": "^2.90.0",
61
+ "@supabase/ssr": "^0.9.0",
62
+ "@supabase/supabase-js": "^2.99.1",
63
63
  "cookie": "^1.1.1"
64
64
  },
65
65
  "devDependencies": {
66
- "@nuxt/devtools": "3.1.1",
67
- "@nuxt/eslint-config": "^1.12.1",
68
- "@nuxt/kit": "^4.2.2",
66
+ "@nuxt/devtools": "3.2.3",
67
+ "@nuxt/eslint-config": "^1.15.2",
68
+ "@nuxt/kit": "^4.4.2",
69
69
  "@nuxt/module-builder": "^1.0.2",
70
- "@nuxt/schema": "^4.2.2",
71
- "@nuxt/test-utils": "3.23.0",
72
- "@playwright/test": "^1.57.0",
70
+ "@nuxt/schema": "^4.4.2",
71
+ "@nuxt/test-utils": "4.0.0",
72
+ "@playwright/test": "^1.58.2",
73
73
  "@snaplet/copycat": "^6.0.0",
74
74
  "@snaplet/seed": "^0.98.0",
75
75
  "@types/eslint-config-prettier": "^6.11.3",
76
- "@types/node": "^25.0.3",
77
- "@vitest/coverage-v8": "4.0.16",
76
+ "@types/node": "^25.5.0",
77
+ "@vitest/coverage-v8": "4.1.0",
78
78
  "@vue/test-utils": "^2.4.6",
79
79
  "changelogen": "^0.6.2",
80
- "eslint": "^9.39.2",
80
+ "eslint": "^10.0.3",
81
81
  "eslint-config-prettier": "^10.1.8",
82
- "happy-dom": "^20.1.0",
83
- "nuxt": "^4.2.2",
84
- "playwright-core": "^1.57.0",
82
+ "happy-dom": "^20.8.4",
83
+ "nuxt": "^4.4.2",
84
+ "playwright-core": "^1.58.2",
85
85
  "postgres": "^3.4.8",
86
- "prettier": "^3.7.4",
87
- "release-it": "^19.2.3",
88
- "supabase": "^2.72.0",
86
+ "prettier": "^3.8.1",
87
+ "release-it": "^19.2.4",
88
+ "supabase": "^2.78.1",
89
89
  "typescript": "5.9.3",
90
- "vitest": "^4.0.16",
91
- "vue-tsc": "^3.2.2"
90
+ "vitest": "^4.1.0",
91
+ "vue-tsc": "^3.2.5"
92
92
  },
93
93
  "pnpm": {
94
94
  "onlyBuiltDependencies": [