Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions dist/module.d.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import * as _nuxt_schema from '@nuxt/schema';
import { CookieOptions } from 'nuxt/app';
import { SupabaseClientOptions } from '@supabase/supabase-js';

declare module '@nuxt/schema' {
interface PublicRuntimeConfig {
supabase: {
url: string;
key: string;
redirect: boolean;
redirectOptions: RedirectOptions;
cookieName: string;
cookiePrefix: string;
useSsrCookies: boolean;
cookieOptions: CookieOptions;
types: string | false;
clientOptions: SupabaseClientOptions<string>;
};
}
}
interface RedirectOptions {
login: string;
callback: string;
include?: string[];
exclude?: string[];
/**
* @deprecated Use `saveRedirectToCookie` instead.
*/
cookieRedirect?: boolean;
/**
* If true, when automatically redirected the redirect path will be saved to a cookie, allowing retrieval later with the `useSupabaseRedirect` composable.
* @default false
*/
saveRedirectToCookie?: boolean;
}

interface ModuleOptions {
/**
* Supabase API URL
* @default process.env.SUPABASE_URL
* @example 'https://*.supabase.co'
* @type string
* @docs https://supabase.com/docs/reference/javascript/initializing#parameters
*/
url: string;
/**
* Supabase Client publishable API Key (previously known as 'anon key')
* @default process.env.SUPABASE_KEY
* @example '123456789'
* @type string
* @docs https://supabase.com/docs/reference/javascript/initializing#parameters
*/
key: string;
/**
* Supabase Legacy 'service_role' key (deprecated)
* @default process.env.SUPABASE_SERVICE_KEY
* @example '123456789'
* @type string
* @docs https://supabase.com/docs/reference/javascript/initializing#parameters
* @deprecated Use `secretKey` instead. Will be removed in a future version.
*/
serviceKey: string;
/**
* Supabase Secret key
* @default process.env.SUPABASE_SECRET_KEY
* @example '123456789'
* @type string
* @docs https://supabase.com/blog/jwt-signing-keys
*/
secretKey: string;
/**
* Redirect automatically to login page if user is not authenticated
* @default `true`
* @type boolean
*/
redirect?: boolean;
/**
* Redirection options, set routes for login and callback redirect
* @default
* {
login: '/login',
callback: '/confirm',
exclude: [],
}
* @type RedirectOptions
*/
redirectOptions?: RedirectOptions;
/**
* Cookie name used for storing the redirect path when using the `redirect` option, added in front of `-redirect-path` to form the full cookie name e.g. `sb-redirect-path`
* @default 'sb'
* @type string
* @deprecated Use `cookiePrefix` instead.
*/
cookieName?: string;
/**
* The prefix used for all supabase cookies, and the redirect cookie.
* @default The default storage key from the supabase-js client.
* @type string
*/
cookiePrefix?: string;
/**
* If true, the supabase client will use cookies to store the session, allowing the session to be used from the server in ssr mode.
* Some `clientOptions` are not configurable when this is enabled. See the docs for more details.
*
* If false, the server will not be able to access the session.
* @default true
* @type boolean
*/
useSsrCookies?: boolean;
/**
* Cookie options
* @default {
maxAge: 60 * 60 * 8,
sameSite: 'lax',
secure: true,
}
* @type CookieOptions
* @docs https://nuxt.com/docs/api/composables/use-cookie#options
*/
cookieOptions?: CookieOptions;
/**
* Path to Supabase database type definitions file
* @default '~/types/database.types.ts'
* @type string
*/
types?: string | false;
/**
* Supabase client options (overrides default options from `@supabase/ssr`)
* @default { }
* @type object
* @docs https://supabase.com/docs/reference/javascript/initializing#parameters
*/
clientOptions?: SupabaseClientOptions<string>;
}
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;

export { _default as default };
export type { ModuleOptions, RedirectOptions };
12 changes: 12 additions & 0 deletions dist/module.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "@nuxtjs/supabase",
"configKey": "supabase",
"compatibility": {
"nuxt": ">=3.0.0"
},
"version": "2.0.3",
"builder": {
"@nuxt/module-builder": "1.0.2",
"unbuild": "3.6.0"
}
}
164 changes: 164 additions & 0 deletions dist/module.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { fileURLToPath } from 'node:url';
import fs from 'node:fs';
import { defu } from 'defu';
import { relative } from 'pathe';
import { defineNuxtModule, useLogger, createResolver, addPlugin, addImportsDir, addTemplate, extendViteConfig } from '@nuxt/kit';

