@zenstackhq/runtime 3.0.0-alpha.27 → 3.0.0-alpha.29

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.
@@ -531,8 +531,8 @@ declare abstract class BaseCrudDialect<Schema extends SchemaDef> {
531
531
  protected readonly options: ClientOptions<Schema>;
532
532
  constructor(schema: Schema, options: ClientOptions<Schema>);
533
533
  transformPrimitive(value: unknown, _type: BuiltinType, _forArrayField: boolean): unknown;
534
- buildSelectModel(eb: ExpressionBuilder<any, any>, model: string): SelectQueryBuilder<any, any, {}>;
535
- buildFilterSortTake(model: GetModels<Schema>, args: FindArgs<Schema, GetModels<Schema>, true>, query: SelectQueryBuilder<any, any, {}>): SelectQueryBuilder<any, any, {}>;
534
+ buildSelectModel(eb: ExpressionBuilder<any, any>, model: string, modelAlias: string): SelectQueryBuilder<any, any, {}>;
535
+ buildFilterSortTake(model: GetModels<Schema>, args: FindArgs<Schema, GetModels<Schema>, true>, query: SelectQueryBuilder<any, any, {}>, modelAlias: string): SelectQueryBuilder<any, any, {}>;
536
536
  buildFilter(eb: ExpressionBuilder<any, any>, model: string, modelAlias: string, where: boolean | object | undefined): Expression<SqlBool>;
537
537
  private buildCursorFilter;
538
538
  private isLogicalCombinator;
@@ -552,9 +552,9 @@ declare abstract class BaseCrudDialect<Schema extends SchemaDef> {
552
552
  private buildBytesFilter;
553
553
  private buildEnumFilter;
554
554
  buildOrderBy(query: SelectQueryBuilder<any, any, any>, model: string, modelAlias: string, orderBy: OrArray<OrderBy<Schema, GetModels<Schema>, boolean, boolean>> | undefined, useDefaultIfEmpty: boolean, negated: boolean): SelectQueryBuilder<any, any, any>;
555
- buildSelectAllFields(model: string, query: SelectQueryBuilder<any, any, any>, omit?: Record<string, boolean | undefined>): SelectQueryBuilder<any, any, any>;
555
+ buildSelectAllFields(model: string, query: SelectQueryBuilder<any, any, any>, omit: Record<string, boolean | undefined> | undefined, modelAlias: string): SelectQueryBuilder<any, any, any>;
556
556
  buildSelectField(query: SelectQueryBuilder<any, any, any>, model: string, modelAlias: string, field: string): SelectQueryBuilder<any, any, any>;
557
- buildDelegateJoin(thisModel: string, otherModel: string, query: SelectQueryBuilder<any, any, any>): SelectQueryBuilder<any, any, any>;
557
+ buildDelegateJoin(thisModel: string, thisModelAlias: string, otherModelAlias: string, query: SelectQueryBuilder<any, any, any>): SelectQueryBuilder<any, any, any>;
558
558
  buildCountJson(model: string, eb: ExpressionBuilder<any, any>, parentAlias: string, payload: any): ExpressionWrapper<any, any, unknown>;
559
559
  private negateSort;
560
560
  true(eb: ExpressionBuilder<any, any>): Expression<SqlBool>;
@@ -777,10 +777,6 @@ type ClientOptions<Schema extends SchemaDef> = {
777
777
  * Logging configuration.
778
778
  */
779
779
  log?: KyselyConfig['log'];
780
- /**
781
- * Debug mode.
782
- */
783
- debug?: boolean;
784
780
  } & (HasComputedFields<Schema> extends true ? {
785
781
  /**
786
782
  * Computed field definitions.
@@ -531,8 +531,8 @@ declare abstract class BaseCrudDialect<Schema extends SchemaDef> {
531
531
  protected readonly options: ClientOptions<Schema>;
532
532
  constructor(schema: Schema, options: ClientOptions<Schema>);
533
533
  transformPrimitive(value: unknown, _type: BuiltinType, _forArrayField: boolean): unknown;
534
- buildSelectModel(eb: ExpressionBuilder<any, any>, model: string): SelectQueryBuilder<any, any, {}>;
535
- buildFilterSortTake(model: GetModels<Schema>, args: FindArgs<Schema, GetModels<Schema>, true>, query: SelectQueryBuilder<any, any, {}>): SelectQueryBuilder<any, any, {}>;
534
+ buildSelectModel(eb: ExpressionBuilder<any, any>, model: string, modelAlias: string): SelectQueryBuilder<any, any, {}>;
535
+ buildFilterSortTake(model: GetModels<Schema>, args: FindArgs<Schema, GetModels<Schema>, true>, query: SelectQueryBuilder<any, any, {}>, modelAlias: string): SelectQueryBuilder<any, any, {}>;
536
536
  buildFilter(eb: ExpressionBuilder<any, any>, model: string, modelAlias: string, where: boolean | object | undefined): Expression<SqlBool>;
537
537
  private buildCursorFilter;
538
538
  private isLogicalCombinator;
@@ -552,9 +552,9 @@ declare abstract class BaseCrudDialect<Schema extends SchemaDef> {
552
552
  private buildBytesFilter;
553
553
  private buildEnumFilter;
554
554
  buildOrderBy(query: SelectQueryBuilder<any, any, any>, model: string, modelAlias: string, orderBy: OrArray<OrderBy<Schema, GetModels<Schema>, boolean, boolean>> | undefined, useDefaultIfEmpty: boolean, negated: boolean): SelectQueryBuilder<any, any, any>;
555
- buildSelectAllFields(model: string, query: SelectQueryBuilder<any, any, any>, omit?: Record<string, boolean | undefined>): SelectQueryBuilder<any, any, any>;
555
+ buildSelectAllFields(model: string, query: SelectQueryBuilder<any, any, any>, omit: Record<string, boolean | undefined> | undefined, modelAlias: string): SelectQueryBuilder<any, any, any>;
556
556
  buildSelectField(query: SelectQueryBuilder<any, any, any>, model: string, modelAlias: string, field: string): SelectQueryBuilder<any, any, any>;
557
- buildDelegateJoin(thisModel: string, otherModel: string, query: SelectQueryBuilder<any, any, any>): SelectQueryBuilder<any, any, any>;
557
+ buildDelegateJoin(thisModel: string, thisModelAlias: string, otherModelAlias: string, query: SelectQueryBuilder<any, any, any>): SelectQueryBuilder<any, any, any>;
558
558
  buildCountJson(model: string, eb: ExpressionBuilder<any, any>, parentAlias: string, payload: any): ExpressionWrapper<any, any, unknown>;
559
559
  private negateSort;
560
560
  true(eb: ExpressionBuilder<any, any>): Expression<SqlBool>;
@@ -777,10 +777,6 @@ type ClientOptions<Schema extends SchemaDef> = {
777
777
  * Logging configuration.
778
778
  */
779
779
  log?: KyselyConfig['log'];
780
- /**
781
- * Debug mode.
782
- */
783
- debug?: boolean;
784
780
  } & (HasComputedFields<Schema> extends true ? {
785
781
  /**
786
782
  * Computed field definitions.
package/dist/index.cjs CHANGED
@@ -321,7 +321,9 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias, inlineComp
321
321
  if (!computer) {
322
322
  throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
323
323
  }
324
- return computer(eb);
324
+ return computer(eb, {
325
+ currentModel: modelAlias
326
+ });
325
327
  }
326
328
  }
327
329
  __name(buildFieldRef, "buildFieldRef");
@@ -372,11 +374,33 @@ function getManyToManyRelation(schema, model, field) {
372
374
  model,
373
375
  fieldDef.type
374
376
  ].sort();
377
+ let orderedFK;
378
+ if (model !== fieldDef.type) {
379
+ orderedFK = sortedModelNames[0] === model ? [
380
+ "A",
381
+ "B"
382
+ ] : [
383
+ "B",
384
+ "A"
385
+ ];
386
+ } else {
387
+ const sortedFieldNames = [
388
+ field,
389
+ oppositeFieldDef.name
390
+ ].sort();
391
+ orderedFK = sortedFieldNames[0] === field ? [
392
+ "A",
393
+ "B"
394
+ ] : [
395
+ "B",
396
+ "A"
397
+ ];
398
+ }
375
399
  return {
376
- parentFkName: sortedModelNames[0] === model ? "A" : "B",
400
+ parentFkName: orderedFK[0],
377
401
  otherModel: fieldDef.type,
378
402
  otherField: fieldDef.relation.opposite,
379
- otherFkName: sortedModelNames[0] === fieldDef.type ? "A" : "B",
403
+ otherFkName: orderedFK[1],
380
404
  joinTable: fieldDef.relation.name ? `_${fieldDef.relation.name}` : `_${sortedModelNames[0]}To${sortedModelNames[1]}`
381
405
  };
382
406
  } else {
@@ -455,7 +479,6 @@ var import_cuid2 = require("@paralleldrive/cuid2");
455
479
  var import_common_helpers8 = require("@zenstackhq/common-helpers");
456
480
  var import_kysely8 = require("kysely");
457
481
  var import_nanoid = require("nanoid");
458
- var import_node_util = require("util");
459
482
  var import_ts_pattern9 = require("ts-pattern");
460
483
  var import_ulid = require("ulid");
461
484
  var uuid = __toESM(require("uuid"), 1);
@@ -540,20 +563,20 @@ var BaseCrudDialect = class {
540
563
  return value;
541
564
  }
542
565
  // #region common query builders
543
- buildSelectModel(eb, model) {
566
+ buildSelectModel(eb, model, modelAlias) {
544
567
  const modelDef = requireModel(this.schema, model);
545
- let result = eb.selectFrom(model);
568
+ let result = eb.selectFrom(model === modelAlias ? model : `${model} as ${modelAlias}`);
546
569
  let joinBase = modelDef.baseModel;
547
570
  while (joinBase) {
548
- result = this.buildDelegateJoin(model, joinBase, result);
571
+ result = this.buildDelegateJoin(model, modelAlias, joinBase, result);
549
572
  joinBase = requireModel(this.schema, joinBase).baseModel;
550
573
  }
551
574
  return result;
552
575
  }
553
- buildFilterSortTake(model, args, query) {
576
+ buildFilterSortTake(model, args, query, modelAlias) {
554
577
  let result = query;
555
578
  if (args.where) {
556
- result = result.where((eb) => this.buildFilter(eb, model, model, args?.where));
579
+ result = result.where((eb) => this.buildFilter(eb, model, modelAlias, args?.where));
557
580
  }
558
581
  let negateOrderBy = false;
559
582
  const skip = args.skip;
@@ -563,17 +586,17 @@ var BaseCrudDialect = class {
563
586
  take = -take;
564
587
  }
565
588
  result = this.buildSkipTake(result, skip, take);
566
- result = this.buildOrderBy(result, model, model, args.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
589
+ result = this.buildOrderBy(result, model, modelAlias, args.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
567
590
  if ("distinct" in args && args.distinct) {
568
591
  const distinct = ensureArray(args.distinct);
569
592
  if (this.supportsDistinctOn) {
570
- result = result.distinctOn(distinct.map((f) => import_kysely.sql.ref(`${model}.${f}`)));
593
+ result = result.distinctOn(distinct.map((f) => import_kysely.sql.ref(`${modelAlias}.${f}`)));
571
594
  } else {
572
595
  throw new QueryError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
573
596
  }
574
597
  }
575
598
  if (args.cursor) {
576
- result = this.buildCursorFilter(model, result, args.cursor, args.orderBy, negateOrderBy);
599
+ result = this.buildCursorFilter(model, result, args.cursor, args.orderBy, negateOrderBy, modelAlias);
577
600
  }
578
601
  return result;
579
602
  }
@@ -614,11 +637,12 @@ var BaseCrudDialect = class {
614
637
  }
615
638
  return result;
616
639
  }
617
- buildCursorFilter(model, query, cursor, orderBy, negateOrderBy) {
640
+ buildCursorFilter(model, query, cursor, orderBy, negateOrderBy, modelAlias) {
618
641
  const _orderBy = orderBy ?? makeDefaultOrderBy(this.schema, model);
619
642
  const orderByItems = ensureArray(_orderBy).flatMap((obj) => Object.entries(obj));
620
643
  const eb = (0, import_kysely.expressionBuilder)();
621
- const cursorFilter = this.buildFilter(eb, model, model, cursor);
644
+ const subQueryAlias = `${model}$cursor$sub`;
645
+ const cursorFilter = this.buildFilter(eb, model, subQueryAlias, cursor);
622
646
  let result = query;
623
647
  const filters = [];
624
648
  for (let i = orderByItems.length - 1; i >= 0; i--) {
@@ -627,7 +651,7 @@ var BaseCrudDialect = class {
627
651
  const [field, order] = orderByItems[j];
628
652
  const _order = negateOrderBy ? order === "asc" ? "desc" : "asc" : order;
629
653
  const op = j === i ? _order === "asc" ? ">=" : "<=" : "=";
630
- andFilters.push(eb(eb.ref(`${model}.${field}`), op, eb.selectFrom(model).select(`${model}.${field}`).where(cursorFilter)));
654
+ andFilters.push(eb(eb.ref(`${modelAlias}.${field}`), op, this.buildSelectModel(eb, model, subQueryAlias).select(`${subQueryAlias}.${field}`).where(cursorFilter)));
631
655
  }
632
656
  filters.push(eb.and(andFilters));
633
657
  }
@@ -696,25 +720,26 @@ var BaseCrudDialect = class {
696
720
  }
697
721
  return this.and(eb, ...conditions);
698
722
  }
699
- buildToManyRelationFilter(eb, model, table, field, fieldDef, payload) {
723
+ buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
700
724
  if (payload === null) {
701
- return eb(import_kysely.sql.ref(`${table}.${field}`), "is", null);
725
+ return eb(import_kysely.sql.ref(`${modelAlias}.${field}`), "is", null);
702
726
  }
703
727
  const relationModel = fieldDef.type;
728
+ const relationFilterSelectAlias = `${modelAlias}$${field}$filter`;
704
729
  const buildPkFkWhereRefs = /* @__PURE__ */ __name((eb2) => {
705
730
  const m2m = getManyToManyRelation(this.schema, model, field);
706
731
  if (m2m) {
707
732
  const modelIdField = getIdFields(this.schema, model)[0];
708
733
  const relationIdField = getIdFields(this.schema, relationModel)[0];
709
- return eb2(import_kysely.sql.ref(`${relationModel}.${relationIdField}`), "in", eb2.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(import_kysely.sql.ref(`${m2m.joinTable}.${m2m.parentFkName}`), "=", import_kysely.sql.ref(`${table}.${modelIdField}`)));
734
+ return eb2(import_kysely.sql.ref(`${relationFilterSelectAlias}.${relationIdField}`), "in", eb2.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(import_kysely.sql.ref(`${m2m.joinTable}.${m2m.parentFkName}`), "=", import_kysely.sql.ref(`${modelAlias}.${modelIdField}`)));
710
735
  } else {
711
736
  const relationKeyPairs = getRelationForeignKeyFieldPairs(this.schema, model, field);
712
737
  let result2 = this.true(eb2);
713
738
  for (const { fk, pk } of relationKeyPairs.keyPairs) {
714
739
  if (relationKeyPairs.ownedByModel) {
715
- result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${table}.${fk}`), "=", import_kysely.sql.ref(`${relationModel}.${pk}`)));
740
+ result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${modelAlias}.${fk}`), "=", import_kysely.sql.ref(`${relationFilterSelectAlias}.${pk}`)));
716
741
  } else {
717
- result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${table}.${pk}`), "=", import_kysely.sql.ref(`${relationModel}.${fk}`)));
742
+ result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${modelAlias}.${pk}`), "=", import_kysely.sql.ref(`${relationFilterSelectAlias}.${fk}`)));
718
743
  }
719
744
  }
720
745
  return result2;
@@ -727,15 +752,15 @@ var BaseCrudDialect = class {
727
752
  }
728
753
  switch (key) {
729
754
  case "some": {
730
- result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), ">", 0));
755
+ result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel, relationFilterSelectAlias).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationFilterSelectAlias, subPayload)), ">", 0));
731
756
  break;
