@insforge/sdk 1.2.1-dev.0 → 1.2.1-dev.2
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 +45 -3
- package/dist/index.d.mts +74 -74
- package/dist/index.d.ts +74 -74
- package/dist/index.js +315 -176
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +315 -176
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -192,6 +192,95 @@ var Logger = class {
|
|
|
192
192
|
}
|
|
193
193
|
};
|
|
194
194
|
|
|
195
|
+
// src/lib/token-manager.ts
|
|
196
|
+
var CSRF_TOKEN_COOKIE = "insforge_csrf_token";
|
|
197
|
+
function getCsrfToken() {
|
|
198
|
+
if (typeof document === "undefined") return null;
|
|
199
|
+
const match = document.cookie.split(";").find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));
|
|
200
|
+
if (!match) return null;
|
|
201
|
+
return match.split("=")[1] || null;
|
|
202
|
+
}
|
|
203
|
+
function setCsrfToken(token) {
|
|
204
|
+
if (typeof document === "undefined") return;
|
|
205
|
+
const maxAge = 7 * 24 * 60 * 60;
|
|
206
|
+
const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
|
|
207
|
+
document.cookie = `${CSRF_TOKEN_COOKIE}=${encodeURIComponent(token)}; path=/; max-age=${maxAge}; SameSite=Lax${secure}`;
|
|
208
|
+
}
|
|
209
|
+
function clearCsrfToken() {
|
|
210
|
+
if (typeof document === "undefined") return;
|
|
211
|
+
const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
|
|
212
|
+
document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax${secure}`;
|
|
213
|
+
}
|
|
214
|
+
var TokenManager = class {
|
|
215
|
+
constructor() {
|
|
216
|
+
// In-memory storage
|
|
217
|
+
this.accessToken = null;
|
|
218
|
+
this.user = null;
|
|
219
|
+
// Callback for token changes (used by realtime to reconnect with new token)
|
|
220
|
+
this.onTokenChange = null;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Save session in memory
|
|
224
|
+
*/
|
|
225
|
+
saveSession(session) {
|
|
226
|
+
const tokenChanged = session.accessToken !== this.accessToken;
|
|
227
|
+
this.accessToken = session.accessToken;
|
|
228
|
+
this.user = session.user;
|
|
229
|
+
if (tokenChanged && this.onTokenChange) {
|
|
230
|
+
this.onTokenChange();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get current session
|
|
235
|
+
*/
|
|
236
|
+
getSession() {
|
|
237
|
+
if (!this.accessToken || !this.user) return null;
|
|
238
|
+
return {
|
|
239
|
+
accessToken: this.accessToken,
|
|
240
|
+
user: this.user
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get access token
|
|
245
|
+
*/
|
|
246
|
+
getAccessToken() {
|
|
247
|
+
return this.accessToken;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Set access token
|
|
251
|
+
*/
|
|
252
|
+
setAccessToken(token) {
|
|
253
|
+
const tokenChanged = token !== this.accessToken;
|
|
254
|
+
this.accessToken = token;
|
|
255
|
+
if (tokenChanged && this.onTokenChange) {
|
|
256
|
+
this.onTokenChange();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Get user
|
|
261
|
+
*/
|
|
262
|
+
getUser() {
|
|
263
|
+
return this.user;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Set user
|
|
267
|
+
*/
|
|
268
|
+
setUser(user) {
|
|
269
|
+
this.user = user;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Clear in-memory session
|
|
273
|
+
*/
|
|
274
|
+
clearSession() {
|
|
275
|
+
const hadToken = this.accessToken !== null;
|
|
276
|
+
this.accessToken = null;
|
|
277
|
+
this.user = null;
|
|
278
|
+
if (hadToken && this.onTokenChange) {
|
|
279
|
+
this.onTokenChange();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
|
|
195
284
|
// src/lib/http-client.ts
|
|
196
285
|
var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
|
|
197
286
|
var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
|
|
@@ -199,16 +288,23 @@ var HttpClient = class {
|
|
|
199
288
|
/**
|
|
200
289
|
* Creates a new HttpClient instance.
|
|
201
290
|
* @param config - SDK configuration including baseUrl, timeout, retry settings, and fetch implementation.
|
|
291
|
+
* @param tokenManager - Token manager for session persistence.
|
|
202
292
|
* @param logger - Optional logger instance for request/response debugging.
|
|
203
293
|
*/
|
|
204
|
-
constructor(config, logger) {
|
|
294
|
+
constructor(config, tokenManager, logger) {
|
|
205
295
|
this.userToken = null;
|
|
296
|
+
this.autoRefreshToken = true;
|
|
297
|
+
this.isRefreshing = false;
|
|
298
|
+
this.refreshPromise = null;
|
|
299
|
+
this.refreshToken = null;
|
|
206
300
|
this.baseUrl = config.baseUrl || "http://localhost:7130";
|
|
301
|
+
this.autoRefreshToken = config.autoRefreshToken ?? true;
|
|
207
302
|
this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
|
|
208
303
|
this.anonKey = config.anonKey;
|
|
209
304
|
this.defaultHeaders = {
|
|
210
305
|
...config.headers
|
|
211
306
|
};
|
|
307
|
+
this.tokenManager = tokenManager ?? new TokenManager();
|
|
212
308
|
this.logger = logger || new Logger(false);
|
|
213
309
|
this.timeout = config.timeout ?? 3e4;
|
|
214
310
|
this.retryCount = config.retryCount ?? 3;
|
|
@@ -262,8 +358,14 @@ var HttpClient = class {
|
|
|
262
358
|
* @returns Parsed response data.
|
|
263
359
|
* @throws {InsForgeError} On timeout, network failure, or HTTP error responses.
|
|
264
360
|
*/
|
|
265
|
-
async
|
|
266
|
-
const {
|
|
361
|
+
async handleRequest(method, path, options = {}) {
|
|
362
|
+
const {
|
|
363
|
+
params,
|
|
364
|
+
headers = {},
|
|
365
|
+
body,
|
|
366
|
+
signal: callerSignal,
|
|
367
|
+
...fetchOptions
|
|
368
|
+
} = options;
|
|
267
369
|
const url = this.buildUrl(path, params);
|
|
268
370
|
const startTime = Date.now();
|
|
269
371
|
const canRetry = IDEMPOTENT_METHODS.has(method.toUpperCase()) || options.idempotent === true;
|
|
@@ -302,7 +404,9 @@ var HttpClient = class {
|
|
|
302
404
|
for (let attempt = 0; attempt <= maxAttempts; attempt++) {
|
|
303
405
|
if (attempt > 0) {
|
|
304
406
|
const delay = this.computeRetryDelay(attempt);
|
|
305
|
-
this.logger.warn(
|
|
407
|
+
this.logger.warn(
|
|
408
|
+
`Retry ${attempt}/${maxAttempts} for ${method} ${url} in ${delay}ms`
|
|
409
|
+
);
|
|
306
410
|
if (callerSignal?.aborted) throw callerSignal.reason;
|
|
307
411
|
await new Promise((resolve, reject) => {
|
|
308
412
|
const onAbort = () => {
|
|
@@ -310,7 +414,8 @@ var HttpClient = class {
|
|
|
310
414
|
reject(callerSignal.reason);
|
|
311
415
|
};
|
|
312
416
|
const timer2 = setTimeout(() => {
|
|
313
|
-
if (callerSignal)
|
|
417
|
+
if (callerSignal)
|
|
418
|
+
callerSignal.removeEventListener("abort", onAbort);
|
|
314
419
|
resolve();
|
|
315
420
|
}, delay);
|
|
316
421
|
if (callerSignal) {
|
|
@@ -330,10 +435,16 @@ var HttpClient = class {
|
|
|
330
435
|
controller.abort(callerSignal.reason);
|
|
331
436
|
} else {
|
|
332
437
|
const onCallerAbort = () => controller.abort(callerSignal.reason);
|
|
333
|
-
callerSignal.addEventListener("abort", onCallerAbort, {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
438
|
+
callerSignal.addEventListener("abort", onCallerAbort, {
|
|
439
|
+
once: true
|
|
440
|
+
});
|
|
441
|
+
controller.signal.addEventListener(
|
|
442
|
+
"abort",
|
|
443
|
+
() => {
|
|
444
|
+
callerSignal.removeEventListener("abort", onCallerAbort);
|
|
445
|
+
},
|
|
446
|
+
{ once: true }
|
|
447
|
+
);
|
|
337
448
|
}
|
|
338
449
|
}
|
|
339
450
|
}
|
|
@@ -377,7 +488,13 @@ var HttpClient = class {
|
|
|
377
488
|
}
|
|
378
489
|
if (timer !== void 0) clearTimeout(timer);
|
|
379
490
|
if (!response.ok) {
|
|
380
|
-
this.logger.logResponse(
|
|
491
|
+
this.logger.logResponse(
|
|
492
|
+
method,
|
|
493
|
+
url,
|
|
494
|
+
response.status,
|
|
495
|
+
Date.now() - startTime,
|
|
496
|
+
data
|
|
497
|
+
);
|
|
381
498
|
if (data && typeof data === "object" && "error" in data) {
|
|
382
499
|
if (!data.statusCode && !data.status) {
|
|
383
500
|
data.statusCode = response.status;
|
|
@@ -396,7 +513,13 @@ var HttpClient = class {
|
|
|
396
513
|
"REQUEST_FAILED"
|
|
397
514
|
);
|
|
398
515
|
}
|
|
399
|
-
this.logger.logResponse(
|
|
516
|
+
this.logger.logResponse(
|
|
517
|
+
method,
|
|
518
|
+
url,
|
|
519
|
+
response.status,
|
|
520
|
+
Date.now() - startTime,
|
|
521
|
+
data
|
|
522
|
+
);
|
|
400
523
|
return data;
|
|
401
524
|
} catch (err) {
|
|
402
525
|
if (timer !== void 0) clearTimeout(timer);
|
|
@@ -430,6 +553,33 @@ var HttpClient = class {
|
|
|
430
553
|
"NETWORK_ERROR"
|
|
431
554
|
);
|
|
432
555
|
}
|
|
556
|
+
async request(method, path, options = {}) {
|
|
557
|
+
try {
|
|
558
|
+
return await this.handleRequest(method, path, { ...options });
|
|
559
|
+
} catch (error) {
|
|
560
|
+
if (error instanceof InsForgeError && error.statusCode === 401 && error.error === "INVALID_TOKEN" && this.autoRefreshToken) {
|
|
561
|
+
try {
|
|
562
|
+
const newTokenData = await this.handleTokenRefresh();
|
|
563
|
+
this.setAuthToken(newTokenData.accessToken);
|
|
564
|
+
this.tokenManager.saveSession(newTokenData);
|
|
565
|
+
if (newTokenData.csrfToken) {
|
|
566
|
+
setCsrfToken(newTokenData.csrfToken);
|
|
567
|
+
}
|
|
568
|
+
if (newTokenData.refreshToken) {
|
|
569
|
+
this.setRefreshToken(newTokenData.refreshToken);
|
|
570
|
+
}
|
|
571
|
+
return await this.handleRequest(method, path, { ...options });
|
|
572
|
+
} catch (error2) {
|
|
573
|
+
this.tokenManager.clearSession();
|
|
574
|
+
this.userToken = null;
|
|
575
|
+
this.refreshToken = null;
|
|
576
|
+
clearCsrfToken();
|
|
577
|
+
throw error2;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
throw error;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
433
583
|
/** Performs a GET request. */
|
|
434
584
|
get(path, options) {
|
|
435
585
|
return this.request("GET", path, options);
|
|
@@ -454,6 +604,9 @@ var HttpClient = class {
|
|
|
454
604
|
setAuthToken(token) {
|
|
455
605
|
this.userToken = token;
|
|
456
606
|
}
|
|
607
|
+
setRefreshToken(token) {
|
|
608
|
+
this.refreshToken = token;
|
|
609
|
+
}
|
|
457
610
|
/** Returns the current default headers including the authorization header if set. */
|
|
458
611
|
getHeaders() {
|
|
459
612
|
const headers = { ...this.defaultHeaders };
|
|
@@ -463,94 +616,31 @@ var HttpClient = class {
|
|
|
463
616
|
}
|
|
464
617
|
return headers;
|
|
465
618
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
var CSRF_TOKEN_COOKIE = "insforge_csrf_token";
|
|
470
|
-
function getCsrfToken() {
|
|
471
|
-
if (typeof document === "undefined") return null;
|
|
472
|
-
const match = document.cookie.split(";").find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));
|
|
473
|
-
if (!match) return null;
|
|
474
|
-
return match.split("=")[1] || null;
|
|
475
|
-
}
|
|
476
|
-
function setCsrfToken(token) {
|
|
477
|
-
if (typeof document === "undefined") return;
|
|
478
|
-
const maxAge = 7 * 24 * 60 * 60;
|
|
479
|
-
const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
|
|
480
|
-
document.cookie = `${CSRF_TOKEN_COOKIE}=${encodeURIComponent(token)}; path=/; max-age=${maxAge}; SameSite=Lax${secure}`;
|
|
481
|
-
}
|
|
482
|
-
function clearCsrfToken() {
|
|
483
|
-
if (typeof document === "undefined") return;
|
|
484
|
-
const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
|
|
485
|
-
document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax${secure}`;
|
|
486
|
-
}
|
|
487
|
-
var TokenManager = class {
|
|
488
|
-
constructor() {
|
|
489
|
-
// In-memory storage
|
|
490
|
-
this.accessToken = null;
|
|
491
|
-
this.user = null;
|
|
492
|
-
// Callback for token changes (used by realtime to reconnect with new token)
|
|
493
|
-
this.onTokenChange = null;
|
|
494
|
-
}
|
|
495
|
-
/**
|
|
496
|
-
* Save session in memory
|
|
497
|
-
*/
|
|
498
|
-
saveSession(session) {
|
|
499
|
-
const tokenChanged = session.accessToken !== this.accessToken;
|
|
500
|
-
this.accessToken = session.accessToken;
|
|
501
|
-
this.user = session.user;
|
|
502
|
-
if (tokenChanged && this.onTokenChange) {
|
|
503
|
-
this.onTokenChange();
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
/**
|
|
507
|
-
* Get current session
|
|
508
|
-
*/
|
|
509
|
-
getSession() {
|
|
510
|
-
if (!this.accessToken || !this.user) return null;
|
|
511
|
-
return {
|
|
512
|
-
accessToken: this.accessToken,
|
|
513
|
-
user: this.user
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
/**
|
|
517
|
-
* Get access token
|
|
518
|
-
*/
|
|
519
|
-
getAccessToken() {
|
|
520
|
-
return this.accessToken;
|
|
521
|
-
}
|
|
522
|
-
/**
|
|
523
|
-
* Set access token
|
|
524
|
-
*/
|
|
525
|
-
setAccessToken(token) {
|
|
526
|
-
const tokenChanged = token !== this.accessToken;
|
|
527
|
-
this.accessToken = token;
|
|
528
|
-
if (tokenChanged && this.onTokenChange) {
|
|
529
|
-
this.onTokenChange();
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
/**
|
|
533
|
-
* Get user
|
|
534
|
-
*/
|
|
535
|
-
getUser() {
|
|
536
|
-
return this.user;
|
|
537
|
-
}
|
|
538
|
-
/**
|
|
539
|
-
* Set user
|
|
540
|
-
*/
|
|
541
|
-
setUser(user) {
|
|
542
|
-
this.user = user;
|
|
543
|
-
}
|
|
544
|
-
/**
|
|
545
|
-
* Clear in-memory session
|
|
546
|
-
*/
|
|
547
|
-
clearSession() {
|
|
548
|
-
const hadToken = this.accessToken !== null;
|
|
549
|
-
this.accessToken = null;
|
|
550
|
-
this.user = null;
|
|
551
|
-
if (hadToken && this.onTokenChange) {
|
|
552
|
-
this.onTokenChange();
|
|
619
|
+
async handleTokenRefresh() {
|
|
620
|
+
if (this.isRefreshing) {
|
|
621
|
+
return this.refreshPromise;
|
|
553
622
|
}
|
|
623
|
+
this.isRefreshing = true;
|
|
624
|
+
this.refreshPromise = (async () => {
|
|
625
|
+
try {
|
|
626
|
+
const csrfToken = getCsrfToken();
|
|
627
|
+
const body = this.refreshToken ? { refreshToken: this.refreshToken } : void 0;
|
|
628
|
+
const response = await this.handleRequest(
|
|
629
|
+
"POST",
|
|
630
|
+
"/api/auth/sessions/current",
|
|
631
|
+
{
|
|
632
|
+
body,
|
|
633
|
+
headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {},
|
|
634
|
+
credentials: "include"
|
|
635
|
+
}
|
|
636
|
+
);
|
|
637
|
+
return response;
|
|
638
|
+
} finally {
|
|
639
|
+
this.isRefreshing = false;
|
|
640
|
+
this.refreshPromise = null;
|
|
641
|
+
}
|
|
642
|
+
})();
|
|
643
|
+
return this.refreshPromise;
|
|
554
644
|
}
|
|
555
645
|
};
|
|
556
646
|
|
|
@@ -639,6 +729,7 @@ var Auth = class {
|
|
|
639
729
|
this.tokenManager.saveSession(session);
|
|
640
730
|
}
|
|
641
731
|
this.http.setAuthToken(response.accessToken);
|
|
732
|
+
this.http.setRefreshToken(response.refreshToken ?? null);
|
|
642
733
|
return true;
|
|
643
734
|
}
|
|
644
735
|
// ============================================================================
|
|
@@ -646,7 +737,7 @@ var Auth = class {
|
|
|
646
737
|
// ============================================================================
|
|
647
738
|
/**
|
|
648
739
|
* Detect and handle OAuth callback parameters in URL
|
|
649
|
-
* Supports PKCE flow (insforge_code)
|
|
740
|
+
* Supports PKCE flow (insforge_code)
|
|
650
741
|
*/
|
|
651
742
|
async detectAuthCallback() {
|
|
652
743
|
if (this.isServerMode() || typeof window === "undefined") return;
|
|
@@ -667,31 +758,6 @@ var Auth = class {
|
|
|
667
758
|
}
|
|
668
759
|
return;
|
|
669
760
|
}
|
|
670
|
-
const accessToken = params.get("access_token");
|
|
671
|
-
const userId = params.get("user_id");
|
|
672
|
-
const email = params.get("email");
|
|
673
|
-
if (accessToken && userId && email) {
|
|
674
|
-
const csrfToken = params.get("csrf_token");
|
|
675
|
-
const name = params.get("name");
|
|
676
|
-
if (csrfToken) {
|
|
677
|
-
setCsrfToken(csrfToken);
|
|
678
|
-
}
|
|
679
|
-
const session = {
|
|
680
|
-
accessToken,
|
|
681
|
-
user: {
|
|
682
|
-
id: userId,
|
|
683
|
-
email,
|
|
684
|
-
profile: { name: name || "" },
|
|
685
|
-
metadata: null,
|
|
686
|
-
emailVerified: false,
|
|
687
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
688
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
689
|
-
}
|
|
690
|
-
};
|
|
691
|
-
this.tokenManager.saveSession(session);
|
|
692
|
-
this.http.setAuthToken(accessToken);
|
|
693
|
-
cleanUrlParams("access_token", "user_id", "email", "name", "csrf_token");
|
|
694
|
-
}
|
|
695
761
|
} catch (error) {
|
|
696
762
|
console.debug("OAuth callback detection skipped:", error);
|
|
697
763
|
}
|
|
@@ -709,6 +775,9 @@ var Auth = class {
|
|
|
709
775
|
if (response.accessToken && response.user) {
|
|
710
776
|
this.saveSessionFromResponse(response);
|
|
711
777
|
}
|
|
778
|
+
if (response.refreshToken) {
|
|
779
|
+
this.http.setRefreshToken(response.refreshToken);
|
|
780
|
+
}
|
|
712
781
|
return { data: response, error: null };
|
|
713
782
|
} catch (error) {
|
|
714
783
|
return wrapError(error, "An unexpected error occurred during sign up");
|
|
@@ -722,6 +791,9 @@ var Auth = class {
|
|
|
722
791
|
{ credentials: "include" }
|
|
723
792
|
);
|
|
724
793
|
this.saveSessionFromResponse(response);
|
|
794
|
+
if (response.refreshToken) {
|
|
795
|
+
this.http.setRefreshToken(response.refreshToken);
|
|
796
|
+
}
|
|
725
797
|
return { data: response, error: null };
|
|
726
798
|
} catch (error) {
|
|
727
799
|
return wrapError(error, "An unexpected error occurred during sign in");
|
|
@@ -739,12 +811,15 @@ var Auth = class {
|
|
|
739
811
|
}
|
|
740
812
|
this.tokenManager.clearSession();
|
|
741
813
|
this.http.setAuthToken(null);
|
|
814
|
+
this.http.setRefreshToken(null);
|
|
742
815
|
if (!this.isServerMode()) {
|
|
743
816
|
clearCsrfToken();
|
|
744
817
|
}
|
|
745
818
|
return { error: null };
|
|
746
819
|
} catch {
|
|
747
|
-
return {
|
|
820
|
+
return {
|
|
821
|
+
error: new InsForgeError("Failed to sign out", 500, "SIGNOUT_ERROR")
|
|
822
|
+
};
|
|
748
823
|
}
|
|
749
824
|
}
|
|
750
825
|
// ============================================================================
|
|
@@ -766,7 +841,9 @@ var Auth = class {
|
|
|
766
841
|
providerKey
|
|
767
842
|
);
|
|
768
843
|
const oauthPath = isBuiltInProvider ? `/api/auth/oauth/${providerKey}` : `/api/auth/oauth/custom/${providerKey}`;
|
|
769
|
-
const response = await this.http.get(oauthPath, {
|
|
844
|
+
const response = await this.http.get(oauthPath, {
|
|
845
|
+
params
|
|
846
|
+
});
|
|
770
847
|
if (!this.isServerMode() && typeof window !== "undefined" && !skipBrowserRedirect) {
|
|
771
848
|
window.location.href = response.authUrl;
|
|
772
849
|
return { data: {}, error: null };
|
|
@@ -806,7 +883,10 @@ var Auth = class {
|
|
|
806
883
|
)
|
|
807
884
|
};
|
|
808
885
|
}
|
|
809
|
-
const request = {
|
|
886
|
+
const request = {
|
|
887
|
+
code,
|
|
888
|
+
code_verifier: verifier
|
|
889
|
+
};
|
|
810
890
|
const response = await this.http.post(
|
|
811
891
|
this.isServerMode() ? "/api/auth/oauth/exchange?client_type=mobile" : "/api/auth/oauth/exchange",
|
|
812
892
|
request,
|
|
@@ -814,16 +894,14 @@ var Auth = class {
|
|
|
814
894
|
);
|
|
815
895
|
this.saveSessionFromResponse(response);
|
|
816
896
|
return {
|
|
817
|
-
data:
|
|
818
|
-
accessToken: response.accessToken,
|
|
819
|
-
refreshToken: response.refreshToken,
|
|
820
|
-
user: response.user,
|
|
821
|
-
redirectTo: response.redirectTo
|
|
822
|
-
},
|
|
897
|
+
data: response,
|
|
823
898
|
error: null
|
|
824
899
|
};
|
|
825
900
|
} catch (error) {
|
|
826
|
-
return wrapError(
|
|
901
|
+
return wrapError(
|
|
902
|
+
error,
|
|
903
|
+
"An unexpected error occurred during OAuth code exchange"
|
|
904
|
+
);
|
|
827
905
|
}
|
|
828
906
|
}
|
|
829
907
|
/**
|
|
@@ -842,16 +920,18 @@ var Auth = class {
|
|
|
842
920
|
{ credentials: "include" }
|
|
843
921
|
);
|
|
844
922
|
this.saveSessionFromResponse(response);
|
|
923
|
+
if (response.refreshToken) {
|
|
924
|
+
this.http.setRefreshToken(response.refreshToken);
|
|
925
|
+
}
|
|
845
926
|
return {
|
|
846
|
-
data:
|
|
847
|
-
accessToken: response.accessToken,
|
|
848
|
-
refreshToken: response.refreshToken,
|
|
849
|
-
user: response.user
|
|
850
|
-
},
|
|
927
|
+
data: response,
|
|
851
928
|
error: null
|
|
852
929
|
};
|
|
853
930
|
} catch (error) {
|
|
854
|
-
return wrapError(
|
|
931
|
+
return wrapError(
|
|
932
|
+
error,
|
|
933
|
+
"An unexpected error occurred during ID token sign in"
|
|
934
|
+
);
|
|
855
935
|
}
|
|
856
936
|
}
|
|
857
937
|
// ============================================================================
|
|
@@ -892,7 +972,10 @@ var Auth = class {
|
|
|
892
972
|
}
|
|
893
973
|
return { data: response, error: null };
|
|
894
974
|
} catch (error) {
|
|
895
|
-
return wrapError(
|
|
975
|
+
return wrapError(
|
|
976
|
+
error,
|
|
977
|
+
"An unexpected error occurred during session refresh"
|
|
978
|
+
);
|
|
896
979
|
}
|
|
897
980
|
}
|
|
898
981
|
/**
|
|
@@ -905,7 +988,9 @@ var Auth = class {
|
|
|
905
988
|
const accessToken = this.tokenManager.getAccessToken();
|
|
906
989
|
if (!accessToken) return { data: { user: null }, error: null };
|
|
907
990
|
this.http.setAuthToken(accessToken);
|
|
908
|
-
const response = await this.http.get(
|
|
991
|
+
const response = await this.http.get(
|
|
992
|
+
"/api/auth/sessions/current"
|
|
993
|
+
);
|
|
909
994
|
const user = response.user ?? null;
|
|
910
995
|
return { data: { user }, error: null };
|
|
911
996
|
}
|
|
@@ -943,24 +1028,38 @@ var Auth = class {
|
|
|
943
1028
|
// ============================================================================
|
|
944
1029
|
async getProfile(userId) {
|
|
945
1030
|
try {
|
|
946
|
-
const response = await this.http.get(
|
|
1031
|
+
const response = await this.http.get(
|
|
1032
|
+
`/api/auth/profiles/${userId}`
|
|
1033
|
+
);
|
|
947
1034
|
return { data: response, error: null };
|
|
948
1035
|
} catch (error) {
|
|
949
|
-
return wrapError(
|
|
1036
|
+
return wrapError(
|
|
1037
|
+
error,
|
|
1038
|
+
"An unexpected error occurred while fetching user profile"
|
|
1039
|
+
);
|
|
950
1040
|
}
|
|
951
1041
|
}
|
|
952
1042
|
async setProfile(profile) {
|
|
953
1043
|
try {
|
|
954
|
-
const response = await this.http.patch(
|
|
955
|
-
|
|
956
|
-
|
|
1044
|
+
const response = await this.http.patch(
|
|
1045
|
+
"/api/auth/profiles/current",
|
|
1046
|
+
{
|
|
1047
|
+
profile
|
|
1048
|
+
}
|
|
1049
|
+
);
|
|
957
1050
|
const currentUser = this.tokenManager.getUser();
|
|
958
1051
|
if (!this.isServerMode() && currentUser && response.profile !== void 0) {
|
|
959
|
-
this.tokenManager.setUser({
|
|
1052
|
+
this.tokenManager.setUser({
|
|
1053
|
+
...currentUser,
|
|
1054
|
+
profile: response.profile
|
|
1055
|
+
});
|
|
960
1056
|
}
|
|
961
1057
|
return { data: response, error: null };
|
|
962
1058
|
} catch (error) {
|
|
963
|
-
return wrapError(
|
|
1059
|
+
return wrapError(
|
|
1060
|
+
error,
|
|
1061
|
+
"An unexpected error occurred while updating user profile"
|
|
1062
|
+
);
|
|
964
1063
|
}
|
|
965
1064
|
}
|
|
966
1065
|
// ============================================================================
|
|
@@ -968,19 +1067,15 @@ var Auth = class {
|
|
|
968
1067
|
// ============================================================================
|
|
969
1068
|
async resendVerificationEmail(request) {
|
|
970
1069
|
try {
|
|
971
|
-
const response = await this.http.post(
|
|
972
|
-
"/api/auth/email/send-verification",
|
|
973
|
-
request
|
|
974
|
-
);
|
|
1070
|
+
const response = await this.http.post("/api/auth/email/send-verification", request);
|
|
975
1071
|
return { data: response, error: null };
|
|
976
1072
|
} catch (error) {
|
|
977
|
-
return wrapError(
|
|
1073
|
+
return wrapError(
|
|
1074
|
+
error,
|
|
1075
|
+
"An unexpected error occurred while sending verification email"
|
|
1076
|
+
);
|
|
978
1077
|
}
|
|
979
1078
|
}
|
|
980
|
-
/** @deprecated Use `resendVerificationEmail` instead */
|
|
981
|
-
async sendVerificationEmail(request) {
|
|
982
|
-
return this.resendVerificationEmail(request);
|
|
983
|
-
}
|
|
984
1079
|
async verifyEmail(request) {
|
|
985
1080
|
try {
|
|
986
1081
|
const response = await this.http.post(
|
|
@@ -989,9 +1084,15 @@ var Auth = class {
|
|
|
989
1084
|
{ credentials: "include" }
|
|
990
1085
|
);
|
|
991
1086
|
this.saveSessionFromResponse(response);
|
|
1087
|
+
if (response.refreshToken) {
|
|
1088
|
+
this.http.setRefreshToken(response.refreshToken);
|
|
1089
|
+
}
|
|
992
1090
|
return { data: response, error: null };
|
|
993
1091
|
} catch (error) {
|
|
994
|
-
return wrapError(
|
|
1092
|
+
return wrapError(
|
|
1093
|
+
error,
|
|
1094
|
+
"An unexpected error occurred while verifying email"
|
|
1095
|
+
);
|
|
995
1096
|
}
|
|
996
1097
|
}
|
|
997
1098
|
// ============================================================================
|
|
@@ -999,13 +1100,13 @@ var Auth = class {
|
|
|
999
1100
|
// ============================================================================
|
|
1000
1101
|
async sendResetPasswordEmail(request) {
|
|
1001
1102
|
try {
|
|
1002
|
-
const response = await this.http.post(
|
|
1003
|
-
"/api/auth/email/send-reset-password",
|
|
1004
|
-
request
|
|
1005
|
-
);
|
|
1103
|
+
const response = await this.http.post("/api/auth/email/send-reset-password", request);
|
|
1006
1104
|
return { data: response, error: null };
|
|
1007
1105
|
} catch (error) {
|
|
1008
|
-
return wrapError(
|
|
1106
|
+
return wrapError(
|
|
1107
|
+
error,
|
|
1108
|
+
"An unexpected error occurred while sending password reset email"
|
|
1109
|
+
);
|
|
1009
1110
|
}
|
|
1010
1111
|
}
|
|
1011
1112
|
async exchangeResetPasswordToken(request) {
|
|
@@ -1016,7 +1117,10 @@ var Auth = class {
|
|
|
1016
1117
|
);
|
|
1017
1118
|
return { data: response, error: null };
|
|
1018
1119
|
} catch (error) {
|
|
1019
|
-
return wrapError(
|
|
1120
|
+
return wrapError(
|
|
1121
|
+
error,
|
|
1122
|
+
"An unexpected error occurred while verifying reset code"
|
|
1123
|
+
);
|
|
1020
1124
|
}
|
|
1021
1125
|
}
|
|
1022
1126
|
async resetPassword(request) {
|
|
@@ -1027,7 +1131,10 @@ var Auth = class {
|
|
|
1027
1131
|
);
|
|
1028
1132
|
return { data: response, error: null };
|
|
1029
1133
|
} catch (error) {
|
|
1030
|
-
return wrapError(
|
|
1134
|
+
return wrapError(
|
|
1135
|
+
error,
|
|
1136
|
+
"An unexpected error occurred while resetting password"
|
|
1137
|
+
);
|
|
1031
1138
|
}
|
|
1032
1139
|
}
|
|
1033
1140
|
// ============================================================================
|
|
@@ -1035,10 +1142,15 @@ var Auth = class {
|
|
|
1035
1142
|
// ============================================================================
|
|
1036
1143
|
async getPublicAuthConfig() {
|
|
1037
1144
|
try {
|
|
1038
|
-
const response = await this.http.get(
|
|
1145
|
+
const response = await this.http.get(
|
|
1146
|
+
"/api/auth/public-config"
|
|
1147
|
+
);
|
|
1039
1148
|
return { data: response, error: null };
|
|
1040
1149
|
} catch (error) {
|
|
1041
|
-
return wrapError(
|
|
1150
|
+
return wrapError(
|
|
1151
|
+
error,
|
|
1152
|
+
"An unexpected error occurred while fetching auth configuration"
|
|
1153
|
+
);
|
|
1042
1154
|
}
|
|
1043
1155
|
}
|
|
1044
1156
|
};
|
|
@@ -1784,9 +1896,17 @@ var Functions = class _Functions {
|
|
|
1784
1896
|
});
|
|
1785
1897
|
return { data, error: null };
|
|
1786
1898
|
} catch (error) {
|
|
1787
|
-
if (error
|
|
1899
|
+
if (error instanceof Error && error.name === "AbortError") throw error;
|
|
1900
|
+
if (error instanceof InsForgeError && error.statusCode === 404) {
|
|
1788
1901
|
} else {
|
|
1789
|
-
return {
|
|
1902
|
+
return {
|
|
1903
|
+
data: null,
|
|
1904
|
+
error: error instanceof InsForgeError ? error : new InsForgeError(
|
|
1905
|
+
error instanceof Error ? error.message : "Function invocation failed",
|
|
1906
|
+
500,
|
|
1907
|
+
"FUNCTION_ERROR"
|
|
1908
|
+
)
|
|
1909
|
+
};
|
|
1790
1910
|
}
|
|
1791
1911
|
}
|
|
1792
1912
|
}
|
|
@@ -1795,7 +1915,15 @@ var Functions = class _Functions {
|
|
|
1795
1915
|
const data = await this.http.request(method, path, { body, headers });
|
|
1796
1916
|
return { data, error: null };
|
|
1797
1917
|
} catch (error) {
|
|
1798
|
-
|
|
1918
|
+
if (error instanceof Error && error.name === "AbortError") throw error;
|
|
1919
|
+
return {
|
|
1920
|
+
data: null,
|
|
1921
|
+
error: error instanceof InsForgeError ? error : new InsForgeError(
|
|
1922
|
+
error instanceof Error ? error.message : "Function invocation failed",
|
|
1923
|
+
500,
|
|
1924
|
+
"FUNCTION_ERROR"
|
|
1925
|
+
)
|
|
1926
|
+
};
|
|
1799
1927
|
}
|
|
1800
1928
|
}
|
|
1801
1929
|
};
|
|
@@ -2066,8 +2194,15 @@ var Emails = class {
|
|
|
2066
2194
|
);
|
|
2067
2195
|
return { data, error: null };
|
|
2068
2196
|
} catch (error) {
|
|
2069
|
-
|
|
2070
|
-
return {
|
|
2197
|
+
if (error instanceof Error && error.name === "AbortError") throw error;
|
|
2198
|
+
return {
|
|
2199
|
+
data: null,
|
|
2200
|
+
error: error instanceof InsForgeError ? error : new InsForgeError(
|
|
2201
|
+
error instanceof Error ? error.message : "Email send failed",
|
|
2202
|
+
500,
|
|
2203
|
+
"EMAIL_ERROR"
|
|
2204
|
+
)
|
|
2205
|
+
};
|
|
2071
2206
|
}
|
|
2072
2207
|
}
|
|
2073
2208
|
};
|
|
@@ -2076,8 +2211,8 @@ var Emails = class {
|
|
|
2076
2211
|
var InsForgeClient = class {
|
|
2077
2212
|
constructor(config = {}) {
|
|
2078
2213
|
const logger = new Logger(config.debug);
|
|
2079
|
-
this.http = new HttpClient(config, logger);
|
|
2080
2214
|
this.tokenManager = new TokenManager();
|
|
2215
|
+
this.http = new HttpClient(config, this.tokenManager, logger);
|
|
2081
2216
|
if (config.edgeFunctionToken) {
|
|
2082
2217
|
this.http.setAuthToken(config.edgeFunctionToken);
|
|
2083
2218
|
this.tokenManager.setAccessToken(config.edgeFunctionToken);
|
|
@@ -2089,12 +2224,16 @@ var InsForgeClient = class {
|
|
|
2089
2224
|
this.storage = new Storage(this.http);
|
|
2090
2225
|
this.ai = new AI(this.http);
|
|
2091
2226
|
this.functions = new Functions(this.http, config.functionsUrl);
|
|
2092
|
-
this.realtime = new Realtime(
|
|
2227
|
+
this.realtime = new Realtime(
|
|
2228
|
+
this.http.baseUrl,
|
|
2229
|
+
this.tokenManager,
|
|
2230
|
+
config.anonKey
|
|
2231
|
+
);
|
|
2093
2232
|
this.emails = new Emails(this.http);
|
|
2094
2233
|
}
|
|
2095
2234
|
/**
|
|
2096
2235
|
* Get the underlying HTTP client for custom requests
|
|
2097
|
-
*
|
|
2236
|
+
*
|
|
2098
2237
|
* @example
|
|
2099
2238
|
* ```typescript
|
|
2100
2239
|
* const httpClient = client.getHttpClient();
|