const module = defineNuxtModule({
meta: {
name: "@nuxtjs/supabase",
configKey: "supabase",
compatibility: {
nuxt: ">=3.0.0"
}
},
defaults: {
url: process.env.SUPABASE_URL,
key: process.env.SUPABASE_KEY,
serviceKey: process.env.SUPABASE_SERVICE_KEY,
secretKey: process.env.SUPABASE_SECRET_KEY,
redirect: true,
redirectOptions: {
login: "/login",
callback: "/confirm",
exclude: [],
cookieRedirect: false,
saveRedirectToCookie: false
},
cookieName: "sb",
cookiePrefix: void 0,
useSsrCookies: true,
cookieOptions: {
maxAge: 60 * 60 * 8,
sameSite: "lax",
secure: true
},
types: "~/types/database.types.ts",
clientOptions: {}
},
setup(options, nuxt) {
const logger = useLogger("@nuxt/supabase");
const { resolve, resolvePath } = createResolver(import.meta.url);
nuxt.options.runtimeConfig.public.supabase = defu(nuxt.options.runtimeConfig.public.supabase, {
url: options.url,
key: options.key,
redirect: options.redirect,
redirectOptions: options.redirectOptions,
cookieName: options.cookieName,
cookiePrefix: options.cookiePrefix,
useSsrCookies: options.useSsrCookies,
cookieOptions: options.cookieOptions,
clientOptions: options.clientOptions
});
nuxt.options.runtimeConfig.supabase = defu(nuxt.options.runtimeConfig.supabase || {}, {
serviceKey: options.serviceKey,
secretKey: options.secretKey
});
const finalUrl = nuxt.options.runtimeConfig.public.supabase.url;
if (!finalUrl) {
logger.warn("Missing supabase url, set it either in `nuxt.config.ts` or via env variable");
} else {
try {
const defaultStorageKey = `sb-${new URL(finalUrl).hostname.split(".")[0]}-auth-token`;
const currentPrefix = nuxt.options.runtimeConfig.public.supabase.cookiePrefix;
nuxt.options.runtimeConfig.public.supabase.cookiePrefix = currentPrefix || defaultStorageKey;
} catch (error) {
logger.error(
`Invalid Supabase URL: "${finalUrl}". Please provide a valid URL (e.g., https://example.supabase.co or http://localhost:5432)`,
error
);
const currentPrefix = nuxt.options.runtimeConfig.public.supabase.cookiePrefix;
nuxt.options.runtimeConfig.public.supabase.cookiePrefix = currentPrefix || "sb-auth-token";
if (!nuxt.options.dev) {
throw new Error("Invalid Supabase URL configuration");
}
}
}
if (!nuxt.options.runtimeConfig.public.supabase.key) {
logger.warn("Missing supabase publishable key, set it either in `nuxt.config.ts` or via env variable");
}
if (nuxt.options.runtimeConfig.public.supabase.redirectOptions.cookieRedirect) {
logger.warn("The `cookieRedirect` option is deprecated, use `saveRedirectToCookie` instead.");
}
if (nuxt.options.runtimeConfig.public.supabase.cookieName != "sb") {
logger.warn("The `cookieName` option is deprecated, use `cookiePrefix` instead.");
}
const supabaseConfig = nuxt.options.runtimeConfig.supabase;
const hasServiceKey = !!supabaseConfig?.serviceKey;
const hasSecretKey = !!supabaseConfig?.secretKey;
if (hasServiceKey && !hasSecretKey) {
logger.warn("`SUPABASE_SERVICE_KEY` is deprecated and will be removed in a future version. Please migrate to `SUPABASE_SECRET_KEY` (JWT signing key). See: https://supabase.com/blog/jwt-signing-keys");
}
const mergedOptions = nuxt.options.runtimeConfig.public.supabase;
if (mergedOptions.redirect && mergedOptions.redirectOptions.callback) {
const routeRules = {};
routeRules[mergedOptions.redirectOptions.callback] = { ssr: false };
nuxt.options.nitro = defu(nuxt.options.nitro, {
routeRules
});
}
const runtimeDir = fileURLToPath(new URL("./runtime", import.meta.url));
nuxt.options.build.transpile.push(runtimeDir);
addPlugin(resolve(runtimeDir, "plugins", "supabase.client"));
addPlugin(resolve(runtimeDir, "plugins", "supabase.server"));
if (mergedOptions.redirect) {
addPlugin(resolve(runtimeDir, "plugins", "auth-redirect"));
}
addImportsDir(resolve("./runtime/composables"));
nuxt.hook("nitro:config", (nitroConfig) => {
nitroConfig.alias = nitroConfig.alias || {};
nitroConfig.externals = defu(typeof nitroConfig.externals === "object" ? nitroConfig.externals : {}, {
inline: [resolve("./runtime"), "@supabase/supabase-js"]
});
nitroConfig.alias["#supabase/server"] = resolve("./runtime/server/services");
nitroConfig.alias["#supabase/database"] = resolve(nitroConfig.buildDir, "types/supabase-database");
});
addTemplate({
filename: "types/supabase.d.ts",
getContents: () => [
"declare module '#supabase/server' {",
` const serverSupabaseClient: typeof import('${resolve("./runtime/server/services")}').serverSupabaseClient`,
` const serverSupabaseServiceRole: typeof import('${resolve(
"./runtime/server/services"
)}').serverSupabaseServiceRole`,
` const serverSupabaseUser: typeof import('${resolve("./runtime/server/services")}').serverSupabaseUser`,
` const serverSupabaseSession: typeof import('${resolve("./runtime/server/services")}').serverSupabaseSession`,
"}"
].join("\n")
});
addTemplate({
filename: "types/supabase-database.d.ts",
getContents: async () => {
if (options.types) {
try {
const path = await resolvePath(options.types);
const typesPath = await resolvePath("~~/.nuxt/types/");
if (fs.existsSync(path)) {
return `export * from '${relative(typesPath, path)}'`;
} else {
logger.warn(
`Database types configured at "${options.types}" but file not found at "${path}". Using "Database = unknown".`
);
}
} catch (error) {
logger.error(`Failed to load Supabase database types from "${options.types}":`, error);
}
}
return `export type Database = unknown`;
}
});
nuxt.hook("prepare:types", async (options2) => {
options2.references.push({ path: resolve(nuxt.options.buildDir, "types/supabase.d.ts") });
});
if (!nuxt.options.dev && !["cloudflare"].includes(process.env.NITRO_PRESET)) {
nuxt.options.build.transpile.push("websocket");
}
extendViteConfig((config) => {
config.optimizeDeps = config.optimizeDeps || {};
config.optimizeDeps.include = config.optimizeDeps.include || [];
config.optimizeDeps.include.push("@nuxtjs/supabase > cookie", "@nuxtjs/supabase > @supabase/postgrest-js", "@supabase/supabase-js");
});
}
});

