@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/README.md +10 -0
- package/dist/index.d.mts +54 -32
- package/dist/index.d.ts +54 -32
- package/dist/index.js +142 -139
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +141 -139
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/browser.mjs +0 -3059
- package/dist/browser.mjs.map +0 -1
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
|
|
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
|
|
625
|
-
if (
|
|
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(
|
|
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
|
|
569
|
+
* Returns profile information from the users table
|
|
662
570
|
*/
|
|
663
571
|
async getProfile(userId) {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
return {
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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
|
-
|
|
745
|
-
|
|
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
|
-
"
|
|
750
|
-
|
|
751
|
-
"
|
|
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,
|