@insforge/sdk 1.0.1-refresh.2 → 1.0.1-refresh.3
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 +129 -92
- package/dist/index.d.ts +129 -92
- package/dist/index.js +135 -102
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +132 -99
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -245,9 +245,9 @@ var SecureSessionStorage = class {
|
|
|
245
245
|
return document.cookie.includes(`${AUTH_FLAG_COOKIE}=true`);
|
|
246
246
|
}
|
|
247
247
|
};
|
|
248
|
-
var
|
|
248
|
+
var LocalSessionStorage = class {
|
|
249
249
|
constructor(storage) {
|
|
250
|
-
this.strategyId = "
|
|
250
|
+
this.strategyId = "local";
|
|
251
251
|
if (storage) {
|
|
252
252
|
this.storage = storage;
|
|
253
253
|
} else if (typeof window !== "undefined" && window.localStorage) {
|
|
@@ -313,10 +313,10 @@ var PersistentSessionStorage = class {
|
|
|
313
313
|
var TokenManager = class {
|
|
314
314
|
/**
|
|
315
315
|
* Create a new TokenManager
|
|
316
|
-
* @param storage - Optional custom storage adapter (used for initial
|
|
316
|
+
* @param storage - Optional custom storage adapter (used for initial LocalSessionStorage)
|
|
317
317
|
*/
|
|
318
318
|
constructor(storage) {
|
|
319
|
-
this.strategy = new
|
|
319
|
+
this.strategy = new LocalSessionStorage(storage);
|
|
320
320
|
}
|
|
321
321
|
/**
|
|
322
322
|
* Set the storage strategy
|
|
@@ -388,12 +388,12 @@ var TokenManager = class {
|
|
|
388
388
|
}
|
|
389
389
|
};
|
|
390
390
|
|
|
391
|
-
// src/lib/
|
|
392
|
-
var
|
|
391
|
+
// src/lib/backend-config.ts
|
|
392
|
+
var DEFAULT_CONFIG = {
|
|
393
393
|
secureSessionStorage: false,
|
|
394
394
|
refreshTokens: false
|
|
395
395
|
};
|
|
396
|
-
async function
|
|
396
|
+
async function discoverBackendConfig(baseUrl, fetchImpl = globalThis.fetch) {
|
|
397
397
|
try {
|
|
398
398
|
const response = await fetchImpl(`${baseUrl}/api/health`, {
|
|
399
399
|
method: "GET",
|
|
@@ -402,25 +402,25 @@ async function discoverCapabilities(baseUrl, fetchImpl = globalThis.fetch) {
|
|
|
402
402
|
}
|
|
403
403
|
});
|
|
404
404
|
if (!response.ok) {
|
|
405
|
-
return
|
|
405
|
+
return DEFAULT_CONFIG;
|
|
406
406
|
}
|
|
407
407
|
const health = await response.json();
|
|
408
|
-
if (health.
|
|
409
|
-
return health.
|
|
408
|
+
if (health.config) {
|
|
409
|
+
return health.config;
|
|
410
410
|
}
|
|
411
|
-
return
|
|
411
|
+
return DEFAULT_CONFIG;
|
|
412
412
|
} catch {
|
|
413
|
-
return
|
|
413
|
+
return DEFAULT_CONFIG;
|
|
414
414
|
}
|
|
415
415
|
}
|
|
416
|
-
function createSessionStorage(
|
|
417
|
-
if (
|
|
416
|
+
function createSessionStorage(config, storage) {
|
|
417
|
+
if (config.secureSessionStorage && config.refreshTokens) {
|
|
418
418
|
return new SecureSessionStorage();
|
|
419
419
|
}
|
|
420
|
-
return new
|
|
420
|
+
return new LocalSessionStorage(storage);
|
|
421
421
|
}
|
|
422
|
-
function
|
|
423
|
-
return { ...
|
|
422
|
+
function getDefaultBackendConfig() {
|
|
423
|
+
return { ...DEFAULT_CONFIG };
|
|
424
424
|
}
|
|
425
425
|
|
|
426
426
|
// src/modules/database-postgrest.ts
|
|
@@ -529,11 +529,72 @@ function isHostedAuthEnvironment() {
|
|
|
529
529
|
return false;
|
|
530
530
|
}
|
|
531
531
|
var Auth = class {
|
|
532
|
-
constructor(http, tokenManager) {
|
|
532
|
+
constructor(http, tokenManager, initializePromise) {
|
|
533
533
|
this.http = http;
|
|
534
534
|
this.tokenManager = tokenManager;
|
|
535
|
-
this.
|
|
535
|
+
this.authStateListeners = /* @__PURE__ */ new Set();
|
|
536
536
|
this.database = new Database(http, tokenManager);
|
|
537
|
+
this.initializePromise = initializePromise ?? Promise.resolve();
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Subscribe to auth state changes
|
|
541
|
+
*
|
|
542
|
+
* New subscribers will receive an INITIAL_SESSION event after initialization completes.
|
|
543
|
+
* This ensures no race condition where subscribers miss the initial state.
|
|
544
|
+
*
|
|
545
|
+
* @param callback - Function called when auth state changes
|
|
546
|
+
* @returns Unsubscribe function
|
|
547
|
+
*
|
|
548
|
+
* @example
|
|
549
|
+
* ```typescript
|
|
550
|
+
* const { data: { subscription } } = client.auth.onAuthStateChange((event, session) => {
|
|
551
|
+
* if (event === 'SIGNED_IN') {
|
|
552
|
+
* console.log('User signed in:', session?.user.email);
|
|
553
|
+
* } else if (event === 'SIGNED_OUT') {
|
|
554
|
+
* console.log('User signed out');
|
|
555
|
+
* }
|
|
556
|
+
* });
|
|
557
|
+
*
|
|
558
|
+
* // Later: unsubscribe
|
|
559
|
+
* subscription.unsubscribe();
|
|
560
|
+
* ```
|
|
561
|
+
*/
|
|
562
|
+
onAuthStateChange(callback) {
|
|
563
|
+
this.authStateListeners.add(callback);
|
|
564
|
+
;
|
|
565
|
+
(async () => {
|
|
566
|
+
await this.initializePromise;
|
|
567
|
+
if (this.authStateListeners.has(callback)) {
|
|
568
|
+
const session = this.tokenManager.getSession();
|
|
569
|
+
try {
|
|
570
|
+
callback("INITIAL_SESSION", session);
|
|
571
|
+
} catch (error) {
|
|
572
|
+
console.error("[Auth] Error in auth state change listener:", error);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
})();
|
|
576
|
+
return {
|
|
577
|
+
data: {
|
|
578
|
+
subscription: {
|
|
579
|
+
unsubscribe: () => {
|
|
580
|
+
this.authStateListeners.delete(callback);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Emit auth state change to all listeners
|
|
588
|
+
* @internal
|
|
589
|
+
*/
|
|
590
|
+
_emitAuthStateChange(event, session) {
|
|
591
|
+
this.authStateListeners.forEach((callback) => {
|
|
592
|
+
try {
|
|
593
|
+
callback(event, session);
|
|
594
|
+
} catch (error) {
|
|
595
|
+
console.error("[Auth] Error in auth state change listener:", error);
|
|
596
|
+
}
|
|
597
|
+
});
|
|
537
598
|
}
|
|
538
599
|
/**
|
|
539
600
|
* Check if an error represents an authentication failure
|
|
@@ -558,30 +619,12 @@ var Auth = class {
|
|
|
558
619
|
return false;
|
|
559
620
|
}
|
|
560
621
|
/**
|
|
561
|
-
*
|
|
562
|
-
*
|
|
622
|
+
* Detect and handle OAuth callback parameters in the URL.
|
|
623
|
+
* Called by client after initialization.
|
|
563
624
|
*/
|
|
564
|
-
|
|
565
|
-
this.initPromise = promise;
|
|
566
|
-
this.detectAuthCallbackAsync();
|
|
567
|
-
}
|
|
568
|
-
/**
|
|
569
|
-
* Wait for initialization to complete (if set)
|
|
570
|
-
*/
|
|
571
|
-
async waitForInit() {
|
|
572
|
-
if (this.initPromise) {
|
|
573
|
-
await this.initPromise;
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
/**
|
|
577
|
-
* Automatically detect and handle OAuth callback parameters in the URL
|
|
578
|
-
* This runs after initialization to seamlessly complete the OAuth flow
|
|
579
|
-
* Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)
|
|
580
|
-
*/
|
|
581
|
-
async detectAuthCallbackAsync() {
|
|
625
|
+
detectAuthCallback() {
|
|
582
626
|
if (typeof window === "undefined") return;
|
|
583
627
|
try {
|
|
584
|
-
await this.waitForInit();
|
|
585
628
|
const params = new URLSearchParams(window.location.search);
|
|
586
629
|
const accessToken = params.get("access_token");
|
|
587
630
|
const userId = params.get("user_id");
|
|
@@ -612,6 +655,7 @@ var Auth = class {
|
|
|
612
655
|
url.searchParams.delete("error");
|
|
613
656
|
}
|
|
614
657
|
window.history.replaceState({}, document.title, url.toString());
|
|
658
|
+
this._emitAuthStateChange("SIGNED_IN", session);
|
|
615
659
|
}
|
|
616
660
|
} catch {
|
|
617
661
|
}
|
|
@@ -621,7 +665,6 @@ var Auth = class {
|
|
|
621
665
|
*/
|
|
622
666
|
async signUp(request) {
|
|
623
667
|
try {
|
|
624
|
-
await this.waitForInit();
|
|
625
668
|
const response = await this.http.post("/api/auth/users", request);
|
|
626
669
|
if (response.accessToken && response.user) {
|
|
627
670
|
const session = {
|
|
@@ -632,6 +675,7 @@ var Auth = class {
|
|
|
632
675
|
this.tokenManager.saveSession(session);
|
|
633
676
|
}
|
|
634
677
|
this.http.setAuthToken(response.accessToken);
|
|
678
|
+
this._emitAuthStateChange("SIGNED_IN", session);
|
|
635
679
|
}
|
|
636
680
|
return {
|
|
637
681
|
data: response,
|
|
@@ -656,7 +700,6 @@ var Auth = class {
|
|
|
656
700
|
*/
|
|
657
701
|
async signInWithPassword(request) {
|
|
658
702
|
try {
|
|
659
|
-
await this.waitForInit();
|
|
660
703
|
const response = await this.http.post("/api/auth/sessions", request);
|
|
661
704
|
const session = {
|
|
662
705
|
accessToken: response.accessToken || "",
|
|
@@ -673,6 +716,7 @@ var Auth = class {
|
|
|
673
716
|
this.tokenManager.saveSession(session);
|
|
674
717
|
}
|
|
675
718
|
this.http.setAuthToken(response.accessToken || "");
|
|
719
|
+
this._emitAuthStateChange("SIGNED_IN", session);
|
|
676
720
|
return {
|
|
677
721
|
data: response,
|
|
678
722
|
error: null
|
|
@@ -739,6 +783,7 @@ var Auth = class {
|
|
|
739
783
|
}
|
|
740
784
|
this.tokenManager.clearSession();
|
|
741
785
|
this.http.setAuthToken(null);
|
|
786
|
+
this._emitAuthStateChange("SIGNED_OUT", null);
|
|
742
787
|
return { error: null };
|
|
743
788
|
} catch (error) {
|
|
744
789
|
return {
|
|
@@ -767,6 +812,8 @@ var Auth = class {
|
|
|
767
812
|
if (response.user) {
|
|
768
813
|
this.tokenManager.setUser(response.user);
|
|
769
814
|
}
|
|
815
|
+
const session = this.tokenManager.getSession();
|
|
816
|
+
this._emitAuthStateChange("TOKEN_REFRESHED", session);
|
|
770
817
|
return response.accessToken;
|
|
771
818
|
}
|
|
772
819
|
throw new InsForgeError(
|
|
@@ -1101,7 +1148,6 @@ var Auth = class {
|
|
|
1101
1148
|
*/
|
|
1102
1149
|
async verifyEmail(request) {
|
|
1103
1150
|
try {
|
|
1104
|
-
await this.waitForInit();
|
|
1105
1151
|
const response = await this.http.post(
|
|
1106
1152
|
"/api/auth/email/verify",
|
|
1107
1153
|
request
|
|
@@ -1113,6 +1159,7 @@ var Auth = class {
|
|
|
1113
1159
|
};
|
|
1114
1160
|
this.tokenManager.saveSession(session);
|
|
1115
1161
|
this.http.setAuthToken(response.accessToken);
|
|
1162
|
+
this._emitAuthStateChange("SIGNED_IN", session);
|
|
1116
1163
|
}
|
|
1117
1164
|
return {
|
|
1118
1165
|
data: response,
|
|
@@ -1658,11 +1705,13 @@ var Functions = class {
|
|
|
1658
1705
|
// src/client.ts
|
|
1659
1706
|
var InsForgeClient = class {
|
|
1660
1707
|
constructor(config = {}) {
|
|
1661
|
-
this.
|
|
1662
|
-
this.
|
|
1663
|
-
|
|
1708
|
+
this.backendConfig = null;
|
|
1709
|
+
this.initializePromise = new Promise((resolve) => {
|
|
1710
|
+
this.initializeResolve = resolve;
|
|
1711
|
+
});
|
|
1664
1712
|
this.http = new HttpClient(config);
|
|
1665
1713
|
this.tokenManager = new TokenManager(config.storage);
|
|
1714
|
+
this.auth = new Auth(this.http, this.tokenManager, this.initializePromise);
|
|
1666
1715
|
if (config.edgeFunctionToken) {
|
|
1667
1716
|
this.http.setAuthToken(config.edgeFunctionToken);
|
|
1668
1717
|
this.tokenManager.saveSession({
|
|
@@ -1671,7 +1720,6 @@ var InsForgeClient = class {
|
|
|
1671
1720
|
// Will be populated by getCurrentUser()
|
|
1672
1721
|
});
|
|
1673
1722
|
}
|
|
1674
|
-
this.auth = new Auth(this.http, this.tokenManager);
|
|
1675
1723
|
this.http.setRefreshCallback(async () => {
|
|
1676
1724
|
try {
|
|
1677
1725
|
return await this.auth.refreshToken();
|
|
@@ -1687,67 +1735,58 @@ var InsForgeClient = class {
|
|
|
1687
1735
|
this.storage = new Storage(this.http);
|
|
1688
1736
|
this.ai = new AI(this.http);
|
|
1689
1737
|
this.functions = new Functions(this.http);
|
|
1690
|
-
this.
|
|
1691
|
-
this.auth.setInitPromise(this.initializationPromise);
|
|
1738
|
+
this._initializeAsync();
|
|
1692
1739
|
}
|
|
1693
1740
|
/**
|
|
1694
|
-
*
|
|
1695
|
-
*
|
|
1696
|
-
*
|
|
1697
|
-
* @example
|
|
1698
|
-
* ```typescript
|
|
1699
|
-
* const client = new InsForgeClient({ baseUrl: 'https://api.example.com' });
|
|
1700
|
-
* await client.initialize(); // Wait for capability discovery
|
|
1701
|
-
* ```
|
|
1741
|
+
* Internal async initialization - discovers backend config and recovers session.
|
|
1742
|
+
* Emits INITIAL_SESSION event when complete.
|
|
1743
|
+
* @internal
|
|
1702
1744
|
*/
|
|
1703
|
-
async
|
|
1704
|
-
if (this.initializationPromise) {
|
|
1705
|
-
await this.initializationPromise;
|
|
1706
|
-
}
|
|
1707
|
-
}
|
|
1708
|
-
/**
|
|
1709
|
-
* Internal async initialization - discovers capabilities and configures storage strategy
|
|
1710
|
-
*/
|
|
1711
|
-
async initializeAsync() {
|
|
1712
|
-
if (this.initialized) return;
|
|
1745
|
+
async _initializeAsync() {
|
|
1713
1746
|
try {
|
|
1714
|
-
this.
|
|
1747
|
+
this.backendConfig = await discoverBackendConfig(
|
|
1715
1748
|
this.http.baseUrl,
|
|
1716
1749
|
this.http.fetch
|
|
1717
1750
|
);
|
|
1718
|
-
const strategy = createSessionStorage(this.
|
|
1751
|
+
const strategy = createSessionStorage(this.backendConfig);
|
|
1719
1752
|
this.tokenManager.setStrategy(strategy);
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1753
|
+
this.auth.detectAuthCallback();
|
|
1754
|
+
let currentSession = this.tokenManager.getSession();
|
|
1755
|
+
if (!currentSession?.accessToken && this.backendConfig.refreshTokens) {
|
|
1756
|
+
if (this.tokenManager.shouldAttemptRefresh()) {
|
|
1757
|
+
try {
|
|
1758
|
+
await this.auth.refreshToken();
|
|
1759
|
+
currentSession = this.tokenManager.getSession();
|
|
1760
|
+
} catch {
|
|
1761
|
+
this.tokenManager.clearSession();
|
|
1762
|
+
this.http.setAuthToken(null);
|
|
1763
|
+
}
|
|
1727
1764
|
}
|
|
1728
1765
|
}
|
|
1729
|
-
this.
|
|
1766
|
+
this.initializeResolve();
|
|
1730
1767
|
} catch {
|
|
1731
|
-
this.
|
|
1768
|
+
this.auth.detectAuthCallback();
|
|
1769
|
+
this.initializeResolve();
|
|
1732
1770
|
}
|
|
1733
1771
|
}
|
|
1772
|
+
/**
|
|
1773
|
+
* Wait for client initialization to complete
|
|
1774
|
+
* @returns Promise that resolves when initialization is done
|
|
1775
|
+
*/
|
|
1776
|
+
async waitForInitialization() {
|
|
1777
|
+
return this.initializePromise;
|
|
1778
|
+
}
|
|
1734
1779
|
/**
|
|
1735
1780
|
* Get the underlying HTTP client for custom requests
|
|
1736
|
-
*
|
|
1737
|
-
* @example
|
|
1738
|
-
* ```typescript
|
|
1739
|
-
* const httpClient = client.getHttpClient();
|
|
1740
|
-
* const customData = await httpClient.get('/api/custom-endpoint');
|
|
1741
|
-
* ```
|
|
1742
1781
|
*/
|
|
1743
1782
|
getHttpClient() {
|
|
1744
1783
|
return this.http;
|
|
1745
1784
|
}
|
|
1746
1785
|
/**
|
|
1747
|
-
* Get the discovered backend
|
|
1786
|
+
* Get the discovered backend configuration
|
|
1748
1787
|
*/
|
|
1749
|
-
|
|
1750
|
-
return this.
|
|
1788
|
+
getBackendConfig() {
|
|
1789
|
+
return this.backendConfig;
|
|
1751
1790
|
}
|
|
1752
1791
|
/**
|
|
1753
1792
|
* Get the current storage strategy identifier
|
|
@@ -1755,18 +1794,12 @@ var InsForgeClient = class {
|
|
|
1755
1794
|
getStorageStrategy() {
|
|
1756
1795
|
return this.tokenManager.getStrategyId();
|
|
1757
1796
|
}
|
|
1758
|
-
/**
|
|
1759
|
-
* Check if the client has been fully initialized
|
|
1760
|
-
*/
|
|
1761
|
-
isInitialized() {
|
|
1762
|
-
return this.initialized;
|
|
1763
|
-
}
|
|
1764
1797
|
};
|
|
1765
|
-
|
|
1766
|
-
// src/index.ts
|
|
1767
|
-
function createClient(config) {
|
|
1798
|
+
function createClient(config = {}) {
|
|
1768
1799
|
return new InsForgeClient(config);
|
|
1769
1800
|
}
|
|
1801
|
+
|
|
1802
|
+
// src/index.ts
|
|
1770
1803
|
var index_default = InsForgeClient;
|
|
1771
1804
|
export {
|
|
1772
1805
|
AI,
|
|
@@ -1776,7 +1809,7 @@ export {
|
|
|
1776
1809
|
HttpClient,
|
|
1777
1810
|
InsForgeClient,
|
|
1778
1811
|
InsForgeError,
|
|
1779
|
-
|
|
1812
|
+
LocalSessionStorage,
|
|
1780
1813
|
SecureSessionStorage,
|
|
1781
1814
|
Storage,
|
|
1782
1815
|
StorageBucket,
|
|
@@ -1784,7 +1817,7 @@ export {
|
|
|
1784
1817
|
createClient,
|
|
1785
1818
|
createSessionStorage,
|
|
1786
1819
|
index_default as default,
|
|
1787
|
-
|
|
1788
|
-
|
|
1820
|
+
discoverBackendConfig,
|
|
1821
|
+
getDefaultBackendConfig
|
|
1789
1822
|
};
|
|
1790
1823
|
//# sourceMappingURL=index.mjs.map
|