@zenstackhq/orm 3.7.0-beta.1 → 3.7.1

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.mjs CHANGED
@@ -189,6 +189,7 @@ var query_utils_exports = /* @__PURE__ */ __exportAll({
189
189
  fieldHasDefaultValue: () => fieldHasDefaultValue,
190
190
  flattenCompoundUniqueFilters: () => flattenCompoundUniqueFilters,
191
191
  getDelegateDescendantModels: () => getDelegateDescendantModels,
192
+ getDelegateDiscriminatorValue: () => getDelegateDiscriminatorValue,
192
193
  getDiscriminatorField: () => getDiscriminatorField,
193
194
  getEnum: () => getEnum,
194
195
  getField: () => getField,
@@ -422,6 +423,10 @@ function getDiscriminatorField(schema, model) {
422
423
  if (!discriminator || !ExpressionUtils.isField(discriminator.value)) throw createInternalError(`Discriminator field not defined for model "${model}"`, model);
423
424
  return discriminator.value.field;
424
425
  }
426
+ function getDelegateDiscriminatorValue(schema, model) {
427
+ const modelDef = requireModel(schema, model);
428
+ return modelDef.delegateMap ?? modelDef.name;
429
+ }
425
430
  function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */ new Set()) {
426
431
  Object.values(schema.models).filter((m) => m.baseModel === model).forEach((def) => {
427
432
  if (!collected.has(def)) {
@@ -531,6 +536,8 @@ const FILTER_PROPERTY_TO_KIND = {
531
536
  array_contains: "Json",
532
537
  array_starts_with: "Json",
533
538
  array_ends_with: "Json",
539
+ fuzzy: "Fuzzy",
540
+ fts: "FullText",
534
541
  has: "List",
535
542
  hasEvery: "List",
536
543
  hasSome: "List",
@@ -550,6 +557,19 @@ let TransactionIsolationLevel = /* @__PURE__ */ function(TransactionIsolationLev
550
557
  return TransactionIsolationLevel;
551
558
  }({});
552
559
  /**
560
+ * Symbol used as a type-only key on `ClientContract` to brand the `ExtQueryArgs`
561
+ * generic slot. Hidden from member-access autocomplete since symbol keys are
562
+ * not surfaced. Consumed by `InferExtQueryArgs` to recover the slot.
563
+ * @internal
564
+ */
565
+ const ExtQueryArgsMarker = Symbol("zenstack.client.extQueryArgs");
566
+ /**
567
+ * Symbol used as a type-only key on `ClientContract` to brand the `ExtResult`
568
+ * generic slot. Consumed by `InferExtResult` to recover the slot.
569
+ * @internal
570
+ */
571
+ const ExtResultMarker = Symbol("zenstack.client.extResult");
572
+ /**
553
573
  * CRUD operations.
554
574
  */
555
575
  const CRUD = [
@@ -572,8 +592,13 @@ var BaseCrudDialect = class {
572
592
  }
573
593
  /**
574
594
  * Transforms input value before sending to database.
595
+ *
596
+ * `fieldDef` is optional so existing callers that don't have it stay
597
+ * source-compatible. Dialects can use it to inspect `@db.*` native-type
598
+ * attributes (e.g. to format `@db.Time` values as `HH:MM:SS` rather than
599
+ * full ISO timestamps).
575
600
  */
576
- transformInput(value, _type, _forArrayField) {
601
+ transformInput(value, _type, _forArrayField, _fieldDef) {
577
602
  return value;
578
603
  }
579
604
  /**
@@ -616,7 +641,17 @@ var BaseCrudDialect = class {
616
641
  if (existingOrderBy.length > 0 && !alreadySatisfied) effectiveOrderBy = [...distinctFields.map((f) => ({ [f]: "asc" })), ...existingOrderBy];
617
642
  }
618
643
  result = this.buildOrderBy(result, model, modelAlias, effectiveOrderBy, negateOrderBy, take);
619
- if (args.cursor) result = this.buildCursorFilter(model, result, args.cursor, effectiveOrderBy, negateOrderBy, modelAlias);
644
+ if (args.cursor) {
645
+ if (effectiveOrderBy) {
646
+ const offendingKey = enumerate(effectiveOrderBy).map((ob) => {
647
+ if (typeof ob !== "object" || ob === null) return void 0;
648
+ if ("_fuzzyRelevance" in ob) return "_fuzzyRelevance";
649
+ if ("_ftsRelevance" in ob) return "_ftsRelevance";
650
+ }).find((k) => k !== void 0);
651
+ if (offendingKey) throw createNotSupportedError(`cursor pagination cannot be combined with "${offendingKey}" ordering`);
652
+ }
653
+ result = this.buildCursorFilter(model, result, args.cursor, effectiveOrderBy, negateOrderBy, modelAlias);
654
+ }
620
655
  return result;
621
656
  }
622
657
  buildFilter(model, modelAlias, where) {
@@ -756,7 +791,7 @@ var BaseCrudDialect = class {
756
791
  for (const [key, _value] of Object.entries(payload)) {
757
792
  if (_value === void 0) continue;
758
793
  invariant(fieldDef.array, "Field must be an array type to build array filter");
759
- const value = this.transformInput(_value, fieldType, true);
794
+ const value = this.transformInput(_value, fieldType, true, fieldDef);
760
795
  let receiver = fieldRef;
761
796
  if (isEnum(this.schema, fieldType)) receiver = this.eb.cast(fieldRef, sql.raw("text[]"));
762
797
  const buildArray = (value) => {
@@ -791,7 +826,7 @@ var BaseCrudDialect = class {
791
826
  if (payload instanceof DbNullClass || payload instanceof JsonNullClass || payload instanceof AnyNullClass) return this.buildJsonValueFilterClause(fieldRef, payload);
792
827
  return this.buildJsonFilter(fieldRef, payload, fieldDef);
793
828
  }
794
- return match(fieldDef.type).with("String", () => this.buildStringFilter(fieldRef, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(fieldRef, type, payload)).with("Boolean", () => this.buildBooleanFilter(fieldRef, payload)).with("DateTime", () => this.buildDateTimeFilter(fieldRef, payload)).with("Bytes", () => this.buildBytesFilter(fieldRef, payload)).with("Json", () => this.buildJsonFilter(fieldRef, payload, fieldDef)).with("Unsupported", () => {
829
+ return match(fieldDef.type).with("String", () => this.buildStringFilter(fieldRef, payload, fieldDef)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(fieldRef, type, payload)).with("Boolean", () => this.buildBooleanFilter(fieldRef, payload)).with("DateTime", () => this.buildDateTimeFilter(fieldRef, payload)).with("Bytes", () => this.buildBytesFilter(fieldRef, payload)).with("Json", () => this.buildJsonFilter(fieldRef, payload, fieldDef)).with("Unsupported", () => {
795
830
  throw createInvalidInputError(`Unsupported field cannot be used in filters`);
796
831
  }).exhaustive();
797
832
  }
@@ -959,13 +994,23 @@ var BaseCrudDialect = class {
959
994
  consumedKeys
960
995
  };
961
996
  }
962
- buildStringFilter(fieldRef, payload) {
997
+ buildStringFilter(fieldRef, payload, fieldDef) {
963
998
  let mode;
964
999
  if (payload && typeof payload === "object" && "mode" in payload) mode = payload.mode;
965
- const { conditions, consumedKeys } = this.buildStandardFilter("String", payload, mode === "insensitive" ? this.eb.fn("lower", [fieldRef]) : fieldRef, (value) => this.prepStringCasing(this.eb, value, mode), (value) => this.buildStringFilter(fieldRef, value));
1000
+ const { conditions, consumedKeys } = this.buildStandardFilter("String", payload, mode === "insensitive" ? this.eb.fn("lower", [fieldRef]) : fieldRef, (value) => this.prepStringCasing(this.eb, value, mode), (value) => this.buildStringFilter(fieldRef, value, fieldDef));
966
1001
  if (payload && typeof payload === "object") for (const [key, value] of Object.entries(payload)) {
967
1002
  if (key === "mode" || consumedKeys.includes(key)) continue;
968
1003
  if (value === void 0) continue;
1004
+ if (key === "fuzzy") {
1005
+ invariant(fieldDef?.fuzzy === true, `field "${fieldDef?.name ?? "<unknown>"}" is not fuzzy-searchable; add the \`@fuzzy\` attribute to use the \`fuzzy\` filter`);
1006
+ conditions.push(this.buildFuzzyFilter(fieldRef, this.normalizeFuzzyOptions(value)));
1007
+ continue;
1008
+ }
1009
+ if (key === "fts") {
1010
+ invariant(fieldDef?.fullText === true, `field "${fieldDef?.name ?? "<unknown>"}" is not full-text-searchable; add the \`@fullText\` attribute to use the \`fts\` filter`);
1011
+ conditions.push(this.buildFullTextFilter(fieldRef, value));
1012
+ continue;
1013
+ }
969
1014
  invariant(typeof value === "string", `${key} value must be a string`);
970
1015
  const escapedValue = this.escapeLikePattern(value);
971
1016
  const condition = match(key).with("contains", () => this.buildStringLike(fieldRef, `%${escapedValue}%`, mode === "insensitive")).with("startsWith", () => this.buildStringLike(fieldRef, `${escapedValue}%`, mode === "insensitive")).with("endsWith", () => this.buildStringLike(fieldRef, `%${escapedValue}`, mode === "insensitive")).otherwise(() => {
@@ -1034,6 +1079,14 @@ var BaseCrudDialect = class {
1034
1079
  enumerate(orderBy).forEach((orderBy, index) => {
1035
1080
  for (const [field, value] of Object.entries(orderBy)) {
1036
1081
  if (!value) continue;
1082
+ if (field === "_fuzzyRelevance") {
1083
+ result = this.applyFuzzyRelevanceOrderBy(result, model, modelAlias, value, negated, buildFieldRef);
1084
+ continue;
1085
+ }
1086
+ if (field === "_ftsRelevance") {
1087
+ result = this.applyFtsRelevanceOrderBy(result, model, modelAlias, value, negated, buildFieldRef);
1088
+ continue;
1089
+ }
1037
1090
  if ([
1038
1091
  "_count",
1039
1092
  "_avg",
@@ -1041,47 +1094,84 @@ var BaseCrudDialect = class {
1041
1094
  "_min",
1042
1095
  "_max"
1043
1096
  ].includes(field)) {
1044
- invariant(typeof value === "object", `invalid orderBy value for field "${field}"`);
1045
- for (const [k, v] of Object.entries(value)) {
1046
- invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
1047
- result = result.orderBy((eb) => aggregate(eb, buildFieldRef(model, k, modelAlias), field), this.negateSort(v, negated));
1048
- }
1097
+ result = this.applyAggregationOrderBy(result, model, modelAlias, field, value, negated, buildFieldRef);
1049
1098
  continue;
1050
1099
  }
1051
1100
  const fieldDef = requireField(this.schema, model, field);
1052
- if (!fieldDef.relation) {
1053
- const fieldRef = buildFieldRef(model, field, modelAlias);
1054
- if (value === "asc" || value === "desc") result = result.orderBy(fieldRef, this.negateSort(value, negated));
1055
- else if (typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) result = this.buildOrderByField(result, fieldRef, this.negateSort(value.sort, negated), value.nulls);
1056
- } else {
1057
- const relationModel = fieldDef.type;
1058
- if (fieldDef.array) {
1059
- if (typeof value !== "object") throw createInvalidInputError(`invalid orderBy value for field "${field}"`);
1060
- if ("_count" in value) {
1061
- invariant(value._count === "asc" || value._count === "desc", "invalid orderBy value for field \"_count\"");
1062
- const sort = this.negateSort(value._count, negated);
1063
- result = result.orderBy((eb) => {
1064
- const subQueryAlias = tmpAlias(`${modelAlias}$ob$${field}$ct`);
1065
- let subQuery = this.buildSelectModel(relationModel, subQueryAlias);
1066
- const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, subQueryAlias);
1067
- subQuery = subQuery.where(() => this.and(...joinPairs.map(([left, right]) => eb(this.eb.ref(left), "=", this.eb.ref(right)))));
1068
- subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
1069
- return subQuery;
1070
- }, sort);
1071
- }
1072
- } else {
1073
- const joinAlias = tmpAlias(`${modelAlias}$ob$${index}`);
1074
- result = result.leftJoin(`${relationModel} as ${joinAlias}`, (join) => {
1075
- const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, joinAlias);
1076
- return join.on((eb) => this.and(...joinPairs.map(([left, right]) => eb(this.eb.ref(left), "=", this.eb.ref(right)))));
1077
- });
1078
- result = this.buildOrderBy(result, relationModel, joinAlias, value, negated, take);
1079
- }
1080
- }
1101
+ if (!fieldDef.relation) result = this.applyScalarOrderBy(result, model, modelAlias, field, value, negated, buildFieldRef);
1102
+ else result = this.applyRelationOrderBy(result, model, modelAlias, field, fieldDef, value, negated, take, index);
1103
+ }
1104
+ });
1105
+ return result;
1106
+ }
1107
+ applyRelationOrderBy(query, model, modelAlias, field, fieldDef, value, negated, take, index) {
1108
+ const relationModel = fieldDef.type;
1109
+ if (fieldDef.array) {
1110
+ if (typeof value !== "object") throw createInvalidInputError(`invalid orderBy value for field "${field}"`);
1111
+ if ("_count" in value) {
1112
+ invariant(value._count === "asc" || value._count === "desc", "invalid orderBy value for field \"_count\"");
1113
+ const sort = this.negateSort(value._count, negated);
1114
+ return query.orderBy((eb) => {
1115
+ const subQueryAlias = tmpAlias(`${modelAlias}$ob$${field}$ct`);
1116
+ let subQuery = this.buildSelectModel(relationModel, subQueryAlias);
1117
+ const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, subQueryAlias);
1118
+ subQuery = subQuery.where(() => this.and(...joinPairs.map(([left, right]) => eb(this.eb.ref(left), "=", this.eb.ref(right)))));
1119
+ subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
1120
+ return subQuery;
1121
+ }, sort);
1081
1122
  }
1123
+ return query;
1124
+ }
1125
+ const joinAlias = tmpAlias(`${modelAlias}$ob$${index}`);
1126
+ const joined = query.leftJoin(`${relationModel} as ${joinAlias}`, (join) => {
1127
+ const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, joinAlias);
1128
+ return join.on((eb) => this.and(...joinPairs.map(([left, right]) => eb(this.eb.ref(left), "=", this.eb.ref(right)))));
1082
1129
  });
1130
+ return this.buildOrderBy(joined, relationModel, joinAlias, value, negated, take);
1131
+ }
1132
+ applyScalarOrderBy(query, model, modelAlias, field, value, negated, buildFieldRef) {
1133
+ const fieldRef = buildFieldRef(model, field, modelAlias);
1134
+ if (value === "asc" || value === "desc") return query.orderBy(fieldRef, this.negateSort(value, negated));
1135
+ if (typeof value === "object" && "sort" in value && (value.sort === "asc" || value.sort === "desc")) {
1136
+ const sort = this.negateSort(value.sort, negated);
1137
+ if (value.nulls === "first" || value.nulls === "last") return this.buildOrderByField(query, fieldRef, sort, value.nulls);
1138
+ else return query.orderBy(fieldRef, sort);
1139
+ }
1140
+ return query;
1141
+ }
1142
+ applyAggregationOrderBy(query, model, modelAlias, field, value, negated, buildFieldRef) {
1143
+ invariant(typeof value === "object", `invalid orderBy value for field "${field}"`);
1144
+ let result = query;
1145
+ for (const [k, v] of Object.entries(value)) {
1146
+ invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
1147
+ result = result.orderBy((eb) => aggregate(eb, buildFieldRef(model, k, modelAlias), field), this.negateSort(v, negated));
1148
+ }
1083
1149
  return result;
1084
1150
  }
1151
+ applyFuzzyRelevanceOrderBy(query, model, modelAlias, value, negated, buildFieldRef) {
1152
+ invariant(typeof value === "object" && "fields" in value && "search" in value && "sort" in value, "invalid orderBy value for \"_fuzzyRelevance\"");
1153
+ invariant(Array.isArray(value.fields) && value.fields.length > 0, "_fuzzyRelevance.fields must be a non-empty array");
1154
+ invariant(value.sort === "asc" || value.sort === "desc", "invalid sort value for \"_fuzzyRelevance\"");
1155
+ invariant(typeof value.search === "string" && value.search.length > 0, "_fuzzyRelevance.search must be a non-empty string");
1156
+ const mode = value.mode ?? "simple";
1157
+ invariant(mode === "simple" || mode === "word" || mode === "strictWord", "_fuzzyRelevance.mode must be \"simple\", \"word\" or \"strictWord\"");
1158
+ const unaccent = value.unaccent ?? false;
1159
+ invariant(typeof unaccent === "boolean", "_fuzzyRelevance.unaccent must be a boolean");
1160
+ for (const fieldName of value.fields) invariant(requireField(this.schema, model, fieldName).fuzzy === true, `field "${fieldName}" is not fuzzy-searchable; add the \`@fuzzy\` attribute to use it in \`_fuzzyRelevance\``);
1161
+ const fieldRefs = value.fields.map((f) => buildFieldRef(model, f, modelAlias));
1162
+ return this.buildFuzzyRelevanceOrderBy(query, fieldRefs, value.search, this.negateSort(value.sort, negated), mode, unaccent);
1163
+ }
1164
+ applyFtsRelevanceOrderBy(query, model, modelAlias, value, negated, buildFieldRef) {
1165
+ invariant(typeof value === "object" && "fields" in value && "search" in value && "sort" in value, "invalid orderBy value for \"_ftsRelevance\"");
1166
+ invariant(Array.isArray(value.fields) && value.fields.length > 0, "_ftsRelevance.fields must be a non-empty array");
1167
+ invariant(value.sort === "asc" || value.sort === "desc", "invalid sort value for \"_ftsRelevance\"");
1168
+ invariant(typeof value.search === "string" && value.search.length > 0, "_ftsRelevance.search must be a non-empty string");
1169
+ if (value.config !== void 0) invariant(typeof value.config === "string" && value.config.length > 0, "_ftsRelevance.config must be a non-empty string");
1170
+ const config = value.config;
1171
+ for (const fieldName of value.fields) invariant(requireField(this.schema, model, fieldName).fullText === true, `field "${fieldName}" is not full-text-searchable; add the \`@fullText\` attribute to use it in \`_ftsRelevance\``);
1172
+ const fieldRefs = value.fields.map((f) => buildFieldRef(model, f, modelAlias));
1173
+ return this.buildFtsRelevanceOrderBy(query, fieldRefs, value.search, config, this.negateSort(value.sort, negated));
1174
+ }
1085
1175
  buildSelectAllFields(model, query, omit, modelAlias) {
1086
1176
  let result = query;
1087
1177
  for (const fieldDef of getModelFields(this.schema, model, {
@@ -1224,6 +1314,27 @@ var BaseCrudDialect = class {
1224
1314
  buildComparison(left, _leftFieldDef, op, right, _rightFieldDef) {
1225
1315
  return this.eb(left, op, right);
1226
1316
  }
1317
+ /**
1318
+ * Validate the user-provided fuzzy filter payload and apply defaults so dialects
1319
+ * always receive a fully-resolved {@link FuzzyFilterOptions} value.
1320
+ */
1321
+ normalizeFuzzyOptions(value) {
1322
+ invariant(value !== null && typeof value === "object" && !Array.isArray(value), "fuzzy filter must be an object with at least a \"search\" field");
1323
+ const raw = value;
1324
+ invariant(typeof raw["search"] === "string" && raw["search"].length > 0, "fuzzy.search must be a non-empty string");
1325
+ const mode = raw["mode"] ?? "simple";
1326
+ invariant(mode === "simple" || mode === "word" || mode === "strictWord", "fuzzy.mode must be \"simple\", \"word\" or \"strictWord\"");
1327
+ const threshold = raw["threshold"];
1328
+ if (threshold !== void 0) invariant(typeof threshold === "number" && threshold >= 0 && threshold <= 1, "fuzzy.threshold must be a number between 0 and 1");
1329
+ const unaccent = raw["unaccent"] ?? false;
1330
+ invariant(typeof unaccent === "boolean", "fuzzy.unaccent must be a boolean");
1331
+ return {
1332
+ search: raw["search"],
1333
+ mode,
1334
+ threshold,
1335
+ unaccent
1336
+ };
1337
+ }
1227
1338
  };
1228
1339
  //#endregion
1229
1340
  //#region src/client/crud/dialects/lateral-join-dialect-base.ts
@@ -1508,9 +1619,32 @@ var MySqlCrudDialect = class extends LateralJoinDialectBase {
1508
1619
  }
1509
1620
  return result;
1510
1621
  }
1622
+ buildFuzzyFilter(_fieldRef, _options) {
1623
+ throw createNotSupportedError("\"fuzzy\" filter is not supported by the \"mysql\" provider");
1624
+ }
1625
+ buildFuzzyRelevanceOrderBy(_query, _fieldRefs, _search, _sort, _mode, _unaccent) {
1626
+ throw createNotSupportedError("\"_fuzzyRelevance\" ordering is not supported by the \"mysql\" provider");
1627
+ }
1628
+ buildFullTextFilter(_fieldRef, _payload) {
1629
+ throw createNotSupportedError("\"fts\" filter is not supported by the \"mysql\" provider");
1630
+ }
1631
+ buildFtsRelevanceOrderBy(_query, _fieldRefs, _search, _config, _sort) {
1632
+ throw createNotSupportedError("\"_ftsRelevance\" ordering is not supported by the \"mysql\" provider");
1633
+ }
1511
1634
  };
1512
1635
  //#endregion
1513
1636
  //#region src/client/crud/dialects/postgresql.ts
1637
+ /**
1638
+ * Formats a JS `Date` as a Postgres TIME / TIMETZ literal (`HH:MM:SS.fff`,
1639
+ * optionally with `+ZZ:ZZ` for TIMETZ). Reads UTC components so the value
1640
+ * round-trips with ISO-input parsing — callers anchor time-only inputs to
1641
+ * the Unix epoch.
1642
+ */
1643
+ function formatTimeOfDay(date, withTimezone) {
1644
+ const pad = (n, w = 2) => String(n).padStart(w, "0");
1645
+ const time = `${pad(date.getUTCHours())}:${pad(date.getUTCMinutes())}:${pad(date.getUTCSeconds())}.${pad(date.getUTCMilliseconds(), 3)}`;
1646
+ return withTimezone ? `${time}+00:00` : time;
1647
+ }
1514
1648
  var PostgresCrudDialect = class PostgresCrudDialect extends LateralJoinDialectBase {
1515
1649
  static typeParserOverrideApplied = false;
1516
1650
  zmodelToSqlTypeMap = {
@@ -1604,7 +1738,7 @@ var PostgresCrudDialect = class PostgresCrudDialect extends LateralJoinDialectBa
1604
1738
  get insertIgnoreMethod() {
1605
1739
  return "onConflict";
1606
1740
  }
1607
- transformInput(value, type, forArrayField) {
1741
+ transformInput(value, type, forArrayField, fieldDef) {
1608
1742
  if (value === void 0) return value;
1609
1743
  if (value instanceof JsonNullClass) return "null";
1610
1744
  else if (value instanceof DbNullClass) return null;
@@ -1612,9 +1746,15 @@ var PostgresCrudDialect = class PostgresCrudDialect extends LateralJoinDialectBa
1612
1746
  if (isTypeDef(this.schema, type)) if (typeof value !== "string") return JSON.stringify(value);
1613
1747
  else return value;
1614
1748
  else if (Array.isArray(value)) if (type === "Json" && !forArrayField) return JSON.stringify(value);
1615
- else return value.map((v) => this.transformInput(v, type, false));
1749
+ else return value.map((v) => this.transformInput(v, type, false, fieldDef));
1616
1750
  else switch (type) {
1617
- case "DateTime": return value instanceof Date ? value.toISOString() : typeof value === "string" ? new Date(value).toISOString() : value;
1751
+ case "DateTime": {
1752
+ const date = value instanceof Date ? value : typeof value === "string" ? new Date(value) : null;
1753
+ if (date === null || isNaN(date.getTime())) return value;
1754
+ const dbAttrName = fieldDef?.attributes?.find((a) => a.name.startsWith("@db."))?.name;
1755
+ if (dbAttrName === "@db.Time" || dbAttrName === "@db.Timetz") return formatTimeOfDay(date, dbAttrName === "@db.Timetz");
1756
+ return date.toISOString();
1757
+ }
1618
1758
  case "Decimal": return value !== null ? value.toString() : value;
1619
1759
  case "Json": if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") return JSON.stringify(value);
1620
1760
  else return value;
@@ -1786,6 +1926,72 @@ var PostgresCrudDialect = class PostgresCrudDialect extends LateralJoinDialectBa
1786
1926
  return ob;
1787
1927
  });
1788
1928
  }
1929
+ /**
1930
+ * Wraps an expression with `unaccent(lower(...))` or just `lower(...)` depending on
1931
+ * whether the user opted into accent-insensitive matching. The lowering is always
1932
+ * applied so trigram comparisons are case-insensitive on both sides.
1933
+ */
1934
+ normalizeForTrigram(expr, applyUnaccent) {
1935
+ return applyUnaccent ? sql`unaccent(lower(${expr}))` : sql`lower(${expr})`;
1936
+ }
1937
+ buildFuzzyFilter(fieldRef, options) {
1938
+ const fieldExpr = this.normalizeForTrigram(fieldRef, options.unaccent);
1939
+ const valueExpr = this.normalizeForTrigram(sql.val(options.search), options.unaccent);
1940
+ if (options.threshold === void 0) switch (options.mode) {
1941
+ case "simple": return sql`${fieldExpr} % ${valueExpr}`;
1942
+ case "word": return sql`${valueExpr} <% ${fieldExpr}`;
1943
+ case "strictWord": return sql`${valueExpr} <<% ${fieldExpr}`;
1944
+ }
1945
+ const threshold = sql.val(options.threshold);
1946
+ switch (options.mode) {
1947
+ case "simple": return sql`similarity(${fieldExpr}, ${valueExpr}) > ${threshold}`;
1948
+ case "word": return sql`word_similarity(${valueExpr}, ${fieldExpr}) > ${threshold}`;
1949
+ case "strictWord": return sql`strict_word_similarity(${valueExpr}, ${fieldExpr}) > ${threshold}`;
1950
+ }
1951
+ }
1952
+ buildFuzzyRelevanceOrderBy(query, fieldRefs, search, sort, mode, unaccent) {
1953
+ const valueExpr = this.normalizeForTrigram(sql.val(search), unaccent);
1954
+ const buildSimilarity = (fieldRef) => {
1955
+ const fieldExpr = this.normalizeForTrigram(fieldRef, unaccent);
1956
+ switch (mode) {
1957
+ case "simple": return sql`similarity(${fieldExpr}, ${valueExpr})`;
1958
+ case "word": return sql`word_similarity(${valueExpr}, ${fieldExpr})`;
1959
+ case "strictWord": return sql`strict_word_similarity(${valueExpr}, ${fieldExpr})`;
1960
+ }
1961
+ };
1962
+ if (fieldRefs.length === 1) return query.orderBy(buildSimilarity(fieldRefs[0]), sort);
1963
+ const similarities = fieldRefs.map((ref) => buildSimilarity(ref));
1964
+ return query.orderBy(sql`GREATEST(${sql.join(similarities)})`, sort);
1965
+ }
1966
+ buildFullTextFilter(fieldRef, payload) {
1967
+ const options = this.normalizeFullTextOptions(payload);
1968
+ const query = sql.val(options.search);
1969
+ if (options.config === void 0) return sql`to_tsvector(${fieldRef}) @@ to_tsquery(${query})`;
1970
+ const cfg = sql.val(options.config);
1971
+ return sql`to_tsvector(${cfg}::regconfig, ${fieldRef}) @@ to_tsquery(${cfg}::regconfig, ${query})`;
1972
+ }
1973
+ /**
1974
+ * Validate the user-provided `fts` filter payload. When `config` is omitted
1975
+ * it stays `undefined` so {@link buildFullTextFilter} can emit the no-regconfig
1976
+ * SQL form and let Postgres fall back to `default_text_search_config`.
1977
+ */
1978
+ normalizeFullTextOptions(value) {
1979
+ invariant(value !== null && typeof value === "object" && !Array.isArray(value), "fts filter must be an object with at least a \"search\" field");
1980
+ const raw = value;
1981
+ invariant(typeof raw["search"] === "string" && raw["search"].length > 0, "fts.search must be a non-empty string");
1982
+ if (raw["config"] !== void 0) invariant(typeof raw["config"] === "string" && raw["config"].length > 0, "fts.config must be a non-empty string");
1983
+ return {
1984
+ search: raw["search"],
1985
+ config: raw["config"]
1986
+ };
1987
+ }
1988
+ buildFtsRelevanceOrderBy(query, fieldRefs, search, config, sort) {
1989
+ const q = sql.val(search);
1990
+ const document = fieldRefs.length === 1 ? sql`coalesce(${fieldRefs[0]}, '')` : sql`concat_ws(' ', ${sql.join(fieldRefs)})`;
1991
+ if (config === void 0) return query.orderBy(sql`ts_rank(to_tsvector(${document}), to_tsquery(${q}))`, sort);
1992
+ const cfg = sql.val(config);
1993
+ return query.orderBy(sql`ts_rank(to_tsvector(${cfg}::regconfig, ${document}), to_tsquery(${cfg}::regconfig, ${q}))`, sort);
1994
+ }
1789
1995
  };
1790
1996
  //#endregion
1791
1997
  //#region src/client/crud/dialects/sqlite.ts
@@ -2003,6 +2209,18 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
2003
2209
  return ob;
2004
2210
  });
2005
2211
  }
2212
+ buildFuzzyFilter(_fieldRef, _options) {
2213
+ throw createNotSupportedError("\"fuzzy\" filter is not supported by the \"sqlite\" provider");
2214
+ }
2215
+ buildFuzzyRelevanceOrderBy(_query, _fieldRefs, _search, _sort, _mode, _unaccent) {
2216
+ throw createNotSupportedError("\"_fuzzyRelevance\" ordering is not supported by the \"sqlite\" provider");
2217
+ }
2218
+ buildFullTextFilter(_fieldRef, _payload) {
2219
+ throw createNotSupportedError("\"fts\" filter is not supported by the \"sqlite\" provider");
2220
+ }
2221
+ buildFtsRelevanceOrderBy(_query, _fieldRefs, _search, _config, _sort) {
2222
+ throw createNotSupportedError("\"_ftsRelevance\" ordering is not supported by the \"sqlite\" provider");
2223
+ }
2006
2224
  };
2007
2225
  //#endregion
2008
2226
  //#region src/client/crud/dialects/index.ts
@@ -2058,6 +2276,33 @@ function createQuerySchemaFactory(clientOrSchema, options) {
2058
2276
  return new ZodSchemaFactory(clientOrSchema, options);
2059
2277
  }
2060
2278
  /**
2279
+ * Builds a `DateTime` value schema that accepts a `Date` object or any string
2280
+ * the JS `Date` constructor parses, and coerces it to a `Date`. ISO datetime,
2281
+ * ISO date, and time-only strings (e.g. `"09:00:00"` for `@db.Time` fields,
2282
+ * anchored to the Unix epoch) are the documented happy paths; other formats
2283
+ * accepted by `new Date(...)` also pass through, mirroring Prisma's pre-3.5
2284
+ * behaviour. Strings the engine can't parse fall through and are rejected by
2285
+ * `z.date()` with the standard error.
2286
+ *
2287
+ * @see https://github.com/zenstackhq/zenstack/issues/2631
2288
+ */
2289
+ function coercedDateTimeSchema() {
2290
+ return z.preprocess((val) => {
2291
+ if (typeof val !== "string") return val;
2292
+ if (/^\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d\d(?::\d\d)?)?$/.test(val)) {
2293
+ const hasTz = val.endsWith("Z") || /[+-]\d\d(?::\d\d)?$/.test(val);
2294
+ const d = /* @__PURE__ */ new Date(`1970-01-01T${val}${hasTz ? "" : "Z"}`);
2295
+ return isNaN(d.getTime()) ? val : d;
2296
+ }
2297
+ const d = new Date(val);
2298
+ return isNaN(d.getTime()) ? val : d;
2299
+ }, z.union([
2300
+ z.iso.datetime(),
2301
+ z.iso.date(),
2302
+ z.date()
2303
+ ]));
2304
+ }
2305
+ /**
2061
2306
  * Factory class responsible for creating and caching Zod schemas for ORM input validation.
2062
2307
  */
2063
2308
  var ZodSchemaFactory = class {
@@ -2226,7 +2471,7 @@ var ZodSchemaFactory = class {
2226
2471
  const typeDef = getTypeDef(this.schema, type);
2227
2472
  invariant(typeDef, `Type definition "${type}" not found in schema`);
2228
2473
  const schema = z.looseObject(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
2229
- let fieldSchema = this.makeScalarSchema(def.type);
2474
+ let fieldSchema = isTypeDef(this.schema, def.type) ? z.lazy(() => this.makeTypeDefSchema(def.type)) : this.makeScalarSchema(def.type);
2230
2475
  if (def.array) fieldSchema = fieldSchema.array();
2231
2476
  if (def.optional) fieldSchema = fieldSchema.nullish();
2232
2477
  return [field, fieldSchema];
@@ -2270,7 +2515,7 @@ var ZodSchemaFactory = class {
2270
2515
  if (Object.keys(enumDef.values).length > 0) fieldSchema = this.makeEnumFilterSchema(fieldDef.type, !!fieldDef.optional, !!fieldDef.array, withAggregations, allowedFilterKinds);
2271
2516
  } else if (fieldDef.array) fieldSchema = this.makeArrayFilterSchema(fieldDef.type, allowedFilterKinds);
2272
2517
  else if (this.isTypeDefType(fieldDef.type)) fieldSchema = this.makeTypedJsonFilterSchema(fieldDef.type, !!fieldDef.optional, !!fieldDef.array, allowedFilterKinds);
2273
- else fieldSchema = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional, withAggregations, allowedFilterKinds);
2518
+ else fieldSchema = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional, withAggregations, allowedFilterKinds, !!fieldDef.fuzzy, !!fieldDef.fullText);
2274
2519
  }
2275
2520
  if (fieldSchema) fields[field] = fieldSchema.optional();
2276
2521
  }
@@ -2399,8 +2644,8 @@ var ZodSchemaFactory = class {
2399
2644
  const filteredOperators = this.trimFilterOperators(operators, allowedFilterKinds);
2400
2645
  return z.strictObject(filteredOperators);
2401
2646
  }
2402
- makePrimitiveFilterSchema(type, optional, withAggregations, allowedFilterKinds) {
2403
- return match(type).with("String", () => this.makeStringFilterSchema(optional, withAggregations, allowedFilterKinds)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.makeNumberFilterSchema(type, optional, withAggregations, allowedFilterKinds)).with("Boolean", () => this.makeBooleanFilterSchema(optional, withAggregations, allowedFilterKinds)).with("DateTime", () => this.makeDateTimeFilterSchema(optional, withAggregations, allowedFilterKinds)).with("Bytes", () => this.makeBytesFilterSchema(optional, withAggregations, allowedFilterKinds)).with("Json", () => this.makeJsonFilterSchema(optional, allowedFilterKinds)).with("Unsupported", () => z.never()).exhaustive();
2647
+ makePrimitiveFilterSchema(type, optional, withAggregations, allowedFilterKinds, withFuzzy = false, withFullText = false) {
2648
+ return match(type).with("String", () => this.makeStringFilterSchema(optional, withAggregations, allowedFilterKinds, withFuzzy, withFullText)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.makeNumberFilterSchema(type, optional, withAggregations, allowedFilterKinds)).with("Boolean", () => this.makeBooleanFilterSchema(optional, withAggregations, allowedFilterKinds)).with("DateTime", () => this.makeDateTimeFilterSchema(optional, withAggregations, allowedFilterKinds)).with("Bytes", () => this.makeBytesFilterSchema(optional, withAggregations, allowedFilterKinds)).with("Json", () => this.makeJsonFilterSchema(optional, allowedFilterKinds)).with("Unsupported", () => z.never()).exhaustive();
2404
2649
  }
2405
2650
  makeJsonValueSchema() {
2406
2651
  const schema = z.union([
@@ -2442,11 +2687,7 @@ var ZodSchemaFactory = class {
2442
2687
  return schema;
2443
2688
  }
2444
2689
  makeDateTimeValueSchema() {
2445
- const schema = z.union([
2446
- z.iso.datetime(),
2447
- z.iso.date(),
2448
- z.date()
2449
- ]);
2690
+ const schema = coercedDateTimeSchema();
2450
2691
  this.registerSchema("DateTime", schema);
2451
2692
  return schema;
2452
2693
  }
@@ -2542,8 +2783,8 @@ var ZodSchemaFactory = class {
2542
2783
  })}`, schema);
2543
2784
  return schema;
2544
2785
  }
2545
- makeStringFilterSchema(optional, withAggregations, allowedFilterKinds) {
2546
- const baseComponents = this.makeCommonPrimitiveFilterComponents(z.string(), optional, () => z.lazy(() => this.makeStringFilterSchema(optional, withAggregations, allowedFilterKinds)), void 0, withAggregations ? [
2786
+ makeStringFilterSchema(optional, withAggregations, allowedFilterKinds, withFuzzy = false, withFullText = false) {
2787
+ const baseComponents = this.makeCommonPrimitiveFilterComponents(z.string(), optional, () => z.lazy(() => this.makeStringFilterSchema(optional, withAggregations, allowedFilterKinds, withFuzzy, withFullText)), void 0, withAggregations ? [
2547
2788
  "_count",
2548
2789
  "_min",
2549
2790
  "_max"
@@ -2552,6 +2793,8 @@ var ZodSchemaFactory = class {
2552
2793
  startsWith: z.string().optional(),
2553
2794
  endsWith: z.string().optional(),
2554
2795
  contains: z.string().optional(),
2796
+ ...withFuzzy && this.providerSupportsFuzzySearch ? { fuzzy: this.makeFuzzyFilterSchema().optional() } : {},
2797
+ ...withFullText && this.providerSupportsFullTextSearch ? { fts: this.makeFullTextFilterSchema().optional() } : {},
2555
2798
  ...this.providerSupportsCaseSensitivity ? { mode: this.makeStringModeSchema().optional() } : {}
2556
2799
  };
2557
2800
  const filteredStringOperators = this.trimFilterOperators(stringSpecificOperators, allowedFilterKinds);
@@ -2560,16 +2803,35 @@ var ZodSchemaFactory = class {
2560
2803
  ...filteredStringOperators
2561
2804
  };
2562
2805
  const schema = this.createUnionFilterSchema(z.string(), optional, allComponents, allowedFilterKinds);
2806
+ const featureSuffix = `${withFuzzy ? "Fuzzy" : ""}${withFullText ? "FullText" : ""}`;
2563
2807
  this.registerSchema(`StringFilter${this.filterSchemaSuffix({
2564
2808
  optional,
2565
2809
  allowedFilterKinds,
2566
2810
  withAggregations
2567
- })}`, schema);
2811
+ })}${featureSuffix}`, schema);
2568
2812
  return schema;
2569
2813
  }
2570
2814
  makeStringModeSchema() {
2571
2815
  return z.union([z.literal("default"), z.literal("insensitive")]);
2572
2816
  }
2817
+ makeFuzzyFilterSchema() {
2818
+ return z.strictObject({
2819
+ search: z.string().min(1),
2820
+ mode: z.union([
2821
+ z.literal("simple"),
2822
+ z.literal("word"),
2823
+ z.literal("strictWord")
2824
+ ]).default("simple"),
2825
+ threshold: z.number().min(0).max(1).optional(),
2826
+ unaccent: z.boolean().default(false)
2827
+ });
2828
+ }
2829
+ makeFullTextFilterSchema() {
2830
+ return z.strictObject({
2831
+ search: z.string().min(1),
2832
+ config: z.string().min(1).optional()
2833
+ });
2834
+ }
2573
2835
  makeSelectSchema(model, options) {
2574
2836
  const fields = {};
2575
2837
  for (const [field, fieldDef] of this.getModelFields(model)) if (fieldDef.relation) {
@@ -2670,7 +2932,7 @@ var ZodSchemaFactory = class {
2670
2932
  }).optional();
2671
2933
  } else if (fieldDef.optional) fields[field] = z.union([sort, z.strictObject({
2672
2934
  sort,
2673
- nulls: z.union([z.literal("first"), z.literal("last")])
2935
+ nulls: z.union([z.literal("first"), z.literal("last")]).optional()
2674
2936
  })]).optional();
