@ragable/sdk 0.4.2 → 0.5.0

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.js CHANGED
@@ -23,11 +23,16 @@ 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
- PostgrestDeleteBuilder: () => PostgrestDeleteBuilder,
27
- PostgrestInsertBuilder: () => PostgrestInsertBuilder,
26
+ PostgrestDeleteReturningBuilder: () => PostgrestDeleteReturningBuilder,
27
+ PostgrestDeleteRootBuilder: () => PostgrestDeleteRootBuilder,
28
+ PostgrestInsertReturningBuilder: () => PostgrestInsertReturningBuilder,
29
+ PostgrestInsertRootBuilder: () => PostgrestInsertRootBuilder,
28
30
  PostgrestSelectBuilder: () => PostgrestSelectBuilder,
29
31
  PostgrestTableApi: () => PostgrestTableApi,
30
- PostgrestUpdateBuilder: () => PostgrestUpdateBuilder,
32
+ PostgrestUpdateReturningBuilder: () => PostgrestUpdateReturningBuilder,
33
+ PostgrestUpdateRootBuilder: () => PostgrestUpdateRootBuilder,
34
+ PostgrestUpsertReturningBuilder: () => PostgrestUpsertReturningBuilder,
35
+ PostgrestUpsertRootBuilder: () => PostgrestUpsertRootBuilder,
31
36
  Ragable: () => Ragable,
32
37
  RagableBrowser: () => RagableBrowser,
33
38
  RagableBrowserAgentsClient: () => RagableBrowserAgentsClient,
@@ -407,6 +412,18 @@ function quoteIdent(name) {
407
412
  assertIdent(name, "column");
408
413
  return `"${name}"`;
409
414
  }
415
+ function parseConflictColumns(onConflict) {
416
+ const parts = onConflict.split(",").map((s) => s.trim()).filter(Boolean);
417
+ if (parts.length === 0) {
418
+ throw new RagableError(
419
+ "upsert requires onConflict with at least one column (e.g. 'id' or 'org_id,user_id')",
420
+ 400,
421
+ null
422
+ );
423
+ }
424
+ for (const p of parts) assertIdent(p, "onConflict");
425
+ return parts;
426
+ }
410
427
  var OP_SQL = {
411
428
  eq: "=",
412
429
  neq: "<>",
@@ -489,7 +506,6 @@ var PostgrestSelectBuilder = class {
489
506
  this._order = { column, ascending: options?.ascending !== false };
490
507
  return this;
491
508
  }
492
- /** @param includeUserLimit when false, omit `.limit()` (for `.single()` / `.maybeSingle()`). */
493
509
  buildSelectCore(params, includeUserLimit) {
494
510
  const tbl = quoteIdent(this.table);
495
511
  const { clause } = buildWhere(this.filters, params);
@@ -529,12 +545,7 @@ var PostgrestSelectBuilder = class {
529
545
  params,
530
546
  readOnly: true
531
547
  });
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) {
548
+ if (res.rows.length === 0 || res.rows.length > 1) {
538
549
  throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
539
550
  code: "PGRST116"
540
551
  });
@@ -562,23 +573,70 @@ var PostgrestSelectBuilder = class {
562
573
  });
563
574
  }
564
575
  };
