@zenstackhq/runtime 3.0.0-alpha.1 → 3.0.0-alpha.11
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-DguafRNB.d.cts → contract-BQGRBbOU.d.cts} +846 -734
- package/dist/{contract-DguafRNB.d.ts → contract-BQGRBbOU.d.ts} +846 -734
- package/dist/{utils/pg-utils.cjs → helpers.cjs} +8 -16
- package/dist/helpers.cjs.map +1 -0
- package/dist/helpers.d.cts +1 -0
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +6 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.cjs +535 -343
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -6
- package/dist/index.d.ts +28 -6
- package/dist/index.js +484 -297
- package/dist/index.js.map +1 -1
- package/dist/plugins/policy.cjs +115 -104
- package/dist/plugins/policy.cjs.map +1 -1
- package/dist/plugins/policy.d.cts +2 -4
- package/dist/plugins/policy.d.ts +2 -4
- package/dist/plugins/policy.js +87 -66
- package/dist/plugins/policy.js.map +1 -1
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js.map +1 -1
- package/package.json +23 -46
- package/dist/client.cjs +0 -6094
- package/dist/client.cjs.map +0 -1
- package/dist/client.d.cts +0 -19
- package/dist/client.d.ts +0 -19
- package/dist/client.js +0 -6060
- package/dist/client.js.map +0 -1
- package/dist/utils/pg-utils.cjs.map +0 -1
- package/dist/utils/pg-utils.d.cts +0 -8
- package/dist/utils/pg-utils.d.ts +0 -8
- package/dist/utils/pg-utils.js +0 -16
- package/dist/utils/pg-utils.js.map +0 -1
- package/dist/utils/sqlite-utils.cjs +0 -55
- package/dist/utils/sqlite-utils.cjs.map +0 -1
- package/dist/utils/sqlite-utils.d.cts +0 -8
- package/dist/utils/sqlite-utils.d.ts +0 -8
- package/dist/utils/sqlite-utils.js +0 -22
- package/dist/utils/sqlite-utils.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,8 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// src/client/client-impl.ts
|
|
9
|
-
import {
|
|
9
|
+
import { invariant as invariant12, lowerCaseFirst as lowerCaseFirst2 } from "@zenstackhq/common-helpers";
|
|
10
|
+
import { CompiledQuery, DefaultConnectionProvider, DefaultQueryExecutor as DefaultQueryExecutor2, Kysely, Log, PostgresDialect, sql as sql10, SqliteDialect } from "kysely";
|
|
10
11
|
import { match as match19 } from "ts-pattern";
|
|
11
12
|
|
|
12
13
|
// src/client/crud/operations/aggregate.ts
|
|
@@ -14,21 +15,30 @@ import { sql as sql5 } from "kysely";
|
|
|
14
15
|
import { match as match9 } from "ts-pattern";
|
|
15
16
|
|
|
16
17
|
// src/client/errors.ts
|
|
18
|
+
var InputValidationError = class extends Error {
|
|
19
|
+
static {
|
|
20
|
+
__name(this, "InputValidationError");
|
|
21
|
+
}
|
|
22
|
+
constructor(message, cause) {
|
|
23
|
+
super(message, {
|
|
24
|
+
cause
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
};
|
|
17
28
|
var QueryError = class extends Error {
|
|
18
29
|
static {
|
|
19
30
|
__name(this, "QueryError");
|
|
20
31
|
}
|
|
21
|
-
constructor(message) {
|
|
22
|
-
super(message
|
|
32
|
+
constructor(message, cause) {
|
|
33
|
+
super(message, {
|
|
34
|
+
cause
|
|
35
|
+
});
|
|
23
36
|
}
|
|
24
37
|
};
|
|
25
38
|
var InternalError = class extends Error {
|
|
26
39
|
static {
|
|
27
40
|
__name(this, "InternalError");
|
|
28
41
|
}
|
|
29
|
-
constructor(message) {
|
|
30
|
-
super(message);
|
|
31
|
-
}
|
|
32
42
|
};
|
|
33
43
|
var NotFoundError = class extends Error {
|
|
34
44
|
static {
|
|
@@ -47,7 +57,7 @@ __name(getModel, "getModel");
|
|
|
47
57
|
function requireModel(schema, model) {
|
|
48
58
|
const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
|
|
49
59
|
if (!matchedName) {
|
|
50
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
60
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
51
61
|
}
|
|
52
62
|
return schema.models[matchedName];
|
|
53
63
|
}
|
|
@@ -172,7 +182,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias) {
|
|
|
172
182
|
computer = computedFields?.[model]?.[field];
|
|
173
183
|
}
|
|
174
184
|
if (!computer) {
|
|
175
|
-
throw new QueryError(`Computed field "${field}" implementation not provided`);
|
|
185
|
+
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
176
186
|
}
|
|
177
187
|
return computer(eb);
|
|
178
188
|
}
|
|
@@ -280,9 +290,10 @@ __name(safeJSONStringify, "safeJSONStringify");
|
|
|
280
290
|
|
|
281
291
|
// src/client/crud/operations/base.ts
|
|
282
292
|
import { createId } from "@paralleldrive/cuid2";
|
|
293
|
+
import { invariant as invariant7, isPlainObject as isPlainObject3 } from "@zenstackhq/common-helpers";
|
|
283
294
|
import { expressionBuilder as expressionBuilder2, sql as sql4 } from "kysely";
|
|
284
295
|
import { nanoid } from "nanoid";
|
|
285
|
-
import
|
|
296
|
+
import { inspect } from "util";
|
|
286
297
|
import { match as match8 } from "ts-pattern";
|
|
287
298
|
import { ulid } from "ulid";
|
|
288
299
|
import * as uuid from "uuid";
|
|
@@ -300,21 +311,21 @@ var RejectedByPolicyError = class extends Error {
|
|
|
300
311
|
};
|
|
301
312
|
|
|
302
313
|
// src/plugins/policy/policy-handler.ts
|
|
314
|
+
import { invariant as invariant6 } from "@zenstackhq/common-helpers";
|
|
303
315
|
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";
|
|
304
|
-
import invariant6 from "tiny-invariant";
|
|
305
316
|
import { match as match7 } from "ts-pattern";
|
|
306
317
|
|
|
307
318
|
// src/client/crud/dialects/index.ts
|
|
308
319
|
import { match as match4 } from "ts-pattern";
|
|
309
320
|
|
|
310
321
|
// src/client/crud/dialects/postgresql.ts
|
|
322
|
+
import { invariant as invariant2 } from "@zenstackhq/common-helpers";
|
|
311
323
|
import { sql as sql2 } from "kysely";
|
|
312
|
-
import invariant2 from "tiny-invariant";
|
|
313
324
|
import { match as match2 } from "ts-pattern";
|
|
314
325
|
|
|
315
326
|
// src/client/crud/dialects/base.ts
|
|
327
|
+
import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
|
|
316
328
|
import { sql } from "kysely";
|
|
317
|
-
import invariant from "tiny-invariant";
|
|
318
329
|
import { match, P } from "ts-pattern";
|
|
319
330
|
|
|
320
331
|
// src/utils/enumerate.ts
|
|
@@ -332,7 +343,6 @@ function enumerate(x) {
|
|
|
332
343
|
__name(enumerate, "enumerate");
|
|
333
344
|
|
|
334
345
|
// src/client/crud/dialects/base.ts
|
|
335
|
-
import { isPlainObject } from "is-plain-object";
|
|
336
346
|
var BaseCrudDialect = class {
|
|
337
347
|
static {
|
|
338
348
|
__name(this, "BaseCrudDialect");
|
|
@@ -343,7 +353,7 @@ var BaseCrudDialect = class {
|
|
|
343
353
|
this.schema = schema;
|
|
344
354
|
this.options = options;
|
|
345
355
|
}
|
|
346
|
-
transformPrimitive(value, _type) {
|
|
356
|
+
transformPrimitive(value, _type, _forArrayField) {
|
|
347
357
|
return value;
|
|
348
358
|
}
|
|
349
359
|
buildFilter(eb, model, modelAlias, where) {
|
|
@@ -486,7 +496,7 @@ var BaseCrudDialect = class {
|
|
|
486
496
|
if (_value === void 0) {
|
|
487
497
|
continue;
|
|
488
498
|
}
|
|
489
|
-
const value = this.transformPrimitive(_value, fieldType);
|
|
499
|
+
const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
|
|
490
500
|
switch (key) {
|
|
491
501
|
case "equals": {
|
|
492
502
|
clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
|
|
@@ -524,10 +534,14 @@ var BaseCrudDialect = class {
|
|
|
524
534
|
if (isEnum(this.schema, fieldDef.type)) {
|
|
525
535
|
return this.buildEnumFilter(eb, modelAlias, field, fieldDef, payload);
|
|
526
536
|
}
|
|
527
|
-
return match(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, model, modelAlias, field, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, modelAlias, field, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, modelAlias, field, payload)).with("Bytes", () => this.buildBytesFilter(eb, modelAlias, field, payload)).
|
|
537
|
+
return match(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, model, modelAlias, field, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, modelAlias, field, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, modelAlias, field, payload)).with("Bytes", () => this.buildBytesFilter(eb, modelAlias, field, payload)).with("Json", () => {
|
|
538
|
+
throw new InternalError("JSON filters are not supported yet");
|
|
539
|
+
}).with("Unsupported", () => {
|
|
540
|
+
throw new QueryError(`Unsupported field cannot be used in filters`);
|
|
541
|
+
}).exhaustive();
|
|
528
542
|
}
|
|
529
543
|
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
530
|
-
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
|
|
544
|
+
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
531
545
|
}
|
|
532
546
|
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
|
|
533
547
|
if (payload === null || !isPlainObject(payload)) {
|
|
@@ -614,22 +628,22 @@ var BaseCrudDialect = class {
|
|
|
614
628
|
}
|
|
615
629
|
}
|
|
616
630
|
buildNumberFilter(eb, model, table, field, type, payload) {
|
|
617
|
-
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));
|
|
631
|
+
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));
|
|
618
632
|
return this.and(eb, ...conditions);
|
|
619
633
|
}
|
|
620
634
|
buildBooleanFilter(eb, table, field, payload) {
|
|
621
|
-
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean"), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
|
|
635
|
+
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
|
|
622
636
|
"equals",
|
|
623
637
|
"not"
|
|
624
638
|
]);
|
|
625
639
|
return this.and(eb, ...conditions);
|
|
626
640
|
}
|
|
627
641
|
buildDateTimeFilter(eb, table, field, payload) {
|
|
628
|
-
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime"), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
|
|
642
|
+
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
|
|
629
643
|
return this.and(eb, ...conditions);
|
|
630
644
|
}
|
|
631
645
|
buildBytesFilter(eb, table, field, payload) {
|
|
632
|
-
const conditions = this.buildStandardFilter(eb, "Bytes", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes"), (value) => this.buildBytesFilter(eb, table, field, value), true, [
|
|
646
|
+
const conditions = this.buildStandardFilter(eb, "Bytes", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, table, field, value), true, [
|
|
633
647
|
"equals",
|
|
634
648
|
"in",
|
|
635
649
|
"notIn",
|
|
@@ -728,10 +742,10 @@ var BaseCrudDialect = class {
|
|
|
728
742
|
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
729
743
|
}
|
|
730
744
|
true(eb) {
|
|
731
|
-
return eb.lit(this.transformPrimitive(true, "Boolean"));
|
|
745
|
+
return eb.lit(this.transformPrimitive(true, "Boolean", false));
|
|
732
746
|
}
|
|
733
747
|
false(eb) {
|
|
734
|
-
return eb.lit(this.transformPrimitive(false, "Boolean"));
|
|
748
|
+
return eb.lit(this.transformPrimitive(false, "Boolean", false));
|
|
735
749
|
}
|
|
736
750
|
isTrue(expression) {
|
|
737
751
|
const node = expression.toOperationNode();
|
|
@@ -780,14 +794,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
780
794
|
get provider() {
|
|
781
795
|
return "postgresql";
|
|
782
796
|
}
|
|
783
|
-
transformPrimitive(value, type) {
|
|
797
|
+
transformPrimitive(value, type, forArrayField) {
|
|
784
798
|
if (value === void 0) {
|
|
785
799
|
return value;
|
|
786
800
|
}
|
|
787
801
|
if (Array.isArray(value)) {
|
|
788
|
-
|
|
802
|
+
if (type === "Json" && !forArrayField) {
|
|
803
|
+
return JSON.stringify(value);
|
|
804
|
+
} else {
|
|
805
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
806
|
+
}
|
|
789
807
|
} else {
|
|
790
|
-
return match2(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).otherwise(() => value);
|
|
808
|
+
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);
|
|
791
809
|
}
|
|
792
810
|
}
|
|
793
811
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -854,25 +872,33 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
854
872
|
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
855
873
|
]).flatMap((v) => v));
|
|
856
874
|
} else if (payload.select) {
|
|
857
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) =>
|
|
858
|
-
|
|
859
|
-
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
860
|
-
|
|
875
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => {
|
|
876
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
877
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentName}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
|
|
878
|
+
return [
|
|
879
|
+
sql2.lit(field),
|
|
880
|
+
fieldValue
|
|
881
|
+
];
|
|
882
|
+
}).flatMap((v) => v));
|
|
861
883
|
}
|
|
862
884
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
863
885
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
864
886
|
sql2.lit(field),
|
|
887
|
+
// reference the synthesized JSON field
|
|
865
888
|
eb.ref(`${parentName}$${relationField}$${field}.$j`)
|
|
866
889
|
]).flatMap((v) => v));
|
|
867
890
|
}
|
|
868
891
|
return objArgs;
|
|
869
892
|
}
|
|
870
|
-
buildRelationJoins(
|
|
893
|
+
buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
|
|
871
894
|
let result = qb;
|
|
872
|
-
if (typeof payload === "object"
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
895
|
+
if (typeof payload === "object") {
|
|
896
|
+
const selectInclude = payload.include ?? payload.select;
|
|
897
|
+
if (selectInclude && typeof selectInclude === "object") {
|
|
898
|
+
Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
|
|
899
|
+
result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
|
|
900
|
+
});
|
|
901
|
+
}
|
|
876
902
|
}
|
|
877
903
|
return result;
|
|
878
904
|
}
|
|
@@ -915,8 +941,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
915
941
|
};
|
|
916
942
|
|
|
917
943
|
// src/client/crud/dialects/sqlite.ts
|
|
944
|
+
import { invariant as invariant3 } from "@zenstackhq/common-helpers";
|
|
918
945
|
import { sql as sql3 } from "kysely";
|
|
919
|
-
import invariant3 from "tiny-invariant";
|
|
920
946
|
import { match as match3 } from "ts-pattern";
|
|
921
947
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
922
948
|
static {
|
|
@@ -925,14 +951,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
925
951
|
get provider() {
|
|
926
952
|
return "sqlite";
|
|
927
953
|
}
|
|
928
|
-
transformPrimitive(value, type) {
|
|
954
|
+
transformPrimitive(value, type, _forArrayField) {
|
|
929
955
|
if (value === void 0) {
|
|
930
956
|
return value;
|
|
931
957
|
}
|
|
932
958
|
if (Array.isArray(value)) {
|
|
933
|
-
return value.map((v) => this.transformPrimitive(v, type));
|
|
959
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
934
960
|
} else {
|
|
935
|
-
return match3(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).otherwise(() => value);
|
|
961
|
+
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);
|
|
936
962
|
}
|
|
937
963
|
}
|
|
938
964
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -1460,12 +1486,12 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1460
1486
|
};
|
|
1461
1487
|
|
|
1462
1488
|
// src/plugins/policy/expression-transformer.ts
|
|
1489
|
+
import { invariant as invariant5 } from "@zenstackhq/common-helpers";
|
|
1463
1490
|
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";
|
|
1464
|
-
import invariant5 from "tiny-invariant";
|
|
1465
1491
|
import { match as match6 } from "ts-pattern";
|
|
1466
1492
|
|
|
1467
1493
|
// src/plugins/policy/expression-evaluator.ts
|
|
1468
|
-
import invariant4 from "
|
|
1494
|
+
import { invariant as invariant4 } from "@zenstackhq/common-helpers";
|
|
1469
1495
|
import { match as match5 } from "ts-pattern";
|
|
1470
1496
|
var ExpressionEvaluator = class {
|
|
1471
1497
|
static {
|
|
@@ -1537,11 +1563,11 @@ var ExpressionEvaluator = class {
|
|
|
1537
1563
|
// src/plugins/policy/utils.ts
|
|
1538
1564
|
import { AliasNode, AndNode, BinaryOperationNode, FunctionNode, OperatorNode, OrNode, ParensNode, ReferenceNode, TableNode, UnaryOperationNode, ValueNode } from "kysely";
|
|
1539
1565
|
function trueNode(dialect) {
|
|
1540
|
-
return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
|
|
1566
|
+
return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1541
1567
|
}
|
|
1542
1568
|
__name(trueNode, "trueNode");
|
|
1543
1569
|
function falseNode(dialect) {
|
|
1544
|
-
return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
|
|
1570
|
+
return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1545
1571
|
}
|
|
1546
1572
|
__name(falseNode, "falseNode");
|
|
1547
1573
|
function isTrueNode(node) {
|
|
@@ -1799,7 +1825,7 @@ var ExpressionTransformer = class {
|
|
|
1799
1825
|
}
|
|
1800
1826
|
}
|
|
1801
1827
|
transformValue(value, type) {
|
|
1802
|
-
return ValueNode2.create(this.dialect.transformPrimitive(value, type) ?? null);
|
|
1828
|
+
return ValueNode2.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
1803
1829
|
}
|
|
1804
1830
|
_unary(expr2, context) {
|
|
1805
1831
|
invariant5(expr2.op === "!", 'only "!" operator is supported');
|
|
@@ -2042,7 +2068,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2042
2068
|
get kysely() {
|
|
2043
2069
|
return this.client.$qb;
|
|
2044
2070
|
}
|
|
2045
|
-
async handle(node, proceed
|
|
2071
|
+
async handle(node, proceed) {
|
|
2046
2072
|
if (!this.isCrudQueryNode(node)) {
|
|
2047
2073
|
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
2048
2074
|
}
|
|
@@ -2062,27 +2088,20 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2062
2088
|
if (!mutationRequiresTransaction && !node.returning) {
|
|
2063
2089
|
return proceed(this.transformNode(node));
|
|
2064
2090
|
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
const
|
|
2072
|
-
if (
|
|
2073
|
-
|
|
2074
|
-
if (readBackResult.rows.length !== result2.rows.length) {
|
|
2075
|
-
readBackError = true;
|
|
2076
|
-
}
|
|
2077
|
-
return readBackResult;
|
|
2078
|
-
} else {
|
|
2079
|
-
return result2;
|
|
2091
|
+
if (InsertQueryNode.is(node)) {
|
|
2092
|
+
await this.enforcePreCreatePolicy(node, proceed);
|
|
2093
|
+
}
|
|
2094
|
+
const transformedNode = this.transformNode(node);
|
|
2095
|
+
const result = await proceed(transformedNode);
|
|
2096
|
+
if (!this.onlyReturningId(node)) {
|
|
2097
|
+
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2098
|
+
if (readBackResult.rows.length !== result.rows.length) {
|
|
2099
|
+
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
2080
2100
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2101
|
+
return readBackResult;
|
|
2102
|
+
} else {
|
|
2103
|
+
return result;
|
|
2084
2104
|
}
|
|
2085
|
-
return result;
|
|
2086
2105
|
}
|
|
2087
2106
|
onlyReturningId(node) {
|
|
2088
2107
|
if (!node.returning) {
|
|
@@ -2143,11 +2162,11 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2143
2162
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2144
2163
|
invariant6(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2145
2164
|
result.push({
|
|
2146
|
-
node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
|
|
2165
|
+
node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2147
2166
|
raw: item.value
|
|
2148
2167
|
});
|
|
2149
2168
|
} else {
|
|
2150
|
-
const value = this.dialect.transformPrimitive(item, fieldDef.type);
|
|
2169
|
+
const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
2151
2170
|
if (Array.isArray(value)) {
|
|
2152
2171
|
result.push({
|
|
2153
2172
|
node: RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
@@ -2378,14 +2397,23 @@ var PolicyPlugin = class {
|
|
|
2378
2397
|
get description() {
|
|
2379
2398
|
return "Enforces access policies defined in the schema.";
|
|
2380
2399
|
}
|
|
2381
|
-
onKyselyQuery({
|
|
2400
|
+
onKyselyQuery({
|
|
2401
|
+
query,
|
|
2402
|
+
client,
|
|
2403
|
+
proceed
|
|
2404
|
+
/*, transaction*/
|
|
2405
|
+
}) {
|
|
2382
2406
|
const handler = new PolicyHandler(client);
|
|
2383
|
-
return handler.handle(
|
|
2407
|
+
return handler.handle(
|
|
2408
|
+
query,
|
|
2409
|
+
proceed
|
|
2410
|
+
/*, transaction*/
|
|
2411
|
+
);
|
|
2384
2412
|
}
|
|
2385
2413
|
};
|
|
2386
2414
|
|
|
2387
2415
|
// src/utils/clone.ts
|
|
2388
|
-
import { isPlainObject as isPlainObject2 } from "
|
|
2416
|
+
import { isPlainObject as isPlainObject2 } from "@zenstackhq/common-helpers";
|
|
2389
2417
|
function clone(value) {
|
|
2390
2418
|
if (Array.isArray(value)) {
|
|
2391
2419
|
return value.map((v) => clone(v));
|
|
@@ -2501,13 +2529,13 @@ var BaseOperationHandler = class {
|
|
|
2501
2529
|
inMemoryDistinct = distinct;
|
|
2502
2530
|
}
|
|
2503
2531
|
}
|
|
2504
|
-
if (args
|
|
2505
|
-
query = this.buildFieldSelection(model, query, args
|
|
2532
|
+
if (args && "select" in args && args.select) {
|
|
2533
|
+
query = this.buildFieldSelection(model, query, args.select, model);
|
|
2506
2534
|
} else {
|
|
2507
2535
|
query = this.buildSelectAllScalarFields(model, query, args?.omit);
|
|
2508
2536
|
}
|
|
2509
|
-
if (args
|
|
2510
|
-
query = this.buildFieldSelection(model, query, args
|
|
2537
|
+
if (args && "include" in args && args.include) {
|
|
2538
|
+
query = this.buildFieldSelection(model, query, args.include, model);
|
|
2511
2539
|
}
|
|
2512
2540
|
if (args?.cursor) {
|
|
2513
2541
|
query = this.buildCursorFilter(model, query, args.cursor, args.orderBy, negateOrderBy);
|
|
@@ -2520,8 +2548,13 @@ var BaseOperationHandler = class {
|
|
|
2520
2548
|
try {
|
|
2521
2549
|
result = await query.execute();
|
|
2522
2550
|
} catch (err) {
|
|
2523
|
-
const { sql:
|
|
2524
|
-
|
|
2551
|
+
const { sql: sql11, parameters } = query.compile();
|
|
2552
|
+
let message = `Failed to execute query: ${err}, sql: ${sql11}`;
|
|
2553
|
+
if (this.options.debug) {
|
|
2554
|
+
message += `, parameters:
|
|
2555
|
+
${parameters.map((p) => inspect(p)).join("\n")}`;
|
|
2556
|
+
}
|
|
2557
|
+
throw new QueryError(message, err);
|
|
2525
2558
|
}
|
|
2526
2559
|
if (inMemoryDistinct) {
|
|
2527
2560
|
const distinctResult = [];
|
|
@@ -2580,30 +2613,20 @@ var BaseOperationHandler = class {
|
|
|
2580
2613
|
for (const [field, value] of Object.entries(selections.select)) {
|
|
2581
2614
|
const fieldDef = requireField(this.schema, model, field);
|
|
2582
2615
|
const fieldModel = fieldDef.type;
|
|
2583
|
-
const
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
for (const [left, right] of joinPairs) {
|
|
2594
|
-
join = join.onRef(left, "=", right);
|
|
2595
|
-
}
|
|
2596
|
-
return join;
|
|
2597
|
-
});
|
|
2598
|
-
jsonObject[field] = this.countIdDistinct(eb, fieldDef.type, jointTable);
|
|
2616
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
2617
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
2618
|
+
for (const [left, right] of joinPairs) {
|
|
2619
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
2620
|
+
}
|
|
2621
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
2622
|
+
const filter = this.dialect.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
2623
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
2624
|
+
}
|
|
2625
|
+
jsonObject[field] = fieldCountQuery;
|
|
2599
2626
|
}
|
|
2600
2627
|
query = query.select((eb2) => this.dialect.buildJsonObject(eb2, jsonObject).as("_count"));
|
|
2601
2628
|
return query;
|
|
2602
2629
|
}
|
|
2603
|
-
countIdDistinct(eb, model, table) {
|
|
2604
|
-
const idFields = getIdFields(this.schema, model);
|
|
2605
|
-
return eb.fn.count(sql4.join(idFields.map((f) => sql4.ref(`${table}.${f}`)))).distinct();
|
|
2606
|
-
}
|
|
2607
2630
|
buildSelectAllScalarFields(model, query, omit) {
|
|
2608
2631
|
const modelDef = this.requireModel(model);
|
|
2609
2632
|
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);
|
|
@@ -2669,14 +2692,14 @@ var BaseOperationHandler = class {
|
|
|
2669
2692
|
const fieldDef = this.requireField(model, field);
|
|
2670
2693
|
if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
|
|
2671
2694
|
if (fieldDef.array && value && typeof value === "object" && "set" in value && Array.isArray(value.set)) {
|
|
2672
|
-
createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type);
|
|
2695
|
+
createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type, true);
|
|
2673
2696
|
} else {
|
|
2674
|
-
createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type);
|
|
2697
|
+
createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
2675
2698
|
}
|
|
2676
2699
|
} else {
|
|
2677
2700
|
const subM2M = getManyToManyRelation(this.schema, model, field);
|
|
2678
2701
|
if (!subM2M && fieldDef.relation?.fields && fieldDef.relation?.references) {
|
|
2679
|
-
const fkValues = await this.
|
|
2702
|
+
const fkValues = await this.processOwnedRelationForCreate(kysely, fieldDef, value);
|
|
2680
2703
|
for (let i = 0; i < fieldDef.relation.fields.length; i++) {
|
|
2681
2704
|
createFields[fieldDef.relation.fields[i]] = fkValues[fieldDef.relation.references[i]];
|
|
2682
2705
|
}
|
|
@@ -2697,7 +2720,7 @@ var BaseOperationHandler = class {
|
|
|
2697
2720
|
const createdEntity = await query.executeTakeFirst();
|
|
2698
2721
|
if (Object.keys(postCreateRelations).length > 0) {
|
|
2699
2722
|
const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
|
|
2700
|
-
return this.
|
|
2723
|
+
return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
|
|
2701
2724
|
});
|
|
2702
2725
|
await Promise.all(relationPromises);
|
|
2703
2726
|
}
|
|
@@ -2764,7 +2787,7 @@ var BaseOperationHandler = class {
|
|
|
2764
2787
|
const eb = expressionBuilder2();
|
|
2765
2788
|
return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
|
|
2766
2789
|
}
|
|
2767
|
-
async
|
|
2790
|
+
async processOwnedRelationForCreate(kysely, relationField, payload) {
|
|
2768
2791
|
if (!payload) {
|
|
2769
2792
|
return;
|
|
2770
2793
|
}
|
|
@@ -2814,21 +2837,27 @@ var BaseOperationHandler = class {
|
|
|
2814
2837
|
}
|
|
2815
2838
|
return result;
|
|
2816
2839
|
}
|
|
2817
|
-
|
|
2840
|
+
processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
|
|
2818
2841
|
const relationFieldDef = this.requireField(contextModel, relationFieldName);
|
|
2819
2842
|
const relationModel = relationFieldDef.type;
|
|
2820
2843
|
const tasks = [];
|
|
2844
|
+
const fromRelationContext = {
|
|
2845
|
+
model: contextModel,
|
|
2846
|
+
field: relationFieldName,
|
|
2847
|
+
ids: parentEntity
|
|
2848
|
+
};
|
|
2821
2849
|
for (const [action, subPayload] of Object.entries(payload)) {
|
|
2822
2850
|
if (!subPayload) {
|
|
2823
2851
|
continue;
|
|
2824
2852
|
}
|
|
2825
2853
|
switch (action) {
|
|
2826
2854
|
case "create": {
|
|
2827
|
-
tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item,
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2855
|
+
tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, fromRelationContext)));
|
|
2856
|
+
break;
|
|
2857
|
+
}
|
|
2858
|
+
case "createMany": {
|
|
2859
|
+
invariant7(relationFieldDef.array, "relation must be an array for createMany");
|
|
2860
|
+
tasks.push(this.createMany(kysely, relationModel, subPayload, false, fromRelationContext));
|
|
2832
2861
|
break;
|
|
2833
2862
|
}
|
|
2834
2863
|
case "connect": {
|
|
@@ -2858,6 +2887,11 @@ var BaseOperationHandler = class {
|
|
|
2858
2887
|
return Promise.all(tasks);
|
|
2859
2888
|
}
|
|
2860
2889
|
async createMany(kysely, model, input, returnData, fromRelation) {
|
|
2890
|
+
if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
|
|
2891
|
+
return returnData ? [] : {
|
|
2892
|
+
count: 0
|
|
2893
|
+
};
|
|
2894
|
+
}
|
|
2861
2895
|
const modelDef = this.requireModel(model);
|
|
2862
2896
|
let relationKeyPairs = [];
|
|
2863
2897
|
if (fromRelation) {
|
|
@@ -2872,7 +2906,7 @@ var BaseOperationHandler = class {
|
|
|
2872
2906
|
for (const [name, value] of Object.entries(item)) {
|
|
2873
2907
|
const fieldDef = this.requireField(model, name);
|
|
2874
2908
|
invariant7(!fieldDef.relation, "createMany does not support relations");
|
|
2875
|
-
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type);
|
|
2909
|
+
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
2876
2910
|
}
|
|
2877
2911
|
if (fromRelation) {
|
|
2878
2912
|
for (const { fk, pk } of relationKeyPairs) {
|
|
@@ -2907,7 +2941,7 @@ var BaseOperationHandler = class {
|
|
|
2907
2941
|
values[field] = generated;
|
|
2908
2942
|
}
|
|
2909
2943
|
} else if (fields[field]?.updatedAt) {
|
|
2910
|
-
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
|
|
2944
|
+
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
2911
2945
|
}
|
|
2912
2946
|
}
|
|
2913
2947
|
}
|
|
@@ -2972,7 +3006,7 @@ var BaseOperationHandler = class {
|
|
|
2972
3006
|
if (finalData === data) {
|
|
2973
3007
|
finalData = clone(data);
|
|
2974
3008
|
}
|
|
2975
|
-
finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
|
|
3009
|
+
finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
2976
3010
|
}
|
|
2977
3011
|
}
|
|
2978
3012
|
if (Object.keys(finalData).length === 0) {
|
|
@@ -2997,7 +3031,7 @@ var BaseOperationHandler = class {
|
|
|
2997
3031
|
updateFields[field] = this.transformScalarListUpdate(model, field, fieldDef, finalData[field]);
|
|
2998
3032
|
continue;
|
|
2999
3033
|
}
|
|
3000
|
-
updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type);
|
|
3034
|
+
updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type, !!fieldDef.array);
|
|
3001
3035
|
} else {
|
|
3002
3036
|
if (!allowRelationUpdate) {
|
|
3003
3037
|
throw new QueryError(`Relation update not allowed for field "${field}"`);
|
|
@@ -3042,7 +3076,7 @@ var BaseOperationHandler = class {
|
|
|
3042
3076
|
transformIncrementalUpdate(model, field, fieldDef, payload) {
|
|
3043
3077
|
invariant7(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
|
|
3044
3078
|
const key = Object.keys(payload)[0];
|
|
3045
|
-
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
|
|
3079
|
+
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
|
|
3046
3080
|
const eb = expressionBuilder2();
|
|
3047
3081
|
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
|
|
3048
3082
|
return match8(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(() => {
|
|
@@ -3052,7 +3086,7 @@ var BaseOperationHandler = class {
|
|
|
3052
3086
|
transformScalarListUpdate(model, field, fieldDef, payload) {
|
|
3053
3087
|
invariant7(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
|
|
3054
3088
|
const key = Object.keys(payload)[0];
|
|
3055
|
-
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
|
|
3089
|
+
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
|
|
3056
3090
|
const eb = expressionBuilder2();
|
|
3057
3091
|
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
|
|
3058
3092
|
return match8(key).with("set", () => value).with("push", () => {
|
|
@@ -3082,7 +3116,7 @@ var BaseOperationHandler = class {
|
|
|
3082
3116
|
if (isRelationField(this.schema, model, field)) {
|
|
3083
3117
|
continue;
|
|
3084
3118
|
}
|
|
3085
|
-
updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type);
|
|
3119
|
+
updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
|
|
3086
3120
|
}
|
|
3087
3121
|
let query = kysely.updateTable(model).set(updateFields);
|
|
3088
3122
|
if (limit === void 0) {
|
|
@@ -3100,20 +3134,15 @@ var BaseOperationHandler = class {
|
|
|
3100
3134
|
model,
|
|
3101
3135
|
operation: "update"
|
|
3102
3136
|
}));
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
return result;
|
|
3113
|
-
}
|
|
3114
|
-
} catch (err) {
|
|
3115
|
-
const { sql: sql10, parameters } = query.compile();
|
|
3116
|
-
throw new QueryError(`Error during updateMany: ${err}, sql: ${sql10}, parameters: ${parameters}`);
|
|
3137
|
+
if (!returnData) {
|
|
3138
|
+
const result = await query.executeTakeFirstOrThrow();
|
|
3139
|
+
return {
|
|
3140
|
+
count: Number(result.numUpdatedRows)
|
|
3141
|
+
};
|
|
3142
|
+
} else {
|
|
3143
|
+
const idFields = getIdFields(this.schema, model);
|
|
3144
|
+
const result = await query.returning(idFields).execute();
|
|
3145
|
+
return result;
|
|
3117
3146
|
}
|
|
3118
3147
|
}
|
|
3119
3148
|
buildIdFieldRefs(kysely, model) {
|
|
@@ -3513,7 +3542,7 @@ var BaseOperationHandler = class {
|
|
|
3513
3542
|
}, {});
|
|
3514
3543
|
}
|
|
3515
3544
|
trimResult(data, args) {
|
|
3516
|
-
if (!args.select) {
|
|
3545
|
+
if (!("select" in args) || !args.select) {
|
|
3517
3546
|
return data;
|
|
3518
3547
|
}
|
|
3519
3548
|
return Object.keys(args.select).reduce((acc, field) => {
|
|
@@ -3523,9 +3552,9 @@ var BaseOperationHandler = class {
|
|
|
3523
3552
|
}
|
|
3524
3553
|
needReturnRelations(model, args) {
|
|
3525
3554
|
let returnRelation = false;
|
|
3526
|
-
if (args.include) {
|
|
3555
|
+
if ("include" in args && args.include) {
|
|
3527
3556
|
returnRelation = Object.keys(args.include).length > 0;
|
|
3528
|
-
} else if (args.select) {
|
|
3557
|
+
} else if ("select" in args && args.select) {
|
|
3529
3558
|
returnRelation = Object.entries(args.select).some(([K, v]) => {
|
|
3530
3559
|
const fieldDef = this.requireField(model, K);
|
|
3531
3560
|
return fieldDef.relation && v;
|
|
@@ -3533,11 +3562,15 @@ var BaseOperationHandler = class {
|
|
|
3533
3562
|
}
|
|
3534
3563
|
return returnRelation;
|
|
3535
3564
|
}
|
|
3536
|
-
async safeTransaction(callback) {
|
|
3565
|
+
async safeTransaction(callback, isolationLevel) {
|
|
3537
3566
|
if (this.kysely.isTransaction) {
|
|
3538
3567
|
return callback(this.kysely);
|
|
3539
3568
|
} else {
|
|
3540
|
-
|
|
3569
|
+
let txBuilder = this.kysely.transaction();
|
|
3570
|
+
if (isolationLevel) {
|
|
3571
|
+
txBuilder = txBuilder.setIsolationLevel(isolationLevel);
|
|
3572
|
+
}
|
|
3573
|
+
return txBuilder.execute(callback);
|
|
3541
3574
|
}
|
|
3542
3575
|
}
|
|
3543
3576
|
// Given a unique filter of a model, return the entity ids by trying to
|
|
@@ -3556,6 +3589,28 @@ var BaseOperationHandler = class {
|
|
|
3556
3589
|
where: uniqueFilter
|
|
3557
3590
|
});
|
|
3558
3591
|
}
|
|
3592
|
+
/**
|
|
3593
|
+
* Normalize input args to strip `undefined` fields
|
|
3594
|
+
*/
|
|
3595
|
+
normalizeArgs(args) {
|
|
3596
|
+
if (!args) {
|
|
3597
|
+
return;
|
|
3598
|
+
}
|
|
3599
|
+
const newArgs = clone(args);
|
|
3600
|
+
this.doNormalizeArgs(newArgs);
|
|
3601
|
+
return newArgs;
|
|
3602
|
+
}
|
|
3603
|
+
doNormalizeArgs(args) {
|
|
3604
|
+
if (args && typeof args === "object") {
|
|
3605
|
+
for (const [key, value] of Object.entries(args)) {
|
|
3606
|
+
if (value === void 0) {
|
|
3607
|
+
delete args[key];
|
|
3608
|
+
} else if (value && isPlainObject3(value)) {
|
|
3609
|
+
this.doNormalizeArgs(value);
|
|
3610
|
+
}
|
|
3611
|
+
}
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3559
3614
|
};
|
|
3560
3615
|
|
|
3561
3616
|
// src/client/crud/operations/aggregate.ts
|
|
@@ -3564,21 +3619,22 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3564
3619
|
__name(this, "AggregateOperationHandler");
|
|
3565
3620
|
}
|
|
3566
3621
|
async handle(_operation, args) {
|
|
3567
|
-
const
|
|
3622
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3623
|
+
const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
|
|
3568
3624
|
let query = this.kysely.selectFrom((eb) => {
|
|
3569
|
-
let subQuery = eb.selectFrom(this.model).selectAll(this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model,
|
|
3570
|
-
const skip =
|
|
3571
|
-
let take =
|
|
3625
|
+
let subQuery = eb.selectFrom(this.model).selectAll(this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
3626
|
+
const skip = parsedArgs?.skip;
|
|
3627
|
+
let take = parsedArgs?.take;
|
|
3572
3628
|
let negateOrderBy = false;
|
|
3573
3629
|
if (take !== void 0 && take < 0) {
|
|
3574
3630
|
negateOrderBy = true;
|
|
3575
3631
|
take = -take;
|
|
3576
3632
|
}
|
|
3577
3633
|
subQuery = this.dialect.buildSkipTake(subQuery, skip, take);
|
|
3578
|
-
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model,
|
|
3634
|
+
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, parsedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
3579
3635
|
return subQuery.as("$sub");
|
|
3580
3636
|
});
|
|
3581
|
-
for (const [key, value] of Object.entries(
|
|
3637
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3582
3638
|
switch (key) {
|
|
3583
3639
|
case "_count": {
|
|
3584
3640
|
if (value === true) {
|
|
@@ -3657,14 +3713,15 @@ var CountOperationHandler = class extends BaseOperationHandler {
|
|
|
3657
3713
|
__name(this, "CountOperationHandler");
|
|
3658
3714
|
}
|
|
3659
3715
|
async handle(_operation, args) {
|
|
3660
|
-
const
|
|
3716
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3717
|
+
const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
|
|
3661
3718
|
let query = this.kysely.selectFrom((eb) => {
|
|
3662
|
-
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model,
|
|
3663
|
-
subQuery = this.dialect.buildSkipTake(subQuery,
|
|
3719
|
+
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
3720
|
+
subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
|
|
3664
3721
|
return subQuery.as("$sub");
|
|
3665
3722
|
});
|
|
3666
|
-
if (
|
|
3667
|
-
query = query.select((eb) => Object.keys(
|
|
3723
|
+
if (parsedArgs?.select && typeof parsedArgs.select === "object") {
|
|
3724
|
+
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(sql6.ref(`$sub.${key}`)), "integer").as(key)));
|
|
3668
3725
|
return query.executeTakeFirstOrThrow();
|
|
3669
3726
|
} else {
|
|
3670
3727
|
query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
|
|
@@ -3681,10 +3738,11 @@ var CreateOperationHandler = class extends BaseOperationHandler {
|
|
|
3681
3738
|
__name(this, "CreateOperationHandler");
|
|
3682
3739
|
}
|
|
3683
3740
|
async handle(operation, args) {
|
|
3684
|
-
|
|
3685
|
-
|
|
3741
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3742
|
+
return match10(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, normalizedArgs))).with("createMany", () => {
|
|
3743
|
+
return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, normalizedArgs));
|
|
3686
3744
|
}).with("createManyAndReturn", () => {
|
|
3687
|
-
return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model,
|
|
3745
|
+
return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, normalizedArgs));
|
|
3688
3746
|
}).exhaustive();
|
|
3689
3747
|
}
|
|
3690
3748
|
async runCreate(args) {
|
|
@@ -3734,7 +3792,8 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
|
3734
3792
|
__name(this, "DeleteOperationHandler");
|
|
3735
3793
|
}
|
|
3736
3794
|
async handle(operation, args) {
|
|
3737
|
-
|
|
3795
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3796
|
+
return match11(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, normalizedArgs))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, normalizedArgs))).exhaustive();
|
|
3738
3797
|
}
|
|
3739
3798
|
async runDelete(args) {
|
|
3740
3799
|
const existing = await this.readUnique(this.kysely, this.model, {
|
|
@@ -3764,7 +3823,8 @@ var FindOperationHandler = class extends BaseOperationHandler {
|
|
|
3764
3823
|
__name(this, "FindOperationHandler");
|
|
3765
3824
|
}
|
|
3766
3825
|
async handle(operation, args, validateArgs = true) {
|
|
3767
|
-
const
|
|
3826
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3827
|
+
const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", normalizedArgs) : normalizedArgs;
|
|
3768
3828
|
const result = await this.read(this.client.$qb, this.model, parsedArgs);
|
|
3769
3829
|
const finalResult = operation === "findMany" ? result : result[0] ?? null;
|
|
3770
3830
|
return finalResult;
|
|
@@ -3774,16 +3834,17 @@ var FindOperationHandler = class extends BaseOperationHandler {
|
|
|
3774
3834
|
// src/client/crud/operations/group-by.ts
|
|
3775
3835
|
import { sql as sql7 } from "kysely";
|
|
3776
3836
|
import { match as match12 } from "ts-pattern";
|
|
3777
|
-
var
|
|
3837
|
+
var GroupByOperationHandler = class extends BaseOperationHandler {
|
|
3778
3838
|
static {
|
|
3779
|
-
__name(this, "
|
|
3839
|
+
__name(this, "GroupByOperationHandler");
|
|
3780
3840
|
}
|
|
3781
3841
|
async handle(_operation, args) {
|
|
3782
|
-
const
|
|
3842
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3843
|
+
const parsedArgs = this.inputValidator.validateGroupByArgs(this.model, normalizedArgs);
|
|
3783
3844
|
let query = this.kysely.selectFrom((eb) => {
|
|
3784
|
-
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model,
|
|
3785
|
-
const skip =
|
|
3786
|
-
let take =
|
|
3845
|
+
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
3846
|
+
const skip = parsedArgs?.skip;
|
|
3847
|
+
let take = parsedArgs?.take;
|
|
3787
3848
|
let negateOrderBy = false;
|
|
3788
3849
|
if (take !== void 0 && take < 0) {
|
|
3789
3850
|
negateOrderBy = true;
|
|
@@ -3793,20 +3854,20 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3793
3854
|
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
3794
3855
|
return subQuery.as("$sub");
|
|
3795
3856
|
});
|
|
3796
|
-
const bys = typeof
|
|
3797
|
-
|
|
3798
|
-
] :
|
|
3857
|
+
const bys = typeof parsedArgs.by === "string" ? [
|
|
3858
|
+
parsedArgs.by
|
|
3859
|
+
] : parsedArgs.by;
|
|
3799
3860
|
query = query.groupBy(bys);
|
|
3800
|
-
if (
|
|
3801
|
-
query = this.dialect.buildOrderBy(query, this.model, "$sub",
|
|
3861
|
+
if (parsedArgs.orderBy) {
|
|
3862
|
+
query = this.dialect.buildOrderBy(query, this.model, "$sub", parsedArgs.orderBy, false, false);
|
|
3802
3863
|
}
|
|
3803
|
-
if (
|
|
3804
|
-
query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub",
|
|
3864
|
+
if (parsedArgs.having) {
|
|
3865
|
+
query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub", parsedArgs.having));
|
|
3805
3866
|
}
|
|
3806
3867
|
for (const by of bys) {
|
|
3807
3868
|
query = query.select(() => sql7.ref(`$sub.${by}`).as(by));
|
|
3808
3869
|
}
|
|
3809
|
-
for (const [key, value] of Object.entries(
|
|
3870
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3810
3871
|
switch (key) {
|
|
3811
3872
|
case "_count": {
|
|
3812
3873
|
if (value === true) {
|
|
@@ -3889,7 +3950,8 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3889
3950
|
__name(this, "UpdateOperationHandler");
|
|
3890
3951
|
}
|
|
3891
3952
|
async handle(operation, args) {
|
|
3892
|
-
|
|
3953
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3954
|
+
return match13(operation).with("update", () => this.runUpdate(this.inputValidator.validateUpdateArgs(this.model, normalizedArgs))).with("updateMany", () => this.runUpdateMany(this.inputValidator.validateUpdateManyArgs(this.model, normalizedArgs))).with("updateManyAndReturn", () => this.runUpdateManyAndReturn(this.inputValidator.validateUpdateManyAndReturnArgs(this.model, normalizedArgs))).with("upsert", () => this.runUpsert(this.inputValidator.validateUpsertArgs(this.model, normalizedArgs))).exhaustive();
|
|
3893
3955
|
}
|
|
3894
3956
|
async runUpdate(args) {
|
|
3895
3957
|
const result = await this.safeTransaction(async (tx) => {
|
|
@@ -3945,6 +4007,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3945
4007
|
};
|
|
3946
4008
|
|
|
3947
4009
|
// src/client/crud/validator.ts
|
|
4010
|
+
import { invariant as invariant8 } from "@zenstackhq/common-helpers";
|
|
3948
4011
|
import Decimal from "decimal.js";
|
|
3949
4012
|
import stableStringify from "json-stable-stringify";
|
|
3950
4013
|
import { match as match14, P as P2 } from "ts-pattern";
|
|
@@ -3954,10 +4017,9 @@ var InputValidator = class {
|
|
|
3954
4017
|
__name(this, "InputValidator");
|
|
3955
4018
|
}
|
|
3956
4019
|
schema;
|
|
3957
|
-
schemaCache;
|
|
4020
|
+
schemaCache = /* @__PURE__ */ new Map();
|
|
3958
4021
|
constructor(schema) {
|
|
3959
4022
|
this.schema = schema;
|
|
3960
|
-
this.schemaCache = /* @__PURE__ */ new Map();
|
|
3961
4023
|
}
|
|
3962
4024
|
validateFindArgs(model, unique, args) {
|
|
3963
4025
|
return this.validate(model, "find", {
|
|
@@ -4014,7 +4076,7 @@ var InputValidator = class {
|
|
|
4014
4076
|
}
|
|
4015
4077
|
const { error } = schema.safeParse(args);
|
|
4016
4078
|
if (error) {
|
|
4017
|
-
throw new
|
|
4079
|
+
throw new InputValidationError(`Invalid ${operation} args: ${error.message}`, error);
|
|
4018
4080
|
}
|
|
4019
4081
|
return args;
|
|
4020
4082
|
}
|
|
@@ -4061,7 +4123,7 @@ var InputValidator = class {
|
|
|
4061
4123
|
makeWhereSchema(model, unique, withoutRelationFields = false) {
|
|
4062
4124
|
const modelDef = getModel(this.schema, model);
|
|
4063
4125
|
if (!modelDef) {
|
|
4064
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
4126
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
4065
4127
|
}
|
|
4066
4128
|
const fields = {};
|
|
4067
4129
|
for (const field of Object.keys(modelDef.fields)) {
|
|
@@ -4111,14 +4173,28 @@ var InputValidator = class {
|
|
|
4111
4173
|
const uniqueFields = getUniqueFields(this.schema, model);
|
|
4112
4174
|
for (const uniqueField of uniqueFields) {
|
|
4113
4175
|
if ("defs" in uniqueField) {
|
|
4114
|
-
fields[uniqueField.name] = z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) =>
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4176
|
+
fields[uniqueField.name] = z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
|
|
4177
|
+
invariant8(!def.relation, "unique field cannot be a relation");
|
|
4178
|
+
let fieldSchema;
|
|
4179
|
+
const enumDef = getEnum(this.schema, def.type);
|
|
4180
|
+
if (enumDef) {
|
|
4181
|
+
if (Object.keys(enumDef).length > 0) {
|
|
4182
|
+
fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional);
|
|
4183
|
+
} else {
|
|
4184
|
+
fieldSchema = z.never();
|
|
4185
|
+
}
|
|
4186
|
+
} else {
|
|
4187
|
+
fieldSchema = this.makePrimitiveFilterSchema(def.type, !!def.optional);
|
|
4188
|
+
}
|
|
4189
|
+
return [
|
|
4190
|
+
key,
|
|
4191
|
+
fieldSchema
|
|
4192
|
+
];
|
|
4193
|
+
}))).optional();
|
|
4118
4194
|
}
|
|
4119
4195
|
}
|
|
4120
4196
|
}
|
|
4121
|
-
fields["$expr"] = z.
|
|
4197
|
+
fields["$expr"] = z.custom((v) => typeof v === "function").optional();
|
|
4122
4198
|
fields["AND"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
|
|
4123
4199
|
fields["OR"] = z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)).array().optional();
|
|
4124
4200
|
fields["NOT"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
|
|
@@ -4164,7 +4240,7 @@ var InputValidator = class {
|
|
|
4164
4240
|
});
|
|
4165
4241
|
}
|
|
4166
4242
|
makePrimitiveFilterSchema(type, optional) {
|
|
4167
|
-
return match14(type).with("String", () => this.makeStringFilterSchema(optional)).with(P2.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();
|
|
4243
|
+
return match14(type).with("String", () => this.makeStringFilterSchema(optional)).with(P2.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", () => z.any()).with("Unsupported", () => z.never()).exhaustive();
|
|
4168
4244
|
}
|
|
4169
4245
|
makeDateTimeFilterSchema(optional) {
|
|
4170
4246
|
return this.makeCommonPrimitiveFilterSchema(z.union([
|
|
@@ -4358,8 +4434,8 @@ var InputValidator = class {
|
|
|
4358
4434
|
return this.refineForSelectOmitMutuallyExclusive(result).optional();
|
|
4359
4435
|
}
|
|
4360
4436
|
makeCreateDataSchema(model, canBeArray, withoutFields = [], withoutRelationFields = false) {
|
|
4361
|
-
const
|
|
4362
|
-
const
|
|
4437
|
+
const uncheckedVariantFields = {};
|
|
4438
|
+
const checkedVariantFields = {};
|
|
4363
4439
|
const modelDef = requireModel(this.schema, model);
|
|
4364
4440
|
const hasRelation = !withoutRelationFields && Object.entries(modelDef.fields).some(([f, def]) => !withoutFields.includes(f) && def.relation);
|
|
4365
4441
|
Object.keys(modelDef.fields).forEach((field) => {
|
|
@@ -4401,7 +4477,10 @@ var InputValidator = class {
|
|
|
4401
4477
|
if (fieldDef.optional && !fieldDef.array) {
|
|
4402
4478
|
fieldSchema = fieldSchema.nullable();
|
|
4403
4479
|
}
|
|
4404
|
-
|
|
4480
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4481
|
+
if (fieldDef.array || !fieldDef.relation.references) {
|
|
4482
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4483
|
+
}
|
|
4405
4484
|
} else {
|
|
4406
4485
|
let fieldSchema = this.makePrimitiveSchema(fieldDef.type);
|
|
4407
4486
|
if (fieldDef.array) {
|
|
@@ -4418,23 +4497,23 @@ var InputValidator = class {
|
|
|
4418
4497
|
if (fieldDef.optional) {
|
|
4419
4498
|
fieldSchema = fieldSchema.nullable();
|
|
4420
4499
|
}
|
|
4421
|
-
|
|
4500
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4422
4501
|
if (!fieldDef.foreignKeyFor) {
|
|
4423
|
-
|
|
4502
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4424
4503
|
}
|
|
4425
4504
|
}
|
|
4426
4505
|
});
|
|
4427
4506
|
if (!hasRelation) {
|
|
4428
|
-
return this.orArray(z.object(
|
|
4507
|
+
return this.orArray(z.object(uncheckedVariantFields).strict(), canBeArray);
|
|
4429
4508
|
} else {
|
|
4430
4509
|
return z.union([
|
|
4431
|
-
z.object(
|
|
4432
|
-
z.object(
|
|
4510
|
+
z.object(uncheckedVariantFields).strict(),
|
|
4511
|
+
z.object(checkedVariantFields).strict(),
|
|
4433
4512
|
...canBeArray ? [
|
|
4434
|
-
z.array(z.object(
|
|
4513
|
+
z.array(z.object(uncheckedVariantFields).strict())
|
|
4435
4514
|
] : [],
|
|
4436
4515
|
...canBeArray ? [
|
|
4437
|
-
z.array(z.object(
|
|
4516
|
+
z.array(z.object(checkedVariantFields).strict())
|
|
4438
4517
|
] : []
|
|
4439
4518
|
]);
|
|
4440
4519
|
}
|
|
@@ -4479,7 +4558,7 @@ var InputValidator = class {
|
|
|
4479
4558
|
fields["deleteMany"] = this.makeDeleteRelationDataSchema(fieldType, true, false).optional();
|
|
4480
4559
|
}
|
|
4481
4560
|
}
|
|
4482
|
-
return z.object(fields).strict()
|
|
4561
|
+
return z.object(fields).strict();
|
|
4483
4562
|
}
|
|
4484
4563
|
makeSetDataSchema(model, canBeArray) {
|
|
4485
4564
|
return this.orArray(this.makeWhereSchema(model, true), canBeArray);
|
|
@@ -4556,8 +4635,8 @@ var InputValidator = class {
|
|
|
4556
4635
|
return this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
4557
4636
|
}
|
|
4558
4637
|
makeUpdateDataSchema(model, withoutFields = [], withoutRelationFields = false) {
|
|
4559
|
-
const
|
|
4560
|
-
const
|
|
4638
|
+
const uncheckedVariantFields = {};
|
|
4639
|
+
const checkedVariantFields = {};
|
|
4561
4640
|
const modelDef = requireModel(this.schema, model);
|
|
4562
4641
|
const hasRelation = Object.entries(modelDef.fields).some(([key, value]) => value.relation && !withoutFields.includes(key));
|
|
4563
4642
|
Object.keys(modelDef.fields).forEach((field) => {
|
|
@@ -4582,7 +4661,10 @@ var InputValidator = class {
|
|
|
4582
4661
|
if (fieldDef.optional && !fieldDef.array) {
|
|
4583
4662
|
fieldSchema = fieldSchema.nullable();
|
|
4584
4663
|
}
|
|
4585
|
-
|
|
4664
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4665
|
+
if (fieldDef.array || !fieldDef.relation.references) {
|
|
4666
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4667
|
+
}
|
|
4586
4668
|
} else {
|
|
4587
4669
|
let fieldSchema = this.makePrimitiveSchema(fieldDef.type).optional();
|
|
4588
4670
|
if (this.isNumericField(fieldDef)) {
|
|
@@ -4609,18 +4691,18 @@ var InputValidator = class {
|
|
|
4609
4691
|
if (fieldDef.optional) {
|
|
4610
4692
|
fieldSchema = fieldSchema.nullable();
|
|
4611
4693
|
}
|
|
4612
|
-
|
|
4694
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4613
4695
|
if (!fieldDef.foreignKeyFor) {
|
|
4614
|
-
|
|
4696
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4615
4697
|
}
|
|
4616
4698
|
}
|
|
4617
4699
|
});
|
|
4618
4700
|
if (!hasRelation) {
|
|
4619
|
-
return z.object(
|
|
4701
|
+
return z.object(uncheckedVariantFields).strict();
|
|
4620
4702
|
} else {
|
|
4621
4703
|
return z.union([
|
|
4622
|
-
z.object(
|
|
4623
|
-
z.object(
|
|
4704
|
+
z.object(uncheckedVariantFields).strict(),
|
|
4705
|
+
z.object(checkedVariantFields).strict()
|
|
4624
4706
|
]);
|
|
4625
4707
|
}
|
|
4626
4708
|
}
|
|
@@ -4914,8 +4996,9 @@ function performanceNow() {
|
|
|
4914
4996
|
__name(performanceNow, "performanceNow");
|
|
4915
4997
|
|
|
4916
4998
|
// src/client/executor/zenstack-query-executor.ts
|
|
4917
|
-
import { AndNode as AndNode2, DefaultQueryExecutor, DeleteQueryNode as DeleteQueryNode2, InsertQueryNode as InsertQueryNode2, ReturningNode as ReturningNode3, SelectionNode as SelectionNode4,
|
|
4999
|
+
import { AndNode as AndNode2, DefaultQueryExecutor, DeleteQueryNode as DeleteQueryNode2, InsertQueryNode as InsertQueryNode2, ReturningNode as ReturningNode3, SelectionNode as SelectionNode4, UpdateQueryNode as UpdateQueryNode2, WhereNode as WhereNode3 } from "kysely";
|
|
4918
5000
|
import { nanoid as nanoid2 } from "nanoid";
|
|
5001
|
+
import { inspect as inspect2 } from "util";
|
|
4919
5002
|
import { match as match15 } from "ts-pattern";
|
|
4920
5003
|
|
|
4921
5004
|
// src/client/executor/name-mapper.ts
|
|
@@ -4925,11 +5008,11 @@ var QueryNameMapper = class extends OperationNodeTransformer2 {
|
|
|
4925
5008
|
__name(this, "QueryNameMapper");
|
|
4926
5009
|
}
|
|
4927
5010
|
schema;
|
|
4928
|
-
modelToTableMap;
|
|
4929
|
-
fieldToColumnMap;
|
|
4930
|
-
modelStack;
|
|
5011
|
+
modelToTableMap = /* @__PURE__ */ new Map();
|
|
5012
|
+
fieldToColumnMap = /* @__PURE__ */ new Map();
|
|
5013
|
+
modelStack = [];
|
|
4931
5014
|
constructor(schema) {
|
|
4932
|
-
super(), this.schema = schema
|
|
5015
|
+
super(), this.schema = schema;
|
|
4933
5016
|
for (const [modelName, modelDef] of Object.entries(schema.models)) {
|
|
4934
5017
|
const mappedName = this.getMappedName(modelDef);
|
|
4935
5018
|
if (mappedName) {
|
|
@@ -5150,7 +5233,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5150
5233
|
mutationInterceptionInfo = await this.callMutationInterceptionFilters(queryNode);
|
|
5151
5234
|
}
|
|
5152
5235
|
const task = /* @__PURE__ */ __name(async () => {
|
|
5153
|
-
|
|
5236
|
+
if (this.isMutationNode(queryNode)) {
|
|
5237
|
+
await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
|
|
5238
|
+
}
|
|
5154
5239
|
const oldQueryNode = queryNode;
|
|
5155
5240
|
if ((InsertQueryNode2.is(queryNode) || DeleteQueryNode2.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
|
|
5156
5241
|
queryNode = {
|
|
@@ -5160,19 +5245,19 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5160
5245
|
])
|
|
5161
5246
|
};
|
|
5162
5247
|
}
|
|
5163
|
-
const
|
|
5164
|
-
await this.
|
|
5248
|
+
const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
|
|
5249
|
+
const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams, queryId);
|
|
5250
|
+
if (this.isMutationNode(queryNode)) {
|
|
5251
|
+
await this.callAfterQueryInterceptionFilters(result, queryNode, mutationInterceptionInfo);
|
|
5252
|
+
}
|
|
5165
5253
|
if (oldQueryNode !== queryNode) {
|
|
5166
5254
|
}
|
|
5167
5255
|
return result;
|
|
5168
5256
|
}, "task");
|
|
5169
|
-
return
|
|
5257
|
+
return task();
|
|
5170
5258
|
}
|
|
5171
|
-
proceedQueryWithKyselyInterceptors(queryNode, queryId) {
|
|
5172
|
-
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, queryId), "proceed");
|
|
5173
|
-
const makeTx = /* @__PURE__ */ __name((p) => (callback) => {
|
|
5174
|
-
return this.executeWithTransaction(() => callback(p));
|
|
5175
|
-
}, "makeTx");
|
|
5259
|
+
proceedQueryWithKyselyInterceptors(queryNode, parameters, queryId) {
|
|
5260
|
+
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters, queryId), "proceed");
|
|
5176
5261
|
const hooks = this.options.plugins?.filter((plugin) => typeof plugin.onKyselyQuery === "function").map((plugin) => plugin.onKyselyQuery.bind(plugin)) ?? [];
|
|
5177
5262
|
for (const hook of hooks) {
|
|
5178
5263
|
const _proceed = proceed;
|
|
@@ -5182,20 +5267,30 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5182
5267
|
schema: this.client.$schema,
|
|
5183
5268
|
kysely: this.kysely,
|
|
5184
5269
|
query,
|
|
5185
|
-
proceed: _proceed
|
|
5186
|
-
transaction: makeTx(_proceed)
|
|
5270
|
+
proceed: _proceed
|
|
5187
5271
|
});
|
|
5188
5272
|
}, "proceed");
|
|
5189
5273
|
}
|
|
5190
5274
|
return proceed(queryNode);
|
|
5191
5275
|
}
|
|
5192
|
-
async proceedQuery(query, queryId) {
|
|
5276
|
+
async proceedQuery(query, parameters, queryId) {
|
|
5193
5277
|
const finalQuery = this.nameMapper.transformNode(query);
|
|
5194
|
-
|
|
5278
|
+
let compiled = this.compileQuery(finalQuery);
|
|
5279
|
+
if (parameters) {
|
|
5280
|
+
compiled = {
|
|
5281
|
+
...compiled,
|
|
5282
|
+
parameters
|
|
5283
|
+
};
|
|
5284
|
+
}
|
|
5195
5285
|
try {
|
|
5196
|
-
return
|
|
5286
|
+
return await super.executeQuery(compiled, queryId);
|
|
5197
5287
|
} catch (err) {
|
|
5198
|
-
|
|
5288
|
+
let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
|
|
5289
|
+
if (this.options.debug) {
|
|
5290
|
+
message += `, parameters:
|
|
5291
|
+
${compiled.parameters.map((p) => inspect2(p)).join("\n")}`;
|
|
5292
|
+
}
|
|
5293
|
+
throw new QueryError(message, err);
|
|
5199
5294
|
}
|
|
5200
5295
|
}
|
|
5201
5296
|
isMutationNode(queryNode) {
|
|
@@ -5223,24 +5318,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5223
5318
|
return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, []);
|
|
5224
5319
|
}
|
|
5225
5320
|
withConnectionProvider(connectionProvider) {
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
if (!useTransaction || this.driver.txConnection) {
|
|
5230
|
-
return callback();
|
|
5231
|
-
} else {
|
|
5232
|
-
return this.provideConnection(async (connection) => {
|
|
5233
|
-
try {
|
|
5234
|
-
await this.driver.beginTransaction(connection, {});
|
|
5235
|
-
const result = await callback();
|
|
5236
|
-
await this.driver.commitTransaction(connection);
|
|
5237
|
-
return result;
|
|
5238
|
-
} catch (error) {
|
|
5239
|
-
await this.driver.rollbackTransaction(connection);
|
|
5240
|
-
throw error;
|
|
5241
|
-
}
|
|
5242
|
-
});
|
|
5243
|
-
}
|
|
5321
|
+
const newExecutor = new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
|
|
5322
|
+
newExecutor.client = this.client.withExecutor(newExecutor);
|
|
5323
|
+
return newExecutor;
|
|
5244
5324
|
}
|
|
5245
5325
|
get hasMutationHooks() {
|
|
5246
5326
|
return this.client.$options.plugins?.some((plugin) => plugin.beforeEntityMutation || plugin.afterEntityMutation);
|
|
@@ -5282,14 +5362,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5282
5362
|
queryNode
|
|
5283
5363
|
});
|
|
5284
5364
|
result.intercept ||= filterResult.intercept;
|
|
5285
|
-
result.useTransactionForMutation ||= filterResult.useTransactionForMutation;
|
|
5286
5365
|
result.loadBeforeMutationEntity ||= filterResult.loadBeforeMutationEntity;
|
|
5287
5366
|
result.loadAfterMutationEntity ||= filterResult.loadAfterMutationEntity;
|
|
5288
5367
|
}
|
|
5289
5368
|
}
|
|
5290
5369
|
let beforeMutationEntities;
|
|
5291
5370
|
if (result.loadBeforeMutationEntity && (UpdateQueryNode2.is(queryNode) || DeleteQueryNode2.is(queryNode))) {
|
|
5292
|
-
beforeMutationEntities = await this.loadEntities(
|
|
5371
|
+
beforeMutationEntities = await this.loadEntities(mutationModel, where);
|
|
5293
5372
|
}
|
|
5294
5373
|
return {
|
|
5295
5374
|
...result,
|
|
@@ -5302,15 +5381,14 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5302
5381
|
return void 0;
|
|
5303
5382
|
}
|
|
5304
5383
|
}
|
|
5305
|
-
callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
5384
|
+
async callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
5306
5385
|
if (!mutationInterceptionInfo?.intercept) {
|
|
5307
5386
|
return;
|
|
5308
5387
|
}
|
|
5309
5388
|
if (this.options.plugins) {
|
|
5310
5389
|
for (const plugin of this.options.plugins) {
|
|
5311
5390
|
if (plugin.beforeEntityMutation) {
|
|
5312
|
-
plugin.beforeEntityMutation({
|
|
5313
|
-
// context: this.queryContext,
|
|
5391
|
+
await plugin.beforeEntityMutation({
|
|
5314
5392
|
model: this.getMutationModel(queryNode),
|
|
5315
5393
|
action: mutationInterceptionInfo.action,
|
|
5316
5394
|
queryNode,
|
|
@@ -5331,12 +5409,12 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5331
5409
|
let afterMutationEntities = void 0;
|
|
5332
5410
|
if (mutationInterceptionInfo.loadAfterMutationEntity) {
|
|
5333
5411
|
if (UpdateQueryNode2.is(queryNode)) {
|
|
5334
|
-
afterMutationEntities = await this.loadEntities(
|
|
5412
|
+
afterMutationEntities = await this.loadEntities(mutationModel, mutationInterceptionInfo.where);
|
|
5335
5413
|
} else {
|
|
5336
5414
|
afterMutationEntities = queryResult.rows;
|
|
5337
5415
|
}
|
|
5338
5416
|
}
|
|
5339
|
-
plugin.afterEntityMutation({
|
|
5417
|
+
await plugin.afterEntityMutation({
|
|
5340
5418
|
model: this.getMutationModel(queryNode),
|
|
5341
5419
|
action: mutationInterceptionInfo.action,
|
|
5342
5420
|
queryNode,
|
|
@@ -5347,17 +5425,17 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5347
5425
|
}
|
|
5348
5426
|
}
|
|
5349
5427
|
}
|
|
5350
|
-
async loadEntities(
|
|
5351
|
-
const selectQuery = kysely.selectFrom(model).selectAll();
|
|
5428
|
+
async loadEntities(model, where) {
|
|
5429
|
+
const selectQuery = this.kysely.selectFrom(model).selectAll();
|
|
5352
5430
|
let selectQueryNode = selectQuery.toOperationNode();
|
|
5353
5431
|
selectQueryNode = {
|
|
5354
5432
|
...selectQueryNode,
|
|
5355
5433
|
where: this.andNodes(selectQueryNode.where, where)
|
|
5356
5434
|
};
|
|
5357
|
-
const compiled =
|
|
5435
|
+
const compiled = this.compileQuery(selectQueryNode);
|
|
5436
|
+
const result = await this.executeQuery(compiled, {
|
|
5358
5437
|
queryId: `zenstack-${nanoid2()}`
|
|
5359
5438
|
});
|
|
5360
|
-
const result = await kysely.executeQuery(compiled);
|
|
5361
5439
|
return result.rows;
|
|
5362
5440
|
}
|
|
5363
5441
|
andNodes(condition1, condition2) {
|
|
@@ -5386,8 +5464,8 @@ __export(functions_exports, {
|
|
|
5386
5464
|
search: () => search,
|
|
5387
5465
|
startsWith: () => startsWith
|
|
5388
5466
|
});
|
|
5467
|
+
import { invariant as invariant9, lowerCaseFirst, upperCaseFirst } from "@zenstackhq/common-helpers";
|
|
5389
5468
|
import { sql as sql8, ValueNode as ValueNode4 } from "kysely";
|
|
5390
|
-
import invariant8 from "tiny-invariant";
|
|
5391
5469
|
import { match as match16 } from "ts-pattern";
|
|
5392
5470
|
var contains = /* @__PURE__ */ __name((eb, args) => {
|
|
5393
5471
|
const [field, search2, caseInsensitive = false] = args;
|
|
@@ -5493,8 +5571,8 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
|
5493
5571
|
}, "currentOperation");
|
|
5494
5572
|
function processCasing(casing, result, model) {
|
|
5495
5573
|
const opNode = casing.toOperationNode();
|
|
5496
|
-
|
|
5497
|
-
result = match16(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () =>
|
|
5574
|
+
invariant9(ValueNode4.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
|
|
5575
|
+
result = match16(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => upperCaseFirst(result)).with("uncapitalize", () => lowerCaseFirst(result)).otherwise(() => {
|
|
5498
5576
|
throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
|
|
5499
5577
|
});
|
|
5500
5578
|
return result;
|
|
@@ -5502,8 +5580,8 @@ function processCasing(casing, result, model) {
|
|
|
5502
5580
|
__name(processCasing, "processCasing");
|
|
5503
5581
|
|
|
5504
5582
|
// src/client/helpers/schema-db-pusher.ts
|
|
5583
|
+
import { invariant as invariant10 } from "@zenstackhq/common-helpers";
|
|
5505
5584
|
import { sql as sql9 } from "kysely";
|
|
5506
|
-
import invariant9 from "tiny-invariant";
|
|
5507
5585
|
import { match as match17 } from "ts-pattern";
|
|
5508
5586
|
var SchemaDbPusher = class {
|
|
5509
5587
|
static {
|
|
@@ -5535,7 +5613,7 @@ var SchemaDbPusher = class {
|
|
|
5535
5613
|
for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
|
|
5536
5614
|
if (fieldDef.relation) {
|
|
5537
5615
|
table = this.addForeignKeyConstraint(table, model, fieldName, fieldDef);
|
|
5538
|
-
} else {
|
|
5616
|
+
} else if (!this.isComputedField(fieldDef)) {
|
|
5539
5617
|
table = this.createModelField(table, fieldName, fieldDef, modelDef);
|
|
5540
5618
|
}
|
|
5541
5619
|
}
|
|
@@ -5543,6 +5621,9 @@ var SchemaDbPusher = class {
|
|
|
5543
5621
|
table = this.addUniqueConstraint(table, modelDef);
|
|
5544
5622
|
return table;
|
|
5545
5623
|
}
|
|
5624
|
+
isComputedField(fieldDef) {
|
|
5625
|
+
return fieldDef.attributes?.some((a) => a.name === "@computed");
|
|
5626
|
+
}
|
|
5546
5627
|
addPrimaryKeyConstraint(table, model, modelDef) {
|
|
5547
5628
|
if (modelDef.idFields.length === 1) {
|
|
5548
5629
|
if (Object.values(modelDef.fields).some((f) => f.id)) {
|
|
@@ -5556,7 +5637,7 @@ var SchemaDbPusher = class {
|
|
|
5556
5637
|
}
|
|
5557
5638
|
addUniqueConstraint(table, modelDef) {
|
|
5558
5639
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
5559
|
-
|
|
5640
|
+
invariant10(typeof value === "object", "expecting an object");
|
|
5560
5641
|
if ("type" in value) {
|
|
5561
5642
|
const fieldDef = modelDef.fields[key];
|
|
5562
5643
|
if (fieldDef.unique) {
|
|
@@ -5602,7 +5683,7 @@ var SchemaDbPusher = class {
|
|
|
5602
5683
|
return "serial";
|
|
5603
5684
|
}
|
|
5604
5685
|
const type = fieldDef.type;
|
|
5605
|
-
const result = match17(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(() => {
|
|
5686
|
+
const result = match17(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(() => {
|
|
5606
5687
|
throw new Error(`Unsupported field type: ${type}`);
|
|
5607
5688
|
});
|
|
5608
5689
|
if (fieldDef.array) {
|
|
@@ -5615,7 +5696,7 @@ var SchemaDbPusher = class {
|
|
|
5615
5696
|
return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
|
|
5616
5697
|
}
|
|
5617
5698
|
addForeignKeyConstraint(table, model, fieldName, fieldDef) {
|
|
5618
|
-
|
|
5699
|
+
invariant10(fieldDef.relation, "field must be a relation");
|
|
5619
5700
|
if (!fieldDef.relation.fields || !fieldDef.relation.references) {
|
|
5620
5701
|
return table;
|
|
5621
5702
|
}
|
|
@@ -5636,11 +5717,11 @@ var SchemaDbPusher = class {
|
|
|
5636
5717
|
};
|
|
5637
5718
|
|
|
5638
5719
|
// src/client/promise.ts
|
|
5639
|
-
function
|
|
5720
|
+
function createZenStackPromise(callback) {
|
|
5640
5721
|
let promise;
|
|
5641
|
-
const cb = /* @__PURE__ */ __name(() => {
|
|
5722
|
+
const cb = /* @__PURE__ */ __name((txClient) => {
|
|
5642
5723
|
try {
|
|
5643
|
-
return promise ??= valueToPromise(callback());
|
|
5724
|
+
return promise ??= valueToPromise(callback(txClient));
|
|
5644
5725
|
} catch (err) {
|
|
5645
5726
|
return Promise.reject(err);
|
|
5646
5727
|
}
|
|
@@ -5655,10 +5736,11 @@ function createDeferredPromise(callback) {
|
|
|
5655
5736
|
finally(onFinally) {
|
|
5656
5737
|
return cb().finally(onFinally);
|
|
5657
5738
|
},
|
|
5739
|
+
cb,
|
|
5658
5740
|
[Symbol.toStringTag]: "ZenStackPromise"
|
|
5659
5741
|
};
|
|
5660
5742
|
}
|
|
5661
|
-
__name(
|
|
5743
|
+
__name(createZenStackPromise, "createZenStackPromise");
|
|
5662
5744
|
function valueToPromise(thing) {
|
|
5663
5745
|
if (typeof thing === "object" && typeof thing?.then === "function") {
|
|
5664
5746
|
return thing;
|
|
@@ -5669,8 +5751,8 @@ function valueToPromise(thing) {
|
|
|
5669
5751
|
__name(valueToPromise, "valueToPromise");
|
|
5670
5752
|
|
|
5671
5753
|
// src/client/result-processor.ts
|
|
5754
|
+
import { invariant as invariant11 } from "@zenstackhq/common-helpers";
|
|
5672
5755
|
import Decimal2 from "decimal.js";
|
|
5673
|
-
import invariant10 from "tiny-invariant";
|
|
5674
5756
|
import { match as match18 } from "ts-pattern";
|
|
5675
5757
|
var ResultProcessor = class {
|
|
5676
5758
|
static {
|
|
@@ -5744,20 +5826,20 @@ var ResultProcessor = class {
|
|
|
5744
5826
|
return this.doProcessResult(relationData, fieldDef.type);
|
|
5745
5827
|
}
|
|
5746
5828
|
transformScalar(value, type) {
|
|
5747
|
-
return match18(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);
|
|
5829
|
+
return match18(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);
|
|
5748
5830
|
}
|
|
5749
5831
|
transformDecimal(value) {
|
|
5750
5832
|
if (value instanceof Decimal2) {
|
|
5751
5833
|
return value;
|
|
5752
5834
|
}
|
|
5753
|
-
|
|
5835
|
+
invariant11(typeof value === "string" || typeof value === "number" || value instanceof Decimal2, `Expected string, number or Decimal, got ${typeof value}`);
|
|
5754
5836
|
return new Decimal2(value);
|
|
5755
5837
|
}
|
|
5756
5838
|
transformBigInt(value) {
|
|
5757
5839
|
if (typeof value === "bigint") {
|
|
5758
5840
|
return value;
|
|
5759
5841
|
}
|
|
5760
|
-
|
|
5842
|
+
invariant11(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
5761
5843
|
return BigInt(value);
|
|
5762
5844
|
}
|
|
5763
5845
|
transformBoolean(value) {
|
|
@@ -5776,6 +5858,9 @@ var ResultProcessor = class {
|
|
|
5776
5858
|
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
5777
5859
|
}
|
|
5778
5860
|
fixReversedResult(data, model, args) {
|
|
5861
|
+
if (!data) {
|
|
5862
|
+
return;
|
|
5863
|
+
}
|
|
5779
5864
|
if (Array.isArray(data) && typeof args === "object" && args && args.take !== void 0 && args.take < 0) {
|
|
5780
5865
|
data.reverse();
|
|
5781
5866
|
}
|
|
@@ -5789,13 +5874,19 @@ var ResultProcessor = class {
|
|
|
5789
5874
|
continue;
|
|
5790
5875
|
}
|
|
5791
5876
|
const fieldDef = getField(this.schema, model, field);
|
|
5792
|
-
if (!fieldDef
|
|
5877
|
+
if (!fieldDef || !fieldDef.relation || !fieldDef.array) {
|
|
5793
5878
|
continue;
|
|
5794
5879
|
}
|
|
5795
5880
|
this.fixReversedResult(row[field], fieldDef.type, value);
|
|
5796
5881
|
}
|
|
5797
5882
|
}
|
|
5798
5883
|
}
|
|
5884
|
+
transformJson(value) {
|
|
5885
|
+
return match18(this.schema.provider.type).with("sqlite", () => {
|
|
5886
|
+
invariant11(typeof value === "string", "Expected string, got " + typeof value);
|
|
5887
|
+
return JSON.parse(value);
|
|
5888
|
+
}).otherwise(() => value);
|
|
5889
|
+
}
|
|
5799
5890
|
};
|
|
5800
5891
|
|
|
5801
5892
|
// src/client/client-impl.ts
|
|
@@ -5814,7 +5905,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
5814
5905
|
$schema;
|
|
5815
5906
|
kyselyProps;
|
|
5816
5907
|
auth;
|
|
5817
|
-
constructor(schema, options, baseClient) {
|
|
5908
|
+
constructor(schema, options, baseClient, executor) {
|
|
5818
5909
|
this.schema = schema;
|
|
5819
5910
|
this.options = options;
|
|
5820
5911
|
this.$schema = schema;
|
|
@@ -5826,16 +5917,16 @@ var ClientImpl = class _ClientImpl {
|
|
|
5826
5917
|
if (baseClient) {
|
|
5827
5918
|
this.kyselyProps = {
|
|
5828
5919
|
...baseClient.kyselyProps,
|
|
5829
|
-
executor: new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
|
|
5920
|
+
executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
|
|
5830
5921
|
};
|
|
5831
5922
|
this.kyselyRaw = baseClient.kyselyRaw;
|
|
5923
|
+
this.auth = baseClient.auth;
|
|
5832
5924
|
} else {
|
|
5833
5925
|
const dialect = this.getKyselyDialect();
|
|
5834
5926
|
const driver = new ZenStackDriver(dialect.createDriver(), new Log(this.$options.log ?? []));
|
|
5835
5927
|
const compiler = dialect.createQueryCompiler();
|
|
5836
5928
|
const adapter = dialect.createAdapter();
|
|
5837
5929
|
const connectionProvider = new DefaultConnectionProvider(driver);
|
|
5838
|
-
const executor = new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider);
|
|
5839
5930
|
this.kyselyProps = {
|
|
5840
5931
|
config: {
|
|
5841
5932
|
dialect,
|
|
@@ -5843,7 +5934,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
5843
5934
|
},
|
|
5844
5935
|
dialect,
|
|
5845
5936
|
driver,
|
|
5846
|
-
executor
|
|
5937
|
+
executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
|
|
5847
5938
|
};
|
|
5848
5939
|
this.kyselyRaw = new Kysely({
|
|
5849
5940
|
...this.kyselyProps,
|
|
@@ -5859,31 +5950,67 @@ var ClientImpl = class _ClientImpl {
|
|
|
5859
5950
|
get $qbRaw() {
|
|
5860
5951
|
return this.kyselyRaw;
|
|
5861
5952
|
}
|
|
5953
|
+
get isTransaction() {
|
|
5954
|
+
return this.kysely.isTransaction;
|
|
5955
|
+
}
|
|
5956
|
+
/**
|
|
5957
|
+
* Create a new client with a new query executor.
|
|
5958
|
+
*/
|
|
5959
|
+
withExecutor(executor) {
|
|
5960
|
+
return new _ClientImpl(this.schema, this.$options, this, executor);
|
|
5961
|
+
}
|
|
5862
5962
|
getKyselyDialect() {
|
|
5863
5963
|
return match19(this.schema.provider.type).with("sqlite", () => this.makeSqliteKyselyDialect()).with("postgresql", () => this.makePostgresKyselyDialect()).exhaustive();
|
|
5864
5964
|
}
|
|
5865
5965
|
makePostgresKyselyDialect() {
|
|
5866
|
-
|
|
5867
|
-
const mergedConfig = {
|
|
5868
|
-
...dialectConfigProvider(),
|
|
5869
|
-
...this.options?.dialectConfig
|
|
5870
|
-
};
|
|
5871
|
-
return new PostgresDialect(mergedConfig);
|
|
5966
|
+
return new PostgresDialect(this.options.dialectConfig);
|
|
5872
5967
|
}
|
|
5873
5968
|
makeSqliteKyselyDialect() {
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5969
|
+
return new SqliteDialect(this.options.dialectConfig);
|
|
5970
|
+
}
|
|
5971
|
+
// implementation
|
|
5972
|
+
async $transaction(input, options) {
|
|
5973
|
+
invariant12(typeof input === "function" || Array.isArray(input) && input.every((p) => p.then && p.cb), "Invalid transaction input, expected a function or an array of ZenStackPromise");
|
|
5974
|
+
if (typeof input === "function") {
|
|
5975
|
+
return this.interactiveTransaction(input, options);
|
|
5976
|
+
} else {
|
|
5977
|
+
return this.sequentialTransaction(input, options);
|
|
5978
|
+
}
|
|
5880
5979
|
}
|
|
5881
|
-
async
|
|
5882
|
-
|
|
5883
|
-
|
|
5980
|
+
async interactiveTransaction(callback, options) {
|
|
5981
|
+
if (this.kysely.isTransaction) {
|
|
5982
|
+
return callback(this);
|
|
5983
|
+
} else {
|
|
5984
|
+
let txBuilder = this.kysely.transaction();
|
|
5985
|
+
if (options?.isolationLevel) {
|
|
5986
|
+
txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
|
|
5987
|
+
}
|
|
5988
|
+
return txBuilder.execute((tx) => {
|
|
5989
|
+
const txClient = new _ClientImpl(this.schema, this.$options, this);
|
|
5990
|
+
txClient.kysely = tx;
|
|
5991
|
+
return callback(txClient);
|
|
5992
|
+
});
|
|
5993
|
+
}
|
|
5994
|
+
}
|
|
5995
|
+
async sequentialTransaction(arg, options) {
|
|
5996
|
+
const execute = /* @__PURE__ */ __name(async (tx) => {
|
|
5997
|
+
const txClient = new _ClientImpl(this.schema, this.$options, this);
|
|
5884
5998
|
txClient.kysely = tx;
|
|
5885
|
-
|
|
5886
|
-
|
|
5999
|
+
const result = [];
|
|
6000
|
+
for (const promise of arg) {
|
|
6001
|
+
result.push(await promise.cb(txClient));
|
|
6002
|
+
}
|
|
6003
|
+
return result;
|
|
6004
|
+
}, "execute");
|
|
6005
|
+
if (this.kysely.isTransaction) {
|
|
6006
|
+
return execute(this.kysely);
|
|
6007
|
+
} else {
|
|
6008
|
+
let txBuilder = this.kysely.transaction();
|
|
6009
|
+
if (options?.isolationLevel) {
|
|
6010
|
+
txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
|
|
6011
|
+
}
|
|
6012
|
+
return txBuilder.execute((tx) => execute(tx));
|
|
6013
|
+
}
|
|
5887
6014
|
}
|
|
5888
6015
|
get $procedures() {
|
|
5889
6016
|
return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
|
|
@@ -5914,12 +6041,19 @@ var ClientImpl = class _ClientImpl {
|
|
|
5914
6041
|
const newOptions = {
|
|
5915
6042
|
...this.options,
|
|
5916
6043
|
plugins: [
|
|
5917
|
-
...this.options
|
|
6044
|
+
...this.options.plugins ?? [],
|
|
5918
6045
|
plugin
|
|
5919
6046
|
]
|
|
5920
6047
|
};
|
|
5921
6048
|
return new _ClientImpl(this.schema, newOptions, this);
|
|
5922
6049
|
}
|
|
6050
|
+
$unuse(pluginId) {
|
|
6051
|
+
const newOptions = {
|
|
6052
|
+
...this.options,
|
|
6053
|
+
plugins: this.options.plugins?.filter((p) => p.id !== pluginId)
|
|
6054
|
+
};
|
|
6055
|
+
return new _ClientImpl(this.schema, newOptions, this);
|
|
6056
|
+
}
|
|
5923
6057
|
$unuseAll() {
|
|
5924
6058
|
const newOptions = {
|
|
5925
6059
|
...this.options,
|
|
@@ -5938,6 +6072,39 @@ var ClientImpl = class _ClientImpl {
|
|
|
5938
6072
|
get $auth() {
|
|
5939
6073
|
return this.auth;
|
|
5940
6074
|
}
|
|
6075
|
+
$executeRaw(query, ...values) {
|
|
6076
|
+
return createZenStackPromise(async () => {
|
|
6077
|
+
const result = await sql10(query, ...values).execute(this.kysely);
|
|
6078
|
+
return Number(result.numAffectedRows ?? 0);
|
|
6079
|
+
});
|
|
6080
|
+
}
|
|
6081
|
+
$executeRawUnsafe(query, ...values) {
|
|
6082
|
+
return createZenStackPromise(async () => {
|
|
6083
|
+
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
6084
|
+
const result = await this.kysely.executeQuery(compiledQuery);
|
|
6085
|
+
return Number(result.numAffectedRows ?? 0);
|
|
6086
|
+
});
|
|
6087
|
+
}
|
|
6088
|
+
$queryRaw(query, ...values) {
|
|
6089
|
+
return createZenStackPromise(async () => {
|
|
6090
|
+
const result = await sql10(query, ...values).execute(this.kysely);
|
|
6091
|
+
return result.rows;
|
|
6092
|
+
});
|
|
6093
|
+
}
|
|
6094
|
+
$queryRawUnsafe(query, ...values) {
|
|
6095
|
+
return createZenStackPromise(async () => {
|
|
6096
|
+
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
6097
|
+
const result = await this.kysely.executeQuery(compiledQuery);
|
|
6098
|
+
return result.rows;
|
|
6099
|
+
});
|
|
6100
|
+
}
|
|
6101
|
+
createRawCompiledQuery(query, values) {
|
|
6102
|
+
const q = CompiledQuery.raw(query, values);
|
|
6103
|
+
return {
|
|
6104
|
+
...q,
|
|
6105
|
+
$raw: true
|
|
6106
|
+
};
|
|
6107
|
+
}
|
|
5941
6108
|
};
|
|
5942
6109
|
function createClientProxy(client) {
|
|
5943
6110
|
const inputValidator = new InputValidator(client.$schema);
|
|
@@ -5960,9 +6127,9 @@ function createClientProxy(client) {
|
|
|
5960
6127
|
__name(createClientProxy, "createClientProxy");
|
|
5961
6128
|
function createModelCrudHandler(client, model, inputValidator, resultProcessor) {
|
|
5962
6129
|
const createPromise = /* @__PURE__ */ __name((operation, args, handler, postProcess = false, throwIfNoResult = false) => {
|
|
5963
|
-
return
|
|
5964
|
-
let proceed = /* @__PURE__ */ __name(async (_args
|
|
5965
|
-
const _handler =
|
|
6130
|
+
return createZenStackPromise(async (txClient) => {
|
|
6131
|
+
let proceed = /* @__PURE__ */ __name(async (_args) => {
|
|
6132
|
+
const _handler = txClient ? handler.withClient(txClient) : handler;
|
|
5966
6133
|
const r = await _handler.handle(operation, _args ?? args);
|
|
5967
6134
|
if (!r && throwIfNoResult) {
|
|
5968
6135
|
throw new NotFoundError(model);
|
|
@@ -5975,22 +6142,31 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
5975
6142
|
}
|
|
5976
6143
|
return result;
|
|
5977
6144
|
}, "proceed");
|
|
5978
|
-
const context = {
|
|
5979
|
-
client,
|
|
5980
|
-
model,
|
|
5981
|
-
operation,
|
|
5982
|
-
queryArgs: args
|
|
5983
|
-
};
|
|
5984
6145
|
const plugins = [
|
|
5985
6146
|
...client.$options.plugins ?? []
|
|
5986
6147
|
];
|
|
5987
6148
|
for (const plugin of plugins) {
|
|
5988
|
-
if (plugin.onQuery) {
|
|
5989
|
-
const
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
6149
|
+
if (plugin.onQuery && typeof plugin.onQuery === "object") {
|
|
6150
|
+
for (const [_model, modelHooks] of Object.entries(plugin.onQuery)) {
|
|
6151
|
+
if (_model === lowerCaseFirst2(model) || _model === "$allModels") {
|
|
6152
|
+
if (modelHooks && typeof modelHooks === "object") {
|
|
6153
|
+
for (const [op, opHooks] of Object.entries(modelHooks)) {
|
|
6154
|
+
if (op === operation || op === "$allOperations") {
|
|
6155
|
+
if (typeof opHooks === "function") {
|
|
6156
|
+
const _proceed = proceed;
|
|
6157
|
+
proceed = /* @__PURE__ */ __name(() => opHooks({
|
|
6158
|
+
client,
|
|
6159
|
+
model,
|
|
6160
|
+
operation,
|
|
6161
|
+
args,
|
|
6162
|
+
query: _proceed
|
|
6163
|
+
}), "proceed");
|
|
6164
|
+
}
|
|
6165
|
+
}
|
|
6166
|
+
}
|
|
6167
|
+
}
|
|
6168
|
+
}
|
|
6169
|
+
}
|
|
5994
6170
|
}
|
|
5995
6171
|
}
|
|
5996
6172
|
return proceed(args);
|
|
@@ -6046,12 +6222,23 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
6046
6222
|
return createPromise("aggregate", args, new AggregateOperationHandler(client, model, inputValidator), false);
|
|
6047
6223
|
}, "aggregate"),
|
|
6048
6224
|
groupBy: /* @__PURE__ */ __name((args) => {
|
|
6049
|
-
return createPromise("groupBy", args, new
|
|
6225
|
+
return createPromise("groupBy", args, new GroupByOperationHandler(client, model, inputValidator));
|
|
6050
6226
|
}, "groupBy")
|
|
6051
6227
|
};
|
|
6052
6228
|
}
|
|
6053
6229
|
__name(createModelCrudHandler, "createModelCrudHandler");
|
|
6230
|
+
|
|
6231
|
+
// src/client/plugin.ts
|
|
6232
|
+
function definePlugin(plugin) {
|
|
6233
|
+
return plugin;
|
|
6234
|
+
}
|
|
6235
|
+
__name(definePlugin, "definePlugin");
|
|
6054
6236
|
export {
|
|
6055
|
-
|
|
6237
|
+
InputValidationError,
|
|
6238
|
+
InternalError,
|
|
6239
|
+
NotFoundError,
|
|
6240
|
+
QueryError,
|
|
6241
|
+
ZenStackClient,
|
|
6242
|
+
definePlugin
|
|
6056
6243
|
};
|
|
6057
6244
|
//# sourceMappingURL=index.js.map
|