auth-vir 1.3.2 → 2.0.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.
Files changed (59) hide show
  1. package/README.md +27 -18
  2. package/dist/auth-client/backend-auth.client.d.ts +177 -0
  3. package/dist/auth-client/backend-auth.client.js +232 -0
  4. package/dist/auth-client/frontend-auth.client.d.ts +64 -0
  5. package/dist/auth-client/frontend-auth.client.js +107 -0
  6. package/dist/auth.d.ts +32 -46
  7. package/dist/auth.js +36 -36
  8. package/dist/cookie.d.ts +15 -4
  9. package/dist/cookie.js +16 -4
  10. package/dist/csrf-token.d.ts +113 -3
  11. package/dist/csrf-token.js +101 -5
  12. package/dist/generated/browser.d.ts +9 -0
  13. package/dist/generated/browser.js +16 -0
  14. package/dist/generated/client.d.ts +26 -0
  15. package/dist/generated/client.js +31 -0
  16. package/dist/generated/commonInputTypes.d.ts +122 -0
  17. package/dist/generated/commonInputTypes.js +1 -0
  18. package/dist/generated/enums.d.ts +1 -0
  19. package/dist/generated/enums.js +9 -0
  20. package/dist/generated/internal/class.d.ts +126 -0
  21. package/dist/generated/internal/class.js +84 -0
  22. package/dist/generated/internal/prismaNamespace.d.ts +544 -0
  23. package/dist/generated/internal/prismaNamespace.js +101 -0
  24. package/dist/generated/internal/prismaNamespaceBrowser.d.ts +75 -0
  25. package/dist/generated/internal/prismaNamespaceBrowser.js +69 -0
  26. package/dist/generated/models/User.d.ts +983 -0
  27. package/dist/generated/models/User.js +1 -0
  28. package/dist/generated/models.d.ts +2 -0
  29. package/dist/generated/models.js +1 -0
  30. package/dist/generated/shapes.gen.d.ts +8 -0
  31. package/dist/generated/shapes.gen.js +11 -0
  32. package/dist/headers.d.ts +20 -0
  33. package/dist/headers.js +33 -0
  34. package/dist/index.d.ts +2 -0
  35. package/dist/index.js +2 -0
  36. package/dist/jwt/jwt.d.ts +11 -2
  37. package/dist/jwt/jwt.js +14 -3
  38. package/dist/jwt/user-jwt.d.ts +8 -8
  39. package/dist/jwt/user-jwt.js +12 -9
  40. package/package.json +12 -7
  41. package/src/auth-client/backend-auth.client.ts +500 -0
  42. package/src/auth-client/frontend-auth.client.ts +182 -0
  43. package/src/auth.ts +99 -77
  44. package/src/cookie.ts +20 -8
  45. package/src/csrf-token.ts +196 -5
  46. package/src/generated/browser.ts +23 -0
  47. package/src/generated/client.ts +47 -0
  48. package/src/generated/commonInputTypes.ts +147 -0
  49. package/src/generated/enums.ts +14 -0
  50. package/src/generated/internal/class.ts +236 -0
  51. package/src/generated/internal/prismaNamespace.ts +761 -0
  52. package/src/generated/internal/prismaNamespaceBrowser.ts +102 -0
  53. package/src/generated/models/User.ts +1135 -0
  54. package/src/generated/models.ts +11 -0
  55. package/src/generated/shapes.gen.ts +15 -0
  56. package/src/headers.ts +35 -0
  57. package/src/index.ts +2 -0
  58. package/src/jwt/jwt.ts +34 -5
  59. package/src/jwt/user-jwt.ts +21 -12
package/src/auth.ts CHANGED
@@ -1,10 +1,20 @@
1
+ import {type PartialWithUndefined} from '@augment-vir/common';
2
+ import {type FullDate, type UtcTimezone} from 'date-vir';
1
3
  import {
4
+ AuthCookieName,
2
5
  clearAuthCookie,
3
6
  type CookieParams,
4
7
  extractCookieJwt,
5
8
  generateAuthCookie,
6
9
  } from './cookie.js';
