@zenstackhq/runtime 3.0.0-alpha.12 → 3.0.0-alpha.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -14,6 +14,85 @@ import { match as match19 } from "ts-pattern";
14
14
  import { sql as sql5 } from "kysely";
15
15
  import { match as match9 } from "ts-pattern";
16
16
 
17
+ // src/schema/expression.ts
18
+ var ExpressionUtils = {
19
+ literal: /* @__PURE__ */ __name((value) => {
20
+ return {
21
+ kind: "literal",
22
+ value
23
+ };
24
+ }, "literal"),
25
+ array: /* @__PURE__ */ __name((items) => {
26
+ return {
27
+ kind: "array",
28
+ items
29
+ };
30
+ }, "array"),
31
+ call: /* @__PURE__ */ __name((functionName, args) => {
32
+ return {
33
+ kind: "call",
34
+ function: functionName,
35
+ args
36
+ };
37
+ }, "call"),
38
+ binary: /* @__PURE__ */ __name((left, op, right) => {
39
+ return {
40
+ kind: "binary",
41
+ op,
42
+ left,
43
+ right
44
+ };
45
+ }, "binary"),
46
+ unary: /* @__PURE__ */ __name((op, operand) => {
47
+ return {
48
+ kind: "unary",
49
+ op,
50
+ operand
51
+ };
52
+ }, "unary"),
53
+ field: /* @__PURE__ */ __name((field) => {
54
+ return {
55
+ kind: "field",
56
+ field
57
+ };
58
+ }, "field"),
59
+ member: /* @__PURE__ */ __name((receiver, members) => {
60
+ return {
61
+ kind: "member",
62
+ receiver,
63
+ members
64
+ };
65
+ }, "member"),
66
+ _this: /* @__PURE__ */ __name(() => {
67
+ return {
68
+ kind: "this"
69
+ };
70
+ }, "_this"),
71
+ _null: /* @__PURE__ */ __name(() => {
72
+ return {
73
+ kind: "null"
74
+ };
75
+ }, "_null"),
76
+ and: /* @__PURE__ */ __name((expr2, ...expressions) => {
77
+ return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
78
+ }, "and"),
79
+ or: /* @__PURE__ */ __name((expr2, ...expressions) => {
80
+ return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
81
+ }, "or"),
82
+ is: /* @__PURE__ */ __name((value, kind) => {
83
+ return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
84
+ }, "is"),
85
+ isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
86
+ isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
87
+ isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
88
+ isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
89
+ isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
90
+ isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
91
+ isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
92
+ isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
93
+ isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
94
+ };
95
+
17
96
  // src/client/errors.ts
18
97
  var InputValidationError = class extends Error {
19
98
  static {
@@ -135,6 +214,11 @@ function isRelationField(schema, model, field) {
135
214
  return !!fieldDef.relation;
136
215
  }
137
216
  __name(isRelationField, "isRelationField");
217
+ function isInheritedField(schema, model, field) {
218
+ const fieldDef = requireField(schema, model, field);
219
+ return !!fieldDef.originModel;
220
+ }
221
+ __name(isInheritedField, "isInheritedField");
138
222
  function getUniqueFields(schema, model) {
139
223
  const modelDef = requireModel(schema, model);
140
224
  const result = [];
@@ -287,6 +371,46 @@ function safeJSONStringify(value) {
287
371
  });
288
372
  }
289
373
  __name(safeJSONStringify, "safeJSONStringify");
374
+ function extractFields(object, fields) {
375
+ return fields.reduce((acc, field) => {
376
+ if (field in object) {
377
+ acc[field] = object[field];
378
+ }
379
+ return acc;
380
+ }, {});
381
+ }
382
+ __name(extractFields, "extractFields");
383
+ function extractIdFields(entity, schema, model) {
384
+ const idFields = getIdFields(schema, model);
385
+ return extractFields(entity, idFields);
386
+ }
387
+ __name(extractIdFields, "extractIdFields");
388
+ function getDiscriminatorField(schema, model) {
389
+ const modelDef = requireModel(schema, model);
390
+ const delegateAttr = modelDef.attributes?.find((attr) => attr.name === "@@delegate");
391
+ if (!delegateAttr) {
392
+ return void 0;
393
+ }
394
+ const discriminator = delegateAttr.args?.find((arg) => arg.name === "discriminator");
395
+ if (!discriminator || !ExpressionUtils.isField(discriminator.value)) {
396
+ throw new InternalError(`Discriminator field not defined for model "${model}"`);
397
+ }
398
+ return discriminator.value.field;
399
+ }
400
+ __name(getDiscriminatorField, "getDiscriminatorField");
401
+ function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */ new Set()) {
402
+ const subModels = Object.values(schema.models).filter((m) => m.baseModel === model);
403
+ subModels.forEach((def) => {
404
+ if (!collected.has(def)) {
405
+ collected.add(def);
406
+ getDelegateDescendantModels(schema, def.name, collected);
407
+ }
408
+ });
409
+ return [
410
+ ...collected
411
+ ];
412
+ }
413
+ __name(getDelegateDescendantModels, "getDelegateDescendantModels");
290
414
 
291
415
  // src/client/crud/operations/base.ts
292
416
  import { createId } from "@paralleldrive/cuid2";
@@ -323,6 +447,16 @@ import { invariant as invariant2 } from "@zenstackhq/common-helpers";
323
447
  import { sql as sql2 } from "kysely";
324
448
  import { match as match2 } from "ts-pattern";
325
449
 
450
+ // src/client/constants.ts
451
+ var CONTEXT_COMMENT_PREFIX = "-- $$context:";
452
+ var NUMERIC_FIELD_TYPES = [
453
+ "Int",
454
+ "Float",
455
+ "BigInt",
456
+ "Decimal"
457
+ ];
458
+ var DELEGATE_JOINED_FIELD_PREFIX = "$delegate$";
459
+
326
460
  // src/client/crud/dialects/base.ts
327
461
  import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
328
462
  import { sql } from "kysely";
@@ -356,6 +490,17 @@ var BaseCrudDialect = class {
356
490
  transformPrimitive(value, _type, _forArrayField) {
357
491
  return value;
358
492
  }
493
+ // #region common query builders
494
+ buildSelectModel(eb, model) {
495
+ const modelDef = requireModel(this.schema, model);
496
+ let result = eb.selectFrom(model);
497
+ let joinBase = modelDef.baseModel;
498
+ while (joinBase) {
499
+ result = this.buildDelegateJoin(model, joinBase, result);
500
+ joinBase = requireModel(this.schema, joinBase).baseModel;
501
+ }
502
+ return result;
503
+ }
359
504
  buildFilter(eb, model, modelAlias, where) {
360
505
  if (where === true || where === void 0) {
361
506
  return this.true(eb);
@@ -379,10 +524,13 @@ var BaseCrudDialect = class {
379
524
  const fieldDef = requireField(this.schema, model, key);
380
525
  if (fieldDef.relation) {
381
526
  result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
382
- } else if (fieldDef.array) {
383
- result = this.and(eb, result, this.buildArrayFilter(eb, model, modelAlias, key, fieldDef, payload));
384
527
  } else {
385
- result = this.and(eb, result, this.buildPrimitiveFilter(eb, model, modelAlias, key, fieldDef, payload));
528
+ const fieldRef = buildFieldRef(this.schema, fieldDef.originModel ?? model, key, this.options, eb, fieldDef.originModel ?? modelAlias);
529
+ if (fieldDef.array) {
530
+ result = this.and(eb, result, this.buildArrayFilter(eb, fieldRef, fieldDef, payload));
531
+ } else {
532
+ result = this.and(eb, result, this.buildPrimitiveFilter(eb, fieldRef, fieldDef, payload));
533
+ }
386
534
  }
387
535
  }
388
536
  if ("$expr" in _where && typeof _where["$expr"] === "function") {
@@ -400,19 +548,26 @@ var BaseCrudDialect = class {
400
548
  return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
401
549
  }
402
550
  }
403
- buildToOneRelationFilter(eb, model, table, field, fieldDef, payload) {
551
+ buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
404
552
  if (payload === null) {
405
553
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
406
- if (ownedByModel) {
407
- return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${table}.${fk}`), "is", null)));
554
+ if (ownedByModel && !fieldDef.originModel) {
555
+ return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${modelAlias}.${fk}`), "is", null)));
408
556
  } else {
409
- return this.buildToOneRelationFilter(eb, model, table, field, fieldDef, {
557
+ return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
410
558
  is: null
411
559
  });
412
560
  }
413
561
  }
414
- const joinAlias = `${table}$${field}`;
415
- const joinPairs = buildJoinPairs(this.schema, model, table, field, joinAlias);
562
+ const joinAlias = `${modelAlias}$${field}`;
563
+ const joinPairs = buildJoinPairs(
564
+ this.schema,
565
+ model,
566
+ // if field is from a base, use the base model to join
567
+ fieldDef.originModel ?? modelAlias,
568
+ field,
569
+ joinAlias
570
+ );
416
571
  const filterResultField = `${field}$filter`;
417
572
  const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
418
573
  const conditions = [];
@@ -473,25 +628,24 @@ var BaseCrudDialect = class {
473
628
  }
474
629
  switch (key) {
475
630
  case "some": {
476
- result = this.and(eb, result, eb(eb.selectFrom(relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), ">", 0));
631
+ result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), ">", 0));
477
632
  break;
478
633
  }
479
634
  case "every": {
480
- result = this.and(eb, result, eb(eb.selectFrom(relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("count")).where(buildPkFkWhereRefs(eb)).where((eb1) => eb1.not(this.buildFilter(eb1, relationModel, relationModel, subPayload))), "=", 0));
635
+ result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => eb1.not(this.buildFilter(eb1, relationModel, relationModel, subPayload))), "=", 0));
481
636
  break;
482
637
  }
483
638
  case "none": {
484
- result = this.and(eb, result, eb(eb.selectFrom(relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), "=", 0));
639
+ result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), "=", 0));
485
640
  break;
486
641
  }
487
642
  }
488
643
  }
489
644
  return result;
490
645
  }
