-
-
Notifications
You must be signed in to change notification settings - Fork 240
/
pagesServerClient.ts
103 lines (94 loc) · 2.97 KB
/
pagesServerClient.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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)
}
});
}