565
- var PostgrestInsertBuilder = class {
576
+ var PostgrestInsertRootBuilder = class {
566
577
  constructor(run, databaseInstanceId, table, rows) {
567
578
  this.run = run;
568
579
  this.databaseInstanceId = databaseInstanceId;
569
580
  this.table = table;
570
581
  this.rows = rows;
571
- __publicField(this, "returning", "*");
572
582
  assertIdent(table, "table");
573
583
  }
584
+ /**
585
+ * Return inserted rows (Supabase: chain `.select()` to get data).
586
+ * @see https://supabase.com/docs/reference/javascript/insert
587
+ */
574
588
  select(columns = "*") {
575
- this.returning = columns;
576
- return this;
589
+ return new PostgrestInsertReturningBuilder(
590
+ this.run,
591
+ this.databaseInstanceId,
592
+ this.table,
593
+ this.rows,
594
+ columns
595
+ );
596
+ }
597
+ then(onfulfilled, onrejected) {
598
+ return this.executeNoReturn().then(onfulfilled, onrejected);
599
+ }
600
+ async executeNoReturn() {
601
+ return asPostgrestResponse(async () => {
602
+ if (this.rows.length === 0) return null;
603
+ const keys = Object.keys(this.rows[0]);
604
+ for (const k of keys) assertIdent(k, "column");
605
+ const tbl = quoteIdent(this.table);
606
+ const params = [];
607
+ const valueGroups = [];
608
+ for (const row of this.rows) {
609
+ const placeholders = [];
610
+ for (const k of keys) {
611
+ params.push(row[k]);
612
+ placeholders.push(`$${params.length}`);
613
+ }
614
+ valueGroups.push(`(${placeholders.join(", ")})`);
615
+ }
616
+ const cols = keys.map(quoteIdent).join(", ");
617
+ const sql = `INSERT INTO ${tbl} (${cols}) VALUES ${valueGroups.join(", ")}`;
618
+ await this.run({
619
+ databaseInstanceId: this.databaseInstanceId,
620
+ sql,
621
+ params,
622
+ readOnly: false
623
+ });
624
+ return null;
625
+ });
626
+ }
627
+ };
628
+ var PostgrestInsertReturningBuilder = class {
629
+ constructor(run, databaseInstanceId, table, rows, returning) {
630
+ this.run = run;
631
+ this.databaseInstanceId = databaseInstanceId;
632
+ this.table = table;
633
+ this.rows = rows;
634
+ this.returning = returning;
577
635
  }
578
636
  then(onfulfilled, onrejected) {
579
- return this.execute().then(onfulfilled, onrejected);
637
+ return this.executeMany().then(onfulfilled, onrejected);
580
638
  }
581
- async execute() {
639
+ async executeMany() {
582
640
  return asPostgrestResponse(async () => {
583
641
  if (this.rows.length === 0) return [];
584
642
  const keys = Object.keys(this.rows[0]);
@@ -605,29 +663,137 @@ var PostgrestInsertBuilder = class {
605
663
  return res.rows;
606
664
  });
607
665
  }
666
+ async single() {
667
+ return asPostgrestResponse(async () => {
668
+ const { data, error } = await this.executeMany();
669
+ if (error) throw error;
670
+ const rows = data ?? [];
671
+ if (rows.length === 0 || rows.length > 1) {
672
+ throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
673
+ code: "PGRST116"
674
+ });
675
+ }
676
+ return rows[0];
677
+ });
678
+ }
679
+ async maybeSingle() {
680
+ return asPostgrestResponse(async () => {
681
+ const { data, error } = await this.executeMany();
682
+ if (error) throw error;
683
+ const rows = data ?? [];
684
+ if (rows.length > 1) {
685
+ throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
686
+ code: "PGRST116"
687
+ });
688
+ }
689
+ return rows[0] ?? null;
690
+ });
691
+ }
608
692
  };
