@insforge/sdk 1.1.0 → 1.1.2-edge.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.
- package/dist/index.d.mts +69 -2
- package/dist/index.d.ts +69 -2
- package/dist/index.js +179 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +179 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -53,7 +53,7 @@ interface TokenStorage {
|
|
|
53
53
|
removeItem(key: string): void | Promise<void>;
|
|
54
54
|
}
|
|
55
55
|
interface AuthSession {
|
|
56
|
-
user: UserSchema;
|
|
56
|
+
user: UserSchema | null;
|
|
57
57
|
accessToken: string;
|
|
58
58
|
expiresAt?: Date;
|
|
59
59
|
}
|
|
@@ -166,11 +166,19 @@ declare class TokenManager {
|
|
|
166
166
|
declare class Auth {
|
|
167
167
|
private http;
|
|
168
168
|
private tokenManager;
|
|
169
|
+
/**
|
|
170
|
+
* Promise that resolves when OAuth callback handling is complete.
|
|
171
|
+
* Resolves immediately if no OAuth callback is detected in the URL.
|
|
172
|
+
*/
|
|
173
|
+
private authCallbackHandled;
|
|
169
174
|
constructor(http: HttpClient, tokenManager: TokenManager);
|
|
170
175
|
/**
|
|
171
176
|
* Automatically detect and handle OAuth callback parameters in the URL
|
|
172
177
|
* This runs after initialization to seamlessly complete the OAuth flow
|
|
173
|
-
*
|
|
178
|
+
*
|
|
179
|
+
* Supports two flows:
|
|
180
|
+
* - PKCE flow (new): Backend returns `insforge_code` param, exchanged for tokens
|
|
181
|
+
* - Legacy flow: Backend returns tokens directly in URL (backward compatible)
|
|
174
182
|
*/
|
|
175
183
|
private detectAuthCallback;
|
|
176
184
|
/**
|
|
@@ -189,6 +197,7 @@ declare class Auth {
|
|
|
189
197
|
}>;
|
|
190
198
|
/**
|
|
191
199
|
* Sign in with OAuth provider
|
|
200
|
+
* Uses PKCE (Proof Key for Code Exchange) for enhanced security
|
|
192
201
|
*/
|
|
193
202
|
signInWithOAuth(options: {
|
|
194
203
|
provider: OAuthProvidersSchema;
|
|
@@ -198,9 +207,45 @@ declare class Auth {
|
|
|
198
207
|
data: {
|
|
199
208
|
url?: string;
|
|
200
209
|
provider?: string;
|
|
210
|
+
codeVerifier?: string;
|
|
201
211
|
};
|
|
202
212
|
error: InsForgeError | null;
|
|
203
213
|
}>;
|
|
214
|
+
/**
|
|
215
|
+
* Exchange OAuth authorization code for tokens (PKCE flow)
|
|
216
|
+
*
|
|
217
|
+
* After OAuth callback redirects with an `insforge_code` parameter, call this method
|
|
218
|
+
* to exchange it for access tokens. The code verifier is automatically
|
|
219
|
+
* retrieved from sessionStorage if available.
|
|
220
|
+
*
|
|
221
|
+
* Note: This is called automatically by the SDK on initialization. You typically
|
|
222
|
+
* don't need to call this directly unless using `skipBrowserRedirect: true`.
|
|
223
|
+
*
|
|
224
|
+
* @param code - The authorization code from OAuth callback URL
|
|
225
|
+
* @param codeVerifier - Optional code verifier (auto-retrieved from sessionStorage if not provided)
|
|
226
|
+
* @returns Session data with access token and user info
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```ts
|
|
230
|
+
* // Automatic verifier retrieval (recommended for browser)
|
|
231
|
+
* const params = new URLSearchParams(window.location.search);
|
|
232
|
+
* const code = params.get('insforge_code');
|
|
233
|
+
* if (code) {
|
|
234
|
+
* const { data, error } = await insforge.auth.exchangeOAuthCode(code);
|
|
235
|
+
* }
|
|
236
|
+
*
|
|
237
|
+
* // Manual verifier (for custom flows)
|
|
238
|
+
* const { data, error } = await insforge.auth.exchangeOAuthCode(code, codeVerifier);
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
exchangeOAuthCode(code: string, codeVerifier?: string): Promise<{
|
|
242
|
+
data: {
|
|
243
|
+
accessToken: string;
|
|
244
|
+
user: UserSchema;
|
|
245
|
+
redirectTo?: string;
|
|
246
|
+
} | null;
|
|
247
|
+
error: InsForgeError | null;
|
|
248
|
+
}>;
|
|
204
249
|
/**
|
|
205
250
|
* Sign out the current user
|
|
206
251
|
*/
|
|
@@ -238,6 +283,7 @@ declare class Auth {
|
|
|
238
283
|
/**
|
|
239
284
|
* Get the current session (only session data, no API call)
|
|
240
285
|
* Returns the stored JWT token and basic user info from local storage
|
|
286
|
+
* Automatically waits for any pending OAuth callback to complete first
|
|
241
287
|
*/
|
|
242
288
|
getCurrentSession(): Promise<{
|
|
243
289
|
data: {
|
|
@@ -395,6 +441,27 @@ declare class Database {
|
|
|
395
441
|
* - Upserts
|
|
396
442
|
*/
|
|
397
443
|
from(table: string): _supabase_postgrest_js.PostgrestQueryBuilder<any, any, any, string, unknown>;
|
|
444
|
+
/**
|
|
445
|
+
* Call a PostgreSQL function (RPC)
|
|
446
|
+
*
|
|
447
|
+
* @example
|
|
448
|
+
* // Call a function with parameters
|
|
449
|
+
* const { data, error } = await client.database
|
|
450
|
+
* .rpc('get_user_stats', { user_id: 123 });
|
|
451
|
+
*
|
|
452
|
+
* // Call a function with no parameters
|
|
453
|
+
* const { data, error } = await client.database
|
|
454
|
+
* .rpc('get_all_active_users');
|
|
455
|
+
*
|
|
456
|
+
* // With options (head, count, get)
|
|
457
|
+
* const { data, count } = await client.database
|
|
458
|
+
* .rpc('search_posts', { query: 'hello' }, { count: 'exact' });
|
|
459
|
+
*/
|
|
460
|
+
rpc(fn: string, args?: Record<string, unknown>, options?: {
|
|
461
|
+
head?: boolean;
|
|
462
|
+
get?: boolean;
|
|
463
|
+
count?: 'exact' | 'planned' | 'estimated';
|
|
464
|
+
}): _supabase_postgrest_js.PostgrestFilterBuilder<any, any, any, any, string, null, "RPC">;
|
|
398
465
|
}
|
|
399
466
|
|
|
400
467
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ interface TokenStorage {
|
|
|
53
53
|
removeItem(key: string): void | Promise<void>;
|
|
54
54
|
}
|
|
55
55
|
interface AuthSession {
|
|
56
|
-
user: UserSchema;
|
|
56
|
+
user: UserSchema | null;
|
|
57
57
|
accessToken: string;
|
|
58
58
|
expiresAt?: Date;
|
|
59
59
|
}
|
|
@@ -166,11 +166,19 @@ declare class TokenManager {
|
|
|
166
166
|
declare class Auth {
|
|
167
167
|
private http;
|
|
168
168
|
private tokenManager;
|
|
169
|
+
/**
|
|
170
|
+
* Promise that resolves when OAuth callback handling is complete.
|
|
171
|
+
* Resolves immediately if no OAuth callback is detected in the URL.
|
|
172
|
+
*/
|
|
173
|
+
private authCallbackHandled;
|
|
169
174
|
constructor(http: HttpClient, tokenManager: TokenManager);
|
|
170
175
|
/**
|
|
171
176
|
* Automatically detect and handle OAuth callback parameters in the URL
|
|
172
177
|
* This runs after initialization to seamlessly complete the OAuth flow
|
|
173
|
-
*
|
|
178
|
+
*
|
|
179
|
+
* Supports two flows:
|
|
180
|
+
* - PKCE flow (new): Backend returns `insforge_code` param, exchanged for tokens
|
|
181
|
+
* - Legacy flow: Backend returns tokens directly in URL (backward compatible)
|
|
174
182
|
*/
|
|
175
183
|
private detectAuthCallback;
|
|
176
184
|
/**
|
|
@@ -189,6 +197,7 @@ declare class Auth {
|
|
|
189
197
|
}>;
|
|
190
198
|
/**
|
|
191
199
|
* Sign in with OAuth provider
|
|
200
|
+
* Uses PKCE (Proof Key for Code Exchange) for enhanced security
|
|
192
201
|
*/
|
|
193
202
|
signInWithOAuth(options: {
|
|
194
203
|
provider: OAuthProvidersSchema;
|
|
@@ -198,9 +207,45 @@ declare class Auth {
|
|
|
198
207
|
data: {
|
|
199
208
|
url?: string;
|
|
200
209
|
provider?: string;
|
|
210
|
+
codeVerifier?: string;
|
|
201
211
|
};
|
|
202
212
|
error: InsForgeError | null;
|
|
203
213
|
}>;
|
|
214
|
+
/**
|
|
215
|
+
* Exchange OAuth authorization code for tokens (PKCE flow)
|
|
216
|
+
*
|
|
217
|
+
* After OAuth callback redirects with an `insforge_code` parameter, call this method
|
|
218
|
+
* to exchange it for access tokens. The code verifier is automatically
|
|
219
|
+
* retrieved from sessionStorage if available.
|
|
220
|
+
*
|
|
221
|
+
* Note: This is called automatically by the SDK on initialization. You typically
|
|
222
|
+
* don't need to call this directly unless using `skipBrowserRedirect: true`.
|
|
223
|
+
*
|
|
224
|
+
* @param code - The authorization code from OAuth callback URL
|
|
225
|
+
* @param codeVerifier - Optional code verifier (auto-retrieved from sessionStorage if not provided)
|
|
226
|
+
* @returns Session data with access token and user info
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```ts
|
|
230
|
+
* // Automatic verifier retrieval (recommended for browser)
|
|
231
|
+
* const params = new URLSearchParams(window.location.search);
|
|
232
|
+
* const code = params.get('insforge_code');
|
|
233
|
+
* if (code) {
|
|
234
|
+
* const { data, error } = await insforge.auth.exchangeOAuthCode(code);
|
|
235
|
+
* }
|
|
236
|
+
*
|
|
237
|
+
* // Manual verifier (for custom flows)
|
|
238
|
+
* const { data, error } = await insforge.auth.exchangeOAuthCode(code, codeVerifier);
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
exchangeOAuthCode(code: string, codeVerifier?: string): Promise<{
|
|
242
|
+
data: {
|
|
243
|
+
accessToken: string;
|
|
244
|
+
user: UserSchema;
|
|
245
|
+
redirectTo?: string;
|
|
246
|
+
} | null;
|
|
247
|
+
error: InsForgeError | null;
|
|
248
|
+
}>;
|
|
204
249
|
/**
|
|
205
250
|
* Sign out the current user
|
|
206
251
|
*/
|
|
@@ -238,6 +283,7 @@ declare class Auth {
|
|
|
238
283
|
/**
|
|
239
284
|
* Get the current session (only session data, no API call)
|
|
240
285
|
* Returns the stored JWT token and basic user info from local storage
|
|
286
|
+
* Automatically waits for any pending OAuth callback to complete first
|
|
241
287
|
*/
|
|
242
288
|
getCurrentSession(): Promise<{
|
|
243
289
|
data: {
|
|
@@ -395,6 +441,27 @@ declare class Database {
|
|
|
395
441
|
* - Upserts
|
|
396
442
|
*/
|
|
397
443
|
from(table: string): _supabase_postgrest_js.PostgrestQueryBuilder<any, any, any, string, unknown>;
|
|
444
|
+
/**
|
|
445
|
+
* Call a PostgreSQL function (RPC)
|
|
446
|
+
*
|
|
447
|
+
* @example
|
|
448
|
+
* // Call a function with parameters
|
|
449
|
+
* const { data, error } = await client.database
|
|
450
|
+
* .rpc('get_user_stats', { user_id: 123 });
|
|
451
|
+
*
|
|
452
|
+
* // Call a function with no parameters
|
|
453
|
+
* const { data, error } = await client.database
|
|
454
|
+
* .rpc('get_all_active_users');
|
|
455
|
+
*
|
|
456
|
+
* // With options (head, count, get)
|
|
457
|
+
* const { data, count } = await client.database
|
|
458
|
+
* .rpc('search_posts', { query: 'hello' }, { count: 'exact' });
|
|
459
|
+
*/
|
|
460
|
+
rpc(fn: string, args?: Record<string, unknown>, options?: {
|
|
461
|
+
head?: boolean;
|
|
462
|
+
get?: boolean;
|
|
463
|
+
count?: 'exact' | 'planned' | 'estimated';
|
|
464
|
+
}): _supabase_postgrest_js.PostgrestFilterBuilder<any, any, any, any, string, null, "RPC">;
|
|
398
465
|
}
|
|
399
466
|
|
|
400
467
|
/**
|
package/dist/index.js
CHANGED
|
@@ -357,21 +357,74 @@ function isHostedAuthEnvironment() {
|
|
|
357
357
|
}
|
|
358
358
|
return false;
|
|
359
359
|
}
|
|
360
|
+
var PKCE_VERIFIER_KEY = "insforge_pkce_verifier";
|
|
361
|
+
function generateCodeVerifier() {
|
|
362
|
+
const array = new Uint8Array(32);
|
|
363
|
+
crypto.getRandomValues(array);
|
|
364
|
+
return base64UrlEncode(array);
|
|
365
|
+
}
|
|
366
|
+
async function generateCodeChallenge(verifier) {
|
|
367
|
+
const encoder = new TextEncoder();
|
|
368
|
+
const data = encoder.encode(verifier);
|
|
369
|
+
const hash = await crypto.subtle.digest("SHA-256", data);
|
|
370
|
+
return base64UrlEncode(new Uint8Array(hash));
|
|
371
|
+
}
|
|
372
|
+
function base64UrlEncode(buffer) {
|
|
373
|
+
const base64 = btoa(String.fromCharCode(...buffer));
|
|
374
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
375
|
+
}
|
|
376
|
+
function storePkceVerifier(verifier) {
|
|
377
|
+
if (typeof sessionStorage !== "undefined") {
|
|
378
|
+
sessionStorage.setItem(PKCE_VERIFIER_KEY, verifier);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
function retrievePkceVerifier() {
|
|
382
|
+
if (typeof sessionStorage === "undefined") {
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
const verifier = sessionStorage.getItem(PKCE_VERIFIER_KEY);
|
|
386
|
+
if (verifier) {
|
|
387
|
+
sessionStorage.removeItem(PKCE_VERIFIER_KEY);
|
|
388
|
+
}
|
|
389
|
+
return verifier;
|
|
390
|
+
}
|
|
360
391
|
var Auth = class {
|
|
361
392
|
constructor(http, tokenManager) {
|
|
362
393
|
this.http = http;
|
|
363
394
|
this.tokenManager = tokenManager;
|
|
364
|
-
this.detectAuthCallback();
|
|
395
|
+
this.authCallbackHandled = this.detectAuthCallback();
|
|
365
396
|
}
|
|
366
397
|
/**
|
|
367
398
|
* Automatically detect and handle OAuth callback parameters in the URL
|
|
368
399
|
* This runs after initialization to seamlessly complete the OAuth flow
|
|
369
|
-
*
|
|
400
|
+
*
|
|
401
|
+
* Supports two flows:
|
|
402
|
+
* - PKCE flow (new): Backend returns `insforge_code` param, exchanged for tokens
|
|
403
|
+
* - Legacy flow: Backend returns tokens directly in URL (backward compatible)
|
|
370
404
|
*/
|
|
371
|
-
detectAuthCallback() {
|
|
405
|
+
async detectAuthCallback() {
|
|
372
406
|
if (typeof window === "undefined") return;
|
|
373
407
|
try {
|
|
374
408
|
const params = new URLSearchParams(window.location.search);
|
|
409
|
+
const error = params.get("error");
|
|
410
|
+
if (error) {
|
|
411
|
+
const url = new URL(window.location.href);
|
|
412
|
+
url.searchParams.delete("error");
|
|
413
|
+
window.history.replaceState({}, document.title, url.toString());
|
|
414
|
+
console.debug("OAuth callback error:", error);
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
const code = params.get("insforge_code");
|
|
418
|
+
if (code) {
|
|
419
|
+
const url = new URL(window.location.href);
|
|
420
|
+
url.searchParams.delete("insforge_code");
|
|
421
|
+
window.history.replaceState({}, document.title, url.toString());
|
|
422
|
+
const { error: exchangeError } = await this.exchangeOAuthCode(code);
|
|
423
|
+
if (exchangeError) {
|
|
424
|
+
console.debug("OAuth code exchange failed:", exchangeError.message);
|
|
425
|
+
}
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
375
428
|
const accessToken = params.get("access_token");
|
|
376
429
|
const userId = params.get("user_id");
|
|
377
430
|
const email = params.get("email");
|
|
@@ -389,8 +442,6 @@ var Auth = class {
|
|
|
389
442
|
email,
|
|
390
443
|
profile: { name: name || "" },
|
|
391
444
|
metadata: null,
|
|
392
|
-
// These fields are not provided by backend OAuth callback
|
|
393
|
-
// They'll be populated when calling getCurrentUser()
|
|
394
445
|
emailVerified: false,
|
|
395
446
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
396
447
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -404,9 +455,6 @@ var Auth = class {
|
|
|
404
455
|
url.searchParams.delete("email");
|
|
405
456
|
url.searchParams.delete("name");
|
|
406
457
|
url.searchParams.delete("csrf_token");
|
|
407
|
-
if (params.has("error")) {
|
|
408
|
-
url.searchParams.delete("error");
|
|
409
|
-
}
|
|
410
458
|
window.history.replaceState({}, document.title, url.toString());
|
|
411
459
|
}
|
|
412
460
|
} catch (error) {
|
|
@@ -487,11 +535,20 @@ var Auth = class {
|
|
|
487
535
|
}
|
|
488
536
|
/**
|
|
489
537
|
* Sign in with OAuth provider
|
|
538
|
+
* Uses PKCE (Proof Key for Code Exchange) for enhanced security
|
|
490
539
|
*/
|
|
491
540
|
async signInWithOAuth(options) {
|
|
492
541
|
try {
|
|
493
542
|
const { provider, redirectTo, skipBrowserRedirect } = options;
|
|
494
|
-
const
|
|
543
|
+
const codeVerifier = generateCodeVerifier();
|
|
544
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
545
|
+
storePkceVerifier(codeVerifier);
|
|
546
|
+
const params = {
|
|
547
|
+
code_challenge: codeChallenge
|
|
548
|
+
};
|
|
549
|
+
if (redirectTo) {
|
|
550
|
+
params.redirect_uri = redirectTo;
|
|
551
|
+
}
|
|
495
552
|
const endpoint = `/api/auth/oauth/${provider}`;
|
|
496
553
|
const response = await this.http.get(endpoint, { params });
|
|
497
554
|
if (typeof window !== "undefined" && !skipBrowserRedirect) {
|
|
@@ -501,7 +558,9 @@ var Auth = class {
|
|
|
501
558
|
return {
|
|
502
559
|
data: {
|
|
503
560
|
url: response.authUrl,
|
|
504
|
-
provider
|
|
561
|
+
provider,
|
|
562
|
+
codeVerifier
|
|
563
|
+
// Return verifier for manual flow (skipBrowserRedirect)
|
|
505
564
|
},
|
|
506
565
|
error: null
|
|
507
566
|
};
|
|
@@ -519,6 +578,85 @@ var Auth = class {
|
|
|
519
578
|
};
|
|
520
579
|
}
|
|
521
580
|
}
|
|
581
|
+
/**
|
|
582
|
+
* Exchange OAuth authorization code for tokens (PKCE flow)
|
|
583
|
+
*
|
|
584
|
+
* After OAuth callback redirects with an `insforge_code` parameter, call this method
|
|
585
|
+
* to exchange it for access tokens. The code verifier is automatically
|
|
586
|
+
* retrieved from sessionStorage if available.
|
|
587
|
+
*
|
|
588
|
+
* Note: This is called automatically by the SDK on initialization. You typically
|
|
589
|
+
* don't need to call this directly unless using `skipBrowserRedirect: true`.
|
|
590
|
+
*
|
|
591
|
+
* @param code - The authorization code from OAuth callback URL
|
|
592
|
+
* @param codeVerifier - Optional code verifier (auto-retrieved from sessionStorage if not provided)
|
|
593
|
+
* @returns Session data with access token and user info
|
|
594
|
+
*
|
|
595
|
+
* @example
|
|
596
|
+
* ```ts
|
|
597
|
+
* // Automatic verifier retrieval (recommended for browser)
|
|
598
|
+
* const params = new URLSearchParams(window.location.search);
|
|
599
|
+
* const code = params.get('insforge_code');
|
|
600
|
+
* if (code) {
|
|
601
|
+
* const { data, error } = await insforge.auth.exchangeOAuthCode(code);
|
|
602
|
+
* }
|
|
603
|
+
*
|
|
604
|
+
* // Manual verifier (for custom flows)
|
|
605
|
+
* const { data, error } = await insforge.auth.exchangeOAuthCode(code, codeVerifier);
|
|
606
|
+
* ```
|
|
607
|
+
*/
|
|
608
|
+
async exchangeOAuthCode(code, codeVerifier) {
|
|
609
|
+
try {
|
|
610
|
+
const verifier = codeVerifier ?? retrievePkceVerifier();
|
|
611
|
+
if (!verifier) {
|
|
612
|
+
return {
|
|
613
|
+
data: null,
|
|
614
|
+
error: new InsForgeError(
|
|
615
|
+
"PKCE code verifier not found. Ensure signInWithOAuth was called in the same browser session.",
|
|
616
|
+
400,
|
|
617
|
+
"PKCE_VERIFIER_MISSING"
|
|
618
|
+
)
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
const request = {
|
|
622
|
+
code,
|
|
623
|
+
code_verifier: verifier
|
|
624
|
+
};
|
|
625
|
+
const response = await this.http.post("/api/auth/oauth/exchange", request, { credentials: "include" });
|
|
626
|
+
if (!isHostedAuthEnvironment()) {
|
|
627
|
+
const session = {
|
|
628
|
+
accessToken: response.accessToken,
|
|
629
|
+
user: response.user
|
|
630
|
+
};
|
|
631
|
+
if (response.csrfToken) {
|
|
632
|
+
this.tokenManager.setMemoryMode();
|
|
633
|
+
setCsrfToken(response.csrfToken);
|
|
634
|
+
}
|
|
635
|
+
this.tokenManager.saveSession(session);
|
|
636
|
+
this.http.setAuthToken(response.accessToken);
|
|
637
|
+
}
|
|
638
|
+
return {
|
|
639
|
+
data: {
|
|
640
|
+
accessToken: response.accessToken,
|
|
641
|
+
user: response.user,
|
|
642
|
+
redirectTo: response.redirectTo
|
|
643
|
+
},
|
|
644
|
+
error: null
|
|
645
|
+
};
|
|
646
|
+
} catch (error) {
|
|
647
|
+
if (error instanceof InsForgeError) {
|
|
648
|
+
return { data: null, error };
|
|
649
|
+
}
|
|
650
|
+
return {
|
|
651
|
+
data: null,
|
|
652
|
+
error: new InsForgeError(
|
|
653
|
+
"An unexpected error occurred during OAuth code exchange",
|
|
654
|
+
500,
|
|
655
|
+
"UNEXPECTED_ERROR"
|
|
656
|
+
)
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
}
|
|
522
660
|
/**
|
|
523
661
|
* Sign out the current user
|
|
524
662
|
*/
|
|
@@ -607,8 +745,10 @@ var Auth = class {
|
|
|
607
745
|
/**
|
|
608
746
|
* Get the current session (only session data, no API call)
|
|
609
747
|
* Returns the stored JWT token and basic user info from local storage
|
|
748
|
+
* Automatically waits for any pending OAuth callback to complete first
|
|
610
749
|
*/
|
|
611
750
|
async getCurrentSession() {
|
|
751
|
+
await this.authCallbackHandled;
|
|
612
752
|
if (isHostedAuthEnvironment()) {
|
|
613
753
|
return { data: { session: null }, error: null };
|
|
614
754
|
}
|
|
@@ -616,6 +756,11 @@ var Auth = class {
|
|
|
616
756
|
const session = this.tokenManager.getSession();
|
|
617
757
|
if (session) {
|
|
618
758
|
this.http.setAuthToken(session.accessToken);
|
|
759
|
+
if (!session.user) {
|
|
760
|
+
const authResponse = await this.http.get("/api/auth/sessions/current", { credentials: "include" });
|
|
761
|
+
session.user = authResponse.user;
|
|
762
|
+
this.tokenManager.setUser(session.user);
|
|
763
|
+
}
|
|
619
764
|
return { data: { session }, error: null };
|
|
620
765
|
}
|
|
621
766
|
if (typeof window !== "undefined") {
|
|
@@ -907,8 +1052,10 @@ function createInsForgePostgrestFetch(httpClient, tokenManager) {
|
|
|
907
1052
|
return async (input, init) => {
|
|
908
1053
|
const url = typeof input === "string" ? input : input.toString();
|
|
909
1054
|
const urlObj = new URL(url);
|
|
910
|
-
const
|
|
911
|
-
const
|
|
1055
|
+
const pathname = urlObj.pathname.slice(1);
|
|
1056
|
+
const rpcMatch = pathname.match(/^rpc\/(.+)$/);
|
|
1057
|
+
const endpoint = rpcMatch ? `/api/database/rpc/${rpcMatch[1]}` : `/api/database/records/${pathname}`;
|
|
1058
|
+
const insforgeUrl = `${httpClient.baseUrl}${endpoint}${urlObj.search}`;
|
|
912
1059
|
const token = tokenManager.getAccessToken();
|
|
913
1060
|
const httpHeaders = httpClient.getHeaders();
|
|
914
1061
|
const authToken = token || httpHeaders["Authorization"]?.replace("Bearer ", "");
|
|
@@ -968,6 +1115,25 @@ var Database = class {
|
|
|
968
1115
|
from(table) {
|
|
969
1116
|
return this.postgrest.from(table);
|
|
970
1117
|
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Call a PostgreSQL function (RPC)
|
|
1120
|
+
*
|
|
1121
|
+
* @example
|
|
1122
|
+
* // Call a function with parameters
|
|
1123
|
+
* const { data, error } = await client.database
|
|
1124
|
+
* .rpc('get_user_stats', { user_id: 123 });
|
|
1125
|
+
*
|
|
1126
|
+
* // Call a function with no parameters
|
|
1127
|
+
* const { data, error } = await client.database
|
|
1128
|
+
* .rpc('get_all_active_users');
|
|
1129
|
+
*
|
|
1130
|
+
* // With options (head, count, get)
|
|
1131
|
+
* const { data, count } = await client.database
|
|
1132
|
+
* .rpc('search_posts', { query: 'hello' }, { count: 'exact' });
|
|
1133
|
+
*/
|
|
1134
|
+
rpc(fn, args, options) {
|
|
1135
|
+
return this.postgrest.rpc(fn, args, options);
|
|
1136
|
+
}
|
|
971
1137
|
};
|
|
972
1138
|
|
|
973
1139
|
// src/modules/storage.ts
|
|
@@ -1773,8 +1939,7 @@ var InsForgeClient = class {
|
|
|
1773
1939
|
this.http.setAuthToken(config.edgeFunctionToken);
|
|
1774
1940
|
this.tokenManager.saveSession({
|
|
1775
1941
|
accessToken: config.edgeFunctionToken,
|
|
1776
|
-
user:
|
|
1777
|
-
// Will be populated by getCurrentUser()
|
|
1942
|
+
user: null
|
|
1778
1943
|
});
|
|
1779
1944
|
}
|
|
1780
1945
|
const existingSession = this.tokenManager.getSession();
|