@zenstackhq/runtime 3.0.0-alpha.8 → 3.0.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{contract-BnvK1nW0.d.cts → contract-BiU0iYAh.d.cts} +82 -40
- package/dist/{contract-BnvK1nW0.d.ts → contract-BiU0iYAh.d.ts} +82 -40
- package/dist/index.cjs +377 -233
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -3
- package/dist/index.d.ts +28 -3
- package/dist/index.js +371 -232
- package/dist/index.js.map +1 -1
- package/dist/plugins/policy.cjs +81 -56
- package/dist/plugins/policy.cjs.map +1 -1
- package/dist/plugins/policy.d.cts +2 -2
- package/dist/plugins/policy.d.ts +2 -2
- package/dist/plugins/policy.js +81 -56
- package/dist/plugins/policy.js.map +1 -1
- package/package.json +7 -17
- package/dist/client.cjs +0 -6150
- package/dist/client.cjs.map +0 -1
- package/dist/client.d.cts +0 -17
- package/dist/client.d.ts +0 -17
- package/dist/client.js +0 -6115
- package/dist/client.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -31,12 +31,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/index.ts
|
|
32
32
|
var src_exports = {};
|
|
33
33
|
__export(src_exports, {
|
|
34
|
-
|
|
34
|
+
InputValidationError: () => InputValidationError,
|
|
35
|
+
InternalError: () => InternalError,
|
|
36
|
+
NotFoundError: () => NotFoundError,
|
|
37
|
+
QueryError: () => QueryError,
|
|
38
|
+
ZenStackClient: () => ZenStackClient,
|
|
39
|
+
definePlugin: () => definePlugin
|
|
35
40
|
});
|
|
36
41
|
module.exports = __toCommonJS(src_exports);
|
|
37
42
|
|
|
38
43
|
// src/client/client-impl.ts
|
|
39
|
-
var
|
|
44
|
+
var import_common_helpers13 = require("@zenstackhq/common-helpers");
|
|
40
45
|
var import_kysely16 = require("kysely");
|
|
41
46
|
var import_ts_pattern19 = require("ts-pattern");
|
|
42
47
|
|
|
@@ -45,12 +50,24 @@ var import_kysely9 = require("kysely");
|
|
|
45
50
|
var import_ts_pattern9 = require("ts-pattern");
|
|
46
51
|
|
|
47
52
|
// src/client/errors.ts
|
|
53
|
+
var InputValidationError = class extends Error {
|
|
54
|
+
static {
|
|
55
|
+
__name(this, "InputValidationError");
|
|
56
|
+
}
|
|
57
|
+
constructor(message, cause) {
|
|
58
|
+
super(message, {
|
|
59
|
+
cause
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
};
|
|
48
63
|
var QueryError = class extends Error {
|
|
49
64
|
static {
|
|
50
65
|
__name(this, "QueryError");
|
|
51
66
|
}
|
|
52
|
-
constructor(message) {
|
|
53
|
-
super(message
|
|
67
|
+
constructor(message, cause) {
|
|
68
|
+
super(message, {
|
|
69
|
+
cause
|
|
70
|
+
});
|
|
54
71
|
}
|
|
55
72
|
};
|
|
56
73
|
var InternalError = class extends Error {
|
|
@@ -78,7 +95,7 @@ __name(getModel, "getModel");
|
|
|
78
95
|
function requireModel(schema, model) {
|
|
79
96
|
const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
|
|
80
97
|
if (!matchedName) {
|
|
81
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
98
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
82
99
|
}
|
|
83
100
|
return schema.models[matchedName];
|
|
84
101
|
}
|
|
@@ -203,7 +220,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias) {
|
|
|
203
220
|
computer = computedFields?.[model]?.[field];
|
|
204
221
|
}
|
|
205
222
|
if (!computer) {
|
|
206
|
-
throw new QueryError(`Computed field "${field}" implementation not provided`);
|
|
223
|
+
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
207
224
|
}
|
|
208
225
|
return computer(eb);
|
|
209
226
|
}
|
|
@@ -314,6 +331,7 @@ var import_cuid2 = require("@paralleldrive/cuid2");
|
|
|
314
331
|
var import_common_helpers8 = require("@zenstackhq/common-helpers");
|
|
315
332
|
var import_kysely8 = require("kysely");
|
|
316
333
|
var import_nanoid = require("nanoid");
|
|
334
|
+
var import_node_util = require("util");
|
|
317
335
|
var import_ts_pattern8 = require("ts-pattern");
|
|
318
336
|
var import_ulid = require("ulid");
|
|
319
337
|
var uuid = __toESM(require("uuid"), 1);
|
|
@@ -373,7 +391,7 @@ var BaseCrudDialect = class {
|
|
|
373
391
|
this.schema = schema;
|
|
374
392
|
this.options = options;
|
|
375
393
|
}
|
|
376
|
-
transformPrimitive(value, _type) {
|
|
394
|
+
transformPrimitive(value, _type, _forArrayField) {
|
|
377
395
|
return value;
|
|
378
396
|
}
|
|
379
397
|
buildFilter(eb, model, modelAlias, where) {
|
|
@@ -516,7 +534,7 @@ var BaseCrudDialect = class {
|
|
|
516
534
|
if (_value === void 0) {
|
|
517
535
|
continue;
|
|
518
536
|
}
|
|
519
|
-
const value = this.transformPrimitive(_value, fieldType);
|
|
537
|
+
const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
|
|
520
538
|
switch (key) {
|
|
521
539
|
case "equals": {
|
|
522
540
|
clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
|
|
@@ -554,10 +572,14 @@ var BaseCrudDialect = class {
|
|
|
554
572
|
if (isEnum(this.schema, fieldDef.type)) {
|
|
555
573
|
return this.buildEnumFilter(eb, modelAlias, field, fieldDef, payload);
|
|
556
574
|
}
|
|
557
|
-
return (0, import_ts_pattern.match)(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(import_ts_pattern.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)).
|
|
575
|
+
return (0, import_ts_pattern.match)(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(import_ts_pattern.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)).with("Json", () => {
|
|
576
|
+
throw new InternalError("JSON filters are not supported yet");
|
|
577
|
+
}).with("Unsupported", () => {
|
|
578
|
+
throw new QueryError(`Unsupported field cannot be used in filters`);
|
|
579
|
+
}).exhaustive();
|
|
558
580
|
}
|
|
559
581
|
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
560
|
-
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
|
|
582
|
+
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
561
583
|
}
|
|
562
584
|
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
|
|
563
585
|
if (payload === null || !(0, import_common_helpers.isPlainObject)(payload)) {
|
|
@@ -644,22 +666,22 @@ var BaseCrudDialect = class {
|
|
|
644
666
|
}
|
|
645
667
|
}
|
|
646
668
|
buildNumberFilter(eb, model, table, field, type, payload) {
|
|
647
|
-
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));
|
|
669
|
+
const { conditions } = this.buildStandardFilter(eb, type, payload, buildFieldRef(this.schema, model, field, this.options, eb), (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, model, table, field, type, value));
|
|
648
670
|
return this.and(eb, ...conditions);
|
|
649
671
|
}
|
|
650
672
|
buildBooleanFilter(eb, table, field, payload) {
|
|
651
|
-
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean"), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
|
|
673
|
+
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
|
|
652
674
|
"equals",
|
|
653
675
|
"not"
|
|
654
676
|
]);
|
|
655
677
|
return this.and(eb, ...conditions);
|
|
656
678
|
}
|
|
657
679
|
buildDateTimeFilter(eb, table, field, payload) {
|
|
658
|
-
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime"), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
|
|
680
|
+
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
|
|
659
681
|
return this.and(eb, ...conditions);
|
|
660
682
|
}
|
|
661
683
|
buildBytesFilter(eb, table, field, payload) {
|
|
662
|
-
const conditions = this.buildStandardFilter(eb, "Bytes", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes"), (value) => this.buildBytesFilter(eb, table, field, value), true, [
|
|
684
|
+
const conditions = this.buildStandardFilter(eb, "Bytes", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, table, field, value), true, [
|
|
663
685
|
"equals",
|
|
664
686
|
"in",
|
|
665
687
|
"notIn",
|
|
@@ -758,10 +780,10 @@ var BaseCrudDialect = class {
|
|
|
758
780
|
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
759
781
|
}
|
|
760
782
|
true(eb) {
|
|
761
|
-
return eb.lit(this.transformPrimitive(true, "Boolean"));
|
|
783
|
+
return eb.lit(this.transformPrimitive(true, "Boolean", false));
|
|
762
784
|
}
|
|
763
785
|
false(eb) {
|
|
764
|
-
return eb.lit(this.transformPrimitive(false, "Boolean"));
|
|
786
|
+
return eb.lit(this.transformPrimitive(false, "Boolean", false));
|
|
765
787
|
}
|
|
766
788
|
isTrue(expression) {
|
|
767
789
|
const node = expression.toOperationNode();
|
|
@@ -810,14 +832,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
810
832
|
get provider() {
|
|
811
833
|
return "postgresql";
|
|
812
834
|
}
|
|
813
|
-
transformPrimitive(value, type) {
|
|
835
|
+
transformPrimitive(value, type, forArrayField) {
|
|
814
836
|
if (value === void 0) {
|
|
815
837
|
return value;
|
|
816
838
|
}
|
|
817
839
|
if (Array.isArray(value)) {
|
|
818
|
-
|
|
840
|
+
if (type === "Json" && !forArrayField) {
|
|
841
|
+
return JSON.stringify(value);
|
|
842
|
+
} else {
|
|
843
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
844
|
+
}
|
|
819
845
|
} else {
|
|
820
|
-
return (0, import_ts_pattern2.match)(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).otherwise(() => value);
|
|
846
|
+
return (0, import_ts_pattern2.match)(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
|
|
821
847
|
}
|
|
822
848
|
}
|
|
823
849
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -884,25 +910,33 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
884
910
|
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
885
911
|
]).flatMap((v) => v));
|
|
886
912
|
} else if (payload.select) {
|
|
887
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) =>
|
|
888
|
-
|
|
889
|
-
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
890
|
-
|
|
913
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => {
|
|
914
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
915
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentName}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
|
|
916
|
+
return [
|
|
917
|
+
import_kysely2.sql.lit(field),
|
|
918
|
+
fieldValue
|
|
919
|
+
];
|
|
920
|
+
}).flatMap((v) => v));
|
|
891
921
|
}
|
|
892
922
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
893
923
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
894
924
|
import_kysely2.sql.lit(field),
|
|
925
|
+
// reference the synthesized JSON field
|
|
895
926
|
eb.ref(`${parentName}$${relationField}$${field}.$j`)
|
|
896
927
|
]).flatMap((v) => v));
|
|
897
928
|
}
|
|
898
929
|
return objArgs;
|
|
899
930
|
}
|
|
900
|
-
buildRelationJoins(
|
|
931
|
+
buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
|
|
901
932
|
let result = qb;
|
|
902
|
-
if (typeof payload === "object"
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
933
|
+
if (typeof payload === "object") {
|
|
934
|
+
const selectInclude = payload.include ?? payload.select;
|
|
935
|
+
if (selectInclude && typeof selectInclude === "object") {
|
|
936
|
+
Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
|
|
937
|
+
result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
|
|
938
|
+
});
|
|
939
|
+
}
|
|
906
940
|
}
|
|
907
941
|
return result;
|
|
908
942
|
}
|
|
@@ -955,14 +989,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
955
989
|
get provider() {
|
|
956
990
|
return "sqlite";
|
|
957
991
|
}
|
|
958
|
-
transformPrimitive(value, type) {
|
|
992
|
+
transformPrimitive(value, type, _forArrayField) {
|
|
959
993
|
if (value === void 0) {
|
|
960
994
|
return value;
|
|
961
995
|
}
|
|
962
996
|
if (Array.isArray(value)) {
|
|
963
|
-
return value.map((v) => this.transformPrimitive(v, type));
|
|
997
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
964
998
|
} else {
|
|
965
|
-
return (0, import_ts_pattern3.match)(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);
|
|
999
|
+
return (0, import_ts_pattern3.match)(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);
|
|
966
1000
|
}
|
|
967
1001
|
}
|
|
968
1002
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -1567,11 +1601,11 @@ var ExpressionEvaluator = class {
|
|
|
1567
1601
|
// src/plugins/policy/utils.ts
|
|
1568
1602
|
var import_kysely5 = require("kysely");
|
|
1569
1603
|
function trueNode(dialect) {
|
|
1570
|
-
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
|
|
1604
|
+
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1571
1605
|
}
|
|
1572
1606
|
__name(trueNode, "trueNode");
|
|
1573
1607
|
function falseNode(dialect) {
|
|
1574
|
-
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
|
|
1608
|
+
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1575
1609
|
}
|
|
1576
1610
|
__name(falseNode, "falseNode");
|
|
1577
1611
|
function isTrueNode(node) {
|
|
@@ -1829,7 +1863,7 @@ var ExpressionTransformer = class {
|
|
|
1829
1863
|
}
|
|
1830
1864
|
}
|
|
1831
1865
|
transformValue(value, type) {
|
|
1832
|
-
return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type) ?? null);
|
|
1866
|
+
return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
1833
1867
|
}
|
|
1834
1868
|
_unary(expr2, context) {
|
|
1835
1869
|
(0, import_common_helpers5.invariant)(expr2.op === "!", 'only "!" operator is supported');
|
|
@@ -2072,7 +2106,7 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2072
2106
|
get kysely() {
|
|
2073
2107
|
return this.client.$qb;
|
|
2074
2108
|
}
|
|
2075
|
-
async handle(node, proceed
|
|
2109
|
+
async handle(node, proceed) {
|
|
2076
2110
|
if (!this.isCrudQueryNode(node)) {
|
|
2077
2111
|
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
2078
2112
|
}
|
|
@@ -2092,27 +2126,20 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2092
2126
|
if (!mutationRequiresTransaction && !node.returning) {
|
|
2093
2127
|
return proceed(this.transformNode(node));
|
|
2094
2128
|
}
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
const
|
|
2102
|
-
if (
|
|
2103
|
-
|
|
2104
|
-
if (readBackResult.rows.length !== result2.rows.length) {
|
|
2105
|
-
readBackError = true;
|
|
2106
|
-
}
|
|
2107
|
-
return readBackResult;
|
|
2108
|
-
} else {
|
|
2109
|
-
return result2;
|
|
2129
|
+
if (import_kysely7.InsertQueryNode.is(node)) {
|
|
2130
|
+
await this.enforcePreCreatePolicy(node, proceed);
|
|
2131
|
+
}
|
|
2132
|
+
const transformedNode = this.transformNode(node);
|
|
2133
|
+
const result = await proceed(transformedNode);
|
|
2134
|
+
if (!this.onlyReturningId(node)) {
|
|
2135
|
+
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2136
|
+
if (readBackResult.rows.length !== result.rows.length) {
|
|
2137
|
+
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
2110
2138
|
}
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2139
|
+
return readBackResult;
|
|
2140
|
+
} else {
|
|
2141
|
+
return result;
|
|
2114
2142
|
}
|
|
2115
|
-
return result;
|
|
2116
2143
|
}
|
|
2117
2144
|
onlyReturningId(node) {
|
|
2118
2145
|
if (!node.returning) {
|
|
@@ -2173,11 +2200,11 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2173
2200
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2174
2201
|
(0, import_common_helpers6.invariant)(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2175
2202
|
result.push({
|
|
2176
|
-
node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
|
|
2203
|
+
node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2177
2204
|
raw: item.value
|
|
2178
2205
|
});
|
|
2179
2206
|
} else {
|
|
2180
|
-
const value = this.dialect.transformPrimitive(item, fieldDef.type);
|
|
2207
|
+
const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
2181
2208
|
if (Array.isArray(value)) {
|
|
2182
2209
|
result.push({
|
|
2183
2210
|
node: import_kysely7.RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
@@ -2408,9 +2435,18 @@ var PolicyPlugin = class {
|
|
|
2408
2435
|
get description() {
|
|
2409
2436
|
return "Enforces access policies defined in the schema.";
|
|
2410
2437
|
}
|
|
2411
|
-
onKyselyQuery({
|
|
2438
|
+
onKyselyQuery({
|
|
2439
|
+
query,
|
|
2440
|
+
client,
|
|
2441
|
+
proceed
|
|
2442
|
+
/*, transaction*/
|
|
2443
|
+
}) {
|
|
2412
2444
|
const handler = new PolicyHandler(client);
|
|
2413
|
-
return handler.handle(
|
|
2445
|
+
return handler.handle(
|
|
2446
|
+
query,
|
|
2447
|
+
proceed
|
|
2448
|
+
/*, transaction*/
|
|
2449
|
+
);
|
|
2414
2450
|
}
|
|
2415
2451
|
};
|
|
2416
2452
|
|
|
@@ -2551,7 +2587,12 @@ var BaseOperationHandler = class {
|
|
|
2551
2587
|
result = await query.execute();
|
|
2552
2588
|
} catch (err) {
|
|
2553
2589
|
const { sql: sql11, parameters } = query.compile();
|
|
2554
|
-
|
|
2590
|
+
let message = `Failed to execute query: ${err}, sql: ${sql11}`;
|
|
2591
|
+
if (this.options.debug) {
|
|
2592
|
+
message += `, parameters:
|
|
2593
|
+
${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
2594
|
+
}
|
|
2595
|
+
throw new QueryError(message, err);
|
|
2555
2596
|
}
|
|
2556
2597
|
if (inMemoryDistinct) {
|
|
2557
2598
|
const distinctResult = [];
|
|
@@ -2610,30 +2651,20 @@ var BaseOperationHandler = class {
|
|
|
2610
2651
|
for (const [field, value] of Object.entries(selections.select)) {
|
|
2611
2652
|
const fieldDef = requireField(this.schema, model, field);
|
|
2612
2653
|
const fieldModel = fieldDef.type;
|
|
2613
|
-
const
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
for (const [left, right] of joinPairs) {
|
|
2624
|
-
join = join.onRef(left, "=", right);
|
|
2625
|
-
}
|
|
2626
|
-
return join;
|
|
2627
|
-
});
|
|
2628
|
-
jsonObject[field] = this.countIdDistinct(eb, fieldDef.type, jointTable);
|
|
2654
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
2655
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
2656
|
+
for (const [left, right] of joinPairs) {
|
|
2657
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
2658
|
+
}
|
|
2659
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
2660
|
+
const filter = this.dialect.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
2661
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
2662
|
+
}
|
|
2663
|
+
jsonObject[field] = fieldCountQuery;
|
|
2629
2664
|
}
|
|
2630
2665
|
query = query.select((eb2) => this.dialect.buildJsonObject(eb2, jsonObject).as("_count"));
|
|
2631
2666
|
return query;
|
|
2632
2667
|
}
|
|
2633
|
-
countIdDistinct(eb, model, table) {
|
|
2634
|
-
const idFields = getIdFields(this.schema, model);
|
|
2635
|
-
return eb.fn.count(import_kysely8.sql.join(idFields.map((f) => import_kysely8.sql.ref(`${table}.${f}`)))).distinct();
|
|
2636
|
-
}
|
|
2637
2668
|
buildSelectAllScalarFields(model, query, omit) {
|
|
2638
2669
|
const modelDef = this.requireModel(model);
|
|
2639
2670
|
return Object.keys(modelDef.fields).filter((f) => !isRelationField(this.schema, model, f)).filter((f) => omit?.[f] !== true).reduce((acc, f) => this.selectField(acc, model, model, f), query);
|
|
@@ -2699,14 +2730,14 @@ var BaseOperationHandler = class {
|
|
|
2699
2730
|
const fieldDef = this.requireField(model, field);
|
|
2700
2731
|
if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
|
|
2701
2732
|
if (fieldDef.array && value && typeof value === "object" && "set" in value && Array.isArray(value.set)) {
|
|
2702
|
-
createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type);
|
|
2733
|
+
createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type, true);
|
|
2703
2734
|
} else {
|
|
2704
|
-
createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type);
|
|
2735
|
+
createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
2705
2736
|
}
|
|
2706
2737
|
} else {
|
|
2707
2738
|
const subM2M = getManyToManyRelation(this.schema, model, field);
|
|
2708
2739
|
if (!subM2M && fieldDef.relation?.fields && fieldDef.relation?.references) {
|
|
2709
|
-
const fkValues = await this.
|
|
2740
|
+
const fkValues = await this.processOwnedRelationForCreate(kysely, fieldDef, value);
|
|
2710
2741
|
for (let i = 0; i < fieldDef.relation.fields.length; i++) {
|
|
2711
2742
|
createFields[fieldDef.relation.fields[i]] = fkValues[fieldDef.relation.references[i]];
|
|
2712
2743
|
}
|
|
@@ -2727,7 +2758,7 @@ var BaseOperationHandler = class {
|
|
|
2727
2758
|
const createdEntity = await query.executeTakeFirst();
|
|
2728
2759
|
if (Object.keys(postCreateRelations).length > 0) {
|
|
2729
2760
|
const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
|
|
2730
|
-
return this.
|
|
2761
|
+
return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
|
|
2731
2762
|
});
|
|
2732
2763
|
await Promise.all(relationPromises);
|
|
2733
2764
|
}
|
|
@@ -2794,7 +2825,7 @@ var BaseOperationHandler = class {
|
|
|
2794
2825
|
const eb = (0, import_kysely8.expressionBuilder)();
|
|
2795
2826
|
return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
|
|
2796
2827
|
}
|
|
2797
|
-
async
|
|
2828
|
+
async processOwnedRelationForCreate(kysely, relationField, payload) {
|
|
2798
2829
|
if (!payload) {
|
|
2799
2830
|
return;
|
|
2800
2831
|
}
|
|
@@ -2844,21 +2875,27 @@ var BaseOperationHandler = class {
|
|
|
2844
2875
|
}
|
|
2845
2876
|
return result;
|
|
2846
2877
|
}
|
|
2847
|
-
|
|
2878
|
+
processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
|
|
2848
2879
|
const relationFieldDef = this.requireField(contextModel, relationFieldName);
|
|
2849
2880
|
const relationModel = relationFieldDef.type;
|
|
2850
2881
|
const tasks = [];
|
|
2882
|
+
const fromRelationContext = {
|
|
2883
|
+
model: contextModel,
|
|
2884
|
+
field: relationFieldName,
|
|
2885
|
+
ids: parentEntity
|
|
2886
|
+
};
|
|
2851
2887
|
for (const [action, subPayload] of Object.entries(payload)) {
|
|
2852
2888
|
if (!subPayload) {
|
|
2853
2889
|
continue;
|
|
2854
2890
|
}
|
|
2855
2891
|
switch (action) {
|
|
2856
2892
|
case "create": {
|
|
2857
|
-
tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item,
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2893
|
+
tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, fromRelationContext)));
|
|
2894
|
+
break;
|
|
2895
|
+
}
|
|
2896
|
+
case "createMany": {
|
|
2897
|
+
(0, import_common_helpers8.invariant)(relationFieldDef.array, "relation must be an array for createMany");
|
|
2898
|
+
tasks.push(this.createMany(kysely, relationModel, subPayload, false, fromRelationContext));
|
|
2862
2899
|
break;
|
|
2863
2900
|
}
|
|
2864
2901
|
case "connect": {
|
|
@@ -2888,6 +2925,11 @@ var BaseOperationHandler = class {
|
|
|
2888
2925
|
return Promise.all(tasks);
|
|
2889
2926
|
}
|
|
2890
2927
|
async createMany(kysely, model, input, returnData, fromRelation) {
|
|
2928
|
+
if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
|
|
2929
|
+
return returnData ? [] : {
|
|
2930
|
+
count: 0
|
|
2931
|
+
};
|
|
2932
|
+
}
|
|
2891
2933
|
const modelDef = this.requireModel(model);
|
|
2892
2934
|
let relationKeyPairs = [];
|
|
2893
2935
|
if (fromRelation) {
|
|
@@ -2902,7 +2944,7 @@ var BaseOperationHandler = class {
|
|
|
2902
2944
|
for (const [name, value] of Object.entries(item)) {
|
|
2903
2945
|
const fieldDef = this.requireField(model, name);
|
|
2904
2946
|
(0, import_common_helpers8.invariant)(!fieldDef.relation, "createMany does not support relations");
|
|
2905
|
-
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type);
|
|
2947
|
+
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
2906
2948
|
}
|
|
2907
2949
|
if (fromRelation) {
|
|
2908
2950
|
for (const { fk, pk } of relationKeyPairs) {
|
|
@@ -2937,7 +2979,7 @@ var BaseOperationHandler = class {
|
|
|
2937
2979
|
values[field] = generated;
|
|
2938
2980
|
}
|
|
2939
2981
|
} else if (fields[field]?.updatedAt) {
|
|
2940
|
-
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
|
|
2982
|
+
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
2941
2983
|
}
|
|
2942
2984
|
}
|
|
2943
2985
|
}
|
|
@@ -3002,7 +3044,7 @@ var BaseOperationHandler = class {
|
|
|
3002
3044
|
if (finalData === data) {
|
|
3003
3045
|
finalData = clone(data);
|
|
3004
3046
|
}
|
|
3005
|
-
finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
|
|
3047
|
+
finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
3006
3048
|
}
|
|
3007
3049
|
}
|
|
3008
3050
|
if (Object.keys(finalData).length === 0) {
|
|
@@ -3027,7 +3069,7 @@ var BaseOperationHandler = class {
|
|
|
3027
3069
|
updateFields[field] = this.transformScalarListUpdate(model, field, fieldDef, finalData[field]);
|
|
3028
3070
|
continue;
|
|
3029
3071
|
}
|
|
3030
|
-
updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type);
|
|
3072
|
+
updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type, !!fieldDef.array);
|
|
3031
3073
|
} else {
|
|
3032
3074
|
if (!allowRelationUpdate) {
|
|
3033
3075
|
throw new QueryError(`Relation update not allowed for field "${field}"`);
|
|
@@ -3072,7 +3114,7 @@ var BaseOperationHandler = class {
|
|
|
3072
3114
|
transformIncrementalUpdate(model, field, fieldDef, payload) {
|
|
3073
3115
|
(0, import_common_helpers8.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
|
|
3074
3116
|
const key = Object.keys(payload)[0];
|
|
3075
|
-
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
|
|
3117
|
+
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
|
|
3076
3118
|
const eb = (0, import_kysely8.expressionBuilder)();
|
|
3077
3119
|
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
|
|
3078
3120
|
return (0, import_ts_pattern8.match)(key).with("set", () => value).with("increment", () => eb(fieldRef, "+", value)).with("decrement", () => eb(fieldRef, "-", value)).with("multiply", () => eb(fieldRef, "*", value)).with("divide", () => eb(fieldRef, "/", value)).otherwise(() => {
|
|
@@ -3082,7 +3124,7 @@ var BaseOperationHandler = class {
|
|
|
3082
3124
|
transformScalarListUpdate(model, field, fieldDef, payload) {
|
|
3083
3125
|
(0, import_common_helpers8.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
|
|
3084
3126
|
const key = Object.keys(payload)[0];
|
|
3085
|
-
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
|
|
3127
|
+
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
|
|
3086
3128
|
const eb = (0, import_kysely8.expressionBuilder)();
|
|
3087
3129
|
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
|
|
3088
3130
|
return (0, import_ts_pattern8.match)(key).with("set", () => value).with("push", () => {
|
|
@@ -3112,7 +3154,7 @@ var BaseOperationHandler = class {
|
|
|
3112
3154
|
if (isRelationField(this.schema, model, field)) {
|
|
3113
3155
|
continue;
|
|
3114
3156
|
}
|
|
3115
|
-
updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type);
|
|
3157
|
+
updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
|
|
3116
3158
|
}
|
|
3117
3159
|
let query = kysely.updateTable(model).set(updateFields);
|
|
3118
3160
|
if (limit === void 0) {
|
|
@@ -3130,20 +3172,15 @@ var BaseOperationHandler = class {
|
|
|
3130
3172
|
model,
|
|
3131
3173
|
operation: "update"
|
|
3132
3174
|
}));
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
return result;
|
|
3143
|
-
}
|
|
3144
|
-
} catch (err) {
|
|
3145
|
-
const { sql: sql11, parameters } = query.compile();
|
|
3146
|
-
throw new QueryError(`Error during updateMany: ${err}, sql: ${sql11}, parameters: ${parameters}`);
|
|
3175
|
+
if (!returnData) {
|
|
3176
|
+
const result = await query.executeTakeFirstOrThrow();
|
|
3177
|
+
return {
|
|
3178
|
+
count: Number(result.numUpdatedRows)
|
|
3179
|
+
};
|
|
3180
|
+
} else {
|
|
3181
|
+
const idFields = getIdFields(this.schema, model);
|
|
3182
|
+
const result = await query.returning(idFields).execute();
|
|
3183
|
+
return result;
|
|
3147
3184
|
}
|
|
3148
3185
|
}
|
|
3149
3186
|
buildIdFieldRefs(kysely, model) {
|
|
@@ -3563,11 +3600,15 @@ var BaseOperationHandler = class {
|
|
|
3563
3600
|
}
|
|
3564
3601
|
return returnRelation;
|
|
3565
3602
|
}
|
|
3566
|
-
async safeTransaction(callback) {
|
|
3603
|
+
async safeTransaction(callback, isolationLevel) {
|
|
3567
3604
|
if (this.kysely.isTransaction) {
|
|
3568
3605
|
return callback(this.kysely);
|
|
3569
3606
|
} else {
|
|
3570
|
-
|
|
3607
|
+
let txBuilder = this.kysely.transaction();
|
|
3608
|
+
if (isolationLevel) {
|
|
3609
|
+
txBuilder = txBuilder.setIsolationLevel(isolationLevel);
|
|
3610
|
+
}
|
|
3611
|
+
return txBuilder.execute(callback);
|
|
3571
3612
|
}
|
|
3572
3613
|
}
|
|
3573
3614
|
// Given a unique filter of a model, return the entity ids by trying to
|
|
@@ -3586,6 +3627,28 @@ var BaseOperationHandler = class {
|
|
|
3586
3627
|
where: uniqueFilter
|
|
3587
3628
|
});
|
|
3588
3629
|
}
|
|
3630
|
+
/**
|
|
3631
|
+
* Normalize input args to strip `undefined` fields
|
|
3632
|
+
*/
|
|
3633
|
+
normalizeArgs(args) {
|
|
3634
|
+
if (!args) {
|
|
3635
|
+
return;
|
|
3636
|
+
}
|
|
3637
|
+
const newArgs = clone(args);
|
|
3638
|
+
this.doNormalizeArgs(newArgs);
|
|
3639
|
+
return newArgs;
|
|
3640
|
+
}
|
|
3641
|
+
doNormalizeArgs(args) {
|
|
3642
|
+
if (args && typeof args === "object") {
|
|
3643
|
+
for (const [key, value] of Object.entries(args)) {
|
|
3644
|
+
if (value === void 0) {
|
|
3645
|
+
delete args[key];
|
|
3646
|
+
} else if (value && (0, import_common_helpers8.isPlainObject)(value)) {
|
|
3647
|
+
this.doNormalizeArgs(value);
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3589
3652
|
};
|
|
3590
3653
|
|
|
3591
3654
|
// src/client/crud/operations/aggregate.ts
|
|
@@ -3594,21 +3657,22 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3594
3657
|
__name(this, "AggregateOperationHandler");
|
|
3595
3658
|
}
|
|
3596
3659
|
async handle(_operation, args) {
|
|
3597
|
-
const
|
|
3660
|
+
const normalizeArgs = this.normalizeArgs(args);
|
|
3661
|
+
const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizeArgs);
|
|
3598
3662
|
let query = this.kysely.selectFrom((eb) => {
|
|
3599
|
-
let subQuery = eb.selectFrom(this.model).selectAll(this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model,
|
|
3600
|
-
const skip =
|
|
3601
|
-
let take =
|
|
3663
|
+
let subQuery = eb.selectFrom(this.model).selectAll(this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
3664
|
+
const skip = parsedArgs?.skip;
|
|
3665
|
+
let take = parsedArgs?.take;
|
|
3602
3666
|
let negateOrderBy = false;
|
|
3603
3667
|
if (take !== void 0 && take < 0) {
|
|
3604
3668
|
negateOrderBy = true;
|
|
3605
3669
|
take = -take;
|
|
3606
3670
|
}
|
|
3607
3671
|
subQuery = this.dialect.buildSkipTake(subQuery, skip, take);
|
|
3608
|
-
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model,
|
|
3672
|
+
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, parsedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
3609
3673
|
return subQuery.as("$sub");
|
|
3610
3674
|
});
|
|
3611
|
-
for (const [key, value] of Object.entries(
|
|
3675
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3612
3676
|
switch (key) {
|
|
3613
3677
|
case "_count": {
|
|
3614
3678
|
if (value === true) {
|
|
@@ -3687,14 +3751,15 @@ var CountOperationHandler = class extends BaseOperationHandler {
|
|
|
3687
3751
|
__name(this, "CountOperationHandler");
|
|
3688
3752
|
}
|
|
3689
3753
|
async handle(_operation, args) {
|
|
3690
|
-
const
|
|
3754
|
+
const normalizeArgs = this.normalizeArgs(args);
|
|
3755
|
+
const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizeArgs);
|
|
3691
3756
|
let query = this.kysely.selectFrom((eb) => {
|
|
3692
|
-
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model,
|
|
3693
|
-
subQuery = this.dialect.buildSkipTake(subQuery,
|
|
3757
|
+
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
3758
|
+
subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
|
|
3694
3759
|
return subQuery.as("$sub");
|
|
3695
3760
|
});
|
|
3696
|
-
if (
|
|
3697
|
-
query = query.select((eb) => Object.keys(
|
|
3761
|
+
if (parsedArgs?.select && typeof parsedArgs.select === "object") {
|
|
3762
|
+
query = query.select((eb) => Object.keys(parsedArgs.select).map((key) => key === "_all" ? eb.cast(eb.fn.countAll(), "integer").as("_all") : eb.cast(eb.fn.count(import_kysely10.sql.ref(`$sub.${key}`)), "integer").as(key)));
|
|
3698
3763
|
return query.executeTakeFirstOrThrow();
|
|
3699
3764
|
} else {
|
|
3700
3765
|
query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
|
|
@@ -3711,10 +3776,11 @@ var CreateOperationHandler = class extends BaseOperationHandler {
|
|
|
3711
3776
|
__name(this, "CreateOperationHandler");
|
|
3712
3777
|
}
|
|
3713
3778
|
async handle(operation, args) {
|
|
3714
|
-
|
|
3715
|
-
|
|
3779
|
+
const normalizeArgs = this.normalizeArgs(args);
|
|
3780
|
+
return (0, import_ts_pattern10.match)(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, normalizeArgs))).with("createMany", () => {
|
|
3781
|
+
return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, normalizeArgs));
|
|
3716
3782
|
}).with("createManyAndReturn", () => {
|
|
3717
|
-
return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model,
|
|
3783
|
+
return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, normalizeArgs));
|
|
3718
3784
|
}).exhaustive();
|
|
3719
3785
|
}
|
|
3720
3786
|
async runCreate(args) {
|
|
@@ -3764,7 +3830,8 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
|
3764
3830
|
__name(this, "DeleteOperationHandler");
|
|
3765
3831
|
}
|
|
3766
3832
|
async handle(operation, args) {
|
|
3767
|
-
|
|
3833
|
+
const normalizeArgs = this.normalizeArgs(args);
|
|
3834
|
+
return (0, import_ts_pattern11.match)(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, normalizeArgs))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, normalizeArgs))).exhaustive();
|
|
3768
3835
|
}
|
|
3769
3836
|
async runDelete(args) {
|
|
3770
3837
|
const existing = await this.readUnique(this.kysely, this.model, {
|
|
@@ -3794,7 +3861,8 @@ var FindOperationHandler = class extends BaseOperationHandler {
|
|
|
3794
3861
|
__name(this, "FindOperationHandler");
|
|
3795
3862
|
}
|
|
3796
3863
|
async handle(operation, args, validateArgs = true) {
|
|
3797
|
-
const
|
|
3864
|
+
const normalizeArgs = this.normalizeArgs(args);
|
|
3865
|
+
const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", normalizeArgs) : normalizeArgs;
|
|
3798
3866
|
const result = await this.read(this.client.$qb, this.model, parsedArgs);
|
|
3799
3867
|
const finalResult = operation === "findMany" ? result : result[0] ?? null;
|
|
3800
3868
|
return finalResult;
|
|
@@ -3809,11 +3877,12 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3809
3877
|
__name(this, "GroupByeOperationHandler");
|
|
3810
3878
|
}
|
|
3811
3879
|
async handle(_operation, args) {
|
|
3812
|
-
const
|
|
3880
|
+
const normalizeArgs = this.normalizeArgs(args);
|
|
3881
|
+
const parsedArgs = this.inputValidator.validateGroupByArgs(this.model, normalizeArgs);
|
|
3813
3882
|
let query = this.kysely.selectFrom((eb) => {
|
|
3814
|
-
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model,
|
|
3815
|
-
const skip =
|
|
3816
|
-
let take =
|
|
3883
|
+
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
3884
|
+
const skip = parsedArgs?.skip;
|
|
3885
|
+
let take = parsedArgs?.take;
|
|
3817
3886
|
let negateOrderBy = false;
|
|
3818
3887
|
if (take !== void 0 && take < 0) {
|
|
3819
3888
|
negateOrderBy = true;
|
|
@@ -3823,20 +3892,20 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3823
3892
|
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
3824
3893
|
return subQuery.as("$sub");
|
|
3825
3894
|
});
|
|
3826
|
-
const bys = typeof
|
|
3827
|
-
|
|
3828
|
-
] :
|
|
3895
|
+
const bys = typeof parsedArgs.by === "string" ? [
|
|
3896
|
+
parsedArgs.by
|
|
3897
|
+
] : parsedArgs.by;
|
|
3829
3898
|
query = query.groupBy(bys);
|
|
3830
|
-
if (
|
|
3831
|
-
query = this.dialect.buildOrderBy(query, this.model, "$sub",
|
|
3899
|
+
if (parsedArgs.orderBy) {
|
|
3900
|
+
query = this.dialect.buildOrderBy(query, this.model, "$sub", parsedArgs.orderBy, false, false);
|
|
3832
3901
|
}
|
|
3833
|
-
if (
|
|
3834
|
-
query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub",
|
|
3902
|
+
if (parsedArgs.having) {
|
|
3903
|
+
query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub", parsedArgs.having));
|
|
3835
3904
|
}
|
|
3836
3905
|
for (const by of bys) {
|
|
3837
3906
|
query = query.select(() => import_kysely11.sql.ref(`$sub.${by}`).as(by));
|
|
3838
3907
|
}
|
|
3839
|
-
for (const [key, value] of Object.entries(
|
|
3908
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3840
3909
|
switch (key) {
|
|
3841
3910
|
case "_count": {
|
|
3842
3911
|
if (value === true) {
|
|
@@ -3919,7 +3988,8 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3919
3988
|
__name(this, "UpdateOperationHandler");
|
|
3920
3989
|
}
|
|
3921
3990
|
async handle(operation, args) {
|
|
3922
|
-
|
|
3991
|
+
const normalizeArgs = this.normalizeArgs(args);
|
|
3992
|
+
return (0, import_ts_pattern13.match)(operation).with("update", () => this.runUpdate(this.inputValidator.validateUpdateArgs(this.model, normalizeArgs))).with("updateMany", () => this.runUpdateMany(this.inputValidator.validateUpdateManyArgs(this.model, normalizeArgs))).with("updateManyAndReturn", () => this.runUpdateManyAndReturn(this.inputValidator.validateUpdateManyAndReturnArgs(this.model, normalizeArgs))).with("upsert", () => this.runUpsert(this.inputValidator.validateUpsertArgs(this.model, normalizeArgs))).exhaustive();
|
|
3923
3993
|
}
|
|
3924
3994
|
async runUpdate(args) {
|
|
3925
3995
|
const result = await this.safeTransaction(async (tx) => {
|
|
@@ -3975,6 +4045,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3975
4045
|
};
|
|
3976
4046
|
|
|
3977
4047
|
// src/client/crud/validator.ts
|
|
4048
|
+
var import_common_helpers9 = require("@zenstackhq/common-helpers");
|
|
3978
4049
|
var import_decimal = __toESM(require("decimal.js"), 1);
|
|
3979
4050
|
var import_json_stable_stringify = __toESM(require("json-stable-stringify"), 1);
|
|
3980
4051
|
var import_ts_pattern14 = require("ts-pattern");
|
|
@@ -4043,7 +4114,7 @@ var InputValidator = class {
|
|
|
4043
4114
|
}
|
|
4044
4115
|
const { error } = schema.safeParse(args);
|
|
4045
4116
|
if (error) {
|
|
4046
|
-
throw new
|
|
4117
|
+
throw new InputValidationError(`Invalid ${operation} args: ${error.message}`, error);
|
|
4047
4118
|
}
|
|
4048
4119
|
return args;
|
|
4049
4120
|
}
|
|
@@ -4090,7 +4161,7 @@ var InputValidator = class {
|
|
|
4090
4161
|
makeWhereSchema(model, unique, withoutRelationFields = false) {
|
|
4091
4162
|
const modelDef = getModel(this.schema, model);
|
|
4092
4163
|
if (!modelDef) {
|
|
4093
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
4164
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
4094
4165
|
}
|
|
4095
4166
|
const fields = {};
|
|
4096
4167
|
for (const field of Object.keys(modelDef.fields)) {
|
|
@@ -4140,10 +4211,24 @@ var InputValidator = class {
|
|
|
4140
4211
|
const uniqueFields = getUniqueFields(this.schema, model);
|
|
4141
4212
|
for (const uniqueField of uniqueFields) {
|
|
4142
4213
|
if ("defs" in uniqueField) {
|
|
4143
|
-
fields[uniqueField.name] = import_v4.z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) =>
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4214
|
+
fields[uniqueField.name] = import_v4.z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
|
|
4215
|
+
(0, import_common_helpers9.invariant)(!def.relation, "unique field cannot be a relation");
|
|
4216
|
+
let fieldSchema;
|
|
4217
|
+
const enumDef = getEnum(this.schema, def.type);
|
|
4218
|
+
if (enumDef) {
|
|
4219
|
+
if (Object.keys(enumDef).length > 0) {
|
|
4220
|
+
fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional);
|
|
4221
|
+
} else {
|
|
4222
|
+
fieldSchema = import_v4.z.never();
|
|
4223
|
+
}
|
|
4224
|
+
} else {
|
|
4225
|
+
fieldSchema = this.makePrimitiveFilterSchema(def.type, !!def.optional);
|
|
4226
|
+
}
|
|
4227
|
+
return [
|
|
4228
|
+
key,
|
|
4229
|
+
fieldSchema
|
|
4230
|
+
];
|
|
4231
|
+
}))).optional();
|
|
4147
4232
|
}
|
|
4148
4233
|
}
|
|
4149
4234
|
}
|
|
@@ -4193,7 +4278,7 @@ var InputValidator = class {
|
|
|
4193
4278
|
});
|
|
4194
4279
|
}
|
|
4195
4280
|
makePrimitiveFilterSchema(type, optional) {
|
|
4196
|
-
return (0, import_ts_pattern14.match)(type).with("String", () => this.makeStringFilterSchema(optional)).with(import_ts_pattern14.P.union("Int", "Float", "Decimal", "BigInt"), (type2) => this.makeNumberFilterSchema(this.makePrimitiveSchema(type2), optional)).with("Boolean", () => this.makeBooleanFilterSchema(optional)).with("DateTime", () => this.makeDateTimeFilterSchema(optional)).with("Bytes", () => this.makeBytesFilterSchema(optional)).exhaustive();
|
|
4281
|
+
return (0, import_ts_pattern14.match)(type).with("String", () => this.makeStringFilterSchema(optional)).with(import_ts_pattern14.P.union("Int", "Float", "Decimal", "BigInt"), (type2) => this.makeNumberFilterSchema(this.makePrimitiveSchema(type2), optional)).with("Boolean", () => this.makeBooleanFilterSchema(optional)).with("DateTime", () => this.makeDateTimeFilterSchema(optional)).with("Bytes", () => this.makeBytesFilterSchema(optional)).with("Json", () => import_v4.z.any()).with("Unsupported", () => import_v4.z.never()).exhaustive();
|
|
4197
4282
|
}
|
|
4198
4283
|
makeDateTimeFilterSchema(optional) {
|
|
4199
4284
|
return this.makeCommonPrimitiveFilterSchema(import_v4.z.union([
|
|
@@ -4387,8 +4472,8 @@ var InputValidator = class {
|
|
|
4387
4472
|
return this.refineForSelectOmitMutuallyExclusive(result).optional();
|
|
4388
4473
|
}
|
|
4389
4474
|
makeCreateDataSchema(model, canBeArray, withoutFields = [], withoutRelationFields = false) {
|
|
4390
|
-
const
|
|
4391
|
-
const
|
|
4475
|
+
const uncheckedVariantFields = {};
|
|
4476
|
+
const checkedVariantFields = {};
|
|
4392
4477
|
const modelDef = requireModel(this.schema, model);
|
|
4393
4478
|
const hasRelation = !withoutRelationFields && Object.entries(modelDef.fields).some(([f, def]) => !withoutFields.includes(f) && def.relation);
|
|
4394
4479
|
Object.keys(modelDef.fields).forEach((field) => {
|
|
@@ -4430,7 +4515,10 @@ var InputValidator = class {
|
|
|
4430
4515
|
if (fieldDef.optional && !fieldDef.array) {
|
|
4431
4516
|
fieldSchema = fieldSchema.nullable();
|
|
4432
4517
|
}
|
|
4433
|
-
|
|
4518
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4519
|
+
if (fieldDef.array || !fieldDef.relation.references) {
|
|
4520
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4521
|
+
}
|
|
4434
4522
|
} else {
|
|
4435
4523
|
let fieldSchema = this.makePrimitiveSchema(fieldDef.type);
|
|
4436
4524
|
if (fieldDef.array) {
|
|
@@ -4447,23 +4535,23 @@ var InputValidator = class {
|
|
|
4447
4535
|
if (fieldDef.optional) {
|
|
4448
4536
|
fieldSchema = fieldSchema.nullable();
|
|
4449
4537
|
}
|
|
4450
|
-
|
|
4538
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4451
4539
|
if (!fieldDef.foreignKeyFor) {
|
|
4452
|
-
|
|
4540
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4453
4541
|
}
|
|
4454
4542
|
}
|
|
4455
4543
|
});
|
|
4456
4544
|
if (!hasRelation) {
|
|
4457
|
-
return this.orArray(import_v4.z.object(
|
|
4545
|
+
return this.orArray(import_v4.z.object(uncheckedVariantFields).strict(), canBeArray);
|
|
4458
4546
|
} else {
|
|
4459
4547
|
return import_v4.z.union([
|
|
4460
|
-
import_v4.z.object(
|
|
4461
|
-
import_v4.z.object(
|
|
4548
|
+
import_v4.z.object(uncheckedVariantFields).strict(),
|
|
4549
|
+
import_v4.z.object(checkedVariantFields).strict(),
|
|
4462
4550
|
...canBeArray ? [
|
|
4463
|
-
import_v4.z.array(import_v4.z.object(
|
|
4551
|
+
import_v4.z.array(import_v4.z.object(uncheckedVariantFields).strict())
|
|
4464
4552
|
] : [],
|
|
4465
4553
|
...canBeArray ? [
|
|
4466
|
-
import_v4.z.array(import_v4.z.object(
|
|
4554
|
+
import_v4.z.array(import_v4.z.object(checkedVariantFields).strict())
|
|
4467
4555
|
] : []
|
|
4468
4556
|
]);
|
|
4469
4557
|
}
|
|
@@ -4508,7 +4596,7 @@ var InputValidator = class {
|
|
|
4508
4596
|
fields["deleteMany"] = this.makeDeleteRelationDataSchema(fieldType, true, false).optional();
|
|
4509
4597
|
}
|
|
4510
4598
|
}
|
|
4511
|
-
return import_v4.z.object(fields).strict()
|
|
4599
|
+
return import_v4.z.object(fields).strict();
|
|
4512
4600
|
}
|
|
4513
4601
|
makeSetDataSchema(model, canBeArray) {
|
|
4514
4602
|
return this.orArray(this.makeWhereSchema(model, true), canBeArray);
|
|
@@ -4945,6 +5033,7 @@ __name(performanceNow, "performanceNow");
|
|
|
4945
5033
|
// src/client/executor/zenstack-query-executor.ts
|
|
4946
5034
|
var import_kysely13 = require("kysely");
|
|
4947
5035
|
var import_nanoid2 = require("nanoid");
|
|
5036
|
+
var import_node_util2 = require("util");
|
|
4948
5037
|
var import_ts_pattern15 = require("ts-pattern");
|
|
4949
5038
|
|
|
4950
5039
|
// src/client/executor/name-mapper.ts
|
|
@@ -5179,7 +5268,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5179
5268
|
mutationInterceptionInfo = await this.callMutationInterceptionFilters(queryNode);
|
|
5180
5269
|
}
|
|
5181
5270
|
const task = /* @__PURE__ */ __name(async () => {
|
|
5182
|
-
|
|
5271
|
+
if (this.isMutationNode(queryNode)) {
|
|
5272
|
+
await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
|
|
5273
|
+
}
|
|
5183
5274
|
const oldQueryNode = queryNode;
|
|
5184
5275
|
if ((import_kysely13.InsertQueryNode.is(queryNode) || import_kysely13.DeleteQueryNode.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
|
|
5185
5276
|
queryNode = {
|
|
@@ -5191,18 +5282,17 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5191
5282
|
}
|
|
5192
5283
|
const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
|
|
5193
5284
|
const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams, queryId);
|
|
5194
|
-
|
|
5285
|
+
if (this.isMutationNode(queryNode)) {
|
|
5286
|
+
await this.callAfterQueryInterceptionFilters(result, queryNode, mutationInterceptionInfo);
|
|
5287
|
+
}
|
|
5195
5288
|
if (oldQueryNode !== queryNode) {
|
|
5196
5289
|
}
|
|
5197
5290
|
return result;
|
|
5198
5291
|
}, "task");
|
|
5199
|
-
return
|
|
5292
|
+
return task();
|
|
5200
5293
|
}
|
|
5201
5294
|
proceedQueryWithKyselyInterceptors(queryNode, parameters, queryId) {
|
|
5202
5295
|
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters, queryId), "proceed");
|
|
5203
|
-
const makeTx = /* @__PURE__ */ __name((p) => (callback) => {
|
|
5204
|
-
return this.executeWithTransaction(() => callback(p));
|
|
5205
|
-
}, "makeTx");
|
|
5206
5296
|
const hooks = this.options.plugins?.filter((plugin) => typeof plugin.onKyselyQuery === "function").map((plugin) => plugin.onKyselyQuery.bind(plugin)) ?? [];
|
|
5207
5297
|
for (const hook of hooks) {
|
|
5208
5298
|
const _proceed = proceed;
|
|
@@ -5212,8 +5302,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5212
5302
|
schema: this.client.$schema,
|
|
5213
5303
|
kysely: this.kysely,
|
|
5214
5304
|
query,
|
|
5215
|
-
proceed: _proceed
|
|
5216
|
-
transaction: makeTx(_proceed)
|
|
5305
|
+
proceed: _proceed
|
|
5217
5306
|
});
|
|
5218
5307
|
}, "proceed");
|
|
5219
5308
|
}
|
|
@@ -5229,9 +5318,14 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5229
5318
|
};
|
|
5230
5319
|
}
|
|
5231
5320
|
try {
|
|
5232
|
-
return
|
|
5321
|
+
return await super.executeQuery(compiled, queryId);
|
|
5233
5322
|
} catch (err) {
|
|
5234
|
-
|
|
5323
|
+
let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
|
|
5324
|
+
if (this.options.debug) {
|
|
5325
|
+
message += `, parameters:
|
|
5326
|
+
${compiled.parameters.map((p) => (0, import_node_util2.inspect)(p)).join("\n")}`;
|
|
5327
|
+
}
|
|
5328
|
+
throw new QueryError(message, err);
|
|
5235
5329
|
}
|
|
5236
5330
|
}
|
|
5237
5331
|
isMutationNode(queryNode) {
|
|
@@ -5259,24 +5353,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5259
5353
|
return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, []);
|
|
5260
5354
|
}
|
|
5261
5355
|
withConnectionProvider(connectionProvider) {
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
if (!useTransaction || this.driver.txConnection) {
|
|
5266
|
-
return callback();
|
|
5267
|
-
} else {
|
|
5268
|
-
return this.provideConnection(async (connection) => {
|
|
5269
|
-
try {
|
|
5270
|
-
await this.driver.beginTransaction(connection, {});
|
|
5271
|
-
const result = await callback();
|
|
5272
|
-
await this.driver.commitTransaction(connection);
|
|
5273
|
-
return result;
|
|
5274
|
-
} catch (error) {
|
|
5275
|
-
await this.driver.rollbackTransaction(connection);
|
|
5276
|
-
throw error;
|
|
5277
|
-
}
|
|
5278
|
-
});
|
|
5279
|
-
}
|
|
5356
|
+
const newExecutor = new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
|
|
5357
|
+
newExecutor.client = this.client.withExecutor(newExecutor);
|
|
5358
|
+
return newExecutor;
|
|
5280
5359
|
}
|
|
5281
5360
|
get hasMutationHooks() {
|
|
5282
5361
|
return this.client.$options.plugins?.some((plugin) => plugin.beforeEntityMutation || plugin.afterEntityMutation);
|
|
@@ -5318,14 +5397,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5318
5397
|
queryNode
|
|
5319
5398
|
});
|
|
5320
5399
|
result.intercept ||= filterResult.intercept;
|
|
5321
|
-
result.useTransactionForMutation ||= filterResult.useTransactionForMutation;
|
|
5322
5400
|
result.loadBeforeMutationEntity ||= filterResult.loadBeforeMutationEntity;
|
|
5323
5401
|
result.loadAfterMutationEntity ||= filterResult.loadAfterMutationEntity;
|
|
5324
5402
|
}
|
|
5325
5403
|
}
|
|
5326
5404
|
let beforeMutationEntities;
|
|
5327
5405
|
if (result.loadBeforeMutationEntity && (import_kysely13.UpdateQueryNode.is(queryNode) || import_kysely13.DeleteQueryNode.is(queryNode))) {
|
|
5328
|
-
beforeMutationEntities = await this.loadEntities(
|
|
5406
|
+
beforeMutationEntities = await this.loadEntities(mutationModel, where);
|
|
5329
5407
|
}
|
|
5330
5408
|
return {
|
|
5331
5409
|
...result,
|
|
@@ -5338,15 +5416,14 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5338
5416
|
return void 0;
|
|
5339
5417
|
}
|
|
5340
5418
|
}
|
|
5341
|
-
callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
5419
|
+
async callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
5342
5420
|
if (!mutationInterceptionInfo?.intercept) {
|
|
5343
5421
|
return;
|
|
5344
5422
|
}
|
|
5345
5423
|
if (this.options.plugins) {
|
|
5346
5424
|
for (const plugin of this.options.plugins) {
|
|
5347
5425
|
if (plugin.beforeEntityMutation) {
|
|
5348
|
-
plugin.beforeEntityMutation({
|
|
5349
|
-
// context: this.queryContext,
|
|
5426
|
+
await plugin.beforeEntityMutation({
|
|
5350
5427
|
model: this.getMutationModel(queryNode),
|
|
5351
5428
|
action: mutationInterceptionInfo.action,
|
|
5352
5429
|
queryNode,
|
|
@@ -5367,12 +5444,12 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5367
5444
|
let afterMutationEntities = void 0;
|
|
5368
5445
|
if (mutationInterceptionInfo.loadAfterMutationEntity) {
|
|
5369
5446
|
if (import_kysely13.UpdateQueryNode.is(queryNode)) {
|
|
5370
|
-
afterMutationEntities = await this.loadEntities(
|
|
5447
|
+
afterMutationEntities = await this.loadEntities(mutationModel, mutationInterceptionInfo.where);
|
|
5371
5448
|
} else {
|
|
5372
5449
|
afterMutationEntities = queryResult.rows;
|
|
5373
5450
|
}
|
|
5374
5451
|
}
|
|
5375
|
-
plugin.afterEntityMutation({
|
|
5452
|
+
await plugin.afterEntityMutation({
|
|
5376
5453
|
model: this.getMutationModel(queryNode),
|
|
5377
5454
|
action: mutationInterceptionInfo.action,
|
|
5378
5455
|
queryNode,
|
|
@@ -5383,17 +5460,17 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5383
5460
|
}
|
|
5384
5461
|
}
|
|
5385
5462
|
}
|
|
5386
|
-
async loadEntities(
|
|
5387
|
-
const selectQuery = kysely.selectFrom(model).selectAll();
|
|
5463
|
+
async loadEntities(model, where) {
|
|
5464
|
+
const selectQuery = this.kysely.selectFrom(model).selectAll();
|
|
5388
5465
|
let selectQueryNode = selectQuery.toOperationNode();
|
|
5389
5466
|
selectQueryNode = {
|
|
5390
5467
|
...selectQueryNode,
|
|
5391
5468
|
where: this.andNodes(selectQueryNode.where, where)
|
|
5392
5469
|
};
|
|
5393
|
-
const compiled =
|
|
5470
|
+
const compiled = this.compileQuery(selectQueryNode);
|
|
5471
|
+
const result = await this.executeQuery(compiled, {
|
|
5394
5472
|
queryId: `zenstack-${(0, import_nanoid2.nanoid)()}`
|
|
5395
5473
|
});
|
|
5396
|
-
const result = await kysely.executeQuery(compiled);
|
|
5397
5474
|
return result.rows;
|
|
5398
5475
|
}
|
|
5399
5476
|
andNodes(condition1, condition2) {
|
|
@@ -5422,7 +5499,7 @@ __export(functions_exports, {
|
|
|
5422
5499
|
search: () => search,
|
|
5423
5500
|
startsWith: () => startsWith
|
|
5424
5501
|
});
|
|
5425
|
-
var
|
|
5502
|
+
var import_common_helpers10 = require("@zenstackhq/common-helpers");
|
|
5426
5503
|
var import_kysely14 = require("kysely");
|
|
5427
5504
|
var import_ts_pattern16 = require("ts-pattern");
|
|
5428
5505
|
var contains = /* @__PURE__ */ __name((eb, args) => {
|
|
@@ -5529,8 +5606,8 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
|
5529
5606
|
}, "currentOperation");
|
|
5530
5607
|
function processCasing(casing, result, model) {
|
|
5531
5608
|
const opNode = casing.toOperationNode();
|
|
5532
|
-
(0,
|
|
5533
|
-
result = (0, import_ts_pattern16.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => (0,
|
|
5609
|
+
(0, import_common_helpers10.invariant)(import_kysely14.ValueNode.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
|
|
5610
|
+
result = (0, import_ts_pattern16.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => (0, import_common_helpers10.upperCaseFirst)(result)).with("uncapitalize", () => (0, import_common_helpers10.lowerCaseFirst)(result)).otherwise(() => {
|
|
5534
5611
|
throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
|
|
5535
5612
|
});
|
|
5536
5613
|
return result;
|
|
@@ -5538,7 +5615,7 @@ function processCasing(casing, result, model) {
|
|
|
5538
5615
|
__name(processCasing, "processCasing");
|
|
5539
5616
|
|
|
5540
5617
|
// src/client/helpers/schema-db-pusher.ts
|
|
5541
|
-
var
|
|
5618
|
+
var import_common_helpers11 = require("@zenstackhq/common-helpers");
|
|
5542
5619
|
var import_kysely15 = require("kysely");
|
|
5543
5620
|
var import_ts_pattern17 = require("ts-pattern");
|
|
5544
5621
|
var SchemaDbPusher = class {
|
|
@@ -5595,7 +5672,7 @@ var SchemaDbPusher = class {
|
|
|
5595
5672
|
}
|
|
5596
5673
|
addUniqueConstraint(table, modelDef) {
|
|
5597
5674
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
5598
|
-
(0,
|
|
5675
|
+
(0, import_common_helpers11.invariant)(typeof value === "object", "expecting an object");
|
|
5599
5676
|
if ("type" in value) {
|
|
5600
5677
|
const fieldDef = modelDef.fields[key];
|
|
5601
5678
|
if (fieldDef.unique) {
|
|
@@ -5641,7 +5718,7 @@ var SchemaDbPusher = class {
|
|
|
5641
5718
|
return "serial";
|
|
5642
5719
|
}
|
|
5643
5720
|
const type = fieldDef.type;
|
|
5644
|
-
const result = (0, import_ts_pattern17.match)(type).with("String", () => "text").with("Boolean", () => "boolean").with("Int", () => "integer").with("Float", () => "real").with("BigInt", () => "bigint").with("Decimal", () => "decimal").with("DateTime", () => "timestamp").with("Bytes", () => this.schema.provider.type === "postgresql" ? "bytea" : "blob").otherwise(() => {
|
|
5721
|
+
const result = (0, import_ts_pattern17.match)(type).with("String", () => "text").with("Boolean", () => "boolean").with("Int", () => "integer").with("Float", () => "real").with("BigInt", () => "bigint").with("Decimal", () => "decimal").with("DateTime", () => "timestamp").with("Bytes", () => this.schema.provider.type === "postgresql" ? "bytea" : "blob").with("Json", () => "jsonb").otherwise(() => {
|
|
5645
5722
|
throw new Error(`Unsupported field type: ${type}`);
|
|
5646
5723
|
});
|
|
5647
5724
|
if (fieldDef.array) {
|
|
@@ -5654,7 +5731,7 @@ var SchemaDbPusher = class {
|
|
|
5654
5731
|
return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
|
|
5655
5732
|
}
|
|
5656
5733
|
addForeignKeyConstraint(table, model, fieldName, fieldDef) {
|
|
5657
|
-
(0,
|
|
5734
|
+
(0, import_common_helpers11.invariant)(fieldDef.relation, "field must be a relation");
|
|
5658
5735
|
if (!fieldDef.relation.fields || !fieldDef.relation.references) {
|
|
5659
5736
|
return table;
|
|
5660
5737
|
}
|
|
@@ -5675,11 +5752,11 @@ var SchemaDbPusher = class {
|
|
|
5675
5752
|
};
|
|
5676
5753
|
|
|
5677
5754
|
// src/client/promise.ts
|
|
5678
|
-
function
|
|
5755
|
+
function createZenStackPromise(callback) {
|
|
5679
5756
|
let promise;
|
|
5680
|
-
const cb = /* @__PURE__ */ __name(() => {
|
|
5757
|
+
const cb = /* @__PURE__ */ __name((txClient) => {
|
|
5681
5758
|
try {
|
|
5682
|
-
return promise ??= valueToPromise(callback());
|
|
5759
|
+
return promise ??= valueToPromise(callback(txClient));
|
|
5683
5760
|
} catch (err) {
|
|
5684
5761
|
return Promise.reject(err);
|
|
5685
5762
|
}
|
|
@@ -5694,10 +5771,11 @@ function createDeferredPromise(callback) {
|
|
|
5694
5771
|
finally(onFinally) {
|
|
5695
5772
|
return cb().finally(onFinally);
|
|
5696
5773
|
},
|
|
5774
|
+
cb,
|
|
5697
5775
|
[Symbol.toStringTag]: "ZenStackPromise"
|
|
5698
5776
|
};
|
|
5699
5777
|
}
|
|
5700
|
-
__name(
|
|
5778
|
+
__name(createZenStackPromise, "createZenStackPromise");
|
|
5701
5779
|
function valueToPromise(thing) {
|
|
5702
5780
|
if (typeof thing === "object" && typeof thing?.then === "function") {
|
|
5703
5781
|
return thing;
|
|
@@ -5708,7 +5786,7 @@ function valueToPromise(thing) {
|
|
|
5708
5786
|
__name(valueToPromise, "valueToPromise");
|
|
5709
5787
|
|
|
5710
5788
|
// src/client/result-processor.ts
|
|
5711
|
-
var
|
|
5789
|
+
var import_common_helpers12 = require("@zenstackhq/common-helpers");
|
|
5712
5790
|
var import_decimal2 = __toESM(require("decimal.js"), 1);
|
|
5713
5791
|
var import_ts_pattern18 = require("ts-pattern");
|
|
5714
5792
|
var ResultProcessor = class {
|
|
@@ -5783,20 +5861,20 @@ var ResultProcessor = class {
|
|
|
5783
5861
|
return this.doProcessResult(relationData, fieldDef.type);
|
|
5784
5862
|
}
|
|
5785
5863
|
transformScalar(value, type) {
|
|
5786
|
-
return (0, import_ts_pattern18.match)(type).with("Boolean", () => this.transformBoolean(value)).with("DateTime", () => this.transformDate(value)).with("Bytes", () => this.transformBytes(value)).with("Decimal", () => this.transformDecimal(value)).with("BigInt", () => this.transformBigInt(value)).otherwise(() => value);
|
|
5864
|
+
return (0, import_ts_pattern18.match)(type).with("Boolean", () => this.transformBoolean(value)).with("DateTime", () => this.transformDate(value)).with("Bytes", () => this.transformBytes(value)).with("Decimal", () => this.transformDecimal(value)).with("BigInt", () => this.transformBigInt(value)).with("Json", () => this.transformJson(value)).otherwise(() => value);
|
|
5787
5865
|
}
|
|
5788
5866
|
transformDecimal(value) {
|
|
5789
5867
|
if (value instanceof import_decimal2.default) {
|
|
5790
5868
|
return value;
|
|
5791
5869
|
}
|
|
5792
|
-
(0,
|
|
5870
|
+
(0, import_common_helpers12.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal2.default, `Expected string, number or Decimal, got ${typeof value}`);
|
|
5793
5871
|
return new import_decimal2.default(value);
|
|
5794
5872
|
}
|
|
5795
5873
|
transformBigInt(value) {
|
|
5796
5874
|
if (typeof value === "bigint") {
|
|
5797
5875
|
return value;
|
|
5798
5876
|
}
|
|
5799
|
-
(0,
|
|
5877
|
+
(0, import_common_helpers12.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
5800
5878
|
return BigInt(value);
|
|
5801
5879
|
}
|
|
5802
5880
|
transformBoolean(value) {
|
|
@@ -5815,6 +5893,9 @@ var ResultProcessor = class {
|
|
|
5815
5893
|
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
5816
5894
|
}
|
|
5817
5895
|
fixReversedResult(data, model, args) {
|
|
5896
|
+
if (!data) {
|
|
5897
|
+
return;
|
|
5898
|
+
}
|
|
5818
5899
|
if (Array.isArray(data) && typeof args === "object" && args && args.take !== void 0 && args.take < 0) {
|
|
5819
5900
|
data.reverse();
|
|
5820
5901
|
}
|
|
@@ -5828,13 +5909,19 @@ var ResultProcessor = class {
|
|
|
5828
5909
|
continue;
|
|
5829
5910
|
}
|
|
5830
5911
|
const fieldDef = getField(this.schema, model, field);
|
|
5831
|
-
if (!fieldDef
|
|
5912
|
+
if (!fieldDef || !fieldDef.relation || !fieldDef.array) {
|
|
5832
5913
|
continue;
|
|
5833
5914
|
}
|
|
5834
5915
|
this.fixReversedResult(row[field], fieldDef.type, value);
|
|
5835
5916
|
}
|
|
5836
5917
|
}
|
|
5837
5918
|
}
|
|
5919
|
+
transformJson(value) {
|
|
5920
|
+
return (0, import_ts_pattern18.match)(this.schema.provider.type).with("sqlite", () => {
|
|
5921
|
+
(0, import_common_helpers12.invariant)(typeof value === "string", "Expected string, got " + typeof value);
|
|
5922
|
+
return JSON.parse(value);
|
|
5923
|
+
}).otherwise(() => value);
|
|
5924
|
+
}
|
|
5838
5925
|
};
|
|
5839
5926
|
|
|
5840
5927
|
// src/client/client-impl.ts
|
|
@@ -5853,7 +5940,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
5853
5940
|
$schema;
|
|
5854
5941
|
kyselyProps;
|
|
5855
5942
|
auth;
|
|
5856
|
-
constructor(schema, options, baseClient) {
|
|
5943
|
+
constructor(schema, options, baseClient, executor) {
|
|
5857
5944
|
this.schema = schema;
|
|
5858
5945
|
this.options = options;
|
|
5859
5946
|
this.$schema = schema;
|
|
@@ -5865,16 +5952,16 @@ var ClientImpl = class _ClientImpl {
|
|
|
5865
5952
|
if (baseClient) {
|
|
5866
5953
|
this.kyselyProps = {
|
|
5867
5954
|
...baseClient.kyselyProps,
|
|
5868
|
-
executor: new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new import_kysely16.DefaultConnectionProvider(baseClient.kyselyProps.driver))
|
|
5955
|
+
executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new import_kysely16.DefaultConnectionProvider(baseClient.kyselyProps.driver))
|
|
5869
5956
|
};
|
|
5870
5957
|
this.kyselyRaw = baseClient.kyselyRaw;
|
|
5958
|
+
this.auth = baseClient.auth;
|
|
5871
5959
|
} else {
|
|
5872
5960
|
const dialect = this.getKyselyDialect();
|
|
5873
5961
|
const driver = new ZenStackDriver(dialect.createDriver(), new import_kysely16.Log(this.$options.log ?? []));
|
|
5874
5962
|
const compiler = dialect.createQueryCompiler();
|
|
5875
5963
|
const adapter = dialect.createAdapter();
|
|
5876
5964
|
const connectionProvider = new import_kysely16.DefaultConnectionProvider(driver);
|
|
5877
|
-
const executor = new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider);
|
|
5878
5965
|
this.kyselyProps = {
|
|
5879
5966
|
config: {
|
|
5880
5967
|
dialect,
|
|
@@ -5882,7 +5969,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
5882
5969
|
},
|
|
5883
5970
|
dialect,
|
|
5884
5971
|
driver,
|
|
5885
|
-
executor
|
|
5972
|
+
executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
|
|
5886
5973
|
};
|
|
5887
5974
|
this.kyselyRaw = new import_kysely16.Kysely({
|
|
5888
5975
|
...this.kyselyProps,
|
|
@@ -5898,6 +5985,15 @@ var ClientImpl = class _ClientImpl {
|
|
|
5898
5985
|
get $qbRaw() {
|
|
5899
5986
|
return this.kyselyRaw;
|
|
5900
5987
|
}
|
|
5988
|
+
get isTransaction() {
|
|
5989
|
+
return this.kysely.isTransaction;
|
|
5990
|
+
}
|
|
5991
|
+
/**
|
|
5992
|
+
* Create a new client with a new query executor.
|
|
5993
|
+
*/
|
|
5994
|
+
withExecutor(executor) {
|
|
5995
|
+
return new _ClientImpl(this.schema, this.$options, this, executor);
|
|
5996
|
+
}
|
|
5901
5997
|
getKyselyDialect() {
|
|
5902
5998
|
return (0, import_ts_pattern19.match)(this.schema.provider.type).with("sqlite", () => this.makeSqliteKyselyDialect()).with("postgresql", () => this.makePostgresKyselyDialect()).exhaustive();
|
|
5903
5999
|
}
|
|
@@ -5907,12 +6003,49 @@ var ClientImpl = class _ClientImpl {
|
|
|
5907
6003
|
makeSqliteKyselyDialect() {
|
|
5908
6004
|
return new import_kysely16.SqliteDialect(this.options.dialectConfig);
|
|
5909
6005
|
}
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
6006
|
+
// implementation
|
|
6007
|
+
async $transaction(input, options) {
|
|
6008
|
+
(0, import_common_helpers13.invariant)(typeof input === "function" || Array.isArray(input) && input.every((p) => p.then && p.cb), "Invalid transaction input, expected a function or an array of ZenStackPromise");
|
|
6009
|
+
if (typeof input === "function") {
|
|
6010
|
+
return this.interactiveTransaction(input, options);
|
|
6011
|
+
} else {
|
|
6012
|
+
return this.sequentialTransaction(input, options);
|
|
6013
|
+
}
|
|
6014
|
+
}
|
|
6015
|
+
async interactiveTransaction(callback, options) {
|
|
6016
|
+
if (this.kysely.isTransaction) {
|
|
6017
|
+
return callback(this);
|
|
6018
|
+
} else {
|
|
6019
|
+
let txBuilder = this.kysely.transaction();
|
|
6020
|
+
if (options?.isolationLevel) {
|
|
6021
|
+
txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
|
|
6022
|
+
}
|
|
6023
|
+
return txBuilder.execute((tx) => {
|
|
6024
|
+
const txClient = new _ClientImpl(this.schema, this.$options, this);
|
|
6025
|
+
txClient.kysely = tx;
|
|
6026
|
+
return callback(txClient);
|
|
6027
|
+
});
|
|
6028
|
+
}
|
|
6029
|
+
}
|
|
6030
|
+
async sequentialTransaction(arg, options) {
|
|
6031
|
+
const execute = /* @__PURE__ */ __name(async (tx) => {
|
|
6032
|
+
const txClient = new _ClientImpl(this.schema, this.$options, this);
|
|
5913
6033
|
txClient.kysely = tx;
|
|
5914
|
-
|
|
5915
|
-
|
|
6034
|
+
const result = [];
|
|
6035
|
+
for (const promise of arg) {
|
|
6036
|
+
result.push(await promise.cb(txClient));
|
|
6037
|
+
}
|
|
6038
|
+
return result;
|
|
6039
|
+
}, "execute");
|
|
6040
|
+
if (this.kysely.isTransaction) {
|
|
6041
|
+
return execute(this.kysely);
|
|
6042
|
+
} else {
|
|
6043
|
+
let txBuilder = this.kysely.transaction();
|
|
6044
|
+
if (options?.isolationLevel) {
|
|
6045
|
+
txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
|
|
6046
|
+
}
|
|
6047
|
+
return txBuilder.execute((tx) => execute(tx));
|
|
6048
|
+
}
|
|
5916
6049
|
}
|
|
5917
6050
|
get $procedures() {
|
|
5918
6051
|
return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
|
|
@@ -5975,26 +6108,26 @@ var ClientImpl = class _ClientImpl {
|
|
|
5975
6108
|
return this.auth;
|
|
5976
6109
|
}
|
|
5977
6110
|
$executeRaw(query, ...values) {
|
|
5978
|
-
return
|
|
6111
|
+
return createZenStackPromise(async () => {
|
|
5979
6112
|
const result = await (0, import_kysely16.sql)(query, ...values).execute(this.kysely);
|
|
5980
6113
|
return Number(result.numAffectedRows ?? 0);
|
|
5981
6114
|
});
|
|
5982
6115
|
}
|
|
5983
6116
|
$executeRawUnsafe(query, ...values) {
|
|
5984
|
-
return
|
|
6117
|
+
return createZenStackPromise(async () => {
|
|
5985
6118
|
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
5986
6119
|
const result = await this.kysely.executeQuery(compiledQuery);
|
|
5987
6120
|
return Number(result.numAffectedRows ?? 0);
|
|
5988
6121
|
});
|
|
5989
6122
|
}
|
|
5990
6123
|
$queryRaw(query, ...values) {
|
|
5991
|
-
return
|
|
6124
|
+
return createZenStackPromise(async () => {
|
|
5992
6125
|
const result = await (0, import_kysely16.sql)(query, ...values).execute(this.kysely);
|
|
5993
6126
|
return result.rows;
|
|
5994
6127
|
});
|
|
5995
6128
|
}
|
|
5996
6129
|
$queryRawUnsafe(query, ...values) {
|
|
5997
|
-
return
|
|
6130
|
+
return createZenStackPromise(async () => {
|
|
5998
6131
|
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
5999
6132
|
const result = await this.kysely.executeQuery(compiledQuery);
|
|
6000
6133
|
return result.rows;
|
|
@@ -6029,9 +6162,9 @@ function createClientProxy(client) {
|
|
|
6029
6162
|
__name(createClientProxy, "createClientProxy");
|
|
6030
6163
|
function createModelCrudHandler(client, model, inputValidator, resultProcessor) {
|
|
6031
6164
|
const createPromise = /* @__PURE__ */ __name((operation, args, handler, postProcess = false, throwIfNoResult = false) => {
|
|
6032
|
-
return
|
|
6033
|
-
let proceed = /* @__PURE__ */ __name(async (_args
|
|
6034
|
-
const _handler =
|
|
6165
|
+
return createZenStackPromise(async (txClient) => {
|
|
6166
|
+
let proceed = /* @__PURE__ */ __name(async (_args) => {
|
|
6167
|
+
const _handler = txClient ? handler.withClient(txClient) : handler;
|
|
6035
6168
|
const r = await _handler.handle(operation, _args ?? args);
|
|
6036
6169
|
if (!r && throwIfNoResult) {
|
|
6037
6170
|
throw new NotFoundError(model);
|
|
@@ -6050,7 +6183,7 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
6050
6183
|
for (const plugin of plugins) {
|
|
6051
6184
|
if (plugin.onQuery && typeof plugin.onQuery === "object") {
|
|
6052
6185
|
for (const [_model, modelHooks] of Object.entries(plugin.onQuery)) {
|
|
6053
|
-
if (_model === (0,
|
|
6186
|
+
if (_model === (0, import_common_helpers13.lowerCaseFirst)(model) || _model === "$allModels") {
|
|
6054
6187
|
if (modelHooks && typeof modelHooks === "object") {
|
|
6055
6188
|
for (const [op, opHooks] of Object.entries(modelHooks)) {
|
|
6056
6189
|
if (op === operation || op === "$allOperations") {
|
|
@@ -6129,8 +6262,19 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
6129
6262
|
};
|
|
6130
6263
|
}
|
|
6131
6264
|
__name(createModelCrudHandler, "createModelCrudHandler");
|
|
6265
|
+
|
|
6266
|
+
// src/client/plugin.ts
|
|
6267
|
+
function definePlugin(plugin) {
|
|
6268
|
+
return plugin;
|
|
6269
|
+
}
|
|
6270
|
+
__name(definePlugin, "definePlugin");
|
|
6132
6271
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6133
6272
|
0 && (module.exports = {
|
|
6134
|
-
|
|
6273
|
+
InputValidationError,
|
|
6274
|
+
InternalError,
|
|
6275
|
+
NotFoundError,
|
|
6276
|
+
QueryError,
|
|
6277
|
+
ZenStackClient,
|
|
6278
|
+
definePlugin
|
|
6135
6279
|
});
|
|
6136
6280
|
//# sourceMappingURL=index.cjs.map
|