@insforge/sdk 1.0.3-dev.3 → 1.0.3-refresh.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
@@ -290,7 +290,98 @@ var TokenManager = class {
290
290
  }
291
291
  };
292
292
 
293
+ // src/modules/database-postgrest.ts
294
+ import { PostgrestClient } from "@supabase/postgrest-js";
295
+ function createInsForgePostgrestFetch(httpClient, tokenManager) {
296
+ return async (input, init) => {
297
+ const url = typeof input === "string" ? input : input.toString();
298
+ const urlObj = new URL(url);
299
+ const tableName = urlObj.pathname.slice(1);
300
+ const insforgeUrl = `${httpClient.baseUrl}/api/database/records/${tableName}${urlObj.search}`;
301
+ const token = tokenManager.getAccessToken();
302
+ const httpHeaders = httpClient.getHeaders();
303
+ const authToken = token || httpHeaders["Authorization"]?.replace("Bearer ", "");
304
+ const headers = new Headers(init?.headers);
305
+ if (authToken && !headers.has("Authorization")) {
306
+ headers.set("Authorization", `Bearer ${authToken}`);
307
+ }
308
+ const response = await fetch(insforgeUrl, {
309
+ ...init,
310
+ headers
311
+ });
312
+ return response;
313
+ };
314
+ }
315
+ var Database = class {
316
+ constructor(httpClient, tokenManager) {
317
+ this.postgrest = new PostgrestClient("http://dummy", {
318
+ fetch: createInsForgePostgrestFetch(httpClient, tokenManager),
319
+ headers: {}
320
+ });
321
+ }
322
+ /**
323
+ * Create a query builder for a table
324
+ *
325
+ * @example
326
+ * // Basic query
327
+ * const { data, error } = await client.database
328
+ * .from('posts')
329
+ * .select('*')
330
+ * .eq('user_id', userId);
331
+ *
332
+ * // With count (Supabase style!)
333
+ * const { data, error, count } = await client.database
334
+ * .from('posts')
335
+ * .select('*', { count: 'exact' })
336
+ * .range(0, 9);
337
+ *
338
+ * // Just get count, no data
339
+ * const { count } = await client.database
340
+ * .from('posts')
341
+ * .select('*', { count: 'exact', head: true });
342
+ *
343
+ * // Complex queries with OR
344
+ * const { data } = await client.database
345
+ * .from('posts')
346
+ * .select('*, users!inner(*)')
347
+ * .or('status.eq.active,status.eq.pending');
348
+ *
349
+ * // All features work:
350
+ * - Nested selects
351
+ * - Foreign key expansion
352
+ * - OR/AND/NOT conditions
353
+ * - Count with head
354
+ * - Range pagination
355
+ * - Upserts
356
+ */
357
+ from(table) {
358
+ return this.postgrest.from(table);
359
+ }
360
+ };
361
+
293
362
  // src/modules/auth.ts
