@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.cjs
CHANGED
|
@@ -31,11 +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
|
|
44
|
+
var import_common_helpers13 = require("@zenstackhq/common-helpers");
|
|
39
45
|
var import_kysely16 = require("kysely");
|
|
40
46
|
var import_ts_pattern19 = require("ts-pattern");
|
|
41
47
|
|
|
@@ -44,21 +50,30 @@ var import_kysely9 = require("kysely");
|
|
|
44
50
|
var import_ts_pattern9 = require("ts-pattern");
|
|
45
51
|
|
|
46
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
|
+
};
|
|
47
63
|
var QueryError = class extends Error {
|
|
48
64
|
static {
|
|
49
65
|
__name(this, "QueryError");
|
|
50
66
|
}
|
|
51
|
-
constructor(message) {
|
|
52
|
-
super(message
|
|
67
|
+
constructor(message, cause) {
|
|
68
|
+
super(message, {
|
|
69
|
+
cause
|
|
70
|
+
});
|
|
53
71
|
}
|
|
54
72
|
};
|
|
55
73
|
var InternalError = class extends Error {
|
|
56
74
|
static {
|
|
57
75
|
__name(this, "InternalError");
|
|
58
76
|
}
|
|
59
|
-
constructor(message) {
|
|
60
|
-
super(message);
|
|
61
|
-
}
|
|
62
77
|
};
|
|
63
78
|
var NotFoundError = class extends Error {
|
|
64
79
|
static {
|
|
@@ -77,7 +92,7 @@ __name(getModel, "getModel");
|
|
|
77
92
|
function requireModel(schema, model) {
|
|
78
93
|
const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
|
|
79
94
|
if (!matchedName) {
|
|
80
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
95
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
81
96
|
}
|
|
82
97
|
return schema.models[matchedName];
|
|
83
98
|
}
|
|
@@ -202,7 +217,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias) {
|
|
|
202
217
|
computer = computedFields?.[model]?.[field];
|
|
203
218
|
}
|
|
204
219
|
if (!computer) {
|
|
205
|
-
throw new QueryError(`Computed field "${field}" implementation not provided`);
|
|
220
|
+
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
206
221
|
}
|
|
207
222
|
return computer(eb);
|
|
208
223
|
}
|
|
@@ -310,9 +325,10 @@ __name(safeJSONStringify, "safeJSONStringify");
|
|
|
310
325
|
|
|
311
326
|
// src/client/crud/operations/base.ts
|
|
312
327
|
var import_cuid2 = require("@paralleldrive/cuid2");
|
|
328
|
+
var import_common_helpers8 = require("@zenstackhq/common-helpers");
|
|
313
329
|
var import_kysely8 = require("kysely");
|
|
314
330
|
var import_nanoid = require("nanoid");
|
|
315
|
-
var
|
|
331
|
+
var import_node_util = require("util");
|
|
316
332
|
var import_ts_pattern8 = require("ts-pattern");
|
|
317
333
|
var import_ulid = require("ulid");
|
|
318
334
|
var uuid = __toESM(require("uuid"), 1);
|
|
@@ -330,21 +346,21 @@ var RejectedByPolicyError = class extends Error {
|
|
|
330
346
|
};
|
|
331
347
|
|
|
332
348
|
// src/plugins/policy/policy-handler.ts
|
|
349
|
+
var import_common_helpers6 = require("@zenstackhq/common-helpers");
|
|
333
350
|
var import_kysely7 = require("kysely");
|
|
334
|
-
var import_tiny_invariant6 = __toESM(require("tiny-invariant"), 1);
|
|
335
351
|
var import_ts_pattern7 = require("ts-pattern");
|
|
336
352
|
|
|
337
353
|
// src/client/crud/dialects/index.ts
|
|
338
354
|
var import_ts_pattern4 = require("ts-pattern");
|
|
339
355
|
|
|
340
356
|
// src/client/crud/dialects/postgresql.ts
|
|
357
|
+
var import_common_helpers2 = require("@zenstackhq/common-helpers");
|
|
341
358
|
var import_kysely2 = require("kysely");
|
|
342
|
-
var import_tiny_invariant2 = __toESM(require("tiny-invariant"), 1);
|
|
343
359
|
var import_ts_pattern2 = require("ts-pattern");
|
|
344
360
|
|
|
345
361
|
// src/client/crud/dialects/base.ts
|
|
362
|
+
var import_common_helpers = require("@zenstackhq/common-helpers");
|
|
346
363
|
var import_kysely = require("kysely");
|
|
347
|
-
var import_tiny_invariant = __toESM(require("tiny-invariant"), 1);
|
|
348
364
|
var import_ts_pattern = require("ts-pattern");
|
|
349
365
|
|
|
350
366
|
// src/utils/enumerate.ts
|
|
@@ -362,7 +378,6 @@ function enumerate(x) {
|
|
|
362
378
|
__name(enumerate, "enumerate");
|
|
363
379
|
|
|
364
380
|
// src/client/crud/dialects/base.ts
|
|
365
|
-
var import_is_plain_object = require("is-plain-object");
|
|
366
381
|
var BaseCrudDialect = class {
|
|
367
382
|
static {
|
|
368
383
|
__name(this, "BaseCrudDialect");
|
|
@@ -373,7 +388,7 @@ var BaseCrudDialect = class {
|
|
|
373
388
|
this.schema = schema;
|
|
374
389
|
this.options = options;
|
|
375
390
|
}
|
|
376
|
-
transformPrimitive(value, _type) {
|
|
391
|
+
transformPrimitive(value, _type, _forArrayField) {
|
|
377
392
|
return value;
|
|
378
393
|
}
|
|
379
394
|
buildFilter(eb, model, modelAlias, where) {
|
|
@@ -516,7 +531,7 @@ var BaseCrudDialect = class {
|
|
|
516
531
|
if (_value === void 0) {
|
|
517
532
|
continue;
|
|
518
533
|
}
|
|
519
|
-
const value = this.transformPrimitive(_value, fieldType);
|
|
534
|
+
const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
|
|
520
535
|
switch (key) {
|
|
521
536
|
case "equals": {
|
|
522
537
|
clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
|
|
@@ -554,13 +569,17 @@ var BaseCrudDialect = class {
|
|
|
554
569
|
if (isEnum(this.schema, fieldDef.type)) {
|
|
555
570
|
return this.buildEnumFilter(eb, modelAlias, field, fieldDef, payload);
|
|
556
571
|
}
|
|
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)).
|
|
572
|
+
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", () => {
|
|
573
|
+
throw new InternalError("JSON filters are not supported yet");
|
|
574
|
+
}).with("Unsupported", () => {
|
|
575
|
+
throw new QueryError(`Unsupported field cannot be used in filters`);
|
|
576
|
+
}).exhaustive();
|
|
558
577
|
}
|
|
559
578
|
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
560
|
-
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
|
|
579
|
+
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
561
580
|
}
|
|
562
581
|
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
|
|
563
|
-
if (payload === null || !(0,
|
|
582
|
+
if (payload === null || !(0, import_common_helpers.isPlainObject)(payload)) {
|
|
564
583
|
return {
|
|
565
584
|
conditions: [
|
|
566
585
|
this.buildLiteralFilter(eb, lhs, type, payload)
|
|
@@ -576,14 +595,14 @@ var BaseCrudDialect = class {
|
|
|
576
595
|
}
|
|
577
596
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
578
597
|
const condition = (0, import_ts_pattern.match)(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
579
|
-
(0,
|
|
598
|
+
(0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
580
599
|
if (rhs.length === 0) {
|
|
581
600
|
return this.false(eb);
|
|
582
601
|
} else {
|
|
583
602
|
return eb(lhs, "in", rhs);
|
|
584
603
|
}
|
|
585
604
|
}).with("notIn", () => {
|
|
586
|
-
(0,
|
|
605
|
+
(0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
587
606
|
if (rhs.length === 0) {
|
|
588
607
|
return this.true(eb);
|
|
589
608
|
} else {
|
|
@@ -644,22 +663,22 @@ var BaseCrudDialect = class {
|
|
|
644
663
|
}
|
|
645
664
|
}
|
|
646
665
|
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));
|
|
666
|
+
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
667
|
return this.and(eb, ...conditions);
|
|
649
668
|
}
|
|
650
669
|
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, [
|
|
670
|
+
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
671
|
"equals",
|
|
653
672
|
"not"
|
|
654
673
|
]);
|
|
655
674
|
return this.and(eb, ...conditions);
|
|
656
675
|
}
|
|
657
676
|
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);
|
|
677
|
+
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
678
|
return this.and(eb, ...conditions);
|
|
660
679
|
}
|
|
661
680
|
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, [
|
|
681
|
+
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
682
|
"equals",
|
|
664
683
|
"in",
|
|
665
684
|
"notIn",
|
|
@@ -697,9 +716,9 @@ var BaseCrudDialect = class {
|
|
|
697
716
|
"_min",
|
|
698
717
|
"_max"
|
|
699
718
|
].includes(field)) {
|
|
700
|
-
(0,
|
|
719
|
+
(0, import_common_helpers.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
701
720
|
for (const [k, v] of Object.entries(value)) {
|
|
702
|
-
(0,
|
|
721
|
+
(0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
703
722
|
result = result.orderBy((eb) => eb.fn(field.slice(1), [
|
|
704
723
|
import_kysely.sql.ref(k)
|
|
705
724
|
]), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
@@ -708,9 +727,9 @@ var BaseCrudDialect = class {
|
|
|
708
727
|
}
|
|
709
728
|
switch (field) {
|
|
710
729
|
case "_count": {
|
|
711
|
-
(0,
|
|
730
|
+
(0, import_common_helpers.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
|
|
712
731
|
for (const [k, v] of Object.entries(value)) {
|
|
713
|
-
(0,
|
|
732
|
+
(0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
714
733
|
result = result.orderBy((eb) => eb.fn.count(import_kysely.sql.ref(k)), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
715
734
|
}
|
|
716
735
|
continue;
|
|
@@ -732,7 +751,7 @@ var BaseCrudDialect = class {
|
|
|
732
751
|
throw new QueryError(`invalid orderBy value for field "${field}"`);
|
|
733
752
|
}
|
|
734
753
|
if ("_count" in value) {
|
|
735
|
-
(0,
|
|
754
|
+
(0, import_common_helpers.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
736
755
|
const sort = this.negateSort(value._count, negated);
|
|
737
756
|
result = result.orderBy((eb) => {
|
|
738
757
|
let subQuery = eb.selectFrom(relationModel);
|
|
@@ -758,10 +777,10 @@ var BaseCrudDialect = class {
|
|
|
758
777
|
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
759
778
|
}
|
|
760
779
|
true(eb) {
|
|
761
|
-
return eb.lit(this.transformPrimitive(true, "Boolean"));
|
|
780
|
+
return eb.lit(this.transformPrimitive(true, "Boolean", false));
|
|
762
781
|
}
|
|
763
782
|
false(eb) {
|
|
764
|
-
return eb.lit(this.transformPrimitive(false, "Boolean"));
|
|
783
|
+
return eb.lit(this.transformPrimitive(false, "Boolean", false));
|
|
765
784
|
}
|
|
766
785
|
isTrue(expression) {
|
|
767
786
|
const node = expression.toOperationNode();
|
|
@@ -810,14 +829,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
810
829
|
get provider() {
|
|
811
830
|
return "postgresql";
|
|
812
831
|
}
|
|
813
|
-
transformPrimitive(value, type) {
|
|
832
|
+
transformPrimitive(value, type, forArrayField) {
|
|
814
833
|
if (value === void 0) {
|
|
815
834
|
return value;
|
|
816
835
|
}
|
|
817
836
|
if (Array.isArray(value)) {
|
|
818
|
-
|
|
837
|
+
if (type === "Json" && !forArrayField) {
|
|
838
|
+
return JSON.stringify(value);
|
|
839
|
+
} else {
|
|
840
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
841
|
+
}
|
|
819
842
|
} else {
|
|
820
|
-
return (0, import_ts_pattern2.match)(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).otherwise(() => value);
|
|
843
|
+
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
844
|
}
|
|
822
845
|
}
|
|
823
846
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -850,8 +873,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
850
873
|
if (m2m) {
|
|
851
874
|
const parentIds = getIdFields(this.schema, model);
|
|
852
875
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
853
|
-
(0,
|
|
854
|
-
(0,
|
|
876
|
+
(0, import_common_helpers2.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
877
|
+
(0, import_common_helpers2.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
855
878
|
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentName}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
856
879
|
} else {
|
|
857
880
|
const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField, relationModel);
|
|
@@ -884,25 +907,33 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
884
907
|
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
885
908
|
]).flatMap((v) => v));
|
|
886
909
|
} 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
|
-
|
|
910
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => {
|
|
911
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
912
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentName}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
|
|
913
|
+
return [
|
|
914
|
+
import_kysely2.sql.lit(field),
|
|
915
|
+
fieldValue
|
|
916
|
+
];
|
|
917
|
+
}).flatMap((v) => v));
|
|
891
918
|
}
|
|
892
919
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
893
920
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
894
921
|
import_kysely2.sql.lit(field),
|
|
922
|
+
// reference the synthesized JSON field
|
|
895
923
|
eb.ref(`${parentName}$${relationField}$${field}.$j`)
|
|
896
924
|
]).flatMap((v) => v));
|
|
897
925
|
}
|
|
898
926
|
return objArgs;
|
|
899
927
|
}
|
|
900
|
-
buildRelationJoins(
|
|
928
|
+
buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
|
|
901
929
|
let result = qb;
|
|
902
|
-
if (typeof payload === "object"
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
930
|
+
if (typeof payload === "object") {
|
|
931
|
+
const selectInclude = payload.include ?? payload.select;
|
|
932
|
+
if (selectInclude && typeof selectInclude === "object") {
|
|
933
|
+
Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
|
|
934
|
+
result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
|
|
935
|
+
});
|
|
936
|
+
}
|
|
906
937
|
}
|
|
907
938
|
return result;
|
|
908
939
|
}
|
|
@@ -945,8 +976,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
945
976
|
};
|
|
946
977
|
|
|
947
978
|
// src/client/crud/dialects/sqlite.ts
|
|
979
|
+
var import_common_helpers3 = require("@zenstackhq/common-helpers");
|
|
948
980
|
var import_kysely3 = require("kysely");
|
|
949
|
-
var import_tiny_invariant3 = __toESM(require("tiny-invariant"), 1);
|
|
950
981
|
var import_ts_pattern3 = require("ts-pattern");
|
|
951
982
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
952
983
|
static {
|
|
@@ -955,14 +986,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
955
986
|
get provider() {
|
|
956
987
|
return "sqlite";
|
|
957
988
|
}
|
|
958
|
-
transformPrimitive(value, type) {
|
|
989
|
+
transformPrimitive(value, type, _forArrayField) {
|
|
959
990
|
if (value === void 0) {
|
|
960
991
|
return value;
|
|
961
992
|
}
|
|
962
993
|
if (Array.isArray(value)) {
|
|
963
|
-
return value.map((v) => this.transformPrimitive(v, type));
|
|
994
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
964
995
|
} 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);
|
|
996
|
+
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
997
|
}
|
|
967
998
|
}
|
|
968
999
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -993,8 +1024,8 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
993
1024
|
if (m2m) {
|
|
994
1025
|
const parentIds = getIdFields(this.schema, model);
|
|
995
1026
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
996
|
-
(0,
|
|
997
|
-
(0,
|
|
1027
|
+
(0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1028
|
+
(0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
998
1029
|
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentName}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
999
1030
|
} else {
|
|
1000
1031
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
@@ -1490,12 +1521,12 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1490
1521
|
};
|
|
1491
1522
|
|
|
1492
1523
|
// src/plugins/policy/expression-transformer.ts
|
|
1524
|
+
var import_common_helpers5 = require("@zenstackhq/common-helpers");
|
|
1493
1525
|
var import_kysely6 = require("kysely");
|
|
1494
|
-
var import_tiny_invariant5 = __toESM(require("tiny-invariant"), 1);
|
|
1495
1526
|
var import_ts_pattern6 = require("ts-pattern");
|
|
1496
1527
|
|
|
1497
1528
|
// src/plugins/policy/expression-evaluator.ts
|
|
1498
|
-
var
|
|
1529
|
+
var import_common_helpers4 = require("@zenstackhq/common-helpers");
|
|
1499
1530
|
var import_ts_pattern5 = require("ts-pattern");
|
|
1500
1531
|
var ExpressionEvaluator = class {
|
|
1501
1532
|
static {
|
|
@@ -1539,18 +1570,18 @@ var ExpressionEvaluator = class {
|
|
|
1539
1570
|
const right = this.evaluate(expr2.right, context);
|
|
1540
1571
|
return (0, import_ts_pattern5.match)(expr2.op).with("==", () => left === right).with("!=", () => left !== right).with(">", () => left > right).with(">=", () => left >= right).with("<", () => left < right).with("<=", () => left <= right).with("&&", () => left && right).with("||", () => left || right).with("in", () => {
|
|
1541
1572
|
const _right = right ?? [];
|
|
1542
|
-
(0,
|
|
1573
|
+
(0, import_common_helpers4.invariant)(Array.isArray(_right), 'expected array for "in" operator');
|
|
1543
1574
|
return _right.includes(left);
|
|
1544
1575
|
}).exhaustive();
|
|
1545
1576
|
}
|
|
1546
1577
|
evaluateCollectionPredicate(expr2, context) {
|
|
1547
1578
|
const op = expr2.op;
|
|
1548
|
-
(0,
|
|
1579
|
+
(0, import_common_helpers4.invariant)(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
|
|
1549
1580
|
const left = this.evaluate(expr2.left, context);
|
|
1550
1581
|
if (!left) {
|
|
1551
1582
|
return false;
|
|
1552
1583
|
}
|
|
1553
|
-
(0,
|
|
1584
|
+
(0, import_common_helpers4.invariant)(Array.isArray(left), "expected array");
|
|
1554
1585
|
return (0, import_ts_pattern5.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1555
1586
|
...context,
|
|
1556
1587
|
thisValue: item
|
|
@@ -1567,11 +1598,11 @@ var ExpressionEvaluator = class {
|
|
|
1567
1598
|
// src/plugins/policy/utils.ts
|
|
1568
1599
|
var import_kysely5 = require("kysely");
|
|
1569
1600
|
function trueNode(dialect) {
|
|
1570
|
-
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
|
|
1601
|
+
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1571
1602
|
}
|
|
1572
1603
|
__name(trueNode, "trueNode");
|
|
1573
1604
|
function falseNode(dialect) {
|
|
1574
|
-
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
|
|
1605
|
+
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1575
1606
|
}
|
|
1576
1607
|
__name(falseNode, "falseNode");
|
|
1577
1608
|
function isTrueNode(node) {
|
|
@@ -1772,20 +1803,20 @@ var ExpressionTransformer = class {
|
|
|
1772
1803
|
return import_kysely6.BinaryOperationNode.create(left, this.transformOperator(op), right);
|
|
1773
1804
|
}
|
|
1774
1805
|
transformCollectionPredicate(expr2, context) {
|
|
1775
|
-
(0,
|
|
1806
|
+
(0, import_common_helpers5.invariant)(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
|
|
1776
1807
|
if (this.isAuthCall(expr2.left) || this.isAuthMember(expr2.left)) {
|
|
1777
1808
|
const value = new ExpressionEvaluator().evaluate(expr2, {
|
|
1778
1809
|
auth: this.auth
|
|
1779
1810
|
});
|
|
1780
1811
|
return this.transformValue(value, "Boolean");
|
|
1781
1812
|
}
|
|
1782
|
-
(0,
|
|
1813
|
+
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
|
|
1783
1814
|
let newContextModel;
|
|
1784
1815
|
if (ExpressionUtils.isField(expr2.left)) {
|
|
1785
1816
|
const fieldDef = requireField(this.schema, context.model, expr2.left.field);
|
|
1786
1817
|
newContextModel = fieldDef.type;
|
|
1787
1818
|
} else {
|
|
1788
|
-
(0,
|
|
1819
|
+
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left.receiver));
|
|
1789
1820
|
const fieldDef = requireField(this.schema, context.model, expr2.left.receiver.field);
|
|
1790
1821
|
newContextModel = fieldDef.type;
|
|
1791
1822
|
for (const member of expr2.left.members) {
|
|
@@ -1829,10 +1860,10 @@ var ExpressionTransformer = class {
|
|
|
1829
1860
|
}
|
|
1830
1861
|
}
|
|
1831
1862
|
transformValue(value, type) {
|
|
1832
|
-
return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type) ?? null);
|
|
1863
|
+
return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
1833
1864
|
}
|
|
1834
1865
|
_unary(expr2, context) {
|
|
1835
|
-
(0,
|
|
1866
|
+
(0, import_common_helpers5.invariant)(expr2.op === "!", 'only "!" operator is supported');
|
|
1836
1867
|
return import_kysely6.BinaryOperationNode.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
|
|
1837
1868
|
}
|
|
1838
1869
|
transformOperator(op) {
|
|
@@ -1875,10 +1906,10 @@ var ExpressionTransformer = class {
|
|
|
1875
1906
|
if (this.isAuthCall(expr2.receiver)) {
|
|
1876
1907
|
return this.valueMemberAccess(this.auth, expr2, this.authType);
|
|
1877
1908
|
}
|
|
1878
|
-
(0,
|
|
1909
|
+
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.receiver), "expect receiver to be field expression");
|
|
1879
1910
|
const { memberFilter, memberSelect, ...restContext } = context;
|
|
1880
1911
|
const receiver = this.transform(expr2.receiver, restContext);
|
|
1881
|
-
(0,
|
|
1912
|
+
(0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(receiver), "expected receiver to be select query");
|
|
1882
1913
|
const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
|
|
1883
1914
|
const memberFields = [];
|
|
1884
1915
|
let currType = receiverField.type;
|
|
@@ -1902,7 +1933,7 @@ var ExpressionTransformer = class {
|
|
|
1902
1933
|
thisEntity: void 0
|
|
1903
1934
|
});
|
|
1904
1935
|
if (currNode) {
|
|
1905
|
-
(0,
|
|
1936
|
+
(0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(currNode), "expected select query node");
|
|
1906
1937
|
currNode = {
|
|
1907
1938
|
...relation,
|
|
1908
1939
|
selections: [
|
|
@@ -1919,8 +1950,8 @@ var ExpressionTransformer = class {
|
|
|
1919
1950
|
};
|
|
1920
1951
|
}
|
|
1921
1952
|
} else {
|
|
1922
|
-
(0,
|
|
1923
|
-
(0,
|
|
1953
|
+
(0, import_common_helpers5.invariant)(i === expr2.members.length - 1, "plain field access must be the last segment");
|
|
1954
|
+
(0, import_common_helpers5.invariant)(!currNode, "plain field access must be the last segment");
|
|
1924
1955
|
currNode = import_kysely6.ColumnNode.create(member);
|
|
1925
1956
|
}
|
|
1926
1957
|
}
|
|
@@ -2072,7 +2103,7 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2072
2103
|
get kysely() {
|
|
2073
2104
|
return this.client.$qb;
|
|
2074
2105
|
}
|
|
2075
|
-
async handle(node, proceed
|
|
2106
|
+
async handle(node, proceed) {
|
|
2076
2107
|
if (!this.isCrudQueryNode(node)) {
|
|
2077
2108
|
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
2078
2109
|
}
|
|
@@ -2092,27 +2123,20 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2092
2123
|
if (!mutationRequiresTransaction && !node.returning) {
|
|
2093
2124
|
return proceed(this.transformNode(node));
|
|
2094
2125
|
}
|
|
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;
|
|
2126
|
+
if (import_kysely7.InsertQueryNode.is(node)) {
|
|
2127
|
+
await this.enforcePreCreatePolicy(node, proceed);
|
|
2128
|
+
}
|
|
2129
|
+
const transformedNode = this.transformNode(node);
|
|
2130
|
+
const result = await proceed(transformedNode);
|
|
2131
|
+
if (!this.onlyReturningId(node)) {
|
|
2132
|
+
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2133
|
+
if (readBackResult.rows.length !== result.rows.length) {
|
|
2134
|
+
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
2110
2135
|
}
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2136
|
+
return readBackResult;
|
|
2137
|
+
} else {
|
|
2138
|
+
return result;
|
|
2114
2139
|
}
|
|
2115
|
-
return result;
|
|
2116
2140
|
}
|
|
2117
2141
|
onlyReturningId(node) {
|
|
2118
2142
|
if (!node.returning) {
|
|
@@ -2165,19 +2189,19 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2165
2189
|
}
|
|
2166
2190
|
}
|
|
2167
2191
|
unwrapCreateValueRow(data, model, fields) {
|
|
2168
|
-
(0,
|
|
2192
|
+
(0, import_common_helpers6.invariant)(data.length === fields.length, "data length must match fields length");
|
|
2169
2193
|
const result = [];
|
|
2170
2194
|
for (let i = 0; i < data.length; i++) {
|
|
2171
2195
|
const item = data[i];
|
|
2172
2196
|
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
2173
2197
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2174
|
-
(0,
|
|
2198
|
+
(0, import_common_helpers6.invariant)(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2175
2199
|
result.push({
|
|
2176
|
-
node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
|
|
2200
|
+
node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2177
2201
|
raw: item.value
|
|
2178
2202
|
});
|
|
2179
2203
|
} else {
|
|
2180
|
-
const value = this.dialect.transformPrimitive(item, fieldDef.type);
|
|
2204
|
+
const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
2181
2205
|
if (Array.isArray(value)) {
|
|
2182
2206
|
result.push({
|
|
2183
2207
|
node: import_kysely7.RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
@@ -2379,8 +2403,8 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2379
2403
|
const modelDef = requireModel(this.client.$schema, modelName);
|
|
2380
2404
|
const result = [];
|
|
2381
2405
|
const extractOperations = /* @__PURE__ */ __name((expr2) => {
|
|
2382
|
-
(0,
|
|
2383
|
-
(0,
|
|
2406
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isLiteral(expr2), "expecting a literal");
|
|
2407
|
+
(0, import_common_helpers6.invariant)(typeof expr2.value === "string", "expecting a string literal");
|
|
2384
2408
|
return expr2.value.split(",").filter((v) => !!v).map((v) => v.trim());
|
|
2385
2409
|
}, "extractOperations");
|
|
2386
2410
|
if (modelDef.attributes) {
|
|
@@ -2408,20 +2432,29 @@ var PolicyPlugin = class {
|
|
|
2408
2432
|
get description() {
|
|
2409
2433
|
return "Enforces access policies defined in the schema.";
|
|
2410
2434
|
}
|
|
2411
|
-
onKyselyQuery({
|
|
2435
|
+
onKyselyQuery({
|
|
2436
|
+
query,
|
|
2437
|
+
client,
|
|
2438
|
+
proceed
|
|
2439
|
+
/*, transaction*/
|
|
2440
|
+
}) {
|
|
2412
2441
|
const handler = new PolicyHandler(client);
|
|
2413
|
-
return handler.handle(
|
|
2442
|
+
return handler.handle(
|
|
2443
|
+
query,
|
|
2444
|
+
proceed
|
|
2445
|
+
/*, transaction*/
|
|
2446
|
+
);
|
|
2414
2447
|
}
|
|
2415
2448
|
};
|
|
2416
2449
|
|
|
2417
2450
|
// src/utils/clone.ts
|
|
2418
|
-
var
|
|
2451
|
+
var import_common_helpers7 = require("@zenstackhq/common-helpers");
|
|
2419
2452
|
function clone(value) {
|
|
2420
2453
|
if (Array.isArray(value)) {
|
|
2421
2454
|
return value.map((v) => clone(v));
|
|
2422
2455
|
}
|
|
2423
2456
|
if (typeof value === "object") {
|
|
2424
|
-
if (!value || !(0,
|
|
2457
|
+
if (!value || !(0, import_common_helpers7.isPlainObject)(value)) {
|
|
2425
2458
|
return value;
|
|
2426
2459
|
}
|
|
2427
2460
|
const result = {};
|
|
@@ -2531,13 +2564,13 @@ var BaseOperationHandler = class {
|
|
|
2531
2564
|
inMemoryDistinct = distinct;
|
|
2532
2565
|
}
|
|
2533
2566
|
}
|
|
2534
|
-
if (args
|
|
2535
|
-
query = this.buildFieldSelection(model, query, args
|
|
2567
|
+
if (args && "select" in args && args.select) {
|
|
2568
|
+
query = this.buildFieldSelection(model, query, args.select, model);
|
|
2536
2569
|
} else {
|
|
2537
2570
|
query = this.buildSelectAllScalarFields(model, query, args?.omit);
|
|
2538
2571
|
}
|
|
2539
|
-
if (args
|
|
2540
|
-
query = this.buildFieldSelection(model, query, args
|
|
2572
|
+
if (args && "include" in args && args.include) {
|
|
2573
|
+
query = this.buildFieldSelection(model, query, args.include, model);
|
|
2541
2574
|
}
|
|
2542
2575
|
if (args?.cursor) {
|
|
2543
2576
|
query = this.buildCursorFilter(model, query, args.cursor, args.orderBy, negateOrderBy);
|
|
@@ -2550,8 +2583,13 @@ var BaseOperationHandler = class {
|
|
|
2550
2583
|
try {
|
|
2551
2584
|
result = await query.execute();
|
|
2552
2585
|
} catch (err) {
|
|
2553
|
-
const { sql:
|
|
2554
|
-
|
|
2586
|
+
const { sql: sql11, parameters } = query.compile();
|
|
2587
|
+
let message = `Failed to execute query: ${err}, sql: ${sql11}`;
|
|
2588
|
+
if (this.options.debug) {
|
|
2589
|
+
message += `, parameters:
|
|
2590
|
+
${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
2591
|
+
}
|
|
2592
|
+
throw new QueryError(message, err);
|
|
2555
2593
|
}
|
|
2556
2594
|
if (inMemoryDistinct) {
|
|
2557
2595
|
const distinctResult = [];
|
|
@@ -2610,30 +2648,20 @@ var BaseOperationHandler = class {
|
|
|
2610
2648
|
for (const [field, value] of Object.entries(selections.select)) {
|
|
2611
2649
|
const fieldDef = requireField(this.schema, model, field);
|
|
2612
2650
|
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);
|
|
2651
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
2652
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
2653
|
+
for (const [left, right] of joinPairs) {
|
|
2654
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
2655
|
+
}
|
|
2656
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
2657
|
+
const filter = this.dialect.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
2658
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
2659
|
+
}
|
|
2660
|
+
jsonObject[field] = fieldCountQuery;
|
|
2629
2661
|
}
|
|
2630
2662
|
query = query.select((eb2) => this.dialect.buildJsonObject(eb2, jsonObject).as("_count"));
|
|
2631
2663
|
return query;
|
|
2632
2664
|
}
|
|
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
2665
|
buildSelectAllScalarFields(model, query, omit) {
|
|
2638
2666
|
const modelDef = this.requireModel(model);
|
|
2639
2667
|
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 +2727,14 @@ var BaseOperationHandler = class {
|
|
|
2699
2727
|
const fieldDef = this.requireField(model, field);
|
|
2700
2728
|
if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
|
|
2701
2729
|
if (fieldDef.array && value && typeof value === "object" && "set" in value && Array.isArray(value.set)) {
|
|
2702
|
-
createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type);
|
|
2730
|
+
createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type, true);
|
|
2703
2731
|
} else {
|
|
2704
|
-
createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type);
|
|
2732
|
+
createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
2705
2733
|
}
|
|
2706
2734
|
} else {
|
|
2707
2735
|
const subM2M = getManyToManyRelation(this.schema, model, field);
|
|
2708
2736
|
if (!subM2M && fieldDef.relation?.fields && fieldDef.relation?.references) {
|
|
2709
|
-
const fkValues = await this.
|
|
2737
|
+
const fkValues = await this.processOwnedRelationForCreate(kysely, fieldDef, value);
|
|
2710
2738
|
for (let i = 0; i < fieldDef.relation.fields.length; i++) {
|
|
2711
2739
|
createFields[fieldDef.relation.fields[i]] = fkValues[fieldDef.relation.references[i]];
|
|
2712
2740
|
}
|
|
@@ -2727,7 +2755,7 @@ var BaseOperationHandler = class {
|
|
|
2727
2755
|
const createdEntity = await query.executeTakeFirst();
|
|
2728
2756
|
if (Object.keys(postCreateRelations).length > 0) {
|
|
2729
2757
|
const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
|
|
2730
|
-
return this.
|
|
2758
|
+
return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
|
|
2731
2759
|
});
|
|
2732
2760
|
await Promise.all(relationPromises);
|
|
2733
2761
|
}
|
|
@@ -2741,8 +2769,8 @@ var BaseOperationHandler = class {
|
|
|
2741
2769
|
}
|
|
2742
2770
|
buildFkAssignments(model, relationField, entity) {
|
|
2743
2771
|
const parentFkFields = {};
|
|
2744
|
-
(0,
|
|
2745
|
-
(0,
|
|
2772
|
+
(0, import_common_helpers8.invariant)(relationField, "parentField must be defined if parentModel is defined");
|
|
2773
|
+
(0, import_common_helpers8.invariant)(entity, "parentEntity must be defined if parentModel is defined");
|
|
2746
2774
|
const { keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
2747
2775
|
for (const pair of keyPairs) {
|
|
2748
2776
|
if (!(pair.pk in entity)) {
|
|
@@ -2769,8 +2797,8 @@ var BaseOperationHandler = class {
|
|
|
2769
2797
|
].sort((a, b) => a.model.localeCompare(b.model));
|
|
2770
2798
|
const firstIds = getIdFields(this.schema, sortedRecords[0].model);
|
|
2771
2799
|
const secondIds = getIdFields(this.schema, sortedRecords[1].model);
|
|
2772
|
-
(0,
|
|
2773
|
-
(0,
|
|
2800
|
+
(0, import_common_helpers8.invariant)(firstIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
2801
|
+
(0, import_common_helpers8.invariant)(secondIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
2774
2802
|
if (action === "connect") {
|
|
2775
2803
|
const result = await kysely.insertInto(joinTable).values({
|
|
2776
2804
|
A: sortedRecords[0].entity[firstIds[0]],
|
|
@@ -2787,14 +2815,14 @@ var BaseOperationHandler = class {
|
|
|
2787
2815
|
}
|
|
2788
2816
|
}
|
|
2789
2817
|
resetManyToManyRelation(kysely, model, field, parentIds) {
|
|
2790
|
-
(0,
|
|
2818
|
+
(0, import_common_helpers8.invariant)(Object.keys(parentIds).length === 1, "parentIds must have exactly one field");
|
|
2791
2819
|
const parentId = Object.values(parentIds)[0];
|
|
2792
2820
|
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
2793
|
-
(0,
|
|
2821
|
+
(0, import_common_helpers8.invariant)(m2m, "not a many-to-many relation");
|
|
2794
2822
|
const eb = (0, import_kysely8.expressionBuilder)();
|
|
2795
2823
|
return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
|
|
2796
2824
|
}
|
|
2797
|
-
async
|
|
2825
|
+
async processOwnedRelationForCreate(kysely, relationField, payload) {
|
|
2798
2826
|
if (!payload) {
|
|
2799
2827
|
return;
|
|
2800
2828
|
}
|
|
@@ -2812,7 +2840,7 @@ var BaseOperationHandler = class {
|
|
|
2812
2840
|
}
|
|
2813
2841
|
case "connect": {
|
|
2814
2842
|
const referencedPkFields = relationField.relation.references;
|
|
2815
|
-
(0,
|
|
2843
|
+
(0, import_common_helpers8.invariant)(referencedPkFields, "relation must have fields info");
|
|
2816
2844
|
const extractedFks = extractFields(subPayload, referencedPkFields);
|
|
2817
2845
|
if (Object.keys(extractedFks).length === referencedPkFields.length) {
|
|
2818
2846
|
result = extractedFks;
|
|
@@ -2844,21 +2872,27 @@ var BaseOperationHandler = class {
|
|
|
2844
2872
|
}
|
|
2845
2873
|
return result;
|
|
2846
2874
|
}
|
|
2847
|
-
|
|
2875
|
+
processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
|
|
2848
2876
|
const relationFieldDef = this.requireField(contextModel, relationFieldName);
|
|
2849
2877
|
const relationModel = relationFieldDef.type;
|
|
2850
2878
|
const tasks = [];
|
|
2879
|
+
const fromRelationContext = {
|
|
2880
|
+
model: contextModel,
|
|
2881
|
+
field: relationFieldName,
|
|
2882
|
+
ids: parentEntity
|
|
2883
|
+
};
|
|
2851
2884
|
for (const [action, subPayload] of Object.entries(payload)) {
|
|
2852
2885
|
if (!subPayload) {
|
|
2853
2886
|
continue;
|
|
2854
2887
|
}
|
|
2855
2888
|
switch (action) {
|
|
2856
2889
|
case "create": {
|
|
2857
|
-
tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item,
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2890
|
+
tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, fromRelationContext)));
|
|
2891
|
+
break;
|
|
2892
|
+
}
|
|
2893
|
+
case "createMany": {
|
|
2894
|
+
(0, import_common_helpers8.invariant)(relationFieldDef.array, "relation must be an array for createMany");
|
|
2895
|
+
tasks.push(this.createMany(kysely, relationModel, subPayload, false, fromRelationContext));
|
|
2862
2896
|
break;
|
|
2863
2897
|
}
|
|
2864
2898
|
case "connect": {
|
|
@@ -2888,6 +2922,11 @@ var BaseOperationHandler = class {
|
|
|
2888
2922
|
return Promise.all(tasks);
|
|
2889
2923
|
}
|
|
2890
2924
|
async createMany(kysely, model, input, returnData, fromRelation) {
|
|
2925
|
+
if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
|
|
2926
|
+
return returnData ? [] : {
|
|
2927
|
+
count: 0
|
|
2928
|
+
};
|
|
2929
|
+
}
|
|
2891
2930
|
const modelDef = this.requireModel(model);
|
|
2892
2931
|
let relationKeyPairs = [];
|
|
2893
2932
|
if (fromRelation) {
|
|
@@ -2901,8 +2940,8 @@ var BaseOperationHandler = class {
|
|
|
2901
2940
|
const newItem = {};
|
|
2902
2941
|
for (const [name, value] of Object.entries(item)) {
|
|
2903
2942
|
const fieldDef = this.requireField(model, name);
|
|
2904
|
-
(0,
|
|
2905
|
-
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type);
|
|
2943
|
+
(0, import_common_helpers8.invariant)(!fieldDef.relation, "createMany does not support relations");
|
|
2944
|
+
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
2906
2945
|
}
|
|
2907
2946
|
if (fromRelation) {
|
|
2908
2947
|
for (const { fk, pk } of relationKeyPairs) {
|
|
@@ -2937,7 +2976,7 @@ var BaseOperationHandler = class {
|
|
|
2937
2976
|
values[field] = generated;
|
|
2938
2977
|
}
|
|
2939
2978
|
} else if (fields[field]?.updatedAt) {
|
|
2940
|
-
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
|
|
2979
|
+
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
2941
2980
|
}
|
|
2942
2981
|
}
|
|
2943
2982
|
}
|
|
@@ -2980,7 +3019,7 @@ var BaseOperationHandler = class {
|
|
|
2980
3019
|
}
|
|
2981
3020
|
} else {
|
|
2982
3021
|
const fromRelationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
2983
|
-
(0,
|
|
3022
|
+
(0, import_common_helpers8.invariant)(fromRelationFieldDef.relation?.opposite);
|
|
2984
3023
|
parentWhere[fromRelationFieldDef.relation.opposite] = {
|
|
2985
3024
|
some: fromRelation.ids
|
|
2986
3025
|
};
|
|
@@ -3002,7 +3041,7 @@ var BaseOperationHandler = class {
|
|
|
3002
3041
|
if (finalData === data) {
|
|
3003
3042
|
finalData = clone(data);
|
|
3004
3043
|
}
|
|
3005
|
-
finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
|
|
3044
|
+
finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
3006
3045
|
}
|
|
3007
3046
|
}
|
|
3008
3047
|
if (Object.keys(finalData).length === 0) {
|
|
@@ -3027,7 +3066,7 @@ var BaseOperationHandler = class {
|
|
|
3027
3066
|
updateFields[field] = this.transformScalarListUpdate(model, field, fieldDef, finalData[field]);
|
|
3028
3067
|
continue;
|
|
3029
3068
|
}
|
|
3030
|
-
updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type);
|
|
3069
|
+
updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type, !!fieldDef.array);
|
|
3031
3070
|
} else {
|
|
3032
3071
|
if (!allowRelationUpdate) {
|
|
3033
3072
|
throw new QueryError(`Relation update not allowed for field "${field}"`);
|
|
@@ -3070,9 +3109,9 @@ var BaseOperationHandler = class {
|
|
|
3070
3109
|
}
|
|
3071
3110
|
}
|
|
3072
3111
|
transformIncrementalUpdate(model, field, fieldDef, payload) {
|
|
3073
|
-
(0,
|
|
3112
|
+
(0, import_common_helpers8.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
|
|
3074
3113
|
const key = Object.keys(payload)[0];
|
|
3075
|
-
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
|
|
3114
|
+
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
|
|
3076
3115
|
const eb = (0, import_kysely8.expressionBuilder)();
|
|
3077
3116
|
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
|
|
3078
3117
|
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(() => {
|
|
@@ -3080,9 +3119,9 @@ var BaseOperationHandler = class {
|
|
|
3080
3119
|
});
|
|
3081
3120
|
}
|
|
3082
3121
|
transformScalarListUpdate(model, field, fieldDef, payload) {
|
|
3083
|
-
(0,
|
|
3122
|
+
(0, import_common_helpers8.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
|
|
3084
3123
|
const key = Object.keys(payload)[0];
|
|
3085
|
-
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
|
|
3124
|
+
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
|
|
3086
3125
|
const eb = (0, import_kysely8.expressionBuilder)();
|
|
3087
3126
|
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
|
|
3088
3127
|
return (0, import_ts_pattern8.match)(key).with("set", () => value).with("push", () => {
|
|
@@ -3112,7 +3151,7 @@ var BaseOperationHandler = class {
|
|
|
3112
3151
|
if (isRelationField(this.schema, model, field)) {
|
|
3113
3152
|
continue;
|
|
3114
3153
|
}
|
|
3115
|
-
updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type);
|
|
3154
|
+
updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
|
|
3116
3155
|
}
|
|
3117
3156
|
let query = kysely.updateTable(model).set(updateFields);
|
|
3118
3157
|
if (limit === void 0) {
|
|
@@ -3130,20 +3169,15 @@ var BaseOperationHandler = class {
|
|
|
3130
3169
|
model,
|
|
3131
3170
|
operation: "update"
|
|
3132
3171
|
}));
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
return result;
|
|
3143
|
-
}
|
|
3144
|
-
} catch (err) {
|
|
3145
|
-
const { sql: sql10, parameters } = query.compile();
|
|
3146
|
-
throw new QueryError(`Error during updateMany: ${err}, sql: ${sql10}, parameters: ${parameters}`);
|
|
3172
|
+
if (!returnData) {
|
|
3173
|
+
const result = await query.executeTakeFirstOrThrow();
|
|
3174
|
+
return {
|
|
3175
|
+
count: Number(result.numUpdatedRows)
|
|
3176
|
+
};
|
|
3177
|
+
} else {
|
|
3178
|
+
const idFields = getIdFields(this.schema, model);
|
|
3179
|
+
const result = await query.returning(idFields).execute();
|
|
3180
|
+
return result;
|
|
3147
3181
|
}
|
|
3148
3182
|
}
|
|
3149
3183
|
buildIdFieldRefs(kysely, model) {
|
|
@@ -3161,12 +3195,12 @@ var BaseOperationHandler = class {
|
|
|
3161
3195
|
for (const [key, value] of Object.entries(args)) {
|
|
3162
3196
|
switch (key) {
|
|
3163
3197
|
case "create": {
|
|
3164
|
-
(0,
|
|
3198
|
+
(0, import_common_helpers8.invariant)(!Array.isArray(value) || fieldDef.array, "relation must be an array if create is an array");
|
|
3165
3199
|
tasks.push(...enumerate(value).map((item) => this.create(kysely, fieldModel, item, fromRelationContext)));
|
|
3166
3200
|
break;
|
|
3167
3201
|
}
|
|
3168
3202
|
case "createMany": {
|
|
3169
|
-
(0,
|
|
3203
|
+
(0, import_common_helpers8.invariant)(fieldDef.array, "relation must be an array for createMany");
|
|
3170
3204
|
tasks.push(this.createMany(kysely, fieldModel, value, false, fromRelationContext));
|
|
3171
3205
|
break;
|
|
3172
3206
|
}
|
|
@@ -3183,7 +3217,7 @@ var BaseOperationHandler = class {
|
|
|
3183
3217
|
break;
|
|
3184
3218
|
}
|
|
3185
3219
|
case "set": {
|
|
3186
|
-
(0,
|
|
3220
|
+
(0, import_common_helpers8.invariant)(fieldDef.array, "relation must be an array");
|
|
3187
3221
|
tasks.push(this.setRelation(kysely, fieldModel, value, fromRelationContext));
|
|
3188
3222
|
break;
|
|
3189
3223
|
}
|
|
@@ -3252,7 +3286,7 @@ var BaseOperationHandler = class {
|
|
|
3252
3286
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3253
3287
|
let updateResult;
|
|
3254
3288
|
if (ownedByModel) {
|
|
3255
|
-
(0,
|
|
3289
|
+
(0, import_common_helpers8.invariant)(_data.length === 1, "only one entity can be connected");
|
|
3256
3290
|
const target = await this.readUnique(kysely, model, {
|
|
3257
3291
|
where: _data[0]
|
|
3258
3292
|
});
|
|
@@ -3342,7 +3376,7 @@ var BaseOperationHandler = class {
|
|
|
3342
3376
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3343
3377
|
const eb = (0, import_kysely8.expressionBuilder)();
|
|
3344
3378
|
if (ownedByModel) {
|
|
3345
|
-
(0,
|
|
3379
|
+
(0, import_common_helpers8.invariant)(disconnectConditions.length === 1, "only one entity can be disconnected");
|
|
3346
3380
|
const condition = disconnectConditions[0];
|
|
3347
3381
|
const query = kysely.updateTable(fromRelation.model).where(eb.and(fromRelation.ids)).$if(condition !== true, (qb) => qb.where(eb(
|
|
3348
3382
|
// @ts-ignore
|
|
@@ -3450,7 +3484,7 @@ var BaseOperationHandler = class {
|
|
|
3450
3484
|
const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
|
|
3451
3485
|
if (m2m) {
|
|
3452
3486
|
const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3453
|
-
(0,
|
|
3487
|
+
(0, import_common_helpers8.invariant)(fieldDef.relation?.opposite);
|
|
3454
3488
|
deleteResult = await this.delete(kysely, model, {
|
|
3455
3489
|
AND: [
|
|
3456
3490
|
{
|
|
@@ -3473,7 +3507,7 @@ var BaseOperationHandler = class {
|
|
|
3473
3507
|
throw new NotFoundError(model);
|
|
3474
3508
|
}
|
|
3475
3509
|
const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3476
|
-
(0,
|
|
3510
|
+
(0, import_common_helpers8.invariant)(fieldDef.relation?.opposite);
|
|
3477
3511
|
deleteResult = await this.delete(kysely, model, {
|
|
3478
3512
|
AND: [
|
|
3479
3513
|
// filter for parent
|
|
@@ -3543,7 +3577,7 @@ var BaseOperationHandler = class {
|
|
|
3543
3577
|
}, {});
|
|
3544
3578
|
}
|
|
3545
3579
|
trimResult(data, args) {
|
|
3546
|
-
if (!args.select) {
|
|
3580
|
+
if (!("select" in args) || !args.select) {
|
|
3547
3581
|
return data;
|
|
3548
3582
|
}
|
|
3549
3583
|
return Object.keys(args.select).reduce((acc, field) => {
|
|
@@ -3553,9 +3587,9 @@ var BaseOperationHandler = class {
|
|
|
3553
3587
|
}
|
|
3554
3588
|
needReturnRelations(model, args) {
|
|
3555
3589
|
let returnRelation = false;
|
|
3556
|
-
if (args.include) {
|
|
3590
|
+
if ("include" in args && args.include) {
|
|
3557
3591
|
returnRelation = Object.keys(args.include).length > 0;
|
|
3558
|
-
} else if (args.select) {
|
|
3592
|
+
} else if ("select" in args && args.select) {
|
|
3559
3593
|
returnRelation = Object.entries(args.select).some(([K, v]) => {
|
|
3560
3594
|
const fieldDef = this.requireField(model, K);
|
|
3561
3595
|
return fieldDef.relation && v;
|
|
@@ -3563,11 +3597,15 @@ var BaseOperationHandler = class {
|
|
|
3563
3597
|
}
|
|
3564
3598
|
return returnRelation;
|
|
3565
3599
|
}
|
|
3566
|
-
async safeTransaction(callback) {
|
|
3600
|
+
async safeTransaction(callback, isolationLevel) {
|
|
3567
3601
|
if (this.kysely.isTransaction) {
|
|
3568
3602
|
return callback(this.kysely);
|
|
3569
3603
|
} else {
|
|
3570
|
-
|
|
3604
|
+
let txBuilder = this.kysely.transaction();
|
|
3605
|
+
if (isolationLevel) {
|
|
3606
|
+
txBuilder = txBuilder.setIsolationLevel(isolationLevel);
|
|
3607
|
+
}
|
|
3608
|
+
return txBuilder.execute(callback);
|
|
3571
3609
|
}
|
|
3572
3610
|
}
|
|
3573
3611
|
// Given a unique filter of a model, return the entity ids by trying to
|
|
@@ -3586,6 +3624,28 @@ var BaseOperationHandler = class {
|
|
|
3586
3624
|
where: uniqueFilter
|
|
3587
3625
|
});
|
|
3588
3626
|
}
|
|
3627
|
+
/**
|
|
3628
|
+
* Normalize input args to strip `undefined` fields
|
|
3629
|
+
*/
|
|
3630
|
+
normalizeArgs(args) {
|
|
3631
|
+
if (!args) {
|
|
3632
|
+
return;
|
|
3633
|
+
}
|
|
3634
|
+
const newArgs = clone(args);
|
|
3635
|
+
this.doNormalizeArgs(newArgs);
|
|
3636
|
+
return newArgs;
|
|
3637
|
+
}
|
|
3638
|
+
doNormalizeArgs(args) {
|
|
3639
|
+
if (args && typeof args === "object") {
|
|
3640
|
+
for (const [key, value] of Object.entries(args)) {
|
|
3641
|
+
if (value === void 0) {
|
|
3642
|
+
delete args[key];
|
|
3643
|
+
} else if (value && (0, import_common_helpers8.isPlainObject)(value)) {
|
|
3644
|
+
this.doNormalizeArgs(value);
|
|
3645
|
+
}
|
|
3646
|
+
}
|
|
3647
|
+
}
|
|
3648
|
+
}
|
|
3589
3649
|
};
|
|
3590
3650
|
|
|
3591
3651
|
// src/client/crud/operations/aggregate.ts
|
|
@@ -3594,21 +3654,22 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3594
3654
|
__name(this, "AggregateOperationHandler");
|
|
3595
3655
|
}
|
|
3596
3656
|
async handle(_operation, args) {
|
|
3597
|
-
const
|
|
3657
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3658
|
+
const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
|
|
3598
3659
|
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 =
|
|
3660
|
+
let subQuery = eb.selectFrom(this.model).selectAll(this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
3661
|
+
const skip = parsedArgs?.skip;
|
|
3662
|
+
let take = parsedArgs?.take;
|
|
3602
3663
|
let negateOrderBy = false;
|
|
3603
3664
|
if (take !== void 0 && take < 0) {
|
|
3604
3665
|
negateOrderBy = true;
|
|
3605
3666
|
take = -take;
|
|
3606
3667
|
}
|
|
3607
3668
|
subQuery = this.dialect.buildSkipTake(subQuery, skip, take);
|
|
3608
|
-
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model,
|
|
3669
|
+
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, parsedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
3609
3670
|
return subQuery.as("$sub");
|
|
3610
3671
|
});
|
|
3611
|
-
for (const [key, value] of Object.entries(
|
|
3672
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3612
3673
|
switch (key) {
|
|
3613
3674
|
case "_count": {
|
|
3614
3675
|
if (value === true) {
|
|
@@ -3687,14 +3748,15 @@ var CountOperationHandler = class extends BaseOperationHandler {
|
|
|
3687
3748
|
__name(this, "CountOperationHandler");
|
|
3688
3749
|
}
|
|
3689
3750
|
async handle(_operation, args) {
|
|
3690
|
-
const
|
|
3751
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3752
|
+
const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
|
|
3691
3753
|
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,
|
|
3754
|
+
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
3755
|
+
subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
|
|
3694
3756
|
return subQuery.as("$sub");
|
|
3695
3757
|
});
|
|
3696
|
-
if (
|
|
3697
|
-
query = query.select((eb) => Object.keys(
|
|
3758
|
+
if (parsedArgs?.select && typeof parsedArgs.select === "object") {
|
|
3759
|
+
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
3760
|
return query.executeTakeFirstOrThrow();
|
|
3699
3761
|
} else {
|
|
3700
3762
|
query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
|
|
@@ -3711,10 +3773,11 @@ var CreateOperationHandler = class extends BaseOperationHandler {
|
|
|
3711
3773
|
__name(this, "CreateOperationHandler");
|
|
3712
3774
|
}
|
|
3713
3775
|
async handle(operation, args) {
|
|
3714
|
-
|
|
3715
|
-
|
|
3776
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3777
|
+
return (0, import_ts_pattern10.match)(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, normalizedArgs))).with("createMany", () => {
|
|
3778
|
+
return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, normalizedArgs));
|
|
3716
3779
|
}).with("createManyAndReturn", () => {
|
|
3717
|
-
return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model,
|
|
3780
|
+
return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, normalizedArgs));
|
|
3718
3781
|
}).exhaustive();
|
|
3719
3782
|
}
|
|
3720
3783
|
async runCreate(args) {
|
|
@@ -3764,7 +3827,8 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
|
3764
3827
|
__name(this, "DeleteOperationHandler");
|
|
3765
3828
|
}
|
|
3766
3829
|
async handle(operation, args) {
|
|
3767
|
-
|
|
3830
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3831
|
+
return (0, import_ts_pattern11.match)(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, normalizedArgs))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, normalizedArgs))).exhaustive();
|
|
3768
3832
|
}
|
|
3769
3833
|
async runDelete(args) {
|
|
3770
3834
|
const existing = await this.readUnique(this.kysely, this.model, {
|
|
@@ -3794,7 +3858,8 @@ var FindOperationHandler = class extends BaseOperationHandler {
|
|
|
3794
3858
|
__name(this, "FindOperationHandler");
|
|
3795
3859
|
}
|
|
3796
3860
|
async handle(operation, args, validateArgs = true) {
|
|
3797
|
-
const
|
|
3861
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3862
|
+
const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", normalizedArgs) : normalizedArgs;
|
|
3798
3863
|
const result = await this.read(this.client.$qb, this.model, parsedArgs);
|
|
3799
3864
|
const finalResult = operation === "findMany" ? result : result[0] ?? null;
|
|
3800
3865
|
return finalResult;
|
|
@@ -3804,16 +3869,17 @@ var FindOperationHandler = class extends BaseOperationHandler {
|
|
|
3804
3869
|
// src/client/crud/operations/group-by.ts
|
|
3805
3870
|
var import_kysely11 = require("kysely");
|
|
3806
3871
|
var import_ts_pattern12 = require("ts-pattern");
|
|
3807
|
-
var
|
|
3872
|
+
var GroupByOperationHandler = class extends BaseOperationHandler {
|
|
3808
3873
|
static {
|
|
3809
|
-
__name(this, "
|
|
3874
|
+
__name(this, "GroupByOperationHandler");
|
|
3810
3875
|
}
|
|
3811
3876
|
async handle(_operation, args) {
|
|
3812
|
-
const
|
|
3877
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3878
|
+
const parsedArgs = this.inputValidator.validateGroupByArgs(this.model, normalizedArgs);
|
|
3813
3879
|
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 =
|
|
3880
|
+
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
3881
|
+
const skip = parsedArgs?.skip;
|
|
3882
|
+
let take = parsedArgs?.take;
|
|
3817
3883
|
let negateOrderBy = false;
|
|
3818
3884
|
if (take !== void 0 && take < 0) {
|
|
3819
3885
|
negateOrderBy = true;
|
|
@@ -3823,20 +3889,20 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3823
3889
|
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
3824
3890
|
return subQuery.as("$sub");
|
|
3825
3891
|
});
|
|
3826
|
-
const bys = typeof
|
|
3827
|
-
|
|
3828
|
-
] :
|
|
3892
|
+
const bys = typeof parsedArgs.by === "string" ? [
|
|
3893
|
+
parsedArgs.by
|
|
3894
|
+
] : parsedArgs.by;
|
|
3829
3895
|
query = query.groupBy(bys);
|
|
3830
|
-
if (
|
|
3831
|
-
query = this.dialect.buildOrderBy(query, this.model, "$sub",
|
|
3896
|
+
if (parsedArgs.orderBy) {
|
|
3897
|
+
query = this.dialect.buildOrderBy(query, this.model, "$sub", parsedArgs.orderBy, false, false);
|
|
3832
3898
|
}
|
|
3833
|
-
if (
|
|
3834
|
-
query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub",
|
|
3899
|
+
if (parsedArgs.having) {
|
|
3900
|
+
query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub", parsedArgs.having));
|
|
3835
3901
|
}
|
|
3836
3902
|
for (const by of bys) {
|
|
3837
3903
|
query = query.select(() => import_kysely11.sql.ref(`$sub.${by}`).as(by));
|
|
3838
3904
|
}
|
|
3839
|
-
for (const [key, value] of Object.entries(
|
|
3905
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3840
3906
|
switch (key) {
|
|
3841
3907
|
case "_count": {
|
|
3842
3908
|
if (value === true) {
|
|
@@ -3919,7 +3985,8 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3919
3985
|
__name(this, "UpdateOperationHandler");
|
|
3920
3986
|
}
|
|
3921
3987
|
async handle(operation, args) {
|
|
3922
|
-
|
|
3988
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
3989
|
+
return (0, import_ts_pattern13.match)(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();
|
|
3923
3990
|
}
|
|
3924
3991
|
async runUpdate(args) {
|
|
3925
3992
|
const result = await this.safeTransaction(async (tx) => {
|
|
@@ -3975,6 +4042,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3975
4042
|
};
|
|
3976
4043
|
|
|
3977
4044
|
// src/client/crud/validator.ts
|
|
4045
|
+
var import_common_helpers9 = require("@zenstackhq/common-helpers");
|
|
3978
4046
|
var import_decimal = __toESM(require("decimal.js"), 1);
|
|
3979
4047
|
var import_json_stable_stringify = __toESM(require("json-stable-stringify"), 1);
|
|
3980
4048
|
var import_ts_pattern14 = require("ts-pattern");
|
|
@@ -3984,10 +4052,9 @@ var InputValidator = class {
|
|
|
3984
4052
|
__name(this, "InputValidator");
|
|
3985
4053
|
}
|
|
3986
4054
|
schema;
|
|
3987
|
-
schemaCache;
|
|
4055
|
+
schemaCache = /* @__PURE__ */ new Map();
|
|
3988
4056
|
constructor(schema) {
|
|
3989
4057
|
this.schema = schema;
|
|
3990
|
-
this.schemaCache = /* @__PURE__ */ new Map();
|
|
3991
4058
|
}
|
|
3992
4059
|
validateFindArgs(model, unique, args) {
|
|
3993
4060
|
return this.validate(model, "find", {
|
|
@@ -4044,7 +4111,7 @@ var InputValidator = class {
|
|
|
4044
4111
|
}
|
|
4045
4112
|
const { error } = schema.safeParse(args);
|
|
4046
4113
|
if (error) {
|
|
4047
|
-
throw new
|
|
4114
|
+
throw new InputValidationError(`Invalid ${operation} args: ${error.message}`, error);
|
|
4048
4115
|
}
|
|
4049
4116
|
return args;
|
|
4050
4117
|
}
|
|
@@ -4091,7 +4158,7 @@ var InputValidator = class {
|
|
|
4091
4158
|
makeWhereSchema(model, unique, withoutRelationFields = false) {
|
|
4092
4159
|
const modelDef = getModel(this.schema, model);
|
|
4093
4160
|
if (!modelDef) {
|
|
4094
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
4161
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
4095
4162
|
}
|
|
4096
4163
|
const fields = {};
|
|
4097
4164
|
for (const field of Object.keys(modelDef.fields)) {
|
|
@@ -4141,14 +4208,28 @@ var InputValidator = class {
|
|
|
4141
4208
|
const uniqueFields = getUniqueFields(this.schema, model);
|
|
4142
4209
|
for (const uniqueField of uniqueFields) {
|
|
4143
4210
|
if ("defs" in uniqueField) {
|
|
4144
|
-
fields[uniqueField.name] = import_zod.z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) =>
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4211
|
+
fields[uniqueField.name] = import_zod.z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
|
|
4212
|
+
(0, import_common_helpers9.invariant)(!def.relation, "unique field cannot be a relation");
|
|
4213
|
+
let fieldSchema;
|
|
4214
|
+
const enumDef = getEnum(this.schema, def.type);
|
|
4215
|
+
if (enumDef) {
|
|
4216
|
+
if (Object.keys(enumDef).length > 0) {
|
|
4217
|
+
fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional);
|
|
4218
|
+
} else {
|
|
4219
|
+
fieldSchema = import_zod.z.never();
|
|
4220
|
+
}
|
|
4221
|
+
} else {
|
|
4222
|
+
fieldSchema = this.makePrimitiveFilterSchema(def.type, !!def.optional);
|
|
4223
|
+
}
|
|
4224
|
+
return [
|
|
4225
|
+
key,
|
|
4226
|
+
fieldSchema
|
|
4227
|
+
];
|
|
4228
|
+
}))).optional();
|
|
4148
4229
|
}
|
|
4149
4230
|
}
|
|
4150
4231
|
}
|
|
4151
|
-
fields["$expr"] = import_zod.z.
|
|
4232
|
+
fields["$expr"] = import_zod.z.custom((v) => typeof v === "function").optional();
|
|
4152
4233
|
fields["AND"] = this.orArray(import_zod.z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
|
|
4153
4234
|
fields["OR"] = import_zod.z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)).array().optional();
|
|
4154
4235
|
fields["NOT"] = this.orArray(import_zod.z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
|
|
@@ -4194,7 +4275,7 @@ var InputValidator = class {
|
|
|
4194
4275
|
});
|
|
4195
4276
|
}
|
|
4196
4277
|
makePrimitiveFilterSchema(type, optional) {
|
|
4197
|
-
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();
|
|
4278
|
+
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_zod.z.any()).with("Unsupported", () => import_zod.z.never()).exhaustive();
|
|
4198
4279
|
}
|
|
4199
4280
|
makeDateTimeFilterSchema(optional) {
|
|
4200
4281
|
return this.makeCommonPrimitiveFilterSchema(import_zod.z.union([
|
|
@@ -4388,8 +4469,8 @@ var InputValidator = class {
|
|
|
4388
4469
|
return this.refineForSelectOmitMutuallyExclusive(result).optional();
|
|
4389
4470
|
}
|
|
4390
4471
|
makeCreateDataSchema(model, canBeArray, withoutFields = [], withoutRelationFields = false) {
|
|
4391
|
-
const
|
|
4392
|
-
const
|
|
4472
|
+
const uncheckedVariantFields = {};
|
|
4473
|
+
const checkedVariantFields = {};
|
|
4393
4474
|
const modelDef = requireModel(this.schema, model);
|
|
4394
4475
|
const hasRelation = !withoutRelationFields && Object.entries(modelDef.fields).some(([f, def]) => !withoutFields.includes(f) && def.relation);
|
|
4395
4476
|
Object.keys(modelDef.fields).forEach((field) => {
|
|
@@ -4431,7 +4512,10 @@ var InputValidator = class {
|
|
|
4431
4512
|
if (fieldDef.optional && !fieldDef.array) {
|
|
4432
4513
|
fieldSchema = fieldSchema.nullable();
|
|
4433
4514
|
}
|
|
4434
|
-
|
|
4515
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4516
|
+
if (fieldDef.array || !fieldDef.relation.references) {
|
|
4517
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4518
|
+
}
|
|
4435
4519
|
} else {
|
|
4436
4520
|
let fieldSchema = this.makePrimitiveSchema(fieldDef.type);
|
|
4437
4521
|
if (fieldDef.array) {
|
|
@@ -4448,23 +4532,23 @@ var InputValidator = class {
|
|
|
4448
4532
|
if (fieldDef.optional) {
|
|
4449
4533
|
fieldSchema = fieldSchema.nullable();
|
|
4450
4534
|
}
|
|
4451
|
-
|
|
4535
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4452
4536
|
if (!fieldDef.foreignKeyFor) {
|
|
4453
|
-
|
|
4537
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4454
4538
|
}
|
|
4455
4539
|
}
|
|
4456
4540
|
});
|
|
4457
4541
|
if (!hasRelation) {
|
|
4458
|
-
return this.orArray(import_zod.z.object(
|
|
4542
|
+
return this.orArray(import_zod.z.object(uncheckedVariantFields).strict(), canBeArray);
|
|
4459
4543
|
} else {
|
|
4460
4544
|
return import_zod.z.union([
|
|
4461
|
-
import_zod.z.object(
|
|
4462
|
-
import_zod.z.object(
|
|
4545
|
+
import_zod.z.object(uncheckedVariantFields).strict(),
|
|
4546
|
+
import_zod.z.object(checkedVariantFields).strict(),
|
|
4463
4547
|
...canBeArray ? [
|
|
4464
|
-
import_zod.z.array(import_zod.z.object(
|
|
4548
|
+
import_zod.z.array(import_zod.z.object(uncheckedVariantFields).strict())
|
|
4465
4549
|
] : [],
|
|
4466
4550
|
...canBeArray ? [
|
|
4467
|
-
import_zod.z.array(import_zod.z.object(
|
|
4551
|
+
import_zod.z.array(import_zod.z.object(checkedVariantFields).strict())
|
|
4468
4552
|
] : []
|
|
4469
4553
|
]);
|
|
4470
4554
|
}
|
|
@@ -4509,7 +4593,7 @@ var InputValidator = class {
|
|
|
4509
4593
|
fields["deleteMany"] = this.makeDeleteRelationDataSchema(fieldType, true, false).optional();
|
|
4510
4594
|
}
|
|
4511
4595
|
}
|
|
4512
|
-
return import_zod.z.object(fields).strict()
|
|
4596
|
+
return import_zod.z.object(fields).strict();
|
|
4513
4597
|
}
|
|
4514
4598
|
makeSetDataSchema(model, canBeArray) {
|
|
4515
4599
|
return this.orArray(this.makeWhereSchema(model, true), canBeArray);
|
|
@@ -4586,8 +4670,8 @@ var InputValidator = class {
|
|
|
4586
4670
|
return this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
4587
4671
|
}
|
|
4588
4672
|
makeUpdateDataSchema(model, withoutFields = [], withoutRelationFields = false) {
|
|
4589
|
-
const
|
|
4590
|
-
const
|
|
4673
|
+
const uncheckedVariantFields = {};
|
|
4674
|
+
const checkedVariantFields = {};
|
|
4591
4675
|
const modelDef = requireModel(this.schema, model);
|
|
4592
4676
|
const hasRelation = Object.entries(modelDef.fields).some(([key, value]) => value.relation && !withoutFields.includes(key));
|
|
4593
4677
|
Object.keys(modelDef.fields).forEach((field) => {
|
|
@@ -4612,7 +4696,10 @@ var InputValidator = class {
|
|
|
4612
4696
|
if (fieldDef.optional && !fieldDef.array) {
|
|
4613
4697
|
fieldSchema = fieldSchema.nullable();
|
|
4614
4698
|
}
|
|
4615
|
-
|
|
4699
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4700
|
+
if (fieldDef.array || !fieldDef.relation.references) {
|
|
4701
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4702
|
+
}
|
|
4616
4703
|
} else {
|
|
4617
4704
|
let fieldSchema = this.makePrimitiveSchema(fieldDef.type).optional();
|
|
4618
4705
|
if (this.isNumericField(fieldDef)) {
|
|
@@ -4639,18 +4726,18 @@ var InputValidator = class {
|
|
|
4639
4726
|
if (fieldDef.optional) {
|
|
4640
4727
|
fieldSchema = fieldSchema.nullable();
|
|
4641
4728
|
}
|
|
4642
|
-
|
|
4729
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4643
4730
|
if (!fieldDef.foreignKeyFor) {
|
|
4644
|
-
|
|
4731
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4645
4732
|
}
|
|
4646
4733
|
}
|
|
4647
4734
|
});
|
|
4648
4735
|
if (!hasRelation) {
|
|
4649
|
-
return import_zod.z.object(
|
|
4736
|
+
return import_zod.z.object(uncheckedVariantFields).strict();
|
|
4650
4737
|
} else {
|
|
4651
4738
|
return import_zod.z.union([
|
|
4652
|
-
import_zod.z.object(
|
|
4653
|
-
import_zod.z.object(
|
|
4739
|
+
import_zod.z.object(uncheckedVariantFields).strict(),
|
|
4740
|
+
import_zod.z.object(checkedVariantFields).strict()
|
|
4654
4741
|
]);
|
|
4655
4742
|
}
|
|
4656
4743
|
}
|
|
@@ -4946,6 +5033,7 @@ __name(performanceNow, "performanceNow");
|
|
|
4946
5033
|
// src/client/executor/zenstack-query-executor.ts
|
|
4947
5034
|
var import_kysely13 = require("kysely");
|
|
4948
5035
|
var import_nanoid2 = require("nanoid");
|
|
5036
|
+
var import_node_util2 = require("util");
|
|
4949
5037
|
var import_ts_pattern15 = require("ts-pattern");
|
|
4950
5038
|
|
|
4951
5039
|
// src/client/executor/name-mapper.ts
|
|
@@ -4955,11 +5043,11 @@ var QueryNameMapper = class extends import_kysely12.OperationNodeTransformer {
|
|
|
4955
5043
|
__name(this, "QueryNameMapper");
|
|
4956
5044
|
}
|
|
4957
5045
|
schema;
|
|
4958
|
-
modelToTableMap;
|
|
4959
|
-
fieldToColumnMap;
|
|
4960
|
-
modelStack;
|
|
5046
|
+
modelToTableMap = /* @__PURE__ */ new Map();
|
|
5047
|
+
fieldToColumnMap = /* @__PURE__ */ new Map();
|
|
5048
|
+
modelStack = [];
|
|
4961
5049
|
constructor(schema) {
|
|
4962
|
-
super(), this.schema = schema
|
|
5050
|
+
super(), this.schema = schema;
|
|
4963
5051
|
for (const [modelName, modelDef] of Object.entries(schema.models)) {
|
|
4964
5052
|
const mappedName = this.getMappedName(modelDef);
|
|
4965
5053
|
if (mappedName) {
|
|
@@ -5180,7 +5268,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5180
5268
|
mutationInterceptionInfo = await this.callMutationInterceptionFilters(queryNode);
|
|
5181
5269
|
}
|
|
5182
5270
|
const task = /* @__PURE__ */ __name(async () => {
|
|
5183
|
-
|
|
5271
|
+
if (this.isMutationNode(queryNode)) {
|
|
5272
|
+
await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
|
|
5273
|
+
}
|
|
5184
5274
|
const oldQueryNode = queryNode;
|
|
5185
5275
|
if ((import_kysely13.InsertQueryNode.is(queryNode) || import_kysely13.DeleteQueryNode.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
|
|
5186
5276
|
queryNode = {
|
|
@@ -5190,19 +5280,19 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5190
5280
|
])
|
|
5191
5281
|
};
|
|
5192
5282
|
}
|
|
5193
|
-
const
|
|
5194
|
-
await this.
|
|
5283
|
+
const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
|
|
5284
|
+
const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams, queryId);
|
|
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
|
-
proceedQueryWithKyselyInterceptors(queryNode, queryId) {
|
|
5202
|
-
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, queryId), "proceed");
|
|
5203
|
-
const makeTx = /* @__PURE__ */ __name((p) => (callback) => {
|
|
5204
|
-
return this.executeWithTransaction(() => callback(p));
|
|
5205
|
-
}, "makeTx");
|
|
5294
|
+
proceedQueryWithKyselyInterceptors(queryNode, parameters, queryId) {
|
|
5295
|
+
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters, queryId), "proceed");
|
|
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,20 +5302,30 @@ 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
|
}
|
|
5220
5309
|
return proceed(queryNode);
|
|
5221
5310
|
}
|
|
5222
|
-
async proceedQuery(query, queryId) {
|
|
5311
|
+
async proceedQuery(query, parameters, queryId) {
|
|
5223
5312
|
const finalQuery = this.nameMapper.transformNode(query);
|
|
5224
|
-
|
|
5313
|
+
let compiled = this.compileQuery(finalQuery);
|
|
5314
|
+
if (parameters) {
|
|
5315
|
+
compiled = {
|
|
5316
|
+
...compiled,
|
|
5317
|
+
parameters
|
|
5318
|
+
};
|
|
5319
|
+
}
|
|
5225
5320
|
try {
|
|
5226
|
-
return
|
|
5321
|
+
return await super.executeQuery(compiled, queryId);
|
|
5227
5322
|
} catch (err) {
|
|
5228
|
-
|
|
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);
|
|
5229
5329
|
}
|
|
5230
5330
|
}
|
|
5231
5331
|
isMutationNode(queryNode) {
|
|
@@ -5253,24 +5353,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5253
5353
|
return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, []);
|
|
5254
5354
|
}
|
|
5255
5355
|
withConnectionProvider(connectionProvider) {
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
if (!useTransaction || this.driver.txConnection) {
|
|
5260
|
-
return callback();
|
|
5261
|
-
} else {
|
|
5262
|
-
return this.provideConnection(async (connection) => {
|
|
5263
|
-
try {
|
|
5264
|
-
await this.driver.beginTransaction(connection, {});
|
|
5265
|
-
const result = await callback();
|
|
5266
|
-
await this.driver.commitTransaction(connection);
|
|
5267
|
-
return result;
|
|
5268
|
-
} catch (error) {
|
|
5269
|
-
await this.driver.rollbackTransaction(connection);
|
|
5270
|
-
throw error;
|
|
5271
|
-
}
|
|
5272
|
-
});
|
|
5273
|
-
}
|
|
5356
|
+
const newExecutor = new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
|
|
5357
|
+
newExecutor.client = this.client.withExecutor(newExecutor);
|
|
5358
|
+
return newExecutor;
|
|
5274
5359
|
}
|
|
5275
5360
|
get hasMutationHooks() {
|
|
5276
5361
|
return this.client.$options.plugins?.some((plugin) => plugin.beforeEntityMutation || plugin.afterEntityMutation);
|
|
@@ -5312,14 +5397,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5312
5397
|
queryNode
|
|
5313
5398
|
});
|
|
5314
5399
|
result.intercept ||= filterResult.intercept;
|
|
5315
|
-
result.useTransactionForMutation ||= filterResult.useTransactionForMutation;
|
|
5316
5400
|
result.loadBeforeMutationEntity ||= filterResult.loadBeforeMutationEntity;
|
|
5317
5401
|
result.loadAfterMutationEntity ||= filterResult.loadAfterMutationEntity;
|
|
5318
5402
|
}
|
|
5319
5403
|
}
|
|
5320
5404
|
let beforeMutationEntities;
|
|
5321
5405
|
if (result.loadBeforeMutationEntity && (import_kysely13.UpdateQueryNode.is(queryNode) || import_kysely13.DeleteQueryNode.is(queryNode))) {
|
|
5322
|
-
beforeMutationEntities = await this.loadEntities(
|
|
5406
|
+
beforeMutationEntities = await this.loadEntities(mutationModel, where);
|
|
5323
5407
|
}
|
|
5324
5408
|
return {
|
|
5325
5409
|
...result,
|
|
@@ -5332,15 +5416,14 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5332
5416
|
return void 0;
|
|
5333
5417
|
}
|
|
5334
5418
|
}
|
|
5335
|
-
callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
5419
|
+
async callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
5336
5420
|
if (!mutationInterceptionInfo?.intercept) {
|
|
5337
5421
|
return;
|
|
5338
5422
|
}
|
|
5339
5423
|
if (this.options.plugins) {
|
|
5340
5424
|
for (const plugin of this.options.plugins) {
|
|
5341
5425
|
if (plugin.beforeEntityMutation) {
|
|
5342
|
-
plugin.beforeEntityMutation({
|
|
5343
|
-
// context: this.queryContext,
|
|
5426
|
+
await plugin.beforeEntityMutation({
|
|
5344
5427
|
model: this.getMutationModel(queryNode),
|
|
5345
5428
|
action: mutationInterceptionInfo.action,
|
|
5346
5429
|
queryNode,
|
|
@@ -5361,12 +5444,12 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5361
5444
|
let afterMutationEntities = void 0;
|
|
5362
5445
|
if (mutationInterceptionInfo.loadAfterMutationEntity) {
|
|
5363
5446
|
if (import_kysely13.UpdateQueryNode.is(queryNode)) {
|
|
5364
|
-
afterMutationEntities = await this.loadEntities(
|
|
5447
|
+
afterMutationEntities = await this.loadEntities(mutationModel, mutationInterceptionInfo.where);
|
|
5365
5448
|
} else {
|
|
5366
5449
|
afterMutationEntities = queryResult.rows;
|
|
5367
5450
|
}
|
|
5368
5451
|
}
|
|
5369
|
-
plugin.afterEntityMutation({
|
|
5452
|
+
await plugin.afterEntityMutation({
|
|
5370
5453
|
model: this.getMutationModel(queryNode),
|
|
5371
5454
|
action: mutationInterceptionInfo.action,
|
|
5372
5455
|
queryNode,
|
|
@@ -5377,17 +5460,17 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5377
5460
|
}
|
|
5378
5461
|
}
|
|
5379
5462
|
}
|
|
5380
|
-
async loadEntities(
|
|
5381
|
-
const selectQuery = kysely.selectFrom(model).selectAll();
|
|
5463
|
+
async loadEntities(model, where) {
|
|
5464
|
+
const selectQuery = this.kysely.selectFrom(model).selectAll();
|
|
5382
5465
|
let selectQueryNode = selectQuery.toOperationNode();
|
|
5383
5466
|
selectQueryNode = {
|
|
5384
5467
|
...selectQueryNode,
|
|
5385
5468
|
where: this.andNodes(selectQueryNode.where, where)
|
|
5386
5469
|
};
|
|
5387
|
-
const compiled =
|
|
5470
|
+
const compiled = this.compileQuery(selectQueryNode);
|
|
5471
|
+
const result = await this.executeQuery(compiled, {
|
|
5388
5472
|
queryId: `zenstack-${(0, import_nanoid2.nanoid)()}`
|
|
5389
5473
|
});
|
|
5390
|
-
const result = await kysely.executeQuery(compiled);
|
|
5391
5474
|
return result.rows;
|
|
5392
5475
|
}
|
|
5393
5476
|
andNodes(condition1, condition2) {
|
|
@@ -5416,8 +5499,8 @@ __export(functions_exports, {
|
|
|
5416
5499
|
search: () => search,
|
|
5417
5500
|
startsWith: () => startsWith
|
|
5418
5501
|
});
|
|
5502
|
+
var import_common_helpers10 = require("@zenstackhq/common-helpers");
|
|
5419
5503
|
var import_kysely14 = require("kysely");
|
|
5420
|
-
var import_tiny_invariant8 = __toESM(require("tiny-invariant"), 1);
|
|
5421
5504
|
var import_ts_pattern16 = require("ts-pattern");
|
|
5422
5505
|
var contains = /* @__PURE__ */ __name((eb, args) => {
|
|
5423
5506
|
const [field, search2, caseInsensitive = false] = args;
|
|
@@ -5523,8 +5606,8 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
|
5523
5606
|
}, "currentOperation");
|
|
5524
5607
|
function processCasing(casing, result, model) {
|
|
5525
5608
|
const opNode = casing.toOperationNode();
|
|
5526
|
-
(0,
|
|
5527
|
-
result = (0, import_ts_pattern16.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () =>
|
|
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(() => {
|
|
5528
5611
|
throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
|
|
5529
5612
|
});
|
|
5530
5613
|
return result;
|
|
@@ -5532,8 +5615,8 @@ function processCasing(casing, result, model) {
|
|
|
5532
5615
|
__name(processCasing, "processCasing");
|
|
5533
5616
|
|
|
5534
5617
|
// src/client/helpers/schema-db-pusher.ts
|
|
5618
|
+
var import_common_helpers11 = require("@zenstackhq/common-helpers");
|
|
5535
5619
|
var import_kysely15 = require("kysely");
|
|
5536
|
-
var import_tiny_invariant9 = __toESM(require("tiny-invariant"), 1);
|
|
5537
5620
|
var import_ts_pattern17 = require("ts-pattern");
|
|
5538
5621
|
var SchemaDbPusher = class {
|
|
5539
5622
|
static {
|
|
@@ -5565,7 +5648,7 @@ var SchemaDbPusher = class {
|
|
|
5565
5648
|
for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
|
|
5566
5649
|
if (fieldDef.relation) {
|
|
5567
5650
|
table = this.addForeignKeyConstraint(table, model, fieldName, fieldDef);
|
|
5568
|
-
} else {
|
|
5651
|
+
} else if (!this.isComputedField(fieldDef)) {
|
|
5569
5652
|
table = this.createModelField(table, fieldName, fieldDef, modelDef);
|
|
5570
5653
|
}
|
|
5571
5654
|
}
|
|
@@ -5573,6 +5656,9 @@ var SchemaDbPusher = class {
|
|
|
5573
5656
|
table = this.addUniqueConstraint(table, modelDef);
|
|
5574
5657
|
return table;
|
|
5575
5658
|
}
|
|
5659
|
+
isComputedField(fieldDef) {
|
|
5660
|
+
return fieldDef.attributes?.some((a) => a.name === "@computed");
|
|
5661
|
+
}
|
|
5576
5662
|
addPrimaryKeyConstraint(table, model, modelDef) {
|
|
5577
5663
|
if (modelDef.idFields.length === 1) {
|
|
5578
5664
|
if (Object.values(modelDef.fields).some((f) => f.id)) {
|
|
@@ -5586,7 +5672,7 @@ var SchemaDbPusher = class {
|
|
|
5586
5672
|
}
|
|
5587
5673
|
addUniqueConstraint(table, modelDef) {
|
|
5588
5674
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
5589
|
-
(0,
|
|
5675
|
+
(0, import_common_helpers11.invariant)(typeof value === "object", "expecting an object");
|
|
5590
5676
|
if ("type" in value) {
|
|
5591
5677
|
const fieldDef = modelDef.fields[key];
|
|
5592
5678
|
if (fieldDef.unique) {
|
|
@@ -5632,7 +5718,7 @@ var SchemaDbPusher = class {
|
|
|
5632
5718
|
return "serial";
|
|
5633
5719
|
}
|
|
5634
5720
|
const type = fieldDef.type;
|
|
5635
|
-
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(() => {
|
|
5636
5722
|
throw new Error(`Unsupported field type: ${type}`);
|
|
5637
5723
|
});
|
|
5638
5724
|
if (fieldDef.array) {
|
|
@@ -5645,7 +5731,7 @@ var SchemaDbPusher = class {
|
|
|
5645
5731
|
return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
|
|
5646
5732
|
}
|
|
5647
5733
|
addForeignKeyConstraint(table, model, fieldName, fieldDef) {
|
|
5648
|
-
(0,
|
|
5734
|
+
(0, import_common_helpers11.invariant)(fieldDef.relation, "field must be a relation");
|
|
5649
5735
|
if (!fieldDef.relation.fields || !fieldDef.relation.references) {
|
|
5650
5736
|
return table;
|
|
5651
5737
|
}
|
|
@@ -5666,11 +5752,11 @@ var SchemaDbPusher = class {
|
|
|
5666
5752
|
};
|
|
5667
5753
|
|
|
5668
5754
|
// src/client/promise.ts
|
|
5669
|
-
function
|
|
5755
|
+
function createZenStackPromise(callback) {
|
|
5670
5756
|
let promise;
|
|
5671
|
-
const cb = /* @__PURE__ */ __name(() => {
|
|
5757
|
+
const cb = /* @__PURE__ */ __name((txClient) => {
|
|
5672
5758
|
try {
|
|
5673
|
-
return promise ??= valueToPromise(callback());
|
|
5759
|
+
return promise ??= valueToPromise(callback(txClient));
|
|
5674
5760
|
} catch (err) {
|
|
5675
5761
|
return Promise.reject(err);
|
|
5676
5762
|
}
|
|
@@ -5685,10 +5771,11 @@ function createDeferredPromise(callback) {
|
|
|
5685
5771
|
finally(onFinally) {
|
|
5686
5772
|
return cb().finally(onFinally);
|
|
5687
5773
|
},
|
|
5774
|
+
cb,
|
|
5688
5775
|
[Symbol.toStringTag]: "ZenStackPromise"
|
|
5689
5776
|
};
|
|
5690
5777
|
}
|
|
5691
|
-
__name(
|
|
5778
|
+
__name(createZenStackPromise, "createZenStackPromise");
|
|
5692
5779
|
function valueToPromise(thing) {
|
|
5693
5780
|
if (typeof thing === "object" && typeof thing?.then === "function") {
|
|
5694
5781
|
return thing;
|
|
@@ -5699,8 +5786,8 @@ function valueToPromise(thing) {
|
|
|
5699
5786
|
__name(valueToPromise, "valueToPromise");
|
|
5700
5787
|
|
|
5701
5788
|
// src/client/result-processor.ts
|
|
5789
|
+
var import_common_helpers12 = require("@zenstackhq/common-helpers");
|
|
5702
5790
|
var import_decimal2 = __toESM(require("decimal.js"), 1);
|
|
5703
|
-
var import_tiny_invariant10 = __toESM(require("tiny-invariant"), 1);
|
|
5704
5791
|
var import_ts_pattern18 = require("ts-pattern");
|
|
5705
5792
|
var ResultProcessor = class {
|
|
5706
5793
|
static {
|
|
@@ -5774,20 +5861,20 @@ var ResultProcessor = class {
|
|
|
5774
5861
|
return this.doProcessResult(relationData, fieldDef.type);
|
|
5775
5862
|
}
|
|
5776
5863
|
transformScalar(value, type) {
|
|
5777
|
-
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);
|
|
5778
5865
|
}
|
|
5779
5866
|
transformDecimal(value) {
|
|
5780
5867
|
if (value instanceof import_decimal2.default) {
|
|
5781
5868
|
return value;
|
|
5782
5869
|
}
|
|
5783
|
-
(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}`);
|
|
5784
5871
|
return new import_decimal2.default(value);
|
|
5785
5872
|
}
|
|
5786
5873
|
transformBigInt(value) {
|
|
5787
5874
|
if (typeof value === "bigint") {
|
|
5788
5875
|
return value;
|
|
5789
5876
|
}
|
|
5790
|
-
(0,
|
|
5877
|
+
(0, import_common_helpers12.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
5791
5878
|
return BigInt(value);
|
|
5792
5879
|
}
|
|
5793
5880
|
transformBoolean(value) {
|
|
@@ -5806,6 +5893,9 @@ var ResultProcessor = class {
|
|
|
5806
5893
|
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
5807
5894
|
}
|
|
5808
5895
|
fixReversedResult(data, model, args) {
|
|
5896
|
+
if (!data) {
|
|
5897
|
+
return;
|
|
5898
|
+
}
|
|
5809
5899
|
if (Array.isArray(data) && typeof args === "object" && args && args.take !== void 0 && args.take < 0) {
|
|
5810
5900
|
data.reverse();
|
|
5811
5901
|
}
|
|
@@ -5819,13 +5909,19 @@ var ResultProcessor = class {
|
|
|
5819
5909
|
continue;
|
|
5820
5910
|
}
|
|
5821
5911
|
const fieldDef = getField(this.schema, model, field);
|
|
5822
|
-
if (!fieldDef
|
|
5912
|
+
if (!fieldDef || !fieldDef.relation || !fieldDef.array) {
|
|
5823
5913
|
continue;
|
|
5824
5914
|
}
|
|
5825
5915
|
this.fixReversedResult(row[field], fieldDef.type, value);
|
|
5826
5916
|
}
|
|
5827
5917
|
}
|
|
5828
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
|
+
}
|
|
5829
5925
|
};
|
|
5830
5926
|
|
|
5831
5927
|
// src/client/client-impl.ts
|
|
@@ -5844,7 +5940,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
5844
5940
|
$schema;
|
|
5845
5941
|
kyselyProps;
|
|
5846
5942
|
auth;
|
|
5847
|
-
constructor(schema, options, baseClient) {
|
|
5943
|
+
constructor(schema, options, baseClient, executor) {
|
|
5848
5944
|
this.schema = schema;
|
|
5849
5945
|
this.options = options;
|
|
5850
5946
|
this.$schema = schema;
|
|
@@ -5856,16 +5952,16 @@ var ClientImpl = class _ClientImpl {
|
|
|
5856
5952
|
if (baseClient) {
|
|
5857
5953
|
this.kyselyProps = {
|
|
5858
5954
|
...baseClient.kyselyProps,
|
|
5859
|
-
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))
|
|
5860
5956
|
};
|
|
5861
5957
|
this.kyselyRaw = baseClient.kyselyRaw;
|
|
5958
|
+
this.auth = baseClient.auth;
|
|
5862
5959
|
} else {
|
|
5863
5960
|
const dialect = this.getKyselyDialect();
|
|
5864
5961
|
const driver = new ZenStackDriver(dialect.createDriver(), new import_kysely16.Log(this.$options.log ?? []));
|
|
5865
5962
|
const compiler = dialect.createQueryCompiler();
|
|
5866
5963
|
const adapter = dialect.createAdapter();
|
|
5867
5964
|
const connectionProvider = new import_kysely16.DefaultConnectionProvider(driver);
|
|
5868
|
-
const executor = new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider);
|
|
5869
5965
|
this.kyselyProps = {
|
|
5870
5966
|
config: {
|
|
5871
5967
|
dialect,
|
|
@@ -5873,7 +5969,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
5873
5969
|
},
|
|
5874
5970
|
dialect,
|
|
5875
5971
|
driver,
|
|
5876
|
-
executor
|
|
5972
|
+
executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
|
|
5877
5973
|
};
|
|
5878
5974
|
this.kyselyRaw = new import_kysely16.Kysely({
|
|
5879
5975
|
...this.kyselyProps,
|
|
@@ -5889,31 +5985,67 @@ var ClientImpl = class _ClientImpl {
|
|
|
5889
5985
|
get $qbRaw() {
|
|
5890
5986
|
return this.kyselyRaw;
|
|
5891
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
|
+
}
|
|
5892
5997
|
getKyselyDialect() {
|
|
5893
5998
|
return (0, import_ts_pattern19.match)(this.schema.provider.type).with("sqlite", () => this.makeSqliteKyselyDialect()).with("postgresql", () => this.makePostgresKyselyDialect()).exhaustive();
|
|
5894
5999
|
}
|
|
5895
6000
|
makePostgresKyselyDialect() {
|
|
5896
|
-
|
|
5897
|
-
const mergedConfig = {
|
|
5898
|
-
...dialectConfigProvider(),
|
|
5899
|
-
...this.options?.dialectConfig
|
|
5900
|
-
};
|
|
5901
|
-
return new import_kysely16.PostgresDialect(mergedConfig);
|
|
6001
|
+
return new import_kysely16.PostgresDialect(this.options.dialectConfig);
|
|
5902
6002
|
}
|
|
5903
6003
|
makeSqliteKyselyDialect() {
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
6004
|
+
return new import_kysely16.SqliteDialect(this.options.dialectConfig);
|
|
6005
|
+
}
|
|
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
|
+
}
|
|
5910
6014
|
}
|
|
5911
|
-
async
|
|
5912
|
-
|
|
5913
|
-
|
|
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);
|
|
5914
6033
|
txClient.kysely = tx;
|
|
5915
|
-
|
|
5916
|
-
|
|
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
|
+
}
|
|
5917
6049
|
}
|
|
5918
6050
|
get $procedures() {
|
|
5919
6051
|
return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
|
|
@@ -5944,12 +6076,19 @@ var ClientImpl = class _ClientImpl {
|
|
|
5944
6076
|
const newOptions = {
|
|
5945
6077
|
...this.options,
|
|
5946
6078
|
plugins: [
|
|
5947
|
-
...this.options
|
|
6079
|
+
...this.options.plugins ?? [],
|
|
5948
6080
|
plugin
|
|
5949
6081
|
]
|
|
5950
6082
|
};
|
|
5951
6083
|
return new _ClientImpl(this.schema, newOptions, this);
|
|
5952
6084
|
}
|
|
6085
|
+
$unuse(pluginId) {
|
|
6086
|
+
const newOptions = {
|
|
6087
|
+
...this.options,
|
|
6088
|
+
plugins: this.options.plugins?.filter((p) => p.id !== pluginId)
|
|
6089
|
+
};
|
|
6090
|
+
return new _ClientImpl(this.schema, newOptions, this);
|
|
6091
|
+
}
|
|
5953
6092
|
$unuseAll() {
|
|
5954
6093
|
const newOptions = {
|
|
5955
6094
|
...this.options,
|
|
@@ -5968,6 +6107,39 @@ var ClientImpl = class _ClientImpl {
|
|
|
5968
6107
|
get $auth() {
|
|
5969
6108
|
return this.auth;
|
|
5970
6109
|
}
|
|
6110
|
+
$executeRaw(query, ...values) {
|
|
6111
|
+
return createZenStackPromise(async () => {
|
|
6112
|
+
const result = await (0, import_kysely16.sql)(query, ...values).execute(this.kysely);
|
|
6113
|
+
return Number(result.numAffectedRows ?? 0);
|
|
6114
|
+
});
|
|
6115
|
+
}
|
|
6116
|
+
$executeRawUnsafe(query, ...values) {
|
|
6117
|
+
return createZenStackPromise(async () => {
|
|
6118
|
+
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
6119
|
+
const result = await this.kysely.executeQuery(compiledQuery);
|
|
6120
|
+
return Number(result.numAffectedRows ?? 0);
|
|
6121
|
+
});
|
|
6122
|
+
}
|
|
6123
|
+
$queryRaw(query, ...values) {
|
|
6124
|
+
return createZenStackPromise(async () => {
|
|
6125
|
+
const result = await (0, import_kysely16.sql)(query, ...values).execute(this.kysely);
|
|
6126
|
+
return result.rows;
|
|
6127
|
+
});
|
|
6128
|
+
}
|
|
6129
|
+
$queryRawUnsafe(query, ...values) {
|
|
6130
|
+
return createZenStackPromise(async () => {
|
|
6131
|
+
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
6132
|
+
const result = await this.kysely.executeQuery(compiledQuery);
|
|
6133
|
+
return result.rows;
|
|
6134
|
+
});
|
|
6135
|
+
}
|
|
6136
|
+
createRawCompiledQuery(query, values) {
|
|
6137
|
+
const q = import_kysely16.CompiledQuery.raw(query, values);
|
|
6138
|
+
return {
|
|
6139
|
+
...q,
|
|
6140
|
+
$raw: true
|
|
6141
|
+
};
|
|
6142
|
+
}
|
|
5971
6143
|
};
|
|
5972
6144
|
function createClientProxy(client) {
|
|
5973
6145
|
const inputValidator = new InputValidator(client.$schema);
|
|
@@ -5990,9 +6162,9 @@ function createClientProxy(client) {
|
|
|
5990
6162
|
__name(createClientProxy, "createClientProxy");
|
|
5991
6163
|
function createModelCrudHandler(client, model, inputValidator, resultProcessor) {
|
|
5992
6164
|
const createPromise = /* @__PURE__ */ __name((operation, args, handler, postProcess = false, throwIfNoResult = false) => {
|
|
5993
|
-
return
|
|
5994
|
-
let proceed = /* @__PURE__ */ __name(async (_args
|
|
5995
|
-
const _handler =
|
|
6165
|
+
return createZenStackPromise(async (txClient) => {
|
|
6166
|
+
let proceed = /* @__PURE__ */ __name(async (_args) => {
|
|
6167
|
+
const _handler = txClient ? handler.withClient(txClient) : handler;
|
|
5996
6168
|
const r = await _handler.handle(operation, _args ?? args);
|
|
5997
6169
|
if (!r && throwIfNoResult) {
|
|
5998
6170
|
throw new NotFoundError(model);
|
|
@@ -6005,22 +6177,31 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
6005
6177
|
}
|
|
6006
6178
|
return result;
|
|
6007
6179
|
}, "proceed");
|
|
6008
|
-
const context = {
|
|
6009
|
-
client,
|
|
6010
|
-
model,
|
|
6011
|
-
operation,
|
|
6012
|
-
queryArgs: args
|
|
6013
|
-
};
|
|
6014
6180
|
const plugins = [
|
|
6015
6181
|
...client.$options.plugins ?? []
|
|
6016
6182
|
];
|
|
6017
6183
|
for (const plugin of plugins) {
|
|
6018
|
-
if (plugin.onQuery) {
|
|
6019
|
-
const
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6184
|
+
if (plugin.onQuery && typeof plugin.onQuery === "object") {
|
|
6185
|
+
for (const [_model, modelHooks] of Object.entries(plugin.onQuery)) {
|
|
6186
|
+
if (_model === (0, import_common_helpers13.lowerCaseFirst)(model) || _model === "$allModels") {
|
|
6187
|
+
if (modelHooks && typeof modelHooks === "object") {
|
|
6188
|
+
for (const [op, opHooks] of Object.entries(modelHooks)) {
|
|
6189
|
+
if (op === operation || op === "$allOperations") {
|
|
6190
|
+
if (typeof opHooks === "function") {
|
|
6191
|
+
const _proceed = proceed;
|
|
6192
|
+
proceed = /* @__PURE__ */ __name(() => opHooks({
|
|
6193
|
+
client,
|
|
6194
|
+
model,
|
|
6195
|
+
operation,
|
|
6196
|
+
args,
|
|
6197
|
+
query: _proceed
|
|
6198
|
+
}), "proceed");
|
|
6199
|
+
}
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
6202
|
+
}
|
|
6203
|
+
}
|
|
6204
|
+
}
|
|
6024
6205
|
}
|
|
6025
6206
|
}
|
|
6026
6207
|
return proceed(args);
|
|
@@ -6076,13 +6257,24 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
6076
6257
|
return createPromise("aggregate", args, new AggregateOperationHandler(client, model, inputValidator), false);
|
|
6077
6258
|
}, "aggregate"),
|
|
6078
6259
|
groupBy: /* @__PURE__ */ __name((args) => {
|
|
6079
|
-
return createPromise("groupBy", args, new
|
|
6260
|
+
return createPromise("groupBy", args, new GroupByOperationHandler(client, model, inputValidator));
|
|
6080
6261
|
}, "groupBy")
|
|
6081
6262
|
};
|
|
6082
6263
|
}
|
|
6083
6264
|
__name(createModelCrudHandler, "createModelCrudHandler");
|
|
6265
|
+
|
|
6266
|
+
// src/client/plugin.ts
|
|
6267
|
+
function definePlugin(plugin) {
|
|
6268
|
+
return plugin;
|
|
6269
|
+
}
|
|
6270
|
+
__name(definePlugin, "definePlugin");
|
|
6084
6271
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6085
6272
|
0 && (module.exports = {
|
|
6086
|
-
|
|
6273
|
+
InputValidationError,
|
|
6274
|
+
InternalError,
|
|
6275
|
+
NotFoundError,
|
|
6276
|
+
QueryError,
|
|
6277
|
+
ZenStackClient,
|
|
6278
|
+
definePlugin
|
|
6087
6279
|
});
|
|
6088
6280
|
//# sourceMappingURL=index.cjs.map
|