491
- buildArrayFilter(eb, model, modelAlias, field, fieldDef, payload) {
646
+ buildArrayFilter(eb, fieldRef, fieldDef, payload) {
492
647
  const clauses = [];
493
648
  const fieldType = fieldDef.type;
494
- const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
495
649
  for (const [key, _value] of Object.entries(payload)) {
496
650
  if (_value === void 0) {
497
651
  continue;
@@ -527,14 +681,14 @@ var BaseCrudDialect = class {
527
681
  }
528
682
  return this.and(eb, ...clauses);
529
683
  }
530
- buildPrimitiveFilter(eb, model, modelAlias, field, fieldDef, payload) {
684
+ buildPrimitiveFilter(eb, fieldRef, fieldDef, payload) {
531
685
  if (payload === null) {
532
- return eb(sql.ref(`${modelAlias}.${field}`), "is", null);
686
+ return eb(fieldRef, "is", null);
533
687
  }
534
688
  if (isEnum(this.schema, fieldDef.type)) {
535
- return this.buildEnumFilter(eb, modelAlias, field, fieldDef, payload);
689
+ return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
536
690
  }
537
- return match(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, model, modelAlias, field, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, modelAlias, field, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, modelAlias, field, payload)).with("Bytes", () => this.buildBytesFilter(eb, modelAlias, field, payload)).with("Json", () => {
691
+ return match(fieldDef.type).with("String", () => this.buildStringFilter(eb, fieldRef, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, fieldRef, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, fieldRef, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, fieldRef, payload)).with("Bytes", () => this.buildBytesFilter(eb, fieldRef, payload)).with("Json", () => {
538
692
  throw new InternalError("JSON filters are not supported yet");
539
693
  }).with("Unsupported", () => {
540
694
  throw new QueryError(`Unsupported field cannot be used in filters`);
@@ -590,9 +744,7 @@ var BaseCrudDialect = class {
590
744
  consumedKeys
591
745
  };
592
746
  }
593
- buildStringFilter(eb, table, field, payload) {
594
- const fieldDef = getField(this.schema, table, field);
595
- let fieldRef = fieldDef?.computed ? sql.ref(field) : sql.ref(`${table}.${field}`);
747
+ buildStringFilter(eb, fieldRef, payload) {
596
748
  let insensitive = false;
597
749
  if (payload && typeof payload === "object" && "mode" in payload && payload.mode === "insensitive") {
598
750
  insensitive = true;
@@ -600,7 +752,7 @@ var BaseCrudDialect = class {
600
752
  fieldRef
601
753
  ]);
602
754
  }
603
- const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => this.prepStringCasing(eb, value, insensitive), (value) => this.buildStringFilter(eb, table, field, value));
755
+ const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => this.prepStringCasing(eb, value, insensitive), (value) => this.buildStringFilter(eb, fieldRef, value));
604
756
  if (payload && typeof payload === "object") {
605
757
  for (const [key, value] of Object.entries(payload)) {
606
758
  if (key === "mode" || consumedKeys.includes(key)) {
@@ -627,23 +779,23 @@ var BaseCrudDialect = class {
627
779
  return value === null ? null : sql.lit(value);
628
780
  }
629
781
  }
630
- buildNumberFilter(eb, model, table, field, type, payload) {
631
- const { conditions } = this.buildStandardFilter(eb, type, payload, buildFieldRef(this.schema, model, field, this.options, eb), (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, model, table, field, type, value));
782
+ buildNumberFilter(eb, fieldRef, type, payload) {
783
+ const { conditions } = this.buildStandardFilter(eb, type, payload, fieldRef, (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, fieldRef, type, value));
632
784
  return this.and(eb, ...conditions);
633
785
  }
634
- buildBooleanFilter(eb, table, field, payload) {
635
- const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
786
+ buildBooleanFilter(eb, fieldRef, payload) {
787
+ const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, fieldRef, (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, fieldRef, value), true, [
636
788
  "equals",
637
789
  "not"
638
790
  ]);
639
791
  return this.and(eb, ...conditions);
640
792
  }
641
- buildDateTimeFilter(eb, table, field, payload) {
642
- const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
793
+ buildDateTimeFilter(eb, fieldRef, payload) {
794
+ const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, fieldRef, (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, fieldRef, value), true);
643
795
  return this.and(eb, ...conditions);
644
796
  }
645
- buildBytesFilter(eb, table, field, payload) {
646
- const conditions = this.buildStandardFilter(eb, "Bytes", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, table, field, value), true, [
797
+ buildBytesFilter(eb, fieldRef, payload) {
798
+ const conditions = this.buildStandardFilter(eb, "Bytes", payload, fieldRef, (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, fieldRef, value), true, [
647
799
  "equals",
648
800
  "in",
649
801
  "notIn",
@@ -651,8 +803,8 @@ var BaseCrudDialect = class {
651
803
  ]);
652
804
  return this.and(eb, ...conditions.conditions);
653
805
  }
654
- buildEnumFilter(eb, table, field, fieldDef, payload) {
655
- const conditions = this.buildStandardFilter(eb, "String", payload, sql.ref(`${table}.${field}`), (value) => value, (value) => this.buildEnumFilter(eb, table, field, fieldDef, value), true, [
806
+ buildEnumFilter(eb, fieldRef, fieldDef, payload) {
807
+ const conditions = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => value, (value) => this.buildEnumFilter(eb, fieldRef, fieldDef, value), true, [
656
808
  "equals",
657
809
  "in",
658
810
  "notIn",
@@ -719,7 +871,7 @@ var BaseCrudDialect = class {
719
871
  invariant(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
720
872
  const sort = this.negateSort(value._count, negated);
721
873
  result = result.orderBy((eb) => {
722
- let subQuery = eb.selectFrom(relationModel);
874
+ let subQuery = this.buildSelectModel(eb, relationModel);
723
875
  const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
724
876
  subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right)))));
725
877
  subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
@@ -738,6 +890,56 @@ var BaseCrudDialect = class {
738
890
  });
739
891
  return result;
740
892
  }
893
+ buildSelectAllFields(model, query, omit) {
894
+ const modelDef = requireModel(this.schema, model);
895
+ let result = query;
896
+ for (const field of Object.keys(modelDef.fields)) {
897
+ if (isRelationField(this.schema, model, field)) {
898
+ continue;
899
+ }
900
+ if (omit?.[field] === true) {
901
+ continue;
902
+ }
903
+ result = this.buildSelectField(result, model, model, field);
904
+ }
905
+ const descendants = getDelegateDescendantModels(this.schema, model);
906
+ for (const subModel of descendants) {
907
+ result = this.buildDelegateJoin(model, subModel.name, result);
908
+ result = result.select((eb) => {
909
+ const jsonObject = {};
910
+ for (const field of Object.keys(subModel.fields)) {
911
+ if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
912
+ continue;
913
+ }
914
+ jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
915
+ }
916
+ return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
917
+ });
918
+ }
919
+ return result;
920
+ }
921
+ buildSelectField(query, model, modelAlias, field) {
922
+ const fieldDef = requireField(this.schema, model, field);
923
+ if (fieldDef.computed) {
924
+ return query.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(field));
925
+ } else if (!fieldDef.originModel) {
926
+ return query.select(sql.ref(`${modelAlias}.${field}`).as(field));
927
+ } else {
928
+ return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
929
+ }
930
+ }
931
+ buildDelegateJoin(thisModel, otherModel, query) {
932
+ const idFields = getIdFields(this.schema, thisModel);
933
+ query = query.leftJoin(otherModel, (qb) => {
934
+ for (const idField of idFields) {
935
+ qb = qb.onRef(`${thisModel}.${idField}`, "=", `${otherModel}.${idField}`);
936
+ }
937
+ return qb;
938
+ });
939
+ return query;
940
+ }
941
+ // #endregion
942
+ // #region utils
741
943
  negateSort(sort, negated) {
742
944
  return negated ? sort === "asc" ? "desc" : "asc" : sort;
743
945
  }
@@ -819,7 +1021,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
819
1021
  const joinTableName = `${parentName}$${relationField}`;
820
1022
  let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
821
1023
  result = eb.selectFrom(() => {
822
- let subQuery = eb.selectFrom(`${relationModel}`).selectAll();
1024
+ let subQuery = this.buildSelectModel(eb, relationModel);
1025
+ subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
823
1026
  if (payload && typeof payload === "object") {
824
1027
  if (payload.where) {
825
1028
  subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
@@ -866,6 +1069,13 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
866
1069
  buildRelationObjectArgs(relationModel, relationField, eb, payload, parentName) {
867
1070
  const relationModelDef = requireModel(this.schema, relationModel);
868
1071
  const objArgs = [];
1072
+ const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
1073
+ if (descendantModels.length > 0) {
1074
+ objArgs.push(...descendantModels.map((subModel) => [
1075
+ sql2.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1076
+ eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
1077
+ ]).flatMap((v) => v));
1078
+ }
869
1079
  if (payload === true || !payload.select) {
870
1080
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
871
1081
  sql2.lit(field),
@@ -958,7 +1168,11 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
958
1168
  if (Array.isArray(value)) {
959
1169
  return value.map((v) => this.transformPrimitive(v, type, false));
960
1170
  } else {
961
- return match3(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);
1171
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
1172
+ return JSON.stringify(value);
1173
+ } else {
1174
+ return match3(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);
1175
+ }
962
1176
  }
963
1177
  }
964
1178
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
@@ -970,7 +1184,8 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
970
1184
  const relationModelDef = requireModel(this.schema, relationModel);
971
1185
  const subQueryName = `${parentName}$${relationField}`;
972
1186
  let tbl = eb.selectFrom(() => {
973
- let subQuery = eb.selectFrom(relationModel).selectAll();
1187
+ let subQuery = this.buildSelectModel(eb, relationModel);
1188
+ subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
974
1189
  if (payload && typeof payload === "object") {
975
1190
  if (payload.where) {
976
1191
  subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
@@ -1006,6 +1221,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1006
1221
  });
1007
1222
  tbl = tbl.select(() => {
1008
1223
  const objArgs = [];
1224
+ const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
1225
+ if (descendantModels.length > 0) {
1226
+ objArgs.push(...descendantModels.map((subModel) => [
1227
+ sql3.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1228
+ eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
1229
+ ]).flatMap((v) => v));
1230
+ }
1009
1231
  if (payload === true || !payload.select) {
1010
1232
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
1011
1233
  sql3.lit(field),
@@ -1088,85 +1310,6 @@ function getCrudDialect(schema, options) {
1088
1310
  }
1089
1311
  __name(getCrudDialect, "getCrudDialect");
1090
1312
 
1091
- // src/schema/expression.ts
1092
- var ExpressionUtils = {
1093
- literal: /* @__PURE__ */ __name((value) => {
1094
- return {
1095
- kind: "literal",
1096
- value
1097
- };
1098
- }, "literal"),
1099
- array: /* @__PURE__ */ __name((items) => {
1100
- return {
1101
- kind: "array",
1102
- items
1103
- };
1104
- }, "array"),
1105
- call: /* @__PURE__ */ __name((functionName, args) => {
1106
- return {
1107
- kind: "call",
1108
- function: functionName,
1109
- args
1110
- };
1111
- }, "call"),
1112
- binary: /* @__PURE__ */ __name((left, op, right) => {
1113
- return {
1114
- kind: "binary",
1115
- op,
1116
- left,
1117
- right
1118
- };
1119
- }, "binary"),
1120
- unary: /* @__PURE__ */ __name((op, operand) => {
1121
- return {
1122
- kind: "unary",
1123
- op,
1124
- operand
1125
- };
1126
- }, "unary"),
1127
- field: /* @__PURE__ */ __name((field) => {
1128
- return {
1129
- kind: "field",
1130
- field
1131
- };
1132
- }, "field"),
1133
- member: /* @__PURE__ */ __name((receiver, members) => {
1134
- return {
1135
- kind: "member",
1136
- receiver,
1137
- members
1138
- };
1139
- }, "member"),
1140
- _this: /* @__PURE__ */ __name(() => {
1141
- return {
1142
- kind: "this"
1143
- };
1144
- }, "_this"),
1145
- _null: /* @__PURE__ */ __name(() => {
1146
- return {
1147
- kind: "null"
1148
- };
1149
- }, "_null"),
1150
- and: /* @__PURE__ */ __name((expr2, ...expressions) => {
1151
- return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
1152
- }, "and"),
1153
- or: /* @__PURE__ */ __name((expr2, ...expressions) => {
1154
- return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
1155
- }, "or"),
1156
- is: /* @__PURE__ */ __name((value, kind) => {
1157
- return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
1158
- }, "is"),
1159
- isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
1160
- isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
1161
- isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
1162
- isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
1163
- isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
1164
- isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
1165
- isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
1166
- isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
1167
- isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
1168
- };
1169
-
1170
1313
  // src/utils/default-operation-node-visitor.ts
1171
1314
  import { OperationNodeVisitor } from "kysely";
1172
1315
  var DefaultOperationNodeVisitor = class extends OperationNodeVisitor {
@@ -2433,10 +2576,10 @@ function clone(value) {
2433
2576
  __name(clone, "clone");
2434
2577
 
2435
2578
  // src/utils/object-utils.ts
2436
- function extractFields(obj, fields) {
2579
+ function extractFields2(obj, fields) {
2437
2580
  return Object.fromEntries(Object.entries(obj).filter(([key]) => fields.includes(key)));
2438
2581
  }
2439
- __name(extractFields, "extractFields");
2582
+ __name(extractFields2, "extractFields");
2440
2583
  function fieldsToSelectObject(fields) {
2441
2584
  return Object.fromEntries(fields.map((f) => [
2442
2585
  f,
@@ -2445,15 +2588,6 @@ function fieldsToSelectObject(fields) {
2445
2588
  }
2446
2589
  __name(fieldsToSelectObject, "fieldsToSelectObject");
2447
2590
 
2448
- // src/client/constants.ts
2449
- var CONTEXT_COMMENT_PREFIX = "-- $$context:";
2450
- var NUMERIC_FIELD_TYPES = [
2451
- "Int",
2452
- "Float",
2453
- "BigInt",
2454
- "Decimal"
2455
- ];
2456
-
2457
2591
  // src/client/crud/operations/base.ts
2458
2592
  var BaseOperationHandler = class {
2459
2593
  static {
@@ -2497,17 +2631,17 @@ var BaseOperationHandler = class {
2497
2631
  getField(model, field) {
2498
2632
  return getField(this.schema, model, field);
2499
2633
  }
2500
- exists(kysely, model, filter) {
2634
+ async exists(kysely, model, filter) {
2501
2635
  const idFields = getIdFields(this.schema, model);
2502
2636
  const _filter = flattenCompoundUniqueFilters(this.schema, model, filter);
2503
2637
  const query = kysely.selectFrom(model).where((eb) => eb.and(_filter)).select(idFields.map((f) => kysely.dynamic.ref(f))).limit(1).modifyEnd(this.makeContextComment({
2504
2638
  model,
2505
2639
  operation: "read"
2506
2640
  }));
2507
- return query.executeTakeFirst();
2641
+ return this.executeQueryTakeFirst(kysely, query, "exists");
2508
2642
  }
2509
2643
  async read(kysely, model, args) {
2510
- let query = kysely.selectFrom(model);
2644
+ let query = this.dialect.buildSelectModel(expressionBuilder2(), model);
2511
2645
  if (args?.where) {
2512
2646
  query = query.where((eb) => this.dialect.buildFilter(eb, model, model, args?.where));
2513
2647
  }
@@ -2532,7 +2666,7 @@ var BaseOperationHandler = class {
2532
2666
  if (args && "select" in args && args.select) {
2533
2667
  query = this.buildFieldSelection(model, query, args.select, model);
2534
2668
  } else {
2535
- query = this.buildSelectAllScalarFields(model, query, args?.omit);
2669
+ query = this.dialect.buildSelectAllFields(model, query, args?.omit);
2536
2670
  }
2537
2671
  if (args && "include" in args && args.include) {
2538
2672
  query = this.buildFieldSelection(model, query, args.include, model);
@@ -2545,14 +2679,18 @@ var BaseOperationHandler = class {
2545
2679
  operation: "read"
2546
2680
  }));
2547
2681
  let result = [];
2682
+ const queryId = {
2683
+ queryId: `zenstack-${createId()}`
2684
+ };
2685
+ const compiled = kysely.getExecutor().compileQuery(query.toOperationNode(), queryId);
2548
2686
  try {
2549
- result = await query.execute();
2687
+ const r = await kysely.getExecutor().executeQuery(compiled, queryId);
2688
+ result = r.rows;
2550
2689
  } catch (err) {
2551
- const { sql: sql11, parameters } = query.compile();
2552
- let message = `Failed to execute query: ${err}, sql: ${sql11}`;
2690
+ let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
2553
2691
  if (this.options.debug) {
2554
2692
  message += `, parameters:
2555
- ${parameters.map((p) => inspect(p)).join("\n")}`;
2693
+ ${compiled.parameters.map((p) => inspect(p)).join("\n")}`;
2556
2694
  }
2557
2695
  throw new QueryError(message, err);
2558
2696
  }
@@ -2589,12 +2727,16 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
2589
2727
  }
2590
2728
  const fieldDef = this.requireField(model, field);
2591
2729
  if (!fieldDef.relation) {
2592
- result = this.selectField(result, model, parentAlias, field);
2730
+ result = this.dialect.buildSelectField(result, model, parentAlias, field);
2593
2731
  } else {
2594
2732
  if (!fieldDef.array && !fieldDef.optional && payload.where) {
2595
2733
  throw new QueryError(`Field "${field}" doesn't support filtering`);
2596
2734
  }
2597
- result = this.dialect.buildRelationSelection(result, model, field, parentAlias, payload);
2735
+ if (fieldDef.originModel) {
2736
+ result = this.dialect.buildRelationSelection(result, fieldDef.originModel, field, fieldDef.originModel, payload);
2737
+ } else {
2738
+ result = this.dialect.buildRelationSelection(result, model, field, parentAlias, payload);
2739
+ }
2598
2740
  }
2599
2741
  }
2600
2742
  return result;
@@ -2627,18 +2769,6 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
2627
2769
  query = query.select((eb2) => this.dialect.buildJsonObject(eb2, jsonObject).as("_count"));
2628
2770
  return query;
2629
2771
  }
2630
- buildSelectAllScalarFields(model, query, omit) {
2631
- const modelDef = this.requireModel(model);
2632
- return Object.keys(modelDef.fields).filter((f) => !isRelationField(this.schema, model, f)).filter((f) => omit?.[f] !== true).reduce((acc, f) => this.selectField(acc, model, model, f), query);
2633
- }
2634
- selectField(query, model, modelAlias, field) {
2635
- const fieldDef = this.requireField(model, field);
2636
- if (!fieldDef.computed) {
2637
- return query.select(sql4.ref(`${modelAlias}.${field}`).as(field));
2638
- } else {
2639
- return query.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(field));
2640
- }
2641
- }
2642
2772
  buildCursorFilter(model, query, cursor, orderBy, negateOrderBy) {
2643
2773
  if (!orderBy) {
2644
2774
  orderBy = makeDefaultOrderBy(this.schema, model);
@@ -2661,9 +2791,12 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
2661
2791
  result = result.where((eb2) => eb2.or(filters));
2662
2792
  return result;
2663
2793
  }
2664
- async create(kysely, model, data, fromRelation) {
2794
+ async create(kysely, model, data, fromRelation, creatingForDelegate = false) {
2665
2795
  const modelDef = this.requireModel(model);
2666
- const createFields = {};
2796
+ if (modelDef.isDelegate && !creatingForDelegate) {
2797
+ throw new QueryError(`Model "${this.model}" is a delegate and cannot be created directly.`);
2798
+ }
2799
+ let createFields = {};
2667
2800
  let parentUpdateTask = void 0;
2668
2801
  let m2m = void 0;
2669
2802
  if (fromRelation) {
@@ -2682,7 +2815,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
2682
2815
  model: fromRelation.model,
2683
2816
  operation: "update"
2684
2817
  }));
2685
- return query2.execute();
2818
+ return this.executeQuery(kysely, query2, "update");
2686
2819
  }, "parentUpdateTask");
2687
2820
  }
2688
2821
  }
@@ -2711,13 +2844,17 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
2711
2844
  }
2712
2845
  }
2713
2846
  }
2847
+ if (modelDef.baseModel) {
2848
+ const baseCreateResult = await this.processBaseModelCreate(kysely, modelDef.baseModel, createFields, model);
2849
+ createFields = baseCreateResult.remainingFields;
2850
+ }
2714
2851
  const updatedData = this.fillGeneratedValues(modelDef, createFields);
2715
2852
  const idFields = getIdFields(this.schema, model);
2716
- const query = kysely.insertInto(model).values(updatedData).returning(idFields).modifyEnd(this.makeContextComment({
2853
+ 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({
2717
2854
  model,
2718
2855
  operation: "create"
2719
2856
  }));
2720
- const createdEntity = await query.executeTakeFirst();
2857
+ const createdEntity = await this.executeQueryTakeFirst(kysely, query, "create");
2721
2858
  if (Object.keys(postCreateRelations).length > 0) {
2722
2859
  const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
2723
2860
  return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
@@ -2732,6 +2869,28 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
2732
2869
  }
2733
2870
  return createdEntity;
2734
2871
  }
2872
+ async processBaseModelCreate(kysely, model, createFields, forModel) {
2873
+ const thisCreateFields = {};
2874
+ const remainingFields = {};
2875
+ Object.entries(createFields).forEach(([field, value]) => {
2876
+ const fieldDef = this.getField(model, field);
2877
+ if (fieldDef) {
2878
+ thisCreateFields[field] = value;
2879
+ } else {
2880
+ remainingFields[field] = value;
2881
+ }
2882
+ });
2883
+ const discriminatorField = getDiscriminatorField(this.schema, model);
2884
+ invariant7(discriminatorField, `Base model "${model}" must have a discriminator field`);
2885
+ thisCreateFields[discriminatorField] = forModel;
2886
+ const baseEntity = await this.create(kysely, model, thisCreateFields, void 0, true);
2887
+ const idValues = extractIdFields(baseEntity, this.schema, model);
2888
+ Object.assign(remainingFields, idValues);
2889
+ return {
2890
+ baseEntity,
2891
+ remainingFields
2892
+ };
2893
+ }
2735
2894
  buildFkAssignments(model, relationField, entity) {
2736
2895
  const parentFkFields = {};
2737
2896
  invariant7(relationField, "parentField must be defined if parentModel is defined");
@@ -2806,7 +2965,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
2806
2965
  case "connect": {
2807
2966
  const referencedPkFields = relationField.relation.references;
2808
2967
  invariant7(referencedPkFields, "relation must have fields info");
2809
- const extractedFks = extractFields(subPayload, referencedPkFields);
2968
+ const extractedFks = extractFields2(subPayload, referencedPkFields);
2810
2969
  if (Object.keys(extractedFks).length === referencedPkFields.length) {
2811
2970
  result = extractedFks;
2812
2971
  } else {
@@ -2901,7 +3060,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
2901
3060
  }
2902
3061
  relationKeyPairs = keyPairs;
2903
3062
  }
2904
- const createData = enumerate(input.data).map((item) => {
3063
+ let createData = enumerate(input.data).map((item) => {
2905
3064
  const newItem = {};
2906
3065
  for (const [name, value] of Object.entries(item)) {
2907
3066
  const fieldDef = this.requireField(model, name);
@@ -2915,14 +3074,21 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
2915
3074
  }
2916
3075
  return this.fillGeneratedValues(modelDef, newItem);
2917
3076
  });
3077
+ if (modelDef.baseModel) {
3078
+ if (input.skipDuplicates) {
3079
+ throw new QueryError('"skipDuplicates" options is not supported for polymorphic models');
3080
+ }
3081
+ const baseCreateResult = await this.processBaseModelCreateMany(kysely, modelDef.baseModel, createData, !!input.skipDuplicates, model);
3082
+ createData = baseCreateResult.remainingFieldRows;
3083
+ }
2918
3084
  const query = kysely.insertInto(model).values(createData).$if(!!input.skipDuplicates, (qb) => qb.onConflict((oc) => oc.doNothing())).modifyEnd(this.makeContextComment({
2919
3085
  model,
2920
3086
  operation: "create"
2921
3087
  }));
2922
3088
  if (!returnData) {
2923
- const result = await query.executeTakeFirstOrThrow();
3089
+ const result = await this.executeQuery(kysely, query, "createMany");
2924
3090
  return {
2925
- count: Number(result.numInsertedOrUpdatedRows)
3091
+ count: Number(result.numAffectedRows)
2926
3092
  };
2927
3093
  } else {
2928
3094
  const idFields = getIdFields(this.schema, model);
@@ -2930,10 +3096,46 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
2930
3096
  return result;
2931
3097
  }
2932
3098
  }
3099
+ async processBaseModelCreateMany(kysely, model, createRows, skipDuplicates, forModel) {
3100
+ const thisCreateRows = [];
3101
+ const remainingFieldRows = [];
3102
+ const discriminatorField = getDiscriminatorField(this.schema, model);
3103
+ invariant7(discriminatorField, `Base model "${model}" must have a discriminator field`);
3104
+ for (const createFields of createRows) {
3105
+ const thisCreateFields = {};
3106
+ const remainingFields = {};
3107
+ Object.entries(createFields).forEach(([field, value]) => {
3108
+ const fieldDef = this.getField(model, field);
3109
+ if (fieldDef) {
3110
+ thisCreateFields[field] = value;
3111
+ } else {
3112
+ remainingFields[field] = value;
3113
+ }
3114
+ });
3115
+ thisCreateFields[discriminatorField] = forModel;
3116
+ thisCreateRows.push(thisCreateFields);
3117
+ remainingFieldRows.push(remainingFields);
3118
+ }
3119
+ const baseEntities = await this.createMany(kysely, model, {
3120
+ data: thisCreateRows,
3121
+ skipDuplicates
3122
+ }, true);
3123
+ for (let i = 0; i < baseEntities.length; i++) {
3124
+ const idValues = extractIdFields(baseEntities[i], this.schema, model);
3125
+ Object.assign(remainingFieldRows[i], idValues);
3126
+ }
3127
+ return {
3128
+ baseEntities,
3129
+ remainingFieldRows
3130
+ };
3131
+ }
2933
3132
  fillGeneratedValues(modelDef, data) {
2934
3133
  const fields = modelDef.fields;
2935
3134
  const values = clone(data);
2936
- for (const field in fields) {
3135
+ for (const [field, fieldDef] of Object.entries(fields)) {
3136
+ if (fieldDef.originModel) {
3137
+ continue;
3138
+ }
2937
3139
  if (!(field in data)) {
2938
3140
  if (typeof fields[field]?.default === "object" && "kind" in fields[field].default) {
2939
3141
  const generated = this.evalGenerator(fields[field].default);
@@ -3010,28 +3212,33 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3010
3212
  }
3011
3213
  }
3012
3214
  if (Object.keys(finalData).length === 0) {
3013
- const r = await this.readUnique(kysely, model, {
3014
- where: combinedWhere
3215
+ return combinedWhere;
3216
+ }
3217
+ let needIdRead = false;
3218
+ if (modelDef.baseModel && !this.isIdFilter(model, combinedWhere)) {
3219
+ needIdRead = true;
3220
+ }
3221
+ if (needIdRead) {
3222
+ const readResult = await this.readUnique(kysely, model, {
3223
+ where: combinedWhere,
3224
+ select: this.makeIdSelect(model)
3015
3225
  });
3016
- if (!r && throwIfNotFound) {
3226
+ if (!readResult && throwIfNotFound) {
3017
3227
  throw new NotFoundError(model);
3018
3228
  }
3019
- return r;
3229
+ combinedWhere = readResult;
3230
+ }
3231
+ if (modelDef.baseModel) {
3232
+ const baseUpdateResult = await this.processBaseModelUpdate(kysely, modelDef.baseModel, combinedWhere, finalData, throwIfNotFound);
3233
+ finalData = baseUpdateResult.remainingFields;
3234
+ combinedWhere = baseUpdateResult.baseEntity;
3020
3235
  }
3021
3236
  const updateFields = {};
3022
3237
  let thisEntity = void 0;
3023
3238
  for (const field in finalData) {
3024
3239
  const fieldDef = this.requireField(model, field);
3025
3240
  if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
3026
- if (this.isNumericField(fieldDef) && typeof finalData[field] === "object" && finalData[field]) {
3027
- updateFields[field] = this.transformIncrementalUpdate(model, field, fieldDef, finalData[field]);
3028
- continue;
3029
- }
3030
- if (fieldDef.array && typeof finalData[field] === "object" && !Array.isArray(finalData[field]) && finalData[field]) {
3031
- updateFields[field] = this.transformScalarListUpdate(model, field, fieldDef, finalData[field]);
3032
- continue;
3033
- }
3034
- updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type, !!fieldDef.array);
3241
+ updateFields[field] = this.processScalarFieldUpdateData(model, field, finalData);
3035
3242
  } else {
3036
3243
  if (!allowRelationUpdate) {
3037
3244
  throw new QueryError(`Relation update not allowed for field "${field}"`);
@@ -3053,16 +3260,14 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3053
3260
  }
3054
3261
  }
3055
3262
  if (Object.keys(updateFields).length === 0) {
3056
- return thisEntity ?? await this.readUnique(kysely, model, {
3057
- where: combinedWhere
3058
- });
3263
+ return combinedWhere;
3059
3264
  } else {
3060
3265
  const idFields = getIdFields(this.schema, model);
3061
3266
  const query = kysely.updateTable(model).where((eb) => this.dialect.buildFilter(eb, model, model, combinedWhere)).set(updateFields).returning(idFields).modifyEnd(this.makeContextComment({
3062
3267
  model,
3063
3268
  operation: "update"
3064
3269
  }));
3065
- const updatedEntity = await query.executeTakeFirst();
3270
+ const updatedEntity = await this.executeQueryTakeFirst(kysely, query, "update");
3066
3271
  if (!updatedEntity) {
3067
3272
  if (throwIfNotFound) {
3068
3273
  throw new NotFoundError(model);
@@ -3073,6 +3278,55 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3073
3278
  return updatedEntity;
3074
3279
  }
3075
3280
  }
3281
+ processScalarFieldUpdateData(model, field, data) {
3282
+ const fieldDef = this.requireField(model, field);
3283
+ if (this.isNumericIncrementalUpdate(fieldDef, data[field])) {
3284
+ return this.transformIncrementalUpdate(model, field, fieldDef, data[field]);
3285
+ }
3286
+ if (fieldDef.array && typeof data[field] === "object" && !Array.isArray(data[field]) && data[field]) {
3287
+ return this.transformScalarListUpdate(model, field, fieldDef, data[field]);
3288
+ }
3289
+ return this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
3290
+ }
3291
+ isNumericIncrementalUpdate(fieldDef, value) {
3292
+ if (!this.isNumericField(fieldDef)) {
3293
+ return false;
3294
+ }
3295
+ if (typeof value !== "object" || !value) {
3296
+ return false;
3297
+ }
3298
+ return [
3299
+ "increment",
3300
+ "decrement",
3301
+ "multiply",
3302
+ "divide",
3303
+ "set"
3304
+ ].some((key) => key in value);
3305
+ }
3306
+ isIdFilter(model, filter) {
3307
+ if (!filter || typeof filter !== "object") {
3308
+ return false;
3309
+ }
3310
+ const idFields = getIdFields(this.schema, model);
3311
+ return idFields.length === Object.keys(filter).length && idFields.every((field) => field in filter);
3312
+ }
3313
+ async processBaseModelUpdate(kysely, model, where, updateFields, throwIfNotFound) {
3314
+ const thisUpdateFields = {};
3315
+ const remainingFields = {};
3316
+ Object.entries(updateFields).forEach(([field, value]) => {
3317
+ const fieldDef = this.getField(model, field);
3318
+ if (fieldDef) {
3319
+ thisUpdateFields[field] = value;
3320
+ } else {
3321
+ remainingFields[field] = value;
3322
+ }
3323
+ });
3324
+ const baseEntity = await this.update(kysely, model, where, thisUpdateFields, void 0, void 0, throwIfNotFound);
3325
+ return {
3326
+ baseEntity,
3327
+ remainingFields
3328
+ };
3329
+ }
3076
3330
  transformIncrementalUpdate(model, field, fieldDef, payload) {
3077
3331
  invariant7(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
3078
3332
  const key = Object.keys(payload)[0];
@@ -3101,7 +3355,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3101
3355
  makeContextComment(context) {
3102
3356
  return sql4.raw(`${CONTEXT_COMMENT_PREFIX}${JSON.stringify(context)}`);
3103
3357
  }
3104
- async updateMany(kysely, model, where, data, limit, returnData) {
3358
+ async updateMany(kysely, model, where, data, limit, returnData, filterModel) {
3105
3359
  if (typeof data !== "object") {
3106
3360
  throw new InternalError("data must be an object");
3107
3361
  }
@@ -3110,34 +3364,52 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3110
3364
  count: 0
3111
3365
  };
3112
3366
  }
3113
- const updateFields = {};
3367
+ const modelDef = this.requireModel(model);
3368
+ if (modelDef.baseModel && limit !== void 0) {
3369
+ throw new QueryError("Updating with a limit is not supported for polymorphic models");
3370
+ }
3371
+ filterModel ??= model;
3372
+ let updateFields = {};
3114
3373
  for (const field in data) {
3115
- const fieldDef = this.requireField(model, field);
3116
3374
  if (isRelationField(this.schema, model, field)) {
3117
3375
  continue;
3118
3376
  }
3119
- updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
3377
+ updateFields[field] = this.processScalarFieldUpdateData(model, field, data);
3378
+ }
3379
+ let shouldFallbackToIdFilter = false;
3380
+ if (limit !== void 0 && !this.dialect.supportsUpdateWithLimit) {
3381
+ shouldFallbackToIdFilter = true;
3382
+ }
3383
+ if (modelDef.isDelegate || modelDef.baseModel) {
3384
+ shouldFallbackToIdFilter = true;
3385
+ }
3386
+ let resultFromBaseModel = void 0;
3387
+ if (modelDef.baseModel) {
3388
+ const baseResult = await this.processBaseModelUpdateMany(kysely, modelDef.baseModel, where, updateFields, filterModel);
3389
+ updateFields = baseResult.remainingFields;
3390
+ resultFromBaseModel = baseResult.baseResult;
3391
+ }
3392
+ if (Object.keys(updateFields).length === 0) {
3393
+ return resultFromBaseModel ?? (returnData ? [] : {
3394
+ count: 0
3395
+ });
3120
3396
  }
3121
3397
  let query = kysely.updateTable(model).set(updateFields);
3122
- if (limit === void 0) {
3123
- query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
3398
+ if (!shouldFallbackToIdFilter) {
3399
+ query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where)).$if(limit !== void 0, (qb) => qb.limit(limit));
3124
3400
  } else {
3125
- if (this.dialect.supportsUpdateWithLimit) {
3126
- query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where)).limit(limit);
3127
- } else {
3128
- query = query.where((eb) => eb(eb.refTuple(
3129
- ...this.buildIdFieldRefs(kysely, model)
3130
- ), "in", kysely.selectFrom(model).where((eb2) => this.dialect.buildFilter(eb2, model, model, where)).select(this.buildIdFieldRefs(kysely, model)).limit(limit)));
3131
- }
3401
+ query = query.where((eb) => eb(eb.refTuple(
3402
+ ...this.buildIdFieldRefs(kysely, model)
3403
+ ), "in", this.dialect.buildSelectModel(eb, filterModel).where(this.dialect.buildFilter(eb, filterModel, filterModel, where)).select(this.buildIdFieldRefs(kysely, filterModel)).$if(limit !== void 0, (qb) => qb.limit(limit))));
3132
3404
  }
3133
3405
  query = query.modifyEnd(this.makeContextComment({
3134
3406
  model,
3135
3407
  operation: "update"
3136
3408
  }));
3137
3409
  if (!returnData) {
3138
- const result = await query.executeTakeFirstOrThrow();
3410
+ const result = await this.executeQuery(kysely, query, "update");
3139
3411
  return {
3140
- count: Number(result.numUpdatedRows)
3412
+ count: Number(result.numAffectedRows)
3141
3413
  };
3142
3414
  } else {
3143
3415
  const idFields = getIdFields(this.schema, model);
@@ -3145,9 +3417,26 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3145
3417
  return result;
3146
3418
  }
3147
3419
  }
3420
+ async processBaseModelUpdateMany(kysely, model, where, updateFields, filterModel) {
3421
+ const thisUpdateFields = {};
3422
+ const remainingFields = {};
3423
+ Object.entries(updateFields).forEach(([field, value]) => {
3424
+ const fieldDef = this.getField(model, field);
3425
+ if (fieldDef) {
3426
+ thisUpdateFields[field] = value;
3427
+ } else {
3428
+ remainingFields[field] = value;
3429
+ }
3430
+ });
3431
+ const baseResult = await this.updateMany(kysely, model, where, thisUpdateFields, void 0, false, filterModel);
3432
+ return {
3433
+ baseResult,
3434
+ remainingFields
3435
+ };
3436
+ }
3148
3437
  buildIdFieldRefs(kysely, model) {
3149
3438
  const idFields = getIdFields(this.schema, model);
3150
- return idFields.map((f) => kysely.dynamic.ref(f));
3439
+ return idFields.map((f) => kysely.dynamic.ref(`${model}.${f}`));
3151
3440
  }
3152
3441
  async processRelationUpdates(kysely, model, field, fieldDef, parentIds, args, throwIfNotFound) {
3153
3442
  const tasks = [];
@@ -3265,7 +3554,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3265
3554
  model: fromRelation.model,
3266
3555
  operation: "update"
3267
3556
  }));
3268
- updateResult = await query.executeTakeFirstOrThrow();
3557
+ updateResult = await this.executeQuery(kysely, query, "connect");
3269
3558
  } else {
3270
3559
  const relationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
3271
3560
  if (!relationFieldDef.array) {
@@ -3276,7 +3565,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3276
3565
  model: fromRelation.model,
3277
3566
  operation: "update"
3278
3567
  }));
3279
- await query2.execute();
3568
+ await this.executeQuery(kysely, query2, "disconnect");
3280
3569
  }
3281
3570
  const query = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
3282
3571
  ...acc,
@@ -3285,9 +3574,9 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3285
3574
  model,
3286
3575
  operation: "update"
3287
3576
  }));
3288
- updateResult = await query.executeTakeFirstOrThrow();
3577
+ updateResult = await this.executeQuery(kysely, query, "connect");
3289
3578
  }
3290
- if (_data.length > updateResult.numUpdatedRows) {
3579
+ if (_data.length > updateResult.numAffectedRows) {
3291
3580
  throw new NotFoundError(model);
3292
3581
  }
3293
3582
  }
@@ -3355,7 +3644,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3355
3644
  model: fromRelation.model,
3356
3645
  operation: "update"
3357
3646
  }));
3358
- await query.executeTakeFirstOrThrow();
3647
+ await this.executeQuery(kysely, query, "disconnect");
3359
3648
  } else {
3360
3649
  const query = kysely.updateTable(model).where(eb.and([
3361
3650
  // fk filter
@@ -3372,7 +3661,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3372
3661
  model,
3373
3662
  operation: "update"
3374
3663
  }));
3375
- await query.executeTakeFirstOrThrow();
3664
+ await this.executeQuery(kysely, query, "disconnect");
3376
3665
  }
3377
3666
  }
3378
3667
  }
@@ -3410,7 +3699,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3410
3699
  model,
3411
3700
  operation: "update"
3412
3701
  }));
3413
- await query.execute();
3702
+ await this.executeQuery(kysely, query, "disconnect");
3414
3703
  if (_data.length > 0) {
3415
3704
  const query2 = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
3416
3705
  ...acc,
@@ -3419,8 +3708,8 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3419
3708
  model,
3420
3709
  operation: "update"
3421
3710
  }));
3422
- const r = await query2.executeTakeFirstOrThrow();
3423
- if (_data.length > r.numUpdatedRows) {
3711
+ const r = await this.executeQuery(kysely, query2, "connect");
3712
+ if (_data.length > r.numAffectedRows) {
3424
3713
  throw new NotFoundError(model);
3425
3714
  }
3426
3715
  }
@@ -3461,7 +3750,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3461
3750
  OR: deleteConditions
3462
3751
  }
3463
3752
  ]
3464
- }, void 0, false);
3753
+ });
3465
3754
  } else {
3466
3755
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
3467
3756
  if (ownedByModel) {
@@ -3484,7 +3773,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3484
3773
  OR: deleteConditions
3485
3774
  }
3486
3775
  ]
3487
- }, void 0, false);
3776
+ });
3488
3777
  } else {
3489
3778
  deleteResult = await this.delete(kysely, model, {
3490
3779
  AND: [
@@ -3496,7 +3785,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3496
3785
  OR: deleteConditions
3497
3786
  }
3498
3787
  ]
3499
- }, void 0, false);
3788
+ });
3500
3789
  }