609
- var PostgrestUpdateBuilder = class {
693
+ var PostgrestUpdateRootBuilder = class {
610
694
  constructor(run, databaseInstanceId, table, patch) {
611
695
  this.run = run;
612
696
  this.databaseInstanceId = databaseInstanceId;
613
697
  this.table = table;
614
698
  this.patch = patch;
615
699
  __publicField(this, "filters", []);
616
- __publicField(this, "returning", "*");
617
700
  assertIdent(table, "table");
618
701
  }
619
702
  eq(column, value) {
620
703
  this.filters.push({ op: "eq", column, value });
621
704
  return this;
622
705
  }
623
- select(columns = "*") {
624
- this.returning = columns;
706
+ neq(column, value) {
707
+ this.filters.push({ op: "neq", column, value });
625
708
  return this;
626
709
  }
710
+ gt(column, value) {
711
+ this.filters.push({ op: "gt", column, value });
712
+ return this;
713
+ }
714
+ gte(column, value) {
715
+ this.filters.push({ op: "gte", column, value });
716
+ return this;
717
+ }
718
+ lt(column, value) {
719
+ this.filters.push({ op: "lt", column, value });
720
+ return this;
721
+ }
722
+ lte(column, value) {
723
+ this.filters.push({ op: "lte", column, value });
724
+ return this;
725
+ }
726
+ like(column, value) {
727
+ this.filters.push({ op: "like", column, value });
728
+ return this;
729
+ }
730
+ ilike(column, value) {
731
+ this.filters.push({ op: "ilike", column, value });
732
+ return this;
733
+ }
734
+ /**
735
+ * Return updated rows (Supabase: `.update().eq().select()`).
736
+ * @see https://supabase.com/docs/reference/javascript/update
737
+ */
738
+ select(columns = "*") {
739
+ return new PostgrestUpdateReturningBuilder(
740
+ this.run,
741
+ this.databaseInstanceId,
742
+ this.table,
743
+ this.patch,
744
+ this.filters,
745
+ columns
746
+ );
747
+ }
627
748
  then(onfulfilled, onrejected) {
628
- return this.execute().then(onfulfilled, onrejected);
749
+ return this.executeNoReturn().then(onfulfilled, onrejected);
629
750
  }
630
- async execute() {
751
+ async executeNoReturn() {
752
+ return asPostgrestResponse(async () => {
753
+ const keys = Object.keys(this.patch);
754
+ if (keys.length === 0) {
755
+ throw new RagableError("Empty update payload", 400, null);
756
+ }
757
+ for (const k of keys) assertIdent(k, "column");
758
+ if (this.filters.length === 0) {
759
+ throw new RagableError(
760
+ "UPDATE requires a filter (e.g. .eq('id', value)) \u2014 refusing unscoped update",
761
+ 400,
762
+ null
763
+ );
764
+ }
765
+ const params = [];
766
+ const sets = [];
767
+ for (const k of keys) {
768
+ params.push(this.patch[k]);
769
+ sets.push(`${quoteIdent(k)} = $${params.length}`);
770
+ }
771
+ const { clause } = buildWhere(this.filters, params);
772
+ const tbl = quoteIdent(this.table);
773
+ const sql = `UPDATE ${tbl} SET ${sets.join(", ")}${clause}`;
774
+ await this.run({
775
+ databaseInstanceId: this.databaseInstanceId,
776
+ sql,
777
+ params,
778
+ readOnly: false
779
+ });
780
+ return null;
781
+ });
782
+ }
783
+ };
784
+ var PostgrestUpdateReturningBuilder = class {
785
+ constructor(run, databaseInstanceId, table, patch, filters, returning) {
786
+ this.run = run;
787
+ this.databaseInstanceId = databaseInstanceId;
788
+ this.table = table;
789
+ this.patch = patch;
790
+ this.filters = filters;
791
+ this.returning = returning;
792
+ }
793
+ then(onfulfilled, onrejected) {
794
+ return this.executeMany().then(onfulfilled, onrejected);
795
+ }
796
+ async executeMany() {
631
797
  return asPostgrestResponse(async () => {
632
798
  const keys = Object.keys(this.patch);
633
799
  if (keys.length === 0) {
@@ -659,28 +825,124 @@ var PostgrestUpdateBuilder = class {
659
825
  return res.rows;
660
826
  });
661
827
  }
828
+ async single() {
829
+ return asPostgrestResponse(async () => {
830
+ const { data, error } = await this.executeMany();
831
+ if (error) throw error;
832
+ const rows = data ?? [];
833
+ if (rows.length === 0 || rows.length > 1) {
834
+ throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
835
+ code: "PGRST116"
836
+ });
837
+ }
838
+ return rows[0];
839
+ });
840
+ }
841
+ async maybeSingle() {
842
+ return asPostgrestResponse(async () => {
843
+ const { data, error } = await this.executeMany();
844
+ if (error) throw error;
845
+ const rows = data ?? [];
846
+ if (rows.length > 1) {
847
+ throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
848
+ code: "PGRST116"
849
+ });
850
+ }
851
+ return rows[0] ?? null;
852
+ });
853
+ }
662
854
  };
663
- var PostgrestDeleteBuilder = class {
855
+ var PostgrestDeleteRootBuilder = class {
664
856
  constructor(run, databaseInstanceId, table) {
665
857
  this.run = run;
666
858
  this.databaseInstanceId = databaseInstanceId;
667
859
  this.table = table;
668
860
  __publicField(this, "filters", []);
669
- __publicField(this, "returning", "*");
670
861
  assertIdent(table, "table");
671
862
  }
672
863
  eq(column, value) {
673
864
  this.filters.push({ op: "eq", column, value });
674
865
  return this;
675
866
  }
676
- select(columns = "*") {
677
- this.returning = columns;
867
+ neq(column, value) {
868
+ this.filters.push({ op: "neq", column, value });
869
+ return this;
870
+ }
871
+ gt(column, value) {
872
+ this.filters.push({ op: "gt", column, value });
873
+ return this;
874
+ }
875
+ gte(column, value) {
876
+ this.filters.push({ op: "gte", column, value });
678
877
  return this;
679
878
  }
879
+ lt(column, value) {
880
+ this.filters.push({ op: "lt", column, value });
881
+ return this;
882
+ }
883
+ lte(column, value) {
884
+ this.filters.push({ op: "lte", column, value });
885
+ return this;
886
+ }
887
+ like(column, value) {
888
+ this.filters.push({ op: "like", column, value });
889
+ return this;
890
+ }
891
+ ilike(column, value) {
892
+ this.filters.push({ op: "ilike", column, value });
893
+ return this;
894
+ }
895
+ /**
896
+ * Return deleted rows (Supabase: `.delete().eq().select()`).
897
+ * @see https://supabase.com/docs/reference/javascript/delete
898
+ */
899
+ select(columns = "*") {
900
+ return new PostgrestDeleteReturningBuilder(
901
+ this.run,
902
+ this.databaseInstanceId,
903
+ this.table,
904
+ this.filters,
905
+ columns
906
+ );
907
+ }
680
908
  then(onfulfilled, onrejected) {
681
- return this.execute().then(onfulfilled, onrejected);
909
+ return this.executeNoReturn().then(onfulfilled, onrejected);
682
910
  }
683
- async execute() {
911
+ async executeNoReturn() {
912
+ return asPostgrestResponse(async () => {
913
+ if (this.filters.length === 0) {
914
+ throw new RagableError(
915
+ "DELETE requires a filter (e.g. .eq('id', value)) \u2014 refusing unscoped delete",
916
+ 400,
917
+ null
918
+ );
919
+ }
920
+ const params = [];
921
+ const { clause } = buildWhere(this.filters, params);
922
+ const tbl = quoteIdent(this.table);
923
+ const sql = `DELETE FROM ${tbl}${clause}`;
924
+ await this.run({
925
+ databaseInstanceId: this.databaseInstanceId,
926
+ sql,
927
+ params,
928
+ readOnly: false
929
+ });
930
+ return null;
931
+ });
932
+ }
933
+ };
934
+ var PostgrestDeleteReturningBuilder = class {
935
+ constructor(run, databaseInstanceId, table, filters, returning) {
936
+ this.run = run;
937
+ this.databaseInstanceId = databaseInstanceId;
938
+ this.table = table;
939
+ this.filters = filters;
940
+ this.returning = returning;
941
+ }
942
+ then(onfulfilled, onrejected) {
943
+ return this.executeMany().then(onfulfilled, onrejected);
944
+ }
945
+ async executeMany() {
684
946
  return asPostgrestResponse(async () => {
685
947
  if (this.filters.length === 0) {
686
948
  throw new RagableError(
@@ -702,6 +964,145 @@ var PostgrestDeleteBuilder = class {
702
964
  return res.rows;
703
965
  });
704
966
  }
967
+ async single() {
968
+ return asPostgrestResponse(async () => {
969
+ const { data, error } = await this.executeMany();
970
+ if (error) throw error;
971
+ const rows = data ?? [];
972
+ if (rows.length === 0 || rows.length > 1) {
973
+ throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
974
+ code: "PGRST116"
975
+ });
976
+ }
977
+ return rows[0];
978
+ });
979
+ }
980
+ async maybeSingle() {
981
+ return asPostgrestResponse(async () => {
982
+ const { data, error } = await this.executeMany();
983
+ if (error) throw error;
984
+ const rows = data ?? [];
985
+ if (rows.length > 1) {
986
+ throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
987
+ code: "PGRST116"
988
+ });
989
+ }
990
+ return rows[0] ?? null;
991
+ });
992
+ }
993
+ };
994
+ var PostgrestUpsertRootBuilder = class {
995
+ constructor(run, databaseInstanceId, table, rows, onConflict, ignoreDuplicates) {
996
+ this.run = run;
997
+ this.databaseInstanceId = databaseInstanceId;
998
+ this.table = table;
999
+ this.rows = rows;
1000
+ this.ignoreDuplicates = ignoreDuplicates;
1001
+ __publicField(this, "conflictCols");
1002
+ assertIdent(table, "table");
1003
+ this.conflictCols = parseConflictColumns(onConflict);
1004
+ }
1005
+ /**
1006
+ * Return upserted rows (Supabase: `.upsert().select()`).
1007
+ * @see https://supabase.com/docs/reference/javascript/upsert
1008
+ */
1009
+ select(columns = "*") {
1010
+ return new PostgrestUpsertReturningBuilder(this, columns);
1011
+ }
1012
+ then(onfulfilled, onrejected) {
1013
+ return this.executeNoReturn().then(onfulfilled, onrejected);
1014
+ }
1015
+ async executeNoReturn() {
1016
+ return asPostgrestResponse(async () => {
1017
+ await this.runUpsert(null);
1018
+ return null;
1019
+ });
1020
+ }
1021
+ async runUpsert(returning) {
1022
+ if (this.rows.length === 0) {
1023
+ return { command: "INSERT", rowCount: 0, truncated: false, rows: [] };
1024
+ }
1025
+ const keys = Object.keys(this.rows[0]);
1026
+ for (const k of keys) assertIdent(k, "column");
1027
+ const tbl = quoteIdent(this.table);
1028
+ const conflictQuoted = this.conflictCols.map(quoteIdent).join(", ");
1029
+ const params = [];
1030
+ const valueGroups = [];
1031
+ for (const row of this.rows) {
1032
+ const placeholders = [];
1033
+ for (const k of keys) {
1034
+ params.push(row[k]);
1035
+ placeholders.push(`$${params.length}`);
1036
+ }
1037
+ valueGroups.push(`(${placeholders.join(", ")})`);
1038
+ }
1039
+ const cols = keys.map(quoteIdent).join(", ");
1040
+ let sql = `INSERT INTO ${tbl} (${cols}) VALUES ${valueGroups.join(", ")} ON CONFLICT (${conflictQuoted})`;
1041
+ if (this.ignoreDuplicates) {
1042
+ sql += " DO NOTHING";
1043
+ } else {
1044
+ const setParts = keys.filter((k) => !this.conflictCols.includes(k)).map((k) => `${quoteIdent(k)} = EXCLUDED.${quoteIdent(k)}`);
1045
+ if (setParts.length === 0) {
1046
+ sql += " DO NOTHING";
1047
+ } else {
1048
+ sql += ` DO UPDATE SET ${setParts.join(", ")}`;
1049
+ }
1050
+ }
1051
+ if (returning) {
1052
+ sql += ` RETURNING ${returning}`;
1053
+ }
1054
+ return this.run({
1055
+ databaseInstanceId: this.databaseInstanceId,
1056
+ sql,
1057
+ params,
1058
+ readOnly: false
1059
+ });
1060
+ }
1061
+ /** Used by returning builder */
1062
+ async runWithReturning(returning) {
1063
+ return this.runUpsert(returning);
1064
+ }
1065
+ };
1066
+ var PostgrestUpsertReturningBuilder = class {
1067
+ constructor(root, returning) {
1068
+ this.root = root;
1069
+ this.returning = returning;
1070
+ }
1071
+ then(onfulfilled, onrejected) {
1072
+ return this.executeMany().then(onfulfilled, onrejected);
1073
+ }
1074
+ async executeMany() {
1075
+ return asPostgrestResponse(async () => {
1076
+ const res = await this.root.runWithReturning(this.returning);
1077
+ return res.rows;
1078
+ });
1079
+ }
1080
+ async single() {
1081
+ return asPostgrestResponse(async () => {
1082
+ const { data, error } = await this.executeMany();
1083
+ if (error) throw error;
1084
+ const rows = data ?? [];
1085
+ if (rows.length === 0 || rows.length > 1) {
1086
+ throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
1087
+ code: "PGRST116"
1088
+ });
1089
+ }
1090
+ return rows[0];
1091
+ });
1092
+ }
1093
+ async maybeSingle() {
1094
+ return asPostgrestResponse(async () => {
1095
+ const { data, error } = await this.executeMany();
1096
+ if (error) throw error;
1097
+ const rows = data ?? [];
1098
+ if (rows.length > 1) {
1099
+ throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
1100
+ code: "PGRST116"
1101
+ });
1102
+ }
1103
+ return rows[0] ?? null;
1104
+ });
1105
+ }
705
1106
  };
