@zenstackhq/runtime 3.0.0-beta.11 → 3.0.0-beta.13

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.d.cts CHANGED
@@ -1038,7 +1038,8 @@ declare class ZenStackError extends Error {
1038
1038
  * Error thrown when input validation fails.
1039
1039
  */
1040
1040
  declare class InputValidationError extends ZenStackError {
1041
- constructor(message: string, cause?: unknown);
1041
+ readonly model: string;
1042
+ constructor(model: string, message: string, cause?: unknown);
1042
1043
  }
1043
1044
  /**
1044
1045
  * Error thrown when a query fails.
@@ -1055,6 +1056,7 @@ declare class InternalError extends ZenStackError {
1055
1056
  * Error thrown when an entity is not found.
1056
1057
  */
1057
1058
  declare class NotFoundError extends ZenStackError {
1059
+ readonly model: string;
1058
1060
  constructor(model: string, details?: string);
1059
1061
  }
1060
1062
  /**
@@ -1129,7 +1131,6 @@ declare function getManyToManyRelation(schema: SchemaDef, model: string, field:
1129
1131
  */
1130
1132
  declare function flattenCompoundUniqueFilters(schema: SchemaDef, model: string, filter: unknown): any;
1131
1133
  declare function ensureArray<T>(value: T | T[]): T[];
1132
- declare function safeJSONStringify(value: unknown): string;
1133
1134
  declare function extractIdFields(entity: any, schema: SchemaDef, model: string): {
1134
1135
  [k: string]: unknown;
1135
1136
  };
@@ -1184,10 +1185,9 @@ declare const queryUtils_makeDefaultOrderBy: typeof makeDefaultOrderBy;
1184
1185
  declare const queryUtils_requireField: typeof requireField;
1185
1186
  declare const queryUtils_requireIdFields: typeof requireIdFields;
1186
1187
  declare const queryUtils_requireModel: typeof requireModel;
1187
- declare const queryUtils_safeJSONStringify: typeof safeJSONStringify;
1188
1188
  declare const queryUtils_stripAlias: typeof stripAlias;
1189
1189
  declare namespace queryUtils {
1190
- export { queryUtils_aggregate as aggregate, queryUtils_buildJoinPairs as buildJoinPairs, queryUtils_ensureArray as ensureArray, queryUtils_extractFieldName as extractFieldName, queryUtils_extractIdFields as extractIdFields, queryUtils_extractModelName as extractModelName, queryUtils_fieldHasDefaultValue as fieldHasDefaultValue, queryUtils_flattenCompoundUniqueFilters as flattenCompoundUniqueFilters, queryUtils_getDelegateDescendantModels as getDelegateDescendantModels, queryUtils_getDiscriminatorField as getDiscriminatorField, queryUtils_getEnum as getEnum, queryUtils_getField as getField, queryUtils_getIdFields as getIdFields, queryUtils_getIdValues as getIdValues, queryUtils_getManyToManyRelation as getManyToManyRelation, queryUtils_getModel as getModel, queryUtils_getRelationForeignKeyFieldPairs as getRelationForeignKeyFieldPairs, queryUtils_getTypeDef as getTypeDef, queryUtils_getUniqueFields as getUniqueFields, queryUtils_hasModel as hasModel, queryUtils_isEnum as isEnum, queryUtils_isForeignKeyField as isForeignKeyField, queryUtils_isInheritedField as isInheritedField, queryUtils_isRelationField as isRelationField, queryUtils_isScalarField as isScalarField, queryUtils_makeDefaultOrderBy as makeDefaultOrderBy, queryUtils_requireField as requireField, queryUtils_requireIdFields as requireIdFields, queryUtils_requireModel as requireModel, queryUtils_safeJSONStringify as safeJSONStringify, queryUtils_stripAlias as stripAlias };
1190
+ export { queryUtils_aggregate as aggregate, queryUtils_buildJoinPairs as buildJoinPairs, queryUtils_ensureArray as ensureArray, queryUtils_extractFieldName as extractFieldName, queryUtils_extractIdFields as extractIdFields, queryUtils_extractModelName as extractModelName, queryUtils_fieldHasDefaultValue as fieldHasDefaultValue, queryUtils_flattenCompoundUniqueFilters as flattenCompoundUniqueFilters, queryUtils_getDelegateDescendantModels as getDelegateDescendantModels, queryUtils_getDiscriminatorField as getDiscriminatorField, queryUtils_getEnum as getEnum, queryUtils_getField as getField, queryUtils_getIdFields as getIdFields, queryUtils_getIdValues as getIdValues, queryUtils_getManyToManyRelation as getManyToManyRelation, queryUtils_getModel as getModel, queryUtils_getRelationForeignKeyFieldPairs as getRelationForeignKeyFieldPairs, queryUtils_getTypeDef as getTypeDef, queryUtils_getUniqueFields as getUniqueFields, queryUtils_hasModel as hasModel, queryUtils_isEnum as isEnum, queryUtils_isForeignKeyField as isForeignKeyField, queryUtils_isInheritedField as isInheritedField, queryUtils_isRelationField as isRelationField, queryUtils_isScalarField as isScalarField, queryUtils_makeDefaultOrderBy as makeDefaultOrderBy, queryUtils_requireField as requireField, queryUtils_requireIdFields as requireIdFields, queryUtils_requireModel as requireModel, queryUtils_stripAlias as stripAlias };
1191
1191
  }
1192
1192
 
1193
1193
  declare class DefaultOperationNodeVisitor extends OperationNodeVisitor {
package/dist/index.d.ts CHANGED
@@ -1038,7 +1038,8 @@ declare class ZenStackError extends Error {
1038
1038
  * Error thrown when input validation fails.
1039
1039
  */
1040
1040
  declare class InputValidationError extends ZenStackError {
1041
- constructor(message: string, cause?: unknown);
1041
+ readonly model: string;
1042
+ constructor(model: string, message: string, cause?: unknown);
1042
1043
  }
1043
1044
  /**
1044
1045
  * Error thrown when a query fails.
@@ -1055,6 +1056,7 @@ declare class InternalError extends ZenStackError {
1055
1056
  * Error thrown when an entity is not found.
1056
1057
  */
1057
1058
  declare class NotFoundError extends ZenStackError {
1059
+ readonly model: string;
1058
1060
  constructor(model: string, details?: string);
1059
1061
  }
1060
1062
  /**
@@ -1129,7 +1131,6 @@ declare function getManyToManyRelation(schema: SchemaDef, model: string, field:
1129
1131
  */
1130
1132
  declare function flattenCompoundUniqueFilters(schema: SchemaDef, model: string, filter: unknown): any;
1131
1133
  declare function ensureArray<T>(value: T | T[]): T[];
1132
- declare function safeJSONStringify(value: unknown): string;
1133
1134
  declare function extractIdFields(entity: any, schema: SchemaDef, model: string): {
1134
1135
  [k: string]: unknown;
1135
1136
  };
@@ -1184,10 +1185,9 @@ declare const queryUtils_makeDefaultOrderBy: typeof makeDefaultOrderBy;
1184
1185
  declare const queryUtils_requireField: typeof requireField;
1185
1186
  declare const queryUtils_requireIdFields: typeof requireIdFields;
1186
1187
  declare const queryUtils_requireModel: typeof requireModel;
1187
- declare const queryUtils_safeJSONStringify: typeof safeJSONStringify;
1188
1188
  declare const queryUtils_stripAlias: typeof stripAlias;
1189
1189
  declare namespace queryUtils {
1190
- export { queryUtils_aggregate as aggregate, queryUtils_buildJoinPairs as buildJoinPairs, queryUtils_ensureArray as ensureArray, queryUtils_extractFieldName as extractFieldName, queryUtils_extractIdFields as extractIdFields, queryUtils_extractModelName as extractModelName, queryUtils_fieldHasDefaultValue as fieldHasDefaultValue, queryUtils_flattenCompoundUniqueFilters as flattenCompoundUniqueFilters, queryUtils_getDelegateDescendantModels as getDelegateDescendantModels, queryUtils_getDiscriminatorField as getDiscriminatorField, queryUtils_getEnum as getEnum, queryUtils_getField as getField, queryUtils_getIdFields as getIdFields, queryUtils_getIdValues as getIdValues, queryUtils_getManyToManyRelation as getManyToManyRelation, queryUtils_getModel as getModel, queryUtils_getRelationForeignKeyFieldPairs as getRelationForeignKeyFieldPairs, queryUtils_getTypeDef as getTypeDef, queryUtils_getUniqueFields as getUniqueFields, queryUtils_hasModel as hasModel, queryUtils_isEnum as isEnum, queryUtils_isForeignKeyField as isForeignKeyField, queryUtils_isInheritedField as isInheritedField, queryUtils_isRelationField as isRelationField, queryUtils_isScalarField as isScalarField, queryUtils_makeDefaultOrderBy as makeDefaultOrderBy, queryUtils_requireField as requireField, queryUtils_requireIdFields as requireIdFields, queryUtils_requireModel as requireModel, queryUtils_safeJSONStringify as safeJSONStringify, queryUtils_stripAlias as stripAlias };
1190
+ export { queryUtils_aggregate as aggregate, queryUtils_buildJoinPairs as buildJoinPairs, queryUtils_ensureArray as ensureArray, queryUtils_extractFieldName as extractFieldName, queryUtils_extractIdFields as extractIdFields, queryUtils_extractModelName as extractModelName, queryUtils_fieldHasDefaultValue as fieldHasDefaultValue, queryUtils_flattenCompoundUniqueFilters as flattenCompoundUniqueFilters, queryUtils_getDelegateDescendantModels as getDelegateDescendantModels, queryUtils_getDiscriminatorField as getDiscriminatorField, queryUtils_getEnum as getEnum, queryUtils_getField as getField, queryUtils_getIdFields as getIdFields, queryUtils_getIdValues as getIdValues, queryUtils_getManyToManyRelation as getManyToManyRelation, queryUtils_getModel as getModel, queryUtils_getRelationForeignKeyFieldPairs as getRelationForeignKeyFieldPairs, queryUtils_getTypeDef as getTypeDef, queryUtils_getUniqueFields as getUniqueFields, queryUtils_hasModel as hasModel, queryUtils_isEnum as isEnum, queryUtils_isForeignKeyField as isForeignKeyField, queryUtils_isInheritedField as isInheritedField, queryUtils_isRelationField as isRelationField, queryUtils_isScalarField as isScalarField, queryUtils_makeDefaultOrderBy as makeDefaultOrderBy, queryUtils_requireField as requireField, queryUtils_requireIdFields as requireIdFields, queryUtils_requireModel as requireModel, queryUtils_stripAlias as stripAlias };
1191
1191
  }
1192
1192
 
1193
1193
  declare class DefaultOperationNodeVisitor extends OperationNodeVisitor {
package/dist/index.js CHANGED
@@ -44,7 +44,6 @@ __export(query_utils_exports, {
44
44
  requireField: () => requireField,
45
45
  requireIdFields: () => requireIdFields,
46
46
  requireModel: () => requireModel,
47
- safeJSONStringify: () => safeJSONStringify,
48
47
  stripAlias: () => stripAlias
49
48
  });
50
49
  import { invariant } from "@zenstackhq/common-helpers";
@@ -159,10 +158,11 @@ var InputValidationError = class extends ZenStackError {
159
158
  static {
160
159
  __name(this, "InputValidationError");
161
160
  }
162
- constructor(message, cause) {
161
+ model;
162
+ constructor(model, message, cause) {
163
163
  super(message, {
164
164
  cause
165
- });
165
+ }), this.model = model;
166
166
  }
167
167
  };
168
168
  var QueryError = class extends ZenStackError {
@@ -184,8 +184,9 @@ var NotFoundError = class extends ZenStackError {
184
184
  static {
185
185
  __name(this, "NotFoundError");
186
186
  }
187
+ model;
187
188
  constructor(model, details) {
188
- super(`Entity not found for model "${model}"${details ? `: ${details}` : ""}`);
189
+ super(`Entity not found for model "${model}"${details ? `: ${details}` : ""}`), this.model = model;
189
190
  }
190
191
  };
191
192
  var RejectedByPolicyReason = /* @__PURE__ */ function(RejectedByPolicyReason2) {
@@ -499,16 +500,6 @@ function ensureArray(value) {
499
500
  }
500
501
  }
501
502
  __name(ensureArray, "ensureArray");
502
- function safeJSONStringify(value) {
503
- return JSON.stringify(value, (_, v) => {
504
- if (typeof v === "bigint") {
505
- return v.toString();
506
- } else {
507
- return v;
508
- }
509
- });
510
- }
511
- __name(safeJSONStringify, "safeJSONStringify");
512
503
  function extractIdFields(entity, schema, model) {
513
504
  const idFields = requireIdFields(schema, model);
514
505
  return extractFields(entity, idFields);
@@ -1369,7 +1360,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1369
1360
  }
1370
1361
  }
1371
1362
  transformOutputBytes(value) {
1372
- return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
1363
+ return Buffer.isBuffer(value) ? Uint8Array.from(value) : typeof value === "string" && value.startsWith("\\x") ? Uint8Array.from(Buffer.from(value.slice(2), "hex")) : value;
1373
1364
  }
1374
1365
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
1375
1366
  const relationResultName = `${parentAlias}$${relationField}`;
@@ -1891,7 +1882,7 @@ var BaseOperationHandler = class {
1891
1882
  buildCountSelection(query, model, parentAlias, payload) {
1892
1883
  return query.select((eb) => this.dialect.buildCountJson(model, eb, parentAlias, payload).as("_count"));
1893
1884
  }
1894
- async create(kysely, model, data, fromRelation, creatingForDelegate = false) {
1885
+ async create(kysely, model, data, fromRelation, creatingForDelegate = false, returnFields) {
1895
1886
  const modelDef = this.requireModel(model);
1896
1887
  if (modelDef.isDelegate && !creatingForDelegate) {
1897
1888
  throw new QueryError(`Model "${this.model}" is a delegate and cannot be created directly.`);
@@ -1944,8 +1935,8 @@ var BaseOperationHandler = class {
1944
1935
  createFields = baseCreateResult.remainingFields;
1945
1936
  }
1946
1937
  const updatedData = this.fillGeneratedAndDefaultValues(modelDef, createFields);
1947
- const idFields = requireIdFields(this.schema, model);
1948
- 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({
1938
+ returnFields = returnFields ?? requireIdFields(this.schema, model);
1939
+ 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(returnFields).modifyEnd(this.makeContextComment({
1949
1940
  model,
1950
1941
  operation: "create"
1951
1942
  }));
@@ -2150,7 +2141,7 @@ var BaseOperationHandler = class {
2150
2141
  }
2151
2142
  }
2152
2143
  }
2153
- async createMany(kysely, model, input, returnData, fromRelation) {
2144
+ async createMany(kysely, model, input, returnData, fromRelation, fieldsToReturn) {
2154
2145
  if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
2155
2146
  return returnData ? [] : {
2156
2147
  count: 0
@@ -2219,8 +2210,8 @@ var BaseOperationHandler = class {
2219
2210
  count: Number(result.numAffectedRows)
2220
2211
  };
2221
2212
  } else {
2222
- const idFields = requireIdFields(this.schema, model);
2223
- const result = await query.returning(idFields).execute();
2213
+ fieldsToReturn = fieldsToReturn ?? requireIdFields(this.schema, model);
2214
+ const result = await query.returning(fieldsToReturn).execute();
2224
2215
  return result;
2225
2216
  }
2226
2217
  }
@@ -2300,7 +2291,7 @@ var BaseOperationHandler = class {
2300
2291
  return void 0;
2301
2292
  }
2302
2293
  }
2303
- async update(kysely, model, where, data, fromRelation, allowRelationUpdate = true, throwIfNotFound = true) {
2294
+ async update(kysely, model, where, data, fromRelation, allowRelationUpdate = true, throwIfNotFound = true, fieldsToReturn) {
2304
2295
  if (!data || typeof data !== "object") {
2305
2296
  throw new InternalError("data must be an object");
2306
2297
  }
@@ -2406,8 +2397,8 @@ var BaseOperationHandler = class {
2406
2397
  if (!hasFieldUpdate) {
2407
2398
  return combinedWhere;
2408
2399
  } else {
2409
- const idFields = requireIdFields(this.schema, model);
2410
- const query = kysely.updateTable(model).where(() => this.dialect.buildFilter(model, model, combinedWhere)).set(updateFields).returning(idFields).modifyEnd(this.makeContextComment({
2400
+ fieldsToReturn = fieldsToReturn ?? requireIdFields(this.schema, model);
2401
+ const query = kysely.updateTable(model).where(() => this.dialect.buildFilter(model, model, combinedWhere)).set(updateFields).returning(fieldsToReturn).modifyEnd(this.makeContextComment({
2411
2402
  model,
2412
2403
  operation: "update"
2413
2404
  }));
@@ -2499,7 +2490,7 @@ var BaseOperationHandler = class {
2499
2490
  makeContextComment(_context) {
2500
2491
  return sql4``;
2501
2492
  }
2502
- async updateMany(kysely, model, where, data, limit, returnData, filterModel) {
2493
+ async updateMany(kysely, model, where, data, limit, returnData, filterModel, fieldsToReturn) {
2503
2494
  if (typeof data !== "object") {
2504
2495
  throw new InternalError("data must be an object");
2505
2496
  }
@@ -2556,8 +2547,8 @@ var BaseOperationHandler = class {
2556
2547
  count: Number(result.numAffectedRows)
2557
2548
  };
2558
2549
  } else {
2559
- const idFields = requireIdFields(this.schema, model);
2560
- const finalQuery = query.returning(idFields);
2550
+ fieldsToReturn = fieldsToReturn ?? requireIdFields(this.schema, model);
2551
+ const finalQuery = query.returning(fieldsToReturn);
2561
2552
  const result = await this.executeQuery(kysely, finalQuery, "update");
2562
2553
  return result.rows;
2563
2554
  }
@@ -2961,7 +2952,7 @@ var BaseOperationHandler = class {
2961
2952
  });
2962
2953
  }
2963
2954
  }
2964
- if (throwForNotFound && expectedDeleteCount > deleteResult.count) {
2955
+ if (throwForNotFound && expectedDeleteCount > deleteResult.rows.length) {
2965
2956
  throw new NotFoundError(deleteFromModel);
2966
2957
  }
2967
2958
  }
@@ -2969,7 +2960,7 @@ var BaseOperationHandler = class {
2969
2960
  return enumerate(data).map((item) => flattenCompoundUniqueFilters(this.schema, model, item));
2970
2961
  }
2971
2962
  // #endregion
2972
- async delete(kysely, model, where, limit, filterModel) {
2963
+ async delete(kysely, model, where, limit, filterModel, fieldsToReturn) {
2973
2964
  filterModel ??= model;
2974
2965
  const modelDef = this.requireModel(model);
2975
2966
  if (modelDef.baseModel) {
@@ -2978,7 +2969,8 @@ var BaseOperationHandler = class {
2978
2969
  }
2979
2970
  return this.processBaseModelDelete(kysely, modelDef.baseModel, where, limit, filterModel);
2980
2971
  }
2981
- let query = kysely.deleteFrom(model);
2972
+ fieldsToReturn = fieldsToReturn ?? requireIdFields(this.schema, model);
2973
+ let query = kysely.deleteFrom(model).returning(fieldsToReturn);
2982
2974
  let needIdFilter = false;
2983
2975
  if (limit !== void 0 && !this.dialect.supportsDeleteWithLimit) {
2984
2976
  needIdFilter = true;
@@ -2998,10 +2990,7 @@ var BaseOperationHandler = class {
2998
2990
  model,
2999
2991
  operation: "delete"
3000
2992
  }));
3001
- const result = await this.executeQuery(kysely, query, "delete");
3002
- return {
3003
- count: Number(result.numAffectedRows)
3004
- };
2993
+ return this.executeQuery(kysely, query, "delete");
3005
2994
  }
3006
2995
  async processDelegateRelationDelete(kysely, modelDef, where, limit) {
3007
2996
  for (const fieldDef of Object.values(modelDef.fields)) {
@@ -3055,7 +3044,7 @@ var BaseOperationHandler = class {
3055
3044
  return callback(this.kysely);
3056
3045
  } else {
3057
3046
  let txBuilder = this.kysely.transaction();
3058
- txBuilder = txBuilder.setIsolationLevel(isolationLevel ?? TransactionIsolationLevel.RepeatableRead);
3047
+ txBuilder = txBuilder.setIsolationLevel(isolationLevel ?? TransactionIsolationLevel.ReadCommitted);
3059
3048
  return txBuilder.execute(callback);
3060
3049
  }
3061
3050
  }
@@ -3107,6 +3096,48 @@ var BaseOperationHandler = class {
3107
3096
  }
3108
3097
  return result.rows[0];
3109
3098
  }
3099
+ mutationNeedsReadBack(model, args) {
3100
+ if (this.hasPolicyEnabled) {
3101
+ return {
3102
+ needReadBack: true,
3103
+ selectedFields: void 0
3104
+ };
3105
+ }
3106
+ if (args.include && typeof args.include === "object" && Object.keys(args.include).length > 0) {
3107
+ return {
3108
+ needReadBack: true,
3109
+ selectedFields: void 0
3110
+ };
3111
+ }
3112
+ const modelDef = this.requireModel(model);
3113
+ if (modelDef.baseModel || modelDef.isDelegate) {
3114
+ return {
3115
+ needReadBack: true,
3116
+ selectedFields: void 0
3117
+ };
3118
+ }
3119
+ const allFields = Object.keys(modelDef.fields);
3120
+ const relationFields = Object.values(modelDef.fields).filter((f) => f.relation).map((f) => f.name);
3121
+ const computedFields = Object.values(modelDef.fields).filter((f) => f.computed).map((f) => f.name);
3122
+ const omit = Object.entries(args.omit ?? {}).filter(([, v]) => v).map(([k]) => k);
3123
+ const allFieldsSelected = [];
3124
+ if (!args.select || typeof args.select !== "object") {
3125
+ allFieldsSelected.push(...allFields.filter((f) => !relationFields.includes(f) && !omit.includes(f)));
3126
+ } else {
3127
+ allFieldsSelected.push(...Object.entries(args.select).filter(([k, v]) => v && !omit.includes(k)).map(([k]) => k));
3128
+ }
3129
+ if (allFieldsSelected.some((f) => relationFields.includes(f) || computedFields.includes(f))) {
3130
+ return {
3131
+ needReadBack: true,
3132
+ selectedFields: void 0
3133
+ };
3134
+ } else {
3135
+ return {
3136
+ needReadBack: false,
3137
+ selectedFields: allFieldsSelected
3138
+ };
3139
+ }
3140
+ }
3110
3141
  };
3111
3142
 
3112
3143
  // src/client/crud/operations/aggregate.ts
@@ -3267,14 +3298,19 @@ var CreateOperationHandler = class extends BaseOperationHandler {
3267
3298
  }).exhaustive();
3268
3299
  }
3269
3300
  async runCreate(args) {
3301
+ const { needReadBack, selectedFields } = this.mutationNeedsReadBack(this.model, args);
3270
3302
  const result = await this.safeTransaction(async (tx) => {
3271
- const createResult = await this.create(tx, this.model, args.data);
3272
- return this.readUnique(tx, this.model, {
3273
- select: args.select,
3274
- include: args.include,
3275
- omit: args.omit,
3276
- where: getIdValues(this.schema, this.model, createResult)
3277
- });
3303
+ const createResult = await this.create(tx, this.model, args.data, void 0, false, selectedFields);
3304
+ if (needReadBack) {
3305
+ return this.readUnique(tx, this.model, {
3306
+ select: args.select,
3307
+ include: args.include,
3308
+ omit: args.omit,
3309
+ where: getIdValues(this.schema, this.model, createResult)
3310
+ });
3311
+ } else {
3312
+ return createResult;
3313
+ }
3278
3314
  });
3279
3315
  if (!result && this.hasPolicyEnabled) {
3280
3316
  throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, `result is not allowed to be read back`);
@@ -3293,15 +3329,20 @@ var CreateOperationHandler = class extends BaseOperationHandler {
3293
3329
  if (args === void 0) {
3294
3330
  return [];
3295
3331
  }
3332
+ const { needReadBack, selectedFields } = this.mutationNeedsReadBack(this.model, args);
3296
3333
  return this.safeTransaction(async (tx) => {
3297
- const createResult = await this.createMany(tx, this.model, args, true);
3298
- return this.read(tx, this.model, {
3299
- select: args.select,
3300
- omit: args.omit,
3301
- where: {
3302
- OR: createResult.map((item) => getIdValues(this.schema, this.model, item))
3303
- }
3304
- });
3334
+ const createResult = await this.createMany(tx, this.model, args, true, void 0, selectedFields);
3335
+ if (needReadBack) {
3336
+ return this.read(tx, this.model, {
3337
+ select: args.select,
3338
+ omit: args.omit,
3339
+ where: {
3340
+ OR: createResult.map((item) => getIdValues(this.schema, this.model, item))
3341
+ }
3342
+ });
3343
+ } else {
3344
+ return createResult;
3345
+ }
3305
3346
  });
3306
3347
  }
3307
3348
  };
@@ -3317,27 +3358,34 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
3317
3358
  return match9(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, normalizedArgs))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, normalizedArgs))).exhaustive();
3318
3359
  }
3319
3360
  async runDelete(args) {
3320
- const existing = await this.readUnique(this.kysely, this.model, {
3321
- select: args.select,
3322
- include: args.include,
3323
- omit: args.omit,
3324
- where: args.where
3325
- });
3326
- await this.safeTransaction(async (tx) => {
3327
- const result = await this.delete(tx, this.model, args.where);
3328
- if (result.count === 0) {
3361
+ const { needReadBack, selectedFields } = this.mutationNeedsReadBack(this.model, args);
3362
+ const result = await this.safeTransaction(async (tx) => {
3363
+ let preDeleteRead = void 0;
3364
+ if (needReadBack) {
3365
+ preDeleteRead = await this.readUnique(tx, this.model, {
3366
+ select: args.select,
3367
+ include: args.include,
3368
+ omit: args.omit,
3369
+ where: args.where
3370
+ });
3371
+ }
3372
+ const deleteResult = await this.delete(tx, this.model, args.where, void 0, void 0, selectedFields);
3373
+ if (deleteResult.rows.length === 0) {
3329
3374
  throw new NotFoundError(this.model);
3330
3375
  }
3376
+ return needReadBack ? preDeleteRead : deleteResult.rows[0];
3331
3377
  });
3332
- if (!existing && this.hasPolicyEnabled) {
3378
+ if (!result && this.hasPolicyEnabled) {
3333
3379
  throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
3334
3380
  }
3335
- return existing;
3381
+ return result;
3336
3382
  }
3337
3383
  async runDeleteMany(args) {
3338
3384
  return await this.safeTransaction(async (tx) => {
3339
3385
  const result = await this.delete(tx, this.model, args?.where, args?.limit);
3340
- return result;
3386
+ return {
3387
+ count: result.rows.length
3388
+ };
3341
3389
  });
3342
3390
  }
3343
3391
  };
@@ -3478,29 +3526,31 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3478
3526
  return match11(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();
3479
3527
  }
3480
3528
  async runUpdate(args) {
3481
- const readBackResult = await this.safeTransaction(async (tx) => {
3482
- const updateResult = await this.update(tx, this.model, args.where, args.data);
3483
- const readFilter = updateResult ?? args.where;
3484
- let readBackResult2 = void 0;
3485
- try {
3486
- readBackResult2 = await this.readUnique(tx, this.model, {
3529
+ const { needReadBack, selectedFields } = this.needReadBack(args);
3530
+ const result = await this.safeTransaction(async (tx) => {
3531
+ const updateResult = await this.update(tx, this.model, args.where, args.data, void 0, void 0, void 0, selectedFields);
3532
+ if (needReadBack) {
3533
+ const readFilter = updateResult ?? args.where;
3534
+ let readBackResult = void 0;
3535
+ readBackResult = await this.readUnique(tx, this.model, {
3487
3536
  select: args.select,
3488
3537
  include: args.include,
3489
3538
  omit: args.omit,
3490
3539
  where: readFilter
3491
3540
  });
3492
- } catch {
3541
+ return readBackResult;
3542
+ } else {
3543
+ return updateResult;
3493
3544
  }
3494
- return readBackResult2;
3495
3545
  });
3496
- if (!readBackResult) {
3546
+ if (!result) {
3497
3547
  if (this.hasPolicyEnabled) {
3498
3548
  throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
3499
3549
  } else {
3500
3550
  return null;
3501
3551
  }
3502
3552
  } else {
3503
- return readBackResult;
3553
+ return result;
3504
3554
  }
3505
3555
  }
3506
3556
  async runUpdateMany(args) {
@@ -3512,19 +3562,27 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3512
3562
  if (!args) {
3513
3563
  return [];
3514
3564
  }
3565
+ const { needReadBack, selectedFields } = this.needReadBack(args);
3515
3566
  const { readBackResult, updateResult } = await this.safeTransaction(async (tx) => {
3516
- const updateResult2 = await this.updateMany(tx, this.model, args.where, args.data, args.limit, true);
3517
- const readBackResult2 = await this.read(tx, this.model, {
3518
- select: args.select,
3519
- omit: args.omit,
3520
- where: {
3521
- OR: updateResult2.map((item) => getIdValues(this.schema, this.model, item))
3522
- }
3523
- });
3524
- return {
3525
- readBackResult: readBackResult2,
3526
- updateResult: updateResult2
3527
- };
3567
+ const updateResult2 = await this.updateMany(tx, this.model, args.where, args.data, args.limit, true, void 0, selectedFields);
3568
+ if (needReadBack) {
3569
+ const readBackResult2 = await this.read(tx, this.model, {
3570
+ select: args.select,
3571
+ omit: args.omit,
3572
+ where: {
3573
+ OR: updateResult2.map((item) => getIdValues(this.schema, this.model, item))
3574
+ }
3575
+ });
3576
+ return {
3577
+ readBackResult: readBackResult2,
3578
+ updateResult: updateResult2
3579
+ };
3580
+ } else {
3581
+ return {
3582
+ readBackResult: updateResult2,
3583
+ updateResult: updateResult2
3584
+ };
3585
+ }
3528
3586
  });
3529
3587
  if (readBackResult.length < updateResult.length && this.hasPolicyEnabled) {
3530
3588
  throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
@@ -3532,23 +3590,49 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3532
3590
  return readBackResult;
3533
3591
  }
3534
3592
  async runUpsert(args) {
3593
+ const { needReadBack, selectedFields } = this.needReadBack(args);
3535
3594
  const result = await this.safeTransaction(async (tx) => {
3536
- let mutationResult = await this.update(tx, this.model, args.where, args.update, void 0, true, false);
3595
+ let mutationResult = await this.update(tx, this.model, args.where, args.update, void 0, true, false, selectedFields);
3537
3596
  if (!mutationResult) {
3538
- mutationResult = await this.create(tx, this.model, args.create);
3597
+ mutationResult = await this.create(tx, this.model, args.create, void 0, void 0, selectedFields);
3598
+ }
3599
+ if (needReadBack) {
3600
+ return this.readUnique(tx, this.model, {
3601
+ select: args.select,
3602
+ include: args.include,
3603
+ omit: args.omit,
3604
+ where: getIdValues(this.schema, this.model, mutationResult)
3605
+ });
3606
+ } else {
3607
+ return mutationResult;
3539
3608
  }
3540
- return this.readUnique(tx, this.model, {
3541
- select: args.select,
3542
- include: args.include,
3543
- omit: args.omit,
3544
- where: getIdValues(this.schema, this.model, mutationResult)
3545
- });
3546
3609
  });
3547
3610
  if (!result && this.hasPolicyEnabled) {
3548
3611
  throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
3549
3612
  }
3550
3613
  return result;
3551
3614
  }
3615
+ needReadBack(args) {
3616
+ const baseResult = this.mutationNeedsReadBack(this.model, args);
3617
+ if (baseResult.needReadBack) {
3618
+ return baseResult;
3619
+ }
3620
+ const modelDef = this.requireModel(this.model);
3621
+ const nonRelationFields = Object.entries(modelDef.fields).filter(([_, def]) => !def.relation).map(([name, _]) => name);
3622
+ if (args.data && !Object.keys(args.data).some((field) => nonRelationFields.includes(field))) {
3623
+ return {
3624
+ needReadBack: true,
3625
+ selectedFields: void 0
3626
+ };
3627
+ }
3628
+ if (args.update && !Object.keys(args.update).some((field) => nonRelationFields.includes(field))) {
3629
+ return {
3630
+ needReadBack: true,
3631
+ selectedFields: void 0
3632
+ };
3633
+ }
3634
+ return baseResult;
3635
+ }
3552
3636
  };
3553
3637
 
3554
3638
  // src/client/crud/validator/index.ts
@@ -3998,7 +4082,7 @@ var InputValidator = class {
3998
4082
  }
3999
4083
  const { error, data } = schema.safeParse(args);
4000
4084
  if (error) {
4001
- throw new InputValidationError(`Invalid ${operation} args for model "${model}": ${formatError(error)}`, error);
4085
+ throw new InputValidationError(model, `Invalid ${operation} args for model "${model}": ${formatError(error)}`, error);
4002
4086
  }
4003
4087
  return data;
4004
4088
  }
@@ -5552,7 +5636,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5552
5636
  try {
5553
5637
  if (this.isMutationNode(compiledQuery.query) && !this.driver.isTransactionConnection(connection)) {
5554
5638
  await this.driver.beginTransaction(connection, {
5555
- isolationLevel: TransactionIsolationLevel.RepeatableRead
5639
+ isolationLevel: TransactionIsolationLevel.ReadCommitted
5556
5640
  });
5557
5641
  startedTx = true;
5558
5642
  }
@@ -6153,9 +6237,15 @@ var SchemaDbPusher = class {
6153
6237
  table = table.addForeignKeyConstraint(`fk_${model}_${fieldName}`, fieldDef.relation.fields.map((f) => this.getColumnName(modelDef.fields[f])), this.getTableName(relationModelDef), fieldDef.relation.references.map((f) => this.getColumnName(relationModelDef.fields[f])), (cb) => {
6154
6238
  if (fieldDef.relation?.onDelete) {
6155
6239
  cb = cb.onDelete(this.mapCascadeAction(fieldDef.relation.onDelete));
6240
+ } else if (fieldDef.optional) {
6241
+ cb = cb.onDelete("set null");
6242
+ } else {
6243
+ cb = cb.onDelete("restrict");
6156
6244
  }
6157
6245
  if (fieldDef.relation?.onUpdate) {
6158
6246
  cb = cb.onUpdate(this.mapCascadeAction(fieldDef.relation.onUpdate));
6247
+ } else {
6248
+ cb = cb.onUpdate("cascade");
6159
6249
  }
6160
6250
  return cb;
6161
6251
  });