3501
3790
  }
3502
3791
  if (throwForNotFound && expectedDeleteCount > deleteResult.count) {
@@ -3507,33 +3796,59 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3507
3796
  return enumerate(data).map((item) => flattenCompoundUniqueFilters(this.schema, model, item));
3508
3797
  }
3509
3798
  // #endregion
3510
- async delete(kysely, model, where, limit, returnData) {
3799
+ async delete(kysely, model, where, limit, filterModel) {
3800
+ filterModel ??= model;
3801
+ const modelDef = this.requireModel(model);
3802
+ if (modelDef.baseModel) {
3803
+ if (limit !== void 0) {
3804
+ throw new QueryError("Deleting with a limit is not supported for polymorphic models");
3805
+ }
3806
+ return this.processBaseModelDelete(kysely, modelDef.baseModel, where, limit, filterModel);
3807
+ }
3511
3808
  let query = kysely.deleteFrom(model);
3512
- if (limit === void 0) {
3809
+ let needIdFilter = false;
3810
+ if (limit !== void 0 && !this.dialect.supportsDeleteWithLimit) {
3811
+ needIdFilter = true;
3812
+ }
3813
+ if (modelDef.isDelegate || modelDef.baseModel) {
3814
+ needIdFilter = true;
3815
+ }
3816
+ if (!needIdFilter) {
3513
3817
  query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
3514
3818
  } else {
3515
- if (this.dialect.supportsDeleteWithLimit) {
3516
- query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where)).limit(limit);
3517
- } else {
3518
- query = query.where((eb) => eb(eb.refTuple(
3519
- ...this.buildIdFieldRefs(kysely, model)
3520
- ), "in", kysely.selectFrom(model).where((eb2) => this.dialect.buildFilter(eb2, model, model, where)).select(this.buildIdFieldRefs(kysely, model)).limit(limit)));
3521
- }
3819
+ query = query.where((eb) => eb(eb.refTuple(
3820
+ ...this.buildIdFieldRefs(kysely, model)
3821
+ ), "in", this.dialect.buildSelectModel(eb, filterModel).where((eb2) => this.dialect.buildFilter(eb2, filterModel, filterModel, where)).select(this.buildIdFieldRefs(kysely, filterModel)).$if(limit !== void 0, (qb) => qb.limit(limit))));
3522
3822
  }
3823
+ await this.processDelegateRelationDelete(kysely, modelDef, where, limit);
3523
3824
  query = query.modifyEnd(this.makeContextComment({
3524
3825
  model,
3525
3826
  operation: "delete"
3526
3827
  }));
3527
- if (returnData) {
3528
- const result = await query.execute();
3529
- return result;
3530
- } else {
3531
- const result = await query.executeTakeFirstOrThrow();
3532
- return {
3533
- count: Number(result.numDeletedRows)
3534
- };
3828
+ const result = await this.executeQuery(kysely, query, "delete");
3829
+ return {
3830
+ count: Number(result.numAffectedRows)
3831
+ };
3832
+ }
3833
+ async processDelegateRelationDelete(kysely, modelDef, where, limit) {
3834
+ for (const fieldDef of Object.values(modelDef.fields)) {
3835
+ if (fieldDef.relation && fieldDef.relation.opposite) {
3836
+ const oppositeModelDef = this.requireModel(fieldDef.type);
3837
+ const oppositeRelation = this.requireField(fieldDef.type, fieldDef.relation.opposite);
3838
+ if (oppositeModelDef.baseModel && oppositeRelation.relation?.onDelete === "Cascade") {
3839
+ if (limit !== void 0) {
3840
+ throw new QueryError("Deleting with a limit is not supported for polymorphic models");
3841
+ }
3842
+ await this.delete(kysely, fieldDef.type, {
3843
+ [fieldDef.relation.opposite]: where
3844
+ }, void 0);
3845
+ }
3846
+ }
3535
3847
  }
3536
3848
  }
3849
+ async processBaseModelDelete(kysely, model, where, limit, filterModel) {
3850
+ return this.delete(kysely, model, where, limit, filterModel);
3851
+ }
3537
3852
  makeIdSelect(model) {
3538
3853
  const modelDef = this.requireModel(model);
3539
3854
  return modelDef.idFields.reduce((acc, f) => {
@@ -3567,9 +3882,7 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3567
3882
  return callback(this.kysely);
3568
3883
  } else {
3569
3884
  let txBuilder = this.kysely.transaction();
3570
- if (isolationLevel) {
3571
- txBuilder = txBuilder.setIsolationLevel(isolationLevel);
3572
- }
3885
+ txBuilder = txBuilder.setIsolationLevel(isolationLevel ?? "repeatable read");
3573
3886
  return txBuilder.execute(callback);
3574
3887
  }
3575
3888
  }
@@ -3611,6 +3924,25 @@ ${parameters.map((p) => inspect(p)).join("\n")}`;
3611
3924
  }
3612
3925
  }
3613
3926
  }
3927
+ makeQueryId(operation) {
3928
+ return {
3929
+ queryId: `${operation}-${createId()}`
3930
+ };
3931
+ }
3932
+ executeQuery(kysely, query, operation) {
3933
+ return kysely.executeQuery(query.compile(), this.makeQueryId(operation));
3934
+ }
3935
+ async executeQueryTakeFirst(kysely, query, operation) {
3936
+ const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
3937
+ return result.rows[0];
3938
+ }
3939
+ async executeQueryTakeFirstOrThrow(kysely, query, operation) {
3940
+ const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
3941
+ if (result.rows.length === 0) {
3942
+ throw new QueryError("No rows found");
3943
+ }
3944
+ return result.rows[0];
3945
+ }
3614
3946
  };
3615
3947
 
3616
3948
  // src/client/crud/operations/aggregate.ts
@@ -3622,7 +3954,22 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3622
3954
  const normalizedArgs = this.normalizeArgs(args);
3623
3955
  const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
3624
3956
  let query = this.kysely.selectFrom((eb) => {
3625
- let subQuery = eb.selectFrom(this.model).selectAll(this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
3957
+ let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
3958
+ const selectedFields = [];
3959
+ for (const [key, value] of Object.entries(parsedArgs)) {
3960
+ if (key.startsWith("_") && value && typeof value === "object") {
3961
+ Object.entries(value).filter(([field]) => field !== "_all").filter(([, val]) => val === true).forEach(([field]) => {
3962
+ if (!selectedFields.includes(field)) selectedFields.push(field);
3963
+ });
3964
+ }
3965
+ }
3966
+ if (selectedFields.length > 0) {
3967
+ for (const field of selectedFields) {
3968
+ subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, field);
3969
+ }
3970
+ } else {
3971
+ subQuery = subQuery.select(() => eb.lit(1).as("_all"));
3972
+ }
3626
3973
  const skip = parsedArgs?.skip;
3627
3974
  let take = parsedArgs?.take;
3628
3975
  let negateOrderBy = false;
@@ -3668,9 +4015,9 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3668
4015
  }
3669
4016
  }
3670
4017
  }
3671
- const result = await query.executeTakeFirstOrThrow();
4018
+ const result = await this.executeQuery(this.kysely, query, "aggregate");
3672
4019
  const ret = {};
3673
- for (const [key, value] of Object.entries(result)) {
4020
+ for (const [key, value] of Object.entries(result.rows[0])) {
3674
4021
  if (key === "_count") {
3675
4022
  ret[key] = value;
3676
4023
  continue;
@@ -3715,18 +4062,29 @@ var CountOperationHandler = class extends BaseOperationHandler {
3715
4062
  async handle(_operation, args) {
3716
4063
  const normalizedArgs = this.normalizeArgs(args);
3717
4064
  const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
4065
+ const subQueryName = "$sub";
3718
4066
  let query = this.kysely.selectFrom((eb) => {
3719
- let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4067
+ let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4068
+ if (parsedArgs?.select && typeof parsedArgs.select === "object") {
4069
+ for (const [key, value] of Object.entries(parsedArgs.select)) {
4070
+ if (key !== "_all" && value === true) {
4071
+ subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, key);
4072
+ }
4073
+ }
4074
+ } else {
4075
+ subQuery = subQuery.select(() => eb.lit(1).as("_all"));
4076
+ }
3720
4077
  subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
3721
- return subQuery.as("$sub");
4078
+ return subQuery.as(subQueryName);
3722
4079
  });
3723
4080
  if (parsedArgs?.select && typeof parsedArgs.select === "object") {
3724
- 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(sql6.ref(`$sub.${key}`)), "integer").as(key)));
3725
- return query.executeTakeFirstOrThrow();
4081
+ 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(sql6.ref(`${subQueryName}.${key}`)), "integer").as(key)));
4082
+ const result = await this.executeQuery(this.kysely, query, "count");
4083
+ return result.rows[0];
3726
4084
  } else {
3727
4085
  query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
3728
- const result = await query.executeTakeFirstOrThrow();
3729
- return result.count;
4086
+ const result = await this.executeQuery(this.kysely, query, "count");
4087
+ return result.rows[0].count;
3730
4088
  }
3731
4089
  }
3732
4090
  };
@@ -3805,15 +4163,19 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
3805
4163
  if (!existing) {
3806
4164
  throw new NotFoundError(this.model);
3807
4165
  }
3808
- const result = await this.delete(this.kysely, this.model, args.where, void 0, false);
3809
- if (result.count === 0) {
3810
- throw new NotFoundError(this.model);
3811
- }
4166
+ await this.safeTransaction(async (tx) => {
4167
+ const result = await this.delete(tx, this.model, args.where);
4168
+ if (result.count === 0) {
4169
+ throw new NotFoundError(this.model);
4170
+ }
4171
+ });
3812
4172
  return existing;
3813
4173
  }
3814
4174
  async runDeleteMany(args) {
3815
- const result = await this.delete(this.kysely, this.model, args?.where, args?.limit, false);
3816
- return result;
4175
+ return await this.safeTransaction(async (tx) => {
4176
+ const result = await this.delete(tx, this.model, args?.where, args?.limit);
4177
+ return result;
4178
+ });
3817
4179
  }
3818
4180
  };
3819
4181
 
@@ -3901,8 +4263,8 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
3901
4263
  }
3902
4264
  }
3903
4265
  }
3904
- const result = await query.execute();
3905
- return result.map((row) => this.postProcessRow(row));
4266
+ const result = await this.executeQuery(this.kysely, query, "groupBy");
4267
+ return result.rows.map((row) => this.postProcessRow(row));
3906
4268
  }
3907
4269
  postProcessRow(row) {
3908
4270
  const ret = {};
@@ -3954,22 +4316,35 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3954
4316
  return match13(operation).with("update", () => this.runUpdate(this.inputValidator.validateUpdateArgs(this.model, normalizedArgs))).with("updateMany", () => this.runUpdateMany(this.inputValidator.validateUpdateManyArgs(this.model, normalizedArgs))).with("updateManyAndReturn", () => this.runUpdateManyAndReturn(this.inputValidator.validateUpdateManyAndReturnArgs(this.model, normalizedArgs))).with("upsert", () => this.runUpsert(this.inputValidator.validateUpsertArgs(this.model, normalizedArgs))).exhaustive();
3955
4317
  }
3956
4318
  async runUpdate(args) {
3957
- const result = await this.safeTransaction(async (tx) => {
3958
- const updated = await this.update(tx, this.model, args.where, args.data);
3959
- return this.readUnique(tx, this.model, {
3960
- select: args.select,
3961
- include: args.include,
3962
- omit: args.omit,
3963
- where: getIdValues(this.schema, this.model, updated)
3964
- });
4319
+ const readBackResult = await this.safeTransaction(async (tx) => {
4320
+ const updateResult = await this.update(tx, this.model, args.where, args.data);
4321
+ const readFilter = updateResult ?? args.where;
4322
+ let readBackResult2 = void 0;
4323
+ try {
4324
+ readBackResult2 = await this.readUnique(tx, this.model, {
4325
+ select: args.select,
4326
+ include: args.include,
4327
+ omit: args.omit,
4328
+ where: readFilter
4329
+ });
4330
+ } catch {
4331
+ }
4332
+ return readBackResult2;
3965
4333
  });
3966
- if (!result && this.hasPolicyEnabled) {
3967
- throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
4334
+ if (!readBackResult) {
4335
+ if (this.hasPolicyEnabled) {
4336
+ throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
4337
+ } else {
4338
+ return null;
4339
+ }
4340
+ } else {
4341
+ return readBackResult;
3968
4342
  }
3969
- return result;
3970
4343
  }
3971
4344
  async runUpdateMany(args) {
3972
- return this.updateMany(this.kysely, this.model, args.where, args.data, args.limit, false);
4345
+ return this.safeTransaction(async (tx) => {
4346
+ return this.updateMany(tx, this.model, args.where, args.data, args.limit, false);
4347
+ });
3973
4348
  }
3974
4349
  async runUpdateManyAndReturn(args) {
3975
4350
  if (!args) {
@@ -4108,17 +4483,45 @@ var InputValidator = class {
4108
4483
  return result;
4109
4484
  }
4110
4485
  makePrimitiveSchema(type) {
4111
- return match14(type).with("String", () => z.string()).with("Int", () => z.number()).with("Float", () => z.number()).with("Boolean", () => z.boolean()).with("BigInt", () => z.union([
4112
- z.number(),
4113
- z.bigint()
4114
- ])).with("Decimal", () => z.union([
4115
- z.number(),
4116
- z.instanceof(Decimal),
4117
- z.string()
4118
- ])).with("DateTime", () => z.union([
4119
- z.date(),
4120
- z.string().datetime()
4121
- ])).with("Bytes", () => z.instanceof(Uint8Array)).otherwise(() => z.unknown());
4486
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
4487
+ return this.makeTypeDefSchema(type);
4488
+ } else {
4489
+ return match14(type).with("String", () => z.string()).with("Int", () => z.number()).with("Float", () => z.number()).with("Boolean", () => z.boolean()).with("BigInt", () => z.union([
4490
+ z.number(),
4491
+ z.bigint()
4492
+ ])).with("Decimal", () => z.union([
4493
+ z.number(),
4494
+ z.instanceof(Decimal),
4495
+ z.string()
4496
+ ])).with("DateTime", () => z.union([
4497
+ z.date(),
4498
+ z.string().datetime()
4499
+ ])).with("Bytes", () => z.instanceof(Uint8Array)).otherwise(() => z.unknown());
4500
+ }
4501
+ }
4502
+ makeTypeDefSchema(type) {
4503
+ const key = `$typedef-${type}`;
4504
+ let schema = this.schemaCache.get(key);
4505
+ if (schema) {
4506
+ return schema;
4507
+ }
4508
+ const typeDef = this.schema.typeDefs?.[type];
4509
+ invariant8(typeDef, `Type definition "${type}" not found in schema`);
4510
+ schema = z.looseObject(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
4511
+ let fieldSchema = this.makePrimitiveSchema(def.type);
4512
+ if (def.array) {
4513
+ fieldSchema = fieldSchema.array();
4514
+ }
4515
+ if (def.optional) {
4516
+ fieldSchema = fieldSchema.optional();
4517
+ }
4518
+ return [
4519
+ field,
4520
+ fieldSchema
4521
+ ];
4522
+ })));
4523
+ this.schemaCache.set(key, schema);
4524
+ return schema;
4122
4525
  }
4123
4526
  makeWhereSchema(model, unique, withoutRelationFields = false) {
4124
4527
  const modelDef = getModel(this.schema, model);
@@ -4240,8 +4643,14 @@ var InputValidator = class {
4240
4643
  });
4241
4644
  }
4242
4645
  makePrimitiveFilterSchema(type, optional) {
4646
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
4647
+ return this.makeTypeDefFilterSchema(type, optional);
4648
+ }
4243
4649
  return match14(type).with("String", () => this.makeStringFilterSchema(optional)).with(P2.union("Int", "Float", "Decimal", "BigInt"), (type2) => this.makeNumberFilterSchema(this.makePrimitiveSchema(type2), optional)).with("Boolean", () => this.makeBooleanFilterSchema(optional)).with("DateTime", () => this.makeDateTimeFilterSchema(optional)).with("Bytes", () => this.makeBytesFilterSchema(optional)).with("Json", () => z.any()).with("Unsupported", () => z.never()).exhaustive();
4244
4650
  }
4651
+ makeTypeDefFilterSchema(_type, _optional) {
4652
+ return z.never();
4653
+ }
4245
4654
  makeDateTimeFilterSchema(optional) {
4246
4655
  return this.makeCommonPrimitiveFilterSchema(z.union([
4247
4656
  z.string().datetime(),
@@ -4446,6 +4855,9 @@ var InputValidator = class {
4446
4855
  if (fieldDef.computed) {
4447
4856
  return;
4448
4857
  }
4858
+ if (this.isDelegateDiscriminator(fieldDef)) {
4859
+ return;
4860
+ }
4449
4861
  if (fieldDef.relation) {
4450
4862
  if (withoutRelationFields) {
4451
4863
  return;
@@ -4518,6 +4930,13 @@ var InputValidator = class {
4518
4930
  ]);
4519
4931
  }
4520
4932
  }
4933
+ isDelegateDiscriminator(fieldDef) {
4934
+ if (!fieldDef.originModel) {
4935
+ return false;
4936
+ }
4937
+ const discriminatorField = getDiscriminatorField(this.schema, fieldDef.originModel);
4938
+ return discriminatorField === fieldDef.name;
4939
+ }
4521
4940
  makeRelationManipulationSchema(fieldDef, withoutFields, mode) {
4522
4941
  const fieldType = fieldDef.type;
4523
4942
  const array = !!fieldDef.array;
@@ -4848,11 +5267,11 @@ var ZenStackDriver = class {
4848
5267
  }
4849
5268
  #driver;
4850
5269
  #log;
4851
- txConnection;
4852
5270
  #initPromise;
4853
5271
  #initDone;
4854
5272
  #destroyPromise;
4855
5273
  #connections = /* @__PURE__ */ new WeakSet();
5274
+ #txConnections = /* @__PURE__ */ new WeakMap();
4856
5275
  constructor(driver, log) {
4857
5276
  this.#initDone = false;
4858
5277
  this.#driver = driver;
@@ -4893,21 +5312,30 @@ var ZenStackDriver = class {
4893
5312
  }
4894
5313
  async beginTransaction(connection, settings) {
4895
5314
  const result = await this.#driver.beginTransaction(connection, settings);
4896
- this.txConnection = connection;
5315
+ this.#txConnections.set(connection, []);
4897
5316
  return result;
4898
5317
  }
4899
- commitTransaction(connection) {
5318
+ async commitTransaction(connection) {
4900
5319
  try {
4901
- return this.#driver.commitTransaction(connection);
4902
- } finally {
4903
- this.txConnection = void 0;
5320
+ const result = await this.#driver.commitTransaction(connection);
5321
+ const callbacks = this.#txConnections.get(connection);
5322
+ this.#txConnections.delete(connection);
5323
+ if (callbacks) {
5324
+ for (const callback of callbacks) {
5325
+ await callback();
5326
+ }
5327
+ }
5328
+ return result;
5329
+ } catch (err) {
5330
+ this.#txConnections.delete(connection);
5331
+ throw err;
4904
5332
  }
4905
5333
  }
4906
- rollbackTransaction(connection) {
5334
+ async rollbackTransaction(connection) {
4907
5335
  try {
4908
- return this.#driver.rollbackTransaction(connection);
5336
+ return await this.#driver.rollbackTransaction(connection);
4909
5337
  } finally {
4910
- this.txConnection = void 0;
5338
+ this.#txConnections.delete(connection);
4911
5339
  }
4912
5340
  }
4913
5341
  async destroy() {
@@ -4985,6 +5413,22 @@ var ZenStackDriver = class {
4985
5413
  #calculateDurationMillis(startTime) {
4986
5414
  return performanceNow() - startTime;
4987
5415
  }
5416
+ isTransactionConnection(connection) {
5417
+ return this.#txConnections.has(connection);
5418
+ }
5419
+ registerTransactionCommitCallback(connection, callback) {
5420
+ if (!this.#txConnections.has(connection)) {
5421
+ return;
5422
+ }
5423
+ const callbacks = this.#txConnections.get(connection);
5424
+ if (callbacks) {
5425
+ callbacks.push(callback);
5426
+ } else {
5427
+ this.#txConnections.set(connection, [
5428
+ callback
5429
+ ]);
5430
+ }
5431
+ }
4988
5432
  };
4989
5433
  function performanceNow() {
4990
5434
  if (typeof performance !== "undefined" && typeof performance.now === "function") {
@@ -5201,7 +5645,7 @@ var QueryNameMapper = class extends OperationNodeTransformer2 {
5201
5645
  this.requireCurrentModel(contextNode);
5202
5646
  model = model ?? this.currentModel;
5203
5647
  const modelDef = requireModel(this.schema, model);
5204
- const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed).map(([fieldName]) => fieldName);
5648
+ const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed && !fieldDef.originModel).map(([fieldName]) => fieldName);
5205
5649
  return scalarFields;
5206
5650
  }
5207
5651
  };
@@ -5226,7 +5670,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5226
5670
  get options() {
5227
5671
  return this.client.$options;
5228
5672
  }
5229
- async executeQuery(compiledQuery, queryId) {
5673
+ async executeQuery(compiledQuery, _queryId) {
5230
5674
  let queryNode = compiledQuery.query;
5231
5675
  let mutationInterceptionInfo;
5232
5676
  if (this.isMutationNode(queryNode) && this.hasMutationHooks) {
@@ -5237,7 +5681,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5237
5681
  await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
5238
5682
  }
5239
5683
  const oldQueryNode = queryNode;
5240
- if ((InsertQueryNode2.is(queryNode) || DeleteQueryNode2.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
5684
+ if ((InsertQueryNode2.is(queryNode) || UpdateQueryNode2.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
5241
5685
  queryNode = {
5242
5686
  ...queryNode,
5243
5687
  returning: ReturningNode3.create([
@@ -5246,34 +5690,49 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5246
5690
  };
5247
5691
  }
5248
5692
  const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
5249
- const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams, queryId);
5693
+ const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams);
5250
5694
  if (this.isMutationNode(queryNode)) {
5251
- await this.callAfterQueryInterceptionFilters(result, queryNode, mutationInterceptionInfo);
5695
+ await this.callAfterMutationHooks(result.result, queryNode, mutationInterceptionInfo, result.connection);
5252
5696
  }
5253
5697
  if (oldQueryNode !== queryNode) {
5254
5698
  }
5255
- return result;
5699
+ return result.result;
5256
5700
  }, "task");
5257
5701
  return task();
5258
5702
  }
5259
- proceedQueryWithKyselyInterceptors(queryNode, parameters, queryId) {
5260
- let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters, queryId), "proceed");
5261
- const hooks = this.options.plugins?.filter((plugin) => typeof plugin.onKyselyQuery === "function").map((plugin) => plugin.onKyselyQuery.bind(plugin)) ?? [];
5703
+ proceedQueryWithKyselyInterceptors(queryNode, parameters) {
5704
+ let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters), "proceed");
5705
+ const hooks = [];
5706
+ for (const plugin of this.client.$options.plugins ?? []) {
5707
+ if (plugin.onKyselyQuery) {
5708
+ hooks.push(plugin.onKyselyQuery.bind(plugin));
5709
+ }
5710
+ }
5262
5711
  for (const hook of hooks) {
5263
5712
  const _proceed = proceed;
5264
- proceed = /* @__PURE__ */ __name((query) => {
5265
- return hook({
5713
+ proceed = /* @__PURE__ */ __name(async (query) => {
5714
+ let connection;
5715
+ const _p = /* @__PURE__ */ __name(async (q) => {
5716
+ const r = await _proceed(q);
5717
+ connection = r.connection;
5718
+ return r.result;
5719
+ }, "_p");
5720
+ const hookResult = await hook({
5266
5721
  client: this.client,
5267
5722
  schema: this.client.$schema,
5268
5723
  kysely: this.kysely,
5269
5724
  query,
5270
- proceed: _proceed
5725
+ proceed: _p
5271
5726
  });
5727
+ return {
5728
+ result: hookResult,
5729
+ connection
5730
+ };
5272
5731
  }, "proceed");
5273
5732
  }
5274
5733
  return proceed(queryNode);
5275
5734
  }
5276
- async proceedQuery(query, parameters, queryId) {
5735
+ async proceedQuery(query, parameters) {
5277
5736
  const finalQuery = this.nameMapper.transformNode(query);
5278
5737
  let compiled = this.compileQuery(finalQuery);
5279
5738
  if (parameters) {
@@ -5283,7 +5742,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5283
5742
  };
5284
5743
  }
5285
5744
  try {
5286
- return await super.executeQuery(compiled, queryId);
5745
+ return await this.provideConnection(async (connection) => {
5746
+ const result = await connection.executeQuery(compiled);
5747
+ return {
5748
+ result,
5749
+ connection
5750
+ };
5751
+ });
5287
5752
  } catch (err) {
5288
5753
  let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
5289
5754
  if (this.options.debug) {
@@ -5386,10 +5851,11 @@ ${compiled.parameters.map((p) => inspect2(p)).join("\n")}`;
5386
5851
  return;
5387
5852
  }
5388
5853
  if (this.options.plugins) {
5854
+ const mutationModel = this.getMutationModel(queryNode);
5389
5855
  for (const plugin of this.options.plugins) {
5390
5856
  if (plugin.beforeEntityMutation) {
5391
5857
  await plugin.beforeEntityMutation({
5392
- model: this.getMutationModel(queryNode),
5858
+ model: mutationModel,
5393
5859
  action: mutationInterceptionInfo.action,
5394
5860
  queryNode,
5395
5861
  entities: mutationInterceptionInfo.beforeMutationEntities
@@ -5398,30 +5864,45 @@ ${compiled.parameters.map((p) => inspect2(p)).join("\n")}`;
5398
5864
  }
5399
5865
  }
5400
5866
  }
5401
- async callAfterQueryInterceptionFilters(queryResult, queryNode, mutationInterceptionInfo) {
5867
+ async callAfterMutationHooks(queryResult, queryNode, mutationInterceptionInfo, connection) {
5402
5868
  if (!mutationInterceptionInfo?.intercept) {
5403
5869
  return;
5404
5870
  }
5405
- if (this.options.plugins) {
5406
- const mutationModel = this.getMutationModel(queryNode);
5407
- for (const plugin of this.options.plugins) {
5408
- if (plugin.afterEntityMutation) {
5409
- let afterMutationEntities = void 0;
5410
- if (mutationInterceptionInfo.loadAfterMutationEntity) {
5411
- if (UpdateQueryNode2.is(queryNode)) {
5412
- afterMutationEntities = await this.loadEntities(mutationModel, mutationInterceptionInfo.where);
5413
- } else {
5414
- afterMutationEntities = queryResult.rows;
5415
- }
5416
- }
5417
- await plugin.afterEntityMutation({
5418
- model: this.getMutationModel(queryNode),
5871
+ const hooks = [];
5872
+ for (const plugin of this.options.plugins ?? []) {
5873
+ if (plugin.afterEntityMutation) {
5874
+ hooks.push(plugin.afterEntityMutation.bind(plugin));
5875
+ }
5876
+ }
5877
+ if (hooks.length === 0) {
5878
+ return;
5879
+ }
5880
+ const mutationModel = this.getMutationModel(queryNode);
5881
+ const inTransaction = this.driver.isTransactionConnection(connection);
5882
+ for (const hook of hooks) {
5883
+ let afterMutationEntities = void 0;
5884
+ if (mutationInterceptionInfo.loadAfterMutationEntity) {
5885
+ if (InsertQueryNode2.is(queryNode) || UpdateQueryNode2.is(queryNode)) {
5886
+ afterMutationEntities = queryResult.rows;
5887
+ }
5888
+ }
5889
+ const action = /* @__PURE__ */ __name(async () => {
5890
+ try {
5891
+ await hook({
5892
+ model: mutationModel,
5419
5893
  action: mutationInterceptionInfo.action,
5420
5894
  queryNode,
5421
5895
  beforeMutationEntities: mutationInterceptionInfo.beforeMutationEntities,
5422
5896
  afterMutationEntities
5423
5897
  });
5898
+ } catch (err) {
5899
+ console.error(`Error in afterEntityMutation hook for model "${mutationModel}": ${err}`);
5424
5900
  }
5901
+ }, "action");
5902
+ if (inTransaction) {
5903
+ this.driver.registerTransactionCommitCallback(connection, action);
5904
+ } else {
5905
+ await action();
5425
5906
  }
5426
5907
  }
5427
5908
  }
@@ -5618,7 +6099,7 @@ var SchemaDbPusher = class {
5618
6099
  }
5619
6100
  }
5620
6101
  table = this.addPrimaryKeyConstraint(table, model, modelDef);
5621
- table = this.addUniqueConstraint(table, modelDef);
6102
+ table = this.addUniqueConstraint(table, model, modelDef);
5622
6103
  return table;
5623
6104
  }
5624
6105
  isComputedField(fieldDef) {
@@ -5635,7 +6116,7 @@ var SchemaDbPusher = class {
5635
6116
  }
5636
6117
  return table;
5637
6118
  }
5638
- addUniqueConstraint(table, modelDef) {
6119
+ addUniqueConstraint(table, model, modelDef) {
5639
6120
  for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
5640
6121
  invariant10(typeof value === "object", "expecting an object");
5641
6122
  if ("type" in value) {
@@ -5643,8 +6124,11 @@ var SchemaDbPusher = class {
5643
6124
  if (fieldDef.unique) {
5644
6125
  continue;
5645
6126
  }
6127
+ table = table.addUniqueConstraint(`unique_${model}_${key}`, [
6128
+ key
6129
+ ]);
5646
6130
  } else {
5647
- table = table.addUniqueConstraint(`unique_${key}`, Object.keys(value));
6131
+ table = table.addUniqueConstraint(`unique_${model}_${key}`, Object.keys(value));
5648
6132
  }
5649
6133
  }
5650
6134
  return table;
@@ -5787,6 +6271,21 @@ var ResultProcessor = class {
5787
6271
  data[key] = typeof value === "string" ? JSON.parse(value) : value;
5788
6272
  continue;
5789
6273
  }
6274
+ if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
6275
+ if (value) {
6276
+ const subRow = this.transformJson(value);
6277
+ const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
6278
+ const idValues = getIdValues(this.schema, subModel, subRow);
6279
+ if (Object.values(idValues).some((v) => v === null || v === void 0)) {
6280
+ delete data[key];
6281
+ continue;
6282
+ }
6283
+ const processedSubRow = this.processRow(subRow, subModel);
6284
+ Object.assign(data, processedSubRow);
6285
+ }
6286
+ delete data[key];
6287
+ continue;
6288
+ }
5790
6289
  const fieldDef = getField(this.schema, model, key);
5791
6290
  if (!fieldDef) {
5792
6291
  continue;
@@ -5826,7 +6325,11 @@ var ResultProcessor = class {
5826
6325
  return this.doProcessResult(relationData, fieldDef.type);
5827
6326
  }
5828
6327
  transformScalar(value, type) {
5829
- return match18(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);
6328
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
6329
+ return this.transformJson(value);
6330
+ } else {
6331
+ return match18(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);
6332
+ }
5830
6333
  }
5831
6334
  transformDecimal(value) {
5832
6335
  if (value instanceof Decimal2) {
@@ -6038,19 +6541,26 @@ var ClientImpl = class _ClientImpl {
6038
6541
  await new SchemaDbPusher(this.schema, this.kysely).push();
6039
6542
  }
6040
6543
  $use(plugin) {
6544
+ const newPlugins = [
6545
+ ...this.$options.plugins ?? [],
6546
+ plugin
6547
+ ];
6041
6548
  const newOptions = {
6042
6549
  ...this.options,
6043
- plugins: [
6044
- ...this.options.plugins ?? [],
6045
- plugin
6046
- ]
6550
+ plugins: newPlugins
6047
6551
  };
6048
6552
  return new _ClientImpl(this.schema, newOptions, this);
6049
6553
  }
6050
6554
  $unuse(pluginId) {
6555
+ const newPlugins = [];
6556
+ for (const plugin of this.options.plugins ?? []) {
6557
+ if (plugin.id !== pluginId) {
6558
+ newPlugins.push(plugin);
6559
+ }
6560
+ }
6051
6561
  const newOptions = {
6052
6562
  ...this.options,
6053
- plugins: this.options.plugins?.filter((p) => p.id !== pluginId)
6563
+ plugins: newPlugins
6054
6564
  };
6055
6565
  return new _ClientImpl(this.schema, newOptions, this);
6056
6566
  }