@zenstackhq/runtime 3.0.0-alpha.20 → 3.0.0-alpha.22

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.
@@ -562,6 +562,7 @@ declare abstract class BaseCrudDialect<Schema extends SchemaDef> {
562
562
  protected and(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): Expression<SqlBool>;
563
563
  protected or(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): Expression<SqlBool>;
564
564
  protected not(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): ExpressionWrapper<any, any, SqlBool>;
565
+ fieldRef(model: string, field: string, eb: ExpressionBuilder<any, any>, modelAlias?: string): ExpressionWrapper<any, any, unknown>;
565
566
  abstract get provider(): DataSourceProviderType;
566
567
  /**
567
568
  * Builds selection for a relation field.
@@ -562,6 +562,7 @@ declare abstract class BaseCrudDialect<Schema extends SchemaDef> {
562
562
  protected and(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): Expression<SqlBool>;
563
563
  protected or(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): Expression<SqlBool>;
564
564
  protected not(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): ExpressionWrapper<any, any, SqlBool>;
565
+ fieldRef(model: string, field: string, eb: ExpressionBuilder<any, any>, modelAlias?: string): ExpressionWrapper<any, any, unknown>;
565
566
  abstract get provider(): DataSourceProviderType;
566
567
  /**
567
568
  * Builds selection for a relation field.
package/dist/index.cjs CHANGED
@@ -582,7 +582,7 @@ var BaseCrudDialect = class {
582
582
  if (fieldDef.relation) {
583
583
  result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
584
584
  } else {
585
- const fieldRef = buildFieldRef(this.schema, fieldDef.originModel ?? model, key, this.options, eb, fieldDef.originModel ?? modelAlias);
585
+ const fieldRef = this.fieldRef(fieldDef.originModel ?? model, key, eb, fieldDef.originModel ?? modelAlias);
586
586
  if (fieldDef.array) {
587
587
  result = this.and(eb, result, this.buildArrayFilter(eb, fieldRef, fieldDef, payload));
588
588
  } else {
@@ -905,7 +905,7 @@ var BaseCrudDialect = class {
905
905
  (0, import_common_helpers.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
906
906
  for (const [k, v] of Object.entries(value)) {
907
907
  (0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
908
- result = result.orderBy((eb) => aggregate(eb, import_kysely.sql.ref(`${modelAlias}.${k}`), field), import_kysely.sql.raw(this.negateSort(v, negated)));
908
+ result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field), import_kysely.sql.raw(this.negateSort(v, negated)));
909
909
  }
910
910
  continue;
911
911
  }
@@ -914,7 +914,7 @@ var BaseCrudDialect = class {
914
914
  (0, import_common_helpers.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
915
915
  for (const [k, v] of Object.entries(value)) {
916
916
  (0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
917
- result = result.orderBy((eb) => eb.fn.count(import_kysely.sql.ref(k)), import_kysely.sql.raw(this.negateSort(v, negated)));
917
+ result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), import_kysely.sql.raw(this.negateSort(v, negated)));
918
918
  }
919
919
  continue;
920
920
  }
@@ -923,10 +923,11 @@ var BaseCrudDialect = class {
923
923
  }
924
924
  const fieldDef = requireField(this.schema, model, field);
925
925
  if (!fieldDef.relation) {
926
+ const fieldRef = this.fieldRef(model, field, (0, import_kysely.expressionBuilder)(), modelAlias);
926
927
  if (value === "asc" || value === "desc") {
927
- result = result.orderBy(import_kysely.sql.ref(`${modelAlias}.${field}`), this.negateSort(value, negated));
928
+ result = result.orderBy(fieldRef, this.negateSort(value, negated));
928
929
  } else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
929
- result = result.orderBy(import_kysely.sql.ref(`${modelAlias}.${field}`), import_kysely.sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
930
+ result = result.orderBy(fieldRef, import_kysely.sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
930
931
  }
931
932
  } else {
932
933
  const relationModel = fieldDef.type;
@@ -988,7 +989,7 @@ var BaseCrudDialect = class {
988
989
  buildSelectField(query, model, modelAlias, field) {
989
990
  const fieldDef = requireField(this.schema, model, field);
990
991
  if (fieldDef.computed) {
991
- return query.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(field));
992
+ return query.select((eb) => this.fieldRef(model, field, eb, modelAlias).as(field));
992
993
  } else if (!fieldDef.originModel) {
993
994
  return query.select(import_kysely.sql.ref(`${modelAlias}.${field}`).as(field));
994
995
  } else {
@@ -1079,6 +1080,9 @@ var BaseCrudDialect = class {
1079
1080
  not(eb, ...args) {
1080
1081
  return eb.not(this.and(eb, ...args));
1081
1082
  }
1083
+ fieldRef(model, field, eb, modelAlias) {
1084
+ return buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
1085
+ }
1082
1086
  };
1083
1087
 
1084
1088
  // src/client/crud/dialects/postgresql.ts
@@ -1172,7 +1176,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1172
1176
  if (payload === true || !payload.select) {
1173
1177
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
1174
1178
  import_kysely2.sql.lit(field),
1175
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
1179
+ this.fieldRef(relationModel, field, eb)
1176
1180
  ]).flatMap((v) => v));
1177
1181
  } else if (payload.select) {
1178
1182
  objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
@@ -1184,7 +1188,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1184
1188
  ];
1185
1189
  } else {
1186
1190
  const fieldDef = requireField(this.schema, relationModel, field);
1187
- const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
1191
+ const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : this.fieldRef(relationModel, field, eb);
1188
1192
  return [
1189
1193
  import_kysely2.sql.lit(field),
1190
1194
  fieldValue
@@ -1335,7 +1339,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1335
1339
  if (payload === true || !payload.select) {
1336
1340
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
1337
1341
  import_kysely3.sql.lit(field),
1338
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
1342
+ this.fieldRef(relationModel, field, eb)
1339
1343
  ]).flatMap((v) => v));
1340
1344
  } else if (payload.select) {
1341
1345
  objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
@@ -1356,7 +1360,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1356
1360
  } else {
1357
1361
  return [
1358
1362
  import_kysely3.sql.lit(field),
1359
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
1363
+ this.fieldRef(relationModel, field, eb)
1360
1364
  ];
1361
1365
  }
1362
1366
  }
@@ -2763,7 +2767,7 @@ var BaseOperationHandler = class {
2763
2767
  query = query.distinctOn(distinct.map((f) => import_kysely8.sql.ref(`${model}.${f}`)));
2764
2768
  } else {
2765
2769
  inMemoryDistinct = distinct;
2766
- query = distinct.reduce((acc, field) => acc.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(`$distinct$${field}`)), query);
2770
+ query = distinct.reduce((acc, field) => acc.select((eb) => this.dialect.fieldRef(model, field, eb).as(`$distinct$${field}`)), query);
2767
2771
  }
2768
2772
  }
2769
2773
  if (args && "select" in args && args.select) {
@@ -3436,7 +3440,7 @@ ${compiled.parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
3436
3440
  const key = Object.keys(payload)[0];
3437
3441
  const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
3438
3442
  const eb = (0, import_kysely8.expressionBuilder)();
3439
- const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
3443
+ const fieldRef = this.dialect.fieldRef(model, field, eb);
3440
3444
  return (0, import_ts_pattern9.match)(key).with("set", () => value).with("increment", () => eb(fieldRef, "+", value)).with("decrement", () => eb(fieldRef, "-", value)).with("multiply", () => eb(fieldRef, "*", value)).with("divide", () => eb(fieldRef, "/", value)).otherwise(() => {
3441
3445
  throw new InternalError(`Invalid incremental update operation: ${key}`);
3442
3446
  });
@@ -3446,7 +3450,7 @@ ${compiled.parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
3446
3450
  const key = Object.keys(payload)[0];
3447
3451
  const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
3448
3452
  const eb = (0, import_kysely8.expressionBuilder)();
3449
- const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
3453
+ const fieldRef = this.dialect.fieldRef(model, field, eb);
3450
3454
  return (0, import_ts_pattern9.match)(key).with("set", () => value).with("push", () => {
3451
3455
  return eb(fieldRef, "||", eb.val(ensureArray(value)));
3452
3456
  }).otherwise(() => {
@@ -4320,10 +4324,11 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
4320
4324
  subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
4321
4325
  return subQuery.as("$sub");
4322
4326
  });
4327
+ const fieldRef = /* @__PURE__ */ __name((field) => this.dialect.fieldRef(this.model, field, (0, import_kysely11.expressionBuilder)(), "$sub"), "fieldRef");
4323
4328
  const bys = typeof parsedArgs.by === "string" ? [
4324
4329
  parsedArgs.by
4325
4330
  ] : parsedArgs.by;
4326
- query = query.groupBy(bys.map((by) => import_kysely11.sql.ref(`$sub.${by}`)));
4331
+ query = query.groupBy(bys.map((by) => fieldRef(by)));
4327
4332
  if (parsedArgs.orderBy) {
4328
4333
  query = this.dialect.buildOrderBy(query, this.model, "$sub", parsedArgs.orderBy, false, false);
4329
4334
  }
@@ -4331,7 +4336,7 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
4331
4336
  query = query.having((eb) => this.dialect.buildFilter(eb, this.model, "$sub", parsedArgs.having));
4332
4337
  }