363
+ function convertDbProfileToCamelCase(dbProfile) {
364
+ const result = {
365
+ id: dbProfile.id
366
+ };
367
+ Object.keys(dbProfile).forEach((key) => {
368
+ result[key] = dbProfile[key];
369
+ if (key.includes("_")) {
370
+ const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
371
+ result[camelKey] = dbProfile[key];
372
+ }
373
+ });
374
+ return result;
375
+ }
376
+ function convertCamelCaseToDbProfile(profile) {
377
+ const dbProfile = {};
378
+ Object.keys(profile).forEach((key) => {
379
+ if (profile[key] === void 0) return;
380
+ const snakeKey = key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
381
+ dbProfile[snakeKey] = profile[key];
382
+ });
383
+ return dbProfile;
384
+ }
294
385
  function isHostedAuthEnvironment() {
295
386
  if (typeof window === "undefined") {
296
387
  return false;
@@ -308,11 +399,12 @@ var Auth = class {
308
399
  constructor(http, tokenManager) {
309
400
  this.http = http;
310
401
  this.tokenManager = tokenManager;
402
+ this.database = new Database(http, tokenManager);
311
403
  this.detectAuthCallback();
312
404
  }
313
405
  /**
314
406
  * Automatically detect and handle OAuth callback parameters in the URL
315
- * This runs after initialization to seamlessly complete the OAuth flow
407
+ * This runs on initialization to seamlessly complete the OAuth flow
316
408
  * Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)
317
409
  */
318
410
  detectAuthCallback() {
@@ -334,8 +426,7 @@ var Auth = class {
334
426
  user: {
335
427
  id: userId,
336
428
  email,
337
- profile: { name: name || "" },
338
- metadata: null,
429
+ name: name || "",
339
430
  // These fields are not provided by backend OAuth callback
340
431
  // They'll be populated when calling getCurrentUser()
341
432
  emailVerified: false,
@@ -530,19 +621,20 @@ var Auth = class {
530
621
  */
531
622
  async getCurrentUser() {
532
623
  try {
533
- const user = this.tokenManager.getUser();
534
- if (user) {
535
- return { data: { user }, error: null };
536
- }
537
- const accessToken = this.tokenManager.getAccessToken();
538
- if (!accessToken) {
624
+ const session = this.tokenManager.getSession();
625
+ if (!session?.accessToken) {
539
626
  return { data: null, error: null };
540
627
  }
541
- this.http.setAuthToken(accessToken);
628
+ this.http.setAuthToken(session.accessToken);
542
629
  const authResponse = await this.http.get("/api/auth/sessions/current");
630
+ const { data: profile, error: profileError } = await this.database.from("users").select("*").eq("id", authResponse.user.id).single();
631
+ if (profileError && profileError.code !== "PGRST116") {
632
+ return { data: null, error: profileError };
633
+ }
543
634
  return {
544
635
  data: {
545
- user: authResponse.user
636
+ user: authResponse.user,
637
+ profile: profile ? convertDbProfileToCamelCase(profile) : null
546
638
  },
547
639
  error: null
548
640
  };
@@ -566,28 +658,17 @@ var Auth = class {
566
658
  }
567
659
  /**
568
660
  * Get any user's profile by ID
569
- * Returns profile information from the users table
661
+ * Returns profile information from the users table (dynamic fields)
570
662
  */
571
663
  async getProfile(userId) {
572
- try {
573
- const response = await this.http.get(`/api/auth/profiles/${userId}`);
574
- return {
575
- data: response,
576
- error: null
577
- };
578
- } catch (error) {
579
- if (error instanceof InsForgeError) {
580
- return { data: null, error };
581
- }
582
- return {
583
- data: null,
584
- error: new InsForgeError(
585
- "An unexpected error occurred while fetching user profile",
586
- 500,
587
- "UNEXPECTED_ERROR"
588
- )
589
- };
664
+ const { data, error } = await this.database.from("users").select("*").eq("id", userId).single();
665
+ if (error && error.code === "PGRST116") {
666
+ return { data: null, error: null };
667
+ }
668
+ if (data) {
669
+ return { data: convertDbProfileToCamelCase(data), error: null };
590
670
  }
671
+ return { data: null, error };
591
672
  }
592
673
  /**
593
674
  * Get the current session (only session data, no API call)
@@ -658,31 +739,42 @@ var Auth = class {
658
739
  /**
659
740
  * Set/Update the current user's profile
660
741
  * Updates profile information in the users table (supports any dynamic fields)
661
- * Requires authentication
662
742
  */
663
743
  async setProfile(profile) {
664
- try {
665
- const response = await this.http.patch(
666
- "/api/auth/profiles/current",
667
- { profile }
668
- );
669
- return {
670
- data: response,
671
- error: null
672
- };
673
- } catch (error) {
674
- if (error instanceof InsForgeError) {
675
- return { data: null, error };
676
- }
744
+ const session = this.tokenManager.getSession();
745
+ if (!session?.accessToken) {
677
746
  return {
678
747
  data: null,
679
748
  error: new InsForgeError(
680
- "An unexpected error occurred while updating user profile",
681
- 500,
682
- "UNEXPECTED_ERROR"
749
+ "No authenticated user found",
750
+ 401,
751
+ "UNAUTHENTICATED"
683
752
  )
684
753
  };
685
754
  }
755
+ if (!session.user?.id) {
756
+ const { data: data2, error: error2 } = await this.getCurrentUser();
757
+ if (error2) {
758
+ return { data: null, error: error2 };
759
+ }
760
+ if (data2?.user) {
761
+ session.user = {
762
+ id: data2.user.id,
763
+ email: data2.user.email,
764
+ name: "",
765
+ emailVerified: false,
766
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
767
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
768
+ };
769
+ this.tokenManager.saveSession(session);
770
+ }
771
+ }
772
+ const dbProfile = convertCamelCaseToDbProfile(profile);
773
+ const { data, error } = await this.database.from("users").update(dbProfile).eq("id", session.user.id).select().single();
774
+ if (data) {
775
+ return { data: convertDbProfileToCamelCase(data), error: null };
776
+ }
777
+ return { data: null, error };
686
778
  }
687
779
  /**
688
780
  * Send email verification (code or link based on config)
@@ -867,75 +959,6 @@ var Auth = class {
867
959
  }
868
960
  };
869
961
 
870
- // src/modules/database-postgrest.ts
871
- import { PostgrestClient } from "@supabase/postgrest-js";
872
- function createInsForgePostgrestFetch(httpClient, tokenManager) {
873
- return async (input, init) => {
874
- const url = typeof input === "string" ? input : input.toString();
875
- const urlObj = new URL(url);
876
- const tableName = urlObj.pathname.slice(1);
877
- const insforgeUrl = `${httpClient.baseUrl}/api/database/records/${tableName}${urlObj.search}`;
878
- const token = tokenManager.getAccessToken();
879
- const httpHeaders = httpClient.getHeaders();
880
- const authToken = token || httpHeaders["Authorization"]?.replace("Bearer ", "");
881
- const headers = new Headers(init?.headers);
882
- if (authToken && !headers.has("Authorization")) {
883
- headers.set("Authorization", `Bearer ${authToken}`);
884
- }
885
- const response = await fetch(insforgeUrl, {
886
- ...init,
887
- headers
888
- });
889
- return response;
890
- };
891
- }
892
- var Database = class {
893
- constructor(httpClient, tokenManager) {
894
- this.postgrest = new PostgrestClient("http://dummy", {
895
- fetch: createInsForgePostgrestFetch(httpClient, tokenManager),
896
- headers: {}
897
- });
898
- }
899
- /**
900
- * Create a query builder for a table
901
- *
902
- * @example
903
- * // Basic query
904
- * const { data, error } = await client.database
905
- * .from('posts')
906
- * .select('*')
907
- * .eq('user_id', userId);
908
- *
909
- * // With count (Supabase style!)
910
- * const { data, error, count } = await client.database
911
- * .from('posts')
912
- * .select('*', { count: 'exact' })
913
- * .range(0, 9);
914
- *
915
- * // Just get count, no data
916
- * const { count } = await client.database
917
- * .from('posts')
918
- * .select('*', { count: 'exact', head: true });
919
- *
920
- * // Complex queries with OR
921
- * const { data } = await client.database
922
- * .from('posts')
923
- * .select('*, users!inner(*)')
924
- * .or('status.eq.active,status.eq.pending');
925
- *
926
- * // All features work:
927
- * - Nested selects
928
- * - Foreign key expansion
929
- * - OR/AND/NOT conditions
930
- * - Count with head
931
- * - Range pagination
932
- * - Upserts
933
- */
934
- from(table) {
935
- return this.postgrest.from(table);
936
- }
937
- };
938
-
939
962
  // src/modules/storage.ts
940
963
  var StorageBucket = class {
941
964
  constructor(bucketName, http) {
@@ -1690,29 +1713,6 @@ var Realtime = class {
1690
1713
  }
1691
1714
  };
1692
1715
 
1693
- // src/modules/email.ts
1694
- var Emails = class {
1695
- constructor(http) {
1696
- this.http = http;
1697
- }
1698
- /**
1699
- * Send a custom HTML email
1700
- * @param options Email options including recipients, subject, and HTML content
1701
- */
1702
- async send(options) {
1703
- try {
1704
- const data = await this.http.post(
1705
- "/api/email/send-raw",
1706
- options
1707
- );
1708
- return { data, error: null };
1709
- } catch (error) {
1710
- const normalizedError = error instanceof Error ? error : new Error(String(error));
1711
- return { data: null, error: normalizedError };
1712
- }
1713
- }
1714
- };
1715
-
1716
1716
  // src/client.ts
1717
1717
  var InsForgeClient = class {
1718
1718
  constructor(config = {}) {
@@ -1736,7 +1736,6 @@ var InsForgeClient = class {
1736
1736
  this.ai = new AI(this.http);
1737
1737
  this.functions = new Functions(this.http);
1738
1738
  this.realtime = new Realtime(this.http.baseUrl, this.tokenManager);
1739
- this.emails = new Emails(this.http);
1740
1739
  }
1741
1740
  /**
1742
1741
  * Get the underlying HTTP client for custom requests
@@ -1769,7 +1768,6 @@ export {
1769
1768
  AI,
1770
1769
  Auth,
1771
1770
  Database,
1772
- Emails,
1773
1771
  Functions,
1774
1772
  HttpClient,
1775
1773
  InsForgeClient,