706
1107
  var PostgrestTableApi = class {
707
1108
  constructor(run, databaseInstanceId, table) {
@@ -719,7 +1120,7 @@ var PostgrestTableApi = class {
719
1120
  }
720
1121
  insert(values) {
721
1122
  const rows = Array.isArray(values) ? values : [values];
722
- return new PostgrestInsertBuilder(
1123
+ return new PostgrestInsertRootBuilder(
723
1124
  this.run,
724
1125
  this.databaseInstanceId,
725
1126
  this.table,
@@ -727,7 +1128,7 @@ var PostgrestTableApi = class {
727
1128
  );
728
1129
  }
729
1130
  update(patch) {
730
- return new PostgrestUpdateBuilder(
1131
+ return new PostgrestUpdateRootBuilder(
731
1132
  this.run,
732
1133
  this.databaseInstanceId,
733
1134
  this.table,
@@ -735,12 +1136,27 @@ var PostgrestTableApi = class {
735
1136
  );
736
1137
  }
737
1138
  delete() {
738
- return new PostgrestDeleteBuilder(
1139
+ return new PostgrestDeleteRootBuilder(
739
1140
  this.run,
740
1141
  this.databaseInstanceId,
741
1142
  this.table
742
1143
  );
743
1144
  }
1145
+ /**
1146
+ * `INSERT ... ON CONFLICT ... DO UPDATE` (or `DO NOTHING` with `ignoreDuplicates`).
1147
+ * @see https://supabase.com/docs/reference/javascript/upsert
1148
+ */
1149
+ upsert(values, options) {
1150
+ const rows = Array.isArray(values) ? values : [values];
1151
+ return new PostgrestUpsertRootBuilder(
1152
+ this.run,
1153
+ this.databaseInstanceId,
1154
+ this.table,
1155
+ rows,
1156
+ options.onConflict,
1157
+ options.ignoreDuplicates === true
1158
+ );
1159
+ }
744
1160
  };
745
1161
 
746
1162
  // src/browser.ts
@@ -1133,11 +1549,16 @@ function createRagableServerClient(options) {
1133
1549
  // Annotate the CommonJS export names for ESM import in node:
1134
1550
  0 && (module.exports = {
1135
1551
  AgentsClient,
1136
- PostgrestDeleteBuilder,
1137
- PostgrestInsertBuilder,
1552
+ PostgrestDeleteReturningBuilder,
1553
+ PostgrestDeleteRootBuilder,
1554
+ PostgrestInsertReturningBuilder,
1555
+ PostgrestInsertRootBuilder,
1138
1556
  PostgrestSelectBuilder,
1139
1557
  PostgrestTableApi,
1140
- PostgrestUpdateBuilder,
1558
+ PostgrestUpdateReturningBuilder,
1559
+ PostgrestUpdateRootBuilder,
1560
+ PostgrestUpsertReturningBuilder,
1561
+ PostgrestUpsertRootBuilder,
1141
1562
  Ragable,
1142
1563
  RagableBrowser,
1143
1564
  RagableBrowserAgentsClient,