@zenstackhq/runtime 3.0.0-beta.4 → 3.0.0-beta.6

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.cjs CHANGED
@@ -37,19 +37,20 @@ __export(src_exports, {
37
37
  QueryError: () => QueryError,
38
38
  ZenStackClient: () => ZenStackClient,
39
39
  definePlugin: () => definePlugin,
40
- sql: () => import_kysely18.sql
40
+ sql: () => import_kysely19.sql
41
41
  });
42
42
  module.exports = __toCommonJS(src_exports);
43
43
 
44
44
  // src/client/client-impl.ts
45
- var import_common_helpers15 = require("@zenstackhq/common-helpers");
46
- var import_kysely17 = require("kysely");
45
+ var import_common_helpers16 = require("@zenstackhq/common-helpers");
46
+ var import_kysely18 = require("kysely");
47
47
 
48
48
  // src/client/crud/operations/aggregate.ts
49
- var import_kysely9 = require("kysely");
49
+ var import_kysely11 = require("kysely");
50
50
  var import_ts_pattern10 = require("ts-pattern");
51
51
 
52
52
  // src/client/query-utils.ts
53
+ var import_common_helpers = require("@zenstackhq/common-helpers");
53
54
  var import_ts_pattern = require("ts-pattern");
54
55
 
55
56
  // src/schema/expression.ts
@@ -228,10 +229,19 @@ function requireField(schema, modelOrType, field) {
228
229
  }
229
230
  __name(requireField, "requireField");
230
231
  function getIdFields(schema, model) {
231
- const modelDef = requireModel(schema, model);
232
+ const modelDef = getModel(schema, model);
232
233
  return modelDef?.idFields;
233
234
  }
234
235
  __name(getIdFields, "getIdFields");
236
+ function requireIdFields(schema, model) {
237
+ const modelDef = requireModel(schema, model);
238
+ const result = modelDef?.idFields;
239
+ if (!result) {
240
+ throw new InternalError(`Model "${model}" does not have ID field(s)`);
241
+ }
242
+ return result;
243
+ }
244
+ __name(requireIdFields, "requireIdFields");
235
245
  function getRelationForeignKeyFieldPairs(schema, model, relationField) {
236
246
  const fieldDef = requireField(schema, model, relationField);
237
247
  if (!fieldDef?.relation) {
@@ -345,7 +355,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias, inlineComp
345
355
  throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
346
356
  }
347
357
  return computer(eb, {
348
- currentModel: modelAlias
358
+ modelAlias
349
359
  });
350
360
  }
351
361
  }
@@ -380,7 +390,7 @@ function buildJoinPairs(schema, model, modelAlias, relationField, relationModelA
380
390
  }
381
391
  __name(buildJoinPairs, "buildJoinPairs");
382
392
  function makeDefaultOrderBy(schema, model) {
383
- const idFields = getIdFields(schema, model);
393
+ const idFields = requireIdFields(schema, model);
384
394
  return idFields.map((f) => ({
385
395
  [f]: "asc"
386
396
  }));
@@ -419,11 +429,17 @@ function getManyToManyRelation(schema, model, field) {
419
429
  "A"
420
430
  ];
421
431
  }
432
+ const modelIdFields = requireIdFields(schema, model);
433
+ (0, import_common_helpers.invariant)(modelIdFields.length === 1, "Only single-field ID is supported for many-to-many relation");
434
+ const otherIdFields = requireIdFields(schema, fieldDef.type);
435
+ (0, import_common_helpers.invariant)(otherIdFields.length === 1, "Only single-field ID is supported for many-to-many relation");
422
436
  return {
423
437
  parentFkName: orderedFK[0],
438
+ parentPKName: modelIdFields[0],
424
439
  otherModel: fieldDef.type,
425
440
  otherField: fieldDef.relation.opposite,
426
441
  otherFkName: orderedFK[1],
442
+ otherPKName: otherIdFields[0],
427
443
  joinTable: fieldDef.relation.name ? `_${fieldDef.relation.name}` : `_${sortedModelNames[0]}To${sortedModelNames[1]}`
428
444
  };
