@cstar.help/js 0.17.5 → 0.18.1
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.
- package/README.md +43 -25
- package/dist/auth/index.cjs +220 -21
- package/dist/auth/index.d.cts +83 -31
- package/dist/auth/index.d.ts +83 -31
- package/dist/auth/index.js +210 -21
- package/dist/chat/index.cjs +134 -22
- package/dist/chat/index.d.cts +32 -4
- package/dist/chat/index.d.ts +32 -4
- package/dist/chat/index.js +134 -22
- package/dist/index.cjs +101 -40
- package/dist/index.d.cts +477 -157
- package/dist/index.d.ts +477 -157
- package/dist/index.js +101 -40
- package/dist/proactive/index.cjs +46 -33
- package/dist/proactive/index.js +45 -34
- package/dist/webhook/index.d.cts +1 -1
- package/dist/webhook/index.d.ts +1 -1
- package/dist/webhook/node.d.cts +1 -1
- package/dist/webhook/node.d.ts +1 -1
- package/dist/{webhookEvents-1N2i2GcQ.d.cts → webhookEvents-Lqpsj935.d.cts} +0 -1
- package/dist/{webhookEvents-1N2i2GcQ.d.ts → webhookEvents-Lqpsj935.d.ts} +0 -1
- package/package.json +1 -1
package/dist/auth/index.d.ts
CHANGED
|
@@ -6,6 +6,14 @@ interface AuthConfig {
|
|
|
6
6
|
teamSlug: string;
|
|
7
7
|
/** Override the base URL (defaults to https://www.cstar.help). */
|
|
8
8
|
baseUrl?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Supabase project URL used to send the signup confirmation email.
|
|
11
|
+
* Defaults to cStar's production project. Required when `baseUrl` points
|
|
12
|
+
* anywhere other than production, so the email comes from the same project.
|
|
13
|
+
*/
|
|
14
|
+
supabaseUrl?: string;
|
|
15
|
+
/** Supabase publishable (anon) key that pairs with `supabaseUrl`. */
|
|
16
|
+
supabaseKey?: string;
|
|
9
17
|
}
|
|
10
18
|
/** A customer identity returned from auth endpoints. */
|
|
11
19
|
interface AuthCustomer {
|
|
@@ -17,26 +25,33 @@ interface AuthCustomer {
|
|
|
17
25
|
interface SignupParams {
|
|
18
26
|
/** Customer email address. */
|
|
19
27
|
email: string;
|
|
20
|
-
/** Password (minimum 6 characters). */
|
|
21
|
-
password: string;
|
|
22
28
|
/** Customer display name. */
|
|
23
29
|
name?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Page the confirmation link returns to. Defaults to the current page in a
|
|
32
|
+
* browser. Its origin must be on the team's allowed redirect list, or cStar
|
|
33
|
+
* falls back to the hosted widget page.
|
|
34
|
+
*/
|
|
35
|
+
returnUrl?: string;
|
|
24
36
|
}
|
|
25
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Response from signup. It is identical for new and existing emails, so a
|
|
39
|
+
* signup form cannot be used to discover who already has an account. The
|
|
40
|
+
* customer confirms through the emailed link; call `completeSignIn()` on the
|
|
41
|
+
* page the link returns to.
|
|
42
|
+
*/
|
|
26
43
|
interface SignupResult {
|
|
27
|
-
customer: AuthCustomer;
|
|
28
|
-
/** Access token for authenticated requests. Null if email confirmation is required. */
|
|
29
|
-
accessToken: string | null;
|
|
30
|
-
/** Refresh token for renewing the session. Null if email confirmation is required. */
|
|
31
|
-
refreshToken: string | null;
|
|
32
|
-
}
|
|
33
|
-
/** Response when email confirmation is required after signup. */
|
|
34
|
-
interface SignupConfirmationResult {
|
|
35
44
|
success: true;
|
|
36
45
|
message: string;
|
|
37
46
|
requiresConfirmation: true;
|
|
38
47
|
}
|
|
39
|
-
/**
|
|
48
|
+
/** @deprecated Signup always requires confirmation now. Use `SignupResult`. */
|
|
49
|
+
type SignupConfirmationResult = SignupResult;
|
|
50
|
+
/**
|
|
51
|
+
* Parameters for logging in an existing customer. Signup is password-less,
|
|
52
|
+
* so this works only after the customer has chosen a password (see
|
|
53
|
+
* `AuthClient.setPassword()`).
|
|
54
|
+
*/
|
|
40
55
|
interface LoginParams {
|
|
41
56
|
/** Customer email address. */
|
|
42
57
|
email: string;
|
|
@@ -69,47 +84,83 @@ interface AuthSession {
|
|
|
69
84
|
*
|
|
70
85
|
* const auth = new AuthClient({ teamSlug: 'acme' });
|
|
71
86
|
*
|
|
72
|
-
* // Sign up a
|
|
73
|
-
*
|
|
74
|
-
* email: 'jane@example.com',
|
|
75
|
-
* password: 'securepass123',
|
|
76
|
-
* name: 'Jane Doe',
|
|
77
|
-
* });
|
|
87
|
+
* // Sign up: cStar emails a sign-in link. No password yet.
|
|
88
|
+
* await auth.signup({ email: 'jane@example.com', name: 'Jane Doe' });
|
|
78
89
|
*
|
|
79
|
-
* //
|
|
80
|
-
* const session = await auth.
|
|
81
|
-
* email: 'jane@example.com',
|
|
82
|
-
* password: 'securepass123',
|
|
83
|
-
* });
|
|
90
|
+
* // On the page the link returns to
|
|
91
|
+
* const session = await auth.completeSignIn();
|
|
84
92
|
*
|
|
85
|
-
* //
|
|
86
|
-
*
|
|
93
|
+
* // Optional: choose a password for faster sign-in next time
|
|
94
|
+
* await auth.setPassword('securepass123');
|
|
95
|
+
*
|
|
96
|
+
* // Later visits: log in with that password
|
|
97
|
+
* await auth.login({ email: 'jane@example.com', password: 'securepass123' });
|
|
87
98
|
* ```
|
|
88
99
|
*/
|
|
89
100
|
declare class AuthClient {
|
|
90
101
|
private readonly baseUrl;
|
|
91
102
|
private readonly teamSlug;
|
|
103
|
+
private readonly supabaseUrl;
|
|
104
|
+
private readonly supabaseKey;
|
|
92
105
|
private session;
|
|
106
|
+
private pkceClient;
|
|
93
107
|
constructor(config: AuthConfig);
|
|
94
108
|
/**
|
|
95
|
-
* Create a
|
|
109
|
+
* Create a password-less customer account and email a sign-in link.
|
|
110
|
+
*
|
|
111
|
+
* The response is the same whether or not the email already has an
|
|
112
|
+
* account. Nothing is signed in yet: the customer clicks the link, and the
|
|
113
|
+
* page it returns to calls `completeSignIn()`. Signup takes no password,
|
|
114
|
+
* because one chosen before the link proves the address could belong to
|
|
115
|
+
* someone else. Once signed in, the customer can call `setPassword()` to
|
|
116
|
+
* enable `login()`.
|
|
96
117
|
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
118
|
+
* Runs in a browser: the PKCE verifier is stored in this page's
|
|
119
|
+
* localStorage so `completeSignIn()` can finish the exchange.
|
|
99
120
|
*
|
|
100
|
-
* @throws
|
|
121
|
+
* @throws CStarRateLimitError when too many signups were attempted
|
|
101
122
|
*/
|
|
102
|
-
signup(params: SignupParams): Promise<SignupResult
|
|
123
|
+
signup(params: SignupParams): Promise<SignupResult>;
|
|
124
|
+
/**
|
|
125
|
+
* Finish sign-in on the page the confirmation link returns to.
|
|
126
|
+
*
|
|
127
|
+
* Reads `?code=` and `?type=` from the URL, removes them from the address
|
|
128
|
+
* bar, exchanges the code, and stores the session. Returns null when the URL
|
|
129
|
+
* holds no cStar confirmation code or the exchange fails.
|
|
130
|
+
*
|
|
131
|
+
* @param url Defaults to `window.location.href`.
|
|
132
|
+
*/
|
|
133
|
+
completeSignIn(url?: string): Promise<AuthSession | null>;
|
|
134
|
+
/**
|
|
135
|
+
* Choose a password for the signed-in customer, so later visits can use
|
|
136
|
+
* `login()` instead of an emailed link.
|
|
137
|
+
*
|
|
138
|
+
* Needs a session from `completeSignIn()` or `login()`. This is the same
|
|
139
|
+
* Supabase Auth password update the hosted widget makes after a first
|
|
140
|
+
* email sign-in, and it clears the widget's "choose a password" prompt.
|
|
141
|
+
* The customer stays signed in.
|
|
142
|
+
*
|
|
143
|
+
* @throws CStarValidationError when the password is under 8 characters or is rejected
|
|
144
|
+
* @throws CStarAuthenticationError when there is no session or it has expired
|
|
145
|
+
*/
|
|
146
|
+
setPassword(password: string): Promise<void>;
|
|
103
147
|
/**
|
|
104
148
|
* Log in an existing customer with email and password.
|
|
105
149
|
*
|
|
150
|
+
* Signup is password-less, so this works only after the customer has
|
|
151
|
+
* chosen a password with `setPassword()` or in the hosted widget.
|
|
152
|
+
*
|
|
106
153
|
* On success, stores the session internally so subsequent
|
|
107
154
|
* ChatClient requests can use `auth.getSession()` for tokens.
|
|
108
155
|
*
|
|
109
156
|
* @throws Error on invalid credentials, unconfirmed email, or server error
|
|
110
157
|
*/
|
|
111
158
|
login(params: LoginParams): Promise<LoginResult>;
|
|
112
|
-
/**
|
|
159
|
+
/**
|
|
160
|
+
* Clear the session: the in-memory one and, when a sign-in link or
|
|
161
|
+
* setPassword() restored it through Supabase Auth, the copy that client
|
|
162
|
+
* keeps in browser storage, so the next person on the device is signed out.
|
|
163
|
+
*/
|
|
113
164
|
logout(): void;
|
|
114
165
|
/** Get the current session, or null if not authenticated. */
|
|
115
166
|
getSession(): AuthSession | null;
|
|
@@ -119,6 +170,7 @@ declare class AuthClient {
|
|
|
119
170
|
get isAuthenticated(): boolean;
|
|
120
171
|
/** Get the current access token, or null. Useful for passing to ChatClient. */
|
|
121
172
|
get accessToken(): string | null;
|
|
173
|
+
private getPkceClient;
|
|
122
174
|
private fetch;
|
|
123
175
|
}
|
|
124
176
|
|
package/dist/auth/index.js
CHANGED
|
@@ -269,45 +269,196 @@ function parseError(statusCode, body, retryAfter) {
|
|
|
269
269
|
|
|
270
270
|
// src/auth/index.ts
|
|
271
271
|
var DEFAULT_BASE_URL = "https://www.cstar.help";
|
|
272
|
+
var PRODUCTION_ORIGINS = /* @__PURE__ */ new Set(["https://www.cstar.help", "https://cstar.help"]);
|
|
273
|
+
var PRODUCTION_SUPABASE_URL = "https://kmorvgcubqthkfrasbny.supabase.co";
|
|
274
|
+
var PRODUCTION_SUPABASE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Imttb3J2Z2N1YnF0aGtmcmFzYm55Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjUzMzczNjIsImV4cCI6MjA4MDkxMzM2Mn0.e0RJbMpZr-8FbJmAGhdw86Ym9M4MCfvX9Qm6Va3d_N8";
|
|
275
|
+
var PKCE_STORAGE_KEY = "cstar_widget_pkce";
|
|
276
|
+
var MIN_PASSWORD_LENGTH = 8;
|
|
277
|
+
var CONFIRMATION_TYPES = /* @__PURE__ */ new Set(["magiclink", "signup", "recovery"]);
|
|
272
278
|
var AuthClient = class {
|
|
273
279
|
constructor(config) {
|
|
274
280
|
this.session = null;
|
|
281
|
+
this.pkceClient = null;
|
|
275
282
|
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
276
283
|
this.teamSlug = config.teamSlug;
|
|
284
|
+
const isProduction = PRODUCTION_ORIGINS.has(this.baseUrl);
|
|
285
|
+
this.supabaseUrl = config.supabaseUrl ?? (isProduction ? PRODUCTION_SUPABASE_URL : null);
|
|
286
|
+
this.supabaseKey = config.supabaseKey ?? (isProduction ? PRODUCTION_SUPABASE_KEY : null);
|
|
277
287
|
}
|
|
278
288
|
/**
|
|
279
|
-
* Create a
|
|
289
|
+
* Create a password-less customer account and email a sign-in link.
|
|
280
290
|
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
291
|
+
* The response is the same whether or not the email already has an
|
|
292
|
+
* account. Nothing is signed in yet: the customer clicks the link, and the
|
|
293
|
+
* page it returns to calls `completeSignIn()`. Signup takes no password,
|
|
294
|
+
* because one chosen before the link proves the address could belong to
|
|
295
|
+
* someone else. Once signed in, the customer can call `setPassword()` to
|
|
296
|
+
* enable `login()`.
|
|
283
297
|
*
|
|
284
|
-
*
|
|
298
|
+
* Runs in a browser: the PKCE verifier is stored in this page's
|
|
299
|
+
* localStorage so `completeSignIn()` can finish the exchange.
|
|
300
|
+
*
|
|
301
|
+
* @throws CStarRateLimitError when too many signups were attempted
|
|
285
302
|
*/
|
|
286
303
|
async signup(params) {
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
name: params.name
|
|
296
|
-
}
|
|
304
|
+
const returnUrl = params.returnUrl ?? (typeof window !== "undefined" && window.location ? window.location.href : void 0);
|
|
305
|
+
const prepared = await this.fetch("/api/widget/auth/signup", {
|
|
306
|
+
method: "POST",
|
|
307
|
+
body: {
|
|
308
|
+
teamId: this.teamSlug,
|
|
309
|
+
email: params.email,
|
|
310
|
+
name: params.name,
|
|
311
|
+
returnUrl
|
|
297
312
|
}
|
|
298
|
-
);
|
|
299
|
-
if (
|
|
313
|
+
});
|
|
314
|
+
if (!prepared?.emailRedirectTo) {
|
|
315
|
+
throw parsePublicError(500, null, "Sign-up prepare returned no redirect URL.");
|
|
316
|
+
}
|
|
317
|
+
const client = await this.getPkceClient();
|
|
318
|
+
const { error } = await client.auth.signInWithOtp({
|
|
319
|
+
email: params.email,
|
|
320
|
+
options: { emailRedirectTo: prepared.emailRedirectTo, shouldCreateUser: false }
|
|
321
|
+
});
|
|
322
|
+
if (error) {
|
|
323
|
+
if (error.status === 429) {
|
|
324
|
+
throw parsePublicError(
|
|
325
|
+
429,
|
|
326
|
+
{ error: "Too many sign-up requests. Please wait a few minutes and try again." },
|
|
327
|
+
"Too many sign-up requests"
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
throw parsePublicError(
|
|
331
|
+
502,
|
|
332
|
+
{
|
|
333
|
+
error: "Couldn't send a confirmation email. Try again, or sign in if you already have an account."
|
|
334
|
+
},
|
|
335
|
+
"Confirmation email failed"
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
success: true,
|
|
340
|
+
message: prepared.message ?? "Check your inbox to finish signing up.",
|
|
341
|
+
requiresConfirmation: true
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Finish sign-in on the page the confirmation link returns to.
|
|
346
|
+
*
|
|
347
|
+
* Reads `?code=` and `?type=` from the URL, removes them from the address
|
|
348
|
+
* bar, exchanges the code, and stores the session. Returns null when the URL
|
|
349
|
+
* holds no cStar confirmation code or the exchange fails.
|
|
350
|
+
*
|
|
351
|
+
* @param url Defaults to `window.location.href`.
|
|
352
|
+
*/
|
|
353
|
+
async completeSignIn(url) {
|
|
354
|
+
const href = url ?? (typeof window !== "undefined" && window.location ? window.location.href : null);
|
|
355
|
+
if (!href) return null;
|
|
356
|
+
const parsed = new URL(href);
|
|
357
|
+
const code = parsed.searchParams.get("code");
|
|
358
|
+
const type = parsed.searchParams.get("type");
|
|
359
|
+
if (!code || !type || !CONFIRMATION_TYPES.has(type)) return null;
|
|
360
|
+
if (url === void 0 && typeof window !== "undefined" && window.history?.replaceState) {
|
|
361
|
+
parsed.searchParams.delete("code");
|
|
362
|
+
parsed.searchParams.delete("type");
|
|
363
|
+
try {
|
|
364
|
+
window.history.replaceState(null, "", parsed.pathname + parsed.search + parsed.hash);
|
|
365
|
+
} catch {
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
const client = await this.getPkceClient();
|
|
369
|
+
const exchanged = await client.auth.exchangeCodeForSession(code);
|
|
370
|
+
const supabaseSession = exchanged?.data?.session;
|
|
371
|
+
if (exchanged?.error || !supabaseSession) return null;
|
|
372
|
+
const result = await this.fetch("/api/widget/auth/magic-link/exchange", {
|
|
373
|
+
method: "POST",
|
|
374
|
+
body: {
|
|
375
|
+
teamId: this.teamSlug,
|
|
376
|
+
accessToken: supabaseSession.access_token,
|
|
377
|
+
refreshToken: supabaseSession.refresh_token
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
if (!result.customer || !result.accessToken || !result.refreshToken) return null;
|
|
381
|
+
this.session = {
|
|
382
|
+
customer: result.customer,
|
|
383
|
+
accessToken: result.accessToken,
|
|
384
|
+
refreshToken: result.refreshToken
|
|
385
|
+
};
|
|
386
|
+
return this.session;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Choose a password for the signed-in customer, so later visits can use
|
|
390
|
+
* `login()` instead of an emailed link.
|
|
391
|
+
*
|
|
392
|
+
* Needs a session from `completeSignIn()` or `login()`. This is the same
|
|
393
|
+
* Supabase Auth password update the hosted widget makes after a first
|
|
394
|
+
* email sign-in, and it clears the widget's "choose a password" prompt.
|
|
395
|
+
* The customer stays signed in.
|
|
396
|
+
*
|
|
397
|
+
* @throws CStarValidationError when the password is under 8 characters or is rejected
|
|
398
|
+
* @throws CStarAuthenticationError when there is no session or it has expired
|
|
399
|
+
*/
|
|
400
|
+
async setPassword(password) {
|
|
401
|
+
if (!password || password.length < MIN_PASSWORD_LENGTH) {
|
|
402
|
+
throw parsePublicError(
|
|
403
|
+
400,
|
|
404
|
+
{ error: `Password must be at least ${MIN_PASSWORD_LENGTH} characters` },
|
|
405
|
+
"Invalid password"
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
const current = this.session;
|
|
409
|
+
if (!current) {
|
|
410
|
+
throw parsePublicError(
|
|
411
|
+
401,
|
|
412
|
+
{ error: "Sign in before choosing a password." },
|
|
413
|
+
"Not signed in"
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
const client = await this.getPkceClient();
|
|
417
|
+
const restored = await client.auth.setSession({
|
|
418
|
+
access_token: current.accessToken,
|
|
419
|
+
refresh_token: current.refreshToken
|
|
420
|
+
});
|
|
421
|
+
const restoredSession = restored?.data?.session;
|
|
422
|
+
if (restored?.error || !restoredSession) {
|
|
423
|
+
throw parsePublicError(
|
|
424
|
+
401,
|
|
425
|
+
{ error: "Your session has expired. Sign in again to choose a password." },
|
|
426
|
+
"Session expired"
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
if (this.session === current) {
|
|
300
430
|
this.session = {
|
|
301
|
-
|
|
302
|
-
accessToken:
|
|
303
|
-
refreshToken:
|
|
431
|
+
...current,
|
|
432
|
+
accessToken: restoredSession.access_token,
|
|
433
|
+
refreshToken: restoredSession.refresh_token
|
|
304
434
|
};
|
|
305
435
|
}
|
|
306
|
-
|
|
436
|
+
const { error } = await client.auth.updateUser({
|
|
437
|
+
password,
|
|
438
|
+
data: { widget_password_pending: false }
|
|
439
|
+
});
|
|
440
|
+
if (error) {
|
|
441
|
+
if (error.status === 429) {
|
|
442
|
+
throw parsePublicError(
|
|
443
|
+
429,
|
|
444
|
+
{ error: "Too many password changes. Please wait a few minutes and try again." },
|
|
445
|
+
"Too many password changes"
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
const rejected = error.status === 400 || error.status === 422;
|
|
449
|
+
throw parsePublicError(
|
|
450
|
+
rejected ? 400 : 502,
|
|
451
|
+
{ error: "That password could not be saved. Please try another one." },
|
|
452
|
+
"Password not saved"
|
|
453
|
+
);
|
|
454
|
+
}
|
|
307
455
|
}
|
|
308
456
|
/**
|
|
309
457
|
* Log in an existing customer with email and password.
|
|
310
458
|
*
|
|
459
|
+
* Signup is password-less, so this works only after the customer has
|
|
460
|
+
* chosen a password with `setPassword()` or in the hosted widget.
|
|
461
|
+
*
|
|
311
462
|
* On success, stores the session internally so subsequent
|
|
312
463
|
* ChatClient requests can use `auth.getSession()` for tokens.
|
|
313
464
|
*
|
|
@@ -331,9 +482,18 @@ var AuthClient = class {
|
|
|
331
482
|
}
|
|
332
483
|
return response;
|
|
333
484
|
}
|
|
334
|
-
/**
|
|
485
|
+
/**
|
|
486
|
+
* Clear the session: the in-memory one and, when a sign-in link or
|
|
487
|
+
* setPassword() restored it through Supabase Auth, the copy that client
|
|
488
|
+
* keeps in browser storage, so the next person on the device is signed out.
|
|
489
|
+
*/
|
|
335
490
|
logout() {
|
|
336
491
|
this.session = null;
|
|
492
|
+
const pkceClient = this.pkceClient;
|
|
493
|
+
if (pkceClient) {
|
|
494
|
+
void pkceClient.then((client) => client.auth.signOut({ scope: "local" })).catch(() => {
|
|
495
|
+
});
|
|
496
|
+
}
|
|
337
497
|
}
|
|
338
498
|
/** Get the current session, or null if not authenticated. */
|
|
339
499
|
getSession() {
|
|
@@ -351,6 +511,35 @@ var AuthClient = class {
|
|
|
351
511
|
get accessToken() {
|
|
352
512
|
return this.session?.accessToken ?? null;
|
|
353
513
|
}
|
|
514
|
+
getPkceClient() {
|
|
515
|
+
const { supabaseUrl, supabaseKey } = this;
|
|
516
|
+
if (!supabaseUrl || !supabaseKey) {
|
|
517
|
+
return Promise.reject(
|
|
518
|
+
parsePublicError(
|
|
519
|
+
400,
|
|
520
|
+
{
|
|
521
|
+
error: "AuthClient needs supabaseUrl and supabaseKey when baseUrl is not https://www.cstar.help."
|
|
522
|
+
},
|
|
523
|
+
"Missing Supabase config"
|
|
524
|
+
)
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
this.pkceClient ?? (this.pkceClient = import(
|
|
528
|
+
/* webpackIgnore: true */
|
|
529
|
+
"@supabase/supabase-js"
|
|
530
|
+
).then(
|
|
531
|
+
({ createClient }) => createClient(supabaseUrl, supabaseKey, {
|
|
532
|
+
auth: {
|
|
533
|
+
flowType: "pkce",
|
|
534
|
+
persistSession: true,
|
|
535
|
+
autoRefreshToken: false,
|
|
536
|
+
storageKey: PKCE_STORAGE_KEY,
|
|
537
|
+
detectSessionInUrl: false
|
|
538
|
+
}
|
|
539
|
+
})
|
|
540
|
+
));
|
|
541
|
+
return this.pkceClient;
|
|
542
|
+
}
|
|
354
543
|
async fetch(path, options) {
|
|
355
544
|
const url = `${this.baseUrl}${path}`;
|
|
356
545
|
const response = await globalThis.fetch(url, {
|