@insforge/sdk 1.0.3-refresh.1 → 1.0.4

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,98 +290,7 @@ 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
-
362
293
  // 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
- }
385
294
  function isHostedAuthEnvironment() {
386
295
  if (typeof window === "undefined") {
387
296
  return false;
@@ -399,12 +308,11 @@ var Auth = class {
399
308
  constructor(http, tokenManager) {
400
309
  this.http = http;
401
310
  this.tokenManager = tokenManager;
402
- this.database = new Database(http, tokenManager);
403
311
  this.detectAuthCallback();
404
312
  }
405
313
  /**
406
314
  * Automatically detect and handle OAuth callback parameters in the URL
407
- * This runs on initialization to seamlessly complete the OAuth flow
315
+ * This runs after initialization to seamlessly complete the OAuth flow
408
316
  * Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)
409
317
  */
410
318
  detectAuthCallback() {
@@ -426,7 +334,8 @@ var Auth = class {
426
334
  user: {
427
335
  id: userId,
428
336
  email,
429
- name: name || "",
337
+ profile: { name: name || "" },
338
+ metadata: null,
430
339
  // These fields are not provided by backend OAuth callback
431
340
  // They'll be populated when calling getCurrentUser()
432
341
  emailVerified: false,
@@ -621,20 +530,19 @@ var Auth = class {
621
530
  */
622
531
  async getCurrentUser() {
623
532
  try {
624
- const session = this.tokenManager.getSession();
625
- if (!session?.accessToken) {
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) {
626
539
  return { data: null, error: null };
627
540
  }
628
- this.http.setAuthToken(session.accessToken);
541
+ this.http.setAuthToken(accessToken);
629
542
  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
- }
634
543
  return {
635
544
  data: {
636
- user: authResponse.user,
637
- profile: profile ? convertDbProfileToCamelCase(profile) : null
545
+ user: authResponse.user
638
546
  },
639
547
  error: null
640
548
  };
@@ -658,17 +566,28 @@ var Auth = class {
658
566
  }
659
567
  /**
660
568
  * Get any user's profile by ID
661
- * Returns profile information from the users table (dynamic fields)
569
+ * Returns profile information from the users table
662
570
  */
663
571
  async getProfile(userId) {
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 };
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
+ };
670
590
  }
671
- return { data: null, error };
672
591
  }
673
592
  /**
674
593
  * Get the current session (only session data, no API call)
@@ -739,42 +658,31 @@ var Auth = class {
739
658
  /**
740
659
  * Set/Update the current user's profile
741
660
  * Updates profile information in the users table (supports any dynamic fields)
661
+ * Requires authentication
742
662
  */
743
663
  async setProfile(profile) {
744
- const session = this.tokenManager.getSession();
745
- if (!session?.accessToken) {
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
+ }
746
677
  return {
747
678
  data: null,
748
679
  error: new InsForgeError(
749
- "No authenticated user found",
750
- 401,
751
- "UNAUTHENTICATED"
680
+ "An unexpected error occurred while updating user profile",
681
+ 500,
682
+ "UNEXPECTED_ERROR"
752
683
  )
753
684
  };
754
685
  }
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 };
778
686
  }
779
687
  /**
780
688
  * Send email verification (code or link based on config)
@@ -959,6 +867,75 @@ var Auth = class {
959
867
  }
960
868
  };
961
869
 
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
+
962
939
  // src/modules/storage.ts
963
940
  var StorageBucket = class {
964
941
  constructor(bucketName, http) {
@@ -1713,6 +1690,29 @@ var Realtime = class {
1713
1690
  }
1714
1691
  };
1715
1692
 
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,6 +1736,7 @@ 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);
1739
1740
  }
1740
1741
  /**
1741
1742
  * Get the underlying HTTP client for custom requests
@@ -1768,6 +1769,7 @@ export {
1768
1769
  AI,
1769
1770
  Auth,
1770
1771
  Database,
1772
+ Emails,
1771
1773
  Functions,
1772
1774
  HttpClient,
1773
1775
  InsForgeClient,