export { module as default };
3 changes: 3 additions & 0 deletions dist/runtime/composables/useSupabaseClient.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { SupabaseClient } from '@supabase/supabase-js';
import type { Database } from '#build/types/supabase-database';
export declare const useSupabaseClient: <T = Database>() => SupabaseClient<T>;
4 changes: 4 additions & 0 deletions dist/runtime/composables/useSupabaseClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { useNuxtApp } from "#imports";
export const useSupabaseClient = () => {
return useNuxtApp().$supabase.client;
};
13 changes: 13 additions & 0 deletions dist/runtime/composables/useSupabaseCookieRedirect.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { CookieRef } from 'nuxt/app';
export interface UseSupabaseCookieRedirectReturn {
/**
* The reactive value of the redirect path cookie.
* Can be both read and written to.
*/
path: CookieRef<string | null>;
/**
* Get the current redirect path cookie value, then clear it
*/
pluck: () => string | null;
}
export declare const useSupabaseCookieRedirect: () => UseSupabaseCookieRedirectReturn;
20 changes: 20 additions & 0 deletions dist/runtime/composables/useSupabaseCookieRedirect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useRuntimeConfig, useCookie } from "#imports";
export const useSupabaseCookieRedirect = () => {
const config = useRuntimeConfig().public.supabase;
const prefix = config.redirectOptions.saveRedirectToCookie ? config.cookiePrefix : config.cookieName;
const cookie = useCookie(
`${prefix}-redirect-path`,
{
...config.cookieOptions,
readonly: false
}
);
return {
path: cookie,
pluck: () => {
const value = cookie.value;
cookie.value = null;
return value;
}
};
};
7 changes: 7 additions & 0 deletions dist/runtime/composables/useSupabaseSession.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { Session } from '@supabase/supabase-js';
import { type Ref } from '#imports';
/**
* Reactive `Session` state from Supabase. This is initialized in both client and server plugin
* and, on the client, also updated through `onAuthStateChange` events.
*/
export declare const useSupabaseSession: () => Ref<Omit<Session, "user"> | null>;
2 changes: 2 additions & 0 deletions dist/runtime/composables/useSupabaseSession.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { useState } from "#imports";
export const useSupabaseSession = () => useState("supabase_session", () => null);
6 changes: 6 additions & 0 deletions dist/runtime/composables/useSupabaseUser.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { JwtPayload } from '@supabase/supabase-js';
import { type Ref } from '#imports';
/**
* Reactive `User` state from Supabase. This is populated by the JWT Payload from the auth.getClaims() call.
*/
export declare const useSupabaseUser: () => Ref<JwtPayload | null>;
2 changes: 2 additions & 0 deletions dist/runtime/composables/useSupabaseUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { useState } from "#imports";
export const useSupabaseUser = () => useState("supabase_user", () => null);
3 changes: 3 additions & 0 deletions dist/runtime/plugins/auth-redirect.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { Plugin } from '#app';
declare const _default: Plugin;
export default _default;
Loading
Loading