-
-
Notifications
You must be signed in to change notification settings - Fork 237
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add shared functions to create browser or server clients
- Loading branch information
1 parent
9b58a60
commit c5f7428
Showing
4 changed files
with
144 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// these variables are defined by tsup | ||
declare const PACKAGE_NAME: string; | ||
declare const PACKAGE_VERSION: string; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { | ||
BrowserCookieAuthStorageAdapter, | ||
CookieOptionsWithName, | ||
SupabaseClientOptionsWithoutAuth, | ||
createSupabaseClient | ||
} from './'; | ||
|
||
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 createBrowserClient< | ||
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: string, | ||
supabaseKey: string, | ||
options?: SupabaseClientOptionsWithoutAuth<SchemaName> & { | ||
cookieOptions?: CookieOptionsWithName; | ||
isSingleton?: boolean; | ||
} | ||
): SupabaseClient<Database, SchemaName, Schema> { | ||
if (!supabaseUrl || !supabaseKey) { | ||
throw new Error('supabaseUrl and supabaseKey are required!'); | ||
} | ||
|
||
const isSingleton = options?.isSingleton ?? true; | ||
|
||
const createNewClient = () => | ||
createSupabaseClient<Database, SchemaName, Schema>(supabaseUrl, supabaseKey, { | ||
...options, | ||
global: { | ||
...options?.global, | ||
headers: { | ||
...options?.global?.headers, | ||
'X-Client-Info': `${PACKAGE_NAME}@${PACKAGE_VERSION}` | ||
} | ||
}, | ||
auth: { | ||
storageKey: options?.cookieOptions?.name, | ||
storage: new BrowserCookieAuthStorageAdapter(options?.cookieOptions) | ||
} | ||
}); | ||
|
||
if (isSingleton) { | ||
// The `Singleton` pattern is the default to simplify the instantiation | ||
// of a Supabase client in the browser - there must only be one | ||
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 for each schema in the browser. | ||
return createNewClient(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { | ||
CookieAuthStorageAdapter, | ||
CookieOptions, | ||
CookieOptionsWithName, | ||
SupabaseClientOptionsWithoutAuth, | ||
createSupabaseClient | ||
} from './'; | ||
|
||
import { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types'; | ||
import type { SupabaseClient } from '@supabase/supabase-js'; | ||
|
||
type CookieStore = { | ||
get: (key: string) => string | undefined; | ||
set: (key: string, value: string, options: CookieOptions) => void; | ||
delete: (key: string) => void; | ||
}; | ||
|
||
class ServerCookieAuthStorageAdapter extends CookieAuthStorageAdapter { | ||
constructor(private readonly cookies: CookieStore, cookieOptions?: CookieOptions) { | ||
super(cookieOptions); | ||
} | ||
|
||
protected getCookie(name: string): string | null | undefined { | ||
return this.cookies.get(name); | ||
} | ||
protected setCookie(name: string, value: string): void { | ||
this.cookies.set(name, value, this.cookieOptions); | ||
} | ||
protected deleteCookie(name: string): void { | ||
this.cookies.delete(name); | ||
} | ||
} | ||
|
||
export function createServerClient< | ||
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: string, | ||
supabaseKey: string, | ||
options: SupabaseClientOptionsWithoutAuth<SchemaName> & { | ||
cookieOptions?: CookieOptionsWithName; | ||
cookies: CookieStore; | ||
} | ||
): SupabaseClient<Database, SchemaName, Schema> { | ||
if (!supabaseUrl || !supabaseKey) { | ||
throw new Error('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: { | ||
storageKey: options.cookieOptions?.name, | ||
storage: new ServerCookieAuthStorageAdapter(options.cookies, options?.cookieOptions) | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters