@zenstackhq/runtime 3.0.0-beta.10 → 3.0.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -62,7 +62,6 @@ var import_ts_pattern7 = require("ts-pattern");
62
62
  var query_utils_exports = {};
63
63
  __export(query_utils_exports, {
64
64
  aggregate: () => aggregate,
65
- buildFieldRef: () => buildFieldRef,
66
65
  buildJoinPairs: () => buildJoinPairs,
67
66
  ensureArray: () => ensureArray,
68
67
  extractFieldName: () => extractFieldName,
@@ -408,28 +407,6 @@ function getIdValues(schema, model, data) {
408
407
  }), {});
409
408
  }
410
409
  __name(getIdValues, "getIdValues");
411
- function buildFieldRef(schema, model, field, options, eb, modelAlias, inlineComputedField = true) {
412
- const fieldDef = requireField(schema, model, field);
413
- if (!fieldDef.computed) {
414
- return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
415
- } else {
416
- if (!inlineComputedField) {
417
- return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
418
- }
419
- let computer;
420
- if ("computedFields" in options) {
421
- const computedFields = options.computedFields;
422
- computer = computedFields?.[model]?.[field];
423
- }
424
- if (!computer) {
425
- throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
426
- }
427
- return computer(eb, {
428
- modelAlias
429
- });
430
- }
431
- }
432
- __name(buildFieldRef, "buildFieldRef");
433
410
  function fieldHasDefaultValue(fieldDef) {
434
411
  return fieldDef.default !== void 0 || fieldDef.updatedAt;
435
412
  }
@@ -781,7 +758,7 @@ var BaseCrudDialect = class {
781
758
  take = -take;
782
759
  }
783
760
  result = this.buildSkipTake(result, skip, take);