2675
2937
  else fields[field] = sort.optional();
2676
2938
  if (WithAggregation) for (const agg of [
@@ -2680,6 +2942,29 @@ var ZodSchemaFactory = class {
2680
2942
  "_min",
2681
2943
  "_max"
2682
2944
  ]) fields[agg] = z.lazy(() => this.makeOrderBySchema(model, true, false, options).optional());
2945
+ if (this.providerSupportsFuzzySearch) {
2946
+ const fuzzyFieldNames = this.getModelFields(model).filter(([, def]) => !def.relation && def.type === "String" && def.fuzzy === true).map(([name]) => name);
2947
+ if (fuzzyFieldNames.length > 0) fields["_fuzzyRelevance"] = z.strictObject({
2948
+ fields: z.array(z.enum(fuzzyFieldNames)).min(1),
2949
+ search: z.string(),
2950
+ mode: z.union([
2951
+ z.literal("simple"),
2952
+ z.literal("word"),
2953
+ z.literal("strictWord")
2954
+ ]).default("simple"),
2955
+ unaccent: z.boolean().default(false),
2956
+ sort
2957
+ }).optional();
2958
+ }
2959
+ if (this.providerSupportsFullTextSearch) {
2960
+ const fullTextFieldNames = this.getModelFields(model).filter(([, def]) => !def.relation && def.type === "String" && def.fullText === true).map(([name]) => name);
2961
+ if (fullTextFieldNames.length > 0) fields["_ftsRelevance"] = z.strictObject({
2962
+ fields: z.array(z.enum(fullTextFieldNames)).min(1),
2963
+ search: z.string().min(1),
2964
+ config: z.string().min(1).optional(),
2965
+ sort
2966
+ }).optional();
2967
+ }
2683
2968
  const schema = refineAtMostOneKey(z.strictObject(fields));
2684
2969
  let schemaId = `${model}OrderBy`;
2685
2970
  if (withRelation) schemaId += "WithRelation";
@@ -3181,6 +3466,12 @@ var ZodSchemaFactory = class {
3181
3466
  get providerSupportsCaseSensitivity() {
3182
3467
  return this.schema.provider.type === "postgresql";
3183
3468
  }
3469
+ get providerSupportsFullTextSearch() {
3470
+ return this.schema.provider.type === "postgresql";
3471
+ }
3472
+ get providerSupportsFuzzySearch() {
3473
+ return this.schema.provider.type === "postgresql";
3474
+ }
3184
3475
  /**
3185
3476
  * Gets the effective set of allowed FilterKind values for a specific model and field.
3186
3477
  * Respects the precedence: model[field] > model.$all > $all[field] > $all.$all.
@@ -3342,6 +3633,8 @@ __decorate([
3342
3633
  Object,
3343
3634
  Boolean,
3344
3635
  Boolean,
3636
+ Object,
3637
+ Object,
3345
3638
  Object
3346
3639
  ]),
3347
3640
  __decorateMetadata("design:returntype", void 0)
@@ -3411,6 +3704,8 @@ __decorate([
3411
3704
  __decorateMetadata("design:paramtypes", [
3412
3705
  Boolean,
3413
3706
  Boolean,
3707
+ Object,
3708
+ Object,
3414
3709
  Object
3415
3710
  ]),
3416
3711
  __decorateMetadata("design:returntype", typeof (_ref10 = typeof ZodType !== "undefined" && ZodType) === "function" ? _ref10 : Object)
@@ -3900,7 +4195,7 @@ var BaseOperationHandler = class {
3900
4195
  return new this.constructor(client, this.model, this.inputValidator);
3901
4196
  }
3902
4197
  get hasPolicyEnabled() {
3903
- return this.options.plugins?.some((plugin) => plugin.constructor.name === "PolicyPlugin");
4198
+ return this.options.plugins?.some((plugin) => plugin.id === "policy") ?? false;
3904
4199
  }
3905
4200
  requireModel(model) {
3906
4201
  return requireModel(this.schema, model);
@@ -4001,8 +4296,8 @@ var BaseOperationHandler = class {
4001
4296
  const postCreateRelations = {};
4002
4297
  for (const [field, value] of Object.entries(data)) {
4003
4298
  const fieldDef = this.requireField(model, field);
4004
- if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) if (fieldDef.array && value && typeof value === "object" && "set" in value && Array.isArray(value.set)) createFields[field] = this.dialect.transformInput(value.set, fieldDef.type, true);
4005
- else createFields[field] = this.dialect.transformInput(value, fieldDef.type, !!fieldDef.array);
4299
+ if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) if (fieldDef.array && value && typeof value === "object" && "set" in value && Array.isArray(value.set)) createFields[field] = this.dialect.transformInput(value.set, fieldDef.type, true, fieldDef);
4300
+ else createFields[field] = this.dialect.transformInput(value, fieldDef.type, !!fieldDef.array, fieldDef);
4006
4301
  else if (!getManyToManyRelation(this.schema, model, field) && fieldDef.relation?.fields && fieldDef.relation?.references) {
4007
4302
  const fkValues = await this.processOwnedRelationForCreate(kysely, fieldDef, value);
4008
4303
  for (let i = 0; i < fieldDef.relation.fields.length; i++) createFields[fieldDef.relation.fields[i]] = fkValues[fieldDef.relation.references[i]];
@@ -4059,7 +4354,7 @@ var BaseOperationHandler = class {
4059
4354
  });
4060
4355
  const discriminatorField = getDiscriminatorField(this.schema, model);
4061
4356
  invariant(discriminatorField, `Base model "${model}" must have a discriminator field`);
4062
- thisCreateFields[discriminatorField] = forModel;
4357
+ thisCreateFields[discriminatorField] = getDelegateDiscriminatorValue(this.schema, forModel);
4063
4358
  const baseEntity = await this.create(kysely, model, thisCreateFields, void 0, true);
4064
4359
  const idValues = extractIdFields(baseEntity, this.schema, model);
4065
4360
  Object.assign(remainingFields, idValues);
@@ -4202,7 +4497,7 @@ var BaseOperationHandler = class {
4202
4497
  for (const [name, value] of Object.entries(item)) {
4203
4498
  const fieldDef = this.requireField(model, name);
4204
4499
  invariant(!fieldDef.relation, "createMany does not support relations");
4205
- newItem[name] = this.dialect.transformInput(value, fieldDef.type, !!fieldDef.array);
4500
+ newItem[name] = this.dialect.transformInput(value, fieldDef.type, !!fieldDef.array, fieldDef);
4206
4501
  }
4207
4502
  if (fromRelation) for (const { fk, pk } of relationKeyPairs) newItem[fk] = fromRelation.ids[pk];
4208
4503
  return this.fillGeneratedAndDefaultValues(modelDef, newItem);
@@ -4218,7 +4513,7 @@ var BaseOperationHandler = class {
4218
4513
  if (Object.keys(item).length === allPassedFields.length) continue;
4219
4514
  for (const field of allPassedFields) if (!(field in item)) {
4220
4515
  const fieldDef = this.requireField(model, field);
4221
- if (fieldDef.default !== void 0 && fieldDef.default !== null && typeof fieldDef.default !== "object") item[field] = this.dialect.transformInput(fieldDef.default, fieldDef.type, !!fieldDef.array);
4516
+ if (fieldDef.default !== void 0 && fieldDef.default !== null && typeof fieldDef.default !== "object") item[field] = this.dialect.transformInput(fieldDef.default, fieldDef.type, !!fieldDef.array, fieldDef);
4222
4517
  }
4223
4518
  }
4224
4519
  }
@@ -4251,7 +4546,7 @@ var BaseOperationHandler = class {
4251
4546
  if (this.getField(model, field)) thisCreateFields[field] = value;
4252
4547
  else remainingFields[field] = value;
4253
4548
  });
4254
- thisCreateFields[discriminatorField] = forModel;
4549
+ thisCreateFields[discriminatorField] = getDelegateDiscriminatorValue(this.schema, forModel);
4255
4550
  thisCreateRows.push(thisCreateFields);
4256
4551
  remainingFieldRows.push(remainingFields);
4257
4552
  }
@@ -4281,15 +4576,15 @@ var BaseOperationHandler = class {
4281
4576
  if (!(field in data)) {
4282
4577
  if (typeof fieldDef?.default === "object" && "kind" in fieldDef.default) {
4283
4578
  const generated = this.evalGenerator(fieldDef.default);
4284
- if (generated !== void 0) values[field] = this.dialect.transformInput(generated, fieldDef.type, !!fieldDef.array);
4285
- } else if (fieldDef?.updatedAt) values[field] = this.dialect.transformInput(/* @__PURE__ */ new Date(), "DateTime", false);
4579
+ if (generated !== void 0) values[field] = this.dialect.transformInput(generated, fieldDef.type, !!fieldDef.array, fieldDef);
4580
+ } else if (fieldDef?.updatedAt) values[field] = this.dialect.transformInput(/* @__PURE__ */ new Date(), "DateTime", false, fieldDef);
4286
4581
  else if (fieldDef?.default !== void 0) {
4287
4582
  let value = fieldDef.default;
4288
4583
  if (fieldDef.type === "Json") {
4289
4584
  if (fieldDef.array && Array.isArray(value)) value = value.map((v) => typeof v === "string" ? JSON.parse(v) : v);
4290
4585
  else if (typeof value === "string") value = JSON.parse(value);
4291
4586
  }
4292
- values[field] = this.dialect.transformInput(value, fieldDef.type, !!fieldDef.array);
4587
+ values[field] = this.dialect.transformInput(value, fieldDef.type, !!fieldDef.array, fieldDef);
4293
4588
  }
