@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.js
CHANGED
|
@@ -27,7 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
HttpClient: () => HttpClient,
|
|
28
28
|
InsForgeClient: () => InsForgeClient,
|
|
29
29
|
InsForgeError: () => InsForgeError,
|
|
30
|
-
|
|
30
|
+
LocalSessionStorage: () => LocalSessionStorage,
|
|
31
31
|
SecureSessionStorage: () => SecureSessionStorage,
|
|
32
32
|
Storage: () => Storage,
|
|
33
33
|
StorageBucket: () => StorageBucket,
|
|
@@ -35,8 +35,8 @@ __export(index_exports, {
|
|
|
35
35
|
createClient: () => createClient,
|
|
36
36
|
createSessionStorage: () => createSessionStorage,
|
|
37
37
|
default: () => index_default,
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
discoverBackendConfig: () => discoverBackendConfig,
|
|
39
|
+
getDefaultBackendConfig: () => getDefaultBackendConfig
|
|
40
40
|
});
|
|
41
41
|
module.exports = __toCommonJS(index_exports);
|
|
42
42
|
|
|
@@ -287,9 +287,9 @@ var SecureSessionStorage = class {
|
|
|
287
287
|
return document.cookie.includes(`${AUTH_FLAG_COOKIE}=true`);
|
|
288
288
|
}
|
|
289
289
|
};
|
|
290
|
-
var
|
|
290
|
+
var LocalSessionStorage = class {
|
|
291
291
|
constructor(storage) {
|
|
292
|
-
this.strategyId = "
|
|
292
|
+
this.strategyId = "local";
|
|
293
293
|
if (storage) {
|
|
294
294
|
this.storage = storage;
|
|
295
295
|
} else if (typeof window !== "undefined" && window.localStorage) {
|
|
@@ -355,10 +355,10 @@ var PersistentSessionStorage = class {
|
|
|
355
355
|
var TokenManager = class {
|
|
356
356
|
/**
|
|
357
357
|
* Create a new TokenManager
|
|
358
|
-
* @param storage - Optional custom storage adapter (used for initial
|
|
358
|
+
* @param storage - Optional custom storage adapter (used for initial LocalSessionStorage)
|
|
359
359
|
*/
|
|
360
360
|
constructor(storage) {
|
|
361
|
-
this.strategy = new
|
|
361
|
+
this.strategy = new LocalSessionStorage(storage);
|
|
362
362
|
}
|
|
363
363
|
/**
|
|
364
364
|
* Set the storage strategy
|
|
@@ -430,12 +430,12 @@ var TokenManager = class {
|
|
|
430
430
|
}
|
|
431
431
|
};
|
|
432
432
|
|
|
433
|
-
// src/lib/
|
|
434
|
-
var
|
|
433
|
+
// src/lib/backend-config.ts
|
|
434
|
+
var DEFAULT_CONFIG = {
|
|
435
435
|
secureSessionStorage: false,
|
|
436
436
|
refreshTokens: false
|
|
437
437
|
};
|
|
438
|
-
async function
|
|
438
|
+
async function discoverBackendConfig(baseUrl, fetchImpl = globalThis.fetch) {
|
|
439
439
|
try {
|
|
440
440
|
const response = await fetchImpl(`${baseUrl}/api/health`, {
|
|
441
441
|
method: "GET",
|
|
@@ -444,25 +444,25 @@ async function discoverCapabilities(baseUrl, fetchImpl = globalThis.fetch) {
|
|
|
444
444
|
}
|
|
445
445
|
});
|
|
446
446
|
if (!response.ok) {
|
|
447
|
-
return
|
|
447
|
+
return DEFAULT_CONFIG;
|
|
448
448
|
}
|
|
449
449
|
const health = await response.json();
|
|
450
|
-
if (health.
|
|
451
|
-
return health.
|
|
450
|
+
if (health.config) {
|
|
451
|
+
return health.config;
|
|
452
452
|
}
|
|
453
|
-
return
|
|
453
|
+
return DEFAULT_CONFIG;
|
|
454
454
|
} catch {
|
|
455
|
-
return
|
|
455
|
+
return DEFAULT_CONFIG;
|
|
456
456
|
}
|
|
457
457
|
}
|
|
458
|
-
function createSessionStorage(
|
|
459
|
-
if (
|
|
458
|
+
function createSessionStorage(config, storage) {
|
|
459
|
+
if (config.secureSessionStorage && config.refreshTokens) {
|
|
460
460
|
return new SecureSessionStorage();
|
|
461
461
|
}
|
|
462
|
-
return new
|
|
462
|
+
return new LocalSessionStorage(storage);
|
|
463
463
|
}
|
|
464
|
-
function
|
|
465
|
-
return { ...
|
|
464
|
+
function getDefaultBackendConfig() {
|
|
465
|
+
return { ...DEFAULT_CONFIG };
|
|
466
466
|
}
|
|
467
467
|
|
|
468
468
|
// src/modules/database-postgrest.ts
|
|
@@ -571,11 +571,72 @@ function isHostedAuthEnvironment() {
|
|
|
571
571
|
return false;
|
|
572
572
|
}
|
|
573
573
|
var Auth = class {
|
|
574
|
-
constructor(http, tokenManager) {
|
|
574
|
+
constructor(http, tokenManager, initializePromise) {
|
|
575
575
|
this.http = http;
|
|
576
576
|
this.tokenManager = tokenManager;
|
|
577
|
-
this.
|
|
577
|
+
this.authStateListeners = /* @__PURE__ */ new Set();
|
|
578
578
|
this.database = new Database(http, tokenManager);
|
|
579
|
+
this.initializePromise = initializePromise ?? Promise.resolve();
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Subscribe to auth state changes
|
|
583
|
+
*
|
|
584
|
+
* New subscribers will receive an INITIAL_SESSION event after initialization completes.
|
|
585
|
+
* This ensures no race condition where subscribers miss the initial state.
|
|
586
|
+
*
|
|
587
|
+
* @param callback - Function called when auth state changes
|
|
588
|
+
* @returns Unsubscribe function
|
|
589
|
+
*
|
|
590
|
+
* @example
|
|
591
|
+
* ```typescript
|
|
592
|
+
* const { data: { subscription } } = client.auth.onAuthStateChange((event, session) => {
|
|
593
|
+
* if (event === 'SIGNED_IN') {
|
|
594
|
+
* console.log('User signed in:', session?.user.email);
|
|
595
|
+
* } else if (event === 'SIGNED_OUT') {
|
|
596
|
+
* console.log('User signed out');
|
|
597
|
+
* }
|
|
598
|
+
* });
|
|
599
|
+
*
|
|
600
|
+
* // Later: unsubscribe
|
|
601
|
+
* subscription.unsubscribe();
|
|
602
|
+
* ```
|
|
603
|
+
*/
|
|
604
|
+
onAuthStateChange(callback) {
|
|
605
|
+
this.authStateListeners.add(callback);
|
|
606
|
+
;
|
|
607
|
+
(async () => {
|
|
608
|
+
await this.initializePromise;
|
|
609
|
+
if (this.authStateListeners.has(callback)) {
|
|
610
|
+
const session = this.tokenManager.getSession();
|
|
611
|
+
try {
|
|
612
|
+
callback("INITIAL_SESSION", session);
|
|
613
|
+
} catch (error) {
|
|
614
|
+
console.error("[Auth] Error in auth state change listener:", error);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
})();
|
|
618
|
+
return {
|
|
619
|
+
data: {
|
|
620
|
+
subscription: {
|
|
621
|
+
unsubscribe: () => {
|
|
622
|
+
this.authStateListeners.delete(callback);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Emit auth state change to all listeners
|
|
630
|
+
* @internal
|
|
631
|
+
*/
|
|
632
|
+
_emitAuthStateChange(event, session) {
|
|
633
|
+
this.authStateListeners.forEach((callback) => {
|
|
634
|
+
try {
|
|
635
|
+
callback(event, session);
|
|
636
|
+
} catch (error) {
|
|
637
|
+
console.error("[Auth] Error in auth state change listener:", error);
|
|
638
|
+
}
|
|
639
|
+
});
|
|
579
640
|
}
|
|
580
641
|
/**
|
|
581
642
|
* Check if an error represents an authentication failure
|
|
@@ -600,30 +661,12 @@ var Auth = class {
|
|
|
600
661
|
return false;
|
|
601
662
|
}
|
|
602
663
|
/**
|
|
603
|
-
*
|
|
604
|
-
*
|
|
664
|
+
* Detect and handle OAuth callback parameters in the URL.
|
|
665
|
+
* Called by client after initialization.
|
|
605
666
|
*/
|
|
606
|
-
|
|
607
|
-
this.initPromise = promise;
|
|
608
|
-
this.detectAuthCallbackAsync();
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Wait for initialization to complete (if set)
|
|
612
|
-
*/
|
|
613
|
-
async waitForInit() {
|
|
614
|
-
if (this.initPromise) {
|
|
615
|
-
await this.initPromise;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
/**
|
|
619
|
-
* Automatically detect and handle OAuth callback parameters in the URL
|
|
620
|
-
* This runs after initialization to seamlessly complete the OAuth flow
|
|
621
|
-
* Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)
|
|
622
|
-
*/
|
|
623
|
-
async detectAuthCallbackAsync() {
|
|
667
|
+
detectAuthCallback() {
|
|
624
668
|
if (typeof window === "undefined") return;
|
|
625
669
|
try {
|
|
626
|
-
await this.waitForInit();
|
|
627
670
|
const params = new URLSearchParams(window.location.search);
|
|
628
671
|
const accessToken = params.get("access_token");
|
|
629
672
|
const userId = params.get("user_id");
|
|
@@ -654,6 +697,7 @@ var Auth = class {
|
|
|
654
697
|
url.searchParams.delete("error");
|
|
655
698
|
}
|
|
656
699
|
window.history.replaceState({}, document.title, url.toString());
|
|
700
|
+
this._emitAuthStateChange("SIGNED_IN", session);
|
|
657
701
|
}
|
|
658
702
|
} catch {
|
|
659
703
|
}
|
|
@@ -663,7 +707,6 @@ var Auth = class {
|
|
|
663
707
|
*/
|
|
664
708
|
async signUp(request) {
|
|
665
709
|
try {
|
|
666
|
-
await this.waitForInit();
|
|
667
710
|
const response = await this.http.post("/api/auth/users", request);
|
|
668
711
|
if (response.accessToken && response.user) {
|
|
669
712
|
const session = {
|
|
@@ -674,6 +717,7 @@ var Auth = class {
|
|
|
674
717
|
this.tokenManager.saveSession(session);
|
|
675
718
|
}
|
|
676
719
|
this.http.setAuthToken(response.accessToken);
|
|
720
|
+
this._emitAuthStateChange("SIGNED_IN", session);
|
|
677
721
|
}
|
|
678
722
|
return {
|
|
679
723
|
data: response,
|
|
@@ -698,7 +742,6 @@ var Auth = class {
|
|
|
698
742
|
*/
|
|
699
743
|
async signInWithPassword(request) {
|
|
700
744
|
try {
|
|
701
|
-
await this.waitForInit();
|
|
702
745
|
const response = await this.http.post("/api/auth/sessions", request);
|
|
703
746
|
const session = {
|
|
704
747
|
accessToken: response.accessToken || "",
|
|
@@ -715,6 +758,7 @@ var Auth = class {
|
|
|
715
758
|
this.tokenManager.saveSession(session);
|
|
716
759
|
}
|
|
717
760
|
this.http.setAuthToken(response.accessToken || "");
|
|
761
|
+
this._emitAuthStateChange("SIGNED_IN", session);
|
|
718
762
|
return {
|
|
719
763
|
data: response,
|
|
720
764
|
error: null
|
|
@@ -781,6 +825,7 @@ var Auth = class {
|
|
|
781
825
|
}
|
|
782
826
|
this.tokenManager.clearSession();
|
|
783
827
|
this.http.setAuthToken(null);
|
|
828
|
+
this._emitAuthStateChange("SIGNED_OUT", null);
|
|
784
829
|
return { error: null };
|
|
785
830
|
} catch (error) {
|
|
786
831
|
return {
|
|
@@ -809,6 +854,8 @@ var Auth = class {
|
|
|
809
854
|
if (response.user) {
|
|
810
855
|
this.tokenManager.setUser(response.user);
|
|
811
856
|
}
|
|
857
|
+
const session = this.tokenManager.getSession();
|
|
858
|
+
this._emitAuthStateChange("TOKEN_REFRESHED", session);
|
|
812
859
|
return response.accessToken;
|
|
813
860
|
}
|
|
814
861
|
throw new InsForgeError(
|
|
@@ -1143,7 +1190,6 @@ var Auth = class {
|
|
|
1143
1190
|
*/
|
|
1144
1191
|
async verifyEmail(request) {
|
|
1145
1192
|
try {
|
|
1146
|
-
await this.waitForInit();
|
|
1147
1193
|
const response = await this.http.post(
|
|
1148
1194
|
"/api/auth/email/verify",
|
|
1149
1195
|
request
|
|
@@ -1155,6 +1201,7 @@ var Auth = class {
|
|
|
1155
1201
|
};
|
|
1156
1202
|
this.tokenManager.saveSession(session);
|
|
1157
1203
|
this.http.setAuthToken(response.accessToken);
|
|
1204
|
+
this._emitAuthStateChange("SIGNED_IN", session);
|
|
1158
1205
|
}
|
|
1159
1206
|
return {
|
|
1160
1207
|
data: response,
|
|
@@ -1700,11 +1747,13 @@ var Functions = class {
|
|
|
1700
1747
|
// src/client.ts
|
|
1701
1748
|
var InsForgeClient = class {
|
|
1702
1749
|
constructor(config = {}) {
|
|
1703
|
-
this.
|
|
1704
|
-
this.
|
|
1705
|
-
|
|
1750
|
+
this.backendConfig = null;
|
|
1751
|
+
this.initializePromise = new Promise((resolve) => {
|
|
1752
|
+
this.initializeResolve = resolve;
|
|
1753
|
+
});
|
|
1706
1754
|
this.http = new HttpClient(config);
|
|
1707
1755
|
this.tokenManager = new TokenManager(config.storage);
|
|
1756
|
+
this.auth = new Auth(this.http, this.tokenManager, this.initializePromise);
|
|
1708
1757
|
if (config.edgeFunctionToken) {
|
|
1709
1758
|
this.http.setAuthToken(config.edgeFunctionToken);
|
|
1710
1759
|
this.tokenManager.saveSession({
|
|
@@ -1713,7 +1762,6 @@ var InsForgeClient = class {
|
|
|
1713
1762
|
// Will be populated by getCurrentUser()
|
|
1714
1763
|
});
|
|
1715
1764
|
}
|
|
1716
|
-
this.auth = new Auth(this.http, this.tokenManager);
|
|
1717
1765
|
this.http.setRefreshCallback(async () => {
|
|
1718
1766
|
try {
|
|
1719
1767
|
return await this.auth.refreshToken();
|
|
@@ -1729,67 +1777,58 @@ var InsForgeClient = class {
|
|
|
1729
1777
|
this.storage = new Storage(this.http);
|
|
1730
1778
|
this.ai = new AI(this.http);
|
|
1731
1779
|
this.functions = new Functions(this.http);
|
|
1732
|
-
this.
|
|
1733
|
-
this.auth.setInitPromise(this.initializationPromise);
|
|
1780
|
+
this._initializeAsync();
|
|
1734
1781
|
}
|
|
1735
1782
|
/**
|
|
1736
|
-
*
|
|
1737
|
-
*
|
|
1738
|
-
*
|
|
1739
|
-
* @example
|
|
1740
|
-
* ```typescript
|
|
1741
|
-
* const client = new InsForgeClient({ baseUrl: 'https://api.example.com' });
|
|
1742
|
-
* await client.initialize(); // Wait for capability discovery
|
|
1743
|
-
* ```
|
|
1783
|
+
* Internal async initialization - discovers backend config and recovers session.
|
|
1784
|
+
* Emits INITIAL_SESSION event when complete.
|
|
1785
|
+
* @internal
|
|
1744
1786
|
*/
|
|
1745
|
-
async
|
|
1746
|
-
if (this.initializationPromise) {
|
|
1747
|
-
await this.initializationPromise;
|
|
1748
|
-
}
|
|
1749
|
-
}
|
|
1750
|
-
/**
|
|
1751
|
-
* Internal async initialization - discovers capabilities and configures storage strategy
|
|
1752
|
-
*/
|
|
1753
|
-
async initializeAsync() {
|
|
1754
|
-
if (this.initialized) return;
|
|
1787
|
+
async _initializeAsync() {
|
|
1755
1788
|
try {
|
|
1756
|
-
this.
|
|
1789
|
+
this.backendConfig = await discoverBackendConfig(
|
|
1757
1790
|
this.http.baseUrl,
|
|
1758
1791
|
this.http.fetch
|
|
1759
1792
|
);
|
|
1760
|
-
const strategy = createSessionStorage(this.
|
|
1793
|
+
const strategy = createSessionStorage(this.backendConfig);
|
|
1761
1794
|
this.tokenManager.setStrategy(strategy);
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1795
|
+
this.auth.detectAuthCallback();
|
|
1796
|
+
let currentSession = this.tokenManager.getSession();
|
|
1797
|
+
if (!currentSession?.accessToken && this.backendConfig.refreshTokens) {
|
|
1798
|
+
if (this.tokenManager.shouldAttemptRefresh()) {
|
|
1799
|
+
try {
|
|
1800
|
+
await this.auth.refreshToken();
|
|
1801
|
+
currentSession = this.tokenManager.getSession();
|
|
1802
|
+
} catch {
|
|
1803
|
+
this.tokenManager.clearSession();
|
|
1804
|
+
this.http.setAuthToken(null);
|
|
1805
|
+
}
|
|
1769
1806
|
}
|
|
1770
1807
|
}
|
|
1771
|
-
this.
|
|
1808
|
+
this.initializeResolve();
|
|
1772
1809
|
} catch {
|
|
1773
|
-
this.
|
|
1810
|
+
this.auth.detectAuthCallback();
|
|
1811
|
+
this.initializeResolve();
|
|
1774
1812
|
}
|
|
1775
1813
|
}
|
|
1814
|
+
/**
|
|
1815
|
+
* Wait for client initialization to complete
|
|
1816
|
+
* @returns Promise that resolves when initialization is done
|
|
1817
|
+
*/
|
|
1818
|
+
async waitForInitialization() {
|
|
1819
|
+
return this.initializePromise;
|
|
1820
|
+
}
|
|
1776
1821
|
/**
|
|
1777
1822
|
* Get the underlying HTTP client for custom requests
|
|
1778
|
-
*
|
|
1779
|
-
* @example
|
|
1780
|
-
* ```typescript
|
|
1781
|
-
* const httpClient = client.getHttpClient();
|
|
1782
|
-
* const customData = await httpClient.get('/api/custom-endpoint');
|
|
1783
|
-
* ```
|
|
1784
1823
|
*/
|
|
1785
1824
|
getHttpClient() {
|
|
1786
1825
|
return this.http;
|
|
1787
1826
|
}
|
|
1788
1827
|
/**
|
|
1789
|
-
* Get the discovered backend
|
|
1828
|
+
* Get the discovered backend configuration
|
|
1790
1829
|
*/
|
|
1791
|
-
|
|
1792
|
-
return this.
|
|
1830
|
+
getBackendConfig() {
|
|
1831
|
+
return this.backendConfig;
|
|
1793
1832
|
}
|
|
1794
1833
|
/**
|
|
1795
1834
|
* Get the current storage strategy identifier
|
|
@@ -1797,18 +1836,12 @@ var InsForgeClient = class {
|
|
|
1797
1836
|
getStorageStrategy() {
|
|
1798
1837
|
return this.tokenManager.getStrategyId();
|
|
1799
1838
|
}
|
|
1800
|
-
/**
|
|
1801
|
-
* Check if the client has been fully initialized
|
|
1802
|
-
*/
|
|
1803
|
-
isInitialized() {
|
|
1804
|
-
return this.initialized;
|
|
1805
|
-
}
|
|
1806
1839
|
};
|
|
1807
|
-
|
|
1808
|
-
// src/index.ts
|
|
1809
|
-
function createClient(config) {
|
|
1840
|
+
function createClient(config = {}) {
|
|
1810
1841
|
return new InsForgeClient(config);
|
|
1811
1842
|
}
|
|
1843
|
+
|
|
1844
|
+
// src/index.ts
|
|
1812
1845
|
var index_default = InsForgeClient;
|
|
1813
1846
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1814
1847
|
0 && (module.exports = {
|
|
@@ -1819,14 +1852,14 @@ var index_default = InsForgeClient;
|
|
|
1819
1852
|
HttpClient,
|
|
1820
1853
|
InsForgeClient,
|
|
1821
1854
|
InsForgeError,
|
|
1822
|
-
|
|
1855
|
+
LocalSessionStorage,
|
|
1823
1856
|
SecureSessionStorage,
|
|
1824
1857
|
Storage,
|
|
1825
1858
|
StorageBucket,
|
|
1826
1859
|
TokenManager,
|
|
1827
1860
|
createClient,
|
|
1828
1861
|
createSessionStorage,
|
|
1829
|
-
|
|
1830
|
-
|
|
1862
|
+
discoverBackendConfig,
|
|
1863
|
+
getDefaultBackendConfig
|
|
1831
1864
|
});
|
|
1832
1865
|
//# sourceMappingURL=index.js.map
|