784
- result = this.buildOrderBy(result, model, modelAlias, args.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
761
+ result = this.buildOrderBy(result, model, modelAlias, args.orderBy, negateOrderBy);
785
762
  if ("distinct" in args && args.distinct) {
786
763
  const distinct = ensureArray(args.distinct);
787
764
  if (this.supportsDistinctOn) {
@@ -1140,16 +1117,12 @@ var BaseCrudDialect = class {
1140
1117
  ]);
1141
1118
  return this.and(...conditions.conditions);
1142
1119
  }
1143
- buildOrderBy(query, model, modelAlias, orderBy, useDefaultIfEmpty, negated) {
1120
+ buildOrderBy(query, model, modelAlias, orderBy, negated) {
1144
1121
  if (!orderBy) {
1145
- if (useDefaultIfEmpty) {
1146
- orderBy = makeDefaultOrderBy(this.schema, model);
1147
- } else {
1148
- return query;
1149
- }
1122
+ return query;
1150
1123
  }
1151
1124
  let result = query;
1152
- const buildFieldRef2 = /* @__PURE__ */ __name((model2, field, modelAlias2) => {
1125
+ const buildFieldRef = /* @__PURE__ */ __name((model2, field, modelAlias2) => {
1153
1126
  const fieldDef = requireField(this.schema, model2, field);
1154
1127
  return fieldDef.originModel ? this.fieldRef(fieldDef.originModel, field, fieldDef.originModel) : this.fieldRef(model2, field, modelAlias2);
1155
1128
  }, "buildFieldRef");
@@ -1168,7 +1141,7 @@ var BaseCrudDialect = class {
1168
1141
  (0, import_common_helpers3.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
1169
1142
  for (const [k, v] of Object.entries(value)) {
1170
1143
  (0, import_common_helpers3.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
1171
- result = result.orderBy((eb) => aggregate(eb, buildFieldRef2(model, k, modelAlias), field), import_kysely2.sql.raw(this.negateSort(v, negated)));
1144
+ result = result.orderBy((eb) => aggregate(eb, buildFieldRef(model, k, modelAlias), field), import_kysely2.sql.raw(this.negateSort(v, negated)));
1172
1145
  }
1173
1146
  continue;
1174
1147
  }
@@ -1177,7 +1150,7 @@ var BaseCrudDialect = class {
1177
1150
  (0, import_common_helpers3.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
1178
1151
  for (const [k, v] of Object.entries(value)) {
1179
1152
  (0, import_common_helpers3.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
1180
- result = result.orderBy((eb) => eb.fn.count(buildFieldRef2(model, k, modelAlias)), import_kysely2.sql.raw(this.negateSort(v, negated)));
1153
+ result = result.orderBy((eb) => eb.fn.count(buildFieldRef(model, k, modelAlias)), import_kysely2.sql.raw(this.negateSort(v, negated)));
1181
1154
  }
1182
1155
  continue;
1183
1156
  }
@@ -1186,7 +1159,7 @@ var BaseCrudDialect = class {
1186
1159
  }
1187
1160
  const fieldDef = requireField(this.schema, model, field);
1188
1161
  if (!fieldDef.relation) {
1189
- const fieldRef = buildFieldRef2(model, field, modelAlias);
1162
+ const fieldRef = buildFieldRef(model, field, modelAlias);
1190
1163
  if (value === "asc" || value === "desc") {
1191
1164
  result = result.orderBy(fieldRef, this.negateSort(value, negated));
1192
1165
  } else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
@@ -1215,7 +1188,7 @@ var BaseCrudDialect = class {
1215
1188
  const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
1216
1189
  return join.on((eb) => this.and(...joinPairs.map(([left, right]) => eb(this.eb.ref(left), "=", this.eb.ref(right)))));
1217
1190
  });
1218
- result = this.buildOrderBy(result, fieldDef.type, relationModel, value, false, negated);
1191
+ result = this.buildOrderBy(result, fieldDef.type, relationModel, value, negated);
1219
1192
  }
1220
1193
  }
1221
1194
  }
@@ -1262,13 +1235,9 @@ var BaseCrudDialect = class {
1262
1235
  }
1263
1236
  buildSelectField(query, model, modelAlias, field) {
1264
1237
  const fieldDef = requireField(this.schema, model, field);
1265
- if (fieldDef.computed) {
1266
- return query.select(() => this.fieldRef(model, field, modelAlias).as(field));
1267
- } else if (!fieldDef.originModel) {
1268
- return query.select(this.eb.ref(`${modelAlias}.${field}`).as(field));
1269
- } else {
1270
- return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
1271
- }
1238
+ const fieldModel = fieldDef.originModel ?? model;
1239
+ const alias = fieldDef.originModel ?? modelAlias;
1240
+ return query.select(() => this.fieldRef(fieldModel, field, alias).as(field));
1272
1241
  }
1273
1242
  buildDelegateJoin(thisModel, thisModelAlias, otherModelAlias, query) {
1274
1243
  const idFields = requireIdFields(this.schema, thisModel);
@@ -1357,7 +1326,25 @@ var BaseCrudDialect = class {
1357
1326
  return this.eb.not(this.and(...args));
1358
1327
  }
1359
1328
  fieldRef(model, field, modelAlias, inlineComputedField = true) {
1360
- return buildFieldRef(this.schema, model, field, this.options, this.eb, modelAlias, inlineComputedField);
1329
+ const fieldDef = requireField(this.schema, model, field);
1330
+ if (!fieldDef.computed) {
1331
+ return this.eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
1332
+ } else {
1333
+ if (!inlineComputedField) {
1334
+ return this.eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
1335
+ }
1336
+ let computer;
1337
+ if ("computedFields" in this.options) {
1338
+ const computedFields = this.options.computedFields;
1339
+ computer = computedFields?.[fieldDef.originModel ?? model]?.[field];
1340
+ }
1341
+ if (!computer) {
1342
+ throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
1343
+ }
1344
+ return computer(this.eb, {
1345
+ modelAlias
1346
+ });
1347
+ }
1361
1348
  }
1362
1349
  canJoinWithoutNestedSelect(modelDef, payload) {
1363
1350
  if (modelDef.computedFields) {
@@ -1950,7 +1937,7 @@ var BaseOperationHandler = class {
1950
1937
  buildCountSelection(query, model, parentAlias, payload) {
1951
1938
  return query.select((eb) => this.dialect.buildCountJson(model, eb, parentAlias, payload).as("_count"));
1952
1939
  }
1953
- async create(kysely, model, data, fromRelation, creatingForDelegate = false) {
1940
+ async create(kysely, model, data, fromRelation, creatingForDelegate = false, returnFields) {
1954
1941
  const modelDef = this.requireModel(model);
1955
1942
  if (modelDef.isDelegate && !creatingForDelegate) {
1956
1943
  throw new QueryError(`Model "${this.model}" is a delegate and cannot be created directly.`);
@@ -2003,8 +1990,8 @@ var BaseOperationHandler = class {
2003
1990
  createFields = baseCreateResult.remainingFields;
2004
1991
  }
2005
1992
  const updatedData = this.fillGeneratedAndDefaultValues(modelDef, createFields);
2006
- const idFields = requireIdFields(this.schema, model);
2007
- 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({
1993
+ returnFields = returnFields ?? requireIdFields(this.schema, model);
1994
+ 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({
2008
1995
  model,
2009
1996
  operation: "create"
2010
1997
  }));
@@ -2209,7 +2196,7 @@ var BaseOperationHandler = class {
2209
2196
  }
2210
2197
  }
2211
2198
  }
2212
- async createMany(kysely, model, input, returnData, fromRelation) {
2199
+ async createMany(kysely, model, input, returnData, fromRelation, fieldsToReturn) {
2213
2200
  if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
2214
2201
  return returnData ? [] : {
2215
2202
  count: 0
@@ -2278,8 +2265,8 @@ var BaseOperationHandler = class {
2278
2265
  count: Number(result.numAffectedRows)
2279
2266
  };
2280
2267
  } else {
2281
- const idFields = requireIdFields(this.schema, model);
2282
- const result = await query.returning(idFields).execute();
2268
+ fieldsToReturn = fieldsToReturn ?? requireIdFields(this.schema, model);
2269
+ const result = await query.returning(fieldsToReturn).execute();
2283
2270
  return result;
2284
2271
  }
2285
2272
  }
@@ -2359,7 +2346,7 @@ var BaseOperationHandler = class {
2359
2346
  return void 0;
2360
2347
  }
2361
2348
  }
2362
- async update(kysely, model, where, data, fromRelation, allowRelationUpdate = true, throwIfNotFound = true) {
2349
+ async update(kysely, model, where, data, fromRelation, allowRelationUpdate = true, throwIfNotFound = true, fieldsToReturn) {
2363
2350
  if (!data || typeof data !== "object") {
2364
2351
  throw new InternalError("data must be an object");
2365
2352
  }
@@ -2465,8 +2452,8 @@ var BaseOperationHandler = class {
2465
2452
  if (!hasFieldUpdate) {
2466
2453
  return combinedWhere;
2467
2454
  } else {
2468
- const idFields = requireIdFields(this.schema, model);
2469
- const query = kysely.updateTable(model).where(() => this.dialect.buildFilter(model, model, combinedWhere)).set(updateFields).returning(idFields).modifyEnd(this.makeContextComment({
2455
+ fieldsToReturn = fieldsToReturn ?? requireIdFields(this.schema, model);
2456
+ const query = kysely.updateTable(model).where(() => this.dialect.buildFilter(model, model, combinedWhere)).set(updateFields).returning(fieldsToReturn).modifyEnd(this.makeContextComment({
2470
2457
  model,
2471
2458
  operation: "update"
2472
2459
  }));
@@ -2558,7 +2545,7 @@ var BaseOperationHandler = class {
2558
2545
  makeContextComment(_context) {
2559
2546
  return import_kysely5.sql``;
2560
2547
  }
2561
- async updateMany(kysely, model, where, data, limit, returnData, filterModel) {
2548
+ async updateMany(kysely, model, where, data, limit, returnData, filterModel, fieldsToReturn) {
2562
2549
  if (typeof data !== "object") {
2563
2550
  throw new InternalError("data must be an object");
2564
2551
  }
@@ -2615,8 +2602,8 @@ var BaseOperationHandler = class {
2615
2602
  count: Number(result.numAffectedRows)
2616
2603
  };
2617
2604
  } else {
2618
- const idFields = requireIdFields(this.schema, model);
2619
- const finalQuery = query.returning(idFields);
2605
+ fieldsToReturn = fieldsToReturn ?? requireIdFields(this.schema, model);
2606
+ const finalQuery = query.returning(fieldsToReturn);
2620
2607
  const result = await this.executeQuery(kysely, finalQuery, "update");
2621
2608
  return result.rows;
2622
2609
  }
@@ -3020,7 +3007,7 @@ var BaseOperationHandler = class {
3020
3007
  });
3021
3008
  }
3022
3009
  }
3023
- if (throwForNotFound && expectedDeleteCount > deleteResult.count) {
3010
+ if (throwForNotFound && expectedDeleteCount > deleteResult.rows.length) {
3024
3011
  throw new NotFoundError(deleteFromModel);
3025
3012
  }
3026
3013
  }
@@ -3028,7 +3015,7 @@ var BaseOperationHandler = class {
3028
3015
  return enumerate(data).map((item) => flattenCompoundUniqueFilters(this.schema, model, item));
3029
3016
  }
3030
3017
  // #endregion
3031
- async delete(kysely, model, where, limit, filterModel) {
3018
+ async delete(kysely, model, where, limit, filterModel, fieldsToReturn) {
3032
3019
  filterModel ??= model;
3033
3020
  const modelDef = this.requireModel(model);
3034
3021
  if (modelDef.baseModel) {
@@ -3037,7 +3024,8 @@ var BaseOperationHandler = class {
3037
3024
  }
3038
3025
  return this.processBaseModelDelete(kysely, modelDef.baseModel, where, limit, filterModel);
3039
3026
  }
3040
- let query = kysely.deleteFrom(model);
3027
+ fieldsToReturn = fieldsToReturn ?? requireIdFields(this.schema, model);
3028
+ let query = kysely.deleteFrom(model).returning(fieldsToReturn);
3041
3029
  let needIdFilter = false;
3042
3030
  if (limit !== void 0 && !this.dialect.supportsDeleteWithLimit) {
3043
3031
  needIdFilter = true;
@@ -3057,10 +3045,7 @@ var BaseOperationHandler = class {
3057
3045
  model,
3058
3046
  operation: "delete"
3059
3047
  }));
3060
- const result = await this.executeQuery(kysely, query, "delete");
3061
- return {
3062
- count: Number(result.numAffectedRows)
3063
- };
3048
+ return this.executeQuery(kysely, query, "delete");
3064
3049
  }
3065
3050
  async processDelegateRelationDelete(kysely, modelDef, where, limit) {
3066
3051
  for (const fieldDef of Object.values(modelDef.fields)) {
@@ -3114,7 +3099,7 @@ var BaseOperationHandler = class {
3114
3099
  return callback(this.kysely);
3115
3100
  } else {
3116
3101
  let txBuilder = this.kysely.transaction();
3117
- txBuilder = txBuilder.setIsolationLevel(isolationLevel ?? TransactionIsolationLevel.RepeatableRead);
3102
+ txBuilder = txBuilder.setIsolationLevel(isolationLevel ?? TransactionIsolationLevel.ReadCommitted);
3118
3103
  return txBuilder.execute(callback);
3119
3104
  }
3120
3105
  }
@@ -3166,6 +3151,48 @@ var BaseOperationHandler = class {
3166
3151
  }
3167
3152
  return result.rows[0];
3168
3153
  }
3154
+ mutationNeedsReadBack(model, args) {
3155
+ if (this.hasPolicyEnabled) {
3156
+ return {
3157
+ needReadBack: true,
3158
+ selectedFields: void 0
3159
+ };
3160
+ }
3161
+ if (args.include && typeof args.include === "object" && Object.keys(args.include).length > 0) {
3162
+ return {
3163
+ needReadBack: true,
3164
+ selectedFields: void 0
3165
+ };
3166
+ }
3167
+ const modelDef = this.requireModel(model);
3168
+ if (modelDef.baseModel || modelDef.isDelegate) {
3169
+ return {
3170
+ needReadBack: true,
3171
+ selectedFields: void 0
3172
+ };
3173
+ }
3174
+ const allFields = Object.keys(modelDef.fields);
3175
+ const relationFields = Object.values(modelDef.fields).filter((f) => f.relation).map((f) => f.name);
3176
+ const computedFields = Object.values(modelDef.fields).filter((f) => f.computed).map((f) => f.name);
3177
+ const omit = Object.entries(args.omit ?? {}).filter(([, v]) => v).map(([k]) => k);
3178
+ const allFieldsSelected = [];
3179
+ if (!args.select || typeof args.select !== "object") {
3180
+ allFieldsSelected.push(...allFields.filter((f) => !relationFields.includes(f) && !omit.includes(f)));
3181
+ } else {
3182
+ allFieldsSelected.push(...Object.entries(args.select).filter(([k, v]) => v && !omit.includes(k)).map(([k]) => k));
3183
+ }
3184
+ if (allFieldsSelected.some((f) => relationFields.includes(f) || computedFields.includes(f))) {
3185
+ return {
3186
+ needReadBack: true,
3187
+ selectedFields: void 0
3188
+ };
3189
+ } else {
3190
+ return {
3191
+ needReadBack: false,
3192
+ selectedFields: allFieldsSelected
3193
+ };
3194
+ }
3195
+ }
3169
3196
  };
3170
3197
 
3171
3198
  // src/client/crud/operations/aggregate.ts
@@ -3201,7 +3228,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3201
3228
  take = -take;
3202
3229
  }
3203
3230
  subQuery = this.dialect.buildSkipTake(subQuery, skip, take);
3204
- subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, parsedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
3231
+ subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, parsedArgs.orderBy, negateOrderBy);
3205
3232
  return subQuery.as("$sub");
3206
3233
  });
3207
3234
  for (const [key, value] of Object.entries(parsedArgs)) {
@@ -3326,14 +3353,19 @@ var CreateOperationHandler = class extends BaseOperationHandler {
3326
3353
  }).exhaustive();
3327
3354
  }
3328
3355
  async runCreate(args) {
3356
+ const { needReadBack, selectedFields } = this.mutationNeedsReadBack(this.model, args);
3329
3357
  const result = await this.safeTransaction(async (tx) => {
3330
- const createResult = await this.create(tx, this.model, args.data);
3331
- return this.readUnique(tx, this.model, {
3332
- select: args.select,
3333
- include: args.include,
3334
- omit: args.omit,
3335
- where: getIdValues(this.schema, this.model, createResult)
3336
- });
3358
+ const createResult = await this.create(tx, this.model, args.data, void 0, false, selectedFields);
3359
+ if (needReadBack) {
3360
+ return this.readUnique(tx, this.model, {
3361
+ select: args.select,
3362
+ include: args.include,
3363
+ omit: args.omit,
3364
+ where: getIdValues(this.schema, this.model, createResult)
3365
+ });
3366
+ } else {
3367
+ return createResult;
3368
+ }
3337
3369
  });
3338
3370
  if (!result && this.hasPolicyEnabled) {
3339
3371
  throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, `result is not allowed to be read back`);
@@ -3352,15 +3384,20 @@ var CreateOperationHandler = class extends BaseOperationHandler {
3352
3384
  if (args === void 0) {
3353
3385
  return [];
3354
3386
  }
3387
+ const { needReadBack, selectedFields } = this.mutationNeedsReadBack(this.model, args);
3355
3388
  return this.safeTransaction(async (tx) => {
3356
- const createResult = await this.createMany(tx, this.model, args, true);
3357
- return this.read(tx, this.model, {
3358
- select: args.select,
3359
- omit: args.omit,
3360
- where: {
3361
- OR: createResult.map((item) => getIdValues(this.schema, this.model, item))
3362
- }
3363
- });
3389
+ const createResult = await this.createMany(tx, this.model, args, true, void 0, selectedFields);
3390
+ if (needReadBack) {
3391
+ return this.read(tx, this.model, {
3392
+ select: args.select,
3393
+ omit: args.omit,
3394
+ where: {
3395
+ OR: createResult.map((item) => getIdValues(this.schema, this.model, item))
3396
+ }
3397
+ });
3398
+ } else {
3399
+ return createResult;
3400
+ }
3364
3401
  });
3365
3402
  }
3366
3403
  };
@@ -3376,27 +3413,34 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
3376
3413
  return (0, import_ts_pattern9.match)(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, normalizedArgs))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, normalizedArgs))).exhaustive();
3377
3414
  }
3378
3415
  async runDelete(args) {
3379
- const existing = await this.readUnique(this.kysely, this.model, {
3380
- select: args.select,
3381
- include: args.include,
3382
- omit: args.omit,
3383
- where: args.where
3384
- });
3385
- await this.safeTransaction(async (tx) => {
3386
- const result = await this.delete(tx, this.model, args.where);
3387
- if (result.count === 0) {
3416
+ const { needReadBack, selectedFields } = this.mutationNeedsReadBack(this.model, args);
3417
+ const result = await this.safeTransaction(async (tx) => {
3418
+ let preDeleteRead = void 0;
3419
+ if (needReadBack) {
3420
+ preDeleteRead = await this.readUnique(tx, this.model, {
3421
+ select: args.select,
3422
+ include: args.include,
3423
+ omit: args.omit,
3424
+ where: args.where
3425
+ });
3426
+ }
3427
+ const deleteResult = await this.delete(tx, this.model, args.where, void 0, void 0, selectedFields);
3428
+ if (deleteResult.rows.length === 0) {
3388
3429
  throw new NotFoundError(this.model);
3389
3430
  }
3431
+ return needReadBack ? preDeleteRead : deleteResult.rows[0];
3390
3432
  });
3391
- if (!existing && this.hasPolicyEnabled) {
3433
+ if (!result && this.hasPolicyEnabled) {
3392
3434
  throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
3393
3435
  }
3394
- return existing;
3436
+ return result;
3395
3437
  }
3396
3438
  async runDeleteMany(args) {
3397
3439
  return await this.safeTransaction(async (tx) => {
3398
3440
  const result = await this.delete(tx, this.model, args?.where, args?.limit);
3399
- return result;
3441
+ return {
3442
+ count: result.rows.length
3443
+ };
3400
3444
  });
3401
3445
  }
3402
3446
  };
@@ -3432,29 +3476,23 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
3432
3476
  async handle(_operation, args) {
3433
3477
  const normalizedArgs = this.normalizeArgs(args);
3434
3478
  const parsedArgs = this.inputValidator.validateGroupByArgs(this.model, normalizedArgs);
3435
- let query = this.kysely.selectFrom((eb) => {
3436
- let subQuery = eb.selectFrom(this.model).selectAll().where(() => this.dialect.buildFilter(this.model, this.model, parsedArgs?.where));
3437
- const skip = parsedArgs?.skip;
3438
- let take = parsedArgs?.take;
3439
- let negateOrderBy = false;
3440
- if (take !== void 0 && take < 0) {
3441
- negateOrderBy = true;
3442
- take = -take;
3443
- }
3444
- subQuery = this.dialect.buildSkipTake(subQuery, skip, take);
3445
- subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
3446
- return subQuery.as("$sub");
3447
- });
3448
- const fieldRef = /* @__PURE__ */ __name((field) => this.dialect.fieldRef(this.model, field, "$sub"), "fieldRef");
3479
+ let query = this.kysely.selectFrom(this.model).where(() => this.dialect.buildFilter(this.model, this.model, parsedArgs?.where));
3480
+ const fieldRef = /* @__PURE__ */ __name((field) => this.dialect.fieldRef(this.model, field), "fieldRef");
3449
3481
  const bys = typeof parsedArgs.by === "string" ? [
3450
3482
  parsedArgs.by
3451
3483
  ] : parsedArgs.by;
3452
3484
  query = query.groupBy(bys.map((by) => fieldRef(by)));
3453
- if (parsedArgs.orderBy) {
3454
- query = this.dialect.buildOrderBy(query, this.model, "$sub", parsedArgs.orderBy, false, false);
3485
+ const skip = parsedArgs?.skip;
3486
+ let take = parsedArgs?.take;
3487
+ let negateOrderBy = false;
3488
+ if (take !== void 0 && take < 0) {
3489
+ negateOrderBy = true;
3490
+ take = -take;
3455
3491
  }
3492
+ query = this.dialect.buildSkipTake(query, skip, take);
3493
+ query = this.dialect.buildOrderBy(query, this.model, this.model, parsedArgs.orderBy, negateOrderBy);
3456
3494
  if (parsedArgs.having) {
3457
- query = query.having(() => this.dialect.buildFilter(this.model, "$sub", parsedArgs.having));
3495
+ query = query.having(() => this.dialect.buildFilter(this.model, this.model, parsedArgs.having));
3458
3496
  }
3459
3497
  for (const by of bys) {
3460
3498
  query = query.select(() => fieldRef(by).as(by));
@@ -3543,29 +3581,31 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3543
3581
  return (0, import_ts_pattern11.match)(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();
3544
3582
  }
3545
3583
  async runUpdate(args) {
3546
- const readBackResult = await this.safeTransaction(async (tx) => {
3547
- const updateResult = await this.update(tx, this.model, args.where, args.data);
3548
- const readFilter = updateResult ?? args.where;
3549
- let readBackResult2 = void 0;
3550
- try {
3551
- readBackResult2 = await this.readUnique(tx, this.model, {
3584
+ const { needReadBack, selectedFields } = this.needReadBack(args);
3585
+ const result = await this.safeTransaction(async (tx) => {
3586
+ const updateResult = await this.update(tx, this.model, args.where, args.data, void 0, void 0, void 0, selectedFields);
3587
+ if (needReadBack) {
3588
+ const readFilter = updateResult ?? args.where;
3589
+ let readBackResult = void 0;
3590
+ readBackResult = await this.readUnique(tx, this.model, {
3552
3591
  select: args.select,
3553
3592
  include: args.include,
3554
3593
  omit: args.omit,
3555
3594
  where: readFilter
3556
3595
  });
3557
- } catch {
3596
+ return readBackResult;
3597
+ } else {
3598
+ return updateResult;
3558
3599
  }
3559
- return readBackResult2;
3560
3600
  });
3561
- if (!readBackResult) {
3601
+ if (!result) {
3562
3602
  if (this.hasPolicyEnabled) {
3563
3603
  throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
3564
3604
  } else {
3565
3605
  return null;
3566
3606
  }
3567
3607
  } else {
3568
- return readBackResult;
3608
+ return result;
3569
3609
  }
3570
3610
  }
3571
3611
  async runUpdateMany(args) {
@@ -3577,19 +3617,27 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3577
3617
  if (!args) {
3578
3618
  return [];
3579
3619
  }
3620
+ const { needReadBack, selectedFields } = this.needReadBack(args);
3580
3621
  const { readBackResult, updateResult } = await this.safeTransaction(async (tx) => {
3581
- const updateResult2 = await this.updateMany(tx, this.model, args.where, args.data, args.limit, true);
3582
- const readBackResult2 = await this.read(tx, this.model, {
3583
- select: args.select,
3584
- omit: args.omit,
3585
- where: {
3586
- OR: updateResult2.map((item) => getIdValues(this.schema, this.model, item))
3587
- }
3588
- });
3589
- return {
3590
- readBackResult: readBackResult2,
3591
- updateResult: updateResult2
3592
- };
3622
+ const updateResult2 = await this.updateMany(tx, this.model, args.where, args.data, args.limit, true, void 0, selectedFields);
3623
+ if (needReadBack) {
3624
+ const readBackResult2 = await this.read(tx, this.model, {
3625
+ select: args.select,
3626
+ omit: args.omit,
3627
+ where: {
3628
+ OR: updateResult2.map((item) => getIdValues(this.schema, this.model, item))
3629
+ }
3630
+ });
3631
+ return {
3632
+ readBackResult: readBackResult2,
3633
+ updateResult: updateResult2
3634
+ };
3635
+ } else {
3636
+ return {
3637
+ readBackResult: updateResult2,
3638
+ updateResult: updateResult2
3639
+ };
3640
+ }
3593
3641
  });
3594
3642
  if (readBackResult.length < updateResult.length && this.hasPolicyEnabled) {
3595
3643
  throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
@@ -3597,23 +3645,49 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3597
3645
  return readBackResult;
3598
3646
  }
3599
3647
  async runUpsert(args) {
3648
+ const { needReadBack, selectedFields } = this.needReadBack(args);
3600
3649
  const result = await this.safeTransaction(async (tx) => {
3601
- let mutationResult = await this.update(tx, this.model, args.where, args.update, void 0, true, false);
3650
+ let mutationResult = await this.update(tx, this.model, args.where, args.update, void 0, true, false, selectedFields);
3602
3651
  if (!mutationResult) {
3603
- mutationResult = await this.create(tx, this.model, args.create);
3652
+ mutationResult = await this.create(tx, this.model, args.create, void 0, void 0, selectedFields);
3653
+ }
3654
+ if (needReadBack) {
3655
+ return this.readUnique(tx, this.model, {
3656
+ select: args.select,
3657
+ include: args.include,
3658
+ omit: args.omit,
3659
+ where: getIdValues(this.schema, this.model, mutationResult)
3660
+ });
3661
+ } else {
3662
+ return mutationResult;
3604
3663
  }
3605
- return this.readUnique(tx, this.model, {
3606
- select: args.select,
3607
- include: args.include,
3608
- omit: args.omit,
3609
- where: getIdValues(this.schema, this.model, mutationResult)
3610
- });
3611
3664
  });
3612
3665
  if (!result && this.hasPolicyEnabled) {
3613
3666
  throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
3614
3667
  }
3615
3668
  return result;
3616
3669
  }
3670
+ needReadBack(args) {
3671
+ const baseResult = this.mutationNeedsReadBack(this.model, args);
3672
+ if (baseResult.needReadBack) {
3673
+ return baseResult;
3674
+ }
3675
+ const modelDef = this.requireModel(this.model);
3676
+ const nonRelationFields = Object.entries(modelDef.fields).filter(([_, def]) => !def.relation).map(([name, _]) => name);
3677
+ if (args.data && !Object.keys(args.data).some((field) => nonRelationFields.includes(field))) {
3678
+ return {
3679
+ needReadBack: true,
3680
+ selectedFields: void 0
3681
+ };
3682
+ }
3683
+ if (args.update && !Object.keys(args.update).some((field) => nonRelationFields.includes(field))) {
3684
+ return {
3685
+ needReadBack: true,
3686
+ selectedFields: void 0
3687
+ };
3688
+ }
3689
+ return baseResult;
3690
+ }
3617
3691
  };
3618
3692
 
3619
3693
  // src/client/crud/validator/index.ts
@@ -3978,12 +4052,12 @@ function evalCall(data, expr) {
3978
4052
  __name(evalCall, "evalCall");
3979
4053
 
3980
4054
  // src/client/crud/validator/index.ts
4055
+ var schemaCache = /* @__PURE__ */ new WeakMap();
3981
4056
  var InputValidator = class {
3982
4057
  static {
3983
4058
  __name(this, "InputValidator");
3984
4059
  }
3985
4060
  client;
3986
- schemaCache = /* @__PURE__ */ new Map();
3987
4061
  constructor(client) {
3988
4062
  this.client = client;
3989
4063
  }
@@ -4032,16 +4106,34 @@ var InputValidator = class {
4032
4106
  validateGroupByArgs(model, args) {
4033
4107
  return this.validate(model, "groupBy", void 0, (model2) => this.makeGroupBySchema(model2), args);
4034
4108
  }
4109
+ getSchemaCache(cacheKey) {
4110
+ let thisCache = schemaCache.get(this.schema);
4111
+ if (!thisCache) {
4112
+ thisCache = /* @__PURE__ */ new Map();
4113
+ schemaCache.set(this.schema, thisCache);
4114
+ }
4115
+ return thisCache.get(cacheKey);
4116
+ }
4117
+ setSchemaCache(cacheKey, schema) {
4118
+ let thisCache = schemaCache.get(this.schema);
4119
+ if (!thisCache) {
4120
+ thisCache = /* @__PURE__ */ new Map();
4121
+ schemaCache.set(this.schema, thisCache);
4122
+ }
4123
+ return thisCache.set(cacheKey, schema);
4124
+ }
4035
4125
  validate(model, operation, options, getSchema, args) {
4036
4126
  const cacheKey = (0, import_json_stable_stringify.default)({
4127
+ type: "model",
4037
4128
  model,
4038
4129
  operation,
4039
- options
4130
+ options,
4131
+ extraValidationsEnabled: this.extraValidationsEnabled
4040
4132
  });
4041
- let schema = this.schemaCache.get(cacheKey);
4133
+ let schema = this.getSchemaCache(cacheKey);
4042
4134
  if (!schema) {
4043
4135
  schema = getSchema(model, options);
4044
- this.schemaCache.set(cacheKey, schema);
4136
+ this.setSchemaCache(cacheKey, schema);
4045
4137
  }
4046
4138
  const { error, data } = schema.safeParse(args);
4047
4139
  if (error) {
@@ -4100,8 +4192,12 @@ var InputValidator = class {
4100
4192
  }
4101
4193
  }
4102
4194
  makeTypeDefSchema(type) {
4103
- const key = `$typedef-${type}`;
4104
- let schema = this.schemaCache.get(key);
4195
+ const key = (0, import_json_stable_stringify.default)({
4196
+ type: "typedef",
4197
+ name: type,
4198
+ extraValidationsEnabled: this.extraValidationsEnabled
4199
+ });
4200
+ let schema = this.getSchemaCache(key);
4105
4201
  if (schema) {
4106
4202
  return schema;
4107
4203
  }
@@ -4120,7 +4216,7 @@ var InputValidator = class {
4120
4216
  fieldSchema
4121
4217
  ];
4122
4218
  }))).passthrough();
4123
- this.schemaCache.set(key, schema);
4219
+ this.setSchemaCache(key, schema);
4124
4220
  return schema;
4125
4221
  }
4126
4222
  makeWhereSchema(model, unique, withoutRelationFields = false, withAggregations = false) {
@@ -5569,7 +5665,18 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely7.
5569
5665
  nameMapper;
5570
5666
  constructor(client, driver, compiler, adapter, connectionProvider, plugins = [], suppressMutationHooks = false) {
5571
5667
  super(compiler, adapter, connectionProvider, plugins), this.client = client, this.driver = driver, this.compiler = compiler, this.connectionProvider = connectionProvider, this.suppressMutationHooks = suppressMutationHooks;
5572
- this.nameMapper = new QueryNameMapper(client.$schema);
5668
+ if (this.schemaHasMappedNames(client.$schema)) {
5669
+ this.nameMapper = new QueryNameMapper(client.$schema);
5670
+ }
5671
+ }
5672
+ schemaHasMappedNames(schema) {
5673
+ const hasMapAttr = /* @__PURE__ */ __name((decl) => {
5674
+ if (decl.attributes?.some((attr) => attr.name === "@@map")) {
5675
+ return true;
5676
+ }
5677
+ return Object.values(decl.fields).some((field) => field.attributes?.some((attr) => attr.name === "@map"));
5678
+ }, "hasMapAttr");
5679
+ return Object.values(schema.models).some(hasMapAttr) || Object.values(schema.typeDefs ?? []).some(hasMapAttr);
5573
5680
  }
5574
5681
  get kysely() {
5575
5682
  return this.client.$qb;
@@ -5584,7 +5691,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely7.
5584
5691
  try {
5585
5692
  if (this.isMutationNode(compiledQuery.query) && !this.driver.isTransactionConnection(connection)) {
5586
5693
  await this.driver.beginTransaction(connection, {
5587
- isolationLevel: TransactionIsolationLevel.RepeatableRead
5694
+ isolationLevel: TransactionIsolationLevel.ReadCommitted
5588
5695
  });
5589
5696
  startedTx = true;
5590
5697
  }
@@ -5651,7 +5758,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely7.
5651
5758
  async proceedQuery(connection, query, parameters, queryId) {
5652
5759
  let compiled;
5653
5760
  if (this.suppressMutationHooks || !this.isMutationNode(query) || !this.hasEntityMutationPlugins) {
5654
- const finalQuery2 = this.nameMapper.transformNode(query);
5761
+ const finalQuery2 = this.processNameMapping(query);
5655
5762
  compiled = this.compileQuery(finalQuery2);
5656
5763
  if (parameters) {
5657
5764
  compiled = {
@@ -5669,7 +5776,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely7.
5669
5776
  ])
5670
5777
  };
5671
5778
  }
5672
- const finalQuery = this.nameMapper.transformNode(query);
5779
+ const finalQuery = this.processNameMapping(query);
5673
5780
  compiled = this.compileQuery(finalQuery);
5674
5781
  if (parameters) {
5675
5782
  compiled = {
@@ -5697,6 +5804,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely7.
5697
5804
  }
5698
5805
  return result;
5699
5806
  }
5807
+ processNameMapping(query) {
5808
+ return this.nameMapper?.transformNode(query) ?? query;
5809
+ }
5700
5810
  createClientForConnection(connection, inTx) {
5701
5811
  const innerExecutor = this.withConnectionProvider(new import_kysely7.SingleConnectionProvider(connection));
5702
5812
  innerExecutor.suppressMutationHooks = true;
@@ -6481,6 +6591,11 @@ var ClientImpl = class _ClientImpl {
6481
6591
  ...args
6482
6592
  ]);
6483
6593
  }
6594
+ async $connect() {
6595
+ await this.kysely.connection().execute(async (conn) => {
6596
+ await conn.executeQuery(import_kysely10.sql`select 1`.compile(this.kysely));
6597
+ });
6598
+ }
6484
6599
  async $disconnect() {
6485
6600
  await this.kysely.destroy();
6486
6601
  }