@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/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 +139 -142
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +139 -141
- 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,
|
|
@@ -530,19 +621,20 @@ var Auth = class {
|
|
|
530
621
|
*/
|
|
531
622
|
async getCurrentUser() {
|
|
532
623
|
try {
|
|
533
|
-
const
|
|
534
|
-
if (
|
|
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
|
-
|
|
573
|
-
|
|
574
|
-
return {
|
|
575
|
-
|
|
576
|
-
|
|
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
|
-
|
|
665
|
-
|
|
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
|
-
"
|
|
681
|
-
|
|
682
|
-
"
|
|
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,
|