429
445
  } else {
@@ -462,7 +478,7 @@ function ensureArray(value) {
462
478
  }
463
479
  __name(ensureArray, "ensureArray");
464
480
  function extractIdFields(entity, schema, model) {
465
- const idFields = getIdFields(schema, model);
481
+ const idFields = requireIdFields(schema, model);
466
482
  return extractFields(entity, idFields);
467
483
  }
468
484
  __name(extractIdFields, "extractIdFields");
@@ -499,36 +515,95 @@ __name(aggregate, "aggregate");
499
515
 
500
516
  // src/client/crud/operations/base.ts
501
517
  var import_cuid2 = require("@paralleldrive/cuid2");
502
- var import_common_helpers8 = require("@zenstackhq/common-helpers");
503
- var import_kysely8 = require("kysely");
518
+ var import_common_helpers10 = require("@zenstackhq/common-helpers");
519
+ var import_kysely10 = require("kysely");
504
520
  var import_nanoid = require("nanoid");
505
521
  var import_ts_pattern9 = require("ts-pattern");
506
522
  var import_ulid = require("ulid");
507
523
  var uuid = __toESM(require("uuid"), 1);
508
524
 
509
525
  // src/plugins/policy/errors.ts
526
+ var RejectedByPolicyReason = /* @__PURE__ */ function(RejectedByPolicyReason2) {
527
+ RejectedByPolicyReason2["NO_ACCESS"] = "no-access";
528
+ RejectedByPolicyReason2["CANNOT_READ_BACK"] = "cannot-read-back";
529
+ RejectedByPolicyReason2["OTHER"] = "other";
530
+ return RejectedByPolicyReason2;
531
+ }({});
510
532
  var RejectedByPolicyError = class extends Error {
511
533
  static {
512
534
  __name(this, "RejectedByPolicyError");
513
535
  }
514
536
  model;
515
537
  reason;
516
- constructor(model, reason) {
517
- super(reason ?? `Operation rejected by policy${model ? ": " + model : ""}`), this.model = model, this.reason = reason;
538
+ constructor(model, reason = "no-access", message) {
539
+ super(message ?? `Operation rejected by policy${model ? ": " + model : ""}`), this.model = model, this.reason = reason;
518
540
  }
519
541
  };
520
542
 
543
+ // src/plugins/policy/functions.ts
544
+ var import_common_helpers8 = require("@zenstackhq/common-helpers");
545
+ var import_kysely9 = require("kysely");
546
+
547
+ // src/client/contract.ts
548
+ var TransactionIsolationLevel = /* @__PURE__ */ function(TransactionIsolationLevel2) {
549
+ TransactionIsolationLevel2["ReadUncommitted"] = "read uncommitted";
550
+ TransactionIsolationLevel2["ReadCommitted"] = "read committed";
551
+ TransactionIsolationLevel2["RepeatableRead"] = "repeatable read";
552
+ TransactionIsolationLevel2["Serializable"] = "serializable";
553
+ TransactionIsolationLevel2["Snapshot"] = "snapshot";
554
+ return TransactionIsolationLevel2;
555
+ }({});
556
+ var CRUD = [
557
+ "create",
558
+ "read",
559
+ "update",
560
+ "delete"
561
+ ];
562
+
563
+ // src/client/kysely-utils.ts
564
+ var import_kysely = require("kysely");
565
+ function stripAlias(node) {
566
+ if (import_kysely.AliasNode.is(node)) {
567
+ return {
568
+ alias: node.alias,
569
+ node: node.node
570
+ };
571
+ } else {
572
+ return {
573
+ alias: void 0,
574
+ node
575
+ };
576
+ }
577
+ }
578
+ __name(stripAlias, "stripAlias");
579
+ function extractModelName(node) {
580
+ const { node: innerNode } = stripAlias(node);
581
+ return import_kysely.TableNode.is(innerNode) ? innerNode.table.identifier.name : void 0;
582
+ }
583
+ __name(extractModelName, "extractModelName");
584
+ function extractFieldName(node) {
585
+ if (import_kysely.ReferenceNode.is(node) && import_kysely.ColumnNode.is(node.column)) {
586
+ return node.column.column.name;
587
+ } else if (import_kysely.ColumnNode.is(node)) {
588
+ return node.column.name;
589
+ } else {
590
+ return void 0;
591
+ }
592
+ }
593
+ __name(extractFieldName, "extractFieldName");
594
+
521
595
  // src/plugins/policy/policy-handler.ts
522
- var import_common_helpers6 = require("@zenstackhq/common-helpers");
523
- var import_kysely7 = require("kysely");
596
+ var import_common_helpers7 = require("@zenstackhq/common-helpers");
597
+ var import_kysely8 = require("kysely");
524
598
  var import_ts_pattern8 = require("ts-pattern");
525
599
 
526
600
  // src/client/crud/dialects/index.ts
527
601
  var import_ts_pattern5 = require("ts-pattern");
528
602
 
529
603
  // src/client/crud/dialects/postgresql.ts
530
- var import_common_helpers2 = require("@zenstackhq/common-helpers");
531
- var import_kysely2 = require("kysely");
604
+ var import_common_helpers3 = require("@zenstackhq/common-helpers");
605
+ var import_decimal = __toESM(require("decimal.js"), 1);
606
+ var import_kysely3 = require("kysely");
532
607
  var import_ts_pattern3 = require("ts-pattern");
533
608
 
534
609
  // src/client/constants.ts
@@ -553,8 +628,8 @@ var AGGREGATE_OPERATORS = [
553
628
  ];
554
629
 
555
630
  // src/client/crud/dialects/base-dialect.ts
556
- var import_common_helpers = require("@zenstackhq/common-helpers");
557
- var import_kysely = require("kysely");
631
+ var import_common_helpers2 = require("@zenstackhq/common-helpers");
632
+ var import_kysely2 = require("kysely");
558
633
  var import_ts_pattern2 = require("ts-pattern");
559
634
 
560
635
  // src/utils/enumerate.ts
@@ -585,6 +660,9 @@ var BaseCrudDialect = class {
585
660
  transformPrimitive(value, _type, _forArrayField) {
586
661
  return value;
587
662
  }
663
+ transformOutput(value, _type) {
664
+ return value;
665
+ }
588
666
  // #region common query builders
589
667
  buildSelectModel(eb, model, modelAlias) {
590
668
  const modelDef = requireModel(this.schema, model);
@@ -613,7 +691,7 @@ var BaseCrudDialect = class {
613
691
  if ("distinct" in args && args.distinct) {
614
692
  const distinct = ensureArray(args.distinct);
615
693
  if (this.supportsDistinctOn) {
616
- result = result.distinctOn(distinct.map((f) => import_kysely.sql.ref(`${modelAlias}.${f}`)));
694
+ result = result.distinctOn(distinct.map((f) => import_kysely2.sql.ref(`${modelAlias}.${f}`)));
617
695
  } else {
618
696
  throw new QueryError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
619
697
  }
@@ -663,7 +741,7 @@ var BaseCrudDialect = class {
663
741
  buildCursorFilter(model, query, cursor, orderBy, negateOrderBy, modelAlias) {
664
742
  const _orderBy = orderBy ?? makeDefaultOrderBy(this.schema, model);
665
743
  const orderByItems = ensureArray(_orderBy).flatMap((obj) => Object.entries(obj));
666
- const eb = (0, import_kysely.expressionBuilder)();
744
+ const eb = (0, import_kysely2.expressionBuilder)();
667
745
  const subQueryAlias = `${model}$cursor$sub`;
668
746
  const cursorFilter = this.buildFilter(eb, model, subQueryAlias, cursor);
669
747
  let result = query;
@@ -698,7 +776,7 @@ var BaseCrudDialect = class {
698
776
  if (payload === null) {
699
777
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
700
778
  if (ownedByModel && !fieldDef.originModel) {
701
- return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely.sql.ref(`${modelAlias}.${fk}`), "is", null)));
779
+ return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely2.sql.ref(`${modelAlias}.${fk}`), "is", null)));
702
780
  } else {
703
781
  return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
704
782
  is: null
@@ -715,7 +793,7 @@ var BaseCrudDialect = class {
715
793
  joinAlias
716
794
  );
717
795
  const filterResultField = `${field}$filter`;
718
- const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
796
+ const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
719
797
  const conditions = [];
720
798
  if ("is" in payload || "isNot" in payload) {
721
799
  if ("is" in payload) {
@@ -745,24 +823,26 @@ var BaseCrudDialect = class {
745
823
  }
746
824
  buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
747
825
  if (payload === null) {
748
- return eb(import_kysely.sql.ref(`${modelAlias}.${field}`), "is", null);
826
+ return eb(import_kysely2.sql.ref(`${modelAlias}.${field}`), "is", null);
749
827
  }
750
828
  const relationModel = fieldDef.type;
751
829
  const relationFilterSelectAlias = `${modelAlias}$${field}$filter`;
752
830
  const buildPkFkWhereRefs = /* @__PURE__ */ __name((eb2) => {
753
831
  const m2m = getManyToManyRelation(this.schema, model, field);
754
832
  if (m2m) {
755
- const modelIdField = getIdFields(this.schema, model)[0];
756
- const relationIdField = getIdFields(this.schema, relationModel)[0];
757
- return eb2(import_kysely.sql.ref(`${relationFilterSelectAlias}.${relationIdField}`), "in", eb2.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(import_kysely.sql.ref(`${m2m.joinTable}.${m2m.parentFkName}`), "=", import_kysely.sql.ref(`${modelAlias}.${modelIdField}`)));
833
+ const modelIdFields = requireIdFields(this.schema, model);
834
+ (0, import_common_helpers2.invariant)(modelIdFields.length === 1, "many-to-many relation must have exactly one id field");
835
+ const relationIdFields = requireIdFields(this.schema, relationModel);
836
+ (0, import_common_helpers2.invariant)(relationIdFields.length === 1, "many-to-many relation must have exactly one id field");
837
+ return eb2(import_kysely2.sql.ref(`${relationFilterSelectAlias}.${relationIdFields[0]}`), "in", eb2.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(import_kysely2.sql.ref(`${m2m.joinTable}.${m2m.parentFkName}`), "=", import_kysely2.sql.ref(`${modelAlias}.${modelIdFields[0]}`)));
758
838
  } else {
759
839
  const relationKeyPairs = getRelationForeignKeyFieldPairs(this.schema, model, field);
760
840
  let result2 = this.true(eb2);
761
841
  for (const { fk, pk } of relationKeyPairs.keyPairs) {
762
842
  if (relationKeyPairs.ownedByModel) {
763
- result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${modelAlias}.${fk}`), "=", import_kysely.sql.ref(`${relationFilterSelectAlias}.${pk}`)));
843
+ result2 = this.and(eb2, result2, eb2(import_kysely2.sql.ref(`${modelAlias}.${fk}`), "=", import_kysely2.sql.ref(`${relationFilterSelectAlias}.${pk}`)));
764
844
  } else {
765
- result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${modelAlias}.${pk}`), "=", import_kysely.sql.ref(`${relationFilterSelectAlias}.${fk}`)));
845
+ result2 = this.and(eb2, result2, eb2(import_kysely2.sql.ref(`${modelAlias}.${pk}`), "=", import_kysely2.sql.ref(`${relationFilterSelectAlias}.${fk}`)));
766
846
  }
767
847
  }
768
848
  return result2;
@@ -845,7 +925,7 @@ var BaseCrudDialect = class {
845
925
  return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
846
926
  }
847
927
  buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
848
- if (payload === null || !(0, import_common_helpers.isPlainObject)(payload)) {
928
+ if (payload === null || !(0, import_common_helpers2.isPlainObject)(payload)) {
849
929
  return {
850
930
  conditions: [
851
931
  this.buildLiteralFilter(eb, lhs, type, payload)
@@ -864,14 +944,14 @@ var BaseCrudDialect = class {
864
944
  }
865
945
  const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
866
946
  const condition = (0, import_ts_pattern2.match)(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
867
- (0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
947
+ (0, import_common_helpers2.invariant)(Array.isArray(rhs), "right hand side must be an array");
868
948
  if (rhs.length === 0) {
869
949
  return this.false(eb);
870
950
  } else {
871
951
  return eb(lhs, "in", rhs);
872
952
  }
873
953
  }).with("notIn", () => {
874
- (0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
954
+ (0, import_common_helpers2.invariant)(Array.isArray(rhs), "right hand side must be an array");
875
955
  if (rhs.length === 0) {
876
956
  return this.true(eb);
877
957
  } else {
@@ -911,7 +991,7 @@ var BaseCrudDialect = class {
911
991
  if (key === "mode" || consumedKeys.includes(key)) {
912
992
  continue;
913
993
  }
914
- const condition = (0, import_ts_pattern2.match)(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely.sql.val(`%${value}%`)) : eb(fieldRef, "like", import_kysely.sql.val(`%${value}%`))).with("startsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely.sql.val(`${value}%`)) : eb(fieldRef, "like", import_kysely.sql.val(`${value}%`))).with("endsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely.sql.val(`%${value}`)) : eb(fieldRef, "like", import_kysely.sql.val(`%${value}`))).otherwise(() => {
994
+ const condition = (0, import_ts_pattern2.match)(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely2.sql.val(`%${value}%`)) : eb(fieldRef, "like", import_kysely2.sql.val(`%${value}%`))).with("startsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely2.sql.val(`${value}%`)) : eb(fieldRef, "like", import_kysely2.sql.val(`${value}%`))).with("endsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely2.sql.val(`%${value}`)) : eb(fieldRef, "like", import_kysely2.sql.val(`%${value}`))).otherwise(() => {
915
995
  throw new QueryError(`Invalid string filter key: ${key}`);
916
996
  });
917
997
  if (condition) {
@@ -923,16 +1003,16 @@ var BaseCrudDialect = class {
923
1003
  }
924
1004
  prepStringCasing(eb, value, mode) {
925
1005
  if (!mode || mode === "default") {
926
- return value === null ? value : import_kysely.sql.val(value);
1006
+ return value === null ? value : import_kysely2.sql.val(value);
927
1007
  }
928
1008
  if (typeof value === "string") {
929
1009
  return eb.fn("lower", [
930
- import_kysely.sql.val(value)
1010
+ import_kysely2.sql.val(value)
931
1011
  ]);
932
1012
  } else if (Array.isArray(value)) {
933
1013
  return value.map((v) => this.prepStringCasing(eb, v, mode));
934
1014
  } else {
935
- return value === null ? null : import_kysely.sql.val(value);
1015
+ return value === null ? null : import_kysely2.sql.val(value);
936
1016
  }
937
1017
  }
938
1018
  buildNumberFilter(eb, fieldRef, type, payload) {
@@ -989,19 +1069,19 @@ var BaseCrudDialect = class {
989
1069
  "_min",
990
1070
  "_max"
991
1071
  ].includes(field)) {
992
- (0, import_common_helpers.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
1072
+ (0, import_common_helpers2.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
993
1073
  for (const [k, v] of Object.entries(value)) {
994
- (0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
995
- result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field), import_kysely.sql.raw(this.negateSort(v, negated)));
1074
+ (0, import_common_helpers2.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
1075
+ result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field), import_kysely2.sql.raw(this.negateSort(v, negated)));
996
1076
  }
997
1077
  continue;
998
1078
  }
999
1079
  switch (field) {
1000
1080
  case "_count": {
1001
- (0, import_common_helpers.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
1081
+ (0, import_common_helpers2.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
1002
1082
  for (const [k, v] of Object.entries(value)) {
1003
- (0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
1004
- result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), import_kysely.sql.raw(this.negateSort(v, negated)));
1083
+ (0, import_common_helpers2.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
1084
+ result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), import_kysely2.sql.raw(this.negateSort(v, negated)));
1005
1085
  }
1006
1086
  continue;
1007
1087
  }
@@ -1010,11 +1090,11 @@ var BaseCrudDialect = class {
1010
1090
  }
1011
1091
  const fieldDef = requireField(this.schema, model, field);
1012
1092
  if (!fieldDef.relation) {
1013
- const fieldRef = this.fieldRef(model, field, (0, import_kysely.expressionBuilder)(), modelAlias);
1093
+ const fieldRef = this.fieldRef(model, field, (0, import_kysely2.expressionBuilder)(), modelAlias);
1014
1094
  if (value === "asc" || value === "desc") {
1015
1095
  result = result.orderBy(fieldRef, this.negateSort(value, negated));
1016
1096
  } else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
1017
- result = result.orderBy(fieldRef, import_kysely.sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
1097
+ result = result.orderBy(fieldRef, import_kysely2.sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
1018
1098
  }
1019
1099
  } else {
1020
1100
  const relationModel = fieldDef.type;
@@ -1023,13 +1103,13 @@ var BaseCrudDialect = class {
1023
1103
  throw new QueryError(`invalid orderBy value for field "${field}"`);
1024
1104
  }
1025
1105
  if ("_count" in value) {
1026
- (0, import_common_helpers.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
1106
+ (0, import_common_helpers2.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
1027
1107
  const sort = this.negateSort(value._count, negated);
1028
1108
  result = result.orderBy((eb) => {
1029
1109
  const subQueryAlias = `${modelAlias}$orderBy$${field}$count`;
1030
1110
  let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
1031
1111
  const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, subQueryAlias);
1032
- subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right)))));
1112
+ subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right)))));
1033
1113
  subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
1034
1114
  return subQuery;
1035
1115
  }, sort);
@@ -1037,7 +1117,7 @@ var BaseCrudDialect = class {
1037
1117
  } else {
1038
1118
  result = result.leftJoin(relationModel, (join) => {
1039
1119
  const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
1040
- return join.on((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right)))));
1120
+ return join.on((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right)))));
1041
1121
  });
1042
1122
  result = this.buildOrderBy(result, fieldDef.type, relationModel, value, false, negated);
1043
1123
  }
@@ -1089,13 +1169,13 @@ var BaseCrudDialect = class {
1089
1169
  if (fieldDef.computed) {
1090
1170
  return query.select((eb) => this.fieldRef(model, field, eb, modelAlias).as(field));
1091
1171
  } else if (!fieldDef.originModel) {
1092
- return query.select(import_kysely.sql.ref(`${modelAlias}.${field}`).as(field));
1172
+ return query.select(import_kysely2.sql.ref(`${modelAlias}.${field}`).as(field));
1093
1173
  } else {
1094
1174
  return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
1095
1175
  }
1096
1176
  }
1097
1177
  buildDelegateJoin(thisModel, thisModelAlias, otherModelAlias, query) {
1098
- const idFields = getIdFields(this.schema, thisModel);
1178
+ const idFields = requireIdFields(this.schema, thisModel);
1099
1179
  query = query.leftJoin(otherModelAlias, (qb) => {
1100
1180
  for (const idField of idFields) {
1101
1181
  qb = qb.onRef(`${thisModelAlias}.${idField}`, "=", `${otherModelAlias}.${idField}`);
@@ -1117,10 +1197,16 @@ var BaseCrudDialect = class {
1117
1197
  for (const [field, value] of Object.entries(selections.select)) {
1118
1198
  const fieldDef = requireField(this.schema, model, field);
1119
1199
  const fieldModel = fieldDef.type;
1120
- const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
1121
- let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
1122
- for (const [left, right] of joinPairs) {
1123
- fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
1200
+ let fieldCountQuery;
1201
+ const m2m = getManyToManyRelation(this.schema, model, field);
1202
+ if (m2m) {
1203
+ fieldCountQuery = eb.selectFrom(fieldModel).innerJoin(m2m.joinTable, (join) => join.onRef(`${m2m.joinTable}.${m2m.otherFkName}`, "=", `${fieldModel}.${m2m.otherPKName}`).onRef(`${m2m.joinTable}.${m2m.parentFkName}`, "=", `${parentAlias}.${m2m.parentPKName}`)).select(eb.fn.countAll().as(`_count$${field}`));
1204
+ } else {
1205
+ fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
1206
+ const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
1207
+ for (const [left, right] of joinPairs) {
1208
+ fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
1209
+ }
1124
1210
  }
1125
1211
  if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
1126
1212
  const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
@@ -1200,6 +1286,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1200
1286
  static {
1201
1287
  __name(this, "PostgresCrudDialect");
1202
1288
  }
1289
+ constructor(schema, options) {
1290
+ super(schema, options);
1291
+ }
1203
1292
  get provider() {
1204
1293
  return "postgresql";
1205
1294
  }
@@ -1214,9 +1303,41 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1214
1303
  return value.map((v) => this.transformPrimitive(v, type, false));
1215
1304
  }
1216
1305
  } else {
1217
- return (0, import_ts_pattern3.match)(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
1306
+ return (0, import_ts_pattern3.match)(type).with("DateTime", () => value instanceof Date ? value.toISOString() : typeof value === "string" ? new Date(value).toISOString() : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
1307
+ }
1308
+ }
1309
+ transformOutput(value, type) {
1310
+ if (value === null || value === void 0) {
1311
+ return value;
1312
+ }
1313
+ return (0, import_ts_pattern3.match)(type).with("DateTime", () => this.transformOutputDate(value)).with("Bytes", () => this.transformOutputBytes(value)).with("BigInt", () => this.transformOutputBigInt(value)).with("Decimal", () => this.transformDecimal(value)).otherwise(() => super.transformOutput(value, type));
1314
+ }
1315
+ transformOutputBigInt(value) {
1316
+ if (typeof value === "bigint") {
1317
+ return value;
1318
+ }
1319
+ (0, import_common_helpers3.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
1320
+ return BigInt(value);
1321
+ }
1322
+ transformDecimal(value) {
1323
+ if (value instanceof import_decimal.default) {
1324
+ return value;
1325
+ }
1326
+ (0, import_common_helpers3.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal.default, `Expected string, number or Decimal, got ${typeof value}`);
1327
+ return new import_decimal.default(value);
1328
+ }
1329
+ transformOutputDate(value) {
1330
+ if (typeof value === "string") {
1331
+ return new Date(value);
1332
+ } else if (value instanceof Date && this.options.fixPostgresTimezone !== false) {
1333
+ return new Date(value.getTime() - value.getTimezoneOffset() * 60 * 1e3);
1334
+ } else {
1335
+ return value;
1218
1336
  }
1219
1337
  }
1338
+ transformOutputBytes(value) {
1339
+ return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
1340
+ }
1220
1341
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
1221
1342
  const relationResultName = `${parentAlias}$${relationField}`;
1222
1343
  const joinedQuery = this.buildRelationJSON(model, query, relationField, parentAlias, payload, relationResultName);
@@ -1247,14 +1368,14 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1247
1368
  buildRelationJoinFilter(query, model, relationField, relationModel, relationModelAlias, parentAlias) {
1248
1369
  const m2m = getManyToManyRelation(this.schema, model, relationField);
1249
1370
  if (m2m) {
1250
- const parentIds = getIdFields(this.schema, model);
1251
- const relationIds = getIdFields(this.schema, relationModel);
1252
- (0, import_common_helpers2.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
1253
- (0, import_common_helpers2.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
1371
+ const parentIds = requireIdFields(this.schema, model);
1372
+ const relationIds = requireIdFields(this.schema, relationModel);
1373
+ (0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
1374
+ (0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
1254
1375
  query = query.where((eb) => eb(eb.ref(`${relationModelAlias}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
1255
1376
  } else {
1256
1377
  const joinPairs = buildJoinPairs(this.schema, model, parentAlias, relationField, relationModelAlias);
1257
- query = query.where((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right)))));
1378
+ query = query.where((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely3.sql.ref(left), "=", import_kysely3.sql.ref(right)))));
1258
1379
  }
1259
1380
  return query;
1260
1381
  }
@@ -1262,9 +1383,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1262
1383
  qb = qb.select((eb) => {
1263
1384
  const objArgs = this.buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName);
1264
1385
  if (relationFieldDef.array) {
1265
- return eb.fn.coalesce(import_kysely2.sql`jsonb_agg(jsonb_build_object(${import_kysely2.sql.join(objArgs)}))`, import_kysely2.sql`'[]'::jsonb`).as("$data");
1386
+ return eb.fn.coalesce(import_kysely3.sql`jsonb_agg(jsonb_build_object(${import_kysely3.sql.join(objArgs)}))`, import_kysely3.sql`'[]'::jsonb`).as("$data");
1266
1387
  } else {
1267
- return import_kysely2.sql`jsonb_build_object(${import_kysely2.sql.join(objArgs)})`.as("$data");
1388
+ return import_kysely3.sql`jsonb_build_object(${import_kysely3.sql.join(objArgs)})`.as("$data");
1268
1389
  }
1269
1390
  });
1270
1391
  return qb;
@@ -1275,13 +1396,13 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1275
1396
  const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
1276
1397
  if (descendantModels.length > 0) {
1277
1398
  objArgs.push(...descendantModels.map((subModel) => [
1278
- import_kysely2.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1399
+ import_kysely3.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1279
1400
  eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
1280
1401
  ]).flatMap((v) => v));
1281
1402
  }
1282
1403
  if (payload === true || !payload.select) {
1283
1404
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
1284
- import_kysely2.sql.lit(field),
1405
+ import_kysely3.sql.lit(field),
1285
1406
  this.fieldRef(relationModel, field, eb, relationModelAlias, false)
1286
1407
  ]).flatMap((v) => v));
1287
1408
  } else if (payload.select) {
@@ -1289,14 +1410,14 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1289
1410
  if (field === "_count") {
1290
1411
  const subJson = this.buildCountJson(relationModel, eb, relationModelAlias, value);
1291
1412
  return [
1292
- import_kysely2.sql.lit(field),
1413
+ import_kysely3.sql.lit(field),
1293
1414
  subJson
1294
1415
  ];
1295
1416
  } else {
1296
1417
  const fieldDef = requireField(this.schema, relationModel, field);
1297
1418
  const fieldValue = fieldDef.relation ? eb.ref(`${parentResultName}$${field}.$data`) : this.fieldRef(relationModel, field, eb, relationModelAlias, false);
1298
1419
  return [
1299
- import_kysely2.sql.lit(field),
1420
+ import_kysely3.sql.lit(field),
1300
1421
  fieldValue
1301
1422
  ];
1302
1423
  }
@@ -1304,7 +1425,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1304
1425
  }
1305
1426
  if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
1306
1427
  objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
1307
- import_kysely2.sql.lit(field),
1428
+ import_kysely3.sql.lit(field),
1308
1429
  // reference the synthesized JSON field
1309
1430
  eb.ref(`${parentResultName}$${field}.$data`)
1310
1431
  ]).flatMap((v) => v));
@@ -1334,7 +1455,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1334
1455
  }
1335
1456
  buildJsonObject(eb, value) {
1336
1457
  return eb.fn("jsonb_build_object", Object.entries(value).flatMap(([key, value2]) => [
1337
- import_kysely2.sql.lit(key),
1458
+ import_kysely3.sql.lit(key),
1338
1459
  value2
1339
1460
  ]));
1340
1461
  }
@@ -1362,11 +1483,33 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1362
1483
  get supportInsertWithDefault() {
1363
1484
  return true;
1364
1485
  }
1486
+ getFieldSqlType(fieldDef) {
1487
+ if (fieldDef.relation) {
1488
+ throw new QueryError("Cannot get SQL type of a relation field");
1489
+ }
1490
+ let result;
1491
+ if (this.schema.enums?.[fieldDef.type]) {
1492
+ result = "text";
1493
+ } else {
1494
+ result = (0, import_ts_pattern3.match)(fieldDef.type).with("String", () => "text").with("Boolean", () => "boolean").with("Int", () => "integer").with("BigInt", () => "bigint").with("Float", () => "double precision").with("Decimal", () => "decimal").with("DateTime", () => "timestamp").with("Bytes", () => "bytea").with("Json", () => "jsonb").otherwise(() => "text");
1495
+ }
1496
+ if (fieldDef.array) {
1497
+ result += "[]";
1498
+ }
1499
+ return result;
1500
+ }
1501
+ getStringCasingBehavior() {
1502
+ return {
1503
+ supportsILike: true,
1504
+ likeCaseSensitive: true
1505
+ };
1506
+ }
1365
1507
  };
1366
1508
 
1367
1509
  // src/client/crud/dialects/sqlite.ts
1368
- var import_common_helpers3 = require("@zenstackhq/common-helpers");
1369
- var import_kysely3 = require("kysely");
1510
+ var import_common_helpers4 = require("@zenstackhq/common-helpers");
1511
+ var import_decimal2 = __toESM(require("decimal.js"), 1);
1512
+ var import_kysely4 = require("kysely");
1370
1513
  var import_ts_pattern4 = require("ts-pattern");
1371
1514
  var SqliteCrudDialect = class extends BaseCrudDialect {
1372
1515
  static {
@@ -1385,10 +1528,58 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1385
1528
  if (this.schema.typeDefs && type in this.schema.typeDefs) {
1386
1529
  return JSON.stringify(value);
1387
1530
  } else {
1388
- return (0, import_ts_pattern4.match)(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).with("Json", () => JSON.stringify(value)).otherwise(() => value);
1531
+ return (0, import_ts_pattern4.match)(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : typeof value === "string" ? new Date(value).toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).with("Json", () => JSON.stringify(value)).otherwise(() => value);
1389
1532
  }
1390
1533
  }
1391
1534
  }
1535
+ transformOutput(value, type) {
1536
+ if (value === null || value === void 0) {
1537
+ return value;
1538
+ } else if (this.schema.typeDefs && type in this.schema.typeDefs) {
1539
+ return this.transformOutputJson(value);
1540
+ } else {
1541
+ return (0, import_ts_pattern4.match)(type).with("Boolean", () => this.transformOutputBoolean(value)).with("DateTime", () => this.transformOutputDate(value)).with("Bytes", () => this.transformOutputBytes(value)).with("Decimal", () => this.transformOutputDecimal(value)).with("BigInt", () => this.transformOutputBigInt(value)).with("Json", () => this.transformOutputJson(value)).otherwise(() => super.transformOutput(value, type));
1542
+ }
1543
+ }
1544
+ transformOutputDecimal(value) {
1545
+ if (value instanceof import_decimal2.default) {
1546
+ return value;
1547
+ }
1548
+ (0, import_common_helpers4.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal2.default, `Expected string, number or Decimal, got ${typeof value}`);
1549
+ return new import_decimal2.default(value);
1550
+ }
1551
+ transformOutputBigInt(value) {
1552
+ if (typeof value === "bigint") {
1553
+ return value;
1554
+ }
1555
+ (0, import_common_helpers4.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
1556
+ return BigInt(value);
1557
+ }
1558
+ transformOutputBoolean(value) {
1559
+ return !!value;
1560
+ }
1561
+ transformOutputDate(value) {
1562
+ if (typeof value === "number") {
1563
+ return new Date(value);
1564
+ } else if (typeof value === "string") {
1565
+ return new Date(value);
1566
+ } else {
1567
+ return value;
1568
+ }
1569
+ }
1570
+ transformOutputBytes(value) {
1571
+ return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
1572
+ }
1573
+ transformOutputJson(value) {
1574
+ if (typeof value === "string") {
1575
+ try {
1576
+ return JSON.parse(value);
1577
+ } catch (e) {
1578
+ throw new QueryError("Invalid JSON returned", e);
1579
+ }
1580
+ }
1581
+ return value;
1582
+ }
1392
1583
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
1393
1584
  return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
1394
1585
  }
@@ -1414,13 +1605,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1414
1605
  const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
1415
1606
  if (descendantModels.length > 0) {
1416
1607
  objArgs.push(...descendantModels.map((subModel) => [
1417
- import_kysely3.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1608
+ import_kysely4.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1418
1609
  eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
1419
1610
  ]).flatMap((v) => v));
1420
1611
  }
1421
1612
  if (payload === true || !payload.select) {
1422
1613
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
1423
- import_kysely3.sql.lit(field),
1614
+ import_kysely4.sql.lit(field),
1424
1615
  this.fieldRef(relationModel, field, eb, subQueryName, false)
1425
1616
  ]).flatMap((v) => v));
1426
1617
  } else if (payload.select) {
@@ -1428,7 +1619,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1428
1619
  if (field === "_count") {
1429
1620
  const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
1430
1621
  return [
1431
- import_kysely3.sql.lit(field),
1622
+ import_kysely4.sql.lit(field),
1432
1623
  subJson
1433
1624
  ];
1434
1625
  } else {
@@ -1436,12 +1627,12 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1436
1627
  if (fieldDef.relation) {
1437
1628
  const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
1438
1629
  return [
1439
- import_kysely3.sql.lit(field),
1630
+ import_kysely4.sql.lit(field),
1440
1631
  subJson
1441
1632
  ];
1442
1633
  } else {
1443
1634
  return [
1444
- import_kysely3.sql.lit(field),
1635
+ import_kysely4.sql.lit(field),
1445
1636
  this.fieldRef(relationModel, field, eb, subQueryName, false)
1446
1637
  ];
1447
1638
  }
@@ -1452,15 +1643,15 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1452
1643
  objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
1453
1644
  const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
1454
1645
  return [
1455
- import_kysely3.sql.lit(field),
1646
+ import_kysely4.sql.lit(field),
1456
1647
  subJson
1457
1648
  ];
1458
1649
  }).flatMap((v) => v));
1459
1650
  }
1460
1651
  if (relationFieldDef.array) {
1461
- return eb.fn.coalesce(import_kysely3.sql`json_group_array(json_object(${import_kysely3.sql.join(objArgs)}))`, import_kysely3.sql`json_array()`).as("$data");
1652
+ return eb.fn.coalesce(import_kysely4.sql`json_group_array(json_object(${import_kysely4.sql.join(objArgs)}))`, import_kysely4.sql`json_array()`).as("$data");
1462
1653
  } else {
1463
- return import_kysely3.sql`json_object(${import_kysely3.sql.join(objArgs)})`.as("$data");
1654
+ return import_kysely4.sql`json_object(${import_kysely4.sql.join(objArgs)})`.as("$data");
1464
1655
  }
1465
1656
  });
1466
1657
  return tbl;
@@ -1470,10 +1661,10 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1470
1661
  const relationModel = fieldDef.type;
1471
1662
  const m2m = getManyToManyRelation(this.schema, model, relationField);
1472
1663
  if (m2m) {
1473
- const parentIds = getIdFields(this.schema, model);
1474
- const relationIds = getIdFields(this.schema, relationModel);
1475
- (0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
1476
- (0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
1664
+ const parentIds = requireIdFields(this.schema, model);
1665
+ const relationIds = requireIdFields(this.schema, relationModel);
1666
+ (0, import_common_helpers4.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
1667
+ (0, import_common_helpers4.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
1477
1668
  selectModelQuery = selectModelQuery.where((eb) => eb(eb.ref(`${relationModelAlias}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
1478
1669
  } else {
1479
1670
  const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
@@ -1501,7 +1692,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1501
1692
  }
1502
1693
  buildJsonObject(eb, value) {
1503
1694
  return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
1504
- import_kysely3.sql.lit(key),
1695
+ import_kysely4.sql.lit(key),
1505
1696
  value2
1506
1697
  ]));
1507
1698
  }
@@ -1525,6 +1716,24 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1525
1716
  get supportInsertWithDefault() {
1526
1717
  return false;
1527
1718
  }
1719
+ getFieldSqlType(fieldDef) {
1720
+ if (fieldDef.relation) {
1721
+ throw new QueryError("Cannot get SQL type of a relation field");
1722
+ }
1723
+ if (fieldDef.array) {
1724
+ throw new QueryError("SQLite does not support scalar list type");
1725
+ }
1726
+ if (this.schema.enums?.[fieldDef.type]) {
1727
+ return "text";
1728
+ }
1729
+ return (0, import_ts_pattern4.match)(fieldDef.type).with("String", () => "text").with("Boolean", () => "integer").with("Int", () => "integer").with("BigInt", () => "integer").with("Float", () => "real").with("Decimal", () => "decimal").with("DateTime", () => "numeric").with("Bytes", () => "blob").with("Json", () => "jsonb").otherwise(() => "text");
1730
+ }
1731
+ getStringCasingBehavior() {
1732
+ return {
1733
+ supportsILike: false,
1734
+ likeCaseSensitive: false
1735
+ };
1736
+ }
1528
1737
  };
1529
1738
 
1530
1739
  // src/client/crud/dialects/index.ts
@@ -1534,8 +1743,8 @@ function getCrudDialect(schema, options) {
1534
1743
  __name(getCrudDialect, "getCrudDialect");
1535
1744
 
1536
1745
  // src/utils/default-operation-node-visitor.ts
1537
- var import_kysely4 = require("kysely");
1538
- var DefaultOperationNodeVisitor = class extends import_kysely4.OperationNodeVisitor {
1746
+ var import_kysely5 = require("kysely");
1747
+ var DefaultOperationNodeVisitor = class extends import_kysely5.OperationNodeVisitor {
1539
1748
  static {
1540
1749
  __name(this, "DefaultOperationNodeVisitor");
1541
1750
  }
@@ -1852,12 +2061,12 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
1852
2061
  };
1853
2062
 
1854
2063
  // src/plugins/policy/expression-transformer.ts
1855
- var import_common_helpers5 = require("@zenstackhq/common-helpers");
1856
- var import_kysely6 = require("kysely");
2064
+ var import_common_helpers6 = require("@zenstackhq/common-helpers");
2065
+ var import_kysely7 = require("kysely");
1857
2066
  var import_ts_pattern7 = require("ts-pattern");
1858
2067
 
1859
2068
  // src/plugins/policy/expression-evaluator.ts
1860
- var import_common_helpers4 = require("@zenstackhq/common-helpers");
2069
+ var import_common_helpers5 = require("@zenstackhq/common-helpers");
1861
2070
  var import_ts_pattern6 = require("ts-pattern");
1862
2071
  var ExpressionEvaluator = class {
1863
2072
  static {
@@ -1901,18 +2110,18 @@ var ExpressionEvaluator = class {
1901
2110
  const right = this.evaluate(expr2.right, context);
1902
2111
  return (0, import_ts_pattern6.match)(expr2.op).with("==", () => left === right).with("!=", () => left !== right).with(">", () => left > right).with(">=", () => left >= right).with("<", () => left < right).with("<=", () => left <= right).with("&&", () => left && right).with("||", () => left || right).with("in", () => {
1903
2112
  const _right = right ?? [];
1904
- (0, import_common_helpers4.invariant)(Array.isArray(_right), 'expected array for "in" operator');
2113
+ (0, import_common_helpers5.invariant)(Array.isArray(_right), 'expected array for "in" operator');
1905
2114
  return _right.includes(left);
1906
2115
  }).exhaustive();
1907
2116
  }
1908
2117
  evaluateCollectionPredicate(expr2, context) {
1909
2118
  const op = expr2.op;
1910
- (0, import_common_helpers4.invariant)(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
2119
+ (0, import_common_helpers5.invariant)(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
1911
2120
  const left = this.evaluate(expr2.left, context);
1912
2121
  if (!left) {
1913
2122
  return false;
1914
2123
  }
1915
- (0, import_common_helpers4.invariant)(Array.isArray(left), "expected array");
2124
+ (0, import_common_helpers5.invariant)(Array.isArray(left), "expected array");
1916
2125
  return (0, import_ts_pattern6.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
1917
2126
  ...context,
1918
2127
  thisValue: item
@@ -1927,21 +2136,21 @@ var ExpressionEvaluator = class {
1927
2136
  };
1928
2137
 
1929
2138
  // src/plugins/policy/utils.ts
1930
- var import_kysely5 = require("kysely");
2139
+ var import_kysely6 = require("kysely");
1931
2140
  function trueNode(dialect) {
1932
- return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
2141
+ return import_kysely6.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
1933
2142
  }
1934
2143
  __name(trueNode, "trueNode");
1935
2144
  function falseNode(dialect) {
1936
- return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
2145
+ return import_kysely6.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
1937
2146
  }
1938
2147
  __name(falseNode, "falseNode");
1939
2148
  function isTrueNode(node) {
1940
- return import_kysely5.ValueNode.is(node) && (node.value === true || node.value === 1);
2149
+ return import_kysely6.ValueNode.is(node) && (node.value === true || node.value === 1);
1941
2150
  }
1942
2151
  __name(isTrueNode, "isTrueNode");
1943
2152
  function isFalseNode(node) {
1944
- return import_kysely5.ValueNode.is(node) && (node.value === false || node.value === 0);
2153
+ return import_kysely6.ValueNode.is(node) && (node.value === false || node.value === 0);
1945
2154
  }
1946
2155
  __name(isFalseNode, "isFalseNode");
1947
2156
  function conjunction(dialect, nodes) {
@@ -1958,7 +2167,7 @@ function conjunction(dialect, nodes) {
1958
2167
  if (items.length === 0) {
1959
2168
  return trueNode(dialect);
1960
2169
  }
1961
- return items.reduce((acc, node) => import_kysely5.AndNode.create(wrapParensIf(acc, import_kysely5.OrNode.is), wrapParensIf(node, import_kysely5.OrNode.is)));
2170
+ return items.reduce((acc, node) => import_kysely6.AndNode.create(wrapParensIf(acc, import_kysely6.OrNode.is), wrapParensIf(node, import_kysely6.OrNode.is)));
1962
2171
  }
1963
2172
  __name(conjunction, "conjunction");
1964
2173
  function disjunction(dialect, nodes) {
@@ -1975,7 +2184,7 @@ function disjunction(dialect, nodes) {
1975
2184
  if (items.length === 0) {
1976
2185
  return falseNode(dialect);
1977
2186
  }
1978
- return items.reduce((acc, node) => import_kysely5.OrNode.create(wrapParensIf(acc, import_kysely5.AndNode.is), wrapParensIf(node, import_kysely5.AndNode.is)));
2187
+ return items.reduce((acc, node) => import_kysely6.OrNode.create(wrapParensIf(acc, import_kysely6.AndNode.is), wrapParensIf(node, import_kysely6.AndNode.is)));
1979
2188
  }
1980
2189
  __name(disjunction, "disjunction");
1981
2190
  function logicalNot(dialect, node) {
@@ -1985,11 +2194,11 @@ function logicalNot(dialect, node) {
1985
2194
  if (isFalseNode(node)) {
1986
2195
  return trueNode(dialect);
1987
2196
  }
1988
- return import_kysely5.UnaryOperationNode.create(import_kysely5.OperatorNode.create("not"), wrapParensIf(node, (n) => import_kysely5.AndNode.is(n) || import_kysely5.OrNode.is(n)));
2197
+ return import_kysely6.UnaryOperationNode.create(import_kysely6.OperatorNode.create("not"), wrapParensIf(node, (n) => import_kysely6.AndNode.is(n) || import_kysely6.OrNode.is(n)));
1989
2198
  }
1990
2199
  __name(logicalNot, "logicalNot");
1991
2200
  function wrapParensIf(node, predicate) {
1992
- return predicate(node) ? import_kysely5.ParensNode.create(node) : node;
2201
+ return predicate(node) ? import_kysely6.ParensNode.create(node) : node;
1993
2202
  }
1994
2203
  __name(wrapParensIf, "wrapParensIf");
1995
2204
  function buildIsFalse(node, dialect) {
@@ -1998,13 +2207,13 @@ function buildIsFalse(node, dialect) {
1998
2207
  } else if (isTrueNode(node)) {
1999
2208
  return falseNode(dialect);
2000
2209
  }
2001
- return import_kysely5.BinaryOperationNode.create(
2210
+ return import_kysely6.BinaryOperationNode.create(
2002
2211
  // coalesce so null is treated as false
2003
- import_kysely5.FunctionNode.create("coalesce", [
2212
+ import_kysely6.FunctionNode.create("coalesce", [
2004
2213
  node,
2005
2214
  falseNode(dialect)
2006
2215
  ]),
2007
- import_kysely5.OperatorNode.create("="),
2216
+ import_kysely6.OperatorNode.create("="),
2008
2217
  falseNode(dialect)
2009
2218
  );
2010
2219
  }
@@ -2013,11 +2222,11 @@ function getTableName(node) {
2013
2222
  if (!node) {
2014
2223
  return node;
2015
2224
  }
2016
- if (import_kysely5.TableNode.is(node)) {
2225
+ if (import_kysely6.TableNode.is(node)) {
2017
2226
  return node.table.identifier.name;
2018
- } else if (import_kysely5.AliasNode.is(node)) {
2227
+ } else if (import_kysely6.AliasNode.is(node)) {
2019
2228
  return getTableName(node.node);
2020
- } else if (import_kysely5.ReferenceNode.is(node) && node.table) {
2229
+ } else if (import_kysely6.ReferenceNode.is(node) && node.table) {
2021
2230
  return getTableName(node.table);
2022
2231
  }
2023
2232
  return void 0;
@@ -2050,16 +2259,21 @@ var ExpressionTransformer = class {
2050
2259
  static {
2051
2260
  __name(this, "ExpressionTransformer");
2052
2261
  }
2053
- schema;
2054
- clientOptions;
2055
- auth;
2262
+ client;
2056
2263
  dialect;
2057
- constructor(schema, clientOptions, auth) {
2058
- this.schema = schema;
2059
- this.clientOptions = clientOptions;
2060
- this.auth = auth;
2264
+ constructor(client) {
2265
+ this.client = client;
2061
2266
  this.dialect = getCrudDialect(this.schema, this.clientOptions);
2062
2267
  }
2268
+ get schema() {
2269
+ return this.client.$schema;
2270
+ }
2271
+ get clientOptions() {
2272
+ return this.client.$options;
2273
+ }
2274
+ get auth() {
2275
+ return this.client.$auth;
2276
+ }
2063
2277
  get authType() {
2064
2278
  if (!this.schema.authType) {
2065
2279
  throw new InternalError('Schema does not have an "authType" specified');
@@ -2077,7 +2291,7 @@ var ExpressionTransformer = class {
2077
2291
  return this.transformValue(expr2.value, typeof expr2.value === "string" ? "String" : typeof expr2.value === "boolean" ? "Boolean" : "Int");
2078
2292
  }
2079
2293
  _array(expr2, context) {
2080
- return import_kysely6.ValueListNode.create(expr2.items.map((item) => this.transform(item, context)));
2294
+ return import_kysely7.ValueListNode.create(expr2.items.map((item) => this.transform(item, context)));
2081
2295
  }
2082
2296
  _field(expr2, context) {
2083
2297
  const fieldDef = requireField(this.schema, context.model, expr2.field);
@@ -2097,18 +2311,18 @@ var ExpressionTransformer = class {
2097
2311
  }
2098
2312
  mergeWhere(where, memberFilter) {
2099
2313
  if (!where) {
2100
- return import_kysely6.WhereNode.create(memberFilter ?? trueNode(this.dialect));
2314
+ return import_kysely7.WhereNode.create(memberFilter ?? trueNode(this.dialect));
2101
2315
  }
2102
2316
  if (!memberFilter) {
2103
2317
  return where;
2104
2318
  }
2105
- return import_kysely6.WhereNode.create(conjunction(this.dialect, [
2319
+ return import_kysely7.WhereNode.create(conjunction(this.dialect, [
2106
2320
  where.where,
2107
2321
  memberFilter
2108
2322
  ]));
2109
2323
  }
2110
2324
  _null() {
2111
- return import_kysely6.ValueNode.createImmediate(null);
2325
+ return import_kysely7.ValueNode.createImmediate(null);
2112
2326
  }
2113
2327
  _binary(expr2, context) {
2114
2328
  if (expr2.op === "&&") {
@@ -2129,45 +2343,82 @@ var ExpressionTransformer = class {
2129
2343
  if (op === "?" || op === "!" || op === "^") {
2130
2344
  return this.transformCollectionPredicate(expr2, context);
2131
2345
  }
2132
- const left = this.transform(expr2.left, context);
2133
- const right = this.transform(expr2.right, context);
2346
+ const { normalizedLeft, normalizedRight } = this.normalizeBinaryOperationOperands(expr2, context);
2347
+ const left = this.transform(normalizedLeft, context);
2348
+ const right = this.transform(normalizedRight, context);
2134
2349
  if (op === "in") {
2135
2350
  if (this.isNullNode(left)) {
2136
2351
  return this.transformValue(false, "Boolean");
2137
2352
  } else {
2138
- if (import_kysely6.ValueListNode.is(right)) {
2139
- return import_kysely6.BinaryOperationNode.create(left, import_kysely6.OperatorNode.create("in"), right);
2353
+ if (import_kysely7.ValueListNode.is(right)) {
2354
+ return import_kysely7.BinaryOperationNode.create(left, import_kysely7.OperatorNode.create("in"), right);
2140
2355
  } else {
2141
- return import_kysely6.BinaryOperationNode.create(left, import_kysely6.OperatorNode.create("="), import_kysely6.FunctionNode.create("any", [
2356
+ return import_kysely7.BinaryOperationNode.create(left, import_kysely7.OperatorNode.create("="), import_kysely7.FunctionNode.create("any", [
2142
2357
  right
2143
2358
  ]));
2144
2359
  }
2145
2360
  }
2146
2361
  }
2147
2362
  if (this.isNullNode(right)) {
2148
- return expr2.op === "==" ? import_kysely6.BinaryOperationNode.create(left, import_kysely6.OperatorNode.create("is"), right) : import_kysely6.BinaryOperationNode.create(left, import_kysely6.OperatorNode.create("is not"), right);
2363
+ return this.transformNullCheck(left, expr2.op);
2149
2364
  } else if (this.isNullNode(left)) {
2150
- return expr2.op === "==" ? import_kysely6.BinaryOperationNode.create(right, import_kysely6.OperatorNode.create("is"), import_kysely6.ValueNode.createImmediate(null)) : import_kysely6.BinaryOperationNode.create(right, import_kysely6.OperatorNode.create("is not"), import_kysely6.ValueNode.createImmediate(null));
2365
+ return this.transformNullCheck(right, expr2.op);
2366
+ } else {
2367
+ return import_kysely7.BinaryOperationNode.create(left, this.transformOperator(op), right);
2368
+ }
2369
+ }
2370
+ transformNullCheck(expr2, operator) {
2371
+ (0, import_common_helpers6.invariant)(operator === "==" || operator === "!=", 'operator must be "==" or "!=" for null comparison');
2372
+ if (import_kysely7.ValueNode.is(expr2)) {
2373
+ if (expr2.value === null) {
2374
+ return operator === "==" ? trueNode(this.dialect) : falseNode(this.dialect);
2375
+ } else {
2376
+ return operator === "==" ? falseNode(this.dialect) : trueNode(this.dialect);
2377
+ }
2378
+ } else {
2379
+ return operator === "==" ? import_kysely7.BinaryOperationNode.create(expr2, import_kysely7.OperatorNode.create("is"), import_kysely7.ValueNode.createImmediate(null)) : import_kysely7.BinaryOperationNode.create(expr2, import_kysely7.OperatorNode.create("is not"), import_kysely7.ValueNode.createImmediate(null));
2380
+ }
2381
+ }
2382
+ normalizeBinaryOperationOperands(expr2, context) {
2383
+ let normalizedLeft = expr2.left;
2384
+ if (this.isRelationField(expr2.left, context.model)) {
2385
+ (0, import_common_helpers6.invariant)(ExpressionUtils.isNull(expr2.right), "only null comparison is supported for relation field");
2386
+ const leftRelDef = this.getFieldDefFromFieldRef(expr2.left, context.model);
2387
+ (0, import_common_helpers6.invariant)(leftRelDef, "failed to get relation field definition");
2388
+ const idFields = requireIdFields(this.schema, leftRelDef.type);
2389
+ normalizedLeft = this.makeOrAppendMember(normalizedLeft, idFields[0]);
2390
+ }
2391
+ let normalizedRight = expr2.right;
2392
+ if (this.isRelationField(expr2.right, context.model)) {
2393
+ (0, import_common_helpers6.invariant)(ExpressionUtils.isNull(expr2.left), "only null comparison is supported for relation field");
2394
+ const rightRelDef = this.getFieldDefFromFieldRef(expr2.right, context.model);
2395
+ (0, import_common_helpers6.invariant)(rightRelDef, "failed to get relation field definition");
2396
+ const idFields = requireIdFields(this.schema, rightRelDef.type);
2397
+ normalizedRight = this.makeOrAppendMember(normalizedRight, idFields[0]);
2151
2398
  }
2152
- return import_kysely6.BinaryOperationNode.create(left, this.transformOperator(op), right);
2399
+ return {
2400
+ normalizedLeft,
2401
+ normalizedRight
2402
+ };
2153
2403
  }
2154
2404
  transformCollectionPredicate(expr2, context) {
2155
- (0, import_common_helpers5.invariant)(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
2405
+ (0, import_common_helpers6.invariant)(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
2156
2406
  if (this.isAuthCall(expr2.left) || this.isAuthMember(expr2.left)) {
2157
2407
  const value = new ExpressionEvaluator().evaluate(expr2, {
2158
2408
  auth: this.auth
2159
2409
  });
2160
2410
  return this.transformValue(value, "Boolean");
2161
2411
  }
2162
- (0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
2412
+ (0, import_common_helpers6.invariant)(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
2163
2413
  let newContextModel;
2164
- if (ExpressionUtils.isField(expr2.left)) {
2165
- const fieldDef = requireField(this.schema, context.model, expr2.left.field);
2414
+ const fieldDef = this.getFieldDefFromFieldRef(expr2.left, context.model);
2415
+ if (fieldDef) {
2416
+ (0, import_common_helpers6.invariant)(fieldDef.relation, `field is not a relation: ${JSON.stringify(expr2.left)}`);
2166
2417
  newContextModel = fieldDef.type;
2167
2418
  } else {
2168
- (0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left.receiver));
2169
- const fieldDef = requireField(this.schema, context.model, expr2.left.receiver.field);
2170
- newContextModel = fieldDef.type;
2419
+ (0, import_common_helpers6.invariant)(ExpressionUtils.isMember(expr2.left) && ExpressionUtils.isField(expr2.left.receiver), "left operand must be member access with field receiver");
2420
+ const fieldDef2 = requireField(this.schema, context.model, expr2.left.receiver.field);
2421
+ newContextModel = fieldDef2.type;
2171
2422
  for (const member of expr2.left.members) {
2172
2423
  const memberDef = requireField(this.schema, newContextModel, member);
2173
2424
  newContextModel = memberDef.type;
@@ -2181,13 +2432,13 @@ var ExpressionTransformer = class {
2181
2432
  if (expr2.op === "!") {
2182
2433
  predicateFilter = logicalNot(this.dialect, predicateFilter);
2183
2434
  }
2184
- const count = import_kysely6.FunctionNode.create("count", [
2185
- import_kysely6.ValueNode.createImmediate(1)
2435
+ const count = import_kysely7.FunctionNode.create("count", [
2436
+ import_kysely7.ValueNode.createImmediate(1)
2186
2437
  ]);
2187
- const predicateResult = (0, import_ts_pattern7.match)(expr2.op).with("?", () => import_kysely6.BinaryOperationNode.create(count, import_kysely6.OperatorNode.create(">"), import_kysely6.ValueNode.createImmediate(0))).with("!", () => import_kysely6.BinaryOperationNode.create(count, import_kysely6.OperatorNode.create("="), import_kysely6.ValueNode.createImmediate(0))).with("^", () => import_kysely6.BinaryOperationNode.create(count, import_kysely6.OperatorNode.create("="), import_kysely6.ValueNode.createImmediate(0))).exhaustive();
2438
+ const predicateResult = (0, import_ts_pattern7.match)(expr2.op).with("?", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create(">"), import_kysely7.ValueNode.createImmediate(0))).with("!", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create("="), import_kysely7.ValueNode.createImmediate(0))).with("^", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create("="), import_kysely7.ValueNode.createImmediate(0))).exhaustive();
2188
2439
  return this.transform(expr2.left, {
2189
2440
  ...context,
2190
- memberSelect: import_kysely6.SelectionNode.create(import_kysely6.AliasNode.create(predicateResult, import_kysely6.IdentifierNode.create("$t"))),
2441
+ memberSelect: import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(predicateResult, import_kysely7.IdentifierNode.create("$t"))),
2191
2442
  memberFilter: predicateFilter
2192
2443
  });
2193
2444
  }
@@ -2212,12 +2463,10 @@ var ExpressionTransformer = class {
2212
2463
  throw new QueryError(`Unsupported use of \`auth()\` in policy of model "${context.model}", comparing with \`auth()\` is only possible when auth type is a model`);
2213
2464
  }
2214
2465
  const idFields = Object.values(authModel.fields).filter((f) => f.id).map((f) => f.name);
2215
- (0, import_common_helpers5.invariant)(idFields.length > 0, "auth type model must have at least one id field");
2466
+ (0, import_common_helpers6.invariant)(idFields.length > 0, "auth type model must have at least one id field");
2216
2467
  const conditions = idFields.map((fieldName) => ExpressionUtils.binary(ExpressionUtils.member(authExpr, [
2217
2468
  fieldName
2218
- ]), "==", ExpressionUtils.member(other, [
2219
- fieldName
2220
- ])));
2469
+ ]), "==", this.makeOrAppendMember(other, fieldName)));
2221
2470
  let result = this.buildAnd(conditions);
2222
2471
  if (expr2.op === "!=") {
2223
2472
  result = this.buildLogicalNot(result);
@@ -2225,33 +2474,65 @@ var ExpressionTransformer = class {
2225
2474
  return this.transform(result, context);
2226
2475
  }
2227
2476
  }
2477
+ makeOrAppendMember(other, fieldName) {
2478
+ if (ExpressionUtils.isMember(other)) {
2479
+ return ExpressionUtils.member(other.receiver, [
2480
+ ...other.members,
2481
+ fieldName
2482
+ ]);
2483
+ } else {
2484
+ return ExpressionUtils.member(other, [
2485
+ fieldName
2486
+ ]);
2487
+ }
2488
+ }
2228
2489
  transformValue(value, type) {
2229
- return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type, false) ?? null);
2490
+ if (value === true) {
2491
+ return trueNode(this.dialect);
2492
+ } else if (value === false) {
2493
+ return falseNode(this.dialect);
2494
+ } else {
2495
+ return import_kysely7.ValueNode.create(this.dialect.transformPrimitive(value, type, false) ?? null);
2496
+ }
2230
2497
  }
2231
2498
  _unary(expr2, context) {
2232
- (0, import_common_helpers5.invariant)(expr2.op === "!", 'only "!" operator is supported');
2499
+ (0, import_common_helpers6.invariant)(expr2.op === "!", 'only "!" operator is supported');
2233
2500
  return logicalNot(this.dialect, this.transform(expr2.operand, context));
2234
2501
  }
2235
2502
  transformOperator(op) {
2236
2503
  const mappedOp = (0, import_ts_pattern7.match)(op).with("==", () => "=").otherwise(() => op);
2237
- return import_kysely6.OperatorNode.create(mappedOp);
2504
+ return import_kysely7.OperatorNode.create(mappedOp);
2238
2505
  }
2239
2506
  _call(expr2, context) {
2240
2507
  const result = this.transformCall(expr2, context);
2241
2508
  return result.toOperationNode();
2242
2509
  }
2243
2510
  transformCall(expr2, context) {
2244
- const func = this.clientOptions.functions?.[expr2.function];
2511
+ const func = this.getFunctionImpl(expr2.function);
2245
2512
  if (!func) {
2246
2513
  throw new QueryError(`Function not implemented: ${expr2.function}`);
2247
2514
  }
2248
- const eb = (0, import_kysely6.expressionBuilder)();
2515
+ const eb = (0, import_kysely7.expressionBuilder)();
2249
2516
  return func(eb, (expr2.args ?? []).map((arg) => this.transformCallArg(eb, arg, context)), {
2517
+ client: this.client,
2250
2518
  dialect: this.dialect,
2251
2519
  model: context.model,
2520
+ modelAlias: context.alias ?? context.model,
2252
2521
  operation: context.operation
2253
2522
  });
2254
2523
  }
2524
+ getFunctionImpl(functionName) {
2525
+ let func = this.clientOptions.functions?.[functionName];
2526
+ if (!func) {
2527
+ for (const plugin of this.clientOptions.plugins ?? []) {
2528
+ if (plugin.functions?.[functionName]) {
2529
+ func = plugin.functions[functionName];
2530
+ break;
2531
+ }
2532
+ }
2533
+ }
2534
+ return func;
2535
+ }
2255
2536
  transformCallArg(eb, arg, context) {
2256
2537
  if (ExpressionUtils.isLiteral(arg)) {
2257
2538
  return eb.val(arg.value);
@@ -2272,23 +2553,22 @@ var ExpressionTransformer = class {
2272
2553
  if (this.isAuthCall(expr2.receiver)) {
2273
2554
  return this.valueMemberAccess(this.auth, expr2, this.authType);
2274
2555
  }
2275
- (0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.receiver) || ExpressionUtils.isThis(expr2.receiver), 'expect receiver to be field expression or "this"');
2556
+ (0, import_common_helpers6.invariant)(ExpressionUtils.isField(expr2.receiver) || ExpressionUtils.isThis(expr2.receiver), 'expect receiver to be field expression or "this"');
2276
2557
  let members = expr2.members;
2277
2558
  let receiver;
2278
2559
  const { memberFilter, memberSelect, ...restContext } = context;
2279
2560
  if (ExpressionUtils.isThis(expr2.receiver)) {
2280
2561
  if (expr2.members.length === 1) {
2281
- const fieldDef = requireField(this.schema, context.model, expr2.members[0]);
2282
- (0, import_common_helpers5.invariant)(!fieldDef.relation, "this.relation access should have been transformed into relation access");
2283
- return this.createColumnRef(expr2.members[0], restContext);
2562
+ return this._field(ExpressionUtils.field(expr2.members[0]), context);
2563
+ } else {
2564
+ const firstMemberFieldDef = requireField(this.schema, context.model, expr2.members[0]);
2565
+ receiver = this.transformRelationAccess(expr2.members[0], firstMemberFieldDef.type, restContext);
2566
+ members = expr2.members.slice(1);
2284
2567
  }
2285
- const firstMemberFieldDef = requireField(this.schema, context.model, expr2.members[0]);
2286
- receiver = this.transformRelationAccess(expr2.members[0], firstMemberFieldDef.type, restContext);
2287
- members = expr2.members.slice(1);
2288
2568
  } else {
2289
2569
  receiver = this.transform(expr2.receiver, restContext);
2290
2570
  }
2291
- (0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(receiver), "expected receiver to be select query");
2571
+ (0, import_common_helpers6.invariant)(import_kysely7.SelectQueryNode.is(receiver), "expected receiver to be select query");
2292
2572
  let startType;
2293
2573
  if (ExpressionUtils.isField(expr2.receiver)) {
2294
2574
  const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
@@ -2317,11 +2597,11 @@ var ExpressionTransformer = class {
2317
2597
  alias: void 0
2318
2598
  });
2319
2599
  if (currNode) {
2320
- (0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(currNode), "expected select query node");
2600
+ (0, import_common_helpers6.invariant)(import_kysely7.SelectQueryNode.is(currNode), "expected select query node");
2321
2601
  currNode = {
2322
2602
  ...relation,
2323
2603
  selections: [
2324
- import_kysely6.SelectionNode.create(import_kysely6.AliasNode.create(currNode, import_kysely6.IdentifierNode.create(members[i + 1])))
2604
+ import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(currNode, import_kysely7.IdentifierNode.create(members[i + 1])))
2325
2605
  ]
2326
2606
  };
2327
2607
  } else {
@@ -2334,21 +2614,21 @@ var ExpressionTransformer = class {
2334
2614
  };
2335
2615
  }
2336
2616
  } else {
2337
- (0, import_common_helpers5.invariant)(i === members.length - 1, "plain field access must be the last segment");
2338
- (0, import_common_helpers5.invariant)(!currNode, "plain field access must be the last segment");
2339
- currNode = import_kysely6.ColumnNode.create(member);
2617
+ (0, import_common_helpers6.invariant)(i === members.length - 1, "plain field access must be the last segment");
2618
+ (0, import_common_helpers6.invariant)(!currNode, "plain field access must be the last segment");
2619
+ currNode = import_kysely7.ColumnNode.create(member);
2340
2620
  }
2341
2621
  }
2342
2622
  return {
2343
2623
  ...receiver,
2344
2624
  selections: [
2345
- import_kysely6.SelectionNode.create(import_kysely6.AliasNode.create(currNode, import_kysely6.IdentifierNode.create("$t")))
2625
+ import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(currNode, import_kysely7.IdentifierNode.create("$t")))
2346
2626
  ]
2347
2627
  };
2348
2628
  }
2349
2629
  valueMemberAccess(receiver, expr2, receiverType) {
2350
2630
  if (!receiver) {
2351
- return import_kysely6.ValueNode.createImmediate(null);
2631
+ return import_kysely7.ValueNode.createImmediate(null);
2352
2632
  }
2353
2633
  if (expr2.members.length !== 1) {
2354
2634
  throw new Error(`Only single member access is supported`);
@@ -2359,24 +2639,33 @@ var ExpressionTransformer = class {
2359
2639
  return this.transformValue(fieldValue, fieldDef.type);
2360
2640
  }
2361
2641
  transformRelationAccess(field, relationModel, context) {
2642
+ const m2m = getManyToManyRelation(this.schema, context.model, field);
2643
+ if (m2m) {
2644
+ return this.transformManyToManyRelationAccess(m2m, context);
2645
+ }
2362
2646
  const fromModel = context.model;
2363
2647
  const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, fromModel, field);
2364
2648
  let condition;
2365
2649
  if (ownedByModel) {
2366
- condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(context.alias ?? fromModel)), import_kysely6.OperatorNode.create("="), import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(relationModel)))));
2650
+ condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely7.BinaryOperationNode.create(import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(fk), import_kysely7.TableNode.create(context.alias ?? fromModel)), import_kysely7.OperatorNode.create("="), import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(pk), import_kysely7.TableNode.create(relationModel)))));
2367
2651
  } else {
2368
- condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(context.alias ?? fromModel)), import_kysely6.OperatorNode.create("="), import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(relationModel)))));
2652
+ condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely7.BinaryOperationNode.create(import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(pk), import_kysely7.TableNode.create(context.alias ?? fromModel)), import_kysely7.OperatorNode.create("="), import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(fk), import_kysely7.TableNode.create(relationModel)))));
2369
2653
  }
2370
2654
  return {
2371
2655
  kind: "SelectQueryNode",
2372
- from: import_kysely6.FromNode.create([
2373
- import_kysely6.TableNode.create(relationModel)
2656
+ from: import_kysely7.FromNode.create([
2657
+ import_kysely7.TableNode.create(relationModel)
2374
2658
  ]),
2375
- where: import_kysely6.WhereNode.create(condition)
2659
+ where: import_kysely7.WhereNode.create(condition)
2376
2660
  };
2377
2661
  }
2662
+ transformManyToManyRelationAccess(m2m, context) {
2663
+ const eb = (0, import_kysely7.expressionBuilder)();
2664
+ const relationQuery = eb.selectFrom(m2m.otherModel).innerJoin(m2m.joinTable, (join) => join.onRef(`${m2m.otherModel}.${m2m.otherPKName}`, "=", `${m2m.joinTable}.${m2m.otherFkName}`).onRef(`${m2m.joinTable}.${m2m.parentFkName}`, "=", `${context.alias ?? context.model}.${m2m.parentPKName}`));
2665
+ return relationQuery.toOperationNode();
2666
+ }
2378
2667
  createColumnRef(column, context) {
2379
- return import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(column), import_kysely6.TableNode.create(context.alias ?? context.model));
2668
+ return import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(column), import_kysely7.TableNode.create(context.alias ?? context.model));
2380
2669
  }
2381
2670
  isAuthCall(value) {
2382
2671
  return ExpressionUtils.isCall(value) && value.function === "auth";
@@ -2385,7 +2674,7 @@ var ExpressionTransformer = class {
2385
2674
  return ExpressionUtils.isMember(expr2) && this.isAuthCall(expr2.receiver);
2386
2675
  }
2387
2676
  isNullNode(node) {
2388
- return import_kysely6.ValueNode.is(node) && node.value === null;
2677
+ return import_kysely7.ValueNode.is(node) && node.value === null;
2389
2678
  }
2390
2679
  buildLogicalNot(result) {
2391
2680
  return ExpressionUtils.unary("!", result);
@@ -2399,6 +2688,19 @@ var ExpressionTransformer = class {
2399
2688
  return conditions.reduce((acc, condition) => ExpressionUtils.binary(acc, "&&", condition));
2400
2689
  }
2401
2690
  }
2691
+ isRelationField(expr2, model) {
2692
+ const fieldDef = this.getFieldDefFromFieldRef(expr2, model);
2693
+ return !!fieldDef?.relation;
2694
+ }
2695
+ getFieldDefFromFieldRef(expr2, model) {
2696
+ if (ExpressionUtils.isField(expr2)) {
2697
+ return requireField(this.schema, model, expr2.field);
2698
+ } else if (ExpressionUtils.isMember(expr2) && expr2.members.length === 1 && ExpressionUtils.isThis(expr2.receiver)) {
2699
+ return requireField(this.schema, model, expr2.members[0]);
2700
+ } else {
2701
+ return void 0;
2702
+ }
2703
+ }
2402
2704
  };
2403
2705
  _ts_decorate([
2404
2706
  expr("literal"),
@@ -2470,7 +2772,7 @@ _ts_decorate([
2470
2772
  ], ExpressionTransformer.prototype, "_member", null);
2471
2773
 
2472
2774
  // src/plugins/policy/policy-handler.ts
2473
- var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
2775
+ var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
2474
2776
  static {
2475
2777
  __name(this, "PolicyHandler");
2476
2778
  }
@@ -2485,129 +2787,296 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
2485
2787
  }
2486
2788
  async handle(node, proceed) {
2487
2789
  if (!this.isCrudQueryNode(node)) {
2488
- throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
2790
+ throw new RejectedByPolicyError(void 0, RejectedByPolicyReason.OTHER, "non-CRUD queries are not allowed");
2489
2791
  }
2490
2792
  if (!this.isMutationQueryNode(node)) {
2491
2793
  return proceed(this.transformNode(node));
2492
2794
  }
2493
- let mutationRequiresTransaction = false;
2494
- const mutationModel = this.getMutationModel(node);
2495
- if (import_kysely7.InsertQueryNode.is(node)) {
2496
- const constCondition = this.tryGetConstantPolicy(mutationModel, "create");
2497
- if (constCondition === false) {
2498
- throw new RejectedByPolicyError(mutationModel);
2499
- } else if (constCondition === void 0) {
2500
- mutationRequiresTransaction = true;
2795
+ const { mutationModel } = this.getMutationModel(node);
2796
+ if (import_kysely8.InsertQueryNode.is(node)) {
2797
+ const isManyToManyJoinTable = this.isManyToManyJoinTable(mutationModel);
2798
+ let needCheckPreCreate = true;
2799
+ if (!isManyToManyJoinTable) {
2800
+ const constCondition = this.tryGetConstantPolicy(mutationModel, "create");
2801
+ if (constCondition === true) {
2802
+ needCheckPreCreate = false;
2803
+ } else if (constCondition === false) {
2804
+ throw new RejectedByPolicyError(mutationModel);
2805
+ }
2806
+ }
2807
+ if (needCheckPreCreate) {
2808
+ await this.enforcePreCreatePolicy(node, mutationModel, isManyToManyJoinTable, proceed);
2501
2809
  }
2502
2810
  }
2503
- if (!mutationRequiresTransaction && !node.returning) {
2504
- return proceed(this.transformNode(node));
2505
- }
2506
- if (import_kysely7.InsertQueryNode.is(node)) {
2507
- await this.enforcePreCreatePolicy(node, proceed);
2508
- }
2509
- const transformedNode = this.transformNode(node);
2510
- const result = await proceed(transformedNode);
2511
- if (!this.onlyReturningId(node)) {
2811
+ const result = await proceed(this.transformNode(node));
2812
+ if (!node.returning || this.onlyReturningId(node)) {
2813
+ return result;
2814
+ } else {
2512
2815
  const readBackResult = await this.processReadBack(node, result, proceed);
2513
2816
  if (readBackResult.rows.length !== result.rows.length) {
2514
- throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
2817
+ throw new RejectedByPolicyError(mutationModel, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
2515
2818
  }
2516
2819
  return readBackResult;
2517
- } else {
2820
+ }
2821
+ }
2822
+ // #region overrides
2823
+ transformSelectQuery(node) {
2824
+ let whereNode = this.transformNode(node.where);
2825
+ const policyFilter = this.createPolicyFilterForFrom(node.from);
2826
+ if (policyFilter) {
2827
+ whereNode = import_kysely8.WhereNode.create(whereNode?.where ? conjunction(this.dialect, [
2828
+ whereNode.where,
2829
+ policyFilter
2830
+ ]) : policyFilter);
2831
+ }
2832
+ const baseResult = super.transformSelectQuery({
2833
+ ...node,
2834
+ where: void 0
2835
+ });
2836
+ return {
2837
+ ...baseResult,
2838
+ where: whereNode
2839
+ };
2840
+ }
2841
+ transformJoin(node) {
2842
+ const table = this.extractTableName(node.table);
2843
+ if (!table) {
2844
+ return super.transformJoin(node);
2845
+ }
2846
+ const filter = this.buildPolicyFilter(table.model, table.alias, "read");
2847
+ const nestedSelect = {
2848
+ kind: "SelectQueryNode",
2849
+ from: import_kysely8.FromNode.create([
2850
+ node.table
2851
+ ]),
2852
+ selections: [
2853
+ import_kysely8.SelectionNode.createSelectAll()
2854
+ ],
2855
+ where: import_kysely8.WhereNode.create(filter)
2856
+ };
2857
+ return {
2858
+ ...node,
2859
+ table: import_kysely8.AliasNode.create(import_kysely8.ParensNode.create(nestedSelect), import_kysely8.IdentifierNode.create(table.alias ?? table.model))
2860
+ };
2861
+ }
2862
+ transformInsertQuery(node) {
2863
+ let onConflict = node.onConflict;
2864
+ if (onConflict?.updates) {
2865
+ const { mutationModel, alias } = this.getMutationModel(node);
2866
+ const filter = this.buildPolicyFilter(mutationModel, alias, "update");
2867
+ if (onConflict.updateWhere) {
2868
+ onConflict = {
2869
+ ...onConflict,
2870
+ updateWhere: import_kysely8.WhereNode.create(conjunction(this.dialect, [
2871
+ onConflict.updateWhere.where,
2872
+ filter
2873
+ ]))
2874
+ };
2875
+ } else {
2876
+ onConflict = {
2877
+ ...onConflict,
2878
+ updateWhere: import_kysely8.WhereNode.create(filter)
2879
+ };
2880
+ }
2881
+ }
2882
+ const processedNode = onConflict ? {
2883
+ ...node,
2884
+ onConflict
2885
+ } : node;
2886
+ const result = super.transformInsertQuery(processedNode);
2887
+ if (!node.returning) {
2888
+ return result;
2889
+ }
2890
+ if (this.onlyReturningId(node)) {
2518
2891
  return result;
2892
+ } else {
2893
+ const { mutationModel } = this.getMutationModel(node);
2894
+ const idFields = requireIdFields(this.client.$schema, mutationModel);
2895
+ return {
2896
+ ...result,
2897
+ returning: import_kysely8.ReturningNode.create(idFields.map((field) => import_kysely8.SelectionNode.create(import_kysely8.ColumnNode.create(field))))
2898
+ };
2899
+ }
2900
+ }
2901
+ transformUpdateQuery(node) {
2902
+ const result = super.transformUpdateQuery(node);
2903
+ const { mutationModel, alias } = this.getMutationModel(node);
2904
+ let filter = this.buildPolicyFilter(mutationModel, alias, "update");
2905
+ if (node.from) {
2906
+ const joinFilter = this.createPolicyFilterForFrom(node.from);
2907
+ if (joinFilter) {
2908
+ filter = conjunction(this.dialect, [
2909
+ filter,
2910
+ joinFilter
2911
+ ]);
2912
+ }
2519
2913
  }
2914
+ return {
2915
+ ...result,
2916
+ where: import_kysely8.WhereNode.create(result.where ? conjunction(this.dialect, [
2917
+ result.where.where,
2918
+ filter
2919
+ ]) : filter)
2920
+ };
2520
2921
  }
2922
+ transformDeleteQuery(node) {
2923
+ const result = super.transformDeleteQuery(node);
2924
+ const { mutationModel, alias } = this.getMutationModel(node);
2925
+ let filter = this.buildPolicyFilter(mutationModel, alias, "delete");
2926
+ if (node.using) {
2927
+ const joinFilter = this.createPolicyFilterForTables(node.using.tables);
2928
+ if (joinFilter) {
2929
+ filter = conjunction(this.dialect, [
2930
+ filter,
2931
+ joinFilter
2932
+ ]);
2933
+ }
2934
+ }
2935
+ return {
2936
+ ...result,
2937
+ where: import_kysely8.WhereNode.create(result.where ? conjunction(this.dialect, [
2938
+ result.where.where,
2939
+ filter
2940
+ ]) : filter)
2941
+ };
2942
+ }
2943
+ // #endregion
2944
+ // #region helpers
2521
2945
  onlyReturningId(node) {
2522
2946
  if (!node.returning) {
2523
2947
  return true;
2524
2948
  }
2525
- const idFields = getIdFields(this.client.$schema, this.getMutationModel(node));
2949
+ const { mutationModel } = this.getMutationModel(node);
2950
+ const idFields = requireIdFields(this.client.$schema, mutationModel);
2526
2951
  const collector = new ColumnCollector();
2527
2952
  const selectedColumns = collector.collect(node.returning);
2528
2953
  return selectedColumns.every((c) => idFields.includes(c));
2529
2954
  }
2530
- async enforcePreCreatePolicy(node, proceed) {
2531
- const model = this.getMutationModel(node);
2955
+ async enforcePreCreatePolicy(node, mutationModel, isManyToManyJoinTable, proceed) {
2532
2956
  const fields = node.columns?.map((c) => c.column.name) ?? [];
2533
- const valueRows = node.values ? this.unwrapCreateValueRows(node.values, model, fields) : [
2957
+ const valueRows = node.values ? this.unwrapCreateValueRows(node.values, mutationModel, fields, isManyToManyJoinTable) : [
2534
2958
  []
2535
2959
  ];
2536
2960
  for (const values of valueRows) {
2537
- await this.enforcePreCreatePolicyForOne(model, fields, values.map((v) => v.node), proceed);
2961
+ if (isManyToManyJoinTable) {
2962
+ await this.enforcePreCreatePolicyForManyToManyJoinTable(mutationModel, fields, values.map((v) => v.node), proceed);
2963
+ } else {
2964
+ await this.enforcePreCreatePolicyForOne(mutationModel, fields, values.map((v) => v.node), proceed);
2965
+ }
2966
+ }
2967
+ }
2968
+ async enforcePreCreatePolicyForManyToManyJoinTable(tableName, fields, values, proceed) {
2969
+ const m2m = this.resolveManyToManyJoinTable(tableName);
2970
+ (0, import_common_helpers7.invariant)(m2m);
2971
+ (0, import_common_helpers7.invariant)(fields.includes("A") && fields.includes("B"), "many-to-many join table must have A and B fk fields");
2972
+ const aIndex = fields.indexOf("A");
2973
+ const aNode = values[aIndex];
2974
+ const bIndex = fields.indexOf("B");
2975
+ const bNode = values[bIndex];
2976
+ (0, import_common_helpers7.invariant)(import_kysely8.ValueNode.is(aNode) && import_kysely8.ValueNode.is(bNode), "A and B values must be ValueNode");
2977
+ const aValue = aNode.value;
2978
+ const bValue = bNode.value;
2979
+ (0, import_common_helpers7.invariant)(aValue !== null && aValue !== void 0, "A value cannot be null or undefined");
2980
+ (0, import_common_helpers7.invariant)(bValue !== null && bValue !== void 0, "B value cannot be null or undefined");
2981
+ const eb = (0, import_kysely8.expressionBuilder)();
2982
+ const filterA = this.buildPolicyFilter(m2m.firstModel, void 0, "update");
2983
+ const queryA = eb.selectFrom(m2m.firstModel).where(eb(eb.ref(`${m2m.firstModel}.${m2m.firstIdField}`), "=", aValue)).select(() => new import_kysely8.ExpressionWrapper(filterA).as("$t"));
2984
+ const filterB = this.buildPolicyFilter(m2m.secondModel, void 0, "update");
2985
+ const queryB = eb.selectFrom(m2m.secondModel).where(eb(eb.ref(`${m2m.secondModel}.${m2m.secondIdField}`), "=", bValue)).select(() => new import_kysely8.ExpressionWrapper(filterB).as("$t"));
2986
+ const queryNode = {
2987
+ kind: "SelectQueryNode",
2988
+ selections: [
2989
+ import_kysely8.SelectionNode.create(import_kysely8.AliasNode.create(queryA.toOperationNode(), import_kysely8.IdentifierNode.create("$conditionA"))),
2990
+ import_kysely8.SelectionNode.create(import_kysely8.AliasNode.create(queryB.toOperationNode(), import_kysely8.IdentifierNode.create("$conditionB")))
2991
+ ]
2992
+ };
2993
+ const result = await proceed(queryNode);
2994
+ if (!result.rows[0]?.$conditionA) {
2995
+ throw new RejectedByPolicyError(m2m.firstModel, RejectedByPolicyReason.CANNOT_READ_BACK, `many-to-many relation participant model "${m2m.firstModel}" not updatable`);
2996
+ }
2997
+ if (!result.rows[0]?.$conditionB) {
2998
+ throw new RejectedByPolicyError(m2m.secondModel, RejectedByPolicyReason.NO_ACCESS, `many-to-many relation participant model "${m2m.secondModel}" not updatable`);
2538
2999
  }
2539
3000
  }
2540
3001
  async enforcePreCreatePolicyForOne(model, fields, values, proceed) {
2541
- const allFields = Object.keys(requireModel(this.client.$schema, model).fields);
3002
+ const allFields = Object.entries(requireModel(this.client.$schema, model).fields).filter(([, def]) => !def.relation);
2542
3003
  const allValues = [];
2543
- for (const fieldName of allFields) {
2544
- const index = fields.indexOf(fieldName);
3004
+ for (const [name, _def] of allFields) {
3005
+ const index = fields.indexOf(name);
2545
3006
  if (index >= 0) {
2546
3007
  allValues.push(values[index]);
2547
3008
  } else {
2548
- allValues.push(import_kysely7.ValueNode.createImmediate(null));
3009
+ allValues.push(import_kysely8.ValueNode.createImmediate(null));
2549
3010
  }
2550
3011
  }
3012
+ const eb = (0, import_kysely8.expressionBuilder)();
2551
3013
  const constTable = {
2552
3014
  kind: "SelectQueryNode",
2553
- from: import_kysely7.FromNode.create([
2554
- import_kysely7.AliasNode.create(import_kysely7.ParensNode.create(import_kysely7.ValuesNode.create([
2555
- import_kysely7.ValueListNode.create(allValues)
2556
- ])), import_kysely7.IdentifierNode.create("$t"))
3015
+ from: import_kysely8.FromNode.create([
3016
+ import_kysely8.AliasNode.create(import_kysely8.ParensNode.create(import_kysely8.ValuesNode.create([
3017
+ import_kysely8.ValueListNode.create(allValues)
3018
+ ])), import_kysely8.IdentifierNode.create("$t"))
2557
3019
  ]),
2558
- selections: allFields.map((field, index) => import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(import_kysely7.ColumnNode.create(`column${index + 1}`), import_kysely7.IdentifierNode.create(field))))
3020
+ selections: allFields.map(([name, def], index) => {
3021
+ const castedColumnRef = import_kysely8.sql`CAST(${eb.ref(`column${index + 1}`)} as ${import_kysely8.sql.raw(this.dialect.getFieldSqlType(def))})`.as(name);
3022
+ return import_kysely8.SelectionNode.create(castedColumnRef.toOperationNode());
3023
+ })
2559
3024
  };
2560
3025
  const filter = this.buildPolicyFilter(model, void 0, "create");
2561
3026
  const preCreateCheck = {
2562
3027
  kind: "SelectQueryNode",
2563
- from: import_kysely7.FromNode.create([
2564
- import_kysely7.AliasNode.create(constTable, import_kysely7.IdentifierNode.create(model))
3028
+ from: import_kysely8.FromNode.create([
3029
+ import_kysely8.AliasNode.create(constTable, import_kysely8.IdentifierNode.create(model))
2565
3030
  ]),
2566
3031
  selections: [
2567
- import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(import_kysely7.BinaryOperationNode.create(import_kysely7.FunctionNode.create("COUNT", [
2568
- import_kysely7.ValueNode.createImmediate(1)
2569
- ]), import_kysely7.OperatorNode.create(">"), import_kysely7.ValueNode.createImmediate(0)), import_kysely7.IdentifierNode.create("$condition")))
3032
+ import_kysely8.SelectionNode.create(import_kysely8.AliasNode.create(import_kysely8.BinaryOperationNode.create(import_kysely8.FunctionNode.create("COUNT", [
3033
+ import_kysely8.ValueNode.createImmediate(1)
3034
+ ]), import_kysely8.OperatorNode.create(">"), import_kysely8.ValueNode.createImmediate(0)), import_kysely8.IdentifierNode.create("$condition")))
2570
3035
  ],
2571
- where: import_kysely7.WhereNode.create(filter)
3036
+ where: import_kysely8.WhereNode.create(filter)
2572
3037
  };
2573
3038
  const result = await proceed(preCreateCheck);
2574
3039
  if (!result.rows[0]?.$condition) {
2575
3040
  throw new RejectedByPolicyError(model);
2576
3041
  }
2577
3042
  }
2578
- unwrapCreateValueRows(node, model, fields) {
2579
- if (import_kysely7.ValuesNode.is(node)) {
2580
- return node.values.map((v) => this.unwrapCreateValueRow(v.values, model, fields));
2581
- } else if (import_kysely7.PrimitiveValueListNode.is(node)) {
3043
+ unwrapCreateValueRows(node, model, fields, isManyToManyJoinTable) {
3044
+ if (import_kysely8.ValuesNode.is(node)) {
3045
+ return node.values.map((v) => this.unwrapCreateValueRow(v.values, model, fields, isManyToManyJoinTable));
3046
+ } else if (import_kysely8.PrimitiveValueListNode.is(node)) {
2582
3047
  return [
2583
- this.unwrapCreateValueRow(node.values, model, fields)
3048
+ this.unwrapCreateValueRow(node.values, model, fields, isManyToManyJoinTable)
2584
3049
  ];
2585
3050
  } else {
2586
3051
  throw new InternalError(`Unexpected node kind: ${node.kind} for unwrapping create values`);
2587
3052
  }
2588
3053
  }
2589
- unwrapCreateValueRow(data, model, fields) {
2590
- (0, import_common_helpers6.invariant)(data.length === fields.length, "data length must match fields length");
3054
+ unwrapCreateValueRow(data, model, fields, isImplicitManyToManyJoinTable) {
3055
+ (0, import_common_helpers7.invariant)(data.length === fields.length, "data length must match fields length");
2591
3056
  const result = [];
2592
3057
  for (let i = 0; i < data.length; i++) {
2593
3058
  const item = data[i];
2594
- const fieldDef = requireField(this.client.$schema, model, fields[i]);
2595
3059
  if (typeof item === "object" && item && "kind" in item) {
2596
- (0, import_common_helpers6.invariant)(item.kind === "ValueNode", "expecting a ValueNode");
3060
+ const fieldDef = requireField(this.client.$schema, model, fields[i]);
3061
+ (0, import_common_helpers7.invariant)(item.kind === "ValueNode", "expecting a ValueNode");
2597
3062
  result.push({
2598
- node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
3063
+ node: import_kysely8.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
2599
3064
  raw: item.value
2600
3065
  });
2601
3066
  } else {
2602
- const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
3067
+ let value = item;
3068
+ if (!isImplicitManyToManyJoinTable) {
3069
+ const fieldDef = requireField(this.client.$schema, model, fields[i]);
3070
+ value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
3071
+ }
2603
3072
  if (Array.isArray(value)) {
2604
3073
  result.push({
2605
- node: import_kysely7.RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
3074
+ node: import_kysely8.RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
2606
3075
  raw: value
2607
3076
  });
2608
3077
  } else {
2609
3078
  result.push({
2610
- node: import_kysely7.ValueNode.create(value),
3079
+ node: import_kysely8.ValueNode.create(value),
2611
3080
  raw: value
2612
3081
  });
2613
3082
  }
@@ -2643,18 +3112,15 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
2643
3112
  if (!this.isMutationQueryNode(node) || !node.returning) {
2644
3113
  return result;
2645
3114
  }
2646
- const table = this.getMutationModel(node);
2647
- if (!table) {
2648
- throw new InternalError(`Unable to get table name for query node: ${node}`);
2649
- }
2650
- const idConditions = this.buildIdConditions(table, result.rows);
2651
- const policyFilter = this.buildPolicyFilter(table, void 0, "read");
3115
+ const { mutationModel } = this.getMutationModel(node);
3116
+ const idConditions = this.buildIdConditions(mutationModel, result.rows);
3117
+ const policyFilter = this.buildPolicyFilter(mutationModel, void 0, "read");
2652
3118
  const select = {
2653
3119
  kind: "SelectQueryNode",
2654
- from: import_kysely7.FromNode.create([
2655
- import_kysely7.TableNode.create(table)
3120
+ from: import_kysely8.FromNode.create([
3121
+ import_kysely8.TableNode.create(mutationModel)
2656
3122
  ]),
2657
- where: import_kysely7.WhereNode.create(conjunction(this.dialect, [
3123
+ where: import_kysely8.WhereNode.create(conjunction(this.dialect, [
2658
3124
  idConditions,
2659
3125
  policyFilter
2660
3126
  ])),
@@ -2664,143 +3130,122 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
2664
3130
  return selectResult;
2665
3131
  }
2666
3132
  buildIdConditions(table, rows) {
2667
- const idFields = getIdFields(this.client.$schema, table);
2668
- return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => import_kysely7.BinaryOperationNode.create(import_kysely7.ColumnNode.create(field), import_kysely7.OperatorNode.create("="), import_kysely7.ValueNode.create(row[field]))))));
3133
+ const idFields = requireIdFields(this.client.$schema, table);
3134
+ return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => import_kysely8.BinaryOperationNode.create(import_kysely8.ColumnNode.create(field), import_kysely8.OperatorNode.create("="), import_kysely8.ValueNode.create(row[field]))))));
2669
3135
  }
2670
3136
  getMutationModel(node) {
2671
- const r = (0, import_ts_pattern8.match)(node).when(import_kysely7.InsertQueryNode.is, (node2) => getTableName(node2.into)).when(import_kysely7.UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(import_kysely7.DeleteQueryNode.is, (node2) => {
3137
+ const r = (0, import_ts_pattern8.match)(node).when(import_kysely8.InsertQueryNode.is, (node2) => ({
3138
+ mutationModel: getTableName(node2.into),
3139
+ alias: void 0
3140
+ })).when(import_kysely8.UpdateQueryNode.is, (node2) => {
3141
+ if (!node2.table) {
3142
+ throw new QueryError("Update query must have a table");
3143
+ }
3144
+ const r2 = this.extractTableName(node2.table);
3145
+ return r2 ? {
3146
+ mutationModel: r2.model,
3147
+ alias: r2.alias
3148
+ } : void 0;
3149
+ }).when(import_kysely8.DeleteQueryNode.is, (node2) => {
2672
3150
  if (node2.from.froms.length !== 1) {
2673
- throw new InternalError("Only one from table is supported for delete");
3151
+ throw new QueryError("Only one from table is supported for delete");
2674
3152
  }
2675
- return getTableName(node2.from.froms[0]);
3153
+ const r2 = this.extractTableName(node2.from.froms[0]);
3154
+ return r2 ? {
3155
+ mutationModel: r2.model,
3156
+ alias: r2.alias
3157
+ } : void 0;
2676
3158
  }).exhaustive();
2677
3159
  if (!r) {
2678
- throw new InternalError(`Unable to get table name for query node: ${node}`);
2679
- }
2680
- return r;
2681
- }
2682
- isCrudQueryNode(node) {
2683
- return import_kysely7.SelectQueryNode.is(node) || import_kysely7.InsertQueryNode.is(node) || import_kysely7.UpdateQueryNode.is(node) || import_kysely7.DeleteQueryNode.is(node);
2684
- }
2685
- isMutationQueryNode(node) {
2686
- return import_kysely7.InsertQueryNode.is(node) || import_kysely7.UpdateQueryNode.is(node) || import_kysely7.DeleteQueryNode.is(node);
2687
- }
2688
- buildPolicyFilter(model, alias, operation) {
2689
- const policies = this.getModelPolicies(model, operation);
2690
- if (policies.length === 0) {
2691
- return falseNode(this.dialect);
2692
- }
2693
- const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.transformPolicyCondition(model, alias, operation, policy));
2694
- const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.transformPolicyCondition(model, alias, operation, policy));
2695
- let combinedPolicy;
2696
- if (allows.length === 0) {
2697
- combinedPolicy = falseNode(this.dialect);
2698
- } else {
2699
- combinedPolicy = disjunction(this.dialect, allows);
2700
- if (denies.length !== 0) {
2701
- const combinedDenies = conjunction(this.dialect, denies.map((d) => buildIsFalse(d, this.dialect)));
2702
- combinedPolicy = conjunction(this.dialect, [
2703
- combinedPolicy,
2704
- combinedDenies
2705
- ]);
2706
- }
2707
- }
2708
- return combinedPolicy;
2709
- }
2710
- transformSelectQuery(node) {
2711
- let whereNode = node.where;
2712
- node.from?.froms.forEach((from) => {
2713
- const extractResult = this.extractTableName(from);
2714
- if (extractResult) {
2715
- const { model, alias } = extractResult;
2716
- const filter = this.buildPolicyFilter(model, alias, "read");
2717
- whereNode = import_kysely7.WhereNode.create(whereNode?.where ? conjunction(this.dialect, [
2718
- whereNode.where,
2719
- filter
2720
- ]) : filter);
2721
- }
2722
- });
2723
- const baseResult = super.transformSelectQuery({
2724
- ...node,
2725
- where: void 0
2726
- });
2727
- return {
2728
- ...baseResult,
2729
- where: whereNode
2730
- };
2731
- }
2732
- transformInsertQuery(node) {
2733
- const result = super.transformInsertQuery(node);
2734
- if (!node.returning) {
2735
- return result;
2736
- }
2737
- if (this.onlyReturningId(node)) {
2738
- return result;
2739
- } else {
2740
- const idFields = getIdFields(this.client.$schema, this.getMutationModel(node));
2741
- return {
2742
- ...result,
2743
- returning: import_kysely7.ReturningNode.create(idFields.map((field) => import_kysely7.SelectionNode.create(import_kysely7.ColumnNode.create(field))))
2744
- };
3160
+ throw new InternalError(`Unable to get table name for query node: ${node}`);
2745
3161
  }
3162
+ return r;
2746
3163
  }
2747
- transformUpdateQuery(node) {
2748
- const result = super.transformUpdateQuery(node);
2749
- const mutationModel = this.getMutationModel(node);
2750
- const filter = this.buildPolicyFilter(mutationModel, void 0, "update");
2751
- return {
2752
- ...result,
2753
- where: import_kysely7.WhereNode.create(result.where ? conjunction(this.dialect, [
2754
- result.where.where,
2755
- filter
2756
- ]) : filter)
2757
- };
3164
+ isCrudQueryNode(node) {
3165
+ return import_kysely8.SelectQueryNode.is(node) || import_kysely8.InsertQueryNode.is(node) || import_kysely8.UpdateQueryNode.is(node) || import_kysely8.DeleteQueryNode.is(node);
2758
3166
  }
2759
- transformDeleteQuery(node) {
2760
- const result = super.transformDeleteQuery(node);
2761
- const mutationModel = this.getMutationModel(node);
2762
- const filter = this.buildPolicyFilter(mutationModel, void 0, "delete");
2763
- return {
2764
- ...result,
2765
- where: import_kysely7.WhereNode.create(result.where ? conjunction(this.dialect, [
2766
- result.where.where,
2767
- filter
2768
- ]) : filter)
2769
- };
3167
+ isMutationQueryNode(node) {
3168
+ return import_kysely8.InsertQueryNode.is(node) || import_kysely8.UpdateQueryNode.is(node) || import_kysely8.DeleteQueryNode.is(node);
3169
+ }
3170
+ buildPolicyFilter(model, alias, operation) {
3171
+ const m2mFilter = this.getModelPolicyFilterForManyToManyJoinTable(model, alias, operation);
3172
+ if (m2mFilter) {
3173
+ return m2mFilter;
3174
+ }
3175
+ const policies = this.getModelPolicies(model, operation);
3176
+ if (policies.length === 0) {
3177
+ return falseNode(this.dialect);
3178
+ }
3179
+ const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.compilePolicyCondition(model, alias, operation, policy));
3180
+ const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.compilePolicyCondition(model, alias, operation, policy));
3181
+ let combinedPolicy;
3182
+ if (allows.length === 0) {
3183
+ combinedPolicy = falseNode(this.dialect);
3184
+ } else {
3185
+ combinedPolicy = disjunction(this.dialect, allows);
3186
+ if (denies.length !== 0) {
3187
+ const combinedDenies = conjunction(this.dialect, denies.map((d) => buildIsFalse(d, this.dialect)));
3188
+ combinedPolicy = conjunction(this.dialect, [
3189
+ combinedPolicy,
3190
+ combinedDenies
3191
+ ]);
3192
+ }
3193
+ }
3194
+ return combinedPolicy;
2770
3195
  }
2771
- extractTableName(from) {
2772
- if (import_kysely7.TableNode.is(from)) {
3196
+ extractTableName(node) {
3197
+ if (import_kysely8.TableNode.is(node)) {
2773
3198
  return {
2774
- model: from.table.identifier.name
3199
+ model: node.table.identifier.name
2775
3200
  };
2776
3201
  }
2777
- if (import_kysely7.AliasNode.is(from)) {
2778
- const inner = this.extractTableName(from.node);
3202
+ if (import_kysely8.AliasNode.is(node)) {
3203
+ const inner = this.extractTableName(node.node);
2779
3204
  if (!inner) {
2780
3205
  return void 0;
2781
3206
  }
2782
3207
  return {
2783
3208
  model: inner.model,
2784
- alias: import_kysely7.IdentifierNode.is(from.alias) ? from.alias.name : void 0
3209
+ alias: import_kysely8.IdentifierNode.is(node.alias) ? node.alias.name : void 0
2785
3210
  };
2786
3211
  } else {
2787
3212
  return void 0;
2788
3213
  }
2789
3214
  }
2790
- transformPolicyCondition(model, alias, operation, policy) {
2791
- return new ExpressionTransformer(this.client.$schema, this.client.$options, this.client.$auth).transform(policy.condition, {
3215
+ createPolicyFilterForFrom(node) {
3216
+ if (!node) {
3217
+ return void 0;
3218
+ }
3219
+ return this.createPolicyFilterForTables(node.froms);
3220
+ }
3221
+ createPolicyFilterForTables(tables) {
3222
+ return tables.reduce((acc, table) => {
3223
+ const extractResult = this.extractTableName(table);
3224
+ if (extractResult) {
3225
+ const { model, alias } = extractResult;
3226
+ const filter = this.buildPolicyFilter(model, alias, "read");
3227
+ return acc ? conjunction(this.dialect, [
3228
+ acc,
3229
+ filter
3230
+ ]) : filter;
3231
+ }
3232
+ return acc;
3233
+ }, void 0);
3234
+ }
3235
+ compilePolicyCondition(model, alias, operation, policy) {
3236
+ return new ExpressionTransformer(this.client).transform(policy.condition, {
2792
3237
  model,
2793
3238
  alias,
2794
3239
  operation,
2795
3240
  auth: this.client.$auth
2796
3241
  });
2797
3242
  }
2798
- getModelPolicies(modelName, operation) {
2799
- const modelDef = requireModel(this.client.$schema, modelName);
3243
+ getModelPolicies(model, operation) {
3244
+ const modelDef = requireModel(this.client.$schema, model);
2800
3245
  const result = [];
2801
3246
  const extractOperations = /* @__PURE__ */ __name((expr2) => {
2802
- (0, import_common_helpers6.invariant)(ExpressionUtils.isLiteral(expr2), "expecting a literal");
2803
- (0, import_common_helpers6.invariant)(typeof expr2.value === "string", "expecting a string literal");
3247
+ (0, import_common_helpers7.invariant)(ExpressionUtils.isLiteral(expr2), "expecting a literal");
3248
+ (0, import_common_helpers7.invariant)(typeof expr2.value === "string", "expecting a string literal");
2804
3249
  return expr2.value.split(",").filter((v) => !!v).map((v) => v.trim());
2805
3250
  }, "extractOperations");
2806
3251
  if (modelDef.attributes) {
@@ -2812,8 +3257,84 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
2812
3257
  }
2813
3258
  return result;
2814
3259
  }
3260
+ resolveManyToManyJoinTable(tableName) {
3261
+ for (const model of Object.values(this.client.$schema.models)) {
3262
+ for (const field of Object.values(model.fields)) {
3263
+ const m2m = getManyToManyRelation(this.client.$schema, model.name, field.name);
3264
+ if (m2m?.joinTable === tableName) {
3265
+ const sortedRecord = [
3266
+ {
3267
+ model: model.name,
3268
+ field: field.name
3269
+ },
3270
+ {
3271
+ model: m2m.otherModel,
3272
+ field: m2m.otherField
3273
+ }
3274
+ ].sort(this.manyToManySorter);
3275
+ const firstIdFields = requireIdFields(this.client.$schema, sortedRecord[0].model);
3276
+ const secondIdFields = requireIdFields(this.client.$schema, sortedRecord[1].model);
3277
+ (0, import_common_helpers7.invariant)(firstIdFields.length === 1 && secondIdFields.length === 1, "only single-field id is supported for implicit many-to-many join table");
3278
+ return {
3279
+ firstModel: sortedRecord[0].model,
3280
+ firstField: sortedRecord[0].field,
3281
+ firstIdField: firstIdFields[0],
3282
+ secondModel: sortedRecord[1].model,
3283
+ secondField: sortedRecord[1].field,
3284
+ secondIdField: secondIdFields[0]
3285
+ };
3286
+ }
3287
+ }
3288
+ }
3289
+ return void 0;
3290
+ }
3291
+ manyToManySorter(a, b) {
3292
+ return a.model !== b.model ? a.model.localeCompare(b.model) : a.field.localeCompare(b.field);
3293
+ }
3294
+ isManyToManyJoinTable(tableName) {
3295
+ return !!this.resolveManyToManyJoinTable(tableName);
3296
+ }
3297
+ getModelPolicyFilterForManyToManyJoinTable(tableName, alias, operation) {
3298
+ const m2m = this.resolveManyToManyJoinTable(tableName);
3299
+ if (!m2m) {
3300
+ return void 0;
3301
+ }
3302
+ const checkForOperation = operation === "read" ? "read" : "update";
3303
+ const eb = (0, import_kysely8.expressionBuilder)();
3304
+ const joinTable = alias ?? tableName;
3305
+ const aQuery = eb.selectFrom(m2m.firstModel).whereRef(`${m2m.firstModel}.${m2m.firstIdField}`, "=", `${joinTable}.A`).select(() => new import_kysely8.ExpressionWrapper(this.buildPolicyFilter(m2m.firstModel, void 0, checkForOperation)).as("$conditionA"));
3306
+ const bQuery = eb.selectFrom(m2m.secondModel).whereRef(`${m2m.secondModel}.${m2m.secondIdField}`, "=", `${joinTable}.B`).select(() => new import_kysely8.ExpressionWrapper(this.buildPolicyFilter(m2m.secondModel, void 0, checkForOperation)).as("$conditionB"));
3307
+ return eb.and([
3308
+ aQuery,
3309
+ bQuery
3310
+ ]).toOperationNode();
3311
+ }
2815
3312
  };
2816
3313
 
3314
+ // src/plugins/policy/functions.ts
3315
+ var check = /* @__PURE__ */ __name((eb, args, { client, model, modelAlias, operation }) => {
3316
+ (0, import_common_helpers8.invariant)(args.length === 1 || args.length === 2, '"check" function requires 1 or 2 arguments');
3317
+ const arg1Node = args[0].toOperationNode();
3318
+ const arg2Node = args.length === 2 ? args[1].toOperationNode() : void 0;
3319
+ if (arg2Node) {
3320
+ (0, import_common_helpers8.invariant)(import_kysely9.ValueNode.is(arg2Node) && typeof arg2Node.value === "string", '"operation" parameter must be a string literal when provided');
3321
+ (0, import_common_helpers8.invariant)(CRUD.includes(arg2Node.value), '"operation" parameter must be one of "create", "read", "update", "delete"');
3322
+ }
3323
+ const fieldName = extractFieldName(arg1Node);
3324
+ (0, import_common_helpers8.invariant)(fieldName, 'Failed to extract field name from the first argument of "check" function');
3325
+ const fieldDef = requireField(client.$schema, model, fieldName);
3326
+ (0, import_common_helpers8.invariant)(fieldDef.relation, `Field "${fieldName}" is not a relation field in model "${model}"`);
3327
+ (0, import_common_helpers8.invariant)(!fieldDef.array, `Field "${fieldName}" is a to-many relation, which is not supported by "check"`);
3328
+ const relationModel = fieldDef.type;
3329
+ const op = arg2Node ? arg2Node.value : operation;
3330
+ const policyHandler = new PolicyHandler(client);
3331
+ const joinPairs = buildJoinPairs(client.$schema, model, modelAlias, fieldName, relationModel);
3332
+ const joinCondition = joinPairs.length === 1 ? eb(eb.ref(joinPairs[0][0]), "=", eb.ref(joinPairs[0][1])) : eb.and(joinPairs.map(([left, right]) => eb(eb.ref(left), "=", eb.ref(right))));
3333
+ const policyCondition = policyHandler.buildPolicyFilter(relationModel, void 0, op);
3334
+ const result = eb.selectFrom(relationModel).where(joinCondition).select(new import_kysely9.ExpressionWrapper(policyCondition).as("$condition"));
3335
+ return result;
3336
+ }, "check");
3337
+
2817
3338
  // src/plugins/policy/plugin.ts
2818
3339
  var PolicyPlugin = class {
2819
3340
  static {
@@ -2828,6 +3349,11 @@ var PolicyPlugin = class {
2828
3349
  get description() {
2829
3350
  return "Enforces access policies defined in the schema.";
2830
3351
  }
3352
+ get functions() {
3353
+ return {
3354
+ check
3355
+ };
3356
+ }
2831
3357
  onKyselyQuery({
2832
3358
  query,
2833
3359
  client,
@@ -2844,13 +3370,13 @@ var PolicyPlugin = class {
2844
3370
  };
2845
3371
 
2846
3372
  // src/utils/clone.ts
2847
- var import_common_helpers7 = require("@zenstackhq/common-helpers");
3373
+ var import_common_helpers9 = require("@zenstackhq/common-helpers");
2848
3374
  function clone(value) {
2849
3375
  if (Array.isArray(value)) {
2850
3376
  return value.map((v) => clone(v));
2851
3377
  }
2852
3378
  if (typeof value === "object") {
2853
- if (!value || !(0, import_common_helpers7.isPlainObject)(value)) {
3379
+ if (!value || !(0, import_common_helpers9.isPlainObject)(value)) {
2854
3380
  return value;
2855
3381
  }
2856
3382
  const result = {};
@@ -2863,16 +3389,6 @@ function clone(value) {
2863
3389
  }
2864
3390
  __name(clone, "clone");
2865
3391
 
2866
- // src/client/contract.ts
2867
- var TransactionIsolationLevel = /* @__PURE__ */ function(TransactionIsolationLevel2) {
2868
- TransactionIsolationLevel2["ReadUncommitted"] = "read uncommitted";
2869
- TransactionIsolationLevel2["ReadCommitted"] = "read committed";
2870
- TransactionIsolationLevel2["RepeatableRead"] = "repeatable read";
2871
- TransactionIsolationLevel2["Serializable"] = "serializable";
2872
- TransactionIsolationLevel2["Snapshot"] = "snapshot";
2873
- return TransactionIsolationLevel2;
2874
- }({});
2875
-
2876
3392
  // src/client/crud/operations/base.ts
2877
3393
  var BaseOperationHandler = class {
2878
3394
  static {
@@ -2917,7 +3433,7 @@ var BaseOperationHandler = class {
2917
3433
  return getField(this.schema, model, field);
2918
3434
  }
2919
3435
  async exists(kysely, model, filter) {
2920
- const idFields = getIdFields(this.schema, model);
3436
+ const idFields = requireIdFields(this.schema, model);
2921
3437
  const _filter = flattenCompoundUniqueFilters(this.schema, model, filter);
2922
3438
  const query = kysely.selectFrom(model).where((eb) => eb.and(_filter)).select(idFields.map((f) => kysely.dynamic.ref(f))).limit(1).modifyEnd(this.makeContextComment({
2923
3439
  model,
@@ -2926,7 +3442,7 @@ var BaseOperationHandler = class {
2926
3442
  return this.executeQueryTakeFirst(kysely, query, "exists");
2927
3443
  }
2928
3444
  async read(kysely, model, args) {
2929
- let query = this.dialect.buildSelectModel((0, import_kysely8.expressionBuilder)(), model, model);
3445
+ let query = this.dialect.buildSelectModel((0, import_kysely10.expressionBuilder)(), model, model);
2930
3446
  if (args) {
2931
3447
  query = this.dialect.buildFilterSortTake(model, args, query, model);
2932
3448
  }
@@ -3005,7 +3521,7 @@ var BaseOperationHandler = class {
3005
3521
  if (!m2m) {
3006
3522
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation?.model ?? "", fromRelation?.field ?? "");
3007
3523
  if (!ownedByModel) {
3008
- const parentFkFields = this.buildFkAssignments(fromRelation.model, fromRelation.field, fromRelation.ids);
3524
+ const parentFkFields = await this.buildFkAssignments(kysely, fromRelation.model, fromRelation.field, fromRelation.ids);
3009
3525
  Object.assign(createFields, parentFkFields);
3010
3526
  } else {
3011
3527
  updateParent = /* @__PURE__ */ __name((entity) => {
@@ -3045,17 +3561,16 @@ var BaseOperationHandler = class {
3045
3561
  createFields = baseCreateResult.remainingFields;
3046
3562
  }
3047
3563
  const updatedData = this.fillGeneratedAndDefaultValues(modelDef, createFields);
3048
- const idFields = getIdFields(this.schema, model);
3564
+ const idFields = requireIdFields(this.schema, model);
3049
3565
  const query = kysely.insertInto(model).$if(Object.keys(updatedData).length === 0, (qb) => qb.defaultValues()).$if(Object.keys(updatedData).length > 0, (qb) => qb.values(updatedData)).returning(idFields).modifyEnd(this.makeContextComment({
3050
3566
  model,
3051
3567
  operation: "create"
3052
3568
  }));
3053
3569
  const createdEntity = await this.executeQueryTakeFirst(kysely, query, "create");
3054
3570
  if (Object.keys(postCreateRelations).length > 0) {
3055
- const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
3056
- return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
3057
- });
3058
- await Promise.all(relationPromises);
3571
+ for (const [field, subPayload] of Object.entries(postCreateRelations)) {
3572
+ await this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
3573
+ }
3059
3574
  }
3060
3575
  if (fromRelation && m2m) {
3061
3576
  await this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, createdEntity, m2m.joinTable);
@@ -3077,7 +3592,7 @@ var BaseOperationHandler = class {
3077
3592
  }
3078
3593
  });
3079
3594
  const discriminatorField = getDiscriminatorField(this.schema, model);
3080
- (0, import_common_helpers8.invariant)(discriminatorField, `Base model "${model}" must have a discriminator field`);
3595
+ (0, import_common_helpers10.invariant)(discriminatorField, `Base model "${model}" must have a discriminator field`);
3081
3596
  thisCreateFields[discriminatorField] = forModel;
3082
3597
  const baseEntity = await this.create(kysely, model, thisCreateFields, void 0, true);
3083
3598
  const idValues = extractIdFields(baseEntity, this.schema, model);
@@ -3087,14 +3602,24 @@ var BaseOperationHandler = class {
3087
3602
  remainingFields
3088
3603
  };
3089
3604
  }
3090
- buildFkAssignments(model, relationField, entity) {
3605
+ async buildFkAssignments(kysely, model, relationField, entity) {
3091
3606
  const parentFkFields = {};
3092
- (0, import_common_helpers8.invariant)(relationField, "parentField must be defined if parentModel is defined");
3093
- (0, import_common_helpers8.invariant)(entity, "parentEntity must be defined if parentModel is defined");
3607
+ (0, import_common_helpers10.invariant)(relationField, "parentField must be defined if parentModel is defined");
3608
+ (0, import_common_helpers10.invariant)(entity, "parentEntity must be defined if parentModel is defined");
3094
3609
  const { keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
3095
3610
  for (const pair of keyPairs) {
3096
3611
  if (!(pair.pk in entity)) {
3097
- throw new QueryError(`Field "${pair.pk}" not found in parent created data`);
3612
+ const extraRead = await this.readUnique(kysely, model, {
3613
+ where: entity,
3614
+ select: {
3615
+ [pair.pk]: true
3616
+ }
3617
+ });
3618
+ if (!extraRead) {
3619
+ throw new QueryError(`Field "${pair.pk}" not found in parent created data`);
3620
+ } else {
3621
+ Object.assign(entity, extraRead);
3622
+ }
3098
3623
  }
3099
3624
  Object.assign(parentFkFields, {
3100
3625
  [pair.fk]: entity[pair.pk]
@@ -3115,15 +3640,15 @@ var BaseOperationHandler = class {
3115
3640
  entity: rightEntity
3116
3641
  }
3117
3642
  ].sort((a, b) => (
3118
- // the implement m2m join table's "A", "B" fk fields' order is determined
3643
+ // the implicit m2m join table's "A", "B" fk fields' order is determined
3119
3644
  // by model name's sort order, and when identical (for self-relations),
3120
3645
  // field name's sort order
3121
3646
  a.model !== b.model ? a.model.localeCompare(b.model) : a.field.localeCompare(b.field)
3122
3647
  ));
3123
- const firstIds = getIdFields(this.schema, sortedRecords[0].model);
3124
- const secondIds = getIdFields(this.schema, sortedRecords[1].model);
3125
- (0, import_common_helpers8.invariant)(firstIds.length === 1, "many-to-many relation must have exactly one id field");
3126
- (0, import_common_helpers8.invariant)(secondIds.length === 1, "many-to-many relation must have exactly one id field");
3648
+ const firstIds = requireIdFields(this.schema, sortedRecords[0].model);
3649
+ const secondIds = requireIdFields(this.schema, sortedRecords[1].model);
3650
+ (0, import_common_helpers10.invariant)(firstIds.length === 1, "many-to-many relation must have exactly one id field");
3651
+ (0, import_common_helpers10.invariant)(secondIds.length === 1, "many-to-many relation must have exactly one id field");
3127
3652
  if (action === "connect") {
3128
3653
  const result = await kysely.insertInto(joinTable).values({
3129
3654
  A: sortedRecords[0].entity[firstIds[0]],
@@ -3134,17 +3659,17 @@ var BaseOperationHandler = class {
3134
3659
  ]).doNothing()).execute();
3135
3660
  return result[0];
3136
3661
  } else {
3137
- const eb = (0, import_kysely8.expressionBuilder)();
3662
+ const eb = (0, import_kysely10.expressionBuilder)();
3138
3663
  const result = await kysely.deleteFrom(joinTable).where(eb(`${joinTable}.A`, "=", sortedRecords[0].entity[firstIds[0]])).where(eb(`${joinTable}.B`, "=", sortedRecords[1].entity[secondIds[0]])).execute();
3139
3664
  return result[0];
3140
3665
  }
3141
3666
  }
3142
3667
  resetManyToManyRelation(kysely, model, field, parentIds) {
3143
- (0, import_common_helpers8.invariant)(Object.keys(parentIds).length === 1, "parentIds must have exactly one field");
3668
+ (0, import_common_helpers10.invariant)(Object.keys(parentIds).length === 1, "parentIds must have exactly one field");
3144
3669
  const parentId = Object.values(parentIds)[0];
3145
3670
  const m2m = getManyToManyRelation(this.schema, model, field);
3146
- (0, import_common_helpers8.invariant)(m2m, "not a many-to-many relation");
3147
- const eb = (0, import_kysely8.expressionBuilder)();
3671
+ (0, import_common_helpers10.invariant)(m2m, "not a many-to-many relation");
3672
+ const eb = (0, import_kysely10.expressionBuilder)();
3148
3673
  return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
3149
3674
  }
3150
3675
  async processOwnedRelationForCreate(kysely, relationField, payload) {
@@ -3165,7 +3690,7 @@ var BaseOperationHandler = class {
3165
3690
  }
3166
3691
  case "connect": {
3167
3692
  const referencedPkFields = relationField.relation.references;
3168
- (0, import_common_helpers8.invariant)(referencedPkFields, "relation must have fields info");
3693
+ (0, import_common_helpers10.invariant)(referencedPkFields, "relation must have fields info");
3169
3694
  const extractedFks = extractFields(subPayload, referencedPkFields);
3170
3695
  if (Object.keys(extractedFks).length === referencedPkFields.length) {
3171
3696
  result = extractedFks;
@@ -3197,10 +3722,9 @@ var BaseOperationHandler = class {
3197
3722
  }
3198
3723
  return result;
3199
3724
  }
3200
- processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
3725
+ async processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
3201
3726
  const relationFieldDef = this.requireField(contextModel, relationFieldName);
3202
3727
  const relationModel = relationFieldDef.type;
3203
- const tasks = [];
3204
3728
  const fromRelationContext = {
3205
3729
  model: contextModel,
3206
3730
  field: relationFieldName,
@@ -3213,27 +3737,35 @@ var BaseOperationHandler = class {
3213
3737
  }
3214
3738
  switch (action) {
3215
3739
  case "create": {
3216
- tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, fromRelationContext)));
3740
+ for (const item of enumerate(subPayload)) {
3741
+ await this.create(kysely, relationModel, item, fromRelationContext);
3742
+ }
3217
3743
  break;
3218
3744
  }
3219
3745
  case "createMany": {
3220
- (0, import_common_helpers8.invariant)(relationFieldDef.array, "relation must be an array for createMany");
3221
- tasks.push(this.createMany(kysely, relationModel, subPayload, false, fromRelationContext));
3746
+ (0, import_common_helpers10.invariant)(relationFieldDef.array, "relation must be an array for createMany");
3747
+ await this.createMany(kysely, relationModel, subPayload, false, fromRelationContext);
3222
3748
  break;
3223
3749
  }
3224
3750
  case "connect": {
3225
- tasks.push(this.connectRelation(kysely, relationModel, subPayload, fromRelationContext));
3751
+ await this.connectRelation(kysely, relationModel, subPayload, fromRelationContext);
3226
3752
  break;
3227
3753
  }
3228
3754
  case "connectOrCreate": {
3229
- tasks.push(...enumerate(subPayload).map((item) => this.exists(kysely, relationModel, item.where).then((found) => !found ? this.create(kysely, relationModel, item.create, fromRelationContext) : this.connectRelation(kysely, relationModel, found, fromRelationContext))));
3755
+ for (const item of enumerate(subPayload)) {
3756
+ const found = await this.exists(kysely, relationModel, item.where);
3757
+ if (!found) {
3758
+ await this.create(kysely, relationModel, item.create, fromRelationContext);
3759
+ } else {
3760
+ await this.connectRelation(kysely, relationModel, found, fromRelationContext);
3761
+ }
3762
+ }
3230
3763
  break;
3231
3764
  }
3232
3765
  default:
3233
3766
  throw new QueryError(`Invalid relation action: ${action}`);
3234
3767
  }
3235
3768
  }
3236
- return Promise.all(tasks);
3237
3769
  }
3238
3770
  async createMany(kysely, model, input, returnData, fromRelation) {
3239
3771
  if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
@@ -3254,7 +3786,7 @@ var BaseOperationHandler = class {
3254
3786
  const newItem = {};
3255
3787
  for (const [name, value] of Object.entries(item)) {
3256
3788
  const fieldDef = this.requireField(model, name);
3257
- (0, import_common_helpers8.invariant)(!fieldDef.relation, "createMany does not support relations");
3789
+ (0, import_common_helpers10.invariant)(!fieldDef.relation, "createMany does not support relations");
3258
3790
  newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
3259
3791
  }
3260
3792
  if (fromRelation) {
@@ -3304,7 +3836,7 @@ var BaseOperationHandler = class {
3304
3836
  count: Number(result.numAffectedRows)
3305
3837
  };
3306
3838
  } else {
3307
- const idFields = getIdFields(this.schema, model);
3839
+ const idFields = requireIdFields(this.schema, model);
3308
3840
  const result = await query.returning(idFields).execute();
3309
3841
  return result;
3310
3842
  }
@@ -3313,7 +3845,7 @@ var BaseOperationHandler = class {
3313
3845
  const thisCreateRows = [];
3314
3846
  const remainingFieldRows = [];
3315
3847
  const discriminatorField = getDiscriminatorField(this.schema, model);
3316
- (0, import_common_helpers8.invariant)(discriminatorField, `Base model "${model}" must have a discriminator field`);
3848
+ (0, import_common_helpers10.invariant)(discriminatorField, `Base model "${model}" must have a discriminator field`);
3317
3849
  for (const createFields of createRows) {
3318
3850
  const thisCreateFields = {};
3319
3851
  const remainingFields = {};
@@ -3409,7 +3941,7 @@ var BaseOperationHandler = class {
3409
3941
  }
3410
3942
  } else {
3411
3943
  const fromRelationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
3412
- (0, import_common_helpers8.invariant)(fromRelationFieldDef.relation?.opposite);
3944
+ (0, import_common_helpers10.invariant)(fromRelationFieldDef.relation?.opposite);
3413
3945
  parentWhere[fromRelationFieldDef.relation.opposite] = {
3414
3946
  some: fromRelation.ids
3415
3947
  };
@@ -3467,10 +3999,7 @@ var BaseOperationHandler = class {
3467
3999
  throw new QueryError(`Relation update not allowed for field "${field}"`);
3468
4000
  }
3469
4001
  if (!thisEntity) {
3470
- thisEntity = await this.readUnique(kysely, model, {
3471
- where: combinedWhere,
3472
- select: this.makeIdSelect(model)
3473
- });
4002
+ thisEntity = await this.getEntityIds(kysely, model, combinedWhere);
3474
4003
  if (!thisEntity) {
3475
4004
  if (throwIfNotFound) {
3476
4005
  throw new NotFoundError(model);
@@ -3488,7 +4017,7 @@ var BaseOperationHandler = class {
3488
4017
  if (Object.keys(updateFields).length === 0) {
3489
4018
  return combinedWhere;
3490
4019
  } else {
3491
- const idFields = getIdFields(this.schema, model);
4020
+ const idFields = requireIdFields(this.schema, model);
3492
4021
  const query = kysely.updateTable(model).where((eb) => this.dialect.buildFilter(eb, model, model, combinedWhere)).set(updateFields).returning(idFields).modifyEnd(this.makeContextComment({
3493
4022
  model,
3494
4023
  operation: "update"
@@ -3533,7 +4062,7 @@ var BaseOperationHandler = class {
3533
4062
  if (!filter || typeof filter !== "object") {
3534
4063
  return false;
3535
4064
  }
3536
- const idFields = getIdFields(this.schema, model);
4065
+ const idFields = requireIdFields(this.schema, model);
3537
4066
  return idFields.length === Object.keys(filter).length && idFields.every((field) => field in filter);
3538
4067
  }
3539
4068
  async processBaseModelUpdate(kysely, model, where, updateFields, throwIfNotFound) {
@@ -3554,20 +4083,20 @@ var BaseOperationHandler = class {
3554
4083
  };
3555
4084
  }
3556
4085
  transformIncrementalUpdate(model, field, fieldDef, payload) {
3557
- (0, import_common_helpers8.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
4086
+ (0, import_common_helpers10.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
3558
4087
  const key = Object.keys(payload)[0];
3559
4088
  const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
3560
- const eb = (0, import_kysely8.expressionBuilder)();
4089
+ const eb = (0, import_kysely10.expressionBuilder)();
3561
4090
  const fieldRef = this.dialect.fieldRef(model, field, eb);
3562
4091
  return (0, import_ts_pattern9.match)(key).with("set", () => value).with("increment", () => eb(fieldRef, "+", value)).with("decrement", () => eb(fieldRef, "-", value)).with("multiply", () => eb(fieldRef, "*", value)).with("divide", () => eb(fieldRef, "/", value)).otherwise(() => {
3563
4092
  throw new InternalError(`Invalid incremental update operation: ${key}`);
3564
4093
  });
3565
4094
  }
3566
4095
  transformScalarListUpdate(model, field, fieldDef, payload) {
3567
- (0, import_common_helpers8.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
4096
+ (0, import_common_helpers10.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
3568
4097
  const key = Object.keys(payload)[0];
3569
4098
  const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
3570
- const eb = (0, import_kysely8.expressionBuilder)();
4099
+ const eb = (0, import_kysely10.expressionBuilder)();
3571
4100
  const fieldRef = this.dialect.fieldRef(model, field, eb);
3572
4101
  return (0, import_ts_pattern9.match)(key).with("set", () => value).with("push", () => {
3573
4102
  return eb(fieldRef, "||", eb.val(ensureArray(value)));
@@ -3579,7 +4108,7 @@ var BaseOperationHandler = class {
3579
4108
  return NUMERIC_FIELD_TYPES.includes(fieldDef.type) && !fieldDef.array;
3580
4109
  }
3581
4110
  makeContextComment(_context) {
3582
- return import_kysely8.sql``;
4111
+ return import_kysely10.sql``;
3583
4112
  }
3584
4113
  async updateMany(kysely, model, where, data, limit, returnData, filterModel) {
3585
4114
  if (typeof data !== "object") {
@@ -3638,7 +4167,7 @@ var BaseOperationHandler = class {
3638
4167
  count: Number(result.numAffectedRows)
3639
4168
  };
3640
4169
  } else {
3641
- const idFields = getIdFields(this.schema, model);
4170
+ const idFields = requireIdFields(this.schema, model);
3642
4171
  const result = await query.returning(idFields).execute();
3643
4172
  return result;
3644
4173
  }
@@ -3661,11 +4190,10 @@ var BaseOperationHandler = class {
3661
4190
  };
3662
4191
  }
3663
4192
  buildIdFieldRefs(kysely, model) {
3664
- const idFields = getIdFields(this.schema, model);
4193
+ const idFields = requireIdFields(this.schema, model);
3665
4194
  return idFields.map((f) => kysely.dynamic.ref(`${model}.${f}`));
3666
4195
  }
3667
4196
  async processRelationUpdates(kysely, model, field, fieldDef, parentIds, args, throwIfNotFound) {
3668
- const tasks = [];
3669
4197
  const fieldModel = fieldDef.type;
3670
4198
  const fromRelationContext = {
3671
4199
  model,
@@ -3676,68 +4204,73 @@ var BaseOperationHandler = class {
3676
4204
  for (const [key, value] of Object.entries(args)) {
3677
4205
  switch (key) {
3678
4206
  case "create": {
3679
- (0, import_common_helpers8.invariant)(!Array.isArray(value) || fieldDef.array, "relation must be an array if create is an array");
3680
- tasks.push(...enumerate(value).map((item) => this.create(kysely, fieldModel, item, fromRelationContext)));
4207
+ (0, import_common_helpers10.invariant)(!Array.isArray(value) || fieldDef.array, "relation must be an array if create is an array");
4208
+ for (const item of enumerate(value)) {
4209
+ await this.create(kysely, fieldModel, item, fromRelationContext);
4210
+ }
3681
4211
  break;
3682
4212
  }
3683
4213
  case "createMany": {
3684
- (0, import_common_helpers8.invariant)(fieldDef.array, "relation must be an array for createMany");
3685
- tasks.push(this.createMany(kysely, fieldModel, value, false, fromRelationContext));
4214
+ (0, import_common_helpers10.invariant)(fieldDef.array, "relation must be an array for createMany");
4215
+ await this.createMany(kysely, fieldModel, value, false, fromRelationContext);
3686
4216
  break;
3687
4217
  }
3688
4218
  case "connect": {
3689
- tasks.push(this.connectRelation(kysely, fieldModel, value, fromRelationContext));
4219
+ await this.connectRelation(kysely, fieldModel, value, fromRelationContext);
3690
4220
  break;
3691
4221
  }
3692
4222
  case "connectOrCreate": {
3693
- tasks.push(this.connectOrCreateRelation(kysely, fieldModel, value, fromRelationContext));
4223
+ await this.connectOrCreateRelation(kysely, fieldModel, value, fromRelationContext);
3694
4224
  break;
3695
4225
  }
3696
4226
  case "disconnect": {
3697
- tasks.push(this.disconnectRelation(kysely, fieldModel, value, fromRelationContext));
4227
+ await this.disconnectRelation(kysely, fieldModel, value, fromRelationContext);
3698
4228
  break;
3699
4229
  }
3700
4230
  case "set": {
3701
- (0, import_common_helpers8.invariant)(fieldDef.array, "relation must be an array");
3702
- tasks.push(this.setRelation(kysely, fieldModel, value, fromRelationContext));
4231
+ (0, import_common_helpers10.invariant)(fieldDef.array, "relation must be an array");
4232
+ await this.setRelation(kysely, fieldModel, value, fromRelationContext);
3703
4233
  break;
3704
4234
  }
3705
4235
  case "update": {
3706
- tasks.push(...enumerate(value).map((item) => {
4236
+ for (const _item of enumerate(value)) {
4237
+ const item = _item;
3707
4238
  let where;
3708
4239
  let data;
3709
- if ("where" in item) {
4240
+ if ("data" in item && typeof item.data === "object") {
3710
4241
  where = item.where;
3711
4242
  data = item.data;
3712
4243
  } else {
3713
4244
  where = void 0;
3714
4245
  data = item;
3715
4246
  }
3716
- return this.update(kysely, fieldModel, where, data, fromRelationContext, true, throwIfNotFound);
3717
- }));
4247
+ await this.update(kysely, fieldModel, where, data, fromRelationContext, true, throwIfNotFound);
4248
+ }
3718
4249
  break;
3719
4250
  }
3720
4251
  case "upsert": {
3721
- tasks.push(...enumerate(value).map(async (item) => {
4252
+ for (const _item of enumerate(value)) {
4253
+ const item = _item;
3722
4254
  const updated = await this.update(kysely, fieldModel, item.where, item.update, fromRelationContext, true, false);
3723
- if (updated) {
3724
- return updated;
3725
- } else {
3726
- return this.create(kysely, fieldModel, item.create, fromRelationContext);
4255
+ if (!updated) {
4256
+ await this.create(kysely, fieldModel, item.create, fromRelationContext);
3727
4257
  }
3728
- }));
4258
+ }
3729
4259
  break;
3730
4260
  }
3731
4261
  case "updateMany": {
3732
- tasks.push(...enumerate(value).map((item) => this.update(kysely, fieldModel, item.where, item.data, fromRelationContext, false, false)));
4262
+ for (const _item of enumerate(value)) {
4263
+ const item = _item;
4264
+ await this.update(kysely, fieldModel, item.where, item.data, fromRelationContext, false, false);
4265
+ }
3733
4266
  break;
3734
4267
  }
3735
4268
  case "delete": {
3736
- tasks.push(this.deleteRelation(kysely, fieldModel, value, fromRelationContext, true));
4269
+ await this.deleteRelation(kysely, fieldModel, value, fromRelationContext, true);
3737
4270
  break;
3738
4271
  }
3739
4272
  case "deleteMany": {
3740
- tasks.push(this.deleteRelation(kysely, fieldModel, value, fromRelationContext, false));
4273
+ await this.deleteRelation(kysely, fieldModel, value, fromRelationContext, false);
3741
4274
  break;
3742
4275
  }
3743
4276
  default: {
@@ -3745,7 +4278,6 @@ var BaseOperationHandler = class {
3745
4278
  }
3746
4279
  }
3747
4280
  }
3748
- await Promise.all(tasks);
3749
4281
  return fromRelationContext.parentUpdates;
3750
4282
  }
3751
4283
  // #region relation manipulation
@@ -3756,18 +4288,22 @@ var BaseOperationHandler = class {
3756
4288
  }
3757
4289
  const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
3758
4290
  if (m2m) {
3759
- const actions = _data.map(async (d) => {
4291
+ const results = [];
4292
+ for (const d of _data) {
3760
4293
  const ids = await this.getEntityIds(kysely, model, d);
3761
- return this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable);
3762
- });
3763
- const results = await Promise.all(actions);
4294
+ if (!ids) {
4295
+ throw new NotFoundError(model);
4296
+ }
4297
+ const r = await this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable);
4298
+ results.push(r);
4299
+ }
3764
4300
  if (_data.length > results.filter((r) => !!r).length) {
3765
4301
  throw new NotFoundError(model);
3766
4302
  }
3767
4303
  } else {
3768
4304
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
3769
4305
  if (ownedByModel) {
3770
- (0, import_common_helpers8.invariant)(_data.length === 1, "only one entity can be connected");
4306
+ (0, import_common_helpers10.invariant)(_data.length === 1, "only one entity can be connected");
3771
4307
  const target = await this.readUnique(kysely, model, {
3772
4308
  where: _data[0]
3773
4309
  });
@@ -3780,7 +4316,7 @@ var BaseOperationHandler = class {
3780
4316
  } else {
3781
4317
  const relationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
3782
4318
  if (!relationFieldDef.array) {
3783
- const query2 = kysely.updateTable(model).where((eb) => eb.and(keyPairs.map(({ fk, pk }) => eb(import_kysely8.sql.ref(fk), "=", fromRelation.ids[pk])))).set(keyPairs.reduce((acc, { fk }) => ({
4319
+ const query2 = kysely.updateTable(model).where((eb) => eb.and(keyPairs.map(({ fk, pk }) => eb(import_kysely10.sql.ref(fk), "=", fromRelation.ids[pk])))).set(keyPairs.reduce((acc, { fk }) => ({
3784
4320
  ...acc,
3785
4321
  [fk]: null
3786
4322
  }), {})).modifyEnd(this.makeContextComment({
@@ -3808,16 +4344,16 @@ var BaseOperationHandler = class {
3808
4344
  if (_data.length === 0) {
3809
4345
  return;
3810
4346
  }
3811
- return Promise.all(_data.map(async ({ where, create }) => {
4347
+ for (const { where, create } of _data) {
3812
4348
  const existing = await this.exists(kysely, model, where);
3813
4349
  if (existing) {
3814
- return this.connectRelation(kysely, model, [
4350
+ await this.connectRelation(kysely, model, [
3815
4351
  where
3816
4352
  ], fromRelation);
3817
4353
  } else {
3818
- return this.create(kysely, model, create, fromRelation);
4354
+ await this.create(kysely, model, create, fromRelation);
3819
4355
  }
3820
- }));
4356
+ }
3821
4357
  }
3822
4358
  async disconnectRelation(kysely, model, data, fromRelation) {
3823
4359
  let disconnectConditions = [];
@@ -3840,19 +4376,18 @@ var BaseOperationHandler = class {
3840
4376
  }
3841
4377
  const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
3842
4378
  if (m2m) {
3843
- const actions = disconnectConditions.map(async (d) => {
4379
+ for (const d of disconnectConditions) {
3844
4380
  const ids = await this.getEntityIds(kysely, model, d);
3845
4381
  if (!ids) {
3846
4382
  return;
3847
4383
  }
3848
- return this.handleManyToManyRelation(kysely, "disconnect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable);
3849
- });
3850
- await Promise.all(actions);
4384
+ await this.handleManyToManyRelation(kysely, "disconnect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable);
4385
+ }
3851
4386
  } else {
3852
4387
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
3853
- const eb = (0, import_kysely8.expressionBuilder)();
4388
+ const eb = (0, import_kysely10.expressionBuilder)();
3854
4389
  if (ownedByModel) {
3855
- (0, import_common_helpers8.invariant)(disconnectConditions.length === 1, "only one entity can be disconnected");
4390
+ (0, import_common_helpers10.invariant)(disconnectConditions.length === 1, "only one entity can be disconnected");
3856
4391
  const condition = disconnectConditions[0];
3857
4392
  if (condition === true) {
3858
4393
  for (const { fk } of keyPairs) {
@@ -3911,11 +4446,14 @@ var BaseOperationHandler = class {
3911
4446
  const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
3912
4447
  if (m2m) {
3913
4448
  await this.resetManyToManyRelation(kysely, fromRelation.model, fromRelation.field, fromRelation.ids);
3914
- const actions = _data.map(async (d) => {
4449
+ const results = [];
4450
+ for (const d of _data) {
3915
4451
  const ids = await this.getEntityIds(kysely, model, d);
3916
- return this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable);
3917
- });
3918
- const results = await Promise.all(actions);
4452
+ if (!ids) {
4453
+ throw new NotFoundError(model);
4454
+ }
4455
+ results.push(await this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable));
4456
+ }
3919
4457
  if (_data.length > results.filter((r) => !!r).length) {
3920
4458
  throw new NotFoundError(model);
3921
4459
  }
@@ -3981,7 +4519,7 @@ var BaseOperationHandler = class {
3981
4519
  if (m2m) {
3982
4520
  deleteFromModel = model;
3983
4521
  const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
3984
- (0, import_common_helpers8.invariant)(fieldDef.relation?.opposite);
4522
+ (0, import_common_helpers10.invariant)(fieldDef.relation?.opposite);
3985
4523
  deleteResult = await this.delete(kysely, model, {
3986
4524
  AND: [
3987
4525
  {
@@ -4005,7 +4543,7 @@ var BaseOperationHandler = class {
4005
4543
  throw new NotFoundError(fromRelation.model);
4006
4544
  }
4007
4545
  const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
4008
- (0, import_common_helpers8.invariant)(fieldDef.relation?.opposite);
4546
+ (0, import_common_helpers10.invariant)(fieldDef.relation?.opposite);
4009
4547
  deleteResult = await this.delete(kysely, model, {
4010
4548
  AND: [
4011
4549
  // filter for parent
@@ -4135,7 +4673,7 @@ var BaseOperationHandler = class {
4135
4673
  // reused the filter if it's a complete id filter (without extra fields)
4136
4674
  // otherwise, read the entity by the filter
4137
4675
  getEntityIds(kysely, model, uniqueFilter) {
4138
- const idFields = getIdFields(this.schema, model);
4676
+ const idFields = requireIdFields(this.schema, model);
4139
4677
  if (
4140
4678
  // all id fields are provided
4141
4679
  idFields.every((f) => f in uniqueFilter && uniqueFilter[f] !== void 0) && // no non-id filter exists
@@ -4163,7 +4701,7 @@ var BaseOperationHandler = class {
4163
4701
  for (const [key, value] of Object.entries(args)) {
4164
4702
  if (value === void 0) {
4165
4703
  delete args[key];
4166
- } else if (value && (0, import_common_helpers8.isPlainObject)(value)) {
4704
+ } else if (value && (0, import_common_helpers10.isPlainObject)(value)) {
4167
4705
  this.doNormalizeArgs(value);
4168
4706
  }
4169
4707
  }
@@ -4237,7 +4775,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
4237
4775
  if (field === "_all") {
4238
4776
  query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as(`_count._all`));
4239
4777
  } else {
4240
- query = query.select((eb) => eb.cast(eb.fn.count(import_kysely9.sql.ref(`$sub.${field}`)), "integer").as(`${key}.${field}`));
4778
+ query = query.select((eb) => eb.cast(eb.fn.count(import_kysely11.sql.ref(`$sub.${field}`)), "integer").as(`${key}.${field}`));
4241
4779
  }
4242
4780
  }
4243
4781
  });
@@ -4252,7 +4790,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
4252
4790
  if (val === true) {
4253
4791
  query = query.select((eb) => {
4254
4792
  const fn = (0, import_ts_pattern10.match)(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
4255
- return fn(import_kysely9.sql.ref(`$sub.${field}`)).as(`${key}.${field}`);
4793
+ return fn(import_kysely11.sql.ref(`$sub.${field}`)).as(`${key}.${field}`);
4256
4794
  });
4257
4795
  }
4258
4796
  });
@@ -4299,7 +4837,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
4299
4837
  };
4300
4838
 
4301
4839
  // src/client/crud/operations/count.ts
4302
- var import_kysely10 = require("kysely");
4840
+ var import_kysely12 = require("kysely");
4303
4841
  var CountOperationHandler = class extends BaseOperationHandler {
4304
4842
  static {
4305
4843
  __name(this, "CountOperationHandler");
@@ -4323,7 +4861,7 @@ var CountOperationHandler = class extends BaseOperationHandler {
4323
4861
  return subQuery.as(subQueryName);
4324
4862
  });
4325
4863
  if (parsedArgs?.select && typeof parsedArgs.select === "object") {
4326
- query = query.select((eb) => Object.keys(parsedArgs.select).map((key) => key === "_all" ? eb.cast(eb.fn.countAll(), "integer").as("_all") : eb.cast(eb.fn.count(import_kysely10.sql.ref(`${subQueryName}.${key}`)), "integer").as(key)));
4864
+ query = query.select((eb) => Object.keys(parsedArgs.select).map((key) => key === "_all" ? eb.cast(eb.fn.countAll(), "integer").as("_all") : eb.cast(eb.fn.count(import_kysely12.sql.ref(`${subQueryName}.${key}`)), "integer").as(key)));
4327
4865
  const result = await this.executeQuery(this.kysely, query, "count");
4328
4866
  return result.rows[0];
4329
4867
  } else {
@@ -4359,7 +4897,7 @@ var CreateOperationHandler = class extends BaseOperationHandler {
4359
4897
  });
4360
4898
  });
4361
4899
  if (!result && this.hasPolicyEnabled) {
4362
- throw new RejectedByPolicyError(this.model, `result is not allowed to be read back`);
4900
+ throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, `result is not allowed to be read back`);
4363
4901
  }
4364
4902
  return result;
4365
4903
  }
@@ -4405,15 +4943,15 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
4405
4943
  omit: args.omit,
4406
4944
  where: args.where
4407
4945
  });
4408
- if (!existing) {
4409
- throw new NotFoundError(this.model);
4410
- }
4411
4946
  await this.safeTransaction(async (tx) => {
4412
4947
  const result = await this.delete(tx, this.model, args.where);
4413
4948
  if (result.count === 0) {
4414
4949
  throw new NotFoundError(this.model);
4415
4950
  }
4416
4951
  });
4952
+ if (!existing && this.hasPolicyEnabled) {
4953
+ throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
4954
+ }
4417
4955
  return existing;
4418
4956
  }
4419
4957
  async runDeleteMany(args) {
@@ -4447,7 +4985,7 @@ var FindOperationHandler = class extends BaseOperationHandler {
4447
4985
  };
4448
4986
 
4449
4987
  // src/client/crud/operations/group-by.ts
4450
- var import_kysely11 = require("kysely");
4988
+ var import_kysely13 = require("kysely");
4451
4989
  var import_ts_pattern13 = require("ts-pattern");
4452
4990
  var GroupByOperationHandler = class extends BaseOperationHandler {
4453
4991
  static {
@@ -4469,7 +5007,7 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
4469
5007
  subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
4470
5008
  return subQuery.as("$sub");
4471
5009
  });
4472
- const fieldRef = /* @__PURE__ */ __name((field) => this.dialect.fieldRef(this.model, field, (0, import_kysely11.expressionBuilder)(), "$sub"), "fieldRef");
5010
+ const fieldRef = /* @__PURE__ */ __name((field) => this.dialect.fieldRef(this.model, field, (0, import_kysely13.expressionBuilder)(), "$sub"), "fieldRef");
4473
5011
  const bys = typeof parsedArgs.by === "string" ? [
4474
5012
  parsedArgs.by
4475
5013
  ] : parsedArgs.by;
@@ -4584,7 +5122,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
4584
5122
  });
4585
5123
  if (!readBackResult) {
4586
5124
  if (this.hasPolicyEnabled) {
4587
- throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
5125
+ throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
4588
5126
  } else {
4589
5127
  return null;
4590
5128
  }
@@ -4601,16 +5139,24 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
4601
5139
  if (!args) {
4602
5140
  return [];
4603
5141
  }
4604
- return this.safeTransaction(async (tx) => {
4605
- const updateResult = await this.updateMany(tx, this.model, args.where, args.data, args.limit, true);
4606
- return this.read(tx, this.model, {
5142
+ const { readBackResult, updateResult } = await this.safeTransaction(async (tx) => {
5143
+ const updateResult2 = await this.updateMany(tx, this.model, args.where, args.data, args.limit, true);
5144
+ const readBackResult2 = await this.read(tx, this.model, {
4607
5145
  select: args.select,
4608
5146
  omit: args.omit,
4609
5147
  where: {
4610
- OR: updateResult.map((item) => getIdValues(this.schema, this.model, item))
5148
+ OR: updateResult2.map((item) => getIdValues(this.schema, this.model, item))
4611
5149
  }
4612
5150
  });
5151
+ return {
5152
+ readBackResult: readBackResult2,
5153
+ updateResult: updateResult2
5154
+ };
4613
5155
  });
5156
+ if (readBackResult.length < updateResult.length && this.hasPolicyEnabled) {
5157
+ throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
5158
+ }
5159
+ return readBackResult;
4614
5160
  }
4615
5161
  async runUpsert(args) {
4616
5162
  const result = await this.safeTransaction(async (tx) => {
@@ -4626,18 +5172,32 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
4626
5172
  });
4627
5173
  });
4628
5174
  if (!result && this.hasPolicyEnabled) {
4629
- throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
5175
+ throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
4630
5176
  }
4631
5177
  return result;
4632
5178
  }
4633
5179
  };
4634
5180
 
4635
5181
  // src/client/crud/validator.ts
4636
- var import_common_helpers9 = require("@zenstackhq/common-helpers");
4637
- var import_decimal = __toESM(require("decimal.js"), 1);
5182
+ var import_common_helpers11 = require("@zenstackhq/common-helpers");
5183
+ var import_decimal3 = __toESM(require("decimal.js"), 1);
4638
5184
  var import_json_stable_stringify = __toESM(require("json-stable-stringify"), 1);
4639
5185
  var import_ts_pattern15 = require("ts-pattern");
4640
5186
  var import_zod = require("zod");
5187
+
5188
+ // src/utils/zod-utils.ts
5189
+ var import_v3 = require("zod-validation-error/v3");
5190
+ var import_v4 = require("zod-validation-error/v4");
5191
+ function formatError(error) {
5192
+ if ("_zod" in error) {
5193
+ return (0, import_v4.fromError)(error).toString();
5194
+ } else {
5195
+ return (0, import_v3.fromError)(error).toString();
5196
+ }
5197
+ }
5198
+ __name(formatError, "formatError");
5199
+
5200
+ // src/client/crud/validator.ts
4641
5201
  var InputValidator = class {
4642
5202
  static {
4643
5203
  __name(this, "InputValidator");
@@ -4699,7 +5259,7 @@ var InputValidator = class {
4699
5259
  }
4700
5260
  const { error } = schema.safeParse(args);
4701
5261
  if (error) {
4702
- throw new InputValidationError(`Invalid ${operation} args: ${error.message}`, error);
5262
+ throw new InputValidationError(`Invalid ${operation} args: ${formatError(error)}`, error);
4703
5263
  }
4704
5264
  return args;
4705
5265
  }
@@ -4743,7 +5303,7 @@ var InputValidator = class {
4743
5303
  import_zod.z.bigint()
4744
5304
  ])).with("Decimal", () => import_zod.z.union([
4745
5305
  import_zod.z.number(),
4746
- import_zod.z.instanceof(import_decimal.default),
5306
+ import_zod.z.instanceof(import_decimal3.default),
4747
5307
  import_zod.z.string()
4748
5308
  ])).with("DateTime", () => import_zod.z.union([
4749
5309
  import_zod.z.date(),
@@ -4758,7 +5318,7 @@ var InputValidator = class {
4758
5318
  return schema;
4759
5319
  }
4760
5320
  const typeDef = this.schema.typeDefs?.[type];
4761
- (0, import_common_helpers9.invariant)(typeDef, `Type definition "${type}" not found in schema`);
5321
+ (0, import_common_helpers11.invariant)(typeDef, `Type definition "${type}" not found in schema`);
4762
5322
  schema = import_zod.z.object(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
4763
5323
  let fieldSchema = this.makePrimitiveSchema(def.type);
4764
5324
  if (def.array) {
@@ -4826,7 +5386,7 @@ var InputValidator = class {
4826
5386
  for (const uniqueField of uniqueFields) {
4827
5387
  if ("defs" in uniqueField) {
4828
5388
  fields[uniqueField.name] = import_zod.z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
4829
- (0, import_common_helpers9.invariant)(!def.relation, "unique field cannot be a relation");
5389
+ (0, import_common_helpers11.invariant)(!def.relation, "unique field cannot be a relation");
4830
5390
  let fieldSchema;
4831
5391
  const enumDef = getEnum(this.schema, def.type);
4832
5392
  if (enumDef) {
@@ -5032,9 +5592,16 @@ var InputValidator = class {
5032
5592
  fields[field] = import_zod.z.boolean().optional();
5033
5593
  }
5034
5594
  }
5595
+ const _countSchema = this.makeCountSelectionSchema(modelDef);
5596
+ if (_countSchema) {
5597
+ fields["_count"] = _countSchema;
5598
+ }
5599
+ return import_zod.z.strictObject(fields);
5600
+ }
5601
+ makeCountSelectionSchema(modelDef) {
5035
5602
  const toManyRelations = Object.values(modelDef.fields).filter((def) => def.relation && def.array);
5036
5603
  if (toManyRelations.length > 0) {
5037
- fields["_count"] = import_zod.z.union([
5604
+ return import_zod.z.union([
5038
5605
  import_zod.z.literal(true),
5039
5606
  import_zod.z.strictObject({
5040
5607
  select: import_zod.z.strictObject(toManyRelations.reduce((acc, fieldDef) => ({
@@ -5048,8 +5615,9 @@ var InputValidator = class {
5048
5615
  }), {}))
5049
5616
  })
5050
5617
  ]).optional();
5618
+ } else {
5619
+ return void 0;
5051
5620
  }
5052
- return import_zod.z.strictObject(fields);
5053
5621
  }
5054
5622
  makeRelationSelectIncludeSchema(fieldDef) {
5055
5623
  let objSchema = import_zod.z.strictObject({
@@ -5096,6 +5664,10 @@ var InputValidator = class {
5096
5664
  fields[field] = this.makeRelationSelectIncludeSchema(fieldDef).optional();
5097
5665
  }
5098
5666
  }
5667
+ const _countSchema = this.makeCountSelectionSchema(modelDef);
5668
+ if (_countSchema) {
5669
+ fields["_count"] = _countSchema;
5670
+ }
5099
5671
  return import_zod.z.strictObject(fields);
5100
5672
  }
5101
5673
  makeOrderBySchema(model, withRelation, WithAggregation) {
@@ -5162,13 +5734,15 @@ var InputValidator = class {
5162
5734
  // #region Create
5163
5735
  makeCreateSchema(model) {
5164
5736
  const dataSchema = this.makeCreateDataSchema(model, false);
5165
- const schema = import_zod.z.strictObject({
5737
+ let schema = import_zod.z.strictObject({
5166
5738
  data: dataSchema,
5167
5739
  select: this.makeSelectSchema(model).optional(),
5168
5740
  include: this.makeIncludeSchema(model).optional(),
5169
5741
  omit: this.makeOmitSchema(model).optional()
5170
5742
  });
5171
- return this.refineForSelectIncludeMutuallyExclusive(schema);
5743
+ schema = this.refineForSelectIncludeMutuallyExclusive(schema);
5744
+ schema = this.refineForSelectOmitMutuallyExclusive(schema);
5745
+ return schema;
5172
5746
  }
5173
5747
  makeCreateManySchema(model) {
5174
5748
  return this.makeCreateManyDataSchema(model, []).optional();
@@ -5293,11 +5867,11 @@ var InputValidator = class {
5293
5867
  fields["delete"] = this.makeDeleteRelationDataSchema(fieldType, array, true).optional();
5294
5868
  }
5295
5869
  fields["update"] = array ? this.orArray(import_zod.z.strictObject({
5296
- where: this.makeWhereSchema(fieldType, true),
5870
+ where: this.makeWhereSchema(fieldType, true).optional(),
5297
5871
  data: this.makeUpdateDataSchema(fieldType, withoutFields)
5298
5872
  }), true).optional() : import_zod.z.union([
5299
5873
  import_zod.z.strictObject({
5300
- where: this.makeWhereSchema(fieldType, true),
5874
+ where: this.makeWhereSchema(fieldType, true).optional(),
5301
5875
  data: this.makeUpdateDataSchema(fieldType, withoutFields)
5302
5876
  }),
5303
5877
  this.makeUpdateDataSchema(fieldType, withoutFields)
@@ -5357,14 +5931,16 @@ var InputValidator = class {
5357
5931
  // #endregion
5358
5932
  // #region Update
5359
5933
  makeUpdateSchema(model) {
5360
- const schema = import_zod.z.strictObject({
5934
+ let schema = import_zod.z.strictObject({
5361
5935
  where: this.makeWhereSchema(model, true),
5362
5936
  data: this.makeUpdateDataSchema(model),
5363
5937
  select: this.makeSelectSchema(model).optional(),
5364
5938
  include: this.makeIncludeSchema(model).optional(),
5365
5939
  omit: this.makeOmitSchema(model).optional()
5366
5940
  });
5367
- return this.refineForSelectIncludeMutuallyExclusive(schema);
5941
+ schema = this.refineForSelectIncludeMutuallyExclusive(schema);
5942
+ schema = this.refineForSelectOmitMutuallyExclusive(schema);
5943
+ return schema;
5368
5944
  }
5369
5945
  makeUpdateManySchema(model) {
5370
5946
  return import_zod.z.strictObject({
@@ -5375,14 +5951,15 @@ var InputValidator = class {
5375
5951
  }
5376
5952
  makeUpdateManyAndReturnSchema(model) {
5377
5953
  const base = this.makeUpdateManySchema(model);
5378
- const result = base.extend({
5954
+ let schema = base.extend({
5379
5955
  select: this.makeSelectSchema(model).optional(),
5380
5956
  omit: this.makeOmitSchema(model).optional()
5381
5957
  });
5382
- return this.refineForSelectOmitMutuallyExclusive(result);
5958
+ schema = this.refineForSelectOmitMutuallyExclusive(schema);
5959
+ return schema;
5383
5960
  }
5384
5961
  makeUpsertSchema(model) {
5385
- const schema = import_zod.z.strictObject({
5962
+ let schema = import_zod.z.strictObject({
5386
5963
  where: this.makeWhereSchema(model, true),
5387
5964
  create: this.makeCreateDataSchema(model, false),
5388
5965
  update: this.makeUpdateDataSchema(model),
@@ -5390,7 +5967,9 @@ var InputValidator = class {
5390
5967
  include: this.makeIncludeSchema(model).optional(),
5391
5968
  omit: this.makeOmitSchema(model).optional()
5392
5969
  });
5393
- return this.refineForSelectIncludeMutuallyExclusive(schema);
5970
+ schema = this.refineForSelectIncludeMutuallyExclusive(schema);
5971
+ schema = this.refineForSelectOmitMutuallyExclusive(schema);
5972
+ return schema;
5394
5973
  }
5395
5974
  makeUpdateDataSchema(model, withoutFields = [], withoutRelationFields = false) {
5396
5975
  const uncheckedVariantFields = {};
@@ -5467,12 +6046,14 @@ var InputValidator = class {
5467
6046
  // #endregion
5468
6047
  // #region Delete
5469
6048
  makeDeleteSchema(model) {
5470
- const schema = import_zod.z.strictObject({
6049
+ let schema = import_zod.z.strictObject({
5471
6050
  where: this.makeWhereSchema(model, true),
5472
6051
  select: this.makeSelectSchema(model).optional(),
5473
6052
  include: this.makeIncludeSchema(model).optional()
5474
6053
  });
5475
- return this.refineForSelectIncludeMutuallyExclusive(schema);
6054
+ schema = this.refineForSelectIncludeMutuallyExclusive(schema);
6055
+ schema = this.refineForSelectOmitMutuallyExclusive(schema);
6056
+ return schema;
5476
6057
  }
5477
6058
  makeDeleteManySchema(model) {
5478
6059
  return import_zod.z.object({
@@ -5822,31 +6403,14 @@ function performanceNow() {
5822
6403
  __name(performanceNow, "performanceNow");
5823
6404
 
5824
6405
  // src/client/executor/zenstack-query-executor.ts
5825
- var import_common_helpers11 = require("@zenstackhq/common-helpers");
5826
- var import_kysely14 = require("kysely");
6406
+ var import_common_helpers13 = require("@zenstackhq/common-helpers");
6407
+ var import_kysely15 = require("kysely");
5827
6408
  var import_ts_pattern16 = require("ts-pattern");
5828
6409
 
5829
- // src/client/executor/kysely-utils.ts
5830
- var import_kysely12 = require("kysely");
5831
- function stripAlias(node) {
5832
- if (import_kysely12.AliasNode.is(node)) {
5833
- return {
5834
- alias: node.alias,
5835
- node: node.node
5836
- };
5837
- } else {
5838
- return {
5839
- alias: void 0,
5840
- node
5841
- };
5842
- }
5843
- }
5844
- __name(stripAlias, "stripAlias");
5845
-
5846
6410
  // src/client/executor/name-mapper.ts
5847
- var import_common_helpers10 = require("@zenstackhq/common-helpers");
5848
- var import_kysely13 = require("kysely");
5849
- var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
6411
+ var import_common_helpers12 = require("@zenstackhq/common-helpers");
6412
+ var import_kysely14 = require("kysely");
6413
+ var QueryNameMapper = class extends import_kysely14.OperationNodeTransformer {
5850
6414
  static {
5851
6415
  __name(this, "QueryNameMapper");
5852
6416
  }
@@ -5888,7 +6452,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
5888
6452
  })) : void 0;
5889
6453
  return {
5890
6454
  ...super.transformSelectQuery(node),
5891
- from: import_kysely13.FromNode.create(processedFroms.map((f) => f.node)),
6455
+ from: import_kysely14.FromNode.create(processedFroms.map((f) => f.node)),
5892
6456
  joins,
5893
6457
  selections: this.processSelectQuerySelections(node)
5894
6458
  };
@@ -5914,7 +6478,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
5914
6478
  };
5915
6479
  }
5916
6480
  transformReference(node) {
5917
- if (!import_kysely13.ColumnNode.is(node.column)) {
6481
+ if (!import_kysely14.ColumnNode.is(node.column)) {
5918
6482
  return super.transformReference(node);
5919
6483
  }
5920
6484
  const scope = this.resolveFieldFromScopes(node.column.column.name, node.table?.table.identifier.name);
@@ -5922,12 +6486,12 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
5922
6486
  const mappedFieldName = this.mapFieldName(scope.model, node.column.column.name);
5923
6487
  let mappedTableName = node.table?.table.identifier.name;
5924
6488
  if (mappedTableName) {
5925
- if (scope.alias && import_kysely13.IdentifierNode.is(scope.alias) && scope.alias.name === mappedTableName) {
6489
+ if (scope.alias && import_kysely14.IdentifierNode.is(scope.alias) && scope.alias.name === mappedTableName) {
5926
6490
  } else if (scope.model === mappedTableName) {
5927
6491
  mappedTableName = this.mapTableName(scope.model);
5928
6492
  }
5929
6493
  }
5930
- return import_kysely13.ReferenceNode.create(import_kysely13.ColumnNode.create(mappedFieldName), mappedTableName ? import_kysely13.TableNode.create(mappedTableName) : void 0);
6494
+ return import_kysely14.ReferenceNode.create(import_kysely14.ColumnNode.create(mappedFieldName), mappedTableName ? import_kysely14.TableNode.create(mappedTableName) : void 0);
5931
6495
  } else {
5932
6496
  return super.transformReference(node);
5933
6497
  }
@@ -5938,14 +6502,14 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
5938
6502
  return super.transformColumn(node);
5939
6503
  }
5940
6504
  const mappedName = this.mapFieldName(scope.model, node.column.name);
5941
- return import_kysely13.ColumnNode.create(mappedName);
6505
+ return import_kysely14.ColumnNode.create(mappedName);
5942
6506
  }
5943
6507
  transformUpdateQuery(node) {
5944
6508
  if (!node.table) {
5945
6509
  return super.transformUpdateQuery(node);
5946
6510
  }
5947
6511
  const { alias, node: innerTable } = stripAlias(node.table);
5948
- if (!innerTable || !import_kysely13.TableNode.is(innerTable)) {
6512
+ if (!innerTable || !import_kysely14.TableNode.is(innerTable)) {
5949
6513
  return super.transformUpdateQuery(node);
5950
6514
  }
5951
6515
  return this.withScope({
@@ -5963,14 +6527,14 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
5963
6527
  const scopes = node.from.froms.map((node2) => {
5964
6528
  const { alias, node: innerNode } = stripAlias(node2);
5965
6529
  return {
5966
- model: this.extractModelName(innerNode),
6530
+ model: extractModelName(innerNode),
5967
6531
  alias,
5968
6532
  namesMapped: false
5969
6533
  };
5970
6534
  });
5971
6535
  const froms = node.from.froms.map((from) => {
5972
6536
  const { alias, node: innerNode } = stripAlias(from);
5973
- if (import_kysely13.TableNode.is(innerNode)) {
6537
+ if (import_kysely14.TableNode.is(innerNode)) {
5974
6538
  return this.wrapAlias(this.processTableRef(innerNode), alias);
5975
6539
  } else {
5976
6540
  return super.transformNode(from);
@@ -5979,7 +6543,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
5979
6543
  return this.withScopes(scopes, () => {
5980
6544
  return {
5981
6545
  ...super.transformDeleteQuery(node),
5982
- from: import_kysely13.FromNode.create(froms)
6546
+ from: import_kysely14.FromNode.create(froms)
5983
6547
  };
5984
6548
  });
5985
6549
  }
@@ -5988,24 +6552,24 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
5988
6552
  processSelectQuerySelections(node) {
5989
6553
  const selections = [];
5990
6554
  for (const selection of node.selections ?? []) {
5991
- if (import_kysely13.SelectAllNode.is(selection.selection)) {
6555
+ if (import_kysely14.SelectAllNode.is(selection.selection)) {
5992
6556
  const scope = this.scopes[this.scopes.length - 1];
5993
6557
  if (scope?.model && !scope.namesMapped) {
5994
6558
  selections.push(...this.createSelectAllFields(scope.model, scope.alias));
5995
6559
  } else {
5996
6560
  selections.push(super.transformSelection(selection));
5997
6561
  }
5998
- } else if (import_kysely13.ReferenceNode.is(selection.selection) || import_kysely13.ColumnNode.is(selection.selection)) {
6562
+ } else if (import_kysely14.ReferenceNode.is(selection.selection) || import_kysely14.ColumnNode.is(selection.selection)) {
5999
6563
  const transformed = this.transformNode(selection.selection);
6000
- if (import_kysely13.AliasNode.is(transformed)) {
6001
- selections.push(import_kysely13.SelectionNode.create(transformed));
6564
+ if (import_kysely14.AliasNode.is(transformed)) {
6565
+ selections.push(import_kysely14.SelectionNode.create(transformed));
6002
6566
  } else {
6003
- const origFieldName = this.extractFieldName(selection.selection);
6004
- const fieldName = this.extractFieldName(transformed);
6567
+ const origFieldName = extractFieldName(selection.selection);
6568
+ const fieldName = extractFieldName(transformed);
6005
6569
  if (fieldName !== origFieldName) {
6006
- selections.push(import_kysely13.SelectionNode.create(this.wrapAlias(transformed, origFieldName ? import_kysely13.IdentifierNode.create(origFieldName) : void 0)));
6570
+ selections.push(import_kysely14.SelectionNode.create(this.wrapAlias(transformed, origFieldName ? import_kysely14.IdentifierNode.create(origFieldName) : void 0)));
6007
6571
  } else {
6008
- selections.push(import_kysely13.SelectionNode.create(transformed));
6572
+ selections.push(import_kysely14.SelectionNode.create(transformed));
6009
6573
  }
6010
6574
  }
6011
6575
  } else {
@@ -6019,7 +6583,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
6019
6583
  const scope = this.scopes[i];
6020
6584
  if (qualifier) {
6021
6585
  if (scope.alias) {
6022
- if (scope.alias && import_kysely13.IdentifierNode.is(scope.alias) && scope.alias.name === qualifier) {
6586
+ if (scope.alias && import_kysely14.IdentifierNode.is(scope.alias) && scope.alias.name === qualifier) {
6023
6587
  return scope;
6024
6588
  } else {
6025
6589
  continue;
@@ -6065,16 +6629,16 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
6065
6629
  }
6066
6630
  }
6067
6631
  wrapAlias(node, alias) {
6068
- return alias ? import_kysely13.AliasNode.create(node, alias) : node;
6632
+ return alias ? import_kysely14.AliasNode.create(node, alias) : node;
6069
6633
  }
6070
6634
  processTableRef(node) {
6071
6635
  if (!node) {
6072
6636
  return node;
6073
6637
  }
6074
- if (!import_kysely13.TableNode.is(node)) {
6638
+ if (!import_kysely14.TableNode.is(node)) {
6075
6639
  return super.transformNode(node);
6076
6640
  }
6077
- return import_kysely13.TableNode.create(this.mapTableName(node.table.identifier.name));
6641
+ return import_kysely14.TableNode.create(this.mapTableName(node.table.identifier.name));
6078
6642
  }
6079
6643
  getMappedName(def) {
6080
6644
  const mapAttr = def.attributes?.find((attr) => attr.name === "@@map" || attr.name === "@map");
@@ -6110,14 +6674,14 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
6110
6674
  // convert a "from" node to a nested query if there are columns with name mapping
6111
6675
  processSelectTable(node) {
6112
6676
  const { alias, node: innerNode } = stripAlias(node);
6113
- if (innerNode && import_kysely13.TableNode.is(innerNode)) {
6677
+ if (innerNode && import_kysely14.TableNode.is(innerNode)) {
6114
6678
  const modelName = innerNode.table.identifier.name;
6115
6679
  const mappedName = this.mapTableName(modelName);
6116
- const finalAlias = alias ?? (mappedName !== modelName ? import_kysely13.IdentifierNode.create(modelName) : void 0);
6680
+ const finalAlias = alias ?? (mappedName !== modelName ? import_kysely14.IdentifierNode.create(modelName) : void 0);
6117
6681
  return {
6118
- node: this.wrapAlias(import_kysely13.TableNode.create(mappedName), finalAlias),
6682
+ node: this.wrapAlias(import_kysely14.TableNode.create(mappedName), finalAlias),
6119
6683
  scope: {
6120
- alias: alias ?? import_kysely13.IdentifierNode.create(modelName),
6684
+ alias: alias ?? import_kysely14.IdentifierNode.create(modelName),
6121
6685
  model: modelName,
6122
6686
  namesMapped: !this.hasMappedColumns(modelName)
6123
6687
  }
@@ -6137,12 +6701,12 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
6137
6701
  const modelDef = requireModel(this.schema, model);
6138
6702
  return this.getModelFields(modelDef).map((fieldDef) => {
6139
6703
  const columnName = this.mapFieldName(model, fieldDef.name);
6140
- const columnRef = import_kysely13.ReferenceNode.create(import_kysely13.ColumnNode.create(columnName), alias && import_kysely13.IdentifierNode.is(alias) ? import_kysely13.TableNode.create(alias.name) : void 0);
6704
+ const columnRef = import_kysely14.ReferenceNode.create(import_kysely14.ColumnNode.create(columnName), alias && import_kysely14.IdentifierNode.is(alias) ? import_kysely14.TableNode.create(alias.name) : void 0);
6141
6705
  if (columnName !== fieldDef.name) {
6142
- const aliased = import_kysely13.AliasNode.create(columnRef, import_kysely13.IdentifierNode.create(fieldDef.name));
6143
- return import_kysely13.SelectionNode.create(aliased);
6706
+ const aliased = import_kysely14.AliasNode.create(columnRef, import_kysely14.IdentifierNode.create(fieldDef.name));
6707
+ return import_kysely14.SelectionNode.create(aliased);
6144
6708
  } else {
6145
- return import_kysely13.SelectionNode.create(columnRef);
6709
+ return import_kysely14.SelectionNode.create(columnRef);
6146
6710
  }
6147
6711
  });
6148
6712
  }
@@ -6152,57 +6716,44 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
6152
6716
  processSelections(selections) {
6153
6717
  const result = [];
6154
6718
  selections.forEach((selection) => {
6155
- if (import_kysely13.SelectAllNode.is(selection.selection)) {
6719
+ if (import_kysely14.SelectAllNode.is(selection.selection)) {
6156
6720
  const processed = this.processSelectAll(selection.selection);
6157
6721
  if (Array.isArray(processed)) {
6158
- result.push(...processed.map((s) => import_kysely13.SelectionNode.create(s)));
6722
+ result.push(...processed.map((s) => import_kysely14.SelectionNode.create(s)));
6159
6723
  } else {
6160
- result.push(import_kysely13.SelectionNode.create(processed));
6724
+ result.push(import_kysely14.SelectionNode.create(processed));
6161
6725
  }
6162
6726
  } else {
6163
- result.push(import_kysely13.SelectionNode.create(this.processSelection(selection.selection)));
6727
+ result.push(import_kysely14.SelectionNode.create(this.processSelection(selection.selection)));
6164
6728
  }
6165
6729
  });
6166
6730
  return result;
6167
6731
  }
6168
6732
  processSelection(node) {
6169
6733
  let alias;
6170
- if (!import_kysely13.AliasNode.is(node)) {
6171
- alias = this.extractFieldName(node);
6734
+ if (!import_kysely14.AliasNode.is(node)) {
6735
+ alias = extractFieldName(node);
6172
6736
  }
6173
6737
  const result = super.transformNode(node);
6174
- return this.wrapAlias(result, alias ? import_kysely13.IdentifierNode.create(alias) : void 0);
6738
+ return this.wrapAlias(result, alias ? import_kysely14.IdentifierNode.create(alias) : void 0);
6175
6739
  }
6176
6740
  processSelectAll(node) {
6177
6741
  const scope = this.scopes[this.scopes.length - 1];
6178
- (0, import_common_helpers10.invariant)(scope);
6742
+ (0, import_common_helpers12.invariant)(scope);
6179
6743
  if (!scope.model || !this.hasMappedColumns(scope.model)) {
6180
6744
  return super.transformSelectAll(node);
6181
6745
  }
6182
6746
  const modelDef = requireModel(this.schema, scope.model);
6183
6747
  return this.getModelFields(modelDef).map((fieldDef) => {
6184
6748
  const columnName = this.mapFieldName(modelDef.name, fieldDef.name);
6185
- const columnRef = import_kysely13.ReferenceNode.create(import_kysely13.ColumnNode.create(columnName));
6186
- return columnName !== fieldDef.name ? this.wrapAlias(columnRef, import_kysely13.IdentifierNode.create(fieldDef.name)) : columnRef;
6749
+ const columnRef = import_kysely14.ReferenceNode.create(import_kysely14.ColumnNode.create(columnName));
6750
+ return columnName !== fieldDef.name ? this.wrapAlias(columnRef, import_kysely14.IdentifierNode.create(fieldDef.name)) : columnRef;
6187
6751
  });
6188
6752
  }
6189
- extractModelName(node) {
6190
- const { node: innerNode } = stripAlias(node);
6191
- return import_kysely13.TableNode.is(innerNode) ? innerNode.table.identifier.name : void 0;
6192
- }
6193
- extractFieldName(node) {
6194
- if (import_kysely13.ReferenceNode.is(node) && import_kysely13.ColumnNode.is(node.column)) {
6195
- return node.column.column.name;
6196
- } else if (import_kysely13.ColumnNode.is(node)) {
6197
- return node.column.name;
6198
- } else {
6199
- return void 0;
6200
- }
6201
- }
6202
6753
  };
6203
6754
 
6204
6755
  // src/client/executor/zenstack-query-executor.ts
6205
- var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14.DefaultQueryExecutor {
6756
+ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely15.DefaultQueryExecutor {
6206
6757
  static {
6207
6758
  __name(this, "ZenStackQueryExecutor");
6208
6759
  }
@@ -6258,13 +6809,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
6258
6809
  }
6259
6810
  getMutationInfo(queryNode) {
6260
6811
  const model = this.getMutationModel(queryNode);
6261
- const { action, where } = (0, import_ts_pattern16.match)(queryNode).when(import_kysely14.InsertQueryNode.is, () => ({
6812
+ const { action, where } = (0, import_ts_pattern16.match)(queryNode).when(import_kysely15.InsertQueryNode.is, () => ({
6262
6813
  action: "create",
6263
6814
  where: void 0
6264
- })).when(import_kysely14.UpdateQueryNode.is, (node) => ({
6815
+ })).when(import_kysely15.UpdateQueryNode.is, (node) => ({
6265
6816
  action: "update",
6266
6817
  where: node.where
6267
- })).when(import_kysely14.DeleteQueryNode.is, (node) => ({
6818
+ })).when(import_kysely15.DeleteQueryNode.is, (node) => ({
6268
6819
  action: "delete",
6269
6820
  where: node.where
6270
6821
  })).exhaustive();
@@ -6292,11 +6843,11 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
6292
6843
  result
6293
6844
  };
6294
6845
  }
6295
- if ((import_kysely14.InsertQueryNode.is(query) || import_kysely14.UpdateQueryNode.is(query)) && this.hasEntityMutationPluginsWithAfterMutationHooks) {
6846
+ if ((import_kysely15.InsertQueryNode.is(query) || import_kysely15.UpdateQueryNode.is(query)) && this.hasEntityMutationPluginsWithAfterMutationHooks) {
6296
6847
  query = {
6297
6848
  ...query,
6298
- returning: import_kysely14.ReturningNode.create([
6299
- import_kysely14.SelectionNode.createSelectAll()
6849
+ returning: import_kysely15.ReturningNode.create([
6850
+ import_kysely15.SelectionNode.createSelectAll()
6300
6851
  ])
6301
6852
  };
6302
6853
  }
@@ -6313,7 +6864,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
6313
6864
  const mutationInfo = this.getMutationInfo(finalQuery);
6314
6865
  let beforeMutationEntities;
6315
6866
  const loadBeforeMutationEntities = /* @__PURE__ */ __name(async () => {
6316
- if (beforeMutationEntities === void 0 && (import_kysely14.UpdateQueryNode.is(query) || import_kysely14.DeleteQueryNode.is(query))) {
6867
+ if (beforeMutationEntities === void 0 && (import_kysely15.UpdateQueryNode.is(query) || import_kysely15.DeleteQueryNode.is(query))) {
6317
6868
  beforeMutationEntities = await this.loadEntities(mutationInfo.model, mutationInfo.where, connection);
6318
6869
  }
6319
6870
  return beforeMutationEntities;
@@ -6355,7 +6906,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
6355
6906
  }
6356
6907
  }
6357
6908
  createClientForConnection(connection, inTx) {
6358
- const innerExecutor = this.withConnectionProvider(new import_kysely14.SingleConnectionProvider(connection));
6909
+ const innerExecutor = this.withConnectionProvider(new import_kysely15.SingleConnectionProvider(connection));
6359
6910
  innerExecutor.suppressMutationHooks = true;
6360
6911
  const innerClient = this.client.withExecutor(innerExecutor);
6361
6912
  if (inTx) {
@@ -6373,7 +6924,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
6373
6924
  return (this.client.$options.plugins ?? []).some((plugin) => plugin.onEntityMutation?.runAfterMutationWithinTransaction);
6374
6925
  }
6375
6926
  isMutationNode(queryNode) {
6376
- return import_kysely14.InsertQueryNode.is(queryNode) || import_kysely14.UpdateQueryNode.is(queryNode) || import_kysely14.DeleteQueryNode.is(queryNode);
6927
+ return import_kysely15.InsertQueryNode.is(queryNode) || import_kysely15.UpdateQueryNode.is(queryNode) || import_kysely15.DeleteQueryNode.is(queryNode);
6377
6928
  }
6378
6929
  withPlugin(plugin) {
6379
6930
  return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, [
@@ -6402,18 +6953,18 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
6402
6953
  return newExecutor;
6403
6954
  }
6404
6955
  getMutationModel(queryNode) {
6405
- return (0, import_ts_pattern16.match)(queryNode).when(import_kysely14.InsertQueryNode.is, (node) => {
6406
- (0, import_common_helpers11.invariant)(node.into, "InsertQueryNode must have an into clause");
6956
+ return (0, import_ts_pattern16.match)(queryNode).when(import_kysely15.InsertQueryNode.is, (node) => {
6957
+ (0, import_common_helpers13.invariant)(node.into, "InsertQueryNode must have an into clause");
6407
6958
  return node.into.table.identifier.name;
6408
- }).when(import_kysely14.UpdateQueryNode.is, (node) => {
6409
- (0, import_common_helpers11.invariant)(node.table, "UpdateQueryNode must have a table");
6959
+ }).when(import_kysely15.UpdateQueryNode.is, (node) => {
6960
+ (0, import_common_helpers13.invariant)(node.table, "UpdateQueryNode must have a table");
6410
6961
  const { node: tableNode } = stripAlias(node.table);
6411
- (0, import_common_helpers11.invariant)(import_kysely14.TableNode.is(tableNode), "UpdateQueryNode must use a TableNode");
6962
+ (0, import_common_helpers13.invariant)(import_kysely15.TableNode.is(tableNode), "UpdateQueryNode must use a TableNode");
6412
6963
  return tableNode.table.identifier.name;
6413
- }).when(import_kysely14.DeleteQueryNode.is, (node) => {
6414
- (0, import_common_helpers11.invariant)(node.from.froms.length === 1, "Delete query must have exactly one from table");
6964
+ }).when(import_kysely15.DeleteQueryNode.is, (node) => {
6965
+ (0, import_common_helpers13.invariant)(node.from.froms.length === 1, "Delete query must have exactly one from table");
6415
6966
  const { node: tableNode } = stripAlias(node.from.froms[0]);
6416
- (0, import_common_helpers11.invariant)(import_kysely14.TableNode.is(tableNode), "DeleteQueryNode must use a TableNode");
6967
+ (0, import_common_helpers13.invariant)(import_kysely15.TableNode.is(tableNode), "DeleteQueryNode must use a TableNode");
6417
6968
  return tableNode.table.identifier.name;
6418
6969
  }).otherwise((node) => {
6419
6970
  throw new InternalError(`Invalid query node: ${node}`);
@@ -6487,9 +7038,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
6487
7038
  }
6488
7039
  andNodes(condition1, condition2) {
6489
7040
  if (condition1 && condition2) {
6490
- return import_kysely14.WhereNode.create(import_kysely14.AndNode.create(condition1, condition2));
7041
+ return import_kysely15.WhereNode.create(import_kysely15.AndNode.create(condition1, condition2));
6491
7042
  } else if (condition1) {
6492
- return import_kysely14.WhereNode.create(condition1);
7043
+ return import_kysely15.WhereNode.create(condition1);
6493
7044
  } else {
6494
7045
  return condition2;
6495
7046
  }
@@ -6511,53 +7062,58 @@ __export(functions_exports, {
6511
7062
  search: () => search,
6512
7063
  startsWith: () => startsWith
6513
7064
  });
6514
- var import_common_helpers12 = require("@zenstackhq/common-helpers");
6515
- var import_kysely15 = require("kysely");
7065
+ var import_common_helpers14 = require("@zenstackhq/common-helpers");
7066
+ var import_kysely16 = require("kysely");
6516
7067
  var import_ts_pattern17 = require("ts-pattern");
6517
- var contains = /* @__PURE__ */ __name((eb, args) => {
6518
- const [field, search2, caseInsensitive = false] = args;
6519
- if (!field) {
6520
- throw new Error('"field" parameter is required');
6521
- }
6522
- if (!search2) {
6523
- throw new Error('"search" parameter is required');
6524
- }
6525
- const searchExpr = eb.fn("CONCAT", [
6526
- import_kysely15.sql.lit("%"),
6527
- search2,
6528
- import_kysely15.sql.lit("%")
6529
- ]);
6530
- return eb(field, caseInsensitive ? "ilike" : "like", searchExpr);
6531
- }, "contains");
7068
+ var contains = /* @__PURE__ */ __name((eb, args, context) => textMatch(eb, args, context, "contains"), "contains");
6532
7069
  var search = /* @__PURE__ */ __name((_eb, _args) => {
6533
7070
  throw new Error(`"search" function is not implemented yet`);
6534
7071
  }, "search");
6535
- var startsWith = /* @__PURE__ */ __name((eb, args) => {
6536
- const [field, search2] = args;
6537
- if (!field) {
6538
- throw new Error('"field" parameter is required');
6539
- }
6540
- if (!search2) {
6541
- throw new Error('"search" parameter is required');
6542
- }
6543
- return eb(field, "like", eb.fn("CONCAT", [
6544
- search2,
6545
- import_kysely15.sql.lit("%")
6546
- ]));
6547
- }, "startsWith");
6548
- var endsWith = /* @__PURE__ */ __name((eb, args) => {
6549
- const [field, search2] = args;
7072
+ var startsWith = /* @__PURE__ */ __name((eb, args, context) => textMatch(eb, args, context, "startsWith"), "startsWith");
7073
+ var endsWith = /* @__PURE__ */ __name((eb, args, context) => textMatch(eb, args, context, "endsWith"), "endsWith");
7074
+ var textMatch = /* @__PURE__ */ __name((eb, args, { dialect }, method) => {
7075
+ const [field, search2, caseInsensitive = void 0] = args;
6550
7076
  if (!field) {
6551
7077
  throw new Error('"field" parameter is required');
6552
7078
  }
6553
7079
  if (!search2) {
6554
7080
  throw new Error('"search" parameter is required');
6555
7081
  }
6556
- return eb(field, "like", eb.fn("CONCAT", [
6557
- import_kysely15.sql.lit("%"),
6558
- search2
6559
- ]));
6560
- }, "endsWith");
7082
+ const casingBehavior = dialect.getStringCasingBehavior();
7083
+ const caseInsensitiveValue = readBoolean(caseInsensitive, false);
7084
+ let op;
7085
+ let fieldExpr = field;
7086
+ let searchExpr = search2;
7087
+ if (caseInsensitiveValue) {
7088
+ if (casingBehavior.supportsILike) {
7089
+ op = "ilike";
7090
+ } else {
7091
+ op = "like";
7092
+ if (casingBehavior.likeCaseSensitive === true) {
7093
+ fieldExpr = eb.fn("LOWER", [
7094
+ fieldExpr
7095
+ ]);
7096
+ searchExpr = eb.fn("LOWER", [
7097
+ searchExpr
7098
+ ]);
7099
+ }
7100
+ }
7101
+ } else {
7102
+ op = "like";
7103
+ }
7104
+ searchExpr = (0, import_ts_pattern17.match)(method).with("contains", () => eb.fn("CONCAT", [
7105
+ import_kysely16.sql.lit("%"),
7106
+ import_kysely16.sql`CAST(${searchExpr} as text)`,
7107
+ import_kysely16.sql.lit("%")
7108
+ ])).with("startsWith", () => eb.fn("CONCAT", [
7109
+ import_kysely16.sql`CAST(${searchExpr} as text)`,
7110
+ import_kysely16.sql.lit("%")
7111
+ ])).with("endsWith", () => eb.fn("CONCAT", [
7112
+ import_kysely16.sql.lit("%"),
7113
+ import_kysely16.sql`CAST(${searchExpr} as text)`
7114
+ ])).exhaustive();
7115
+ return eb(fieldExpr, op, searchExpr);
7116
+ }, "textMatch");
6561
7117
  var has = /* @__PURE__ */ __name((eb, args) => {
6562
7118
  const [field, search2] = args;
6563
7119
  if (!field) {
@@ -6595,18 +7151,16 @@ var isEmpty = /* @__PURE__ */ __name((eb, args, { dialect }) => {
6595
7151
  if (!field) {
6596
7152
  throw new Error('"field" parameter is required');
6597
7153
  }
6598
- return eb(dialect.buildArrayLength(eb, field), "=", import_kysely15.sql.lit(0));
7154
+ return eb(dialect.buildArrayLength(eb, field), "=", import_kysely16.sql.lit(0));
6599
7155
  }, "isEmpty");
6600
- var now = /* @__PURE__ */ __name((eb, _args, { dialect }) => {
6601
- return (0, import_ts_pattern17.match)(dialect.provider).with("postgresql", () => eb.fn("now")).with("sqlite", () => import_kysely15.sql.raw("CURRENT_TIMESTAMP")).exhaustive();
6602
- }, "now");
7156
+ var now = /* @__PURE__ */ __name(() => import_kysely16.sql.raw("CURRENT_TIMESTAMP"), "now");
6603
7157
  var currentModel = /* @__PURE__ */ __name((_eb, args, { model }) => {
6604
7158
  let result = model;
6605
7159
  const [casing] = args;
6606
7160
  if (casing) {
6607
7161
  result = processCasing(casing, result, model);
6608
7162
  }
6609
- return import_kysely15.sql.lit(result);
7163
+ return import_kysely16.sql.lit(result);
6610
7164
  }, "currentModel");
6611
7165
  var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
6612
7166
  let result = operation;
@@ -6614,21 +7168,30 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
6614
7168
  if (casing) {
6615
7169
  result = processCasing(casing, result, operation);
6616
7170
  }
6617
- return import_kysely15.sql.lit(result);
7171
+ return import_kysely16.sql.lit(result);
6618
7172
  }, "currentOperation");
6619
7173
  function processCasing(casing, result, model) {
6620
7174
  const opNode = casing.toOperationNode();
6621
- (0, import_common_helpers12.invariant)(import_kysely15.ValueNode.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
6622
- result = (0, import_ts_pattern17.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => (0, import_common_helpers12.upperCaseFirst)(result)).with("uncapitalize", () => (0, import_common_helpers12.lowerCaseFirst)(result)).otherwise(() => {
7175
+ (0, import_common_helpers14.invariant)(import_kysely16.ValueNode.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
7176
+ result = (0, import_ts_pattern17.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => (0, import_common_helpers14.upperCaseFirst)(result)).with("uncapitalize", () => (0, import_common_helpers14.lowerCaseFirst)(result)).otherwise(() => {
6623
7177
  throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
6624
7178
  });
6625
7179
  return result;
6626
7180
  }
6627
7181
  __name(processCasing, "processCasing");
7182
+ function readBoolean(expr2, defaultValue) {
7183
+ if (expr2 === void 0) {
7184
+ return defaultValue;
7185
+ }
7186
+ const opNode = expr2.toOperationNode();
7187
+ (0, import_common_helpers14.invariant)(import_kysely16.ValueNode.is(opNode), "expression must be a literal value");
7188
+ return !!opNode.value;
7189
+ }
7190
+ __name(readBoolean, "readBoolean");
6628
7191
 
6629
7192
  // src/client/helpers/schema-db-pusher.ts
6630
- var import_common_helpers13 = require("@zenstackhq/common-helpers");
6631
- var import_kysely16 = require("kysely");
7193
+ var import_common_helpers15 = require("@zenstackhq/common-helpers");
7194
+ var import_kysely17 = require("kysely");
6632
7195
  var import_toposort = __toESM(require("toposort"), 1);
6633
7196
  var import_ts_pattern18 = require("ts-pattern");
6634
7197
  var SchemaDbPusher = class {
@@ -6649,7 +7212,8 @@ var SchemaDbPusher = class {
6649
7212
  await createEnum.execute();
6650
7213
  }
6651
7214
  }
6652
- const sortedModels = this.sortModels(this.schema.models);
7215
+ const models = Object.values(this.schema.models).filter((m) => !m.isView);
7216
+ const sortedModels = this.sortModels(models);
6653
7217
  for (const modelDef of sortedModels) {
6654
7218
  const createTable = this.createModelTable(tx, modelDef);
6655
7219
  await createTable.execute();
@@ -6658,7 +7222,7 @@ var SchemaDbPusher = class {
6658
7222
  }
6659
7223
  sortModels(models) {
6660
7224
  const graph = [];
6661
- for (const model of Object.values(models)) {
7225
+ for (const model of models) {
6662
7226
  let added = false;
6663
7227
  if (model.baseModel) {
6664
7228
  const baseDef = requireModel(this.schema, model.baseModel);
@@ -6743,7 +7307,7 @@ var SchemaDbPusher = class {
6743
7307
  }
6744
7308
  addUniqueConstraint(table, modelDef) {
6745
7309
  for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
6746
- (0, import_common_helpers13.invariant)(typeof value === "object", "expecting an object");
7310
+ (0, import_common_helpers15.invariant)(typeof value === "object", "expecting an object");
6747
7311
  if ("type" in value) {
6748
7312
  const fieldDef = modelDef.fields[key];
6749
7313
  if (fieldDef.unique) {
@@ -6766,7 +7330,7 @@ var SchemaDbPusher = class {
6766
7330
  if (fieldDef.default !== void 0) {
6767
7331
  if (typeof fieldDef.default === "object" && "kind" in fieldDef.default) {
6768
7332
  if (ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "now") {
6769
- col = col.defaultTo(import_kysely16.sql`CURRENT_TIMESTAMP`);
7333
+ col = col.defaultTo(import_kysely17.sql`CURRENT_TIMESTAMP`);
6770
7334
  }
6771
7335
  } else {
6772
7336
  col = col.defaultTo(fieldDef.default);
@@ -6786,7 +7350,7 @@ var SchemaDbPusher = class {
6786
7350
  }
6787
7351
  mapFieldType(fieldDef) {
6788
7352
  if (this.schema.enums?.[fieldDef.type]) {
6789
- return this.schema.provider.type === "postgresql" ? import_kysely16.sql.ref(fieldDef.type) : "text";
7353
+ return this.schema.provider.type === "postgresql" ? import_kysely17.sql.ref(fieldDef.type) : "text";
6790
7354
  }
6791
7355
  if (this.isAutoIncrement(fieldDef) && this.schema.provider.type === "postgresql") {
6792
7356
  return "serial";
@@ -6799,7 +7363,7 @@ var SchemaDbPusher = class {
6799
7363
  throw new Error(`Unsupported field type: ${type}`);
6800
7364
  });
6801
7365
  if (fieldDef.array) {
6802
- return import_kysely16.sql.raw(`${result}[]`);
7366
+ return import_kysely17.sql.raw(`${result}[]`);
6803
7367
  } else {
6804
7368
  return result;
6805
7369
  }
@@ -6811,7 +7375,7 @@ var SchemaDbPusher = class {
6811
7375
  return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
6812
7376
  }
6813
7377
  addForeignKeyConstraint(table, model, fieldName, fieldDef) {
6814
- (0, import_common_helpers13.invariant)(fieldDef.relation, "field must be a relation");
7378
+ (0, import_common_helpers15.invariant)(fieldDef.relation, "field must be a relation");
6815
7379
  if (!fieldDef.relation.fields || !fieldDef.relation.references) {
6816
7380
  return table;
6817
7381
  }
@@ -6868,16 +7432,15 @@ function valueToPromise(thing) {
6868
7432
  __name(valueToPromise, "valueToPromise");
6869
7433
 
6870
7434
  // src/client/result-processor.ts
6871
- var import_common_helpers14 = require("@zenstackhq/common-helpers");
6872
- var import_decimal2 = __toESM(require("decimal.js"), 1);
6873
- var import_ts_pattern19 = require("ts-pattern");
6874
7435
  var ResultProcessor = class {
6875
7436
  static {
6876
7437
  __name(this, "ResultProcessor");
6877
7438
  }
6878
7439
  schema;
6879
- constructor(schema) {
7440
+ dialect;
7441
+ constructor(schema, options) {
6880
7442
  this.schema = schema;
7443
+ this.dialect = getCrudDialect(schema, options);
6881
7444
  }
6882
7445
  processResult(data, model, args) {
6883
7446
  const result = this.doProcessResult(data, model);
@@ -6906,7 +7469,7 @@ var ResultProcessor = class {
6906
7469
  }
6907
7470
  if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
6908
7471
  if (value) {
6909
- const subRow = this.transformJson(value);
7472
+ const subRow = this.dialect.transformOutput(value, "Json");
6910
7473
  const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
6911
7474
  const idValues = getIdValues(this.schema, subModel, subRow);
6912
7475
  if (Object.values(idValues).some((v) => v === null || v === void 0)) {
@@ -6940,10 +7503,10 @@ var ResultProcessor = class {
6940
7503
  processFieldValue(value, fieldDef) {
6941
7504
  const type = fieldDef.type;
6942
7505
  if (Array.isArray(value)) {
6943
- value.forEach((v, i) => value[i] = this.transformScalar(v, type));
7506
+ value.forEach((v, i) => value[i] = this.dialect.transformOutput(v, type));
6944
7507
  return value;
6945
7508
  } else {
6946
- return this.transformScalar(value, type);
7509
+ return this.dialect.transformOutput(value, type);
6947
7510
  }
6948
7511
  }
6949
7512
  processRelation(value, fieldDef) {
@@ -6957,42 +7520,6 @@ var ResultProcessor = class {
6957
7520
  }
6958
7521
  return this.doProcessResult(relationData, fieldDef.type);
6959
7522
  }
6960
- transformScalar(value, type) {
6961
- if (this.schema.typeDefs && type in this.schema.typeDefs) {
6962
- return this.transformJson(value);
6963
- } else {
6964
- return (0, import_ts_pattern19.match)(type).with("Boolean", () => this.transformBoolean(value)).with("DateTime", () => this.transformDate(value)).with("Bytes", () => this.transformBytes(value)).with("Decimal", () => this.transformDecimal(value)).with("BigInt", () => this.transformBigInt(value)).with("Json", () => this.transformJson(value)).otherwise(() => value);
6965
- }
6966
- }
6967
- transformDecimal(value) {
6968
- if (value instanceof import_decimal2.default) {
6969
- return value;
6970
- }
6971
- (0, import_common_helpers14.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal2.default, `Expected string, number or Decimal, got ${typeof value}`);
6972
- return new import_decimal2.default(value);
6973
- }
6974
- transformBigInt(value) {
6975
- if (typeof value === "bigint") {
6976
- return value;
6977
- }
6978
- (0, import_common_helpers14.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
6979
- return BigInt(value);
6980
- }
6981
- transformBoolean(value) {
6982
- return !!value;
6983
- }
6984
- transformDate(value) {
6985
- if (typeof value === "number") {
6986
- return new Date(value);
6987
- } else if (typeof value === "string") {
6988
- return new Date(Date.parse(value));
6989
- } else {
6990
- return value;
6991
- }
6992
- }
6993
- transformBytes(value) {
6994
- return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
6995
- }
6996
7523
  fixReversedResult(data, model, args) {
6997
7524
  if (!data) {
6998
7525
  return;
@@ -7017,12 +7544,6 @@ var ResultProcessor = class {
7017
7544
  }
7018
7545
  }
7019
7546
  }
7020
- transformJson(value) {
7021
- return (0, import_ts_pattern19.match)(this.schema.provider.type).with("sqlite", () => {
7022
- (0, import_common_helpers14.invariant)(typeof value === "string", "Expected string, got " + typeof value);
7023
- return JSON.parse(value);
7024
- }).otherwise(() => value);
7025
- }
7026
7547
  };
7027
7548
 
7028
7549
  // src/client/client-impl.ts
@@ -7045,7 +7566,7 @@ var ClientImpl = class _ClientImpl {
7045
7566
  this.schema = schema;
7046
7567
  this.options = options;
7047
7568
  this.$schema = schema;
7048
- this.$options = options ?? {};
7569
+ this.$options = options;
7049
7570
  this.$options.functions = {
7050
7571
  ...functions_exports,
7051
7572
  ...this.$options.functions
@@ -7053,15 +7574,15 @@ var ClientImpl = class _ClientImpl {
7053
7574
  if (baseClient) {
7054
7575
  this.kyselyProps = {
7055
7576
  ...baseClient.kyselyProps,
7056
- executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new import_kysely17.DefaultConnectionProvider(baseClient.kyselyProps.driver))
7577
+ executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new import_kysely18.DefaultConnectionProvider(baseClient.kyselyProps.driver))
7057
7578
  };
7058
7579
  this.kyselyRaw = baseClient.kyselyRaw;
7059
7580
  this.auth = baseClient.auth;
7060
7581
  } else {
7061
- const driver = new ZenStackDriver(options.dialect.createDriver(), new import_kysely17.Log(this.$options.log ?? []));
7582
+ const driver = new ZenStackDriver(options.dialect.createDriver(), new import_kysely18.Log(this.$options.log ?? []));
7062
7583
  const compiler = options.dialect.createQueryCompiler();
7063
7584
  const adapter = options.dialect.createAdapter();
7064
- const connectionProvider = new import_kysely17.DefaultConnectionProvider(driver);
7585
+ const connectionProvider = new import_kysely18.DefaultConnectionProvider(driver);
7065
7586
  this.kyselyProps = {
7066
7587
  config: {
7067
7588
  dialect: options.dialect,
@@ -7071,12 +7592,12 @@ var ClientImpl = class _ClientImpl {
7071
7592
  driver,
7072
7593
  executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
7073
7594
  };
7074
- this.kyselyRaw = new import_kysely17.Kysely({
7595
+ this.kyselyRaw = new import_kysely18.Kysely({
7075
7596
  ...this.kyselyProps,
7076
- executor: new import_kysely17.DefaultQueryExecutor(compiler, adapter, connectionProvider, [])
7597
+ executor: new import_kysely18.DefaultQueryExecutor(compiler, adapter, connectionProvider, [])
7077
7598
  });
7078
7599
  }
7079
- this.kysely = new import_kysely17.Kysely(this.kyselyProps);
7600
+ this.kysely = new import_kysely18.Kysely(this.kyselyProps);
7080
7601
  return createClientProxy(this);
7081
7602
  }
7082
7603
  get $qb() {
@@ -7096,7 +7617,7 @@ var ClientImpl = class _ClientImpl {
7096
7617
  }
7097
7618
  // implementation
7098
7619
  async $transaction(input, options) {
7099
- (0, import_common_helpers15.invariant)(typeof input === "function" || Array.isArray(input) && input.every((p) => p.then && p.cb), "Invalid transaction input, expected a function or an array of ZenStackPromise");
7620
+ (0, import_common_helpers16.invariant)(typeof input === "function" || Array.isArray(input) && input.every((p) => p.then && p.cb), "Invalid transaction input, expected a function or an array of ZenStackPromise");
7100
7621
  if (typeof input === "function") {
7101
7622
  return this.interactiveTransaction(input, options);
7102
7623
  } else {
@@ -7105,7 +7626,7 @@ var ClientImpl = class _ClientImpl {
7105
7626
  }
7106
7627
  forceTransaction() {
7107
7628
  if (!this.kysely.isTransaction) {
7108
- this.kysely = new import_kysely17.Transaction(this.kyselyProps);
7629
+ this.kysely = new import_kysely18.Transaction(this.kyselyProps);
7109
7630
  }
7110
7631
  }
7111
7632
  async interactiveTransaction(callback, options) {
@@ -7212,7 +7733,7 @@ var ClientImpl = class _ClientImpl {
7212
7733
  }
7213
7734
  $executeRaw(query, ...values) {
7214
7735
  return createZenStackPromise(async () => {
7215
- const result = await (0, import_kysely17.sql)(query, ...values).execute(this.kysely);
7736
+ const result = await (0, import_kysely18.sql)(query, ...values).execute(this.kysely);
7216
7737
  return Number(result.numAffectedRows ?? 0);
7217
7738
  });
7218
7739
  }
@@ -7225,7 +7746,7 @@ var ClientImpl = class _ClientImpl {
7225
7746
  }
7226
7747
  $queryRaw(query, ...values) {
7227
7748
  return createZenStackPromise(async () => {
7228
- const result = await (0, import_kysely17.sql)(query, ...values).execute(this.kysely);
7749
+ const result = await (0, import_kysely18.sql)(query, ...values).execute(this.kysely);
7229
7750
  return result.rows;
7230
7751
  });
7231
7752
  }
@@ -7237,7 +7758,7 @@ var ClientImpl = class _ClientImpl {
7237
7758
  });
7238
7759
  }
7239
7760
  createRawCompiledQuery(query, values) {
7240
- const q = import_kysely17.CompiledQuery.raw(query, values);
7761
+ const q = import_kysely18.CompiledQuery.raw(query, values);
7241
7762
  return {
7242
7763
  ...q,
7243
7764
  $raw: true
@@ -7246,7 +7767,7 @@ var ClientImpl = class _ClientImpl {
7246
7767
  };
7247
7768
  function createClientProxy(client) {
7248
7769
  const inputValidator = new InputValidator(client.$schema);
7249
- const resultProcessor = new ResultProcessor(client.$schema);
7770
+ const resultProcessor = new ResultProcessor(client.$schema, client.$options);
7250
7771
  return new Proxy(client, {
7251
7772
  get: /* @__PURE__ */ __name((target, prop, receiver) => {
7252
7773
  if (typeof prop === "string" && prop.startsWith("$")) {
@@ -7364,7 +7885,7 @@ function definePlugin(plugin) {
7364
7885
  __name(definePlugin, "definePlugin");
7365
7886
 
7366
7887
  // src/client/index.ts
7367
- var import_kysely18 = require("kysely");
7888
+ var import_kysely19 = require("kysely");
7368
7889
  // Annotate the CommonJS export names for ESM import in node:
7369
7890
  0 && (module.exports = {
7370
7891
  InputValidationError,