@zenstackhq/runtime 3.0.0-alpha.0 → 3.0.0-alpha.10
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-BiU0iYAh.d.cts} +813 -709
- package/dist/{contract-DguafRNB.d.ts → contract-BiU0iYAh.d.ts} +813 -709
- 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 +517 -328
- 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 +466 -282
- 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 = {};
|
|
@@ -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
|
|
@@ -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 normalizeArgs = this.normalizeArgs(args);
|
|
3862
|
+
const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", normalizeArgs) : normalizeArgs;
|
|
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);
|
|
@@ -4946,6 +5030,7 @@ __name(performanceNow, "performanceNow");
|
|
|
4946
5030
|
// src/client/executor/zenstack-query-executor.ts
|
|
4947
5031
|
var import_kysely13 = require("kysely");
|
|
4948
5032
|
var import_nanoid2 = require("nanoid");
|
|
5033
|
+
var import_node_util2 = require("util");
|
|
4949
5034
|
var import_ts_pattern15 = require("ts-pattern");
|
|
4950
5035
|
|
|
4951
5036
|
// src/client/executor/name-mapper.ts
|
|
@@ -4955,11 +5040,11 @@ var QueryNameMapper = class extends import_kysely12.OperationNodeTransformer {
|
|
|
4955
5040
|
__name(this, "QueryNameMapper");
|
|
4956
5041
|
}
|
|
4957
5042
|
schema;
|
|
4958
|
-
modelToTableMap;
|
|
4959
|
-
fieldToColumnMap;
|
|
4960
|
-
modelStack;
|
|
5043
|
+
modelToTableMap = /* @__PURE__ */ new Map();
|
|
5044
|
+
fieldToColumnMap = /* @__PURE__ */ new Map();
|
|
5045
|
+
modelStack = [];
|
|
4961
5046
|
constructor(schema) {
|
|
4962
|
-
super(), this.schema = schema
|
|
5047
|
+
super(), this.schema = schema;
|
|
4963
5048
|
for (const [modelName, modelDef] of Object.entries(schema.models)) {
|
|
4964
5049
|
const mappedName = this.getMappedName(modelDef);
|
|
4965
5050
|
if (mappedName) {
|
|
@@ -5180,7 +5265,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5180
5265
|
mutationInterceptionInfo = await this.callMutationInterceptionFilters(queryNode);
|
|
5181
5266
|
}
|
|
5182
5267
|
const task = /* @__PURE__ */ __name(async () => {
|
|
5183
|
-
|
|
5268
|
+
if (this.isMutationNode(queryNode)) {
|
|
5269
|
+
await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
|
|
5270
|
+
}
|
|
5184
5271
|
const oldQueryNode = queryNode;
|
|
5185
5272
|
if ((import_kysely13.InsertQueryNode.is(queryNode) || import_kysely13.DeleteQueryNode.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
|
|
5186
5273
|
queryNode = {
|
|
@@ -5190,19 +5277,19 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5190
5277
|
])
|
|
5191
5278
|
};
|
|
5192
5279
|
}
|
|
5193
|
-
const
|
|
5194
|
-
await this.
|
|
5280
|
+
const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
|
|
5281
|
+
const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams, queryId);
|
|
5282
|
+
if (this.isMutationNode(queryNode)) {
|
|
5283
|
+
await this.callAfterQueryInterceptionFilters(result, queryNode, mutationInterceptionInfo);
|
|
5284
|
+
}
|
|
5195
5285
|
if (oldQueryNode !== queryNode) {
|
|
5196
5286
|
}
|
|
5197
5287
|
return result;
|
|
5198
5288
|
}, "task");
|
|
5199
|
-
return
|
|
5289
|
+
return task();
|
|
5200
5290
|
}
|
|
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");
|
|
5291
|
+
proceedQueryWithKyselyInterceptors(queryNode, parameters, queryId) {
|
|
5292
|
+
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters, queryId), "proceed");
|
|
5206
5293
|
const hooks = this.options.plugins?.filter((plugin) => typeof plugin.onKyselyQuery === "function").map((plugin) => plugin.onKyselyQuery.bind(plugin)) ?? [];
|
|
5207
5294
|
for (const hook of hooks) {
|
|
5208
5295
|
const _proceed = proceed;
|
|
@@ -5212,20 +5299,30 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5212
5299
|
schema: this.client.$schema,
|
|
5213
5300
|
kysely: this.kysely,
|
|
5214
5301
|
query,
|
|
5215
|
-
proceed: _proceed
|
|
5216
|
-
transaction: makeTx(_proceed)
|
|
5302
|
+
proceed: _proceed
|
|
5217
5303
|
});
|
|
5218
5304
|
}, "proceed");
|
|
5219
5305
|
}
|
|
5220
5306
|
return proceed(queryNode);
|
|
5221
5307
|
}
|
|
5222
|
-
async proceedQuery(query, queryId) {
|
|
5308
|
+
async proceedQuery(query, parameters, queryId) {
|
|
5223
5309
|
const finalQuery = this.nameMapper.transformNode(query);
|
|
5224
|
-
|
|
5310
|
+
let compiled = this.compileQuery(finalQuery);
|
|
5311
|
+
if (parameters) {
|
|
5312
|
+
compiled = {
|
|
5313
|
+
...compiled,
|
|
5314
|
+
parameters
|
|
5315
|
+
};
|
|
5316
|
+
}
|
|
5225
5317
|
try {
|
|
5226
|
-
return
|
|
5318
|
+
return await super.executeQuery(compiled, queryId);
|
|
5227
5319
|
} catch (err) {
|
|
5228
|
-
|
|
5320
|
+
let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
|
|
5321
|
+
if (this.options.debug) {
|
|
5322
|
+
message += `, parameters:
|
|
5323
|
+
${compiled.parameters.map((p) => (0, import_node_util2.inspect)(p)).join("\n")}`;
|
|
5324
|
+
}
|
|
5325
|
+
throw new QueryError(message, err);
|
|
5229
5326
|
}
|
|
5230
5327
|
}
|
|
5231
5328
|
isMutationNode(queryNode) {
|
|
@@ -5253,24 +5350,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5253
5350
|
return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, []);
|
|
5254
5351
|
}
|
|
5255
5352
|
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
|
-
}
|
|
5353
|
+
const newExecutor = new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
|
|
5354
|
+
newExecutor.client = this.client.withExecutor(newExecutor);
|
|
5355
|
+
return newExecutor;
|
|
5274
5356
|
}
|
|
5275
5357
|
get hasMutationHooks() {
|
|
5276
5358
|
return this.client.$options.plugins?.some((plugin) => plugin.beforeEntityMutation || plugin.afterEntityMutation);
|
|
@@ -5312,14 +5394,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5312
5394
|
queryNode
|
|
5313
5395
|
});
|
|
5314
5396
|
result.intercept ||= filterResult.intercept;
|
|
5315
|
-
result.useTransactionForMutation ||= filterResult.useTransactionForMutation;
|
|
5316
5397
|
result.loadBeforeMutationEntity ||= filterResult.loadBeforeMutationEntity;
|
|
5317
5398
|
result.loadAfterMutationEntity ||= filterResult.loadAfterMutationEntity;
|
|
5318
5399
|
}
|
|
5319
5400
|
}
|
|
5320
5401
|
let beforeMutationEntities;
|
|
5321
5402
|
if (result.loadBeforeMutationEntity && (import_kysely13.UpdateQueryNode.is(queryNode) || import_kysely13.DeleteQueryNode.is(queryNode))) {
|
|
5322
|
-
beforeMutationEntities = await this.loadEntities(
|
|
5403
|
+
beforeMutationEntities = await this.loadEntities(mutationModel, where);
|
|
5323
5404
|
}
|
|
5324
5405
|
return {
|
|
5325
5406
|
...result,
|
|
@@ -5332,15 +5413,14 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5332
5413
|
return void 0;
|
|
5333
5414
|
}
|
|
5334
5415
|
}
|
|
5335
|
-
callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
5416
|
+
async callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
5336
5417
|
if (!mutationInterceptionInfo?.intercept) {
|
|
5337
5418
|
return;
|
|
5338
5419
|
}
|
|
5339
5420
|
if (this.options.plugins) {
|
|
5340
5421
|
for (const plugin of this.options.plugins) {
|
|
5341
5422
|
if (plugin.beforeEntityMutation) {
|
|
5342
|
-
plugin.beforeEntityMutation({
|
|
5343
|
-
// context: this.queryContext,
|
|
5423
|
+
await plugin.beforeEntityMutation({
|
|
5344
5424
|
model: this.getMutationModel(queryNode),
|
|
5345
5425
|
action: mutationInterceptionInfo.action,
|
|
5346
5426
|
queryNode,
|
|
@@ -5361,12 +5441,12 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5361
5441
|
let afterMutationEntities = void 0;
|
|
5362
5442
|
if (mutationInterceptionInfo.loadAfterMutationEntity) {
|
|
5363
5443
|
if (import_kysely13.UpdateQueryNode.is(queryNode)) {
|
|
5364
|
-
afterMutationEntities = await this.loadEntities(
|
|
5444
|
+
afterMutationEntities = await this.loadEntities(mutationModel, mutationInterceptionInfo.where);
|
|
5365
5445
|
} else {
|
|
5366
5446
|
afterMutationEntities = queryResult.rows;
|
|
5367
5447
|
}
|
|
5368
5448
|
}
|
|
5369
|
-
plugin.afterEntityMutation({
|
|
5449
|
+
await plugin.afterEntityMutation({
|
|
5370
5450
|
model: this.getMutationModel(queryNode),
|
|
5371
5451
|
action: mutationInterceptionInfo.action,
|
|
5372
5452
|
queryNode,
|
|
@@ -5377,17 +5457,17 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5377
5457
|
}
|
|
5378
5458
|
}
|
|
5379
5459
|
}
|
|
5380
|
-
async loadEntities(
|
|
5381
|
-
const selectQuery = kysely.selectFrom(model).selectAll();
|
|
5460
|
+
async loadEntities(model, where) {
|
|
5461
|
+
const selectQuery = this.kysely.selectFrom(model).selectAll();
|
|
5382
5462
|
let selectQueryNode = selectQuery.toOperationNode();
|
|
5383
5463
|
selectQueryNode = {
|
|
5384
5464
|
...selectQueryNode,
|
|
5385
5465
|
where: this.andNodes(selectQueryNode.where, where)
|
|
5386
5466
|
};
|
|
5387
|
-
const compiled =
|
|
5467
|
+
const compiled = this.compileQuery(selectQueryNode);
|
|
5468
|
+
const result = await this.executeQuery(compiled, {
|
|
5388
5469
|
queryId: `zenstack-${(0, import_nanoid2.nanoid)()}`
|
|
5389
5470
|
});
|
|
5390
|
-
const result = await kysely.executeQuery(compiled);
|
|
5391
5471
|
return result.rows;
|
|
5392
5472
|
}
|
|
5393
5473
|
andNodes(condition1, condition2) {
|
|
@@ -5416,8 +5496,8 @@ __export(functions_exports, {
|
|
|
5416
5496
|
search: () => search,
|
|
5417
5497
|
startsWith: () => startsWith
|
|
5418
5498
|
});
|
|
5499
|
+
var import_common_helpers10 = require("@zenstackhq/common-helpers");
|
|
5419
5500
|
var import_kysely14 = require("kysely");
|
|
5420
|
-
var import_tiny_invariant8 = __toESM(require("tiny-invariant"), 1);
|
|
5421
5501
|
var import_ts_pattern16 = require("ts-pattern");
|
|
5422
5502
|
var contains = /* @__PURE__ */ __name((eb, args) => {
|
|
5423
5503
|
const [field, search2, caseInsensitive = false] = args;
|
|
@@ -5523,8 +5603,8 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
|
5523
5603
|
}, "currentOperation");
|
|
5524
5604
|
function processCasing(casing, result, model) {
|
|
5525
5605
|
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", () =>
|
|
5606
|
+
(0, import_common_helpers10.invariant)(import_kysely14.ValueNode.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
|
|
5607
|
+
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
5608
|
throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
|
|
5529
5609
|
});
|
|
5530
5610
|
return result;
|
|
@@ -5532,8 +5612,8 @@ function processCasing(casing, result, model) {
|
|
|
5532
5612
|
__name(processCasing, "processCasing");
|
|
5533
5613
|
|
|
5534
5614
|
// src/client/helpers/schema-db-pusher.ts
|
|
5615
|
+
var import_common_helpers11 = require("@zenstackhq/common-helpers");
|
|
5535
5616
|
var import_kysely15 = require("kysely");
|
|
5536
|
-
var import_tiny_invariant9 = __toESM(require("tiny-invariant"), 1);
|
|
5537
5617
|
var import_ts_pattern17 = require("ts-pattern");
|
|
5538
5618
|
var SchemaDbPusher = class {
|
|
5539
5619
|
static {
|
|
@@ -5565,7 +5645,7 @@ var SchemaDbPusher = class {
|
|
|
5565
5645
|
for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
|
|
5566
5646
|
if (fieldDef.relation) {
|
|
5567
5647
|
table = this.addForeignKeyConstraint(table, model, fieldName, fieldDef);
|
|
5568
|
-
} else {
|
|
5648
|
+
} else if (!this.isComputedField(fieldDef)) {
|
|
5569
5649
|
table = this.createModelField(table, fieldName, fieldDef, modelDef);
|
|
5570
5650
|
}
|
|
5571
5651
|
}
|
|
@@ -5573,6 +5653,9 @@ var SchemaDbPusher = class {
|
|
|
5573
5653
|
table = this.addUniqueConstraint(table, modelDef);
|
|
5574
5654
|
return table;
|
|
5575
5655
|
}
|
|
5656
|
+
isComputedField(fieldDef) {
|
|
5657
|
+
return fieldDef.attributes?.some((a) => a.name === "@computed");
|
|
5658
|
+
}
|
|
5576
5659
|
addPrimaryKeyConstraint(table, model, modelDef) {
|
|
5577
5660
|
if (modelDef.idFields.length === 1) {
|
|
5578
5661
|
if (Object.values(modelDef.fields).some((f) => f.id)) {
|
|
@@ -5586,7 +5669,7 @@ var SchemaDbPusher = class {
|
|
|
5586
5669
|
}
|
|
5587
5670
|
addUniqueConstraint(table, modelDef) {
|
|
5588
5671
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
5589
|
-
(0,
|
|
5672
|
+
(0, import_common_helpers11.invariant)(typeof value === "object", "expecting an object");
|
|
5590
5673
|
if ("type" in value) {
|
|
5591
5674
|
const fieldDef = modelDef.fields[key];
|
|
5592
5675
|
if (fieldDef.unique) {
|
|
@@ -5632,7 +5715,7 @@ var SchemaDbPusher = class {
|
|
|
5632
5715
|
return "serial";
|
|
5633
5716
|
}
|
|
5634
5717
|
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(() => {
|
|
5718
|
+
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
5719
|
throw new Error(`Unsupported field type: ${type}`);
|
|
5637
5720
|
});
|
|
5638
5721
|
if (fieldDef.array) {
|
|
@@ -5645,7 +5728,7 @@ var SchemaDbPusher = class {
|
|
|
5645
5728
|
return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
|
|
5646
5729
|
}
|
|
5647
5730
|
addForeignKeyConstraint(table, model, fieldName, fieldDef) {
|
|
5648
|
-
(0,
|
|
5731
|
+
(0, import_common_helpers11.invariant)(fieldDef.relation, "field must be a relation");
|
|
5649
5732
|
if (!fieldDef.relation.fields || !fieldDef.relation.references) {
|
|
5650
5733
|
return table;
|
|
5651
5734
|
}
|
|
@@ -5666,11 +5749,11 @@ var SchemaDbPusher = class {
|
|
|
5666
5749
|
};
|
|
5667
5750
|
|
|
5668
5751
|
// src/client/promise.ts
|
|
5669
|
-
function
|
|
5752
|
+
function createZenStackPromise(callback) {
|
|
5670
5753
|
let promise;
|
|
5671
|
-
const cb = /* @__PURE__ */ __name(() => {
|
|
5754
|
+
const cb = /* @__PURE__ */ __name((txClient) => {
|
|
5672
5755
|
try {
|
|
5673
|
-
return promise ??= valueToPromise(callback());
|
|
5756
|
+
return promise ??= valueToPromise(callback(txClient));
|
|
5674
5757
|
} catch (err) {
|
|
5675
5758
|
return Promise.reject(err);
|
|
5676
5759
|
}
|
|
@@ -5685,10 +5768,11 @@ function createDeferredPromise(callback) {
|
|
|
5685
5768
|
finally(onFinally) {
|
|
5686
5769
|
return cb().finally(onFinally);
|
|
5687
5770
|
},
|
|
5771
|
+
cb,
|
|
5688
5772
|
[Symbol.toStringTag]: "ZenStackPromise"
|
|
5689
5773
|
};
|
|
5690
5774
|
}
|
|
5691
|
-
__name(
|
|
5775
|
+
__name(createZenStackPromise, "createZenStackPromise");
|
|
5692
5776
|
function valueToPromise(thing) {
|
|
5693
5777
|
if (typeof thing === "object" && typeof thing?.then === "function") {
|
|
5694
5778
|
return thing;
|
|
@@ -5699,8 +5783,8 @@ function valueToPromise(thing) {
|
|
|
5699
5783
|
__name(valueToPromise, "valueToPromise");
|
|
5700
5784
|
|
|
5701
5785
|
// src/client/result-processor.ts
|
|
5786
|
+
var import_common_helpers12 = require("@zenstackhq/common-helpers");
|
|
5702
5787
|
var import_decimal2 = __toESM(require("decimal.js"), 1);
|
|
5703
|
-
var import_tiny_invariant10 = __toESM(require("tiny-invariant"), 1);
|
|
5704
5788
|
var import_ts_pattern18 = require("ts-pattern");
|
|
5705
5789
|
var ResultProcessor = class {
|
|
5706
5790
|
static {
|
|
@@ -5774,20 +5858,20 @@ var ResultProcessor = class {
|
|
|
5774
5858
|
return this.doProcessResult(relationData, fieldDef.type);
|
|
5775
5859
|
}
|
|
5776
5860
|
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);
|
|
5861
|
+
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
5862
|
}
|
|
5779
5863
|
transformDecimal(value) {
|
|
5780
5864
|
if (value instanceof import_decimal2.default) {
|
|
5781
5865
|
return value;
|
|
5782
5866
|
}
|
|
5783
|
-
(0,
|
|
5867
|
+
(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
5868
|
return new import_decimal2.default(value);
|
|
5785
5869
|
}
|
|
5786
5870
|
transformBigInt(value) {
|
|
5787
5871
|
if (typeof value === "bigint") {
|
|
5788
5872
|
return value;
|
|
5789
5873
|
}
|
|
5790
|
-
(0,
|
|
5874
|
+
(0, import_common_helpers12.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
5791
5875
|
return BigInt(value);
|
|
5792
5876
|
}
|
|
5793
5877
|
transformBoolean(value) {
|
|
@@ -5806,6 +5890,9 @@ var ResultProcessor = class {
|
|
|
5806
5890
|
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
5807
5891
|
}
|
|
5808
5892
|
fixReversedResult(data, model, args) {
|
|
5893
|
+
if (!data) {
|
|
5894
|
+
return;
|
|
5895
|
+
}
|
|
5809
5896
|
if (Array.isArray(data) && typeof args === "object" && args && args.take !== void 0 && args.take < 0) {
|
|
5810
5897
|
data.reverse();
|
|
5811
5898
|
}
|
|
@@ -5819,13 +5906,19 @@ var ResultProcessor = class {
|
|
|
5819
5906
|
continue;
|
|
5820
5907
|
}
|
|
5821
5908
|
const fieldDef = getField(this.schema, model, field);
|
|
5822
|
-
if (!fieldDef
|
|
5909
|
+
if (!fieldDef || !fieldDef.relation || !fieldDef.array) {
|
|
5823
5910
|
continue;
|
|
5824
5911
|
}
|
|
5825
5912
|
this.fixReversedResult(row[field], fieldDef.type, value);
|
|
5826
5913
|
}
|
|
5827
5914
|
}
|
|
5828
5915
|
}
|
|
5916
|
+
transformJson(value) {
|
|
5917
|
+
return (0, import_ts_pattern18.match)(this.schema.provider.type).with("sqlite", () => {
|
|
5918
|
+
(0, import_common_helpers12.invariant)(typeof value === "string", "Expected string, got " + typeof value);
|
|
5919
|
+
return JSON.parse(value);
|
|
5920
|
+
}).otherwise(() => value);
|
|
5921
|
+
}
|
|
5829
5922
|
};
|
|
5830
5923
|
|
|
5831
5924
|
// src/client/client-impl.ts
|
|
@@ -5844,7 +5937,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
5844
5937
|
$schema;
|
|
5845
5938
|
kyselyProps;
|
|
5846
5939
|
auth;
|
|
5847
|
-
constructor(schema, options, baseClient) {
|
|
5940
|
+
constructor(schema, options, baseClient, executor) {
|
|
5848
5941
|
this.schema = schema;
|
|
5849
5942
|
this.options = options;
|
|
5850
5943
|
this.$schema = schema;
|
|
@@ -5856,16 +5949,16 @@ var ClientImpl = class _ClientImpl {
|
|
|
5856
5949
|
if (baseClient) {
|
|
5857
5950
|
this.kyselyProps = {
|
|
5858
5951
|
...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))
|
|
5952
|
+
executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new import_kysely16.DefaultConnectionProvider(baseClient.kyselyProps.driver))
|
|
5860
5953
|
};
|
|
5861
5954
|
this.kyselyRaw = baseClient.kyselyRaw;
|
|
5955
|
+
this.auth = baseClient.auth;
|
|
5862
5956
|
} else {
|
|
5863
5957
|
const dialect = this.getKyselyDialect();
|
|
5864
5958
|
const driver = new ZenStackDriver(dialect.createDriver(), new import_kysely16.Log(this.$options.log ?? []));
|
|
5865
5959
|
const compiler = dialect.createQueryCompiler();
|
|
5866
5960
|
const adapter = dialect.createAdapter();
|
|
5867
5961
|
const connectionProvider = new import_kysely16.DefaultConnectionProvider(driver);
|
|
5868
|
-
const executor = new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider);
|
|
5869
5962
|
this.kyselyProps = {
|
|
5870
5963
|
config: {
|
|
5871
5964
|
dialect,
|
|
@@ -5873,7 +5966,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
5873
5966
|
},
|
|
5874
5967
|
dialect,
|
|
5875
5968
|
driver,
|
|
5876
|
-
executor
|
|
5969
|
+
executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
|
|
5877
5970
|
};
|
|
5878
5971
|
this.kyselyRaw = new import_kysely16.Kysely({
|
|
5879
5972
|
...this.kyselyProps,
|
|
@@ -5889,31 +5982,67 @@ var ClientImpl = class _ClientImpl {
|
|
|
5889
5982
|
get $qbRaw() {
|
|
5890
5983
|
return this.kyselyRaw;
|
|
5891
5984
|
}
|
|
5985
|
+
get isTransaction() {
|
|
5986
|
+
return this.kysely.isTransaction;
|
|
5987
|
+
}
|
|
5988
|
+
/**
|
|
5989
|
+
* Create a new client with a new query executor.
|
|
5990
|
+
*/
|
|
5991
|
+
withExecutor(executor) {
|
|
5992
|
+
return new _ClientImpl(this.schema, this.$options, this, executor);
|
|
5993
|
+
}
|
|
5892
5994
|
getKyselyDialect() {
|
|
5893
5995
|
return (0, import_ts_pattern19.match)(this.schema.provider.type).with("sqlite", () => this.makeSqliteKyselyDialect()).with("postgresql", () => this.makePostgresKyselyDialect()).exhaustive();
|
|
5894
5996
|
}
|
|
5895
5997
|
makePostgresKyselyDialect() {
|
|
5896
|
-
|
|
5897
|
-
const mergedConfig = {
|
|
5898
|
-
...dialectConfigProvider(),
|
|
5899
|
-
...this.options?.dialectConfig
|
|
5900
|
-
};
|
|
5901
|
-
return new import_kysely16.PostgresDialect(mergedConfig);
|
|
5998
|
+
return new import_kysely16.PostgresDialect(this.options.dialectConfig);
|
|
5902
5999
|
}
|
|
5903
6000
|
makeSqliteKyselyDialect() {
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
6001
|
+
return new import_kysely16.SqliteDialect(this.options.dialectConfig);
|
|
6002
|
+
}
|
|
6003
|
+
// implementation
|
|
6004
|
+
async $transaction(input, options) {
|
|
6005
|
+
(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");
|
|
6006
|
+
if (typeof input === "function") {
|
|
6007
|
+
return this.interactiveTransaction(input, options);
|
|
6008
|
+
} else {
|
|
6009
|
+
return this.sequentialTransaction(input, options);
|
|
6010
|
+
}
|
|
6011
|
+
}
|
|
6012
|
+
async interactiveTransaction(callback, options) {
|
|
6013
|
+
if (this.kysely.isTransaction) {
|
|
6014
|
+
return callback(this);
|
|
6015
|
+
} else {
|
|
6016
|
+
let txBuilder = this.kysely.transaction();
|
|
6017
|
+
if (options?.isolationLevel) {
|
|
6018
|
+
txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
|
|
6019
|
+
}
|
|
6020
|
+
return txBuilder.execute((tx) => {
|
|
6021
|
+
const txClient = new _ClientImpl(this.schema, this.$options, this);
|
|
6022
|
+
txClient.kysely = tx;
|
|
6023
|
+
return callback(txClient);
|
|
6024
|
+
});
|
|
6025
|
+
}
|
|
5910
6026
|
}
|
|
5911
|
-
async
|
|
5912
|
-
|
|
5913
|
-
const txClient = new _ClientImpl(this.schema, this.$options);
|
|
6027
|
+
async sequentialTransaction(arg, options) {
|
|
6028
|
+
const execute = /* @__PURE__ */ __name(async (tx) => {
|
|
6029
|
+
const txClient = new _ClientImpl(this.schema, this.$options, this);
|
|
5914
6030
|
txClient.kysely = tx;
|
|
5915
|
-
|
|
5916
|
-
|
|
6031
|
+
const result = [];
|
|
6032
|
+
for (const promise of arg) {
|
|
6033
|
+
result.push(await promise.cb(txClient));
|
|
6034
|
+
}
|
|
6035
|
+
return result;
|
|
6036
|
+
}, "execute");
|
|
6037
|
+
if (this.kysely.isTransaction) {
|
|
6038
|
+
return execute(this.kysely);
|
|
6039
|
+
} else {
|
|
6040
|
+
let txBuilder = this.kysely.transaction();
|
|
6041
|
+
if (options?.isolationLevel) {
|
|
6042
|
+
txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
|
|
6043
|
+
}
|
|
6044
|
+
return txBuilder.execute((tx) => execute(tx));
|
|
6045
|
+
}
|
|
5917
6046
|
}
|
|
5918
6047
|
get $procedures() {
|
|
5919
6048
|
return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
|
|
@@ -5944,12 +6073,19 @@ var ClientImpl = class _ClientImpl {
|
|
|
5944
6073
|
const newOptions = {
|
|
5945
6074
|
...this.options,
|
|
5946
6075
|
plugins: [
|
|
5947
|
-
...this.options
|
|
6076
|
+
...this.options.plugins ?? [],
|
|
5948
6077
|
plugin
|
|
5949
6078
|
]
|
|
5950
6079
|
};
|
|
5951
6080
|
return new _ClientImpl(this.schema, newOptions, this);
|
|
5952
6081
|
}
|
|
6082
|
+
$unuse(pluginId) {
|
|
6083
|
+
const newOptions = {
|
|
6084
|
+
...this.options,
|
|
6085
|
+
plugins: this.options.plugins?.filter((p) => p.id !== pluginId)
|
|
6086
|
+
};
|
|
6087
|
+
return new _ClientImpl(this.schema, newOptions, this);
|
|
6088
|
+
}
|
|
5953
6089
|
$unuseAll() {
|
|
5954
6090
|
const newOptions = {
|
|
5955
6091
|
...this.options,
|
|
@@ -5968,6 +6104,39 @@ var ClientImpl = class _ClientImpl {
|
|
|
5968
6104
|
get $auth() {
|
|
5969
6105
|
return this.auth;
|
|
5970
6106
|
}
|
|
6107
|
+
$executeRaw(query, ...values) {
|
|
6108
|
+
return createZenStackPromise(async () => {
|
|
6109
|
+
const result = await (0, import_kysely16.sql)(query, ...values).execute(this.kysely);
|
|
6110
|
+
return Number(result.numAffectedRows ?? 0);
|
|
6111
|
+
});
|
|
6112
|
+
}
|
|
6113
|
+
$executeRawUnsafe(query, ...values) {
|
|
6114
|
+
return createZenStackPromise(async () => {
|
|
6115
|
+
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
6116
|
+
const result = await this.kysely.executeQuery(compiledQuery);
|
|
6117
|
+
return Number(result.numAffectedRows ?? 0);
|
|
6118
|
+
});
|
|
6119
|
+
}
|
|
6120
|
+
$queryRaw(query, ...values) {
|
|
6121
|
+
return createZenStackPromise(async () => {
|
|
6122
|
+
const result = await (0, import_kysely16.sql)(query, ...values).execute(this.kysely);
|
|
6123
|
+
return result.rows;
|
|
6124
|
+
});
|
|
6125
|
+
}
|
|
6126
|
+
$queryRawUnsafe(query, ...values) {
|
|
6127
|
+
return createZenStackPromise(async () => {
|
|
6128
|
+
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
6129
|
+
const result = await this.kysely.executeQuery(compiledQuery);
|
|
6130
|
+
return result.rows;
|
|
6131
|
+
});
|
|
6132
|
+
}
|
|
6133
|
+
createRawCompiledQuery(query, values) {
|
|
6134
|
+
const q = import_kysely16.CompiledQuery.raw(query, values);
|
|
6135
|
+
return {
|
|
6136
|
+
...q,
|
|
6137
|
+
$raw: true
|
|
6138
|
+
};
|
|
6139
|
+
}
|
|
5971
6140
|
};
|
|
5972
6141
|
function createClientProxy(client) {
|
|
5973
6142
|
const inputValidator = new InputValidator(client.$schema);
|
|
@@ -5990,9 +6159,9 @@ function createClientProxy(client) {
|
|
|
5990
6159
|
__name(createClientProxy, "createClientProxy");
|
|
5991
6160
|
function createModelCrudHandler(client, model, inputValidator, resultProcessor) {
|
|
5992
6161
|
const createPromise = /* @__PURE__ */ __name((operation, args, handler, postProcess = false, throwIfNoResult = false) => {
|
|
5993
|
-
return
|
|
5994
|
-
let proceed = /* @__PURE__ */ __name(async (_args
|
|
5995
|
-
const _handler =
|
|
6162
|
+
return createZenStackPromise(async (txClient) => {
|
|
6163
|
+
let proceed = /* @__PURE__ */ __name(async (_args) => {
|
|
6164
|
+
const _handler = txClient ? handler.withClient(txClient) : handler;
|
|
5996
6165
|
const r = await _handler.handle(operation, _args ?? args);
|
|
5997
6166
|
if (!r && throwIfNoResult) {
|
|
5998
6167
|
throw new NotFoundError(model);
|
|
@@ -6005,22 +6174,31 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
6005
6174
|
}
|
|
6006
6175
|
return result;
|
|
6007
6176
|
}, "proceed");
|
|
6008
|
-
const context = {
|
|
6009
|
-
client,
|
|
6010
|
-
model,
|
|
6011
|
-
operation,
|
|
6012
|
-
queryArgs: args
|
|
6013
|
-
};
|
|
6014
6177
|
const plugins = [
|
|
6015
6178
|
...client.$options.plugins ?? []
|
|
6016
6179
|
];
|
|
6017
6180
|
for (const plugin of plugins) {
|
|
6018
|
-
if (plugin.onQuery) {
|
|
6019
|
-
const
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6181
|
+
if (plugin.onQuery && typeof plugin.onQuery === "object") {
|
|
6182
|
+
for (const [_model, modelHooks] of Object.entries(plugin.onQuery)) {
|
|
6183
|
+
if (_model === (0, import_common_helpers13.lowerCaseFirst)(model) || _model === "$allModels") {
|
|
6184
|
+
if (modelHooks && typeof modelHooks === "object") {
|
|
6185
|
+
for (const [op, opHooks] of Object.entries(modelHooks)) {
|
|
6186
|
+
if (op === operation || op === "$allOperations") {
|
|
6187
|
+
if (typeof opHooks === "function") {
|
|
6188
|
+
const _proceed = proceed;
|
|
6189
|
+
proceed = /* @__PURE__ */ __name(() => opHooks({
|
|
6190
|
+
client,
|
|
6191
|
+
model,
|
|
6192
|
+
operation,
|
|
6193
|
+
args,
|
|
6194
|
+
query: _proceed
|
|
6195
|
+
}), "proceed");
|
|
6196
|
+
}
|
|
6197
|
+
}
|
|
6198
|
+
}
|
|
6199
|
+
}
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
6024
6202
|
}
|
|
6025
6203
|
}
|
|
6026
6204
|
return proceed(args);
|
|
@@ -6076,13 +6254,24 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
6076
6254
|
return createPromise("aggregate", args, new AggregateOperationHandler(client, model, inputValidator), false);
|
|
6077
6255
|
}, "aggregate"),
|
|
6078
6256
|
groupBy: /* @__PURE__ */ __name((args) => {
|
|
6079
|
-
return createPromise("groupBy", args, new
|
|
6257
|
+
return createPromise("groupBy", args, new GroupByOperationHandler(client, model, inputValidator));
|
|
6080
6258
|
}, "groupBy")
|
|
6081
6259
|
};
|
|
6082
6260
|
}
|
|
6083
6261
|
__name(createModelCrudHandler, "createModelCrudHandler");
|
|
6262
|
+
|
|
6263
|
+
// src/client/plugin.ts
|
|
6264
|
+
function definePlugin(plugin) {
|
|
6265
|
+
return plugin;
|
|
6266
|
+
}
|
|
6267
|
+
__name(definePlugin, "definePlugin");
|
|
6084
6268
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6085
6269
|
0 && (module.exports = {
|
|
6086
|
-
|
|
6270
|
+
InputValidationError,
|
|
6271
|
+
InternalError,
|
|
6272
|
+
NotFoundError,
|
|
6273
|
+
QueryError,
|
|
6274
|
+
ZenStackClient,
|
|
6275
|
+
definePlugin
|
|
6087
6276
|
});
|
|
6088
6277
|
//# sourceMappingURL=index.cjs.map
|