@zenstackhq/runtime 3.0.0-alpha.3 → 3.0.0-alpha.31

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.
@@ -14,34 +14,130 @@ var RejectedByPolicyError = class extends Error {
14
14
  };
15
15
 
16
16
  // src/plugins/policy/policy-handler.ts
17
+ import { invariant as invariant6 } from "@zenstackhq/common-helpers";
17
18
  import { AliasNode as AliasNode3, BinaryOperationNode as BinaryOperationNode3, ColumnNode as ColumnNode2, DeleteQueryNode, FromNode as FromNode2, IdentifierNode as IdentifierNode2, InsertQueryNode, OperationNodeTransformer, OperatorNode as OperatorNode3, PrimitiveValueListNode, RawNode, ReturningNode, SelectionNode as SelectionNode2, SelectQueryNode as SelectQueryNode2, TableNode as TableNode3, UpdateQueryNode, ValueNode as ValueNode3, ValuesNode, WhereNode as WhereNode2 } from "kysely";
18
- import invariant6 from "tiny-invariant";
19
- import { match as match7 } from "ts-pattern";
19
+ import { match as match8 } from "ts-pattern";
20
20
 
21
21
  // src/client/crud/dialects/index.ts
22
- import { match as match4 } from "ts-pattern";
22
+ import { match as match5 } from "ts-pattern";
23
23
 
24
24
  // src/client/crud/dialects/postgresql.ts
25
+ import { invariant as invariant2 } from "@zenstackhq/common-helpers";
25
26
  import { sql as sql2 } from "kysely";
26
- import invariant2 from "tiny-invariant";
27
- import { match as match2 } from "ts-pattern";
27
+ import { match as match3 } from "ts-pattern";
28
+
29
+ // src/client/constants.ts
30
+ var DELEGATE_JOINED_FIELD_PREFIX = "$delegate$";
31
+ var LOGICAL_COMBINATORS = [
32
+ "AND",
33
+ "OR",
34
+ "NOT"
35
+ ];
36
+ var AGGREGATE_OPERATORS = [
37
+ "_count",
38
+ "_sum",
39
+ "_avg",
40
+ "_min",
41
+ "_max"
42
+ ];
43
+
44
+ // src/client/query-utils.ts
45
+ import { match } from "ts-pattern";
46
+
47
+ // src/schema/expression.ts
48
+ var ExpressionUtils = {
49
+ literal: /* @__PURE__ */ __name((value) => {
50
+ return {
51
+ kind: "literal",
52
+ value
53
+ };
54
+ }, "literal"),
55
+ array: /* @__PURE__ */ __name((items) => {
56
+ return {
57
+ kind: "array",
58
+ items
59
+ };
60
+ }, "array"),
61
+ call: /* @__PURE__ */ __name((functionName, args) => {
62
+ return {
63
+ kind: "call",
64
+ function: functionName,
65
+ args
66
+ };
67
+ }, "call"),
68
+ binary: /* @__PURE__ */ __name((left, op, right) => {
69
+ return {
70
+ kind: "binary",
71
+ op,
72
+ left,
73
+ right
74
+ };
75
+ }, "binary"),
76
+ unary: /* @__PURE__ */ __name((op, operand) => {
77
+ return {
78
+ kind: "unary",
79
+ op,
80
+ operand
81
+ };
82
+ }, "unary"),
83
+ field: /* @__PURE__ */ __name((field) => {
84
+ return {
85
+ kind: "field",
86
+ field
87
+ };
88
+ }, "field"),
89
+ member: /* @__PURE__ */ __name((receiver, members) => {
90
+ return {
91
+ kind: "member",
92
+ receiver,
93
+ members
94
+ };
95
+ }, "member"),
96
+ _this: /* @__PURE__ */ __name(() => {
97
+ return {
98
+ kind: "this"
99
+ };
100
+ }, "_this"),
101
+ _null: /* @__PURE__ */ __name(() => {
102
+ return {
103
+ kind: "null"
104
+ };
105
+ }, "_null"),
106
+ and: /* @__PURE__ */ __name((expr2, ...expressions) => {
107
+ return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
108
+ }, "and"),
109
+ or: /* @__PURE__ */ __name((expr2, ...expressions) => {
110
+ return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
111
+ }, "or"),
112
+ is: /* @__PURE__ */ __name((value, kind) => {
113
+ return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
114
+ }, "is"),
115
+ isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
116
+ isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
117
+ isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
118
+ isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
119
+ isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
120
+ isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
121
+ isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
122
+ isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
123
+ isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
124
+ };
28
125
 
29
126
  // src/client/errors.ts
30
127
  var QueryError = class extends Error {
31
128
  static {
32
129
  __name(this, "QueryError");
33
130
  }
34
- constructor(message) {
35
- super(message);
131
+ constructor(message, cause) {
132
+ super(message, {
133
+ cause
134
+ });
36
135
  }
37
136
  };
38
137
  var InternalError = class extends Error {
39
138
  static {
40
139
  __name(this, "InternalError");
41
140
  }
42
- constructor(message) {
43
- super(message);
44
- }
45
141
  };
46
142
 
47
143
  // src/client/query-utils.ts
@@ -52,7 +148,7 @@ __name(getModel, "getModel");
52
148
  function requireModel(schema, model) {
53
149
  const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
54
150
  if (!matchedName) {
55
- throw new QueryError(`Model "${model}" not found`);
151
+ throw new QueryError(`Model "${model}" not found in schema`);
56
152
  }
57
153
  return schema.models[matchedName];
58
154
  }
@@ -115,6 +211,16 @@ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
115
211
  }
116
212
  }
117
213
  __name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