7
- import {csrfTokenHeaderName, generateCsrfToken} from './csrf-token.js';
10
+ import {
11
+ extractCsrfTokenHeader,
12
+ generateCsrfToken,
13
+ parseCsrfToken,
14
+ storeCsrfToken,
15
+ wipeCurrentCsrfToken,
16
+ } from './csrf-token.js';
17
+ import {AuthHeaderName} from './headers.js';
8
18
  import {type ParseJwtParams} from './jwt/jwt.js';
9
19
 
10
20
  /**
@@ -30,6 +40,32 @@ function readHeader(headers: HeaderContainer, headerName: string): string | unde
30
40
  }
31
41
  }
32
42
 
43
+ /**
44
+ * Output from {@link extractUserIdFromRequestHeaders}.
45
+ *
46
+ * @category Internal
47
+ */
48
+ export type UserIdResult<UserId extends string | number> = {
49
+ userId: UserId;
50
+ jwtExpiration: FullDate<UtcTimezone>;
51
+ cookieName: string;
52
+ };
53
+
54
+ function readCsrfTokenHeader(
55
+ headers: HeaderContainer,
56
+ overrides: PartialWithUndefined<{
57
+ csrfHeaderName: string;
58
+ }>,
59
+ ): string | undefined {
60
+ const rawCsrfToken = readHeader(headers, overrides.csrfHeaderName || AuthHeaderName.CsrfToken);
61
+
62
+ if (!rawCsrfToken) {
63
+ return undefined;
64
+ }
65
+
66
+ return parseCsrfToken(rawCsrfToken).csrfToken?.token || rawCsrfToken;
67
+ }
68
+
33
69
  /**
34
70
  * Extract the user id from a request by checking both the request cookie and CSRF token. This is
35
71
  * used by host (backend) code to help verify a request. After extracting the user id using this,
@@ -38,13 +74,16 @@ function readHeader(headers: HeaderContainer, headerName: string): string | unde
38
74
  * @category Auth : Host
39
75
  * @returns The extracted user id or `undefined` if no valid auth headers exist.
40
76
  */
