@insforge/sdk 1.1.6 → 1.2.0-dev.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/dist/index.mjs CHANGED
@@ -136,8 +136,6 @@ var HttpClient = class {
136
136
  };
137
137
 
138
138
  // src/lib/token-manager.ts
139
- var TOKEN_KEY = "insforge-auth-token";
140
- var USER_KEY = "insforge-auth-user";
141
139
  var CSRF_TOKEN_COOKIE = "insforge_csrf_token";
142
140
  function getCsrfToken() {
143
141
  if (typeof document === "undefined") return null;
@@ -157,81 +155,20 @@ function clearCsrfToken() {
157
155
  document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax${secure}`;
158
156
  }
159
157
  var TokenManager = class {
160
- constructor(storage) {
158
+ constructor() {
161
159
  // In-memory storage
162
160
  this.accessToken = null;
163
161
  this.user = null;
164
- // Mode: 'memory' (new backend) or 'storage' (legacy backend, default)
165
- this._mode = "storage";
166
162
  // Callback for token changes (used by realtime to reconnect with new token)
167
163
  this.onTokenChange = null;
168
- if (storage) {
169
- this.storage = storage;
170
- } else if (typeof window !== "undefined" && window.localStorage) {
171
- this.storage = window.localStorage;
172
- } else {
173
- const store = /* @__PURE__ */ new Map();
174
- this.storage = {
175
- getItem: (key) => store.get(key) || null,
176
- setItem: (key, value) => {
177
- store.set(key, value);
178
- },
179
- removeItem: (key) => {
180
- store.delete(key);
181
- }
182
- };
183
- }
184
164
  }
185
165
  /**
186
- * Get current mode
187
- */
188
- get mode() {
189
- return this._mode;
190
- }
191
- /**
192
- * Set mode to memory (new backend with cookies + memory)
193
- */
194
- setMemoryMode() {
195
- if (this._mode === "storage") {
196
- this.storage.removeItem(TOKEN_KEY);
197
- this.storage.removeItem(USER_KEY);
198
- }
199
- this._mode = "memory";
200
- }
201
- /**
202
- * Set mode to storage (legacy backend with localStorage)
203
- * Also loads existing session from localStorage
204
- */
205
- setStorageMode() {
206
- this._mode = "storage";
207
- this.loadFromStorage();
208
- }
209
- /**
210
- * Load session from localStorage
211
- */
212
- loadFromStorage() {
213
- const token = this.storage.getItem(TOKEN_KEY);
214
- const userStr = this.storage.getItem(USER_KEY);
215
- if (token && userStr) {
216
- try {
217
- this.accessToken = token;
218
- this.user = JSON.parse(userStr);
219
- } catch {
220
- this.clearSession();
221
- }
222
- }
223
- }
224
- /**
225
- * Save session (memory always, localStorage only in storage mode)
166
+ * Save session in memory
226
167
  */
227
168
  saveSession(session) {
228
169
  const tokenChanged = session.accessToken !== this.accessToken;
229
170
  this.accessToken = session.accessToken;
230
171
  this.user = session.user;
231
- if (this._mode === "storage") {
232
- this.storage.setItem(TOKEN_KEY, session.accessToken);
233
- this.storage.setItem(USER_KEY, JSON.stringify(session.user));
234
- }
235
172
  if (tokenChanged && this.onTokenChange) {
236
173
  this.onTokenChange();
237
174
  }
@@ -240,7 +177,6 @@ var TokenManager = class {
240
177
  * Get current session
241
178
  */
242
179
  getSession() {
243
- this.loadFromStorage();
244
180
  if (!this.accessToken || !this.user) return null;
245
181
  return {
246
182
  accessToken: this.accessToken,
@@ -251,7 +187,6 @@ var TokenManager = class {
251
187
  * Get access token
252
188
  */
253
189
  getAccessToken() {
254
- this.loadFromStorage();
255
190
  return this.accessToken;
256
191
  }
257
192
  /**
@@ -260,9 +195,6 @@ var TokenManager = class {
260
195
  setAccessToken(token) {
261
196
  const tokenChanged = token !== this.accessToken;
262
197
  this.accessToken = token;
263
- if (this._mode === "storage") {
264
- this.storage.setItem(TOKEN_KEY, token);
265
- }
266
198
  if (tokenChanged && this.onTokenChange) {
267
199
  this.onTokenChange();
268
200
  }
@@ -278,30 +210,18 @@ var TokenManager = class {
278
210
  */
279
211
  setUser(user) {
280
212
  this.user = user;
281
- if (this._mode === "storage") {
282
- this.storage.setItem(USER_KEY, JSON.stringify(user));
283
- }
284
213
  }
285
214
  /**
286
- * Clear session (both memory and localStorage)
215
+ * Clear in-memory session
287
216
  */
288
217
  clearSession() {
289
218
  const hadToken = this.accessToken !== null;
290
219
  this.accessToken = null;
291
220
  this.user = null;
292
- this.storage.removeItem(TOKEN_KEY);
293
- this.storage.removeItem(USER_KEY);
294
221
  if (hadToken && this.onTokenChange) {
295
222
  this.onTokenChange();
296
223
  }
297
224
  }
298
- /**
299
- * Check if there's a session in localStorage (for legacy detection)
300
- */
301
- hasStoredSession() {
302
- const token = this.storage.getItem(TOKEN_KEY);
303
- return !!token;
304
- }
305
225
  };
306
226
 
307
227
  // src/modules/auth/helpers.ts
@@ -336,19 +256,6 @@ function retrievePkceVerifier() {
336
256
  }
337
257
  return verifier;
338
258
  }
339
- function isHostedAuthEnvironment() {
340
- if (typeof window === "undefined") {
341
- return false;
342
- }
343
- const { hostname, port, protocol } = window.location;
344
- if (hostname === "localhost" && port === "7130") {
345
- return true;
346
- }
347
- if (protocol === "https:" && hostname.endsWith(".insforge.app")) {
348
- return true;
349
- }
350
- return false;
351
- }
352
259
  function wrapError(error, fallbackMessage) {
353
260
  if (error instanceof InsForgeError) {
354
261
  return { data: null, error };
@@ -373,14 +280,18 @@ function cleanUrlParams(...params) {
373
280
 
374
281
  // src/modules/auth/auth.ts
375
282
  var Auth = class {
376
- constructor(http, tokenManager) {
283
+ constructor(http, tokenManager, options = {}) {
377
284
  this.http = http;
378
285
  this.tokenManager = tokenManager;
286
+ this.options = options;
379
287
  this.authCallbackHandled = this.detectAuthCallback();
380
288
  }
289
+ isServerMode() {
290
+ return !!this.options.isServerMode;
291
+ }
381
292
  /**
382
293
  * Save session from API response
383
- * Handles token storage, CSRF token, and HTTP client auth header
294
+ * Handles token storage, CSRF token, and HTTP auth header
384
295
  */
385
296
  saveSessionFromResponse(response) {
386
297
  if (!response.accessToken || !response.user) {
@@ -390,11 +301,12 @@ var Auth = class {
390
301
  accessToken: response.accessToken,
391
302
  user: response.user
392
303
  };
393
- if (response.csrfToken) {
394
- this.tokenManager.setMemoryMode();
304
+ if (!this.isServerMode() && response.csrfToken) {
395
305
  setCsrfToken(response.csrfToken);
396
306
  }
397
- this.tokenManager.saveSession(session);
307
+ if (!this.isServerMode()) {
308
+ this.tokenManager.saveSession(session);
309
+ }
398
310
  this.http.setAuthToken(response.accessToken);
399
311
  return true;
400
312
  }
@@ -406,7 +318,7 @@ var Auth = class {
406
318
  * Supports PKCE flow (insforge_code) and legacy flow (access_token in URL)
407
319
  */
408
320
  async detectAuthCallback() {
409
- if (typeof window === "undefined") return;
321
+ if (this.isServerMode() || typeof window === "undefined") return;
410
322
  try {
411
323
  const params = new URLSearchParams(window.location.search);
412
324
  const error = params.get("error");
@@ -431,7 +343,6 @@ var Auth = class {
431
343
  const csrfToken = params.get("csrf_token");
432
344
  const name = params.get("name");
433
345
  if (csrfToken) {
434
- this.tokenManager.setMemoryMode();
435
346
  setCsrfToken(csrfToken);
436
347
  }
437
348
  const session = {
@@ -460,7 +371,7 @@ var Auth = class {
460
371
  async signUp(request) {
461
372
  try {
462
373
  const response = await this.http.post(
463
- "/api/auth/users",
374
+ this.isServerMode() ? "/api/auth/users?client_type=mobile" : "/api/auth/users",
464
375
  request,
465
376
  { credentials: "include" }
466
377
  );
@@ -475,7 +386,7 @@ var Auth = class {
475
386
  async signInWithPassword(request) {
476
387
  try {
477
388
  const response = await this.http.post(
478
- "/api/auth/sessions",
389
+ this.isServerMode() ? "/api/auth/sessions?client_type=mobile" : "/api/auth/sessions",
479
390
  request,
480
391
  { credentials: "include" }
481
392
  );
@@ -488,12 +399,18 @@ var Auth = class {
488
399
  async signOut() {
489
400
  try {
490
401
  try {
491
- await this.http.post("/api/auth/logout", void 0, { credentials: "include" });
402
+ await this.http.post(
403
+ this.isServerMode() ? "/api/auth/logout?client_type=mobile" : "/api/auth/logout",
404
+ void 0,
405
+ { credentials: "include" }
406
+ );
492
407
  } catch {
493
408
  }
494
409
  this.tokenManager.clearSession();
495
410
  this.http.setAuthToken(null);
496
- clearCsrfToken();
411
+ if (!this.isServerMode()) {
412
+ clearCsrfToken();
413
+ }
497
414
  return { error: null };
498
415
  } catch {
499
416
  return { error: new InsForgeError("Failed to sign out", 500, "SIGNOUT_ERROR") };
@@ -513,11 +430,8 @@ var Auth = class {
513
430
  storePkceVerifier(codeVerifier);
514
431
  const params = { code_challenge: codeChallenge };
515
432
  if (redirectTo) params.redirect_uri = redirectTo;
516
- const response = await this.http.get(
517
- `/api/auth/oauth/${provider}`,
518
- { params }
519
- );
520
- if (typeof window !== "undefined" && !skipBrowserRedirect) {
433
+ const response = await this.http.get(`/api/auth/oauth/${provider}`, { params });
434
+ if (!this.isServerMode() && typeof window !== "undefined" && !skipBrowserRedirect) {
521
435
  window.location.href = response.authUrl;
522
436
  return { data: {}, error: null };
523
437
  }
@@ -557,11 +471,16 @@ var Auth = class {
557
471
  };
558
472
  }
559
473
  const request = { code, code_verifier: verifier };
560
- const response = await this.http.post("/api/auth/oauth/exchange", request, { credentials: "include" });
474
+ const response = await this.http.post(
475
+ this.isServerMode() ? "/api/auth/oauth/exchange?client_type=mobile" : "/api/auth/oauth/exchange",
476
+ request,
477
+ { credentials: "include" }
478
+ );
561
479
  this.saveSessionFromResponse(response);
562
480
  return {
563
481
  data: {
564
482
  accessToken: response.accessToken,
483
+ refreshToken: response.refreshToken,
565
484
  user: response.user,
566
485
  redirectTo: response.redirectTo
567
486
  },
@@ -581,7 +500,11 @@ var Auth = class {
581
500
  async signInWithIdToken(credentials) {
582
501
  try {
583
502
  const { provider, token } = credentials;
584
- const response = await this.http.post("/api/auth/id-token?client_type=mobile", { provider, token }, { credentials: "include" });
503
+ const response = await this.http.post(
504
+ "/api/auth/id-token?client_type=mobile",
505
+ { provider, token },
506
+ { credentials: "include" }
507
+ );
585
508
  this.saveSessionFromResponse(response);
586
509
  return {
587
510
  data: {
@@ -599,102 +522,69 @@ var Auth = class {
599
522
  // Session Management
600
523
  // ============================================================================
601
524
  /**
602
- * Get current session, automatically waits for pending OAuth callback
603
- * @deprecated Use `getCurrentUser` instead
525
+ * Refresh the current auth session.
526
+ *
527
+ * Browser mode:
528
+ * - Uses httpOnly refresh cookie and optional CSRF header.
529
+ *
530
+ * Server mode (`isServerMode: true`):
531
+ * - Uses mobile auth flow and requires `refreshToken` in request body.
604
532
  */
605
- async getCurrentSession() {
606
- await this.authCallbackHandled;
533
+ async refreshSession(options) {
607
534
  try {
608
- const session = this.tokenManager.getSession();
609
- if (session) {
610
- this.http.setAuthToken(session.accessToken);
611
- return { data: { session }, error: null };
535
+ if (this.isServerMode() && !options?.refreshToken) {
536
+ return {
537
+ data: null,
538
+ error: new InsForgeError(
539
+ "refreshToken is required when refreshing session in server mode",
540
+ 400,
541
+ "REFRESH_TOKEN_REQUIRED"
542
+ )
543
+ };
612
544
  }
613
- if (typeof window !== "undefined") {
614
- try {
615
- const csrfToken = getCsrfToken();
616
- const response = await this.http.post("/api/auth/refresh", void 0, {
617
- headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {},
618
- credentials: "include"
619
- });
620
- if (response.accessToken) {
621
- this.tokenManager.setMemoryMode();
622
- this.tokenManager.setAccessToken(response.accessToken);
623
- this.http.setAuthToken(response.accessToken);
624
- if (response.user) this.tokenManager.setUser(response.user);
625
- if (response.csrfToken) setCsrfToken(response.csrfToken);
626
- return { data: { session: this.tokenManager.getSession() }, error: null };
627
- }
628
- } catch (error) {
629
- if (error instanceof InsForgeError) {
630
- if (error.statusCode === 404) {
631
- this.tokenManager.setStorageMode();
632
- const session2 = this.tokenManager.getSession();
633
- if (session2?.accessToken) {
634
- +this.http.setAuthToken(session2.accessToken);
635
- }
636
- return { data: { session: session2 }, error: null };
637
- }
638
- return { data: { session: null }, error };
639
- }
545
+ const csrfToken = !this.isServerMode() ? getCsrfToken() : null;
546
+ const response = await this.http.post(
547
+ this.isServerMode() ? "/api/auth/refresh?client_type=mobile" : "/api/auth/refresh",
548
+ this.isServerMode() ? { refreshToken: options?.refreshToken } : void 0,
549
+ {
550
+ headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {},
551
+ credentials: "include"
640
552
  }
553
+ );
554
+ if (response.accessToken) {
555
+ this.saveSessionFromResponse(response);
641
556
  }
642
- return { data: { session: null }, error: null };
557
+ return { data: response, error: null };
643
558
  } catch (error) {
644
- if (error instanceof InsForgeError) {
645
- return { data: { session: null }, error };
646
- }
647
- return {
648
- data: { session: null },
649
- error: new InsForgeError(
650
- "An unexpected error occurred while getting session",
651
- 500,
652
- "UNEXPECTED_ERROR"
653
- )
654
- };
559
+ return wrapError(error, "An unexpected error occurred during session refresh");
655
560
  }
656
561
  }
657
562
  /**
658
- * Get current user, automatically waits for pending OAuth callback
659
- */
563
+ * Get current user, automatically waits for pending OAuth callback
564
+ */
660
565
  async getCurrentUser() {
661
566
  await this.authCallbackHandled;
662
- if (isHostedAuthEnvironment()) {
663
- return { data: { user: null }, error: null };
664
- }
665
567
  try {
568
+ if (this.isServerMode()) {
569
+ const accessToken = this.tokenManager.getAccessToken();
570
+ if (!accessToken) return { data: { user: null }, error: null };
571
+ this.http.setAuthToken(accessToken);
572
+ const response = await this.http.get("/api/auth/sessions/current");
573
+ const user = response.user ?? null;
574
+ return { data: { user }, error: null };
575
+ }
666
576
  const session = this.tokenManager.getSession();
667
577
  if (session) {
668
578
  this.http.setAuthToken(session.accessToken);
669
579
  return { data: { user: session.user }, error: null };
670
580
  }
671
581
  if (typeof window !== "undefined") {
672
- try {
673
- const csrfToken = getCsrfToken();
674
- const response = await this.http.post("/api/auth/refresh", void 0, {
675
- headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {},
676
- credentials: "include"
677
- });
678
- if (response.accessToken) {
679
- this.tokenManager.setMemoryMode();
680
- this.tokenManager.setAccessToken(response.accessToken);
681
- this.http.setAuthToken(response.accessToken);
682
- if (response.user) this.tokenManager.setUser(response.user);
683
- if (response.csrfToken) setCsrfToken(response.csrfToken);
684
- return { data: { user: response.user ?? null }, error: null };
685
- }
686
- } catch (error) {
687
- if (error instanceof InsForgeError) {
688
- if (error.statusCode === 404) {
689
- this.tokenManager.setStorageMode();
690
- const session2 = this.tokenManager.getSession();
691
- if (session2?.accessToken) {
692
- +this.http.setAuthToken(session2.accessToken);
693
- }
694
- return { data: { user: session2?.user ?? null }, error: null };
695
- }
696
- return { data: { user: null }, error };
697
- }
582
+ const { data: refreshed, error: refreshError } = await this.refreshSession();
583
+ if (refreshError) {
584
+ return { data: { user: null }, error: refreshError };
585
+ }
586
+ if (refreshed?.accessToken) {
587
+ return { data: { user: refreshed.user ?? null }, error: null };
698
588
  }
699
589
  }
700
590
  return { data: { user: null }, error: null };
@@ -725,12 +615,11 @@ var Auth = class {
725
615
  }
726
616
  async setProfile(profile) {
727
617
  try {
728
- const response = await this.http.patch(
729
- "/api/auth/profiles/current",
730
- { profile }
731
- );
618
+ const response = await this.http.patch("/api/auth/profiles/current", {
619
+ profile
620
+ });
732
621
  const currentUser = this.tokenManager.getUser();
733
- if (currentUser && response.profile !== void 0) {
622
+ if (!this.isServerMode() && currentUser && response.profile !== void 0) {
734
623
  this.tokenManager.setUser({ ...currentUser, profile: response.profile });
735
624
  }
736
625
  return { data: response, error: null };
@@ -759,7 +648,7 @@ var Auth = class {
759
648
  async verifyEmail(request) {
760
649
  try {
761
650
  const response = await this.http.post(
762
- "/api/auth/email/verify",
651
+ this.isServerMode() ? "/api/auth/email/verify?client_type=mobile" : "/api/auth/email/verify",
763
652
  request,
764
653
  { credentials: "include" }
765
654
  );
@@ -1612,8 +1501,7 @@ var Realtime = class {
1612
1501
  return this.connectPromise;
1613
1502
  }
1614
1503
  this.connectPromise = new Promise((resolve, reject) => {
1615
- const session = this.tokenManager.getSession();
1616
- const token = session?.accessToken ?? this.anonKey;
1504
+ const token = this.tokenManager.getAccessToken() ?? this.anonKey;
1617
1505
  this.socket = io(this.baseUrl, {
1618
1506
  transports: ["websocket"],
1619
1507
  auth: token ? { token } : void 0
@@ -1852,19 +1740,14 @@ var Emails = class {
1852
1740
  var InsForgeClient = class {
1853
1741
  constructor(config = {}) {
1854
1742
  this.http = new HttpClient(config);
1855
- this.tokenManager = new TokenManager(config.storage);
1743
+ this.tokenManager = new TokenManager();
1856
1744
  if (config.edgeFunctionToken) {
1857
1745
  this.http.setAuthToken(config.edgeFunctionToken);
1858
- this.tokenManager.saveSession({
1859
- accessToken: config.edgeFunctionToken,
1860
- user: {}
1861
- });
1862
- }
1863
- const existingSession = this.tokenManager.getSession();
1864
- if (existingSession?.accessToken) {
1865
- this.http.setAuthToken(existingSession.accessToken);
1746
+ this.tokenManager.setAccessToken(config.edgeFunctionToken);
1866
1747
  }
1867
- this.auth = new Auth(this.http, this.tokenManager);
1748
+ this.auth = new Auth(this.http, this.tokenManager, {
1749
+ isServerMode: config.isServerMode ?? false
1750
+ });
1868
1751
  this.database = new Database(this.http, this.tokenManager);
1869
1752
  this.storage = new Storage(this.http);
1870
1753
  this.ai = new AI(this.http);