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

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.
@@ -1,5 +1,5 @@
1
1
  import * as kysely from 'kysely';
2
- import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-CxX20JtH.cjs';
2
+ import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-XFKcwhq7.cjs';
3
3
  import { SchemaDef } from '@zenstackhq/sdk/schema';
4
4
  import 'decimal.js';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import * as kysely from 'kysely';
2
- import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-CxX20JtH.js';
2
+ import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-XFKcwhq7.js';
3
3
  import { SchemaDef } from '@zenstackhq/sdk/schema';
4
4
  import 'decimal.js';
5
5
 
@@ -16,18 +16,33 @@ var RejectedByPolicyError = class extends Error {
16
16
  // src/plugins/policy/policy-handler.ts
17
17
  import { invariant as invariant6 } from "@zenstackhq/common-helpers";
18
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";
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
25
  import { invariant as invariant2 } from "@zenstackhq/common-helpers";
26
26
  import { sql as sql2 } from "kysely";
27
- import { match as match2 } from "ts-pattern";
27
+ import { match as match3 } from "ts-pattern";
28
28
 
29
29
  // src/client/constants.ts
30
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";
31
46
 
32
47
  // src/schema/expression.ts
33
48
  var ExpressionUtils = {
@@ -332,11 +347,15 @@ function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */
332
347
  ];
333
348
  }
334
349
  __name(getDelegateDescendantModels, "getDelegateDescendantModels");
350
+ function aggregate(eb, expr2, op) {
351
+ 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();
352
+ }
353
+ __name(aggregate, "aggregate");
335
354
 
336
355
  // src/client/crud/dialects/base.ts
337
356
  import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
338
357
  import { sql } from "kysely";
339
- import { match, P } from "ts-pattern";
358
+ import { match as match2, P } from "ts-pattern";
340
359
 
341
360
  // src/utils/enumerate.ts
