@ragable/sdk 0.4.2 → 0.5.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.d.mts +165 -23
- package/dist/index.d.ts +165 -23
- package/dist/index.js +478 -38
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +469 -35
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23,11 +23,17 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
23
23
|
var index_exports = {};
|
|
24
24
|
__export(index_exports, {
|
|
25
25
|
AgentsClient: () => AgentsClient,
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
DEFAULT_RAGABLE_API_BASE: () => DEFAULT_RAGABLE_API_BASE,
|
|
27
|
+
PostgrestDeleteReturningBuilder: () => PostgrestDeleteReturningBuilder,
|
|
28
|
+
PostgrestDeleteRootBuilder: () => PostgrestDeleteRootBuilder,
|
|
29
|
+
PostgrestInsertReturningBuilder: () => PostgrestInsertReturningBuilder,
|
|
30
|
+
PostgrestInsertRootBuilder: () => PostgrestInsertRootBuilder,
|
|
28
31
|
PostgrestSelectBuilder: () => PostgrestSelectBuilder,
|
|
29
32
|
PostgrestTableApi: () => PostgrestTableApi,
|
|
30
|
-
|
|
33
|
+
PostgrestUpdateReturningBuilder: () => PostgrestUpdateReturningBuilder,
|
|
34
|
+
PostgrestUpdateRootBuilder: () => PostgrestUpdateRootBuilder,
|
|
35
|
+
PostgrestUpsertReturningBuilder: () => PostgrestUpsertReturningBuilder,
|
|
36
|
+
PostgrestUpsertRootBuilder: () => PostgrestUpsertRootBuilder,
|
|
31
37
|
Ragable: () => Ragable,
|
|
32
38
|
RagableBrowser: () => RagableBrowser,
|
|
33
39
|
RagableBrowserAgentsClient: () => RagableBrowserAgentsClient,
|
|
@@ -58,6 +64,7 @@ function bindFetch(custom) {
|
|
|
58
64
|
return f.call(globalThis, input, init);
|
|
59
65
|
};
|
|
60
66
|
}
|
|
67
|
+
var DEFAULT_RAGABLE_API_BASE = "https://ragable-341305259977.asia-southeast1.run.app/api";
|
|
61
68
|
var RagableError = class extends Error {
|
|
62
69
|
constructor(message, status, body) {
|
|
63
70
|
super(message);
|
|
@@ -89,7 +96,7 @@ var RagableRequestClient = class {
|
|
|
89
96
|
__publicField(this, "fetchImpl");
|
|
90
97
|
__publicField(this, "defaultHeaders");
|
|
91
98
|
this.apiKey = options.apiKey;
|
|
92
|
-
this.baseUrl = options.baseUrl ??
|
|
99
|
+
this.baseUrl = options.baseUrl ?? DEFAULT_RAGABLE_API_BASE;
|
|
93
100
|
this.fetchImpl = bindFetch(options.fetch);
|
|
94
101
|
this.defaultHeaders = options.headers;
|
|
95
102
|
}
|
|
@@ -407,6 +414,18 @@ function quoteIdent(name) {
|
|
|
407
414
|
assertIdent(name, "column");
|
|
408
415
|
return `"${name}"`;
|
|
409
416
|
}
|
|
417
|
+
function parseConflictColumns(onConflict) {
|
|
418
|
+
const parts = onConflict.split(",").map((s) => s.trim()).filter(Boolean);
|
|
419
|
+
if (parts.length === 0) {
|
|
420
|
+
throw new RagableError(
|
|
421
|
+
"upsert requires onConflict with at least one column (e.g. 'id' or 'org_id,user_id')",
|
|
422
|
+
400,
|
|
423
|
+
null
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
for (const p of parts) assertIdent(p, "onConflict");
|
|
427
|
+
return parts;
|
|
428
|
+
}
|
|
410
429
|
var OP_SQL = {
|
|
411
430
|
eq: "=",
|
|
412
431
|
neq: "<>",
|
|
@@ -489,7 +508,6 @@ var PostgrestSelectBuilder = class {
|
|
|
489
508
|
this._order = { column, ascending: options?.ascending !== false };
|
|
490
509
|
return this;
|
|
491
510
|
}
|
|
492
|
-
/** @param includeUserLimit when false, omit `.limit()` (for `.single()` / `.maybeSingle()`). */
|
|
493
511
|
buildSelectCore(params, includeUserLimit) {
|
|
494
512
|
const tbl = quoteIdent(this.table);
|
|
495
513
|
const { clause } = buildWhere(this.filters, params);
|
|
@@ -529,12 +547,7 @@ var PostgrestSelectBuilder = class {
|
|
|
529
547
|
params,
|
|
530
548
|
readOnly: true
|
|
531
549
|
});
|
|
532
|
-
if (res.rows.length === 0) {
|
|
533
|
-
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
534
|
-
code: "PGRST116"
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
|
-
if (res.rows.length > 1) {
|
|
550
|
+
if (res.rows.length === 0 || res.rows.length > 1) {
|
|
538
551
|
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
539
552
|
code: "PGRST116"
|
|
540
553
|
});
|
|
@@ -562,23 +575,70 @@ var PostgrestSelectBuilder = class {
|
|
|
562
575
|
});
|
|
563
576
|
}
|
|
564
577
|
};
|
|
565
|
-
var
|
|
578
|
+
var PostgrestInsertRootBuilder = class {
|
|
566
579
|
constructor(run, databaseInstanceId, table, rows) {
|
|
567
580
|
this.run = run;
|
|
568
581
|
this.databaseInstanceId = databaseInstanceId;
|
|
569
582
|
this.table = table;
|
|
570
583
|
this.rows = rows;
|
|
571
|
-
__publicField(this, "returning", "*");
|
|
572
584
|
assertIdent(table, "table");
|
|
573
585
|
}
|
|
586
|
+
/**
|
|
587
|
+
* Return inserted rows (Supabase: chain `.select()` to get data).
|
|
588
|
+
* @see https://supabase.com/docs/reference/javascript/insert
|
|
589
|
+
*/
|
|
574
590
|
select(columns = "*") {
|
|
575
|
-
|
|
576
|
-
|
|
591
|
+
return new PostgrestInsertReturningBuilder(
|
|
592
|
+
this.run,
|
|
593
|
+
this.databaseInstanceId,
|
|
594
|
+
this.table,
|
|
595
|
+
this.rows,
|
|
596
|
+
columns
|
|
597
|
+
);
|
|
577
598
|
}
|
|
578
599
|
then(onfulfilled, onrejected) {
|
|
579
|
-
return this.
|
|
600
|
+
return this.executeNoReturn().then(onfulfilled, onrejected);
|
|
580
601
|
}
|
|
581
|
-
async
|
|
602
|
+
async executeNoReturn() {
|
|
603
|
+
return asPostgrestResponse(async () => {
|
|
604
|
+
if (this.rows.length === 0) return null;
|
|
605
|
+
const keys = Object.keys(this.rows[0]);
|
|
606
|
+
for (const k of keys) assertIdent(k, "column");
|
|
607
|
+
const tbl = quoteIdent(this.table);
|
|
608
|
+
const params = [];
|
|
609
|
+
const valueGroups = [];
|
|
610
|
+
for (const row of this.rows) {
|
|
611
|
+
const placeholders = [];
|
|
612
|
+
for (const k of keys) {
|
|
613
|
+
params.push(row[k]);
|
|
614
|
+
placeholders.push(`$${params.length}`);
|
|
615
|
+
}
|
|
616
|
+
valueGroups.push(`(${placeholders.join(", ")})`);
|
|
617
|
+
}
|
|
618
|
+
const cols = keys.map(quoteIdent).join(", ");
|
|
619
|
+
const sql = `INSERT INTO ${tbl} (${cols}) VALUES ${valueGroups.join(", ")}`;
|
|
620
|
+
await this.run({
|
|
621
|
+
databaseInstanceId: this.databaseInstanceId,
|
|
622
|
+
sql,
|
|
623
|
+
params,
|
|
624
|
+
readOnly: false
|
|
625
|
+
});
|
|
626
|
+
return null;
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
var PostgrestInsertReturningBuilder = class {
|
|
631
|
+
constructor(run, databaseInstanceId, table, rows, returning) {
|
|
632
|
+
this.run = run;
|
|
633
|
+
this.databaseInstanceId = databaseInstanceId;
|
|
634
|
+
this.table = table;
|
|
635
|
+
this.rows = rows;
|
|
636
|
+
this.returning = returning;
|
|
637
|
+
}
|
|
638
|
+
then(onfulfilled, onrejected) {
|
|
639
|
+
return this.executeMany().then(onfulfilled, onrejected);
|
|
640
|
+
}
|
|
641
|
+
async executeMany() {
|
|
582
642
|
return asPostgrestResponse(async () => {
|
|
583
643
|
if (this.rows.length === 0) return [];
|
|
584
644
|
const keys = Object.keys(this.rows[0]);
|
|
@@ -605,29 +665,137 @@ var PostgrestInsertBuilder = class {
|
|
|
605
665
|
return res.rows;
|
|
606
666
|
});
|
|
607
667
|
}
|
|
668
|
+
async single() {
|
|
669
|
+
return asPostgrestResponse(async () => {
|
|
670
|
+
const { data, error } = await this.executeMany();
|
|
671
|
+
if (error) throw error;
|
|
672
|
+
const rows = data ?? [];
|
|
673
|
+
if (rows.length === 0 || rows.length > 1) {
|
|
674
|
+
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
675
|
+
code: "PGRST116"
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
return rows[0];
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
async maybeSingle() {
|
|
682
|
+
return asPostgrestResponse(async () => {
|
|
683
|
+
const { data, error } = await this.executeMany();
|
|
684
|
+
if (error) throw error;
|
|
685
|
+
const rows = data ?? [];
|
|
686
|
+
if (rows.length > 1) {
|
|
687
|
+
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
688
|
+
code: "PGRST116"
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
return rows[0] ?? null;
|
|
692
|
+
});
|
|
693
|
+
}
|
|
608
694
|
};
|
|
609
|
-
var
|
|
695
|
+
var PostgrestUpdateRootBuilder = class {
|
|
610
696
|
constructor(run, databaseInstanceId, table, patch) {
|
|
611
697
|
this.run = run;
|
|
612
698
|
this.databaseInstanceId = databaseInstanceId;
|
|
613
699
|
this.table = table;
|
|
614
700
|
this.patch = patch;
|
|
615
701
|
__publicField(this, "filters", []);
|
|
616
|
-
__publicField(this, "returning", "*");
|
|
617
702
|
assertIdent(table, "table");
|
|
618
703
|
}
|
|
619
704
|
eq(column, value) {
|
|
620
705
|
this.filters.push({ op: "eq", column, value });
|
|
621
706
|
return this;
|
|
622
707
|
}
|
|
623
|
-
|
|
624
|
-
this.
|
|
708
|
+
neq(column, value) {
|
|
709
|
+
this.filters.push({ op: "neq", column, value });
|
|
625
710
|
return this;
|
|
626
711
|
}
|
|
712
|
+
gt(column, value) {
|
|
713
|
+
this.filters.push({ op: "gt", column, value });
|
|
714
|
+
return this;
|
|
715
|
+
}
|
|
716
|
+
gte(column, value) {
|
|
717
|
+
this.filters.push({ op: "gte", column, value });
|
|
718
|
+
return this;
|
|
719
|
+
}
|
|
720
|
+
lt(column, value) {
|
|
721
|
+
this.filters.push({ op: "lt", column, value });
|
|
722
|
+
return this;
|
|
723
|
+
}
|
|
724
|
+
lte(column, value) {
|
|
725
|
+
this.filters.push({ op: "lte", column, value });
|
|
726
|
+
return this;
|
|
727
|
+
}
|
|
728
|
+
like(column, value) {
|
|
729
|
+
this.filters.push({ op: "like", column, value });
|
|
730
|
+
return this;
|
|
731
|
+
}
|
|
732
|
+
ilike(column, value) {
|
|
733
|
+
this.filters.push({ op: "ilike", column, value });
|
|
734
|
+
return this;
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Return updated rows (Supabase: `.update().eq().select()`).
|
|
738
|
+
* @see https://supabase.com/docs/reference/javascript/update
|
|
739
|
+
*/
|
|
740
|
+
select(columns = "*") {
|
|
741
|
+
return new PostgrestUpdateReturningBuilder(
|
|
742
|
+
this.run,
|
|
743
|
+
this.databaseInstanceId,
|
|
744
|
+
this.table,
|
|
745
|
+
this.patch,
|
|
746
|
+
this.filters,
|
|
747
|
+
columns
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
then(onfulfilled, onrejected) {
|
|
751
|
+
return this.executeNoReturn().then(onfulfilled, onrejected);
|
|
752
|
+
}
|
|
753
|
+
async executeNoReturn() {
|
|
754
|
+
return asPostgrestResponse(async () => {
|
|
755
|
+
const keys = Object.keys(this.patch);
|
|
756
|
+
if (keys.length === 0) {
|
|
757
|
+
throw new RagableError("Empty update payload", 400, null);
|
|
758
|
+
}
|
|
759
|
+
for (const k of keys) assertIdent(k, "column");
|
|
760
|
+
if (this.filters.length === 0) {
|
|
761
|
+
throw new RagableError(
|
|
762
|
+
"UPDATE requires a filter (e.g. .eq('id', value)) \u2014 refusing unscoped update",
|
|
763
|
+
400,
|
|
764
|
+
null
|
|
765
|
+
);
|
|
766
|
+
}
|
|
767
|
+
const params = [];
|
|
768
|
+
const sets = [];
|
|
769
|
+
for (const k of keys) {
|
|
770
|
+
params.push(this.patch[k]);
|
|
771
|
+
sets.push(`${quoteIdent(k)} = $${params.length}`);
|
|
772
|
+
}
|
|
773
|
+
const { clause } = buildWhere(this.filters, params);
|
|
774
|
+
const tbl = quoteIdent(this.table);
|
|
775
|
+
const sql = `UPDATE ${tbl} SET ${sets.join(", ")}${clause}`;
|
|
776
|
+
await this.run({
|
|
777
|
+
databaseInstanceId: this.databaseInstanceId,
|
|
778
|
+
sql,
|
|
779
|
+
params,
|
|
780
|
+
readOnly: false
|
|
781
|
+
});
|
|
782
|
+
return null;
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
var PostgrestUpdateReturningBuilder = class {
|
|
787
|
+
constructor(run, databaseInstanceId, table, patch, filters, returning) {
|
|
788
|
+
this.run = run;
|
|
789
|
+
this.databaseInstanceId = databaseInstanceId;
|
|
790
|
+
this.table = table;
|
|
791
|
+
this.patch = patch;
|
|
792
|
+
this.filters = filters;
|
|
793
|
+
this.returning = returning;
|
|
794
|
+
}
|
|
627
795
|
then(onfulfilled, onrejected) {
|
|
628
|
-
return this.
|
|
796
|
+
return this.executeMany().then(onfulfilled, onrejected);
|
|
629
797
|
}
|
|
630
|
-
async
|
|
798
|
+
async executeMany() {
|
|
631
799
|
return asPostgrestResponse(async () => {
|
|
632
800
|
const keys = Object.keys(this.patch);
|
|
633
801
|
if (keys.length === 0) {
|
|
@@ -659,28 +827,124 @@ var PostgrestUpdateBuilder = class {
|
|
|
659
827
|
return res.rows;
|
|
660
828
|
});
|
|
661
829
|
}
|
|
830
|
+
async single() {
|
|
831
|
+
return asPostgrestResponse(async () => {
|
|
832
|
+
const { data, error } = await this.executeMany();
|
|
833
|
+
if (error) throw error;
|
|
834
|
+
const rows = data ?? [];
|
|
835
|
+
if (rows.length === 0 || rows.length > 1) {
|
|
836
|
+
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
837
|
+
code: "PGRST116"
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
return rows[0];
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
async maybeSingle() {
|
|
844
|
+
return asPostgrestResponse(async () => {
|
|
845
|
+
const { data, error } = await this.executeMany();
|
|
846
|
+
if (error) throw error;
|
|
847
|
+
const rows = data ?? [];
|
|
848
|
+
if (rows.length > 1) {
|
|
849
|
+
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
850
|
+
code: "PGRST116"
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
return rows[0] ?? null;
|
|
854
|
+
});
|
|
855
|
+
}
|
|
662
856
|
};
|
|
663
|
-
var
|
|
857
|
+
var PostgrestDeleteRootBuilder = class {
|
|
664
858
|
constructor(run, databaseInstanceId, table) {
|
|
665
859
|
this.run = run;
|
|
666
860
|
this.databaseInstanceId = databaseInstanceId;
|
|
667
861
|
this.table = table;
|
|
668
862
|
__publicField(this, "filters", []);
|
|
669
|
-
__publicField(this, "returning", "*");
|
|
670
863
|
assertIdent(table, "table");
|
|
671
864
|
}
|
|
672
865
|
eq(column, value) {
|
|
673
866
|
this.filters.push({ op: "eq", column, value });
|
|
674
867
|
return this;
|
|
675
868
|
}
|
|
676
|
-
|
|
677
|
-
this.
|
|
869
|
+
neq(column, value) {
|
|
870
|
+
this.filters.push({ op: "neq", column, value });
|
|
871
|
+
return this;
|
|
872
|
+
}
|
|
873
|
+
gt(column, value) {
|
|
874
|
+
this.filters.push({ op: "gt", column, value });
|
|
875
|
+
return this;
|
|
876
|
+
}
|
|
877
|
+
gte(column, value) {
|
|
878
|
+
this.filters.push({ op: "gte", column, value });
|
|
678
879
|
return this;
|
|
679
880
|
}
|
|
881
|
+
lt(column, value) {
|
|
882
|
+
this.filters.push({ op: "lt", column, value });
|
|
883
|
+
return this;
|
|
884
|
+
}
|
|
885
|
+
lte(column, value) {
|
|
886
|
+
this.filters.push({ op: "lte", column, value });
|
|
887
|
+
return this;
|
|
888
|
+
}
|
|
889
|
+
like(column, value) {
|
|
890
|
+
this.filters.push({ op: "like", column, value });
|
|
891
|
+
return this;
|
|
892
|
+
}
|
|
893
|
+
ilike(column, value) {
|
|
894
|
+
this.filters.push({ op: "ilike", column, value });
|
|
895
|
+
return this;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Return deleted rows (Supabase: `.delete().eq().select()`).
|
|
899
|
+
* @see https://supabase.com/docs/reference/javascript/delete
|
|
900
|
+
*/
|
|
901
|
+
select(columns = "*") {
|
|
902
|
+
return new PostgrestDeleteReturningBuilder(
|
|
903
|
+
this.run,
|
|
904
|
+
this.databaseInstanceId,
|
|
905
|
+
this.table,
|
|
906
|
+
this.filters,
|
|
907
|
+
columns
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
then(onfulfilled, onrejected) {
|
|
911
|
+
return this.executeNoReturn().then(onfulfilled, onrejected);
|
|
912
|
+
}
|
|
913
|
+
async executeNoReturn() {
|
|
914
|
+
return asPostgrestResponse(async () => {
|
|
915
|
+
if (this.filters.length === 0) {
|
|
916
|
+
throw new RagableError(
|
|
917
|
+
"DELETE requires a filter (e.g. .eq('id', value)) \u2014 refusing unscoped delete",
|
|
918
|
+
400,
|
|
919
|
+
null
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
const params = [];
|
|
923
|
+
const { clause } = buildWhere(this.filters, params);
|
|
924
|
+
const tbl = quoteIdent(this.table);
|
|
925
|
+
const sql = `DELETE FROM ${tbl}${clause}`;
|
|
926
|
+
await this.run({
|
|
927
|
+
databaseInstanceId: this.databaseInstanceId,
|
|
928
|
+
sql,
|
|
929
|
+
params,
|
|
930
|
+
readOnly: false
|
|
931
|
+
});
|
|
932
|
+
return null;
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
var PostgrestDeleteReturningBuilder = class {
|
|
937
|
+
constructor(run, databaseInstanceId, table, filters, returning) {
|
|
938
|
+
this.run = run;
|
|
939
|
+
this.databaseInstanceId = databaseInstanceId;
|
|
940
|
+
this.table = table;
|
|
941
|
+
this.filters = filters;
|
|
942
|
+
this.returning = returning;
|
|
943
|
+
}
|
|
680
944
|
then(onfulfilled, onrejected) {
|
|
681
|
-
return this.
|
|
945
|
+
return this.executeMany().then(onfulfilled, onrejected);
|
|
682
946
|
}
|
|
683
|
-
async
|
|
947
|
+
async executeMany() {
|
|
684
948
|
return asPostgrestResponse(async () => {
|
|
685
949
|
if (this.filters.length === 0) {
|
|
686
950
|
throw new RagableError(
|
|
@@ -702,6 +966,145 @@ var PostgrestDeleteBuilder = class {
|
|
|
702
966
|
return res.rows;
|
|
703
967
|
});
|
|
704
968
|
}
|
|
969
|
+
async single() {
|
|
970
|
+
return asPostgrestResponse(async () => {
|
|
971
|
+
const { data, error } = await this.executeMany();
|
|
972
|
+
if (error) throw error;
|
|
973
|
+
const rows = data ?? [];
|
|
974
|
+
if (rows.length === 0 || rows.length > 1) {
|
|
975
|
+
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
976
|
+
code: "PGRST116"
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
return rows[0];
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
async maybeSingle() {
|
|
983
|
+
return asPostgrestResponse(async () => {
|
|
984
|
+
const { data, error } = await this.executeMany();
|
|
985
|
+
if (error) throw error;
|
|
986
|
+
const rows = data ?? [];
|
|
987
|
+
if (rows.length > 1) {
|
|
988
|
+
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
989
|
+
code: "PGRST116"
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
return rows[0] ?? null;
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
};
|
|
996
|
+
var PostgrestUpsertRootBuilder = class {
|
|
997
|
+
constructor(run, databaseInstanceId, table, rows, onConflict, ignoreDuplicates) {
|
|
998
|
+
this.run = run;
|
|
999
|
+
this.databaseInstanceId = databaseInstanceId;
|
|
1000
|
+
this.table = table;
|
|
1001
|
+
this.rows = rows;
|
|
1002
|
+
this.ignoreDuplicates = ignoreDuplicates;
|
|
1003
|
+
__publicField(this, "conflictCols");
|
|
1004
|
+
assertIdent(table, "table");
|
|
1005
|
+
this.conflictCols = parseConflictColumns(onConflict);
|
|
1006
|
+
}
|
|
1007
|
+
/**
|
|
1008
|
+
* Return upserted rows (Supabase: `.upsert().select()`).
|
|
1009
|
+
* @see https://supabase.com/docs/reference/javascript/upsert
|
|
1010
|
+
*/
|
|
1011
|
+
select(columns = "*") {
|
|
1012
|
+
return new PostgrestUpsertReturningBuilder(this, columns);
|
|
1013
|
+
}
|
|
1014
|
+
then(onfulfilled, onrejected) {
|
|
1015
|
+
return this.executeNoReturn().then(onfulfilled, onrejected);
|
|
1016
|
+
}
|
|
1017
|
+
async executeNoReturn() {
|
|
1018
|
+
return asPostgrestResponse(async () => {
|
|
1019
|
+
await this.runUpsert(null);
|
|
1020
|
+
return null;
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
async runUpsert(returning) {
|
|
1024
|
+
if (this.rows.length === 0) {
|
|
1025
|
+
return { command: "INSERT", rowCount: 0, truncated: false, rows: [] };
|
|
1026
|
+
}
|
|
1027
|
+
const keys = Object.keys(this.rows[0]);
|
|
1028
|
+
for (const k of keys) assertIdent(k, "column");
|
|
1029
|
+
const tbl = quoteIdent(this.table);
|
|
1030
|
+
const conflictQuoted = this.conflictCols.map(quoteIdent).join(", ");
|
|
1031
|
+
const params = [];
|
|
1032
|
+
const valueGroups = [];
|
|
1033
|
+
for (const row of this.rows) {
|
|
1034
|
+
const placeholders = [];
|
|
1035
|
+
for (const k of keys) {
|
|
1036
|
+
params.push(row[k]);
|
|
1037
|
+
placeholders.push(`$${params.length}`);
|
|
1038
|
+
}
|
|
1039
|
+
valueGroups.push(`(${placeholders.join(", ")})`);
|
|
1040
|
+
}
|
|
1041
|
+
const cols = keys.map(quoteIdent).join(", ");
|
|
1042
|
+
let sql = `INSERT INTO ${tbl} (${cols}) VALUES ${valueGroups.join(", ")} ON CONFLICT (${conflictQuoted})`;
|
|
1043
|
+
if (this.ignoreDuplicates) {
|
|
1044
|
+
sql += " DO NOTHING";
|
|
1045
|
+
} else {
|
|
1046
|
+
const setParts = keys.filter((k) => !this.conflictCols.includes(k)).map((k) => `${quoteIdent(k)} = EXCLUDED.${quoteIdent(k)}`);
|
|
1047
|
+
if (setParts.length === 0) {
|
|
1048
|
+
sql += " DO NOTHING";
|
|
1049
|
+
} else {
|
|
1050
|
+
sql += ` DO UPDATE SET ${setParts.join(", ")}`;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
if (returning) {
|
|
1054
|
+
sql += ` RETURNING ${returning}`;
|
|
1055
|
+
}
|
|
1056
|
+
return this.run({
|
|
1057
|
+
databaseInstanceId: this.databaseInstanceId,
|
|
1058
|
+
sql,
|
|
1059
|
+
params,
|
|
1060
|
+
readOnly: false
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
/** Used by returning builder */
|
|
1064
|
+
async runWithReturning(returning) {
|
|
1065
|
+
return this.runUpsert(returning);
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1068
|
+
var PostgrestUpsertReturningBuilder = class {
|
|
1069
|
+
constructor(root, returning) {
|
|
1070
|
+
this.root = root;
|
|
1071
|
+
this.returning = returning;
|
|
1072
|
+
}
|
|
1073
|
+
then(onfulfilled, onrejected) {
|
|
1074
|
+
return this.executeMany().then(onfulfilled, onrejected);
|
|
1075
|
+
}
|
|
1076
|
+
async executeMany() {
|
|
1077
|
+
return asPostgrestResponse(async () => {
|
|
1078
|
+
const res = await this.root.runWithReturning(this.returning);
|
|
1079
|
+
return res.rows;
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
async single() {
|
|
1083
|
+
return asPostgrestResponse(async () => {
|
|
1084
|
+
const { data, error } = await this.executeMany();
|
|
1085
|
+
if (error) throw error;
|
|
1086
|
+
const rows = data ?? [];
|
|
1087
|
+
if (rows.length === 0 || rows.length > 1) {
|
|
1088
|
+
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
1089
|
+
code: "PGRST116"
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
1092
|
+
return rows[0];
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
async maybeSingle() {
|
|
1096
|
+
return asPostgrestResponse(async () => {
|
|
1097
|
+
const { data, error } = await this.executeMany();
|
|
1098
|
+
if (error) throw error;
|
|
1099
|
+
const rows = data ?? [];
|
|
1100
|
+
if (rows.length > 1) {
|
|
1101
|
+
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
1102
|
+
code: "PGRST116"
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
return rows[0] ?? null;
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
705
1108
|
};
|
|
706
1109
|
var PostgrestTableApi = class {
|
|
707
1110
|
constructor(run, databaseInstanceId, table) {
|
|
@@ -719,7 +1122,7 @@ var PostgrestTableApi = class {
|
|
|
719
1122
|
}
|
|
720
1123
|
insert(values) {
|
|
721
1124
|
const rows = Array.isArray(values) ? values : [values];
|
|
722
|
-
return new
|
|
1125
|
+
return new PostgrestInsertRootBuilder(
|
|
723
1126
|
this.run,
|
|
724
1127
|
this.databaseInstanceId,
|
|
725
1128
|
this.table,
|
|
@@ -727,7 +1130,7 @@ var PostgrestTableApi = class {
|
|
|
727
1130
|
);
|
|
728
1131
|
}
|
|
729
1132
|
update(patch) {
|
|
730
|
-
return new
|
|
1133
|
+
return new PostgrestUpdateRootBuilder(
|
|
731
1134
|
this.run,
|
|
732
1135
|
this.databaseInstanceId,
|
|
733
1136
|
this.table,
|
|
@@ -735,17 +1138,33 @@ var PostgrestTableApi = class {
|
|
|
735
1138
|
);
|
|
736
1139
|
}
|
|
737
1140
|
delete() {
|
|
738
|
-
return new
|
|
1141
|
+
return new PostgrestDeleteRootBuilder(
|
|
739
1142
|
this.run,
|
|
740
1143
|
this.databaseInstanceId,
|
|
741
1144
|
this.table
|
|
742
1145
|
);
|
|
743
1146
|
}
|
|
1147
|
+
/**
|
|
1148
|
+
* `INSERT ... ON CONFLICT ... DO UPDATE` (or `DO NOTHING` with `ignoreDuplicates`).
|
|
1149
|
+
* @see https://supabase.com/docs/reference/javascript/upsert
|
|
1150
|
+
*/
|
|
1151
|
+
upsert(values, options) {
|
|
1152
|
+
const rows = Array.isArray(values) ? values : [values];
|
|
1153
|
+
return new PostgrestUpsertRootBuilder(
|
|
1154
|
+
this.run,
|
|
1155
|
+
this.databaseInstanceId,
|
|
1156
|
+
this.table,
|
|
1157
|
+
rows,
|
|
1158
|
+
options.onConflict,
|
|
1159
|
+
options.ignoreDuplicates === true
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
744
1162
|
};
|
|
745
1163
|
|
|
746
1164
|
// src/browser.ts
|
|
747
1165
|
function normalizeBrowserApiBase(baseUrl) {
|
|
748
|
-
|
|
1166
|
+
const trimmed = (baseUrl ?? DEFAULT_RAGABLE_API_BASE).trim().replace(/\/+$/, "");
|
|
1167
|
+
return trimmed.endsWith("/api") ? trimmed : `${trimmed}/api`;
|
|
749
1168
|
}
|
|
750
1169
|
function requireAuthGroupId(options) {
|
|
751
1170
|
const id = options.authGroupId?.trim();
|
|
@@ -769,6 +1188,20 @@ async function requireAccessToken(options) {
|
|
|
769
1188
|
}
|
|
770
1189
|
return token.trim();
|
|
771
1190
|
}
|
|
1191
|
+
async function resolveDatabaseAuthBearer(options) {
|
|
1192
|
+
const mode = options.dataAuth ?? "user";
|
|
1193
|
+
if (mode === "user") {
|
|
1194
|
+
return requireAccessToken(options);
|
|
1195
|
+
}
|
|
1196
|
+
const fromGetter = options.getDataStaticKey ? await options.getDataStaticKey() : null;
|
|
1197
|
+
const key = (fromGetter?.trim() || options.dataStaticKey?.trim()) ?? "";
|
|
1198
|
+
if (!key) {
|
|
1199
|
+
throw new Error(
|
|
1200
|
+
mode === "publicAnon" ? "dataAuth publicAnon requires getDataStaticKey or dataStaticKey (rotate key in dashboard)" : "dataAuth admin requires getDataStaticKey or dataStaticKey (server-side only; rotate in dashboard)"
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
return key;
|
|
1204
|
+
}
|
|
772
1205
|
async function parseJsonOrThrow(response) {
|
|
773
1206
|
const payload = await parseMaybeJsonBody(response);
|
|
774
1207
|
if (!response.ok) {
|
|
@@ -938,7 +1371,7 @@ var RagableBrowserDatabaseClient = class {
|
|
|
938
1371
|
}
|
|
939
1372
|
async query(params) {
|
|
940
1373
|
const gid = requireAuthGroupId(this.options);
|
|
941
|
-
const token = await
|
|
1374
|
+
const token = await resolveDatabaseAuthBearer(this.options);
|
|
942
1375
|
const databaseInstanceId = params.databaseInstanceId?.trim() || this.options.databaseInstanceId?.trim();
|
|
943
1376
|
if (!databaseInstanceId) {
|
|
944
1377
|
throw new Error(
|
|
@@ -948,6 +1381,7 @@ var RagableBrowserDatabaseClient = class {
|
|
|
948
1381
|
const headers = this.baseHeaders();
|
|
949
1382
|
headers.set("Authorization", `Bearer ${token}`);
|
|
950
1383
|
headers.set("Content-Type", "application/json");
|
|
1384
|
+
const readOnly = (this.options.dataAuth ?? "user") === "publicAnon" ? true : params.readOnly !== false;
|
|
951
1385
|
const response = await this.fetchImpl(
|
|
952
1386
|
this.toUrl(`/auth-groups/${gid}/data/query`),
|
|
953
1387
|
{
|
|
@@ -957,7 +1391,7 @@ var RagableBrowserDatabaseClient = class {
|
|
|
957
1391
|
databaseInstanceId,
|
|
958
1392
|
sql: params.sql,
|
|
959
1393
|
...params.params !== void 0 ? { params: params.params } : {},
|
|
960
|
-
|
|
1394
|
+
readOnly,
|
|
961
1395
|
...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
|
|
962
1396
|
...params.rowLimit !== void 0 ? { rowLimit: params.rowLimit } : {}
|
|
963
1397
|
})
|
|
@@ -1133,11 +1567,17 @@ function createRagableServerClient(options) {
|
|
|
1133
1567
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1134
1568
|
0 && (module.exports = {
|
|
1135
1569
|
AgentsClient,
|
|
1136
|
-
|
|
1137
|
-
|
|
1570
|
+
DEFAULT_RAGABLE_API_BASE,
|
|
1571
|
+
PostgrestDeleteReturningBuilder,
|
|
1572
|
+
PostgrestDeleteRootBuilder,
|
|
1573
|
+
PostgrestInsertReturningBuilder,
|
|
1574
|
+
PostgrestInsertRootBuilder,
|
|
1138
1575
|
PostgrestSelectBuilder,
|
|
1139
1576
|
PostgrestTableApi,
|
|
1140
|
-
|
|
1577
|
+
PostgrestUpdateReturningBuilder,
|
|
1578
|
+
PostgrestUpdateRootBuilder,
|
|
1579
|
+
PostgrestUpsertReturningBuilder,
|
|
1580
|
+
PostgrestUpsertRootBuilder,
|
|
1141
1581
|
Ragable,
|
|
1142
1582
|
RagableBrowser,
|
|
1143
1583
|
RagableBrowserAgentsClient,
|