@centia-io/sdk 0.0.28 → 0.0.30

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.
@@ -198,6 +198,9 @@ var Gc2Service = class {
198
198
  isPasswordFlowOptions(options) {
199
199
  return "username" in options;
200
200
  }
201
+ isSignUpOptions(options) {
202
+ return "parentDb" in options;
203
+ }
201
204
  buildUrl(path) {
202
205
  if (path.startsWith("http://") || path.startsWith("https://")) return path;
203
206
  return `${this.host}${path}`;
@@ -262,6 +265,15 @@ var Gc2Service = class {
262
265
  if (this.options.scope) params.set("scope", this.options.scope);
263
266
  return `${base}?${params.toString()}`;
264
267
  }
268
+ getSignUpURL() {
269
+ if (!this.isSignUpOptions(this.options)) throw new Error("CodeFlow options required for this operation");
270
+ const base = this.options.authUri ?? `${this.host}/signup/`;
271
+ const params = new URLSearchParams();
272
+ params.set("client_id", this.options.clientId);
273
+ params.set("parentdb", this.options.parentDb);
274
+ params.set("redirect_uri", this.options.redirectUri);
275
+ return `${base}?${params.toString()}`;
276
+ }
265
277
  async getAuthorizationCodeToken(code, codeVerifier) {
266
278
  let redirectUri;
267
279
  if (this.isCodeFlowOptions(this.options)) redirectUri = this.options.redirectUri;
@@ -501,17 +513,21 @@ var Users = class {
501
513
  var Ws = class {
502
514
  constructor(options) {
503
515
  this.options = options;
516
+ this.options.wsClient = this.options?.wsClient ?? WebSocket;
504
517
  }
505
518
  connect() {
506
519
  const me = this;
507
520
  const { accessToken } = getTokens();
508
521
  const connect = () => {
509
- const ws = new WebSocket(this.options.host + `/?token=` + accessToken);
522
+ let queryString = `?token=` + accessToken;
523
+ if (this.options?.rel) queryString = queryString + `&rel=` + this.options.rel;
524
+ const WSClass = this.options.wsClient;
525
+ const ws = new WSClass(this.options.host + `/` + queryString);
510
526
  ws.onopen = function() {
511
527
  console.log("WebSocket connected!");
512
528
  };
513
529
  ws.onmessage = function(event) {
514
- me.options?.callBack(event.data);
530
+ me.options.callBack(event.data);
515
531
  };
516
532
  ws.onclose = function(event) {
517
533
  if (accessToken !== "") {
@@ -555,23 +571,835 @@ var Tables = class {
555
571
 
556
572
  //#endregion
557
573
  //#region src/Api.ts
558
- async function dispatch(name, args) {
574
+ function isPlainObject$1(v) {
575
+ return typeof v === "object" && v !== null && !Array.isArray(v);
576
+ }
577
+ function validateParamsForMethod(method, params) {
578
+ if (Array.isArray(params)) {
579
+ const badIndex = params.findIndex((p) => !isPlainObject$1(p));
580
+ if (badIndex !== -1) throw new TypeError(`createApi: Invalid argument at index ${badIndex} for RPC method "${method}". Expected a plain object.`);
581
+ return params;
582
+ }
583
+ if (params === void 0) return {};
584
+ if (!isPlainObject$1(params)) throw new TypeError(`createApi: Invalid argument for RPC method "${method}". Expected a plain object.`);
585
+ return params;
586
+ }
587
+ function extractDataFromResponse(method, res) {
588
+ if (!res || typeof res !== "object") throw new TypeError(`createApi: Invalid RPC response for method "${method}". Expected an object.`);
589
+ if (res.jsonrpc !== "2.0") throw new TypeError(`createApi: Invalid RPC response for method "${method}". Missing or invalid jsonrpc version.`);
590
+ const err = res.error;
591
+ if (err !== void 0) {
592
+ if (!err || typeof err !== "object") throw new TypeError(`createApi: Invalid RPC error for method "${method}". Expected 'error' to be an object.`);
593
+ const code = err.code;
594
+ const message = err.message;
595
+ const data$1 = err.data;
596
+ const codeIsNum = typeof code === "number" && Number.isFinite(code);
597
+ const details = typeof message === "string" && message.length > 0 ? message : "Unknown error";
598
+ const e = /* @__PURE__ */ new Error(`createApi: RPC error for method "${method}"${codeIsNum ? ` (${code})` : ""}: ${details}`);
599
+ e.code = code;
600
+ if (data$1 !== void 0) e.data = data$1;
601
+ e.method = method;
602
+ e.name = "JsonRpcError";
603
+ throw e;
604
+ }
605
+ const result = res.result;
606
+ if (!result || typeof result !== "object") throw new TypeError(`createApi: Invalid RPC response for method "${method}". Missing result object.`);
607
+ const data = result.data;
608
+ if (!Array.isArray(data)) throw new TypeError(`createApi: Invalid RPC response for method "${method}". Expected result.data to be an array.`);
609
+ return data;
610
+ }
611
+ async function dispatch(name, paramsLike) {
612
+ if (typeof name !== "string" || name.length === 0) throw new TypeError("createApi: RPC method name must be a non-empty string.");
613
+ const params = validateParamsForMethod(String(name), paramsLike);
559
614
  const rpc = new Rpc();
560
615
  const request = {
561
616
  jsonrpc: "2.0",
562
617
  method: name,
563
618
  id: 1,
564
- params: args
619
+ params
565
620
  };
566
- return (await rpc.call(request)).result.data;
621
+ const res = await rpc.call(request);
622
+ return extractDataFromResponse(String(name), res);
567
623
  }
568
624
  function createApi() {
569
625
  return new Proxy({}, { get(_target, prop) {
570
626
  if (typeof prop !== "string") return void 0;
571
- return (...args) => dispatch(prop, ...args);
627
+ return (...args) => {
628
+ return dispatch(prop, args.length === 0 ? {} : args.length === 1 ? args[0] : args);
629
+ };
572
630
  } });
573
631
  }
574
632
 
575
633
  //#endregion
576
- export { Claims, CodeFlow, Meta, PasswordFlow, Rpc, Sql, Stats, Status, Tables, Users, Ws, createApi };
634
+ //#region src/SignUp.ts
635
+ var SignUp = class {
636
+ constructor(options) {
637
+ this.options = options;
638
+ this.service = new Gc2Service(options);
639
+ }
640
+ async signUp() {
641
+ window.location = this.service.getSignUpURL();
642
+ }
643
+ };
644
+
645
+ //#endregion
646
+ //#region src/SqlBuilder.ts
647
+ function findTable(schema, name) {
648
+ const tbl = schema.tables.find((t) => t.name === name);
649
+ if (!tbl) throw new Error(`Table not found in schema: ${name}`);
650
+ return tbl;
651
+ }
652
+ function findColumn(table, name) {
653
+ const col = table.columns.find((c) => c.name === name);
654
+ if (!col) throw new Error(`Column not found in table ${table.name}: ${name}`);
655
+ return col;
656
+ }
657
+ function getPrimaryKeyColumns(table) {
658
+ const pk = (table.constraints || []).find((c) => c.constraint === "primary" && Array.isArray(c.columns) && c.columns.length > 0);
659
+ return pk ? pk.columns.map(String) : [];
660
+ }
661
+ function typeNameToHint(typname, isArray) {
662
+ if (!typname) return void 0;
663
+ const base = typname;
664
+ return isArray ? base + "[]" : base;
665
+ }
666
+ function addTypeHintForParam(typeHints, paramName, col, value) {
667
+ let isArr = col._is_array;
668
+ if (Array.isArray(value)) if (isArrayShapedGeomTypename(col._typname)) isArr = value.every(Array.isArray);
669
+ else isArr = true;
670
+ const hint = typeNameToHint(col._typname, isArr);
671
+ if (hint) typeHints[paramName] = hint;
672
+ }
673
+ function expectedScalarKind(typname) {
674
+ const t = typname.toLowerCase();
675
+ if (t === "int2" || t === "int4" || t === "int8" || t === "float4" || t === "float8") return "number";
676
+ if (t === "numeric" || t === "decimal") return "string";
677
+ if (t === "varchar" || t === "text" || t === "bpchar" || t === "char" || t === "date" || t === "time" || t === "timetz" || t === "timestamp" || t === "timestamptz") return "string";
678
+ if (t === "bool") return "boolean";
679
+ if (t === "json" || t === "jsonb") return "json";
680
+ if (t === "int4range" || t === "int8range" || t === "numrange" || t === "tsrange" || t === "tstzrange" || t === "daterange") return "range";
681
+ if (t === "interval") return "interval";
682
+ if (t === "point" || t === "line" || t === "lseg" || t === "box" || t === "path" || t === "polygon" || t === "circle") return "geom";
683
+ return "unknown";
684
+ }
685
+ function isArrayShapedGeomTypename(typname) {
686
+ const t = typname.toLowerCase();
687
+ return t === "path" || t === "polygon";
688
+ }
689
+ function isArrayShapedGeomScalarValue(col, value) {
690
+ if (!Array.isArray(value)) return false;
691
+ if (!isArrayShapedGeomTypename(col._typname)) return false;
692
+ return !value.every(Array.isArray);
693
+ }
694
+ function expectedRangeInnerKind(typname) {
695
+ const t = typname.toLowerCase();
696
+ if (t === "int4range" || t === "int8range") return "number";
697
+ if (t === "numrange" || t === "tsrange" || t === "tstzrange" || t === "daterange") return "string";
698
+ return "unknown";
699
+ }
700
+ function isPlainObject(v) {
701
+ return typeof v === "object" && v !== null && !Array.isArray(v);
702
+ }
703
+ function isFiniteNumber(n) {
704
+ return typeof n === "number" && Number.isFinite(n);
705
+ }
706
+ function isPointLike(v) {
707
+ if (!isPlainObject(v)) return false;
708
+ const x = v.x;
709
+ const y = v.y;
710
+ return isFiniteNumber(x) && isFiniteNumber(y);
711
+ }
712
+ function validateGeometryForColumn(col, value, context) {
713
+ const t = col._typname.toLowerCase();
714
+ if (t === "point") {
715
+ if (!isPointLike(value)) throw new Error(`Invalid value for ${context}. Expected Point { x: number, y: number }`);
716
+ return;
717
+ }
718
+ if (t === "line") {
719
+ if (!isPlainObject(value)) throw new Error(`Invalid value for ${context}. Expected Line { A: number, B: number, C: number }`);
720
+ const A = value.A, B = value.B, C = value.C;
721
+ if (!isFiniteNumber(A) || !isFiniteNumber(B) || !isFiniteNumber(C)) throw new Error(`Invalid Line for ${context}. A, B, C must be finite numbers`);
722
+ return;
723
+ }
724
+ if (t === "lseg" || t === "box") {
725
+ if (!isPlainObject(value)) throw new Error(`Invalid value for ${context}. Expected ${t.toUpperCase()} { start: Point, end: Point }`);
726
+ const start = value.start;
727
+ const end = value.end;
728
+ if (!isPointLike(start) || !isPointLike(end)) throw new Error(`Invalid ${t} for ${context}. 'start' and 'end' must be Point { x, y }`);
729
+ return;
730
+ }
731
+ if (t === "path") {
732
+ if (!Array.isArray(value) || value.length < 1) throw new Error(`Invalid value for ${context}. Expected Path [isClosed: boolean, ...points: Point[]]`);
733
+ const [isClosed, ...points] = value;
734
+ if (typeof isClosed !== "boolean") throw new Error(`Invalid Path for ${context}. First element must be boolean (isClosed)`);
735
+ for (let i = 0; i < points.length; i++) if (!isPointLike(points[i])) throw new Error(`Invalid Path for ${context}. Element at index ${i + 1} must be Point { x, y }`);
736
+ return;
737
+ }
738
+ if (t === "polygon") {
739
+ if (!Array.isArray(value)) throw new Error(`Invalid value for ${context}. Expected Polygon as Point[]`);
740
+ for (let i = 0; i < value.length; i++) if (!isPointLike(value[i])) throw new Error(`Invalid Polygon for ${context}. Element at index ${i} must be Point { x, y }`);
741
+ return;
742
+ }
743
+ if (t === "circle") {
744
+ if (!isPlainObject(value)) throw new Error(`Invalid value for ${context}. Expected Circle { center: Point, radius: number }`);
745
+ const center = value.center;
746
+ const radius = value.radius;
747
+ if (!isPointLike(center) || !isFiniteNumber(radius)) throw new Error(`Invalid Circle for ${context}. 'center' must be Point and 'radius' must be finite number`);
748
+ return;
749
+ }
750
+ }
751
+ function validateRangeForColumn(col, value, context) {
752
+ if (!isPlainObject(value)) throw new Error(`Invalid value for ${context}. Expected a range object for type ${col._typname}`);
753
+ const r = value;
754
+ const hasLower = Object.prototype.hasOwnProperty.call(r, "lower");
755
+ const hasUpper = Object.prototype.hasOwnProperty.call(r, "upper");
756
+ const hasLi = Object.prototype.hasOwnProperty.call(r, "lowerInclusive");
757
+ const hasUi = Object.prototype.hasOwnProperty.call(r, "upperInclusive");
758
+ if (!hasLower || !hasUpper || !hasLi || !hasUi) throw new Error(`Invalid range for ${context}. Required properties: lower, upper, lowerInclusive, upperInclusive`);
759
+ if (typeof r.lowerInclusive !== "boolean" || typeof r.upperInclusive !== "boolean") throw new Error(`Invalid range for ${context}. lowerInclusive and upperInclusive must be boolean`);
760
+ const inner = expectedRangeInnerKind(col._typname);
761
+ if (inner === "number") {
762
+ if (typeof r.lower !== "number" || !Number.isFinite(r.lower)) throw new Error(`Invalid range.lower for ${context}. Expected number for type ${col._typname}`);
763
+ if (typeof r.upper !== "number" || !Number.isFinite(r.upper)) throw new Error(`Invalid range.upper for ${context}. Expected number for type ${col._typname}`);
764
+ } else if (inner === "string") {
765
+ if (typeof r.lower !== "string") throw new Error(`Invalid range.lower for ${context}. Expected string for type ${col._typname}`);
766
+ if (typeof r.upper !== "string") throw new Error(`Invalid range.upper for ${context}. Expected string for type ${col._typname}`);
767
+ }
768
+ }
769
+ function validateIntervalForColumn(col, value, context) {
770
+ if (!isPlainObject(value)) throw new Error(`Invalid value for ${context}. Expected an interval object for type ${col._typname}`);
771
+ const v = value;
772
+ for (const k of [
773
+ "y",
774
+ "m",
775
+ "d",
776
+ "h",
777
+ "i",
778
+ "s"
779
+ ]) {
780
+ if (!Object.prototype.hasOwnProperty.call(v, k)) throw new Error(`Invalid interval for ${context}. Missing property '${k}'`);
781
+ const num = v[k];
782
+ if (typeof num !== "number" || !Number.isFinite(num)) throw new Error(`Invalid interval.${String(k)} for ${context}. Expected finite number`);
783
+ }
784
+ }
785
+ function isValidJsonLike(value) {
786
+ return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "object" && value !== null;
787
+ }
788
+ function validateScalarForColumn(col, value, context) {
789
+ const kind = expectedScalarKind(col._typname);
790
+ if (kind === "unknown") return;
791
+ if (kind === "number") {
792
+ if (typeof value !== "number" || !Number.isFinite(value)) throw new Error(`Invalid value for ${context}. Expected number for type ${col._typname}, got ${typeof value}`);
793
+ return;
794
+ }
795
+ if (kind === "string") {
796
+ if (typeof value !== "string") throw new Error(`Invalid value for ${context}. Expected string for type ${col._typname}, got ${typeof value}`);
797
+ return;
798
+ }
799
+ if (kind === "boolean") {
800
+ if (typeof value !== "boolean") throw new Error(`Invalid value for ${context}. Expected boolean for type ${col._typname}, got ${typeof value}`);
801
+ return;
802
+ }
803
+ if (kind === "json") {
804
+ if (!isValidJsonLike(value)) throw new Error(`Invalid value for ${context}. Expected JSON-compatible value for type ${col._typname}`);
805
+ return;
806
+ }
807
+ if (kind === "range") {
808
+ validateRangeForColumn(col, value, context);
809
+ return;
810
+ }
811
+ if (kind === "interval") {
812
+ validateIntervalForColumn(col, value, context);
813
+ return;
814
+ }
815
+ if (kind === "geom") {
816
+ validateGeometryForColumn(col, value, context);
817
+ return;
818
+ }
819
+ }
820
+ function validateComparisonValue(col, key, value, op) {
821
+ if (value === void 0 || value === null) throw new Error(`Operator ${op} on column ${key} requires a non-null value. Use isnull/notnull for null checks.`);
822
+ if (col._is_array) {
823
+ if (!Array.isArray(value)) throw new Error(`Operator ${op} on array column ${key} requires an array value`);
824
+ for (const [i, v] of value.entries()) validateScalarForColumn(col, v, `column ${key}[${i}]`);
825
+ } else {
826
+ if (Array.isArray(value) && !isArrayShapedGeomScalarValue(col, value)) throw new Error(`Operator ${op} on scalar column ${key} cannot accept an array value`);
827
+ validateScalarForColumn(col, value, `column ${key}`);
828
+ }
829
+ }
830
+ function validateInArrayValues(col, key, values, op) {
831
+ if (!col._is_array) {
832
+ let idx = 0;
833
+ for (const v of values) {
834
+ validateScalarForColumn(col, v, `column ${key} (element ${idx})`);
835
+ idx++;
836
+ }
837
+ }
838
+ }
839
+ function findJoinOn(base, target) {
840
+ const bc = base.constraints || [];
841
+ const tc = target.constraints || [];
842
+ for (const c of bc) if (c.constraint === "foreign" && c.referenced_table === target.name && c.columns?.length && c.referenced_columns?.length && c.columns.length === c.referenced_columns.length) return c.columns.map((col, i) => ({
843
+ left: String(col),
844
+ right: String(c.referenced_columns[i])
845
+ }));
846
+ for (const c of tc) if (c.constraint === "foreign" && c.referenced_table === base.name && c.columns?.length && c.referenced_columns?.length && c.columns.length === c.referenced_columns.length) return c.referenced_columns.map((rcol, i) => ({
847
+ left: String(rcol),
848
+ right: String(c.columns[i])
849
+ }));
850
+ return null;
851
+ }
852
+ var TableQueryImpl = class {
853
+ constructor(schema, tableName) {
854
+ this.schema = schema;
855
+ this.table = findTable(schema, tableName);
856
+ }
857
+ select(cols) {
858
+ const table = this.table;
859
+ const schema = this.schema;
860
+ const selected = cols && cols.length ? cols : ["*"];
861
+ const state = {
862
+ table,
863
+ selected,
864
+ where: {},
865
+ orWhereGroups: [],
866
+ andOps: [],
867
+ orOpGroups: [],
868
+ order: [],
869
+ limit: void 0,
870
+ offset: void 0,
871
+ joins: [],
872
+ joinSelections: []
873
+ };
874
+ return new class {
875
+ constructor() {
876
+ this.s = state;
877
+ this.toSql = () => {
878
+ const params = {};
879
+ const type_hints = {};
880
+ let p = 0;
881
+ const parts = [];
882
+ const selectParts = [];
883
+ if (selected.length === 1 && selected[0] === "*") selectParts.push(`"${table.name}".*`);
884
+ else {
885
+ const sel = selected;
886
+ for (const c of sel) findColumn(table, String(c));
887
+ selectParts.push(sel.map((c) => `"${table.name}"."${c}"`).join(", "));
888
+ }
889
+ for (const js of state.joinSelections) if (js.selected.length === 1 && js.selected[0] === "*") selectParts.push(`"${js.target.name}".*`);
890
+ else {
891
+ const cols$1 = js.selected;
892
+ for (const c of cols$1) findColumn(js.target, String(c));
893
+ selectParts.push(cols$1.map((c) => `"${js.target.name}"."${c}"`).join(", "));
894
+ }
895
+ parts.push(`select ${selectParts.join(", ")} from "${schema.name}"."${table.name}"`);
896
+ for (const j of state.joins) {
897
+ const onExpr = j.on.map((p$1) => `"${table.name}"."${p$1.left}" = "${j.target.name}"."${p$1.right}"`).join(" and ");
898
+ parts.push(`${j.type} join "${schema.name}"."${j.target.name}" on ${onExpr}`);
899
+ }
900
+ const andParts = [];
901
+ for (const key in state.where) {
902
+ const value = state.where[key];
903
+ const col = findColumn(table, key);
904
+ p += 1;
905
+ const paramName = `${table.name}_${key}_${p}`;
906
+ if (value === null) {
907
+ if (!col.is_nullable) throw new Error(`Column ${table.name}.${key} is not nullable; cannot compare to null`);
908
+ andParts.push(`"${table.name}"."${key}" is null`);
909
+ } else if (Array.isArray(value) && !isArrayShapedGeomScalarValue(col, value)) {
910
+ validateInArrayValues(col, key, value, "in");
911
+ andParts.push(`"${table.name}"."${key}" = ANY(:${paramName})`);
912
+ params[paramName] = value;
913
+ addTypeHintForParam(type_hints, paramName, col, value);
914
+ } else {
915
+ validateScalarForColumn(col, value, `column ${key}`);
916
+ andParts.push(`"${table.name}"."${key}" = :${paramName}`);
917
+ params[paramName] = value;
918
+ addTypeHintForParam(type_hints, paramName, col, value);
919
+ }
920
+ }
921
+ for (const pred of state.andOps) {
922
+ const key = String(pred.col);
923
+ const op = String(pred.op);
924
+ const col = findColumn(table, key);
925
+ const qualified = `"${table.name}"."${key}"`;
926
+ if (op === "isnull" || op === "notnull") {
927
+ if (pred.value !== void 0) throw new Error(`Operator ${op} does not take a value for column ${key}`);
928
+ andParts.push(`${qualified} is ${op === "isnull" ? "null" : "not null"}`);
929
+ } else if (op === "in" || op === "notin") {
930
+ const val = pred.value;
931
+ if (!Array.isArray(val)) throw new Error(`Operator ${op} requires an array value for column ${key}`);
932
+ validateInArrayValues(col, key, val, op);
933
+ p += 1;
934
+ const paramName = `${table.name}_${key}_${p}`;
935
+ andParts.push(`${qualified} ${op === "in" ? "= ANY" : "!= ALL"}(:${paramName})`);
936
+ params[paramName] = val;
937
+ addTypeHintForParam(type_hints, paramName, col, val);
938
+ } else if (op === "like" || op === "ilike" || op === "notlike" || op === "notilike") {
939
+ const val = pred.value;
940
+ if (typeof val !== "string") throw new Error(`Operator ${op} requires a string value for column ${key}`);
941
+ p += 1;
942
+ const paramName = `${table.name}_${key}_${p}`;
943
+ const sqlOp = op === "like" ? "like" : op === "ilike" ? "ilike" : op === "notlike" ? "not like" : "not ilike";
944
+ andParts.push(`${qualified} ${sqlOp} :${paramName}`);
945
+ params[paramName] = val;
946
+ addTypeHintForParam(type_hints, paramName, col, val);
947
+ } else {
948
+ const val = pred.value;
949
+ if (val === void 0) throw new Error(`Operator ${op} requires a value for column ${key}`);
950
+ validateComparisonValue(col, key, val, op);
951
+ p += 1;
952
+ const paramName = `${table.name}_${key}_${p}`;
953
+ if (op === "=") andParts.push(`${qualified} = :${paramName}`);
954
+ else if (op === "!=") andParts.push(`${qualified} <> :${paramName}`);
955
+ else if (op === "<" || op === "<=" || op === ">" || op === ">=") andParts.push(`${qualified} ${op} :${paramName}`);
956
+ else throw new Error(`Unsupported operator: ${op}`);
957
+ params[paramName] = val;
958
+ addTypeHintForParam(type_hints, paramName, col, val);
959
+ }
960
+ }
961
+ const orGroupSql = [];
962
+ for (const group of state.orWhereGroups) {
963
+ const orParts = [];
964
+ for (const key in group) {
965
+ const value = group[key];
966
+ const col = findColumn(table, key);
967
+ p += 1;
968
+ const paramName = `${table.name}_${key}_${p}`;
969
+ if (value === null) {
970
+ if (!col.is_nullable) throw new Error(`Column ${table.name}.${key} is not nullable; cannot compare to null`);
971
+ orParts.push(`"${table.name}"."${key}" is null`);
972
+ } else if (Array.isArray(value) && !isArrayShapedGeomScalarValue(col, value)) {
973
+ validateInArrayValues(col, key, value, "in");
974
+ orParts.push(`"${table.name}"."${key}" = ANY(:${paramName})`);
975
+ params[paramName] = value;
976
+ addTypeHintForParam(type_hints, paramName, col, value);
977
+ } else {
978
+ validateScalarForColumn(col, value, `column ${key}`);
979
+ orParts.push(`"${table.name}"."${key}" = :${paramName}`);
980
+ params[paramName] = value;
981
+ addTypeHintForParam(type_hints, paramName, col, value);
982
+ }
983
+ }
984
+ if (orParts.length) orGroupSql.push("(" + orParts.join(" or ") + ")");
985
+ }
986
+ for (const group of state.orOpGroups) {
987
+ const orParts = [];
988
+ for (const pred of group) {
989
+ const key = String(pred.col);
990
+ const op = String(pred.op);
991
+ const col = findColumn(table, key);
992
+ const qualified = `"${table.name}"."${key}"`;
993
+ if (op === "isnull" || op === "notnull") {
994
+ if (pred.value !== void 0) throw new Error(`Operator ${op} does not take a value for column ${key}`);
995
+ orParts.push(`${qualified} is ${op === "isnull" ? "null" : "not null"}`);
996
+ } else if (op === "in" || op === "notin") {
997
+ const val = pred.value;
998
+ if (!Array.isArray(val)) throw new Error(`Operator ${op} requires an array value for column ${key}`);
999
+ validateInArrayValues(col, key, val, op);
1000
+ p += 1;
1001
+ const paramName = `${table.name}_${key}_${p}`;
1002
+ orParts.push(`${qualified} ${op === "in" ? "= ANY" : "!= ALL"}(:${paramName})`);
1003
+ params[paramName] = val;
1004
+ addTypeHintForParam(type_hints, paramName, col, val);
1005
+ } else if (op === "like" || op === "ilike" || op === "notlike" || op === "notilike") {
1006
+ const val = pred.value;
1007
+ if (typeof val !== "string") throw new Error(`Operator ${op} requires a string value for column ${key}`);
1008
+ p += 1;
1009
+ const paramName = `${table.name}_${key}_${p}`;
1010
+ const sqlOp = op === "like" ? "like" : op === "ilike" ? "ilike" : op === "notlike" ? "not like" : "not ilike";
1011
+ orParts.push(`${qualified} ${sqlOp} :${paramName}`);
1012
+ params[paramName] = val;
1013
+ addTypeHintForParam(type_hints, paramName, col, val);
1014
+ } else {
1015
+ const val = pred.value;
1016
+ if (val === void 0) throw new Error(`Operator ${op} requires a value for column ${key}`);
1017
+ validateComparisonValue(col, key, val, op);
1018
+ p += 1;
1019
+ const paramName = `${table.name}_${key}_${p}`;
1020
+ if (op === "=") orParts.push(`${qualified} = :${paramName}`);
1021
+ else if (op === "!=") orParts.push(`${qualified} <> :${paramName}`);
1022
+ else if (op === "<" || op === "<=" || op === ">" || op === ">=") orParts.push(`${qualified} ${op} :${paramName}`);
1023
+ else throw new Error(`Unsupported operator: ${op}`);
1024
+ params[paramName] = val;
1025
+ addTypeHintForParam(type_hints, paramName, col, val);
1026
+ }
1027
+ }
1028
+ if (orParts.length) orGroupSql.push("(" + orParts.join(" or ") + ")");
1029
+ }
1030
+ if (orGroupSql.length) {
1031
+ const andSql = andParts.length ? `(${andParts.join(" and ")})` : "";
1032
+ const orSql = orGroupSql.join(" or ");
1033
+ const full = andSql ? `${andSql} or ${orSql}` : orSql;
1034
+ if (full.trim().length) parts.push("where " + full);
1035
+ } else if (andParts.length) parts.push("where " + andParts.join(" and "));
1036
+ if (state.order.length) {
1037
+ const orders = [];
1038
+ for (const o of state.order) orders.push(`"${table.name}"."${o.col}" ${o.dir}`);
1039
+ parts.push("order by " + orders.join(", "));
1040
+ }
1041
+ if (state.limit !== void 0) parts.push("limit " + state.limit);
1042
+ if (state.offset !== void 0) parts.push("offset " + state.offset);
1043
+ return {
1044
+ q: parts.join(" "),
1045
+ params,
1046
+ type_hints: Object.keys(type_hints).length ? type_hints : void 0
1047
+ };
1048
+ };
1049
+ }
1050
+ selectFrom(tableName, cols$1) {
1051
+ const jtName = String(tableName);
1052
+ const join = this.s.joins.find((j) => j.target.name === jtName);
1053
+ if (!join) throw new Error(`selectFrom('${jtName}') requires a prior join('${jtName}') call`);
1054
+ const sel = !cols$1 || cols$1.length === 0 ? ["*"] : cols$1.map(String);
1055
+ if (!(sel.length === 1 && sel[0] === "*")) for (const c of sel) findColumn(join.target, String(c));
1056
+ const existing = this.s.joinSelections.find((js) => js.target.name === jtName);
1057
+ if (existing) {
1058
+ if (existing.selected.includes("*")) return this;
1059
+ if (sel.length === 1 && sel[0] === "*") existing.selected = ["*"];
1060
+ else {
1061
+ const set = new Set(existing.selected);
1062
+ for (const c of sel) set.add(String(c));
1063
+ existing.selected = Array.from(set);
1064
+ }
1065
+ } else this.s.joinSelections.push({
1066
+ target: join.target,
1067
+ selected: sel
1068
+ });
1069
+ return this;
1070
+ }
1071
+ andWhere(where) {
1072
+ for (const k in where) this.s.where[k] = where[k];
1073
+ return this;
1074
+ }
1075
+ /** @deprecated Use andWhere() instead */
1076
+ where(where) {
1077
+ return this.andWhere(where);
1078
+ }
1079
+ orWhere(where) {
1080
+ this.s.orWhereGroups.push(where);
1081
+ return this;
1082
+ }
1083
+ wherePk(pk) {
1084
+ const pkCols = getPrimaryKeyColumns(table);
1085
+ if (!pkCols || pkCols.length === 0) throw new Error(`Table ${table.name} does not have a primary key`);
1086
+ if (pkCols.length === 1) {
1087
+ const colName = pkCols[0];
1088
+ const colDef = findColumn(table, colName);
1089
+ if (pk === null || pk === void 0) throw new Error(`wherePk on ${table.name} requires a non-null value for primary key column ${colName}`);
1090
+ if (Array.isArray(pk)) throw new Error(`wherePk on ${table.name} expects a scalar for primary key column ${colName}, not an array`);
1091
+ if (isPlainObject(pk)) throw new Error(`wherePk on ${table.name} expects a scalar for primary key column ${colName}`);
1092
+ validateScalarForColumn(colDef, pk, `primary key ${table.name}.${colName}`);
1093
+ this.s.where[colName] = pk;
1094
+ return this;
1095
+ } else {
1096
+ if (!isPlainObject(pk) || pk === null) throw new Error(`wherePk on ${table.name} requires an object with keys: ${pkCols.join(", ")}`);
1097
+ const obj = pk;
1098
+ for (const k of Object.keys(obj)) if (!pkCols.includes(k)) throw new Error(`wherePk received unknown key '${k}'. Expected keys: ${pkCols.join(", ")}`);
1099
+ for (const colName of pkCols) {
1100
+ if (!(colName in obj)) throw new Error(`wherePk missing key '${colName}'. Required keys: ${pkCols.join(", ")}`);
1101
+ const v = obj[colName];
1102
+ if (v === null || v === void 0) throw new Error(`wherePk on ${table.name} requires non-null values for all primary key columns (${pkCols.join(", ")})`);
1103
+ if (Array.isArray(v)) throw new Error(`wherePk on ${table.name} expects scalar values for primary key column ${colName}, not an array`);
1104
+ validateScalarForColumn(findColumn(table, colName), v, `primary key ${table.name}.${colName}`);
1105
+ this.s.where[colName] = v;
1106
+ }
1107
+ return this;
1108
+ }
1109
+ }
1110
+ andWhereOp(col, op, ...args) {
1111
+ const value = args[0];
1112
+ this.s.andOps.push({
1113
+ col,
1114
+ op,
1115
+ value
1116
+ });
1117
+ return this;
1118
+ }
1119
+ orWhereOp(col, op, ...args) {
1120
+ const value = args[0];
1121
+ this.s.orOpGroups.push([{
1122
+ col,
1123
+ op,
1124
+ value
1125
+ }]);
1126
+ return this;
1127
+ }
1128
+ andWhereOpGroup(predicates) {
1129
+ const group = predicates.map((p) => ({
1130
+ col: p[0],
1131
+ op: p[1],
1132
+ value: p[2]
1133
+ }));
1134
+ for (const g of group) this.s.andOps.push(g);
1135
+ return this;
1136
+ }
1137
+ orWhereOpGroup(predicates) {
1138
+ const group = predicates.map((p) => ({
1139
+ col: p[0],
1140
+ op: p[1],
1141
+ value: p[2]
1142
+ }));
1143
+ this.s.orOpGroups.push(group);
1144
+ return this;
1145
+ }
1146
+ orderBy(order) {
1147
+ this.s.order = [];
1148
+ const isValidDir = (d) => d === "asc" || d === "desc";
1149
+ if (typeof order === "string") {
1150
+ findColumn(table, String(order));
1151
+ this.s.order.push({
1152
+ col: order,
1153
+ dir: "asc"
1154
+ });
1155
+ } else for (const item of order) {
1156
+ const col = String(item[0]);
1157
+ const dir = String(item[1]);
1158
+ findColumn(table, col);
1159
+ if (!isValidDir(dir)) throw new Error(`Invalid order direction: ${dir}. Allowed: asc | desc`);
1160
+ this.s.order.push({
1161
+ col: item[0],
1162
+ dir
1163
+ });
1164
+ }
1165
+ return this;
1166
+ }
1167
+ limit(n) {
1168
+ if (typeof n !== "number" || !Number.isFinite(n) || !Number.isInteger(n) || n < 0) throw new Error(`Invalid limit: ${n}. Limit must be a non-negative integer`);
1169
+ this.s.limit = n;
1170
+ return this;
1171
+ }
1172
+ offset(n) {
1173
+ if (typeof n !== "number" || !Number.isFinite(n) || !Number.isInteger(n) || n < 0) throw new Error(`Invalid offset: ${n}. Offset must be a non-negative integer`);
1174
+ this.s.offset = n;
1175
+ return this;
1176
+ }
1177
+ join(tableName, type = "inner") {
1178
+ const target = findTable(schema, String(tableName));
1179
+ const pairs = findJoinOn(table, target);
1180
+ if (!pairs || !pairs.length) throw new Error(`No foreign key relation found between ${table.name} and ${target.name}`);
1181
+ const jt = String(type);
1182
+ if (jt !== "inner" && jt !== "left" && jt !== "right" && jt !== "full") throw new Error(`Invalid join type: ${jt}. Allowed: inner | left | right | full`);
1183
+ this.s.joins.push({
1184
+ type: jt,
1185
+ target,
1186
+ on: pairs
1187
+ });
1188
+ return this;
1189
+ }
1190
+ }();
1191
+ }
1192
+ insert(values) {
1193
+ const table = this.table;
1194
+ const schema = this.schema;
1195
+ const state = {
1196
+ values,
1197
+ returning: []
1198
+ };
1199
+ return new class {
1200
+ constructor() {
1201
+ this.returning = (cols) => {
1202
+ state.returning = cols || [];
1203
+ return this;
1204
+ };
1205
+ this.toSql = () => {
1206
+ const cols = [];
1207
+ const vals = [];
1208
+ const params = {};
1209
+ const type_hints = {};
1210
+ let p = 0;
1211
+ for (const key in state.values) {
1212
+ const value = state.values[key];
1213
+ const col = findColumn(table, key);
1214
+ p += 1;
1215
+ const paramName = `${table.name}_${key}_${p}`;
1216
+ cols.push(`"${key}"`);
1217
+ vals.push(`:${paramName}`);
1218
+ params[paramName] = value;
1219
+ addTypeHintForParam(type_hints, paramName, col, value);
1220
+ }
1221
+ const parts = [];
1222
+ parts.push(`insert into "${schema.name}"."${table.name}" (${cols.join(", ")}) values (${vals.join(", ")})`);
1223
+ if (state.returning.length) parts.push("returning " + state.returning.join(", "));
1224
+ return {
1225
+ q: parts.join(" "),
1226
+ params,
1227
+ type_hints: Object.keys(type_hints).length ? type_hints : void 0
1228
+ };
1229
+ };
1230
+ }
1231
+ }();
1232
+ }
1233
+ update(values) {
1234
+ const table = this.table;
1235
+ const schema = this.schema;
1236
+ const state = {
1237
+ values,
1238
+ where: {},
1239
+ returning: []
1240
+ };
1241
+ return new class {
1242
+ constructor() {
1243
+ this.where = (w) => {
1244
+ for (const k in w) state.where[k] = w[k];
1245
+ return this;
1246
+ };
1247
+ this.wherePk = (pk) => {
1248
+ const pkCols = getPrimaryKeyColumns(table);
1249
+ if (!pkCols || pkCols.length === 0) throw new Error(`Table ${table.name} does not have a primary key`);
1250
+ if (pkCols.length === 1) {
1251
+ const colName = pkCols[0];
1252
+ const colDef = findColumn(table, colName);
1253
+ if (pk === null || pk === void 0) throw new Error(`wherePk on ${table.name} requires a non-null value for primary key column ${colName}`);
1254
+ if (Array.isArray(pk)) throw new Error(`wherePk on ${table.name} expects a scalar for primary key column ${colName}, not an array`);
1255
+ if (isPlainObject(pk)) throw new Error(`wherePk on ${table.name} expects a scalar for primary key column ${colName}`);
1256
+ validateScalarForColumn(colDef, pk, `primary key ${table.name}.${colName}`);
1257
+ state.where[colName] = pk;
1258
+ } else {
1259
+ if (!isPlainObject(pk) || pk === null) throw new Error(`wherePk on ${table.name} requires an object with keys: ${pkCols.join(", ")}`);
1260
+ const obj = pk;
1261
+ for (const k of Object.keys(obj)) if (!pkCols.includes(k)) throw new Error(`wherePk received unknown key '${k}'. Expected keys: ${pkCols.join(", ")}`);
1262
+ for (const colName of pkCols) {
1263
+ if (!(colName in obj)) throw new Error(`wherePk missing key '${colName}'. Required keys: ${pkCols.join(", ")}`);
1264
+ const v = obj[colName];
1265
+ if (v === null || v === void 0) throw new Error(`wherePk on ${table.name} requires non-null values for all primary key columns (${pkCols.join(", ")})`);
1266
+ if (Array.isArray(v)) throw new Error(`wherePk on ${table.name} expects scalar values for primary key column ${colName}, not an array`);
1267
+ validateScalarForColumn(findColumn(table, colName), v, `primary key ${table.name}.${colName}`);
1268
+ state.where[colName] = v;
1269
+ }
1270
+ }
1271
+ return this;
1272
+ };
1273
+ this.returning = (cols) => {
1274
+ state.returning = cols || [];
1275
+ return this;
1276
+ };
1277
+ this.toSql = () => {
1278
+ const params = {};
1279
+ const type_hints = {};
1280
+ let p = 0;
1281
+ const setParts = [];
1282
+ for (const key in state.values) {
1283
+ const value = state.values[key];
1284
+ const col = findColumn(table, key);
1285
+ p += 1;
1286
+ const paramName = `${table.name}_${key}_${p}`;
1287
+ setParts.push(`"${key}" = :${paramName}`);
1288
+ params[paramName] = value;
1289
+ addTypeHintForParam(type_hints, paramName, col, value);
1290
+ }
1291
+ const whereClauses = [];
1292
+ for (const key in state.where) {
1293
+ const value = state.where[key];
1294
+ const col = findColumn(table, key);
1295
+ p += 1;
1296
+ const paramName = `${table.name}_${key}_${p}`;
1297
+ if (value === null) {
1298
+ if (!col.is_nullable) throw new Error(`Column ${table.name}.${key} is not nullable; cannot compare to null`);
1299
+ whereClauses.push(`"${key}" is null`);
1300
+ } else if (Array.isArray(value) && !isArrayShapedGeomScalarValue(col, value)) {
1301
+ validateInArrayValues(col, key, value, "in");
1302
+ whereClauses.push(`"${key}" = ANY(:${paramName})`);
1303
+ params[paramName] = value;
1304
+ addTypeHintForParam(type_hints, paramName, col, value);
1305
+ } else {
1306
+ validateScalarForColumn(col, value, `column ${key}`);
1307
+ whereClauses.push(`"${key}" = :${paramName}`);
1308
+ params[paramName] = value;
1309
+ addTypeHintForParam(type_hints, paramName, col, value);
1310
+ }
1311
+ }
1312
+ const parts = [];
1313
+ parts.push(`update "${schema.name}"."${table.name}" set ${setParts.join(", ")}`);
1314
+ if (whereClauses.length) parts.push("where " + whereClauses.join(" and "));
1315
+ if (state.returning.length) parts.push("returning " + state.returning.join(", "));
1316
+ return {
1317
+ q: parts.join(" "),
1318
+ params,
1319
+ type_hints: Object.keys(type_hints).length ? type_hints : void 0
1320
+ };
1321
+ };
1322
+ }
1323
+ }();
1324
+ }
1325
+ delete() {
1326
+ const table = this.table;
1327
+ const schema = this.schema;
1328
+ const state = {
1329
+ where: {},
1330
+ returning: []
1331
+ };
1332
+ return new class {
1333
+ constructor() {
1334
+ this.where = (w) => {
1335
+ for (const k in w) state.where[k] = w[k];
1336
+ return this;
1337
+ };
1338
+ this.wherePk = (pk) => {
1339
+ const pkCols = getPrimaryKeyColumns(table);
1340
+ if (!pkCols || pkCols.length === 0) throw new Error(`Table ${table.name} does not have a primary key`);
1341
+ if (pkCols.length === 1) {
1342
+ const col = pkCols[0];
1343
+ if (isPlainObject(pk)) throw new Error(`wherePk on ${table.name} expects a scalar for primary key column ${col}`);
1344
+ state.where[col] = pk;
1345
+ } else {
1346
+ if (!isPlainObject(pk)) throw new Error(`wherePk on ${table.name} requires an object with keys: ${pkCols.join(", ")}`);
1347
+ const obj = pk;
1348
+ for (const k of Object.keys(obj)) if (!pkCols.includes(k)) throw new Error(`wherePk received unknown key '${k}'. Expected keys: ${pkCols.join(", ")}`);
1349
+ for (const col of pkCols) {
1350
+ if (!(col in obj)) throw new Error(`wherePk missing key '${col}'. Required keys: ${pkCols.join(", ")}`);
1351
+ state.where[col] = obj[col];
1352
+ }
1353
+ }
1354
+ return this;
1355
+ };
1356
+ this.returning = (cols) => {
1357
+ state.returning = cols || [];
1358
+ return this;
1359
+ };
1360
+ this.toSql = () => {
1361
+ const params = {};
1362
+ const type_hints = {};
1363
+ let p = 0;
1364
+ const whereClauses = [];
1365
+ for (const key in state.where) {
1366
+ const value = state.where[key];
1367
+ const col = findColumn(table, key);
1368
+ p += 1;
1369
+ const paramName = `${table.name}_${key}_${p}`;
1370
+ if (value === null) {
1371
+ if (!col.is_nullable) throw new Error(`Column ${table.name}.${key} is not nullable; cannot compare to null`);
1372
+ whereClauses.push(`"${key}" is null`);
1373
+ } else if (Array.isArray(value)) {
1374
+ validateInArrayValues(col, key, value, "in");
1375
+ whereClauses.push(`"${key}" = ANY(:${paramName})`);
1376
+ params[paramName] = value;
1377
+ addTypeHintForParam(type_hints, paramName, col, value);
1378
+ } else {
1379
+ validateScalarForColumn(col, value, `column ${key}`);
1380
+ whereClauses.push(`"${key}" = :${paramName}`);
1381
+ params[paramName] = value;
1382
+ addTypeHintForParam(type_hints, paramName, col, value);
1383
+ }
1384
+ }
1385
+ const parts = [];
1386
+ parts.push(`delete from "${schema.name}"."${table.name}"`);
1387
+ if (whereClauses.length) parts.push("where " + whereClauses.join(" and "));
1388
+ if (state.returning.length) parts.push("returning " + state.returning.join(", "));
1389
+ return {
1390
+ q: parts.join(" "),
1391
+ params,
1392
+ type_hints: Object.keys(type_hints).length ? type_hints : void 0
1393
+ };
1394
+ };
1395
+ }
1396
+ }();
1397
+ }
1398
+ };
1399
+ function createSqlBuilder(schema) {
1400
+ return { table: (name) => new TableQueryImpl(schema, String(name)) };
1401
+ }
1402
+
1403
+ //#endregion
1404
+ export { Claims, CodeFlow, Meta, PasswordFlow, Rpc, SignUp, Sql, Stats, Status, Tables, Users, Ws, createApi, createSqlBuilder };
577
1405
  //# sourceMappingURL=centia-io-sdk.js.map