342
361
  function enumerate(x) {
@@ -393,7 +412,7 @@ var BaseCrudDialect = class {
393
412
  if (key.startsWith("$")) {
394
413
  continue;
395
414
  }
396
- if (key === "AND" || key === "OR" || key === "NOT") {
415
+ if (this.isLogicalCombinator(key)) {
397
416
  result = this.and(eb, result, this.buildCompositeFilter(eb, model, modelAlias, key, payload));
398
417
  continue;
399
418
  }
@@ -414,8 +433,11 @@ var BaseCrudDialect = class {
414
433
  }
415
434
  return result;
416
435
  }
436
+ isLogicalCombinator(key) {
437
+ return LOGICAL_COMBINATORS.includes(key);
438
+ }
417
439
  buildCompositeFilter(eb, model, modelAlias, key, payload) {
418
- 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();
440
+ 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();
419
441
  }
420
442
  buildRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
421
443
  if (!fieldDef.array) {
@@ -564,7 +586,7 @@ var BaseCrudDialect = class {
564
586
  if (isEnum(this.schema, fieldDef.type)) {
565
587
  return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
566
588
  }
567
- return match(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", () => {
589
+ 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", () => {
568
590
  throw new InternalError("JSON filters are not supported yet");
569
591
  }).with("Unsupported", () => {
570
592
  throw new QueryError(`Unsupported field cannot be used in filters`);
@@ -592,7 +614,7 @@ var BaseCrudDialect = class {
592
614
  continue;
593
615
  }
594
616
  const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
595
- const condition = match(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
617
+ const condition = match2(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
596
618
  invariant(Array.isArray(rhs), "right hand side must be an array");
597
619
  if (rhs.length === 0) {
598
620
  return this.false(eb);
@@ -606,7 +628,11 @@ var BaseCrudDialect = class {
606
628
  } else {
607
629
  return eb.not(eb(lhs, "in", rhs));
608
630
  }
609
- }).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(() => {
631
+ }).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) => {
632
+ const innerResult = this.buildStandardFilter(eb, type, value, aggregate(eb, lhs, op2), getRhs, recurse, throwIfInvalid);
633
+ consumedKeys.push(...innerResult.consumedKeys);
634
+ return this.and(eb, ...innerResult.conditions);
635
+ }).otherwise(() => {
610
636
  if (throwIfInvalid) {
611
637
  throw new QueryError(`Invalid filter key: ${op}`);
612
638
  } else {
@@ -636,7 +662,7 @@ var BaseCrudDialect = class {
636
662
  if (key === "mode" || consumedKeys.includes(key)) {
637
663
  continue;
638
664
  }
639
- const condition = match(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(() => {
665
+ 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(() => {
640
666
  throw new QueryError(`Invalid string filter key: ${key}`);
641
667
  });
642
668
  if (condition) {
@@ -717,9 +743,7 @@ var BaseCrudDialect = class {
717
743
  invariant(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
718
744
  for (const [k, v] of Object.entries(value)) {
719
745
  invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
720
- result = result.orderBy((eb) => eb.fn(field.slice(1), [
721
- sql.ref(k)
722
- ]), sql.raw(this.negateSort(v, negated)));
746
+ result = result.orderBy((eb) => aggregate(eb, sql.ref(`${modelAlias}.${k}`), field), sql.raw(this.negateSort(v, negated)));
723
747
  }
724
748
  continue;
725
749
  }
@@ -914,7 +938,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
914
938
  return value.map((v) => this.transformPrimitive(v, type, false));
915
939
  }
916
940
  } else {
917
- return match2(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
941
+ 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);
918
942
  }
919
943
  }
920
944
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
@@ -1071,7 +1095,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1071
1095
  // src/client/crud/dialects/sqlite.ts
1072
1096
  import { invariant as invariant3 } from "@zenstackhq/common-helpers";
1073
1097
  import { sql as sql3 } from "kysely";
1074
- import { match as match3 } from "ts-pattern";
1098
+ import { match as match4 } from "ts-pattern";
1075
1099
  var SqliteCrudDialect = class extends BaseCrudDialect {
1076
1100
  static {
1077
1101
  __name(this, "SqliteCrudDialect");
@@ -1089,7 +1113,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1089
1113
  if (this.schema.typeDefs && type in this.schema.typeDefs) {
1090
1114
  return JSON.stringify(value);
1091
1115
  } else {
1092
- 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)).with("Json", () => JSON.stringify(value)).otherwise(() => value);
1116
+ 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);
1093
1117
  }
1094
1118
  }
1095
1119
  }
@@ -1235,7 +1259,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1235
1259
 
1236
1260
  // src/client/crud/dialects/index.ts
1237
1261
  function getCrudDialect(schema, options) {
1238
- return match4(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
1262
+ return match5(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
1239
1263
  }
1240
1264
  __name(getCrudDialect, "getCrudDialect");
1241
1265
 
@@ -1560,17 +1584,17 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
1560
1584
  // src/plugins/policy/expression-transformer.ts
1561
1585
  import { invariant as invariant5 } from "@zenstackhq/common-helpers";
1562
1586
  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";
1563
- import { match as match6 } from "ts-pattern";
1587
+ import { match as match7 } from "ts-pattern";
1564
1588
 
1565
1589
  // src/plugins/policy/expression-evaluator.ts
1566
1590
  import { invariant as invariant4 } from "@zenstackhq/common-helpers";
1567
- import { match as match5 } from "ts-pattern";
1591
+ import { match as match6 } from "ts-pattern";
1568
1592
  var ExpressionEvaluator = class {
1569
1593
  static {
1570
1594
  __name(this, "ExpressionEvaluator");
1571
1595
  }
1572
1596
  evaluate(expression, context) {
1573
- 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();
1597
+ 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();
1574
1598
  return result ?? null;
1575
1599
  }
1576
1600
  evaluateCall(expr2, context) {
@@ -1581,7 +1605,7 @@ var ExpressionEvaluator = class {
1581
1605
  }
1582
1606
  }
1583
1607
  evaluateUnary(expr2, context) {
1584
- return match5(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
1608
+ return match6(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
1585
1609
  }
1586
1610
  evaluateMember(expr2, context) {
1587
1611
  let val = this.evaluate(expr2.receiver, context);
@@ -1605,7 +1629,7 @@ var ExpressionEvaluator = class {
1605
1629
  }
1606
1630
  const left = this.evaluate(expr2.left, context);
1607
1631
  const right = this.evaluate(expr2.right, context);
1608
- 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", () => {
1632
+ 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", () => {
1609
1633
  const _right = right ?? [];
1610
1634
  invariant4(Array.isArray(_right), 'expected array for "in" operator');
1611
1635
  return _right.includes(left);
@@ -1619,7 +1643,7 @@ var ExpressionEvaluator = class {
1619
1643
  return false;
1620
1644
  }
1621
1645
  invariant4(Array.isArray(left), "expected array");
1622
- return match5(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
1646
+ return match6(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
1623
1647
  ...context,
1624
1648
  thisValue: item
1625
1649
  }))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
@@ -1873,7 +1897,7 @@ var ExpressionTransformer = class {
1873
1897
  const count = FunctionNode2.create("count", [
1874
1898
  ValueNode2.createImmediate(1)
1875
1899
  ]);
1876
- 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();
1900
+ 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();
1877
1901
  return this.transform(expr2.left, {
1878
1902
  ...context,
1879
1903
  memberSelect: SelectionNode.create(AliasNode2.create(predicateResult, IdentifierNode.create("$t"))),
@@ -1904,7 +1928,7 @@ var ExpressionTransformer = class {
1904
1928
  return BinaryOperationNode2.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
1905
1929
  }
1906
1930
  transformOperator(op) {
1907
- const mappedOp = match6(op).with("==", () => "=").otherwise(() => op);
1931
+ const mappedOp = match7(op).with("==", () => "=").otherwise(() => op);
1908
1932
  return OperatorNode2.create(mappedOp);
1909
1933
  }
1910
1934
  _call(expr2, context) {
@@ -2307,7 +2331,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
2307
2331
  return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => BinaryOperationNode3.create(ColumnNode2.create(field), OperatorNode3.create("="), ValueNode3.create(row[field]))))));
2308
2332
  }
2309
2333
  getMutationModel(node) {
2310
- const r = match7(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
2334
+ const r = match8(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
2311
2335
  if (node2.from.froms.length !== 1) {
2312
2336
  throw new InternalError("Only one from table is supported for delete");
2313
2337
  }