@centia-io/sdk 0.0.29 → 0.0.31

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