4294
4589
  }
4295
4590
  }
@@ -4339,7 +4634,7 @@ var BaseOperationHandler = class {
4339
4634
  const ignoredFields = new Set(typeof fieldDef.updatedAt === "boolean" ? [] : fieldDef.updatedAt.ignore);
4340
4635
  if (Object.keys(data).some((field) => (isScalarField(this.schema, modelDef.name, field) || isForeignKeyField(this.schema, modelDef.name, field)) && !ignoredFields.has(field))) {
4341
4636
  if (finalData === data) finalData = clone(data);
4342
- finalData[fieldName] = this.dialect.transformInput(/* @__PURE__ */ new Date(), "DateTime", false);
4637
+ finalData[fieldName] = this.dialect.transformInput(/* @__PURE__ */ new Date(), "DateTime", false, fieldDef);
4343
4638
  autoUpdatedFields.push(fieldName);
4344
4639
  }
4345
4640
  }
@@ -4443,7 +4738,7 @@ var BaseOperationHandler = class {
4443
4738
  const fieldDef = this.requireField(model, field);
4444
4739
  if (this.isNumericIncrementalUpdate(fieldDef, data[field])) return this.transformIncrementalUpdate(model, field, fieldDef, data[field]);
4445
4740
  if (fieldDef.array && typeof data[field] === "object" && !Array.isArray(data[field]) && data[field]) return this.transformScalarListUpdate(model, field, fieldDef, data[field]);
4446
- return this.dialect.transformInput(data[field], fieldDef.type, !!fieldDef.array);
4741
+ return this.dialect.transformInput(data[field], fieldDef.type, !!fieldDef.array, fieldDef);
4447
4742
  }