4333
4338
  for (const by of bys) {
4334
- query = query.select(() => import_kysely11.sql.ref(`$sub.${by}`).as(by));
4339
+ query = query.select(() => fieldRef(by).as(by));
4335
4340
  }
4336
4341
  for (const [key, value] of Object.entries(parsedArgs)) {
4337
4342
  switch (key) {
@@ -4344,7 +4349,7 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
4344
4349
  if (field === "_all") {
4345
4350
  query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as(`_count._all`));
4346
4351
  } else {
4347
- query = query.select((eb) => eb.cast(eb.fn.count(import_kysely11.sql.ref(`$sub.${field}`)), "integer").as(`${key}.${field}`));
4352
+ query = query.select((eb) => eb.cast(eb.fn.count(fieldRef(field)), "integer").as(`${key}.${field}`));
4348
4353
  }
4349
4354
  }
4350
4355
  });
@@ -4357,10 +4362,7 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
4357
4362
  case "_min": {
4358
4363
  Object.entries(value).forEach(([field, val]) => {
4359
4364
  if (val === true) {
4360
- query = query.select((eb) => {
4361
- const fn = (0, import_ts_pattern13.match)(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
4362
- return fn(import_kysely11.sql.ref(`$sub.${field}`)).as(`${key}.${field}`);
4363
- });
4365
+ query = query.select((eb) => aggregate(eb, fieldRef(field), key).as(`${key}.${field}`));
4364
4366
  }
4365
4367
  });
4366
4368
  break;
@@ -6288,6 +6290,7 @@ __name(processCasing, "processCasing");
6288
6290
  // src/client/helpers/schema-db-pusher.ts
6289
6291
  var import_common_helpers11 = require("@zenstackhq/common-helpers");
6290
6292
  var import_kysely15 = require("kysely");
6293
+ var import_toposort = __toESM(require("toposort"), 1);
6291
6294
  var import_ts_pattern18 = require("ts-pattern");
6292
6295
  var SchemaDbPusher = class {
6293
6296
  static {
@@ -6307,41 +6310,79 @@ var SchemaDbPusher = class {
6307
6310
  await createEnum.execute();
6308
6311
  }
6309
6312
  }
6310
- for (const model of Object.keys(this.schema.models)) {
6311
- const createTable = this.createModelTable(tx, model);
6313
+ const sortedModels = this.sortModels(this.schema.models);
6314
+ for (const modelDef of sortedModels) {
6315
+ const createTable = this.createModelTable(tx, modelDef);
6312
6316
  await createTable.execute();
6313
6317
  }
6314
6318
  });
6315
6319
  }
6316
- createModelTable(kysely, model) {
6317
- let table = kysely.schema.createTable(model).ifNotExists();
6318
- const modelDef = requireModel(this.schema, model);
6320
+ sortModels(models) {
6321
+ const graph = [];
6322
+ for (const model of Object.values(models)) {
6323
+ let added = false;
6324
+ if (model.baseModel) {
6325
+ const baseDef = requireModel(this.schema, model.baseModel);
6326
+ graph.push([
6327
+ model,
6328
+ baseDef
6329
+ ]);
6330
+ added = true;
6331
+ }
6332
+ for (const field of Object.values(model.fields)) {
6333
+ if (field.relation && field.relation.fields && field.relation.references) {
6334
+ const targetModel = requireModel(this.schema, field.type);
6335
+ graph.push([
6336
+ model,
6337
+ targetModel
6338
+ ]);
6339
+ added = true;
6340
+ }
6341
+ }
6342
+ if (!added) {
6343
+ graph.push([
6344
+ model,
6345
+ void 0
6346
+ ]);
6347
+ }
6348
+ }
6349
+ return (0, import_toposort.default)(graph).reverse().filter((m) => !!m);
6350
+ }
6351
+ createModelTable(kysely, modelDef) {
6352
+ let table = kysely.schema.createTable(modelDef.name).ifNotExists();
6319
6353
  for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
6354
+ if (fieldDef.originModel && !fieldDef.id) {
6355
+ continue;
6356
+ }
6320
6357
  if (fieldDef.relation) {
6321
- table = this.addForeignKeyConstraint(table, model, fieldName, fieldDef);
6358
+ table = this.addForeignKeyConstraint(table, modelDef.name, fieldName, fieldDef);
6322
6359
  } else if (!this.isComputedField(fieldDef)) {
6323
- table = this.createModelField(table, fieldName, fieldDef, modelDef);
6360
+ table = this.createModelField(table, fieldDef, modelDef);
6324
6361
  }
6325
6362
  }
6326
- table = this.addPrimaryKeyConstraint(table, model, modelDef);
6327
- table = this.addUniqueConstraint(table, model, modelDef);
6363
+ if (modelDef.baseModel) {
6364
+ const baseModelDef = requireModel(this.schema, modelDef.baseModel);
6365
+ table = table.addForeignKeyConstraint(`fk_${modelDef.baseModel}_delegate`, baseModelDef.idFields, modelDef.baseModel, baseModelDef.idFields, (cb) => cb.onDelete("cascade").onUpdate("cascade"));
6366
+ }
6367
+ table = this.addPrimaryKeyConstraint(table, modelDef);
6368
+ table = this.addUniqueConstraint(table, modelDef);
6328
6369
  return table;
6329
6370
  }
6330
6371
  isComputedField(fieldDef) {
6331
6372
  return fieldDef.attributes?.some((a) => a.name === "@computed");
6332
6373
  }
6333
- addPrimaryKeyConstraint(table, model, modelDef) {
6374
+ addPrimaryKeyConstraint(table, modelDef) {
6334
6375
  if (modelDef.idFields.length === 1) {
6335
6376
  if (Object.values(modelDef.fields).some((f) => f.id)) {
6336
6377
  return table;
6337
6378
  }
6338
6379
  }
6339
6380
  if (modelDef.idFields.length > 0) {
6340
- table = table.addPrimaryKeyConstraint(`pk_${model}`, modelDef.idFields);
6381
+ table = table.addPrimaryKeyConstraint(`pk_${modelDef.name}`, modelDef.idFields);
6341
6382
  }
6342
6383
  return table;
6343
6384
  }
6344
- addUniqueConstraint(table, model, modelDef) {
6385
+ addUniqueConstraint(table, modelDef) {
6345
6386
  for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
6346
6387
  (0, import_common_helpers11.invariant)(typeof value === "object", "expecting an object");
6347
6388
  if ("type" in value) {
@@ -6349,17 +6390,17 @@ var SchemaDbPusher = class {
6349
6390
  if (fieldDef.unique) {
6350
6391
  continue;
6351
6392
  }
6352
- table = table.addUniqueConstraint(`unique_${model}_${key}`, [
6393
+ table = table.addUniqueConstraint(`unique_${modelDef.name}_${key}`, [
6353
6394
  key
6354
6395
  ]);
6355
6396
  } else {
6356
- table = table.addUniqueConstraint(`unique_${model}_${key}`, Object.keys(value));
6397
+ table = table.addUniqueConstraint(`unique_${modelDef.name}_${key}`, Object.keys(value));
6357
6398
  }
6358
6399
  }
6359
6400
  return table;
6360
6401
  }
6361
- createModelField(table, fieldName, fieldDef, modelDef) {
6362
- return table.addColumn(fieldName, this.mapFieldType(fieldDef), (col) => {
6402
+ createModelField(table, fieldDef, modelDef) {
6403
+ return table.addColumn(fieldDef.name, this.mapFieldType(fieldDef), (col) => {
6363
6404
  if (fieldDef.id && modelDef.idFields.length === 1) {
6364
6405
  col = col.primaryKey();
6365
6406
  }