41
- export async function extractUserIdFromRequestHeaders(
77
+ export async function extractUserIdFromRequestHeaders<UserId extends string | number>(
42
78
  headers: HeaderContainer,
43
79
  jwtParams: Readonly<ParseJwtParams>,
44
- cookieName?: string | undefined,
45
- ): Promise<string | undefined> {
80
+ cookieName: string = AuthCookieName.Auth,
81
+ overrides: PartialWithUndefined<{
82
+ csrfHeaderName: string;
83
+ }> = {},
84
+ ): Promise<Readonly<UserIdResult<UserId>> | undefined> {
46
85
  try {
47
- const csrfToken = readHeader(headers, csrfTokenHeaderName);
86
+ const csrfToken = readCsrfTokenHeader(headers, overrides);
48
87
  const cookie = readHeader(headers, 'cookie');
49
88
 
50
89
  if (!cookie || !csrfToken) {
@@ -53,11 +92,15 @@ export async function extractUserIdFromRequestHeaders(
53
92
 
54
93
  const jwt = await extractCookieJwt(cookie, jwtParams, cookieName);
55
94
 
56
- if (!jwt || jwt.csrfToken !== csrfToken) {
95
+ if (!jwt || jwt.data.csrfToken !== csrfToken) {
57
96
  return undefined;
58
97
  }
59
98
 
60
- return jwt.userId;
99
+ return {
100
+ userId: jwt.data.userId as UserId,
101
+ jwtExpiration: jwt.jwtExpiration,
102
+ cookieName,
103
+ };
61
104
  } catch {
62
105
  return undefined;
63
106
  }
@@ -69,12 +112,13 @@ export async function extractUserIdFromRequestHeaders(
69
112
  * circumstances where you cannot rely on client-side JavaScript to insert the CSRF token.
70
113
  *
71
114
  * @deprecated Prefer {@link extractUserIdFromRequestHeaders} instead: it is more secure.
115
+ * @category Auth : Host
72
116
  */
73
- export async function extractUserIdFromCookieAlone(
117
+ export async function insecureExtractUserIdFromCookieAlone<UserId extends string | number>(
74
118
  headers: HeaderContainer,
75
119
  jwtParams: Readonly<ParseJwtParams>,
76
- cookieName?: string | undefined,
77
- ): Promise<string | undefined> {
120
+ cookieName: string = AuthCookieName.Auth,
121
+ ): Promise<Readonly<UserIdResult<UserId>> | undefined> {
78
122
  try {
79
123
  const cookie = readHeader(headers, 'cookie');
80
124
 
@@ -88,7 +132,11 @@ export async function extractUserIdFromCookieAlone(
88
132
  return undefined;
89
133
  }
90
134
 
91
- return jwt.userId;
135
+ return {
136
+ userId: jwt.data.userId as UserId,
137
+ jwtExpiration: jwt.jwtExpiration,
138
+ cookieName,
139
+ };
92
140
  } catch {
93
141
  return undefined;
94
142
  }
@@ -99,23 +147,35 @@ export async function extractUserIdFromCookieAlone(
99
147
  *
100
148
  * @category Auth : Host
101
149
  */
102
- export async function generateSuccessfulLoginHeaders(
150
+ export async function generateSuccessfulLoginHeaders<
151
+ CsrfHeaderName extends string = AuthHeaderName.CsrfToken,
152
+ >(
103
153
  /** The id from your database of the user you're authenticating. */
104
- userId: string,
154
+ userId: string | number,
105
155
  cookieConfig: Readonly<CookieParams>,
106
- ) {
107
- const csrfToken = generateCsrfToken();
156
+ overrides: PartialWithUndefined<{
157
+ csrfHeaderName: CsrfHeaderName;
158
+ }> = {},
159
+ ): Promise<
160
+ {
161
+ 'set-cookie': string;
162
+ } & Record<CsrfHeaderName, string>
163
+ > {
164
+ const csrfToken = generateCsrfToken(cookieConfig.cookieDuration);
165
+ const csrfHeaderName = (overrides.csrfHeaderName || AuthHeaderName.CsrfToken) as CsrfHeaderName;
108
166
 
109
167
  return {
110
168
  'set-cookie': await generateAuthCookie(
111
169
  {
112
- csrfToken,
170
+ csrfToken: csrfToken.token,
113
171
  userId,
114
172
  },
115
173
  cookieConfig,
116
174
  ),
117
- [csrfTokenHeaderName]: csrfToken,
118
- };
175
+ [csrfHeaderName]: JSON.stringify(csrfToken),
176
+ } as {
177
+ 'set-cookie': string;
178
+ } & Record<CsrfHeaderName, string>;
119
179
  }
120
180
 
121
181
  /**
@@ -124,11 +184,22 @@ export async function generateSuccessfulLoginHeaders(
124
184
  *
125
185
  * @category Auth : Host
126
186
  */
127
- export function generateLogoutHeaders(...params: Parameters<typeof clearAuthCookie>) {
187
+ export function generateLogoutHeaders<CsrfHeaderName extends string = AuthHeaderName.CsrfToken>(
188
+ cookieConfig: Readonly<Pick<CookieParams, 'cookieName' | 'hostOrigin' | 'isDev'>>,
189
+ overrides: PartialWithUndefined<{
190
+ csrfHeaderName: CsrfHeaderName;
191
+ }> = {},
192
+ ): {
193
+ 'set-cookie': string;
194
+ } & Record<CsrfHeaderName, string> {
195
+ const csrfHeaderName = (overrides.csrfHeaderName || AuthHeaderName.CsrfToken) as CsrfHeaderName;
196
+
128
197
  return {
129
- 'set-cookie': clearAuthCookie(...params),
130
- [csrfTokenHeaderName]: 'redacted',
131
- };
198
+ 'set-cookie': clearAuthCookie(cookieConfig),
199
+ [csrfHeaderName]: 'redacted',
200
+ } as {
201
+ 'set-cookie': string;
202
+ } & Record<CsrfHeaderName, string>;
132
203
  }
133
204
 
134
205
  /**
@@ -142,77 +213,28 @@ export function generateLogoutHeaders(...params: Parameters<typeof clearAuthCook
142
213
  */
143
214
  export function handleAuthResponse(
144
215
  response: Readonly<Pick<Response, 'ok' | 'headers'>>,
145
- overrides: {
216
+ overrides: PartialWithUndefined<{
146
217
  /**
147
218
  * Allows mocking or overriding the global `localStorage`.
148
219
  *
149
220
  * @default globalThis.localStorage
150
221
  */
151
- localStorage?: Pick<Storage, 'setItem' | 'removeItem'>;
222
+ localStorage: Pick<Storage, 'setItem' | 'removeItem'>;
152
223
  /** Override the default CSRF token header name. */
153
- csrfHeaderName?: string;
154
- } = {},
224
+ csrfHeaderName: string;
225
+ }> = {},
155
226
  ) {
156
227
  if (!response.ok) {
157
228
  wipeCurrentCsrfToken(overrides);
158
229
  return;
159
230
  }
160
- const headerName = overrides.csrfHeaderName || csrfTokenHeaderName;
161
231
 
162
- const csrfToken = response.headers.get(headerName);
232
+ const {csrfToken} = extractCsrfTokenHeader(response, overrides);
163
233
 
164
234
  if (!csrfToken) {
165
235
  wipeCurrentCsrfToken(overrides);
166
236
  throw new Error('Did not receive any CSRF token.');
167
237
  }
168
238
 
169
- (overrides.localStorage || globalThis.localStorage).setItem(headerName, csrfToken);
170
- }
171
-
172
- /**
173
- * Used in client (frontend) code to retrieve the current CSRF token in order to send it with
174
- * requests to the host (backend).
175
- *
176
- * @category Auth : Client
177
- */
178
- export function getCurrentCsrfToken(
179
- overrides: {
180
- /**
181
- * Allows mocking or overriding the global `localStorage`.
182
- *
183
- * @default globalThis.localStorage
184
- */
185
- localStorage?: Pick<Storage, 'getItem'>;
186
- /** Override the default CSRF token header name. */
187
- csrfHeaderName?: string;
188
- } = {},
189
- ): string | undefined {
190
- return (
191
- (overrides.localStorage || globalThis.localStorage).getItem(
192
- overrides.csrfHeaderName || csrfTokenHeaderName,
193
- ) || undefined
194
- );
195
- }
196
-
197
- /**
198
- * Wipes the current stored CSRF token. This should be used by client (frontend) code to logout a
199
- * user or react to a session timeout.
200
- *
201
- * @category Auth : Client
202
- */
203
- export function wipeCurrentCsrfToken(
204
- overrides: {
205
- /**
206
- * Allows mocking or overriding the global `localStorage`.
207
- *
208
- * @default globalThis.localStorage
209
- */
210
- localStorage?: Pick<Storage, 'removeItem'>;
211
- /** Override the default CSRF token header name. */
212
- csrfHeaderName?: string;
213
- } = {},
214
- ) {
215
- return (overrides.localStorage || globalThis.localStorage).removeItem(
216
- overrides.csrfHeaderName || csrfTokenHeaderName,
217
- );
239
+ storeCsrfToken(csrfToken, overrides);
218
240
  }
package/src/cookie.ts CHANGED
@@ -3,8 +3,20 @@ import {safeMatch, type PartialWithUndefined} from '@augment-vir/common';
3
3
  import {convertDuration, type AnyDuration} from 'date-vir';
4
4
  import {type Primitive} from 'type-fest';
5
5
  import {parseUrl} from 'url-vir';
6
- import {type CreateJwtParams, type ParseJwtParams} from './jwt/jwt.js';
7
- import {createUserJwt, parseUserJwt, type UserJwtData} from './jwt/user-jwt.js';
6
+ import {type CreateJwtParams, type ParseJwtParams, type ParsedJwt} from './jwt/jwt.js';
7
+ import {createUserJwt, parseUserJwt, type JwtUserData} from './jwt/user-jwt.js';
8
+
9
+ /**
10
+ * Cookie header names supported by default.
11
+ *
12
+ * @category Internal
13
+ */
14
+ export enum AuthCookieName {
15
+ /** Used for a full user login auth. */
16
+ Auth = 'auth',
17
+ /** Use for a temporary "just signed up" auth. */
18
+ SignUp = 'sign-up',
19
+ }
8
20
 
9
21
  /**
10
22
  * Parameters for {@link generateAuthCookie}.
@@ -47,7 +59,7 @@ export type CookieParams = {
47
59
  * @category Internal
48
60
  */
49
61
  export async function generateAuthCookie(
50
- userJwtData: Readonly<UserJwtData>,
62
+ userJwtData: Readonly<JwtUserData>,
51
63
  cookieConfig: Readonly<CookieParams>,
52
64
  ): Promise<string> {
53
65
  return generateCookie({
@@ -122,17 +134,17 @@ export function generateCookie(
122
134
  export async function extractCookieJwt(
123
135
  rawCookie: string,
124
136
  jwtParams: Readonly<ParseJwtParams>,
125
- cookieName: string = 'auth',
126
- ): Promise<undefined | UserJwtData> {
137
+ cookieName: string = AuthCookieName.Auth,
138
+ ): Promise<undefined | ParsedJwt<JwtUserData>> {
127
139
  const cookieRegExp = new RegExp(`${cookieName}=[^;]+(?:;|$)`);
128
140
 
129
- const [auth] = safeMatch(rawCookie, cookieRegExp);
141
+ const [cookieValue] = safeMatch(rawCookie, cookieRegExp);
130
142
 
131
- if (!auth) {
143
+ if (!cookieValue) {
132
144
  return undefined;
133
145
  }
134
146
 
135
- const rawJwt = auth.replace(`${cookieName}=`, '').replace(';', '');
147
+ const rawJwt = cookieValue.replace(`${cookieName}=`, '').replace(';', '');
136
148
 
137
149
  const jwt = await parseUserJwt(rawJwt, jwtParams);
138
150
 
package/src/csrf-token.ts CHANGED
@@ -1,17 +1,208 @@
1
- import {randomString} from '@augment-vir/common';
1
+ import {
2
+ randomString,
3
+ wrapInTry,
4
+ type PartialWithUndefined,
5
+ type SelectFrom,
6
+ } from '@augment-vir/common';
7
+ import {
8
+ calculateRelativeDate,
9
+ fullDateShape,
10
+ getNowInUtcTimezone,
11
+ isDateAfter,
12
+ type AnyDuration,
13
+ } from 'date-vir';
14
+ import {defineShape, parseJsonWithShape} from 'object-shape-tester';
15
+ import {type RequireExactlyOne} from 'type-fest';
16
+ import {AuthHeaderName} from './headers.js';
2
17
 
3
18
  /**
4
- * Name of the header attached to responses that stores the CSRF token value.
19
+ * Shape definition for {@link CsrfToken}.
5
20
  *
6
21
  * @category Internal
7
22
  */
8
- export const csrfTokenHeaderName = 'csrf-token';
23
+ export const csrfTokenShape = defineShape({
24
+ token: '',
25
+ expiration: fullDateShape,
26
+ });
27
+
28
+ /**
29
+ * A cryptographically CSRF token with expiration date.
30
+ *
31
+ * @category Internal
32
+ */
33
+ export type CsrfToken = typeof csrfTokenShape.runtimeType;
9
34
 
10
35
  /**
11
36
  * Generates a random, cryptographically secure CSRF token.
12
37
  *
13
38
  * @category Internal
14
39
  */
15
- export function generateCsrfToken(): string {
16
- return randomString(256);
40
+ export function generateCsrfToken(
41
+ /** How long the CSRF token is valid for. */
42
+ duration: Readonly<AnyDuration>,
43
+ ): CsrfToken {
44
+ return {
45
+ token: randomString(256),
46
+ expiration: calculateRelativeDate(getNowInUtcTimezone(), duration),
47
+ };
48
+ }
49
+
50
+ /**
51
+ * CSRF token failure reasons for {@link GetCsrfTokenResult}.
52
+ *
53
+ * @category Internal
54
+ */
55
+ export enum CsrfTokenFailureReason {
56
+ /** No CSRF token was found. */
57
+ DoesNotExist = 'does-not-exist',
58
+ /** A CSRF token was found but parsing it failed. */
59
+ ParseFailed = 'parse-failed',
60
+ /** A CSRF token was found and parsed but is expired. */
61
+ Expired = 'expired',
62
+ }
63
+
64
+ /**
65
+ * Output from {@link getCurrentCsrfToken}.
66
+ *
67
+ * @category Internal
68
+ */
69
+ export type GetCsrfTokenResult = RequireExactlyOne<{
70
+ csrfToken: Readonly<CsrfToken>;
71
+ failure: CsrfTokenFailureReason;
72
+ }>;
73
+
74
+ /**
75
+ * Extract the CSRF token header from a response.
76
+ *
77
+ * @category Auth : Client
78
+ */
79
+ export function extractCsrfTokenHeader(
80
+ response: Readonly<SelectFrom<Response, {headers: true}>>,
81
+ overrides: PartialWithUndefined<{
82
+ csrfHeaderName: string;
83
+ }> = {},
84
+ ): Readonly<GetCsrfTokenResult> {
85
+ const csrfTokenHeaderName = overrides.csrfHeaderName || AuthHeaderName.CsrfToken;
86
+
87
+ const rawCsrfToken = response.headers.get(csrfTokenHeaderName);
88
+
89
+ return parseCsrfToken(rawCsrfToken);
90
+ }
91
+
92
+ /**
93
+ * Stores the given CSRF token into local storage.
94
+ *
95
+ * @category Auth : Client
96
+ */
97
+ export function storeCsrfToken(
98
+ csrfToken: Readonly<CsrfToken>,
99
+ overrides: PartialWithUndefined<{
100
+ /**
101
+ * Allows mocking or overriding the global `localStorage`.
102
+ *
103
+ * @default globalThis.localStorage
104
+ */
105
+ localStorage: Pick<Storage, 'setItem' | 'removeItem'>;
106
+ /** Override the default CSRF token header name. */
107
+ csrfHeaderName: string;
108
+ }> = {},
109
+ ) {
110
+ (overrides.localStorage || globalThis.localStorage).setItem(
111
+ overrides.csrfHeaderName || AuthHeaderName.CsrfToken,
112
+ JSON.stringify(csrfToken),
113
+ );
114
+ }
115
+
116
+ /**
117
+ * Parse a raw CSRF token JSON string.
118
+ *
119
+ * @category Internal
120
+ */
121
+ export function parseCsrfToken(value: string | undefined | null): Readonly<GetCsrfTokenResult> {
122
+ if (!value) {
123
+ return {
124
+ failure: CsrfTokenFailureReason.DoesNotExist,
125
+ };
126
+ }
127
+
128
+ const csrfToken: CsrfToken | undefined = wrapInTry(
129
+ () =>
130
+ parseJsonWithShape(value, csrfTokenShape, {
131
+ /** For forwards / backwards compatibility. */
132
+ allowExtraKeys: true,
133
+ }),
134
+ {
135
+ fallbackValue: undefined,
136
+ },
137
+ );
138
+
139
+ if (!csrfToken) {
140
+ return {
141
+ failure: CsrfTokenFailureReason.ParseFailed,
142
+ };
143
+ }
144
+
145
+ if (
146
+ isDateAfter({
147
+ fullDate: getNowInUtcTimezone(),
148
+ relativeTo: csrfToken.expiration,
149
+ })
150
+ ) {
151
+ return {
152
+ failure: CsrfTokenFailureReason.Expired,
153
+ };
154
+ }
155
+
156
+ return {
157
+ csrfToken,
158
+ };
159
+ }
160
+
161
+ /**
162
+ * Used in client (frontend) code to retrieve the current CSRF token in order to send it with
163
+ * requests to the host (backend).
164
+ *
165
+ * @category Auth : Client
166
+ */
167
+ export function getCurrentCsrfToken(
168
+ overrides: PartialWithUndefined<{
169
+ /**
170
+ * Allows mocking or overriding the global `localStorage`.
171
+ *
172
+ * @default globalThis.localStorage
173
+ */
174
+ localStorage: Pick<Storage, 'getItem'>;
175
+ /** Override the default CSRF token header name. */
176
+ csrfHeaderName: string;
177
+ }> = {},
178
+ ): Readonly<GetCsrfTokenResult> {
179
+ const rawCsrfToken: string | undefined =
180
+ (overrides.localStorage || globalThis.localStorage).getItem(
181
+ overrides.csrfHeaderName || AuthHeaderName.CsrfToken,
182
+ ) || undefined;
183
+
184
+ return parseCsrfToken(rawCsrfToken);
185
+ }
186
+
187
+ /**
188
+ * Wipes the current stored CSRF token. This should be used by client (frontend) code to logout a
189
+ * user or react to a session timeout.
190
+ *
191
+ * @category Auth : Client
192
+ */
193
+ export function wipeCurrentCsrfToken(
194
+ overrides: PartialWithUndefined<{
195
+ /**
196
+ * Allows mocking or overriding the global `localStorage`.
197
+ *
198
+ * @default globalThis.localStorage
199
+ */
200
+ localStorage: Pick<Storage, 'removeItem'>;
201
+ /** Override the default CSRF token header name. */
202
+ csrfHeaderName: string;
203
+ }> = {},
204
+ ) {
205
+ return (overrides.localStorage || globalThis.localStorage).removeItem(
206
+ overrides.csrfHeaderName || AuthHeaderName.CsrfToken,
207
+ );
17
208
  }
@@ -0,0 +1,23 @@
1
+
2
+ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
+ /* eslint-disable */
4
+ // @ts-nocheck
5
+ /*
6
+ * This file should be your main import to use Prisma-related types and utilities in a browser.
7
+ * Use it to get access to models, enums, and input types.
8
+ *
9
+ * This file does not contain a `PrismaClient` class, nor several other helpers that are intended as server-side only.
10
+ * See `client.ts` for the standard, server-side entry point.
11
+ *
12
+ * 🟢 You can import this file directly.
13
+ */
14
+
15
+ import * as Prisma from './internal/prismaNamespaceBrowser.js'
16
+ export { Prisma }
17
+ export * as $Enums from './enums.js'
18
+ export * from './enums.js';
19
+ /**
20
+ * Model User
21
+ *
22
+ */
23
+ export type User = Prisma.UserModel
@@ -0,0 +1,47 @@
1
+
2
+ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
+ /* eslint-disable */
4
+ // @ts-nocheck
5
+ /*
6
+ * This file should be your main import to use Prisma. Through it you get access to all the models, enums, and input types.
7
+ * If you're looking for something you can import in the client-side of your application, please refer to the `browser.ts` file instead.
8
+ *
9
+ * 🟢 You can import this file directly.
10
+ */
11
+
12
+ import * as process from 'node:process'
13
+ import * as path from 'node:path'
14
+ import { fileURLToPath } from 'node:url'
15
+ globalThis['__dirname'] = path.dirname(fileURLToPath(import.meta.url))
16
+
17
+ import * as runtime from "@prisma/client/runtime/client"
18
+ import * as $Enums from "./enums.js"
19
+ import * as $Class from "./internal/class.js"
20
+ import * as Prisma from "./internal/prismaNamespace.js"
21
+
22
+ export * as $Enums from './enums.js'
23
+ export * from "./enums.js"
24
+ /**
25
+ * ## Prisma Client
26
+ *
27
+ * Type-safe database client for TypeScript
28
+ * @example
29
+ * ```
30
+ * const prisma = new PrismaClient()
31
+ * // Fetch zero or more Users
32
+ * const users = await prisma.user.findMany()
33
+ * ```
34
+ *
35
+ * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client).
36
+ */
37
+ export const PrismaClient = $Class.getPrismaClientClass(__dirname)
38
+ export type PrismaClient<LogOpts extends Prisma.LogLevel = never, OmitOpts extends Prisma.PrismaClientOptions["omit"] = Prisma.PrismaClientOptions["omit"], ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = $Class.PrismaClient<LogOpts, OmitOpts, ExtArgs>
39
+ export { Prisma }
40
+
41
+
42
+
43
+ /**
44
+ * Model User
45
+ *
46
+ */
47
+ export type User = Prisma.UserModel