4448
4743
  isNumericIncrementalUpdate(fieldDef, value) {
4449
4744
  if (!this.isNumericField(fieldDef)) return false;
@@ -4471,7 +4766,7 @@ var BaseOperationHandler = class {
4471
4766
  transformIncrementalUpdate(model, field, fieldDef, payload) {
4472
4767
  invariant(Object.keys(payload).length === 1, "Only one of \"set\", \"increment\", \"decrement\", \"multiply\", or \"divide\" can be provided");
4473
4768
  const key = Object.keys(payload)[0];
4474
- const value = this.dialect.transformInput(payload[key], fieldDef.type, false);
4769
+ const value = this.dialect.transformInput(payload[key], fieldDef.type, false, fieldDef);
4475
4770
  const eb = expressionBuilder();
4476
4771
  const fieldRef = this.dialect.fieldRef(model, field);
4477
4772
  return 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(() => {
@@ -4481,7 +4776,7 @@ var BaseOperationHandler = class {
4481
4776
  transformScalarListUpdate(model, field, fieldDef, payload) {
4482
4777
  invariant(Object.keys(payload).length === 1, "Only one of \"set\", \"push\" can be provided");
4483
4778
  const key = Object.keys(payload)[0];
4484
- const value = this.dialect.transformInput(payload[key], fieldDef.type, true);
4779
+ const value = this.dialect.transformInput(payload[key], fieldDef.type, true, fieldDef);
4485
4780
  const eb = expressionBuilder();
4486
4781
  const fieldRef = this.dialect.fieldRef(model, field);
4487
4782
  return match(key).with("set", () => value).with("push", () => {
@@ -6892,12 +7187,21 @@ var ClientImpl = class ClientImpl {
6892
7187
  });
6893
7188
  }
6894
7189
  }
7190
+ getPromiseCallback(promise) {
7191
+ invariant(promise.cb, "Invalid ZenStackPromise, missing cb property");
7192
+ const cb = promise.cb;
7193
+ invariant(typeof cb === "function", "Invalid ZenStackPromise, cb property is not a function");
7194
+ return promise.cb;
7195
+ }
6895
7196
  async sequentialTransaction(arg, options) {
6896
7197
  const execute = async (tx) => {
6897
7198
  const txClient = new ClientImpl(this.schema, this.$options, this);
6898
7199
  txClient.kysely = tx;
6899
7200
  const result = [];
6900
- for (const promise of arg) result.push(await promise.cb(txClient));
7201
+ for (const promise of arg) {
7202
+ const cb = this.getPromiseCallback(promise);
7203
+ result.push(await cb(txClient));
7204
+ }
6901
7205
  return result;
6902
7206
  };
6903
7207
  if (this.kysely.isTransaction) return execute(this.kysely);
@@ -7684,6 +7988,15 @@ var DefaultOperationNodeVisitor = class extends OperationNodeVisitor {
7684
7988
  visitCollate(node) {
7685
7989
  this.defaultVisit(node);
7686
7990
  }
7991
+ visitAlterType(node) {
7992
+ this.defaultVisit(node);
7993
+ }
7994
+ visitAddValue(node) {
7995
+ this.defaultVisit(node);
7996
+ }
7997
+ visitRenameValue(node) {
7998
+ this.defaultVisit(node);
7999
+ }
7687
8000
  };
7688
8001
  //#endregion
7689
8002
  //#region src/utils/schema-utils.ts
@@ -7743,6 +8056,6 @@ var MatchingExpressionVisitor = class extends ExpressionVisitor {
7743
8056
  }
7744
8057
  };
7745
8058
  //#endregion
7746
- export { AllCrudOperations, AllReadOperations, AllWriteOperations, AnyNull, AnyNullClass, BaseCrudDialect, CRUD, CRUD_EXT, CoreCreateOperations, CoreCrudOperations, CoreDeleteOperations, CoreReadOperations, CoreUpdateOperations, CoreWriteOperations, DbNull, DbNullClass, InputValidator, JsonNull, JsonNullClass, kysely_utils_exports as KyselyUtils, ORMError, ORMErrorReason, query_utils_exports as QueryUtils, RejectedByPolicyReason, schema_utils_exports as SchemaUtils, TransactionIsolationLevel, ZenStackClient, createQuerySchemaFactory, definePlugin, getCrudDialect };
8059
+ export { AllCrudOperations, AllReadOperations, AllWriteOperations, AnyNull, AnyNullClass, BaseCrudDialect, CRUD, CRUD_EXT, CoreCreateOperations, CoreCrudOperations, CoreDeleteOperations, CoreReadOperations, CoreUpdateOperations, CoreWriteOperations, DbNull, DbNullClass, ExtQueryArgsMarker, ExtResultMarker, InputValidator, JsonNull, JsonNullClass, kysely_utils_exports as KyselyUtils, ORMError, ORMErrorReason, query_utils_exports as QueryUtils, RejectedByPolicyReason, schema_utils_exports as SchemaUtils, TransactionIsolationLevel, ZenStackClient, createQuerySchemaFactory, definePlugin, getCrudDialect };
7747
8060
 
7748
8061
  //# sourceMappingURL=index.mjs.map