main repo

This commit is contained in:
Basilosaurusrex
2025-11-24 18:09:40 +01:00
parent b636ee5e70
commit f027651f9b
34146 changed files with 4436636 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
// these variables are defined by tsup
declare const PACKAGE_NAME: string;
declare const PACKAGE_VERSION: string;

View File

@@ -0,0 +1,71 @@
import {
BrowserCookieAuthStorageAdapter,
CookieOptionsWithName,
SupabaseClientOptionsWithoutAuth,
createSupabaseClient
} from '@supabase/auth-helpers-shared';
import type { SupabaseClient } from '@supabase/supabase-js';
import type { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types';
// can't type this properly as `Database`, `SchemaName` and `Schema` are only available within `createClientComponentClient` function
let supabase: any;
export function createClientComponentClient<
Database = any,
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
? Database[SchemaName]
: any
>({
supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
options,
cookieOptions,
isSingleton = true
}: {
supabaseUrl?: string;
supabaseKey?: string;
options?: SupabaseClientOptionsWithoutAuth<SchemaName>;
cookieOptions?: CookieOptionsWithName;
isSingleton?: boolean;
} = {}): SupabaseClient<Database, SchemaName, Schema> {
if (!supabaseUrl || !supabaseKey) {
throw new Error(
'either NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY env variables or supabaseUrl and supabaseKey are required!'
);
}
const createNewClient = () =>
createSupabaseClient<Database, SchemaName, Schema>(supabaseUrl, supabaseKey, {
...options,
global: {
...options?.global,
headers: {
...options?.global?.headers,
'X-Client-Info': `${PACKAGE_NAME}@${PACKAGE_VERSION}`
}
},
auth: {
storage: new BrowserCookieAuthStorageAdapter(cookieOptions)
}
});
if (isSingleton) {
// The `Singleton` pattern is the default to simplify the instantiation
// of a Supabase client across Client Components.
const _supabase = supabase ?? createNewClient();
// For SSG and SSR always create a new Supabase client
if (typeof window === 'undefined') return _supabase;
// Create the Supabase client once in the client
if (!supabase) supabase = _supabase;
return supabase;
}
// This allows for multiple Supabase clients, which may be required when using
// multiple schemas. The user will be responsible for ensuring a single
// instance of Supabase is used across Client Components, for each schema.
return createNewClient();
}

View File

@@ -0,0 +1,239 @@
import {
SupabaseClientOptionsWithoutAuth,
CookieOptionsWithName
} from '@supabase/auth-helpers-shared';
import { NextResponse } from 'next/server';
import { createPagesBrowserClient } from './pagesBrowserClient';
import { createPagesServerClient } from './pagesServerClient';
import { createMiddlewareClient } from './middlewareClient';
import { createClientComponentClient } from './clientComponentClient';
import { createServerComponentClient } from './serverComponentClient';
import { createRouteHandlerClient } from './routeHandlerClient';
import { headers, cookies } from 'next/headers';
import type { GetServerSidePropsContext, NextApiRequest, NextApiResponse } from 'next';
import type { NextRequest } from 'next/server';
import type { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types';
/**
* @deprecated utilize the `createPagesBrowserClient` function instead
*/
export function createBrowserSupabaseClient<
Database = any,
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
? Database[SchemaName]
: any
>({
supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
options,
cookieOptions
}: {
supabaseUrl?: string;
supabaseKey?: string;
options?: SupabaseClientOptionsWithoutAuth<SchemaName>;
cookieOptions?: CookieOptionsWithName;
} = {}) {
console.warn(
'Please utilize the `createPagesBrowserClient` function instead of the deprecated `createBrowserSupabaseClient` function. Learn more: https://supabase.com/docs/guides/auth/auth-helpers/nextjs-pages'
);
return createPagesBrowserClient<Database, SchemaName, Schema>({
supabaseUrl,
supabaseKey,
options,
cookieOptions
});
}
/**
* @deprecated utilize the `createPagesServerClient` function instead
*/
export function createServerSupabaseClient<
Database = any,
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
? Database[SchemaName]
: any
>(
context: GetServerSidePropsContext | { req: NextApiRequest; res: NextApiResponse },
{
supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
options,
cookieOptions
}: {
supabaseUrl?: string;
supabaseKey?: string;
options?: SupabaseClientOptionsWithoutAuth<SchemaName>;
cookieOptions?: CookieOptionsWithName;
} = {}
) {
console.warn(
'Please utilize the `createPagesServerClient` function instead of the deprecated `createServerSupabaseClient` function. Learn more: https://supabase.com/docs/guides/auth/auth-helpers/nextjs-pages'
);
return createPagesServerClient<Database, SchemaName, Schema>(context, {
supabaseUrl,
supabaseKey,
options,
cookieOptions
});
}
/**
* @deprecated utilize the `createMiddlewareClient` function instead
*/
export function createMiddlewareSupabaseClient<
Database = any,
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
? Database[SchemaName]
: any
>(
context: { req: NextRequest; res: NextResponse },
{
supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
options,
cookieOptions
}: {
supabaseUrl?: string;
supabaseKey?: string;
options?: SupabaseClientOptionsWithoutAuth<SchemaName>;
cookieOptions?: CookieOptionsWithName;
} = {}
) {
console.warn(
'Please utilize the `createMiddlewareClient` function instead of the deprecated `createMiddlewareSupabaseClient` function. Learn more: https://supabase.com/docs/guides/auth/auth-helpers/nextjs#middleware'
);
return createMiddlewareClient<Database, SchemaName, Schema>(context, {
supabaseUrl,
supabaseKey,
options,
cookieOptions
});
}
/**
* @deprecated utilize the `createClientComponentClient` function instead
*/
export function createClientComponentSupabaseClient<
Database = any,
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
? Database[SchemaName]
: any
>({
supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
options,
cookieOptions
}: {
supabaseUrl?: string;
supabaseKey?: string;
options?: SupabaseClientOptionsWithoutAuth<SchemaName>;
cookieOptions?: CookieOptionsWithName;
} = {}) {
console.warn(
'Please utilize the `createClientComponentClient` function instead of the deprecated `createClientComponentSupabaseClient` function. Learn more: https://supabase.com/docs/guides/auth/auth-helpers/nextjs#client-component'
);
return createClientComponentClient<Database, SchemaName, Schema>({
supabaseUrl,
supabaseKey,
options,
cookieOptions
});
}
/**
* @deprecated utilize the `createServerComponentClient` function instead
*/
export function createServerComponentSupabaseClient<
Database = any,
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
? Database[SchemaName]
: any
>(
context: {
headers: () => ReturnType<typeof headers>;
cookies: () => ReturnType<typeof cookies>;
},
{
supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
options,
cookieOptions
}: {
supabaseUrl?: string;
supabaseKey?: string;
options?: SupabaseClientOptionsWithoutAuth<SchemaName>;
cookieOptions?: CookieOptionsWithName;
} = {}
) {
console.warn(
'Please utilize the `createServerComponentClient` function instead of the deprecated `createServerComponentSupabaseClient` function. Additionally, this function no longer requires the `headers` function as a parameter. Learn more: https://supabase.com/docs/guides/auth/auth-helpers/nextjs#server-component'
);
return createServerComponentClient<Database, SchemaName, Schema>(
{ cookies: context.cookies },
{
supabaseUrl,
supabaseKey,
options,
cookieOptions
}
);
}
/**
* @deprecated utilize the `createRouteHandlerClient` function instead
*/
export function createRouteHandlerSupabaseClient<
Database = any,
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
? Database[SchemaName]
: any
>(
context: { headers: () => ReturnType<typeof headers>; cookies: () => ReturnType<typeof cookies> },
{
supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
options,
cookieOptions
}: {
supabaseUrl?: string;
supabaseKey?: string;
options?: SupabaseClientOptionsWithoutAuth<SchemaName>;
cookieOptions?: CookieOptionsWithName;
} = {}
) {
console.warn(
'Please utilize the `createRouteHandlerClient` function instead of the deprecated `createRouteHandlerSupabaseClient` function. Additionally, this function no longer requires the `headers` function as a parameter. Learn more: https://supabase.com/docs/guides/auth/auth-helpers/nextjs#route-handler'
);
return createRouteHandlerClient<Database, SchemaName, Schema>(
{ cookies: context.cookies },
{
supabaseUrl,
supabaseKey,
options,
cookieOptions
}
);
}

View File

@@ -0,0 +1,17 @@
// Types
export type { Session, User, SupabaseClient } from '@supabase/supabase-js';
export { createPagesBrowserClient } from './pagesBrowserClient';
export { createPagesServerClient } from './pagesServerClient';
export { createMiddlewareClient } from './middlewareClient';
export { createClientComponentClient } from './clientComponentClient';
export { createServerComponentClient } from './serverComponentClient';
export { createRouteHandlerClient } from './routeHandlerClient';
export { createServerActionClient } from './serverActionClient';
// Deprecated Functions
export {
createBrowserSupabaseClient,
createServerSupabaseClient,
createMiddlewareSupabaseClient
} from './deprecated';

View File

@@ -0,0 +1,104 @@
import {
CookieAuthStorageAdapter,
CookieOptions,
CookieOptionsWithName,
createSupabaseClient,
DefaultCookieOptions,
parseCookies,
serializeCookie,
SupabaseClientOptionsWithoutAuth
} from '@supabase/auth-helpers-shared';
import { NextResponse } from 'next/server';
import { splitCookiesString } from 'set-cookie-parser';
import type { NextRequest } from 'next/server';
import type { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types';
import type { SupabaseClient } from '@supabase/supabase-js';
class NextMiddlewareAuthStorageAdapter extends CookieAuthStorageAdapter {
constructor(
private readonly context: { req: NextRequest; res: NextResponse },
cookieOptions?: CookieOptions
) {
super(cookieOptions);
}
protected getCookie(name: string): string | null | undefined {
const setCookie = splitCookiesString(
this.context.res.headers.get('set-cookie')?.toString() ?? ''
)
.map((c) => parseCookies(c)[name])
.find((c) => !!c);
if (setCookie) {
return setCookie;
}
const cookies = parseCookies(this.context.req.headers.get('cookie') ?? '');
return cookies[name];
}
protected setCookie(name: string, value: string): void {
this._setCookie(name, value);
}
protected deleteCookie(name: string): void {
this._setCookie(name, '', {
maxAge: 0
});
}
private _setCookie(name: string, value: string, options?: DefaultCookieOptions) {
const newSessionStr = serializeCookie(name, value, {
...this.cookieOptions,
...options,
// Allow supabase-js on the client to read the cookie as well
httpOnly: false
});
if (this.context.res.headers) {
this.context.res.headers.append('set-cookie', newSessionStr);
}
}
}
export function createMiddlewareClient<
Database = any,
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
? Database[SchemaName]
: any
>(
context: { req: NextRequest; res: NextResponse },
{
supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
options,
cookieOptions
}: {
supabaseUrl?: string;
supabaseKey?: string;
options?: SupabaseClientOptionsWithoutAuth<SchemaName>;
cookieOptions?: CookieOptionsWithName;
} = {}
): SupabaseClient<Database, SchemaName, Schema> {
if (!supabaseUrl || !supabaseKey) {
throw new Error(
'either NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY env variables or supabaseUrl and supabaseKey are required!'
);
}
return createSupabaseClient<Database, SchemaName, Schema>(supabaseUrl, supabaseKey, {
...options,
global: {
...options?.global,
headers: {
...options?.global?.headers,
'X-Client-Info': `${PACKAGE_NAME}@${PACKAGE_VERSION}`
}
},
auth: {
storage: new NextMiddlewareAuthStorageAdapter(context, cookieOptions)
}
});
}

View File

@@ -0,0 +1,3 @@
import { createClientComponentClient } from './clientComponentClient';
export const createPagesBrowserClient = createClientComponentClient;

View File

@@ -0,0 +1,103 @@
import {
CookieAuthStorageAdapter,
CookieOptions,
CookieOptionsWithName,
createSupabaseClient,
DefaultCookieOptions,
parseCookies,
serializeCookie,
SupabaseClientOptionsWithoutAuth
} from '@supabase/auth-helpers-shared';
import { GetServerSidePropsContext, NextApiRequest, NextApiResponse } from 'next';
import { splitCookiesString } from 'set-cookie-parser';
import type { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types';
import type { SupabaseClient } from '@supabase/supabase-js';
class NextServerAuthStorageAdapter extends CookieAuthStorageAdapter {
constructor(
private readonly context:
| GetServerSidePropsContext
| { req: NextApiRequest; res: NextApiResponse },
cookieOptions?: CookieOptions
) {
super(cookieOptions);
}
protected getCookie(name: string): string | null | undefined {
const setCookie = splitCookiesString(
this.context.res?.getHeader('set-cookie')?.toString() ?? ''
)
.map((c) => parseCookies(c)[name])
.find((c) => !!c);
const value = setCookie ?? this.context.req?.cookies[name];
return value;
}
protected setCookie(name: string, value: string): void {
this._setCookie(name, value);
}
protected deleteCookie(name: string): void {
this._setCookie(name, '', {
maxAge: 0
});
}
private _setCookie(name: string, value: string, options?: DefaultCookieOptions) {
const setCookies = splitCookiesString(
this.context.res.getHeader('set-cookie')?.toString() ?? ''
).filter((c) => !(name in parseCookies(c)));
const cookieStr = serializeCookie(name, value, {
...this.cookieOptions,
...options,
// Allow supabase-js on the client to read the cookie as well
httpOnly: false
});
this.context.res.setHeader('set-cookie', [...setCookies, cookieStr]);
}
}
export function createPagesServerClient<
Database = any,
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
? Database[SchemaName]
: any
>(
context: GetServerSidePropsContext | { req: NextApiRequest; res: NextApiResponse },
{
supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
options,
cookieOptions
}: {
supabaseUrl?: string;
supabaseKey?: string;
options?: SupabaseClientOptionsWithoutAuth<SchemaName>;
cookieOptions?: CookieOptionsWithName;
} = {}
): SupabaseClient<Database, SchemaName, Schema> {
if (!supabaseUrl || !supabaseKey) {
throw new Error(
'either NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY env variables or supabaseUrl and supabaseKey are required!'
);
}
return createSupabaseClient<Database, SchemaName, Schema>(supabaseUrl, supabaseKey, {
...options,
global: {
...options?.global,
headers: {
...options?.global?.headers,
'X-Client-Info': `${PACKAGE_NAME}@${PACKAGE_VERSION}`
}
},
auth: {
storage: new NextServerAuthStorageAdapter(context, cookieOptions)
}
});
}

View File

@@ -0,0 +1,83 @@
import {
CookieAuthStorageAdapter,
CookieOptions,
CookieOptionsWithName,
SupabaseClientOptionsWithoutAuth,
createSupabaseClient
} from '@supabase/auth-helpers-shared';
import { cookies } from 'next/headers';
import type { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types';
import type { SupabaseClient } from '@supabase/supabase-js';
class NextRouteHandlerAuthStorageAdapter extends CookieAuthStorageAdapter {
constructor(
private readonly context: {
cookies: () => ReturnType<typeof cookies>;
},
cookieOptions?: CookieOptions
) {
super(cookieOptions);
}
protected getCookie(name: string): string | null | undefined {
const nextCookies = this.context.cookies();
return nextCookies.get(name)?.value;
}
protected setCookie(name: string, value: string): void {
const nextCookies = this.context.cookies();
nextCookies.set(name, value, this.cookieOptions);
}
protected deleteCookie(name: string): void {
const nextCookies = this.context.cookies();
nextCookies.set(name, '', {
...this.cookieOptions,
maxAge: 0
});
}
}
export function createRouteHandlerClient<
Database = any,
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
? Database[SchemaName]
: any
>(
context: {
cookies: () => ReturnType<typeof cookies>;
},
{
supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
options,
cookieOptions
}: {
supabaseUrl?: string;
supabaseKey?: string;
options?: SupabaseClientOptionsWithoutAuth<SchemaName>;
cookieOptions?: CookieOptionsWithName;
} = {}
): SupabaseClient<Database, SchemaName, Schema> {
if (!supabaseUrl || !supabaseKey) {
throw new Error(
'either NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY env variables or supabaseUrl and supabaseKey are required!'
);
}
return createSupabaseClient<Database, SchemaName, Schema>(supabaseUrl, supabaseKey, {
...options,
global: {
...options?.global,
headers: {
...options?.global?.headers,
'X-Client-Info': `${PACKAGE_NAME}@${PACKAGE_VERSION}`
}
},
auth: {
storage: new NextRouteHandlerAuthStorageAdapter(context, cookieOptions)
}
});
}

View File

@@ -0,0 +1,3 @@
import { createRouteHandlerClient } from './routeHandlerClient';
export const createServerActionClient = createRouteHandlerClient;

View File

@@ -0,0 +1,82 @@
import {
CookieAuthStorageAdapter,
CookieOptions,
CookieOptionsWithName,
SupabaseClientOptionsWithoutAuth,
createSupabaseClient
} from '@supabase/auth-helpers-shared';
import { cookies } from 'next/headers';
import type { SupabaseClient } from '@supabase/supabase-js';
import type { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types';
class NextServerComponentAuthStorageAdapter extends CookieAuthStorageAdapter {
readonly isServer = true;
constructor(
private readonly context: {
cookies: () => ReturnType<typeof cookies>;
},
cookieOptions?: CookieOptions
) {
super(cookieOptions);
}
protected getCookie(name: string): string | null | undefined {
const nextCookies = this.context.cookies();
return nextCookies.get(name)?.value;
}
protected setCookie(name: string, value: string): void {
// Server Components cannot set cookies. Must use Middleware, Server Action or Route Handler
// https://github.com/vercel/next.js/discussions/41745#discussioncomment-5198848
}
protected deleteCookie(name: string): void {
// Server Components cannot set cookies. Must use Middleware, Server Action or Route Handler
// https://github.com/vercel/next.js/discussions/41745#discussioncomment-5198848
}
}
export function createServerComponentClient<
Database = any,
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
? Database[SchemaName]
: any
>(
context: {
cookies: () => ReturnType<typeof cookies>;
},
{
supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
options,
cookieOptions
}: {
supabaseUrl?: string;
supabaseKey?: string;
options?: SupabaseClientOptionsWithoutAuth<SchemaName>;
cookieOptions?: CookieOptionsWithName;
} = {}
): SupabaseClient<Database, SchemaName, Schema> {
if (!supabaseUrl || !supabaseKey) {
throw new Error(
'either NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY env variables or supabaseUrl and supabaseKey are required!'
);
}
return createSupabaseClient<Database, SchemaName, Schema>(supabaseUrl, supabaseKey, {
...options,
global: {
...options?.global,
headers: {
...options?.global?.headers,
'X-Client-Info': `${PACKAGE_NAME}@${PACKAGE_VERSION}`
}
},
auth: {
storage: new NextServerComponentAuthStorageAdapter(context, cookieOptions)
}
});
}