732
757
  }
733
758
  case "every": {
734
- result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => eb1.not(this.buildFilter(eb1, relationModel, relationModel, subPayload))), "=", 0));
759
+ result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel, relationFilterSelectAlias).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => eb1.not(this.buildFilter(eb1, relationModel, relationFilterSelectAlias, subPayload))), "=", 0));
735
760
  break;
736
761
  }
737
762
  case "none": {
738
- result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), "=", 0));
763
+ result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel, relationFilterSelectAlias).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationFilterSelectAlias, subPayload)), "=", 0));
739
764
  break;
740
765
  }
741
766
  }
@@ -978,8 +1003,9 @@ var BaseCrudDialect = class {
978
1003
  (0, import_common_helpers.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
979
1004
  const sort = this.negateSort(value._count, negated);
980
1005
  result = result.orderBy((eb) => {
981
- let subQuery = this.buildSelectModel(eb, relationModel);
982
- const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
1006
+ const subQueryAlias = `${modelAlias}$orderBy$${field}$count`;
1007
+ let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
1008
+ const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, subQueryAlias);
983
1009
  subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right)))));
984
1010
  subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
985
1011
  return subQuery;
@@ -997,7 +1023,7 @@ var BaseCrudDialect = class {
997
1023
  });
998
1024
  return result;