214
+ function isRelationField(schema, model, field) {
215
+ const fieldDef = getField(schema, model, field);
216
+ return !!fieldDef?.relation;
217
+ }
218
+ __name(isRelationField, "isRelationField");
219
+ function isInheritedField(schema, model, field) {
220
+ const fieldDef = getField(schema, model, field);
221
+ return !!fieldDef?.originModel;
222
+ }
223
+ __name(isInheritedField, "isInheritedField");
118
224
  function getUniqueFields(schema, model) {
119
225
  const modelDef = requireModel(schema, model);
120
226
  const result = [];
@@ -140,20 +246,25 @@ function getUniqueFields(schema, model) {
140
246
  return result;
141
247
  }
142
248
  __name(getUniqueFields, "getUniqueFields");
143
- function buildFieldRef(schema, model, field, options, eb, modelAlias) {
249
+ function buildFieldRef(schema, model, field, options, eb, modelAlias, inlineComputedField = true) {
144
250
  const fieldDef = requireField(schema, model, field);
145
251
  if (!fieldDef.computed) {
146
252
  return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
147
253
  } else {
254
+ if (!inlineComputedField) {
255
+ return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
256
+ }
148
257
  let computer;
149
258
  if ("computedFields" in options) {
150
259
  const computedFields = options.computedFields;
151
260
  computer = computedFields?.[model]?.[field];
152
261
  }
153
262
  if (!computer) {
154
- throw new QueryError(`Computed field "${field}" implementation not provided`);
263
+ throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
155
264
  }
156
- return computer(eb);
265
+ return computer(eb, {
266
+ currentModel: modelAlias
267
+ });
157
268
  }
158
269
  }
159
270
  __name(buildFieldRef, "buildFieldRef");
@@ -196,11 +307,33 @@ function getManyToManyRelation(schema, model, field) {
196
307
  model,
197
308
  fieldDef.type
198
309
  ].sort();
310
+ let orderedFK;
311
+ if (model !== fieldDef.type) {
312
+ orderedFK = sortedModelNames[0] === model ? [
313
+ "A",
314
+ "B"
315
+ ] : [
316
+ "B",
317
+ "A"
318
+ ];
319
+ } else {
320
+ const sortedFieldNames = [
321
+ field,
322
+ oppositeFieldDef.name
323
+ ].sort();
324
+ orderedFK = sortedFieldNames[0] === field ? [
325
+ "A",
326
+ "B"
327
+ ] : [
328
+ "B",
329
+ "A"
330
+ ];
331
+ }
199
332
  return {
200
- parentFkName: sortedModelNames[0] === model ? "A" : "B",
333
+ parentFkName: orderedFK[0],
201
334
  otherModel: fieldDef.type,
202
335
  otherField: fieldDef.relation.opposite,
203
- otherFkName: sortedModelNames[0] === fieldDef.type ? "A" : "B",
336
+ otherFkName: orderedFK[1],
204
337
  joinTable: fieldDef.relation.name ? `_${fieldDef.relation.name}` : `_${sortedModelNames[0]}To${sortedModelNames[1]}`
205
338
  };
206
339
  } else {
@@ -228,11 +361,38 @@ function flattenCompoundUniqueFilters(schema, model, filter) {
228
361
  return result;
229
362
  }
230
363
  __name(flattenCompoundUniqueFilters, "flattenCompoundUniqueFilters");
364
+ function ensureArray(value) {
365
+ if (Array.isArray(value)) {
366
+ return value;
367
+ } else {
368
+ return [
369
+ value
370
+ ];
371
+ }
372
+ }
373
+ __name(ensureArray, "ensureArray");
374
+ function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */ new Set()) {
375
+ const subModels = Object.values(schema.models).filter((m) => m.baseModel === model);
376
+ subModels.forEach((def) => {
377
+ if (!collected.has(def)) {
378
+ collected.add(def);
379
+ getDelegateDescendantModels(schema, def.name, collected);
380
+ }
381
+ });
382
+ return [
383
+ ...collected
384
+ ];
385
+ }
386
+ __name(getDelegateDescendantModels, "getDelegateDescendantModels");
387
+ function aggregate(eb, expr2, op) {
388
+ return match(op).with("_count", () => eb.fn.count(expr2)).with("_sum", () => eb.fn.sum(expr2)).with("_avg", () => eb.fn.avg(expr2)).with("_min", () => eb.fn.min(expr2)).with("_max", () => eb.fn.max(expr2)).exhaustive();
389
+ }
390
+ __name(aggregate, "aggregate");
231
391
 
232
392
  // src/client/crud/dialects/base.ts
233
- import { sql } from "kysely";
234
- import invariant from "tiny-invariant";
235
- import { match, P } from "ts-pattern";
393
+ import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
394
+ import { expressionBuilder, sql } from "kysely";
395
+ import { match as match2, P } from "ts-pattern";
236
396
 
237
397
  // src/utils/enumerate.ts
238
398
  function enumerate(x) {
@@ -249,7 +409,6 @@ function enumerate(x) {
249
409
  __name(enumerate, "enumerate");
250
410
 
251
411
  // src/client/crud/dialects/base.ts
252
- import { isPlainObject } from "is-plain-object";
253
412
  var BaseCrudDialect = class {
254
413
  static {
255
414
  __name(this, "BaseCrudDialect");
@@ -260,9 +419,47 @@ var BaseCrudDialect = class {
260
419
  this.schema = schema;
261
420
  this.options = options;
262
421
  }
263
- transformPrimitive(value, _type) {
422
+ transformPrimitive(value, _type, _forArrayField) {
264
423
  return value;
265
424
  }
425
+ // #region common query builders
426
+ buildSelectModel(eb, model, modelAlias) {
427
+ const modelDef = requireModel(this.schema, model);
428
+ let result = eb.selectFrom(model === modelAlias ? model : `${model} as ${modelAlias}`);
429
+ let joinBase = modelDef.baseModel;
430
+ while (joinBase) {
431
+ result = this.buildDelegateJoin(model, modelAlias, joinBase, result);
432
+ joinBase = requireModel(this.schema, joinBase).baseModel;
433
+ }
434
+ return result;
435
+ }
436
+ buildFilterSortTake(model, args, query, modelAlias) {
437
+ let result = query;
438
+ if (args.where) {
439
+ result = result.where((eb) => this.buildFilter(eb, model, modelAlias, args?.where));
440
+ }
441
+ let negateOrderBy = false;
442
+ const skip = args.skip;
443
+ let take = args.take;
444
+ if (take !== void 0 && take < 0) {
445
+ negateOrderBy = true;
446
+ take = -take;
447
+ }
448
+ result = this.buildSkipTake(result, skip, take);
449
+ result = this.buildOrderBy(result, model, modelAlias, args.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
450
+ if ("distinct" in args && args.distinct) {
451
+ const distinct = ensureArray(args.distinct);
452
+ if (this.supportsDistinctOn) {
453
+ result = result.distinctOn(distinct.map((f) => sql.ref(`${modelAlias}.${f}`)));
454
+ } else {
455
+ throw new QueryError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
456
+ }
457
+ }
458
+ if (args.cursor) {
459
+ result = this.buildCursorFilter(model, result, args.cursor, args.orderBy, negateOrderBy, modelAlias);
460
+ }
461
+ return result;
462
+ }
266
463
  buildFilter(eb, model, modelAlias, where) {
267
464
  if (where === true || where === void 0) {
268
465
  return this.true(eb);
@@ -279,17 +476,20 @@ var BaseCrudDialect = class {
279
476
  if (key.startsWith("$")) {
280
477
  continue;
281
478
  }
282
- if (key === "AND" || key === "OR" || key === "NOT") {
479
+ if (this.isLogicalCombinator(key)) {
283
480
  result = this.and(eb, result, this.buildCompositeFilter(eb, model, modelAlias, key, payload));
284
481
  continue;
285
482
  }
286
483
  const fieldDef = requireField(this.schema, model, key);
287
484
  if (fieldDef.relation) {
288
485
  result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
289
- } else if (fieldDef.array) {
290
- result = this.and(eb, result, this.buildArrayFilter(eb, model, modelAlias, key, fieldDef, payload));
291
486
  } else {
292
- result = this.and(eb, result, this.buildPrimitiveFilter(eb, model, modelAlias, key, fieldDef, payload));
487
+ const fieldRef = this.fieldRef(fieldDef.originModel ?? model, key, eb, fieldDef.originModel ?? modelAlias);
488
+ if (fieldDef.array) {
489
+ result = this.and(eb, result, this.buildArrayFilter(eb, fieldRef, fieldDef, payload));
490
+ } else {
491
+ result = this.and(eb, result, this.buildPrimitiveFilter(eb, fieldRef, fieldDef, payload));
492
+ }
293
493
  }
294
494
  }
295
495
  if ("$expr" in _where && typeof _where["$expr"] === "function") {
@@ -297,8 +497,32 @@ var BaseCrudDialect = class {
297
497
  }
298
498
  return result;
299
499
  }
500
+ buildCursorFilter(model, query, cursor, orderBy, negateOrderBy, modelAlias) {
501
+ const _orderBy = orderBy ?? makeDefaultOrderBy(this.schema, model);
502
+ const orderByItems = ensureArray(_orderBy).flatMap((obj) => Object.entries(obj));
503
+ const eb = expressionBuilder();
504
+ const subQueryAlias = `${model}$cursor$sub`;
505
+ const cursorFilter = this.buildFilter(eb, model, subQueryAlias, cursor);
506
+ let result = query;
507
+ const filters = [];
508
+ for (let i = orderByItems.length - 1; i >= 0; i--) {
509
+ const andFilters = [];
510
+ for (let j = 0; j <= i; j++) {
511
+ const [field, order] = orderByItems[j];
512
+ const _order = negateOrderBy ? order === "asc" ? "desc" : "asc" : order;
513
+ const op = j === i ? _order === "asc" ? ">=" : "<=" : "=";
514
+ andFilters.push(eb(eb.ref(`${modelAlias}.${field}`), op, this.buildSelectModel(eb, model, subQueryAlias).select(`${subQueryAlias}.${field}`).where(cursorFilter)));
515
+ }
516
+ filters.push(eb.and(andFilters));
517
+ }
518
+ result = result.where((eb2) => eb2.or(filters));
519
+ return result;
520
+ }
521
+ isLogicalCombinator(key) {
522
+ return LOGICAL_COMBINATORS.includes(key);
523
+ }
300
524
  buildCompositeFilter(eb, model, modelAlias, key, payload) {
301
- return match(key).with("AND", () => this.and(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("OR", () => this.or(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("NOT", () => eb.not(this.buildCompositeFilter(eb, model, modelAlias, "AND", payload))).exhaustive();
525
+ return match2(key).with("AND", () => this.and(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("OR", () => this.or(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("NOT", () => eb.not(this.buildCompositeFilter(eb, model, modelAlias, "AND", payload))).exhaustive();
302
526
  }
303
527
  buildRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
304
528
  if (!fieldDef.array) {
@@ -307,19 +531,26 @@ var BaseCrudDialect = class {
307
531
  return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
308
532
  }
309
533
  }
310
- buildToOneRelationFilter(eb, model, table, field, fieldDef, payload) {
534
+ buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
311
535
  if (payload === null) {
312
536
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
313
- if (ownedByModel) {
314
- return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${table}.${fk}`), "is", null)));
537
+ if (ownedByModel && !fieldDef.originModel) {
538
+ return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${modelAlias}.${fk}`), "is", null)));
315
539
  } else {
316
- return this.buildToOneRelationFilter(eb, model, table, field, fieldDef, {
540
+ return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
317
541
  is: null
318
542
  });
319
543
  }
320
544
  }
321
- const joinAlias = `${table}$${field}`;
322
- const joinPairs = buildJoinPairs(this.schema, model, table, field, joinAlias);
545
+ const joinAlias = `${modelAlias}$${field}`;
546
+ const joinPairs = buildJoinPairs(
547
+ this.schema,
548
+ model,
549
+ // if field is from a base, use the base model to join
550
+ fieldDef.originModel ?? modelAlias,
551
+ field,
552
+ joinAlias
553
+ );
323
554
  const filterResultField = `${field}$filter`;
324
555
  const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
325
556
  const conditions = [];
@@ -349,25 +580,26 @@ var BaseCrudDialect = class {
349
580
  }
350
581
  return this.and(eb, ...conditions);
351
582
  }
352
- buildToManyRelationFilter(eb, model, table, field, fieldDef, payload) {
583
+ buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
353
584
  if (payload === null) {
354
- return eb(sql.ref(`${table}.${field}`), "is", null);
585
+ return eb(sql.ref(`${modelAlias}.${field}`), "is", null);
355
586
  }
356
587
  const relationModel = fieldDef.type;
588
+ const relationFilterSelectAlias = `${modelAlias}$${field}$filter`;
357
589
  const buildPkFkWhereRefs = /* @__PURE__ */ __name((eb2) => {
358
590
  const m2m = getManyToManyRelation(this.schema, model, field);
359
591
  if (m2m) {
360
592
  const modelIdField = getIdFields(this.schema, model)[0];
361
593
  const relationIdField = getIdFields(this.schema, relationModel)[0];
362
- return eb2(sql.ref(`${relationModel}.${relationIdField}`), "in", eb2.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(sql.ref(`${m2m.joinTable}.${m2m.parentFkName}`), "=", sql.ref(`${table}.${modelIdField}`)));
594
+ return eb2(sql.ref(`${relationFilterSelectAlias}.${relationIdField}`), "in", eb2.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(sql.ref(`${m2m.joinTable}.${m2m.parentFkName}`), "=", sql.ref(`${modelAlias}.${modelIdField}`)));
363
595
  } else {
364
596
  const relationKeyPairs = getRelationForeignKeyFieldPairs(this.schema, model, field);
365
597
  let result2 = this.true(eb2);
366
598
  for (const { fk, pk } of relationKeyPairs.keyPairs) {
367
599
  if (relationKeyPairs.ownedByModel) {
368
- result2 = this.and(eb2, result2, eb2(sql.ref(`${table}.${fk}`), "=", sql.ref(`${relationModel}.${pk}`)));
600
+ result2 = this.and(eb2, result2, eb2(sql.ref(`${modelAlias}.${fk}`), "=", sql.ref(`${relationFilterSelectAlias}.${pk}`)));
369
601
  } else {
370
- result2 = this.and(eb2, result2, eb2(sql.ref(`${table}.${pk}`), "=", sql.ref(`${relationModel}.${fk}`)));
602
+ result2 = this.and(eb2, result2, eb2(sql.ref(`${modelAlias}.${pk}`), "=", sql.ref(`${relationFilterSelectAlias}.${fk}`)));
371
603
  }
372
604
  }
373
605
  return result2;
@@ -380,30 +612,29 @@ var BaseCrudDialect = class {
380
612
  }
381
613
  switch (key) {
382
614
  case "some": {
383
- result = this.and(eb, result, eb(eb.selectFrom(relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), ">", 0));
615
+ 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));
384
616
  break;
385
617
  }
386
618
  case "every": {
387
- result = this.and(eb, result, eb(eb.selectFrom(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));
619
+ 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));
388
620
  break;
389
621
  }
390
622
  case "none": {
391
- result = this.and(eb, result, eb(eb.selectFrom(relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), "=", 0));
623
+ 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));
392
624
  break;
393
625
  }
394
626
  }
395
627
  }
396
628
  return result;
397
629
  }
398
- buildArrayFilter(eb, model, modelAlias, field, fieldDef, payload) {
630
+ buildArrayFilter(eb, fieldRef, fieldDef, payload) {
399
631
  const clauses = [];
400
632
  const fieldType = fieldDef.type;
401
- const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
402
633
  for (const [key, _value] of Object.entries(payload)) {
403
634
  if (_value === void 0) {
404
635
  continue;
405
636
  }
406
- const value = this.transformPrimitive(_value, fieldType);
637
+ const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
407
638
  switch (key) {
408
639
  case "equals": {
409
640
  clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
@@ -434,19 +665,23 @@ var BaseCrudDialect = class {
434
665
  }
435
666
  return this.and(eb, ...clauses);
436
667
  }
437
- buildPrimitiveFilter(eb, model, modelAlias, field, fieldDef, payload) {
668
+ buildPrimitiveFilter(eb, fieldRef, fieldDef, payload) {
438
669
  if (payload === null) {
439
- return eb(sql.ref(`${modelAlias}.${field}`), "is", null);
670
+ return eb(fieldRef, "is", null);
440
671
  }
441
672
  if (isEnum(this.schema, fieldDef.type)) {
442
- return this.buildEnumFilter(eb, modelAlias, field, fieldDef, payload);
673
+ return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
443
674
  }
444
- return match(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, model, modelAlias, field, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, modelAlias, field, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, modelAlias, field, payload)).with("Bytes", () => this.buildBytesFilter(eb, modelAlias, field, payload)).exhaustive();
675
+ return match2(fieldDef.type).with("String", () => this.buildStringFilter(eb, fieldRef, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, fieldRef, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, fieldRef, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, fieldRef, payload)).with("Bytes", () => this.buildBytesFilter(eb, fieldRef, payload)).with("Json", () => {
676
+ throw new InternalError("JSON filters are not supported yet");
677
+ }).with("Unsupported", () => {
678
+ throw new QueryError(`Unsupported field cannot be used in filters`);
679
+ }).exhaustive();
445
680
  }
446
681
  buildLiteralFilter(eb, lhs, type, rhs) {
447
- return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
682
+ return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
448
683
  }
449
- buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
684
+ buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
450
685
  if (payload === null || !isPlainObject(payload)) {
451
686
  return {
452
687
  conditions: [
@@ -461,8 +696,11 @@ var BaseCrudDialect = class {
461
696
  if (onlyForKeys && !onlyForKeys.includes(op)) {
462
697
  continue;
463
698
  }
699
+ if (excludeKeys.includes(op)) {
700
+ continue;
701
+ }
464
702
  const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
465
- const condition = match(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
703
+ const condition = match2(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
466
704
  invariant(Array.isArray(rhs), "right hand side must be an array");
467
705
  if (rhs.length === 0) {
468
706
  return this.false(eb);
@@ -476,7 +714,11 @@ var BaseCrudDialect = class {
476
714
  } else {
477
715
  return eb.not(eb(lhs, "in", rhs));
478
716
  }
479
- }).with("lt", () => eb(lhs, "<", rhs)).with("lte", () => eb(lhs, "<=", rhs)).with("gt", () => eb(lhs, ">", rhs)).with("gte", () => eb(lhs, ">=", rhs)).with("not", () => eb.not(recurse(value))).otherwise(() => {
717
+ }).with("lt", () => eb(lhs, "<", rhs)).with("lte", () => eb(lhs, "<=", rhs)).with("gt", () => eb(lhs, ">", rhs)).with("gte", () => eb(lhs, ">=", rhs)).with("not", () => eb.not(recurse(value))).with(P.union(...AGGREGATE_OPERATORS), (op2) => {
718
+ const innerResult = this.buildStandardFilter(eb, type, value, aggregate(eb, lhs, op2), getRhs, recurse, throwIfInvalid);
719
+ consumedKeys.push(...innerResult.consumedKeys);
720
+ return this.and(eb, ...innerResult.conditions);
721
+ }).otherwise(() => {
480
722
  if (throwIfInvalid) {
481
723
  throw new QueryError(`Invalid filter key: ${op}`);
482
724
  } else {
@@ -493,24 +735,21 @@ var BaseCrudDialect = class {
493
735
  consumedKeys
494
736
  };
495
737
  }
496
- buildStringFilter(eb, table, field, payload) {
497
- const fieldDef = getField(this.schema, table, field);
498
- let fieldRef = fieldDef?.computed ? sql.ref(field) : sql.ref(`${table}.${field}`);
499
- let insensitive = false;
500
- if (payload && typeof payload === "object" && "mode" in payload && payload.mode === "insensitive") {
501
- insensitive = true;
502
- fieldRef = eb.fn("lower", [
503
- fieldRef
504
- ]);
738
+ buildStringFilter(eb, fieldRef, payload) {
739
+ let mode;
740
+ if (payload && typeof payload === "object" && "mode" in payload) {
741
+ mode = payload.mode;
505
742
  }
506
- const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => this.prepStringCasing(eb, value, insensitive), (value) => this.buildStringFilter(eb, table, field, value));
743
+ const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, mode === "insensitive" ? eb.fn("lower", [
744
+ fieldRef
745
+ ]) : fieldRef, (value) => this.prepStringCasing(eb, value, mode), (value) => this.buildStringFilter(eb, fieldRef, value));
507
746
  if (payload && typeof payload === "object") {
508
747
  for (const [key, value] of Object.entries(payload)) {
509
748
  if (key === "mode" || consumedKeys.includes(key)) {
510
749
  continue;
511
750
  }
512
- const condition = match(key).with("contains", () => insensitive ? eb(fieldRef, "ilike", sql.lit(`%${value}%`)) : eb(fieldRef, "like", sql.lit(`%${value}%`))).with("startsWith", () => insensitive ? eb(fieldRef, "ilike", sql.lit(`${value}%`)) : eb(fieldRef, "like", sql.lit(`${value}%`))).with("endsWith", () => insensitive ? eb(fieldRef, "ilike", sql.lit(`%${value}`)) : eb(fieldRef, "like", sql.lit(`%${value}`))).otherwise(() => {
513
- throw new Error(`Invalid string filter key: ${key}`);
751
+ const condition = match2(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`%${value}%`)) : eb(fieldRef, "like", sql.val(`%${value}%`))).with("startsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`${value}%`)) : eb(fieldRef, "like", sql.val(`${value}%`))).with("endsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`%${value}`)) : eb(fieldRef, "like", sql.val(`%${value}`))).otherwise(() => {
752
+ throw new QueryError(`Invalid string filter key: ${key}`);
514
753
  });
515
754
  if (condition) {
516
755
  conditions.push(condition);
@@ -519,34 +758,37 @@ var BaseCrudDialect = class {
519
758
  }
520
759
  return this.and(eb, ...conditions);
521
760
  }
522
- prepStringCasing(eb, value, toLower = true) {
761
+ prepStringCasing(eb, value, mode) {
762
+ if (!mode || mode === "default") {
763
+ return value === null ? value : sql.val(value);
764
+ }
523
765
  if (typeof value === "string") {
524
- return toLower ? eb.fn("lower", [
525
- sql.lit(value)
526
- ]) : sql.lit(value);
766
+ return eb.fn("lower", [
767
+ sql.val(value)
768
+ ]);
527
769
  } else if (Array.isArray(value)) {
528
- return value.map((v) => this.prepStringCasing(eb, v, toLower));
770
+ return value.map((v) => this.prepStringCasing(eb, v, mode));
529
771
  } else {
530
- return value === null ? null : sql.lit(value);
772
+ return value === null ? null : sql.val(value);
531
773
  }
532
774
  }
533
- buildNumberFilter(eb, model, table, field, type, payload) {
534
- const { conditions } = this.buildStandardFilter(eb, type, payload, buildFieldRef(this.schema, model, field, this.options, eb), (value) => this.transformPrimitive(value, type), (value) => this.buildNumberFilter(eb, model, table, field, type, value));
775
+ buildNumberFilter(eb, fieldRef, type, payload) {
776
+ const { conditions } = this.buildStandardFilter(eb, type, payload, fieldRef, (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, fieldRef, type, value));
535
777
  return this.and(eb, ...conditions);
536
778
  }
537
- buildBooleanFilter(eb, table, field, payload) {
538
- const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean"), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
779
+ buildBooleanFilter(eb, fieldRef, payload) {
780
+ const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, fieldRef, (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, fieldRef, value), true, [
539
781
  "equals",
540
782
  "not"
541
783
  ]);
542
784
  return this.and(eb, ...conditions);
543
785
  }
544
- buildDateTimeFilter(eb, table, field, payload) {
545
- const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime"), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
786
+ buildDateTimeFilter(eb, fieldRef, payload) {
787
+ const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, fieldRef, (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, fieldRef, value), true);
546
788
  return this.and(eb, ...conditions);
547
789
  }
548
- buildBytesFilter(eb, table, field, payload) {
549
- const conditions = this.buildStandardFilter(eb, "Bytes", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes"), (value) => this.buildBytesFilter(eb, table, field, value), true, [
790
+ buildBytesFilter(eb, fieldRef, payload) {
791
+ const conditions = this.buildStandardFilter(eb, "Bytes", payload, fieldRef, (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, fieldRef, value), true, [
550
792
  "equals",
551
793
  "in",
552
794
  "notIn",
@@ -554,8 +796,8 @@ var BaseCrudDialect = class {
554
796
  ]);
555
797
  return this.and(eb, ...conditions.conditions);
556
798
  }
557
- buildEnumFilter(eb, table, field, fieldDef, payload) {
558
- const conditions = this.buildStandardFilter(eb, "String", payload, sql.ref(`${table}.${field}`), (value) => value, (value) => this.buildEnumFilter(eb, table, field, fieldDef, value), true, [
799
+ buildEnumFilter(eb, fieldRef, fieldDef, payload) {
800
+ const conditions = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => value, (value) => this.buildEnumFilter(eb, fieldRef, fieldDef, value), true, [
559
801
  "equals",
560
802
  "in",
561
803
  "notIn",
@@ -587,9 +829,7 @@ var BaseCrudDialect = class {
587
829
  invariant(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
588
830
  for (const [k, v] of Object.entries(value)) {
589
831
  invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
590
- result = result.orderBy((eb) => eb.fn(field.slice(1), [
591
- sql.ref(k)
592
- ]), sql.raw(this.negateSort(v, negated)));
832
+ result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field), sql.raw(this.negateSort(v, negated)));
593
833
  }
594
834
  continue;
595
835
  }
@@ -598,7 +838,7 @@ var BaseCrudDialect = class {
598
838
  invariant(value && typeof value === "object", 'invalid orderBy value for field "_count"');
599
839
  for (const [k, v] of Object.entries(value)) {
600
840
  invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
601
- result = result.orderBy((eb) => eb.fn.count(sql.ref(k)), sql.raw(this.negateSort(v, negated)));
841
+ result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), sql.raw(this.negateSort(v, negated)));
602
842
  }
603
843
  continue;
604
844
  }
@@ -607,10 +847,11 @@ var BaseCrudDialect = class {
607
847
  }
608
848
  const fieldDef = requireField(this.schema, model, field);
609
849
  if (!fieldDef.relation) {
850
+ const fieldRef = this.fieldRef(model, field, expressionBuilder(), modelAlias);
610
851
  if (value === "asc" || value === "desc") {
611
- result = result.orderBy(sql.ref(`${modelAlias}.${field}`), this.negateSort(value, negated));
852
+ result = result.orderBy(fieldRef, this.negateSort(value, negated));
612
853
  } else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
613
- result = result.orderBy(sql.ref(`${modelAlias}.${field}`), sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
854
+ result = result.orderBy(fieldRef, sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
614
855
  }
615
856
  } else {
616
857
  const relationModel = fieldDef.type;
@@ -622,8 +863,9 @@ var BaseCrudDialect = class {
622
863
  invariant(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
623
864
  const sort = this.negateSort(value._count, negated);
624
865
  result = result.orderBy((eb) => {
625
- let subQuery = eb.selectFrom(relationModel);
626
- const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
866
+ const subQueryAlias = `${modelAlias}$orderBy$${field}$count`;
867
+ let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
868
+ const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, subQueryAlias);
627
869
  subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right)))));
628
870
  subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
629
871
  return subQuery;
@@ -641,14 +883,90 @@ var BaseCrudDialect = class {
641
883
  });
642
884
  return result;
643
885
  }
886
+ buildSelectAllFields(model, query, omit, modelAlias) {
887
+ const modelDef = requireModel(this.schema, model);
888
+ let result = query;
889
+ for (const field of Object.keys(modelDef.fields)) {
890
+ if (isRelationField(this.schema, model, field)) {
891
+ continue;
892
+ }
893
+ if (omit?.[field] === true) {
894
+ continue;
895
+ }
896
+ result = this.buildSelectField(result, model, modelAlias, field);
897
+ }
898
+ const descendants = getDelegateDescendantModels(this.schema, model);
899
+ for (const subModel of descendants) {
900
+ result = this.buildDelegateJoin(model, modelAlias, subModel.name, result);
901
+ result = result.select((eb) => {
902
+ const jsonObject = {};
903
+ for (const field of Object.keys(subModel.fields)) {
904
+ if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
905
+ continue;
906
+ }
907
+ jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
908
+ }
909
+ return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
910
+ });
911
+ }
912
+ return result;
913
+ }
914
+ buildSelectField(query, model, modelAlias, field) {
915
+ const fieldDef = requireField(this.schema, model, field);
916
+ if (fieldDef.computed) {
917
+ return query.select((eb) => this.fieldRef(model, field, eb, modelAlias).as(field));
918
+ } else if (!fieldDef.originModel) {
919
+ return query.select(sql.ref(`${modelAlias}.${field}`).as(field));
920
+ } else {
921
+ return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
922
+ }
923
+ }
924
+ buildDelegateJoin(thisModel, thisModelAlias, otherModelAlias, query) {
925
+ const idFields = getIdFields(this.schema, thisModel);
926
+ query = query.leftJoin(otherModelAlias, (qb) => {
927
+ for (const idField of idFields) {
928
+ qb = qb.onRef(`${thisModelAlias}.${idField}`, "=", `${otherModelAlias}.${idField}`);
929
+ }
930
+ return qb;
931
+ });
932
+ return query;
933
+ }
934
+ buildCountJson(model, eb, parentAlias, payload) {
935
+ const modelDef = requireModel(this.schema, model);
936
+ const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
937
+ const selections = payload === true ? {
938
+ select: toManyRelations.reduce((acc, [field]) => {
939
+ acc[field] = true;
940
+ return acc;
941
+ }, {})
942
+ } : payload;
943
+ const jsonObject = {};
944
+ for (const [field, value] of Object.entries(selections.select)) {
945
+ const fieldDef = requireField(this.schema, model, field);
946
+ const fieldModel = fieldDef.type;
947
+ const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
948
+ let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
949
+ for (const [left, right] of joinPairs) {
950
+ fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
951
+ }
952
+ if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
953
+ const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
954
+ fieldCountQuery = fieldCountQuery.where(filter);
955
+ }
956
+ jsonObject[field] = fieldCountQuery;
957
+ }
958
+ return this.buildJsonObject(eb, jsonObject);
959
+ }
960
+ // #endregion
961
+ // #region utils
644
962
  negateSort(sort, negated) {
645
963
  return negated ? sort === "asc" ? "desc" : "asc" : sort;
646
964
  }
647
965
  true(eb) {
648
- return eb.lit(this.transformPrimitive(true, "Boolean"));
966
+ return eb.lit(this.transformPrimitive(true, "Boolean", false));
649
967
  }
650
968
  false(eb) {
651
- return eb.lit(this.transformPrimitive(false, "Boolean"));
969
+ return eb.lit(this.transformPrimitive(false, "Boolean", false));
652
970
  }
653
971
  isTrue(expression) {
654
972
  const node = expression.toOperationNode();
@@ -687,6 +1005,9 @@ var BaseCrudDialect = class {
687
1005
  not(eb, ...args) {
688
1006
  return eb.not(this.and(eb, ...args));
689
1007
  }
1008
+ fieldRef(model, field, eb, modelAlias, inlineComputedField = true) {
1009
+ return buildFieldRef(this.schema, model, field, this.options, eb, modelAlias, inlineComputedField);
1010
+ }
690
1011
  };
691
1012
 
692
1013
  // src/client/crud/dialects/postgresql.ts
@@ -697,14 +1018,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
697
1018
  get provider() {
698
1019
  return "postgresql";
699
1020
  }
700
- transformPrimitive(value, type) {
1021
+ transformPrimitive(value, type, forArrayField) {
701
1022
  if (value === void 0) {
702
1023
  return value;
703
1024
  }
704
1025
  if (Array.isArray(value)) {
705
- return value.map((v) => this.transformPrimitive(v, type));
1026
+ if (type === "Json" && !forArrayField) {
1027
+ return JSON.stringify(value);
1028
+ } else {
1029
+ return value.map((v) => this.transformPrimitive(v, type, false));
1030
+ }
706
1031
  } else {
707
- return match2(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).otherwise(() => value);
1032
+ return match3(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
708
1033
  }
709
1034
  }
710
1035
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
@@ -717,21 +1042,12 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
717
1042
  return qb.leftJoinLateral((eb) => {
718
1043
  const joinTableName = `${parentName}$${relationField}`;
719
1044
  let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
1045
+ const subQueryAlias = `${relationModel}$${relationField}$sub`;
720
1046
  result = eb.selectFrom(() => {
721
- let subQuery = eb.selectFrom(`${relationModel}`).selectAll();
1047
+ let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
1048
+ subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0, subQueryAlias);
722
1049
  if (payload && typeof payload === "object") {
723
- if (payload.where) {
724
- subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
725
- }
726
- const skip = payload.skip;
727
- let take = payload.take;
728
- let negateOrderBy = false;
729
- if (take !== void 0 && take < 0) {
730
- negateOrderBy = true;
731
- take = -take;
732
- }
733
- subQuery = this.buildSkipTake(subQuery, skip, take);
734
- subQuery = this.buildOrderBy(subQuery, relationModel, relationModel, payload.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
1050
+ subQuery = this.buildFilterSortTake(relationModel, payload, subQuery, subQueryAlias);
735
1051
  }
736
1052
  const m2m = getManyToManyRelation(this.schema, model, relationField);
737
1053
  if (m2m) {
@@ -739,21 +1055,21 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
739
1055
  const relationIds = getIdFields(this.schema, relationModel);
740
1056
  invariant2(parentIds.length === 1, "many-to-many relation must have exactly one id field");
741
1057
  invariant2(relationIds.length === 1, "many-to-many relation must have exactly one id field");
742
- 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}`)));
1058
+ 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}`)));
743
1059
  } else {
744
- const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField, relationModel);
1060
+ const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField, subQueryAlias);
745
1061
  subQuery = subQuery.where((eb2) => this.and(eb2, ...joinPairs.map(([left, right]) => eb2(sql2.ref(left), "=", sql2.ref(right)))));
746
1062
  }
747
1063
  return subQuery.as(joinTableName);
748
1064
  });
749
- result = this.buildRelationObjectSelect(relationModel, relationField, relationFieldDef, result, payload, parentName);
1065
+ result = this.buildRelationObjectSelect(relationModel, joinTableName, relationField, relationFieldDef, result, payload, parentName);
750
1066
  result = this.buildRelationJoins(relationModel, relationField, result, payload, parentName);
751
1067
  return result.as(joinTableName);
752
1068
  }, (join) => join.onTrue());
753
1069
  }
754
- buildRelationObjectSelect(relationModel, relationField, relationFieldDef, qb, payload, parentName) {
1070
+ buildRelationObjectSelect(relationModel, relationModelAlias, relationField, relationFieldDef, qb, payload, parentName) {
755
1071
  qb = qb.select((eb) => {
756
- const objArgs = this.buildRelationObjectArgs(relationModel, relationField, eb, payload, parentName);
1072
+ const objArgs = this.buildRelationObjectArgs(relationModel, relationModelAlias, relationField, eb, payload, parentName);
757
1073
  if (relationFieldDef.array) {
758
1074
  return eb.fn.coalesce(sql2`jsonb_agg(jsonb_build_object(${sql2.join(objArgs)}))`, sql2`'[]'::jsonb`).as("$j");
759
1075
  } else {
@@ -762,34 +1078,57 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
762
1078
  });
763
1079
  return qb;
764
1080
  }
765
- buildRelationObjectArgs(relationModel, relationField, eb, payload, parentName) {
1081
+ buildRelationObjectArgs(relationModel, relationModelAlias, relationField, eb, payload, parentAlias) {
766
1082
  const relationModelDef = requireModel(this.schema, relationModel);
767
1083
  const objArgs = [];
1084
+ const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
1085
+ if (descendantModels.length > 0) {
1086
+ objArgs.push(...descendantModels.map((subModel) => [
1087
+ sql2.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1088
+ eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
1089
+ ]).flatMap((v) => v));
1090
+ }
768
1091
  if (payload === true || !payload.select) {
769
1092
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
770
1093
  sql2.lit(field),
771
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
1094
+ this.fieldRef(relationModel, field, eb, relationModelAlias, false)
772
1095
  ]).flatMap((v) => v));
773
1096
  } else if (payload.select) {
774
- objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => [
775
- sql2.lit(field),
776
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
777
- ]).flatMap((v) => v));
1097
+ objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
1098
+ if (field === "_count") {
1099
+ const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
1100
+ return [
1101
+ sql2.lit(field),
1102
+ subJson
1103
+ ];
1104
+ } else {
1105
+ const fieldDef = requireField(this.schema, relationModel, field);
1106
+ const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : this.fieldRef(relationModel, field, eb, void 0, false);
1107
+ return [
1108
+ sql2.lit(field),
1109
+ fieldValue
1110
+ ];
1111
+ }
1112
+ }).flatMap((v) => v));
778
1113
  }
779
1114
  if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
780
1115
  objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
781
1116
  sql2.lit(field),
782
- eb.ref(`${parentName}$${relationField}$${field}.$j`)
1117
+ // reference the synthesized JSON field
1118
+ eb.ref(`${parentAlias}$${relationField}$${field}.$j`)
783
1119
  ]).flatMap((v) => v));
784
1120
  }
785
1121
  return objArgs;
786
1122
  }
787
- buildRelationJoins(model, relationField, qb, payload, parentName) {
1123
+ buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
788
1124
  let result = qb;
789
- if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
790
- Object.entries(payload.include).filter(([, value]) => value).forEach(([field, value]) => {
791
- result = this.buildRelationJSON(model, result, field, `${parentName}$${relationField}`, value);
792
- });
1125
+ if (typeof payload === "object") {
1126
+ const selectInclude = payload.include ?? payload.select;
1127
+ if (selectInclude && typeof selectInclude === "object") {
1128
+ Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
1129
+ result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
1130
+ });
1131
+ }
793
1132
  }
794
1133
  return result;
795
1134
  }
@@ -829,12 +1168,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
829
1168
  return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
830
1169
  }
831
1170
  }
1171
+ get supportInsertWithDefault() {
1172
+ return true;
1173
+ }
832
1174
  };
833
1175
 
834
1176
  // src/client/crud/dialects/sqlite.ts
1177
+ import { invariant as invariant3 } from "@zenstackhq/common-helpers";
835
1178
  import { sql as sql3 } from "kysely";
836
- import invariant3 from "tiny-invariant";
837
- import { match as match3 } from "ts-pattern";
1179
+ import { match as match4 } from "ts-pattern";
838
1180
  var SqliteCrudDialect = class extends BaseCrudDialect {
839
1181
  static {
840
1182
  __name(this, "SqliteCrudDialect");
@@ -842,39 +1184,34 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
842
1184
  get provider() {
843
1185
  return "sqlite";
844
1186
  }
845
- transformPrimitive(value, type) {
1187
+ transformPrimitive(value, type, _forArrayField) {
846
1188
  if (value === void 0) {
847
1189
  return value;
848
1190
  }
849
1191
  if (Array.isArray(value)) {
850
- return value.map((v) => this.transformPrimitive(v, type));
1192
+ return value.map((v) => this.transformPrimitive(v, type, false));
851
1193
  } else {
852
- return match3(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).otherwise(() => value);
1194
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
1195
+ return JSON.stringify(value);
1196
+ } else {
1197
+ return match4(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).with("Json", () => JSON.stringify(value)).otherwise(() => value);
1198
+ }
853
1199
  }
854
1200
  }
855
1201
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
856
1202
  return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
857
1203
  }
858
- buildRelationJSON(model, eb, relationField, parentName, payload) {
1204
+ buildRelationJSON(model, eb, relationField, parentAlias, payload) {
859
1205
  const relationFieldDef = requireField(this.schema, model, relationField);
860
1206
  const relationModel = relationFieldDef.type;
861
1207
  const relationModelDef = requireModel(this.schema, relationModel);
862
- const subQueryName = `${parentName}$${relationField}`;
1208
+ const subQueryName = `${parentAlias}$${relationField}`;
863
1209
  let tbl = eb.selectFrom(() => {
864
- let subQuery = eb.selectFrom(relationModel).selectAll();
1210
+ const subQueryAlias = `${parentAlias}$${relationField}$sub`;
1211
+ let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
1212
+ subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0, subQueryAlias);
865
1213
  if (payload && typeof payload === "object") {
866
- if (payload.where) {
867
- subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
868
- }
869
- const skip = payload.skip;
870
- let take = payload.take;
871
- let negateOrderBy = false;
872
- if (take !== void 0 && take < 0) {
873
- negateOrderBy = true;
874
- take = -take;
875
- }
876
- subQuery = this.buildSkipTake(subQuery, skip, take);
877
- subQuery = this.buildOrderBy(subQuery, relationModel, relationModel, payload.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
1214
+ subQuery = this.buildFilterSortTake(relationModel, payload, subQuery, subQueryAlias);
878
1215
  }
879
1216
  const m2m = getManyToManyRelation(this.schema, model, relationField);
880
1217
  if (m2m) {
@@ -882,14 +1219,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
882
1219
  const relationIds = getIdFields(this.schema, relationModel);
883
1220
  invariant3(parentIds.length === 1, "many-to-many relation must have exactly one id field");
884
1221
  invariant3(relationIds.length === 1, "many-to-many relation must have exactly one id field");
885
- 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}`)));
1222
+ 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}`)));
886
1223
  } else {
887
1224
  const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
888
1225
  keyPairs.forEach(({ fk, pk }) => {
889
1226
  if (ownedByModel) {
890
- subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentName}.${fk}`);
1227
+ subQuery = subQuery.whereRef(`${subQueryAlias}.${pk}`, "=", `${parentAlias}.${fk}`);
891
1228
  } else {
892
- subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentName}.${pk}`);
1229
+ subQuery = subQuery.whereRef(`${subQueryAlias}.${fk}`, "=", `${parentAlias}.${pk}`);
893
1230
  }
894
1231
  });
895
1232
  }
@@ -897,31 +1234,46 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
897
1234
  });
898
1235
  tbl = tbl.select(() => {
899
1236
  const objArgs = [];
1237
+ const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
1238
+ if (descendantModels.length > 0) {
1239
+ objArgs.push(...descendantModels.map((subModel) => [
1240
+ sql3.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1241
+ eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
1242
+ ]).flatMap((v) => v));
1243
+ }
900
1244
  if (payload === true || !payload.select) {
901
1245
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
902
1246
  sql3.lit(field),
903
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
1247
+ this.fieldRef(relationModel, field, eb, void 0, false)
904
1248
  ]).flatMap((v) => v));
905
1249
  } else if (payload.select) {
906
1250
  objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
907
- const fieldDef = requireField(this.schema, relationModel, field);
908
- if (fieldDef.relation) {
909
- const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
1251
+ if (field === "_count") {
1252
+ const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
910
1253
  return [
911
1254
  sql3.lit(field),
912
1255
  subJson
913
1256
  ];
914
1257
  } else {
915
- return [
916
- sql3.lit(field),
917
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
918
- ];
1258
+ const fieldDef = requireField(this.schema, relationModel, field);
1259
+ if (fieldDef.relation) {
1260
+ const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
1261
+ return [
1262
+ sql3.lit(field),
1263
+ subJson
1264
+ ];
1265
+ } else {
1266
+ return [
1267
+ sql3.lit(field),
1268
+ this.fieldRef(relationModel, field, eb, void 0, false)
1269
+ ];
1270
+ }
919
1271
  }
920
1272
  }).flatMap((v) => v));
921
1273
  }
922
1274
  if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
923
1275
  objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
924
- const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
1276
+ const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
925
1277
  return [
926
1278
  sql3.lit(field),
927
1279
  subJson
@@ -971,93 +1323,17 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
971
1323
  buildArrayLiteralSQL(_values) {
972
1324
  throw new Error("SQLite does not support array literals");
973
1325
  }
1326
+ get supportInsertWithDefault() {
1327
+ return false;
1328
+ }
974
1329
  };
975
1330
 
976
1331
  // src/client/crud/dialects/index.ts
977
1332
  function getCrudDialect(schema, options) {
978
- return match4(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
1333
+ return match5(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
979
1334
  }
980
1335
  __name(getCrudDialect, "getCrudDialect");
981
1336
 
982
- // src/schema/expression.ts
983
- var ExpressionUtils = {
984
- literal: /* @__PURE__ */ __name((value) => {
985
- return {
986
- kind: "literal",
987
- value
988
- };
989
- }, "literal"),
990
- array: /* @__PURE__ */ __name((items) => {
991
- return {
992
- kind: "array",
993
- items
994
- };
995
- }, "array"),
996
- call: /* @__PURE__ */ __name((functionName, args) => {
997
- return {
998
- kind: "call",
999
- function: functionName,
1000
- args
1001
- };
1002
- }, "call"),
1003
- binary: /* @__PURE__ */ __name((left, op, right) => {
1004
- return {
1005
- kind: "binary",
1006
- op,
1007
- left,
1008
- right
1009
- };
1010
- }, "binary"),
1011
- unary: /* @__PURE__ */ __name((op, operand) => {
1012
- return {
1013
- kind: "unary",
1014
- op,
1015
- operand
1016
- };
1017
- }, "unary"),
1018
- field: /* @__PURE__ */ __name((field) => {
1019
- return {
1020
- kind: "field",
1021
- field
1022
- };
1023
- }, "field"),
1024
- member: /* @__PURE__ */ __name((receiver, members) => {
1025
- return {
1026
- kind: "member",
1027
- receiver,
1028
- members
1029
- };
1030
- }, "member"),
1031
- _this: /* @__PURE__ */ __name(() => {
1032
- return {
1033
- kind: "this"
1034
- };
1035
- }, "_this"),
1036
- _null: /* @__PURE__ */ __name(() => {
1037
- return {
1038
- kind: "null"
1039
- };
1040
- }, "_null"),
1041
- and: /* @__PURE__ */ __name((expr2, ...expressions) => {
1042
- return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
1043
- }, "and"),
1044
- or: /* @__PURE__ */ __name((expr2, ...expressions) => {
1045
- return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
1046
- }, "or"),
1047
- is: /* @__PURE__ */ __name((value, kind) => {
1048
- return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
1049
- }, "is"),
1050
- isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
1051
- isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
1052
- isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
1053
- isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
1054
- isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
1055
- isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
1056
- isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
1057
- isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
1058
- isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
1059
- };
1060
-
1061
1337
  // src/utils/default-operation-node-visitor.ts
1062
1338
  import { OperationNodeVisitor } from "kysely";
1063
1339
  var DefaultOperationNodeVisitor = class extends OperationNodeVisitor {
@@ -1377,19 +1653,19 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
1377
1653
  };
1378
1654
 
1379
1655
  // src/plugins/policy/expression-transformer.ts
1380
- import { AliasNode as AliasNode2, BinaryOperationNode as BinaryOperationNode2, ColumnNode, expressionBuilder, FromNode, FunctionNode as FunctionNode2, IdentifierNode, OperatorNode as OperatorNode2, ReferenceNode as ReferenceNode2, SelectionNode, SelectQueryNode, TableNode as TableNode2, ValueListNode, ValueNode as ValueNode2, WhereNode } from "kysely";
1381
- import invariant5 from "tiny-invariant";
1382
- import { match as match6 } from "ts-pattern";
1656
+ import { invariant as invariant5 } from "@zenstackhq/common-helpers";
1657
+ import { AliasNode as AliasNode2, BinaryOperationNode as BinaryOperationNode2, ColumnNode, expressionBuilder as expressionBuilder2, FromNode, FunctionNode as FunctionNode2, IdentifierNode, OperatorNode as OperatorNode2, ReferenceNode as ReferenceNode2, SelectionNode, SelectQueryNode, TableNode as TableNode2, ValueListNode, ValueNode as ValueNode2, WhereNode } from "kysely";
1658
+ import { match as match7 } from "ts-pattern";
1383
1659
 
1384
1660
  // src/plugins/policy/expression-evaluator.ts
1385
- import invariant4 from "tiny-invariant";
1386
- import { match as match5 } from "ts-pattern";
1661
+ import { invariant as invariant4 } from "@zenstackhq/common-helpers";
1662
+ import { match as match6 } from "ts-pattern";
1387
1663
  var ExpressionEvaluator = class {
1388
1664
  static {
1389
1665
  __name(this, "ExpressionEvaluator");
1390
1666
  }
1391
1667
  evaluate(expression, context) {
1392
- const result = match5(expression).when(ExpressionUtils.isArray, (expr2) => this.evaluateArray(expr2, context)).when(ExpressionUtils.isBinary, (expr2) => this.evaluateBinary(expr2, context)).when(ExpressionUtils.isField, (expr2) => this.evaluateField(expr2, context)).when(ExpressionUtils.isLiteral, (expr2) => this.evaluateLiteral(expr2)).when(ExpressionUtils.isMember, (expr2) => this.evaluateMember(expr2, context)).when(ExpressionUtils.isUnary, (expr2) => this.evaluateUnary(expr2, context)).when(ExpressionUtils.isCall, (expr2) => this.evaluateCall(expr2, context)).when(ExpressionUtils.isThis, () => context.thisValue).when(ExpressionUtils.isNull, () => null).exhaustive();
1668
+ const result = match6(expression).when(ExpressionUtils.isArray, (expr2) => this.evaluateArray(expr2, context)).when(ExpressionUtils.isBinary, (expr2) => this.evaluateBinary(expr2, context)).when(ExpressionUtils.isField, (expr2) => this.evaluateField(expr2, context)).when(ExpressionUtils.isLiteral, (expr2) => this.evaluateLiteral(expr2)).when(ExpressionUtils.isMember, (expr2) => this.evaluateMember(expr2, context)).when(ExpressionUtils.isUnary, (expr2) => this.evaluateUnary(expr2, context)).when(ExpressionUtils.isCall, (expr2) => this.evaluateCall(expr2, context)).when(ExpressionUtils.isThis, () => context.thisValue).when(ExpressionUtils.isNull, () => null).exhaustive();
1393
1669
  return result ?? null;
1394
1670
  }
1395
1671
  evaluateCall(expr2, context) {
@@ -1400,7 +1676,7 @@ var ExpressionEvaluator = class {
1400
1676
  }
1401
1677
  }
1402
1678
  evaluateUnary(expr2, context) {
1403
- return match5(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
1679
+ return match6(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
1404
1680
  }
1405
1681
  evaluateMember(expr2, context) {
1406
1682
  let val = this.evaluate(expr2.receiver, context);
@@ -1424,7 +1700,7 @@ var ExpressionEvaluator = class {
1424
1700
  }
1425
1701
  const left = this.evaluate(expr2.left, context);
1426
1702
  const right = this.evaluate(expr2.right, context);
1427
- return match5(expr2.op).with("==", () => left === right).with("!=", () => left !== right).with(">", () => left > right).with(">=", () => left >= right).with("<", () => left < right).with("<=", () => left <= right).with("&&", () => left && right).with("||", () => left || right).with("in", () => {
1703
+ return match6(expr2.op).with("==", () => left === right).with("!=", () => left !== right).with(">", () => left > right).with(">=", () => left >= right).with("<", () => left < right).with("<=", () => left <= right).with("&&", () => left && right).with("||", () => left || right).with("in", () => {
1428
1704
  const _right = right ?? [];
1429
1705
  invariant4(Array.isArray(_right), 'expected array for "in" operator');
1430
1706
  return _right.includes(left);
@@ -1438,7 +1714,7 @@ var ExpressionEvaluator = class {
1438
1714
  return false;
1439
1715
  }
1440
1716
  invariant4(Array.isArray(left), "expected array");
1441
- return match5(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
1717
+ return match6(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
1442
1718
  ...context,
1443
1719
  thisValue: item
1444
1720
  }))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
@@ -1454,11 +1730,11 @@ var ExpressionEvaluator = class {
1454
1730
  // src/plugins/policy/utils.ts
1455
1731
  import { AliasNode, AndNode, BinaryOperationNode, FunctionNode, OperatorNode, OrNode, ParensNode, ReferenceNode, TableNode, UnaryOperationNode, ValueNode } from "kysely";
1456
1732
  function trueNode(dialect) {
1457
- return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
1733
+ return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
1458
1734
  }
1459
1735
  __name(trueNode, "trueNode");
1460
1736
  function falseNode(dialect) {
1461
- return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
1737
+ return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
1462
1738
  }
1463
1739
  __name(falseNode, "falseNode");
1464
1740
  function isTrueNode(node) {
@@ -1692,7 +1968,7 @@ var ExpressionTransformer = class {
1692
1968
  const count = FunctionNode2.create("count", [
1693
1969
  ValueNode2.createImmediate(1)
1694
1970
  ]);
1695
- const predicateResult = match6(expr2.op).with("?", () => BinaryOperationNode2.create(count, OperatorNode2.create(">"), ValueNode2.createImmediate(0))).with("!", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).with("^", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).exhaustive();
1971
+ const predicateResult = match7(expr2.op).with("?", () => BinaryOperationNode2.create(count, OperatorNode2.create(">"), ValueNode2.createImmediate(0))).with("!", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).with("^", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).exhaustive();
1696
1972
  return this.transform(expr2.left, {
1697
1973
  ...context,
1698
1974
  memberSelect: SelectionNode.create(AliasNode2.create(predicateResult, IdentifierNode.create("$t"))),
@@ -1716,14 +1992,14 @@ var ExpressionTransformer = class {
1716
1992
  }
1717
1993
  }
1718
1994
  transformValue(value, type) {
1719
- return ValueNode2.create(this.dialect.transformPrimitive(value, type) ?? null);
1995
+ return ValueNode2.create(this.dialect.transformPrimitive(value, type, false) ?? null);
1720
1996
  }
1721
1997
  _unary(expr2, context) {
1722
1998
  invariant5(expr2.op === "!", 'only "!" operator is supported');
1723
1999
  return BinaryOperationNode2.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
1724
2000
  }
1725
2001
  transformOperator(op) {
1726
- const mappedOp = match6(op).with("==", () => "=").otherwise(() => op);
2002
+ const mappedOp = match7(op).with("==", () => "=").otherwise(() => op);
1727
2003
  return OperatorNode2.create(mappedOp);
1728
2004
  }
1729
2005
  _call(expr2, context) {
@@ -1735,7 +2011,7 @@ var ExpressionTransformer = class {
1735
2011
  if (!func) {
1736
2012
  throw new QueryError(`Function not implemented: ${expr2.function}`);
1737
2013
  }
1738
- const eb = expressionBuilder();
2014
+ const eb = expressionBuilder2();
1739
2015
  return func(eb, (expr2.args ?? []).map((arg) => this.transformCallArg(eb, arg, context)), {
1740
2016
  dialect: this.dialect,
1741
2017
  model: context.model,
@@ -1959,7 +2235,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
1959
2235
  get kysely() {
1960
2236
  return this.client.$qb;
1961
2237
  }
1962
- async handle(node, proceed, transaction) {
2238
+ async handle(node, proceed) {
1963
2239
  if (!this.isCrudQueryNode(node)) {
1964
2240
  throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
1965
2241
  }
@@ -1979,27 +2255,20 @@ var PolicyHandler = class extends OperationNodeTransformer {
1979
2255
  if (!mutationRequiresTransaction && !node.returning) {
1980
2256
  return proceed(this.transformNode(node));
1981
2257
  }
1982
- let readBackError = false;
1983
- const result = await transaction(async (txProceed) => {
1984
- if (InsertQueryNode.is(node)) {
1985
- await this.enforcePreCreatePolicy(node, txProceed);
1986
- }
1987
- const transformedNode = this.transformNode(node);
1988
- const result2 = await txProceed(transformedNode);
1989
- if (!this.onlyReturningId(node)) {
1990
- const readBackResult = await this.processReadBack(node, result2, txProceed);
1991
- if (readBackResult.rows.length !== result2.rows.length) {
1992
- readBackError = true;
1993
- }
1994
- return readBackResult;
1995
- } else {
1996
- return result2;
2258
+ if (InsertQueryNode.is(node)) {
2259
+ await this.enforcePreCreatePolicy(node, proceed);
2260
+ }
2261
+ const transformedNode = this.transformNode(node);
2262
+ const result = await proceed(transformedNode);
2263
+ if (!this.onlyReturningId(node)) {
2264
+ const readBackResult = await this.processReadBack(node, result, proceed);
2265
+ if (readBackResult.rows.length !== result.rows.length) {
2266
+ throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
1997
2267
  }
1998
- });
1999
- if (readBackError) {
2000
- throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
2268
+ return readBackResult;
2269
+ } else {
2270
+ return result;
2001
2271
  }
2002
- return result;
2003
2272
  }
2004
2273
  onlyReturningId(node) {
2005
2274
  if (!node.returning) {
@@ -2060,11 +2329,11 @@ var PolicyHandler = class extends OperationNodeTransformer {
2060
2329
  if (typeof item === "object" && item && "kind" in item) {
2061
2330
  invariant6(item.kind === "ValueNode", "expecting a ValueNode");
2062
2331
  result.push({
2063
- node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
2332
+ node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
2064
2333
  raw: item.value
2065
2334
  });
2066
2335
  } else {
2067
- const value = this.dialect.transformPrimitive(item, fieldDef.type);
2336
+ const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
2068
2337
  if (Array.isArray(value)) {
2069
2338
  result.push({
2070
2339
  node: RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
@@ -2133,7 +2402,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
2133
2402
  return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => BinaryOperationNode3.create(ColumnNode2.create(field), OperatorNode3.create("="), ValueNode3.create(row[field]))))));
2134
2403
  }
2135
2404
  getMutationModel(node) {
2136
- const r = match7(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
2405
+ const r = match8(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
2137
2406
  if (node2.from.froms.length !== 1) {
2138
2407
  throw new InternalError("Only one from table is supported for delete");
2139
2408
  }
@@ -2295,13 +2564,22 @@ var PolicyPlugin = class {
2295
2564
  get description() {
2296
2565
  return "Enforces access policies defined in the schema.";
2297
2566
  }
2298
- onKyselyQuery({ query, client, proceed, transaction }) {
2567
+ onKyselyQuery({
2568
+ query,
2569
+ client,
2570
+ proceed
2571
+ /*, transaction*/
2572
+ }) {
2299
2573
  const handler = new PolicyHandler(client);
2300
- return handler.handle(query, proceed, transaction);
2574
+ return handler.handle(
2575
+ query,
2576
+ proceed
2577
+ /*, transaction*/
2578
+ );
2301
2579
  }
2302
2580
  };
2303
2581
  export {
2304
2582
  PolicyPlugin,
2305
2583
  RejectedByPolicyError
2306
2584
  };
2307
- //# sourceMappingURL=policy.js.map
2585
+ //# sourceMappingURL=index.js.map