@insforge/sdk 1.0.3-dev.2 → 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/README.md +0 -10
- package/dist/browser.mjs +3059 -0
- package/dist/browser.mjs.map +1 -0
- package/dist/index.d.mts +32 -54
- package/dist/index.d.ts +32 -54
- package/dist/index.js +136 -135
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +136 -134
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
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
|
|
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
|
-
|
|
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,
|
|
@@ -536,9 +627,14 @@ var Auth = class {
|
|
|
536
627
|
}
|
|
537
628
|
this.http.setAuthToken(session.accessToken);
|
|
538
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
|
+
}
|
|
539
634
|
return {
|
|
540
635
|
data: {
|
|
541
|
-
user: authResponse.user
|
|
636
|
+
user: authResponse.user,
|
|
637
|
+
profile: profile ? convertDbProfileToCamelCase(profile) : null
|
|
542
638
|
},
|
|
543
639
|
error: null
|
|
544
640
|
};
|
|
@@ -562,28 +658,17 @@ var Auth = class {
|
|
|
562
658
|
}
|
|
563
659
|
/**
|
|
564
660
|
* Get any user's profile by ID
|
|
565
|
-
* Returns profile information from the users table
|
|
661
|
+
* Returns profile information from the users table (dynamic fields)
|
|
566
662
|
*/
|
|
567
663
|
async getProfile(userId) {
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
return {
|
|
571
|
-
data: response,
|
|
572
|
-
error: null
|
|
573
|
-
};
|
|
574
|
-
} catch (error) {
|
|
575
|
-
if (error instanceof InsForgeError) {
|
|
576
|
-
return { data: null, error };
|
|
577
|
-
}
|
|
578
|
-
return {
|
|
579
|
-
data: null,
|
|
580
|
-
error: new InsForgeError(
|
|
581
|
-
"An unexpected error occurred while fetching user profile",
|
|
582
|
-
500,
|
|
583
|
-
"UNEXPECTED_ERROR"
|
|
584
|
-
)
|
|
585
|
-
};
|
|
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 };
|
|
586
667
|
}
|
|
668
|
+
if (data) {
|
|
669
|
+
return { data: convertDbProfileToCamelCase(data), error: null };
|
|
670
|
+
}
|
|
671
|
+
return { data: null, error };
|
|
587
672
|
}
|
|
588
673
|
/**
|
|
589
674
|
* Get the current session (only session data, no API call)
|
|
@@ -654,31 +739,42 @@ var Auth = class {
|
|
|
654
739
|
/**
|
|
655
740
|
* Set/Update the current user's profile
|
|
656
741
|
* Updates profile information in the users table (supports any dynamic fields)
|
|
657
|
-
* Requires authentication
|
|
658
742
|
*/
|
|
659
743
|
async setProfile(profile) {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
"/api/auth/profiles/current",
|
|
663
|
-
{ profile }
|
|
664
|
-
);
|
|
665
|
-
return {
|
|
666
|
-
data: response,
|
|
667
|
-
error: null
|
|
668
|
-
};
|
|
669
|
-
} catch (error) {
|
|
670
|
-
if (error instanceof InsForgeError) {
|
|
671
|
-
return { data: null, error };
|
|
672
|
-
}
|
|
744
|
+
const session = this.tokenManager.getSession();
|
|
745
|
+
if (!session?.accessToken) {
|
|
673
746
|
return {
|
|
674
747
|
data: null,
|
|
675
748
|
error: new InsForgeError(
|
|
676
|
-
"
|
|
677
|
-
|
|
678
|
-
"
|
|
749
|
+
"No authenticated user found",
|
|
750
|
+
401,
|
|
751
|
+
"UNAUTHENTICATED"
|
|
679
752
|
)
|
|
680
753
|
};
|
|
681
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 };
|
|
682
778
|
}
|
|
683
779
|
/**
|
|
684
780
|
* Send email verification (code or link based on config)
|
|
@@ -863,75 +959,6 @@ var Auth = class {
|
|
|
863
959
|
}
|
|
864
960
|
};
|
|
865
961
|
|
|
866
|
-
// src/modules/database-postgrest.ts
|
|
867
|
-
import { PostgrestClient } from "@supabase/postgrest-js";
|
|
868
|
-
function createInsForgePostgrestFetch(httpClient, tokenManager) {
|
|
869
|
-
return async (input, init) => {
|
|
870
|
-
const url = typeof input === "string" ? input : input.toString();
|
|
871
|
-
const urlObj = new URL(url);
|
|
872
|
-
const tableName = urlObj.pathname.slice(1);
|
|
873
|
-
const insforgeUrl = `${httpClient.baseUrl}/api/database/records/${tableName}${urlObj.search}`;
|
|
874
|
-
const token = tokenManager.getAccessToken();
|
|
875
|
-
const httpHeaders = httpClient.getHeaders();
|
|
876
|
-
const authToken = token || httpHeaders["Authorization"]?.replace("Bearer ", "");
|
|
877
|
-
const headers = new Headers(init?.headers);
|
|
878
|
-
if (authToken && !headers.has("Authorization")) {
|
|
879
|
-
headers.set("Authorization", `Bearer ${authToken}`);
|
|
880
|
-
}
|
|
881
|
-
const response = await fetch(insforgeUrl, {
|
|
882
|
-
...init,
|
|
883
|
-
headers
|
|
884
|
-
});
|
|
885
|
-
return response;
|
|
886
|
-
};
|
|
887
|
-
}
|
|
888
|
-
var Database = class {
|
|
889
|
-
constructor(httpClient, tokenManager) {
|
|
890
|
-
this.postgrest = new PostgrestClient("http://dummy", {
|
|
891
|
-
fetch: createInsForgePostgrestFetch(httpClient, tokenManager),
|
|
892
|
-
headers: {}
|
|
893
|
-
});
|
|
894
|
-
}
|
|
895
|
-
/**
|
|
896
|
-
* Create a query builder for a table
|
|
897
|
-
*
|
|
898
|
-
* @example
|
|
899
|
-
* // Basic query
|
|
900
|
-
* const { data, error } = await client.database
|
|
901
|
-
* .from('posts')
|
|
902
|
-
* .select('*')
|
|
903
|
-
* .eq('user_id', userId);
|
|
904
|
-
*
|
|
905
|
-
* // With count (Supabase style!)
|
|
906
|
-
* const { data, error, count } = await client.database
|
|
907
|
-
* .from('posts')
|
|
908
|
-
* .select('*', { count: 'exact' })
|
|
909
|
-
* .range(0, 9);
|
|
910
|
-
*
|
|
911
|
-
* // Just get count, no data
|
|
912
|
-
* const { count } = await client.database
|
|
913
|
-
* .from('posts')
|
|
914
|
-
* .select('*', { count: 'exact', head: true });
|
|
915
|
-
*
|
|
916
|
-
* // Complex queries with OR
|
|
917
|
-
* const { data } = await client.database
|
|
918
|
-
* .from('posts')
|
|
919
|
-
* .select('*, users!inner(*)')
|
|
920
|
-
* .or('status.eq.active,status.eq.pending');
|
|
921
|
-
*
|
|
922
|
-
* // All features work:
|
|
923
|
-
* - Nested selects
|
|
924
|
-
* - Foreign key expansion
|
|
925
|
-
* - OR/AND/NOT conditions
|
|
926
|
-
* - Count with head
|
|
927
|
-
* - Range pagination
|
|
928
|
-
* - Upserts
|
|
929
|
-
*/
|
|
930
|
-
from(table) {
|
|
931
|
-
return this.postgrest.from(table);
|
|
932
|
-
}
|
|
933
|
-
};
|
|
934
|
-
|
|
935
962
|
// src/modules/storage.ts
|
|
936
963
|
var StorageBucket = class {
|
|
937
964
|
constructor(bucketName, http) {
|
|
@@ -1686,29 +1713,6 @@ var Realtime = class {
|
|
|
1686
1713
|
}
|
|
1687
1714
|
};
|
|
1688
1715
|
|
|
1689
|
-
// src/modules/email.ts
|
|
1690
|
-
var Emails = class {
|
|
1691
|
-
constructor(http) {
|
|
1692
|
-
this.http = http;
|
|
1693
|
-
}
|
|
1694
|
-
/**
|
|
1695
|
-
* Send a custom HTML email
|
|
1696
|
-
* @param options Email options including recipients, subject, and HTML content
|
|
1697
|
-
*/
|
|
1698
|
-
async send(options) {
|
|
1699
|
-
try {
|
|
1700
|
-
const data = await this.http.post(
|
|
1701
|
-
"/api/email/send-raw",
|
|
1702
|
-
options
|
|
1703
|
-
);
|
|
1704
|
-
return { data, error: null };
|
|
1705
|
-
} catch (error) {
|
|
1706
|
-
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
1707
|
-
return { data: null, error: normalizedError };
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
};
|
|
1711
|
-
|
|
1712
1716
|
// src/client.ts
|
|
1713
1717
|
var InsForgeClient = class {
|
|
1714
1718
|
constructor(config = {}) {
|
|
@@ -1732,7 +1736,6 @@ var InsForgeClient = class {
|
|
|
1732
1736
|
this.ai = new AI(this.http);
|
|
1733
1737
|
this.functions = new Functions(this.http);
|
|
1734
1738
|
this.realtime = new Realtime(this.http.baseUrl, this.tokenManager);
|
|
1735
|
-
this.emails = new Emails(this.http);
|
|
1736
1739
|
}
|
|
1737
1740
|
/**
|
|
1738
1741
|
* Get the underlying HTTP client for custom requests
|
|
@@ -1765,7 +1768,6 @@ export {
|
|
|
1765
1768
|
AI,
|
|
1766
1769
|
Auth,
|
|
1767
1770
|
Database,
|
|
1768
|
-
Emails,
|
|
1769
1771
|
Functions,
|
|
1770
1772
|
HttpClient,
|
|
1771
1773
|
InsForgeClient,
|