999
1025
  }
1000
- buildSelectAllFields(model, query, omit) {
1026
+ buildSelectAllFields(model, query, omit, modelAlias) {
1001
1027
  const modelDef = requireModel(this.schema, model);
1002
1028
  let result = query;
1003
1029
  for (const field of Object.keys(modelDef.fields)) {
@@ -1007,11 +1033,11 @@ var BaseCrudDialect = class {
1007
1033
  if (omit?.[field] === true) {
1008
1034
  continue;
1009
1035
  }
1010
- result = this.buildSelectField(result, model, model, field);
1036
+ result = this.buildSelectField(result, model, modelAlias, field);
1011
1037
  }
1012
1038
  const descendants = getDelegateDescendantModels(this.schema, model);
1013
1039
  for (const subModel of descendants) {
1014
- result = this.buildDelegateJoin(model, subModel.name, result);
1040
+ result = this.buildDelegateJoin(model, modelAlias, subModel.name, result);
1015
1041
  result = result.select((eb) => {
1016
1042
  const jsonObject = {};
1017
1043
  for (const field of Object.keys(subModel.fields)) {
@@ -1035,11 +1061,11 @@ var BaseCrudDialect = class {
1035
1061
  return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
1036
1062
  }
1037
1063
  }
1038
- buildDelegateJoin(thisModel, otherModel, query) {
1064
+ buildDelegateJoin(thisModel, thisModelAlias, otherModelAlias, query) {
1039
1065
  const idFields = getIdFields(this.schema, thisModel);
1040
- query = query.leftJoin(otherModel, (qb) => {
1066
+ query = query.leftJoin(otherModelAlias, (qb) => {
1041
1067
  for (const idField of idFields) {
1042
- qb = qb.onRef(`${thisModel}.${idField}`, "=", `${otherModel}.${idField}`);
1068
+ qb = qb.onRef(`${thisModelAlias}.${idField}`, "=", `${otherModelAlias}.${idField}`);
1043
1069
  }
1044
1070
  return qb;
1045
1071
  });
@@ -1156,11 +1182,12 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1156
1182
  return qb.leftJoinLateral((eb) => {
1157
1183
  const joinTableName = `${parentName}$${relationField}`;
1158
1184
  let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
1185
+ const subQueryAlias = `${relationModel}$${relationField}$sub`;
1159
1186
  result = eb.selectFrom(() => {
1160
- let subQuery = this.buildSelectModel(eb, relationModel);
1161
- subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
1187
+ let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
1188
+ subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0, subQueryAlias);
1162
1189
  if (payload && typeof payload === "object") {
1163
- subQuery = this.buildFilterSortTake(relationModel, payload, subQuery);
1190
+ subQuery = this.buildFilterSortTake(relationModel, payload, subQuery, subQueryAlias);
1164
1191
  }
1165
1192
  const m2m = getManyToManyRelation(this.schema, model, relationField);
1166
1193
  if (m2m) {
@@ -1168,21 +1195,21 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1168
1195
  const relationIds = getIdFields(this.schema, relationModel);
1169
1196
  (0, import_common_helpers2.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
1170
1197
  (0, import_common_helpers2.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
1171
- subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentName}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
1198
+ subQuery = subQuery.where(eb(eb.ref(`${subQueryAlias}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentName}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
1172
1199
  } else {
1173
- const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField, relationModel);
1200
+ const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField, subQueryAlias);
1174
1201
  subQuery = subQuery.where((eb2) => this.and(eb2, ...joinPairs.map(([left, right]) => eb2(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right)))));
1175
1202
  }
1176
1203
  return subQuery.as(joinTableName);
1177
1204
  });
1178
- result = this.buildRelationObjectSelect(relationModel, relationField, relationFieldDef, result, payload, parentName);
1205
+ result = this.buildRelationObjectSelect(relationModel, joinTableName, relationField, relationFieldDef, result, payload, parentName);
1179
1206
  result = this.buildRelationJoins(relationModel, relationField, result, payload, parentName);
1180
1207
  return result.as(joinTableName);
1181
1208
  }, (join) => join.onTrue());
1182
1209
  }
1183
- buildRelationObjectSelect(relationModel, relationField, relationFieldDef, qb, payload, parentName) {
1210
+ buildRelationObjectSelect(relationModel, relationModelAlias, relationField, relationFieldDef, qb, payload, parentName) {
1184
1211
  qb = qb.select((eb) => {
1185
- const objArgs = this.buildRelationObjectArgs(relationModel, relationField, eb, payload, parentName);
1212
+ const objArgs = this.buildRelationObjectArgs(relationModel, relationModelAlias, relationField, eb, payload, parentName);
1186
1213
  if (relationFieldDef.array) {
1187
1214
  return eb.fn.coalesce(import_kysely2.sql`jsonb_agg(jsonb_build_object(${import_kysely2.sql.join(objArgs)}))`, import_kysely2.sql`'[]'::jsonb`).as("$j");
1188
1215
  } else {
@@ -1191,7 +1218,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1191
1218
  });
1192
1219
  return qb;
1193
1220
  }
1194
- buildRelationObjectArgs(relationModel, relationField, eb, payload, parentAlias) {
1221
+ buildRelationObjectArgs(relationModel, relationModelAlias, relationField, eb, payload, parentAlias) {
1195
1222
  const relationModelDef = requireModel(this.schema, relationModel);
1196
1223
  const objArgs = [];
1197
1224
  const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
@@ -1204,7 +1231,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1204
1231
  if (payload === true || !payload.select) {
1205
1232
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
1206
1233
  import_kysely2.sql.lit(field),
1207
- this.fieldRef(relationModel, field, eb, void 0, false)
1234
+ this.fieldRef(relationModel, field, eb, relationModelAlias, false)
1208
1235
  ]).flatMap((v) => v));
1209
1236
  } else if (payload.select) {
1210
1237
  objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
@@ -1320,10 +1347,11 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1320
1347
  const relationModelDef = requireModel(this.schema, relationModel);
1321
1348
  const subQueryName = `${parentAlias}$${relationField}`;
1322
1349
  let tbl = eb.selectFrom(() => {
1323
- let subQuery = this.buildSelectModel(eb, relationModel);
1324
- subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
1350
+ const subQueryAlias = `${parentAlias}$${relationField}$sub`;
1351
+ let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
1352
+ subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0, subQueryAlias);
1325
1353
  if (payload && typeof payload === "object") {
1326
- subQuery = this.buildFilterSortTake(relationModel, payload, subQuery);
1354
+ subQuery = this.buildFilterSortTake(relationModel, payload, subQuery, subQueryAlias);
1327
1355
  }
1328
1356
  const m2m = getManyToManyRelation(this.schema, model, relationField);
1329
1357
  if (m2m) {
@@ -1331,14 +1359,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1331
1359
  const relationIds = getIdFields(this.schema, relationModel);
1332
1360
  (0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
1333
1361
  (0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
1334
- subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
1362
+ subQuery = subQuery.where(eb(eb.ref(`${subQueryAlias}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
1335
1363
  } else {
1336
1364
  const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
1337
1365
  keyPairs.forEach(({ fk, pk }) => {
1338
1366
  if (ownedByModel) {
1339
- subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentAlias}.${fk}`);
1367
+ subQuery = subQuery.whereRef(`${subQueryAlias}.${pk}`, "=", `${parentAlias}.${fk}`);
1340
1368
  } else {
1341
- subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentAlias}.${pk}`);
1369
+ subQuery = subQuery.whereRef(`${subQueryAlias}.${fk}`, "=", `${parentAlias}.${pk}`);
1342
1370
  }
1343
1371
  });
1344
1372
  }
@@ -2764,14 +2792,14 @@ var BaseOperationHandler = class {
2764
2792
  return this.executeQueryTakeFirst(kysely, query, "exists");
2765
2793
  }
2766
2794
  async read(kysely, model, args) {
2767
- let query = this.dialect.buildSelectModel((0, import_kysely8.expressionBuilder)(), model);
2795
+ let query = this.dialect.buildSelectModel((0, import_kysely8.expressionBuilder)(), model, model);
2768
2796
  if (args) {
2769
- query = this.dialect.buildFilterSortTake(model, args, query);
2797
+ query = this.dialect.buildFilterSortTake(model, args, query, model);
2770
2798
  }
2771
2799
  if (args && "select" in args && args.select) {
2772
2800
  query = this.buildFieldSelection(model, query, args.select, model);
2773
2801
  } else {
2774
- query = this.dialect.buildSelectAllFields(model, query, args?.omit);
2802
+ query = this.dialect.buildSelectAllFields(model, query, args?.omit, model);
2775
2803
  }
2776
2804
  if (args && "include" in args && args.include) {
2777
2805
  query = this.buildFieldSelection(model, query, args.include, model);
@@ -2789,11 +2817,7 @@ var BaseOperationHandler = class {
2789
2817
  const r = await kysely.getExecutor().executeQuery(compiled, queryId);
2790
2818
  result = r.rows;
2791
2819
  } catch (err) {
2792
- let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
2793
- if (this.options.debug) {
2794
- message += `, parameters:
2795
- ${compiled.parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
2796
- }
2820
+ const message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
2797
2821
  throw new QueryError(message, err);
2798
2822
  }
2799
2823
  return result;
@@ -2961,7 +2985,12 @@ ${compiled.parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
2961
2985
  field: rightField,
2962
2986
  entity: rightEntity
2963
2987
  }
2964
- ].sort((a, b) => a.model.localeCompare(b.model));
2988
+ ].sort((a, b) => (
2989
+ // the implement m2m join table's "A", "B" fk fields' order is determined
2990
+ // by model name's sort order, and when identical (for self-relations),
2991
+ // field name's sort order
2992
+ a.model !== b.model ? a.model.localeCompare(b.model) : a.field.localeCompare(b.field)
2993
+ ));
2965
2994
  const firstIds = getIdFields(this.schema, sortedRecords[0].model);
2966
2995
  const secondIds = getIdFields(this.schema, sortedRecords[1].model);
2967
2996
  (0, import_common_helpers8.invariant)(firstIds.length === 1, "many-to-many relation must have exactly one id field");
@@ -3466,7 +3495,7 @@ ${compiled.parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
3466
3495
  } else {
3467
3496
  query = query.where((eb) => eb(eb.refTuple(
3468
3497
  ...this.buildIdFieldRefs(kysely, model)
3469
- ), "in", this.dialect.buildSelectModel(eb, filterModel).where(this.dialect.buildFilter(eb, filterModel, filterModel, where)).select(this.buildIdFieldRefs(kysely, filterModel)).$if(limit !== void 0, (qb) => qb.limit(limit))));
3498
+ ), "in", this.dialect.buildSelectModel(eb, filterModel, filterModel).where(this.dialect.buildFilter(eb, filterModel, filterModel, where)).select(this.buildIdFieldRefs(kysely, filterModel)).$if(limit !== void 0, (qb) => qb.limit(limit))));
3470
3499
  }
3471
3500
  query = query.modifyEnd(this.makeContextComment({
3472
3501
  model,
@@ -3884,7 +3913,7 @@ ${compiled.parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
3884
3913
  } else {
3885
3914
  query = query.where((eb) => eb(eb.refTuple(
3886
3915
  ...this.buildIdFieldRefs(kysely, model)
3887
- ), "in", this.dialect.buildSelectModel(eb, filterModel).where((eb2) => this.dialect.buildFilter(eb2, filterModel, filterModel, where)).select(this.buildIdFieldRefs(kysely, filterModel)).$if(limit !== void 0, (qb) => qb.limit(limit))));
3916
+ ), "in", this.dialect.buildSelectModel(eb, filterModel, filterModel).where((eb2) => this.dialect.buildFilter(eb2, filterModel, filterModel, where)).select(this.buildIdFieldRefs(kysely, filterModel)).$if(limit !== void 0, (qb) => qb.limit(limit))));
3888
3917
  }
3889
3918
  await this.processDelegateRelationDelete(kysely, modelDef, where, limit);
3890
3919
  query = query.modifyEnd(this.makeContextComment({
@@ -4020,7 +4049,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
4020
4049
  const normalizedArgs = this.normalizeArgs(args);
4021
4050
  const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
4022
4051
  let query = this.kysely.selectFrom((eb) => {
4023
- let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4052
+ let subQuery = this.dialect.buildSelectModel(eb, this.model, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4024
4053
  const selectedFields = [];
4025
4054
  for (const [key, value] of Object.entries(parsedArgs)) {
4026
4055
  if (key.startsWith("_") && value && typeof value === "object") {
@@ -4130,7 +4159,7 @@ var CountOperationHandler = class extends BaseOperationHandler {
4130
4159
  const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
4131
4160
  const subQueryName = "$sub";
4132
4161
  let query = this.kysely.selectFrom((eb) => {
4133
- let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4162
+ let subQuery = this.dialect.buildSelectModel(eb, this.model, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4134
4163
  if (parsedArgs?.select && typeof parsedArgs.select === "object") {
4135
4164
  for (const [key, value] of Object.entries(parsedArgs.select)) {
4136
4165
  if (key !== "_all" && value === true) {
@@ -5633,7 +5662,6 @@ __name(performanceNow, "performanceNow");
5633
5662
  // src/client/executor/zenstack-query-executor.ts
5634
5663
  var import_kysely13 = require("kysely");
5635
5664
  var import_nanoid2 = require("nanoid");
5636
- var import_node_util2 = require("util");
5637
5665
  var import_ts_pattern16 = require("ts-pattern");
5638
5666
 
5639
5667
  // src/client/executor/name-mapper.ts
@@ -5941,11 +5969,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
5941
5969
  };
5942
5970
  });
5943
5971
  } catch (err) {
5944
- let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
5945
- if (this.options.debug) {
5946
- message += `, parameters:
5947
- ${compiled.parameters.map((p) => (0, import_node_util2.inspect)(p)).join("\n")}`;
5948
- }
5972
+ const message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
5949
5973
  throw new QueryError(message, err);
5950
5974
  }
5951
5975
  }