@zenstackhq/runtime 3.0.0-alpha.12 → 3.0.0-alpha.14
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-BEAyf7Es.d.cts → contract-BYc34jr_.d.cts} +78 -54
- package/dist/{contract-BEAyf7Es.d.ts → contract-BYc34jr_.d.ts} +78 -54
- package/dist/index.cjs +821 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +821 -311
- package/dist/index.js.map +1 -1
- package/dist/plugins/{policy.cjs → policy/index.cjs} +225 -125
- package/dist/plugins/policy/index.cjs.map +1 -0
- package/dist/plugins/{policy.d.ts → policy/index.d.cts} +1 -1
- package/dist/plugins/{policy.d.cts → policy/index.d.ts} +1 -1
- package/dist/plugins/{policy.js → policy/index.js} +225 -125
- package/dist/plugins/policy/index.js.map +1 -0
- package/dist/plugins/policy/plugin.zmodel +33 -0
- package/package.json +12 -12
- package/dist/plugins/policy.cjs.map +0 -1
- package/dist/plugins/policy.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -49,6 +49,85 @@ var import_ts_pattern19 = require("ts-pattern");
|
|
|
49
49
|
var import_kysely9 = require("kysely");
|
|
50
50
|
var import_ts_pattern9 = require("ts-pattern");
|
|
51
51
|
|
|
52
|
+
// src/schema/expression.ts
|
|
53
|
+
var ExpressionUtils = {
|
|
54
|
+
literal: /* @__PURE__ */ __name((value) => {
|
|
55
|
+
return {
|
|
56
|
+
kind: "literal",
|
|
57
|
+
value
|
|
58
|
+
};
|
|
59
|
+
}, "literal"),
|
|
60
|
+
array: /* @__PURE__ */ __name((items) => {
|
|
61
|
+
return {
|
|
62
|
+
kind: "array",
|
|
63
|
+
items
|
|
64
|
+
};
|
|
65
|
+
}, "array"),
|
|
66
|
+
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
67
|
+
return {
|
|
68
|
+
kind: "call",
|
|
69
|
+
function: functionName,
|
|
70
|
+
args
|
|
71
|
+
};
|
|
72
|
+
}, "call"),
|
|
73
|
+
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
74
|
+
return {
|
|
75
|
+
kind: "binary",
|
|
76
|
+
op,
|
|
77
|
+
left,
|
|
78
|
+
right
|
|
79
|
+
};
|
|
80
|
+
}, "binary"),
|
|
81
|
+
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
82
|
+
return {
|
|
83
|
+
kind: "unary",
|
|
84
|
+
op,
|
|
85
|
+
operand
|
|
86
|
+
};
|
|
87
|
+
}, "unary"),
|
|
88
|
+
field: /* @__PURE__ */ __name((field) => {
|
|
89
|
+
return {
|
|
90
|
+
kind: "field",
|
|
91
|
+
field
|
|
92
|
+
};
|
|
93
|
+
}, "field"),
|
|
94
|
+
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
95
|
+
return {
|
|
96
|
+
kind: "member",
|
|
97
|
+
receiver,
|
|
98
|
+
members
|
|
99
|
+
};
|
|
100
|
+
}, "member"),
|
|
101
|
+
_this: /* @__PURE__ */ __name(() => {
|
|
102
|
+
return {
|
|
103
|
+
kind: "this"
|
|
104
|
+
};
|
|
105
|
+
}, "_this"),
|
|
106
|
+
_null: /* @__PURE__ */ __name(() => {
|
|
107
|
+
return {
|
|
108
|
+
kind: "null"
|
|
109
|
+
};
|
|
110
|
+
}, "_null"),
|
|
111
|
+
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
112
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
113
|
+
}, "and"),
|
|
114
|
+
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
115
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
116
|
+
}, "or"),
|
|
117
|
+
is: /* @__PURE__ */ __name((value, kind) => {
|
|
118
|
+
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
119
|
+
}, "is"),
|
|
120
|
+
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
121
|
+
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
122
|
+
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
123
|
+
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
124
|
+
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
125
|
+
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
126
|
+
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
127
|
+
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
128
|
+
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
|
|
129
|
+
};
|
|
130
|
+
|
|
52
131
|
// src/client/errors.ts
|
|
53
132
|
var InputValidationError = class extends Error {
|
|
54
133
|
static {
|
|
@@ -170,6 +249,11 @@ function isRelationField(schema, model, field) {
|
|
|
170
249
|
return !!fieldDef.relation;
|
|
171
250
|
}
|
|
172
251
|
__name(isRelationField, "isRelationField");
|
|
252
|
+
function isInheritedField(schema, model, field) {
|
|
253
|
+
const fieldDef = requireField(schema, model, field);
|
|
254
|
+
return !!fieldDef.originModel;
|
|
255
|
+
}
|
|
256
|
+
__name(isInheritedField, "isInheritedField");
|
|
173
257
|
function getUniqueFields(schema, model) {
|
|
174
258
|
const modelDef = requireModel(schema, model);
|
|
175
259
|
const result = [];
|
|
@@ -322,6 +406,46 @@ function safeJSONStringify(value) {
|
|
|
322
406
|
});
|
|
323
407
|
}
|
|
324
408
|
__name(safeJSONStringify, "safeJSONStringify");
|
|
409
|
+
function extractFields(object, fields) {
|
|
410
|
+
return fields.reduce((acc, field) => {
|
|
411
|
+
if (field in object) {
|
|
412
|
+
acc[field] = object[field];
|
|
413
|
+
}
|
|
414
|
+
return acc;
|
|
415
|
+
}, {});
|
|
416
|
+
}
|
|
417
|
+
__name(extractFields, "extractFields");
|
|
418
|
+
function extractIdFields(entity, schema, model) {
|
|
419
|
+
const idFields = getIdFields(schema, model);
|
|
420
|
+
return extractFields(entity, idFields);
|
|
421
|
+
}
|
|
422
|
+
__name(extractIdFields, "extractIdFields");
|
|
423
|
+
function getDiscriminatorField(schema, model) {
|
|
424
|
+
const modelDef = requireModel(schema, model);
|
|
425
|
+
const delegateAttr = modelDef.attributes?.find((attr) => attr.name === "@@delegate");
|
|
426
|
+
if (!delegateAttr) {
|
|
427
|
+
return void 0;
|
|
428
|
+
}
|
|
429
|
+
const discriminator = delegateAttr.args?.find((arg) => arg.name === "discriminator");
|
|
430
|
+
if (!discriminator || !ExpressionUtils.isField(discriminator.value)) {
|
|
431
|
+
throw new InternalError(`Discriminator field not defined for model "${model}"`);
|
|
432
|
+
}
|
|
433
|
+
return discriminator.value.field;
|
|
434
|
+
}
|
|
435
|
+
__name(getDiscriminatorField, "getDiscriminatorField");
|
|
436
|
+
function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */ new Set()) {
|
|
437
|
+
const subModels = Object.values(schema.models).filter((m) => m.baseModel === model);
|
|
438
|
+
subModels.forEach((def) => {
|
|
439
|
+
if (!collected.has(def)) {
|
|
440
|
+
collected.add(def);
|
|
441
|
+
getDelegateDescendantModels(schema, def.name, collected);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
return [
|
|
445
|
+
...collected
|
|
446
|
+
];
|
|
447
|
+
}
|
|
448
|
+
__name(getDelegateDescendantModels, "getDelegateDescendantModels");
|
|
325
449
|
|
|
326
450
|
// src/client/crud/operations/base.ts
|
|
327
451
|
var import_cuid2 = require("@paralleldrive/cuid2");
|
|
@@ -358,6 +482,16 @@ var import_common_helpers2 = require("@zenstackhq/common-helpers");
|
|
|
358
482
|
var import_kysely2 = require("kysely");
|
|
359
483
|
var import_ts_pattern2 = require("ts-pattern");
|
|
360
484
|
|
|
485
|
+
// src/client/constants.ts
|
|
486
|
+
var CONTEXT_COMMENT_PREFIX = "-- $$context:";
|
|
487
|
+
var NUMERIC_FIELD_TYPES = [
|
|
488
|
+
"Int",
|
|
489
|
+
"Float",
|
|
490
|
+
"BigInt",
|
|
491
|
+
"Decimal"
|
|
492
|
+
];
|
|
493
|
+
var DELEGATE_JOINED_FIELD_PREFIX = "$delegate$";
|
|
494
|
+
|
|
361
495
|
// src/client/crud/dialects/base.ts
|
|
362
496
|
var import_common_helpers = require("@zenstackhq/common-helpers");
|
|
363
497
|
var import_kysely = require("kysely");
|
|
@@ -391,6 +525,17 @@ var BaseCrudDialect = class {
|
|
|
391
525
|
transformPrimitive(value, _type, _forArrayField) {
|
|
392
526
|
return value;
|
|
393
527
|
}
|
|
528
|
+
// #region common query builders
|
|
529
|
+
buildSelectModel(eb, model) {
|
|
530
|
+
const modelDef = requireModel(this.schema, model);
|
|
531
|
+
let result = eb.selectFrom(model);
|
|
532
|
+
let joinBase = modelDef.baseModel;
|
|
533
|
+
while (joinBase) {
|
|
534
|
+
result = this.buildDelegateJoin(model, joinBase, result);
|
|
535
|
+
joinBase = requireModel(this.schema, joinBase).baseModel;
|
|
536
|
+
}
|
|
537
|
+
return result;
|
|
538
|
+
}
|
|
394
539
|
buildFilter(eb, model, modelAlias, where) {
|
|
395
540
|
if (where === true || where === void 0) {
|
|
396
541
|
return this.true(eb);
|
|
@@ -414,10 +559,13 @@ var BaseCrudDialect = class {
|
|
|
414
559
|
const fieldDef = requireField(this.schema, model, key);
|
|
415
560
|
if (fieldDef.relation) {
|
|
416
561
|
result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
417
|
-
} else if (fieldDef.array) {
|
|
418
|
-
result = this.and(eb, result, this.buildArrayFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
419
562
|
} else {
|
|
420
|
-
|
|
563
|
+
const fieldRef = buildFieldRef(this.schema, fieldDef.originModel ?? model, key, this.options, eb, fieldDef.originModel ?? modelAlias);
|
|
564
|
+
if (fieldDef.array) {
|
|
565
|
+
result = this.and(eb, result, this.buildArrayFilter(eb, fieldRef, fieldDef, payload));
|
|
566
|
+
} else {
|
|
567
|
+
result = this.and(eb, result, this.buildPrimitiveFilter(eb, fieldRef, fieldDef, payload));
|
|
568
|
+
}
|
|
421
569
|
}
|
|
422
570
|
}
|
|
423
571
|
if ("$expr" in _where && typeof _where["$expr"] === "function") {
|
|
@@ -435,19 +583,26 @@ var BaseCrudDialect = class {
|
|
|
435
583
|
return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
|
|
436
584
|
}
|
|
437
585
|
}
|
|
438
|
-
buildToOneRelationFilter(eb, model,
|
|
586
|
+
buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
439
587
|
if (payload === null) {
|
|
440
588
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
441
|
-
if (ownedByModel) {
|
|
442
|
-
return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely.sql.ref(`${
|
|
589
|
+
if (ownedByModel && !fieldDef.originModel) {
|
|
590
|
+
return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely.sql.ref(`${modelAlias}.${fk}`), "is", null)));
|
|
443
591
|
} else {
|
|
444
|
-
return this.buildToOneRelationFilter(eb, model,
|
|
592
|
+
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
|
|
445
593
|
is: null
|
|
446
594
|
});
|
|
447
595
|
}
|
|
448
596
|
}
|
|
449
|
-
const joinAlias = `${
|
|
450
|
-
const joinPairs = buildJoinPairs(
|
|
597
|
+
const joinAlias = `${modelAlias}$${field}`;
|
|
598
|
+
const joinPairs = buildJoinPairs(
|
|
599
|
+
this.schema,
|
|
600
|
+
model,
|
|
601
|
+
// if field is from a base, use the base model to join
|
|
602
|
+
fieldDef.originModel ?? modelAlias,
|
|
603
|
+
field,
|
|
604
|
+
joinAlias
|
|
605
|
+
);
|
|
451
606
|
const filterResultField = `${field}$filter`;
|
|
452
607
|
const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
|
|
453
608
|
const conditions = [];
|
|
@@ -508,25 +663,24 @@ var BaseCrudDialect = class {
|
|
|
508
663
|
}
|
|
509
664
|
switch (key) {
|
|
510
665
|
case "some": {
|
|
511
|
-
result = this.and(eb, result, eb(
|
|
666
|
+
result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), ">", 0));
|
|
512
667
|
break;
|
|
513
668
|
}
|
|
514
669
|
case "every": {
|
|
515
|
-
result = this.and(eb, result, eb(
|
|
670
|
+
result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => eb1.not(this.buildFilter(eb1, relationModel, relationModel, subPayload))), "=", 0));
|
|
516
671
|
break;
|
|
517
672
|
}
|
|
518
673
|
case "none": {
|
|
519
|
-
result = this.and(eb, result, eb(
|
|
674
|
+
result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), "=", 0));
|
|
520
675
|
break;
|
|
521
676
|
}
|
|
522
677
|
}
|
|
523
678
|
}
|
|
524
679
|
return result;
|
|
525
680
|
}
|
|
526
|
-
buildArrayFilter(eb,
|
|
681
|
+
buildArrayFilter(eb, fieldRef, fieldDef, payload) {
|
|
527
682
|
const clauses = [];
|
|
528
683
|
const fieldType = fieldDef.type;
|
|
529
|
-
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
|
|
530
684
|
for (const [key, _value] of Object.entries(payload)) {
|
|
531
685
|
if (_value === void 0) {
|
|
532
686
|
continue;
|
|
@@ -562,14 +716,14 @@ var BaseCrudDialect = class {
|
|
|
562
716
|
}
|
|
563
717
|
return this.and(eb, ...clauses);
|
|
564
718
|
}
|
|
565
|
-
buildPrimitiveFilter(eb,
|
|
719
|
+
buildPrimitiveFilter(eb, fieldRef, fieldDef, payload) {
|
|
566
720
|
if (payload === null) {
|
|
567
|
-
return eb(
|
|
721
|
+
return eb(fieldRef, "is", null);
|
|
568
722
|
}
|
|
569
723
|
if (isEnum(this.schema, fieldDef.type)) {
|
|
570
|
-
return this.buildEnumFilter(eb,
|
|
724
|
+
return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
|
|
571
725
|
}
|
|
572
|
-
return (0, import_ts_pattern.match)(fieldDef.type).with("String", () => this.buildStringFilter(eb,
|
|
726
|
+
return (0, import_ts_pattern.match)(fieldDef.type).with("String", () => this.buildStringFilter(eb, fieldRef, payload)).with(import_ts_pattern.P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, fieldRef, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, fieldRef, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, fieldRef, payload)).with("Bytes", () => this.buildBytesFilter(eb, fieldRef, payload)).with("Json", () => {
|
|
573
727
|
throw new InternalError("JSON filters are not supported yet");
|
|
574
728
|
}).with("Unsupported", () => {
|
|
575
729
|
throw new QueryError(`Unsupported field cannot be used in filters`);
|
|
@@ -625,9 +779,7 @@ var BaseCrudDialect = class {
|
|
|
625
779
|
consumedKeys
|
|
626
780
|
};
|
|
627
781
|
}
|
|
628
|
-
buildStringFilter(eb,
|
|
629
|
-
const fieldDef = getField(this.schema, table, field);
|
|
630
|
-
let fieldRef = fieldDef?.computed ? import_kysely.sql.ref(field) : import_kysely.sql.ref(`${table}.${field}`);
|
|
782
|
+
buildStringFilter(eb, fieldRef, payload) {
|
|
631
783
|
let insensitive = false;
|
|
632
784
|
if (payload && typeof payload === "object" && "mode" in payload && payload.mode === "insensitive") {
|
|
633
785
|
insensitive = true;
|
|
@@ -635,7 +787,7 @@ var BaseCrudDialect = class {
|
|
|
635
787
|
fieldRef
|
|
636
788
|
]);
|
|
637
789
|
}
|
|
638
|
-
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => this.prepStringCasing(eb, value, insensitive), (value) => this.buildStringFilter(eb,
|
|
790
|
+
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => this.prepStringCasing(eb, value, insensitive), (value) => this.buildStringFilter(eb, fieldRef, value));
|
|
639
791
|
if (payload && typeof payload === "object") {
|
|
640
792
|
for (const [key, value] of Object.entries(payload)) {
|
|
641
793
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
@@ -662,23 +814,23 @@ var BaseCrudDialect = class {
|
|
|
662
814
|
return value === null ? null : import_kysely.sql.lit(value);
|
|
663
815
|
}
|
|
664
816
|
}
|
|
665
|
-
buildNumberFilter(eb,
|
|
666
|
-
const { conditions } = this.buildStandardFilter(eb, type, payload,
|
|
817
|
+
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
818
|
+
const { conditions } = this.buildStandardFilter(eb, type, payload, fieldRef, (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, fieldRef, type, value));
|
|
667
819
|
return this.and(eb, ...conditions);
|
|
668
820
|
}
|
|
669
|
-
buildBooleanFilter(eb,
|
|
670
|
-
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload,
|
|
821
|
+
buildBooleanFilter(eb, fieldRef, payload) {
|
|
822
|
+
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, fieldRef, (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, fieldRef, value), true, [
|
|
671
823
|
"equals",
|
|
672
824
|
"not"
|
|
673
825
|
]);
|
|
674
826
|
return this.and(eb, ...conditions);
|
|
675
827
|
}
|
|
676
|
-
buildDateTimeFilter(eb,
|
|
677
|
-
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload,
|
|
828
|
+
buildDateTimeFilter(eb, fieldRef, payload) {
|
|
829
|
+
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, fieldRef, (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, fieldRef, value), true);
|
|
678
830
|
return this.and(eb, ...conditions);
|
|
679
831
|
}
|
|
680
|
-
buildBytesFilter(eb,
|
|
681
|
-
const conditions = this.buildStandardFilter(eb, "Bytes", payload,
|
|
832
|
+
buildBytesFilter(eb, fieldRef, payload) {
|
|
833
|
+
const conditions = this.buildStandardFilter(eb, "Bytes", payload, fieldRef, (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, fieldRef, value), true, [
|
|
682
834
|
"equals",
|
|
683
835
|
"in",
|
|
684
836
|
"notIn",
|
|
@@ -686,8 +838,8 @@ var BaseCrudDialect = class {
|
|
|
686
838
|
]);
|
|
687
839
|
return this.and(eb, ...conditions.conditions);
|
|
688
840
|
}
|
|
689
|
-
buildEnumFilter(eb,
|
|
690
|
-
const conditions = this.buildStandardFilter(eb, "String", payload,
|
|
841
|
+
buildEnumFilter(eb, fieldRef, fieldDef, payload) {
|
|
842
|
+
const conditions = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => value, (value) => this.buildEnumFilter(eb, fieldRef, fieldDef, value), true, [
|
|
691
843
|
"equals",
|
|
692
844
|
"in",
|
|
693
845
|
"notIn",
|
|
@@ -754,7 +906,7 @@ var BaseCrudDialect = class {
|
|
|
754
906
|
(0, import_common_helpers.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
755
907
|
const sort = this.negateSort(value._count, negated);
|
|
756
908
|
result = result.orderBy((eb) => {
|
|
757
|
-
let subQuery =
|
|
909
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
758
910
|
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
|
|
759
911
|
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right)))));
|
|
760
912
|
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
@@ -773,6 +925,56 @@ var BaseCrudDialect = class {
|
|
|
773
925
|
});
|
|
774
926
|
return result;
|
|
775
927
|
}
|
|
928
|
+
buildSelectAllFields(model, query, omit) {
|
|
929
|
+
const modelDef = requireModel(this.schema, model);
|
|
930
|
+
let result = query;
|
|
931
|
+
for (const field of Object.keys(modelDef.fields)) {
|
|
932
|
+
if (isRelationField(this.schema, model, field)) {
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
935
|
+
if (omit?.[field] === true) {
|
|
936
|
+
continue;
|
|
937
|
+
}
|
|
938
|
+
result = this.buildSelectField(result, model, model, field);
|
|
939
|
+
}
|
|
940
|
+
const descendants = getDelegateDescendantModels(this.schema, model);
|
|
941
|
+
for (const subModel of descendants) {
|
|
942
|
+
result = this.buildDelegateJoin(model, subModel.name, result);
|
|
943
|
+
result = result.select((eb) => {
|
|
944
|
+
const jsonObject = {};
|
|
945
|
+
for (const field of Object.keys(subModel.fields)) {
|
|
946
|
+
if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
|
|
947
|
+
continue;
|
|
948
|
+
}
|
|
949
|
+
jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
|
|
950
|
+
}
|
|
951
|
+
return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
return result;
|
|
955
|
+
}
|
|
956
|
+
buildSelectField(query, model, modelAlias, field) {
|
|
957
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
958
|
+
if (fieldDef.computed) {
|
|
959
|
+
return query.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(field));
|
|
960
|
+
} else if (!fieldDef.originModel) {
|
|
961
|
+
return query.select(import_kysely.sql.ref(`${modelAlias}.${field}`).as(field));
|
|
962
|
+
} else {
|
|
963
|
+
return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
buildDelegateJoin(thisModel, otherModel, query) {
|
|
967
|
+
const idFields = getIdFields(this.schema, thisModel);
|
|
968
|
+
query = query.leftJoin(otherModel, (qb) => {
|
|
969
|
+
for (const idField of idFields) {
|
|
970
|
+
qb = qb.onRef(`${thisModel}.${idField}`, "=", `${otherModel}.${idField}`);
|
|
971
|
+
}
|
|
972
|
+
return qb;
|
|
973
|
+
});
|
|
974
|
+
return query;
|
|
975
|
+
}
|
|
976
|
+
// #endregion
|
|
977
|
+
// #region utils
|
|
776
978
|
negateSort(sort, negated) {
|
|
777
979
|
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
778
980
|
}
|
|
@@ -854,7 +1056,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
854
1056
|
const joinTableName = `${parentName}$${relationField}`;
|
|
855
1057
|
let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
|
|
856
1058
|
result = eb.selectFrom(() => {
|
|
857
|
-
let subQuery =
|
|
1059
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
1060
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
858
1061
|
if (payload && typeof payload === "object") {
|
|
859
1062
|
if (payload.where) {
|
|
860
1063
|
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
@@ -901,6 +1104,13 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
901
1104
|
buildRelationObjectArgs(relationModel, relationField, eb, payload, parentName) {
|
|
902
1105
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
903
1106
|
const objArgs = [];
|
|
1107
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1108
|
+
if (descendantModels.length > 0) {
|
|
1109
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1110
|
+
import_kysely2.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1111
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1112
|
+
]).flatMap((v) => v));
|
|
1113
|
+
}
|
|
904
1114
|
if (payload === true || !payload.select) {
|
|
905
1115
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
906
1116
|
import_kysely2.sql.lit(field),
|
|
@@ -993,7 +1203,11 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
993
1203
|
if (Array.isArray(value)) {
|
|
994
1204
|
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
995
1205
|
} else {
|
|
996
|
-
|
|
1206
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1207
|
+
return JSON.stringify(value);
|
|
1208
|
+
} else {
|
|
1209
|
+
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);
|
|
1210
|
+
}
|
|
997
1211
|
}
|
|
998
1212
|
}
|
|
999
1213
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -1005,7 +1219,8 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1005
1219
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
1006
1220
|
const subQueryName = `${parentName}$${relationField}`;
|
|
1007
1221
|
let tbl = eb.selectFrom(() => {
|
|
1008
|
-
let subQuery =
|
|
1222
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
1223
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
1009
1224
|
if (payload && typeof payload === "object") {
|
|
1010
1225
|
if (payload.where) {
|
|
1011
1226
|
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
@@ -1041,6 +1256,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1041
1256
|
});
|
|
1042
1257
|
tbl = tbl.select(() => {
|
|
1043
1258
|
const objArgs = [];
|
|
1259
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1260
|
+
if (descendantModels.length > 0) {
|
|
1261
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1262
|
+
import_kysely3.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1263
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1264
|
+
]).flatMap((v) => v));
|
|
1265
|
+
}
|
|
1044
1266
|
if (payload === true || !payload.select) {
|
|
1045
1267
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
1046
1268
|
import_kysely3.sql.lit(field),
|
|
@@ -1123,85 +1345,6 @@ function getCrudDialect(schema, options) {
|
|
|
1123
1345
|
}
|
|
1124
1346
|
__name(getCrudDialect, "getCrudDialect");
|
|
1125
1347
|
|
|
1126
|
-
// src/schema/expression.ts
|
|
1127
|
-
var ExpressionUtils = {
|
|
1128
|
-
literal: /* @__PURE__ */ __name((value) => {
|
|
1129
|
-
return {
|
|
1130
|
-
kind: "literal",
|
|
1131
|
-
value
|
|
1132
|
-
};
|
|
1133
|
-
}, "literal"),
|
|
1134
|
-
array: /* @__PURE__ */ __name((items) => {
|
|
1135
|
-
return {
|
|
1136
|
-
kind: "array",
|
|
1137
|
-
items
|
|
1138
|
-
};
|
|
1139
|
-
}, "array"),
|
|
1140
|
-
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
1141
|
-
return {
|
|
1142
|
-
kind: "call",
|
|
1143
|
-
function: functionName,
|
|
1144
|
-
args
|
|
1145
|
-
};
|
|
1146
|
-
}, "call"),
|
|
1147
|
-
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
1148
|
-
return {
|
|
1149
|
-
kind: "binary",
|
|
1150
|
-
op,
|
|
1151
|
-
left,
|
|
1152
|
-
right
|
|
1153
|
-
};
|
|
1154
|
-
}, "binary"),
|
|
1155
|
-
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
1156
|
-
return {
|
|
1157
|
-
kind: "unary",
|
|
1158
|
-
op,
|
|
1159
|
-
operand
|
|
1160
|
-
};
|
|
1161
|
-
}, "unary"),
|
|
1162
|
-
field: /* @__PURE__ */ __name((field) => {
|
|
1163
|
-
return {
|
|
1164
|
-
kind: "field",
|
|
1165
|
-
field
|
|
1166
|
-
};
|
|
1167
|
-
}, "field"),
|
|
1168
|
-
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
1169
|
-
return {
|
|
1170
|
-
kind: "member",
|
|
1171
|
-
receiver,
|
|
1172
|
-
members
|
|
1173
|
-
};
|
|
1174
|
-
}, "member"),
|
|
1175
|
-
_this: /* @__PURE__ */ __name(() => {
|
|
1176
|
-
return {
|
|
1177
|
-
kind: "this"
|
|
1178
|
-
};
|
|
1179
|
-
}, "_this"),
|
|
1180
|
-
_null: /* @__PURE__ */ __name(() => {
|
|
1181
|
-
return {
|
|
1182
|
-
kind: "null"
|
|
1183
|
-
};
|
|
1184
|
-
}, "_null"),
|
|
1185
|
-
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1186
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
1187
|
-
}, "and"),
|
|
1188
|
-
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1189
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
1190
|
-
}, "or"),
|
|
1191
|
-
is: /* @__PURE__ */ __name((value, kind) => {
|
|
1192
|
-
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
1193
|
-
}, "is"),
|
|
1194
|
-
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
1195
|
-
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
1196
|
-
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
1197
|
-
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
1198
|
-
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
1199
|
-
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
1200
|
-
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
1201
|
-
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
1202
|
-
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
|
|
1203
|
-
};
|
|
1204
|
-
|
|
1205
1348
|
// src/utils/default-operation-node-visitor.ts
|
|
1206
1349
|
var import_kysely4 = require("kysely");
|
|
1207
1350
|
var DefaultOperationNodeVisitor = class extends import_kysely4.OperationNodeVisitor {
|
|
@@ -2468,10 +2611,10 @@ function clone(value) {
|
|
|
2468
2611
|
__name(clone, "clone");
|
|
2469
2612
|
|
|
2470
2613
|
// src/utils/object-utils.ts
|
|
2471
|
-
function
|
|
2614
|
+
function extractFields2(obj, fields) {
|
|
2472
2615
|
return Object.fromEntries(Object.entries(obj).filter(([key]) => fields.includes(key)));
|
|
2473
2616
|
}
|
|
2474
|
-
__name(
|
|
2617
|
+
__name(extractFields2, "extractFields");
|
|
2475
2618
|
function fieldsToSelectObject(fields) {
|
|
2476
2619
|
return Object.fromEntries(fields.map((f) => [
|
|
2477
2620
|
f,
|
|
@@ -2480,15 +2623,6 @@ function fieldsToSelectObject(fields) {
|
|
|
2480
2623
|
}
|
|
2481
2624
|
__name(fieldsToSelectObject, "fieldsToSelectObject");
|
|
2482
2625
|
|
|
2483
|
-
// src/client/constants.ts
|
|
2484
|
-
var CONTEXT_COMMENT_PREFIX = "-- $$context:";
|
|
2485
|
-
var NUMERIC_FIELD_TYPES = [
|
|
2486
|
-
"Int",
|
|
2487
|
-
"Float",
|
|
2488
|
-
"BigInt",
|
|
2489
|
-
"Decimal"
|
|
2490
|
-
];
|
|
2491
|
-
|
|
2492
2626
|
// src/client/crud/operations/base.ts
|
|
2493
2627
|
var BaseOperationHandler = class {
|
|
2494
2628
|
static {
|
|
@@ -2532,17 +2666,17 @@ var BaseOperationHandler = class {
|
|
|
2532
2666
|
getField(model, field) {
|
|
2533
2667
|
return getField(this.schema, model, field);
|
|
2534
2668
|
}
|
|
2535
|
-
exists(kysely, model, filter) {
|
|
2669
|
+
async exists(kysely, model, filter) {
|
|
2536
2670
|
const idFields = getIdFields(this.schema, model);
|
|
2537
2671
|
const _filter = flattenCompoundUniqueFilters(this.schema, model, filter);
|
|
2538
2672
|
const query = kysely.selectFrom(model).where((eb) => eb.and(_filter)).select(idFields.map((f) => kysely.dynamic.ref(f))).limit(1).modifyEnd(this.makeContextComment({
|
|
2539
2673
|
model,
|
|
2540
2674
|
operation: "read"
|
|
2541
2675
|
}));
|
|
2542
|
-
return
|
|
2676
|
+
return this.executeQueryTakeFirst(kysely, query, "exists");
|
|
2543
2677
|
}
|
|
2544
2678
|
async read(kysely, model, args) {
|
|
2545
|
-
let query =
|
|
2679
|
+
let query = this.dialect.buildSelectModel((0, import_kysely8.expressionBuilder)(), model);
|
|
2546
2680
|
if (args?.where) {
|
|
2547
2681
|
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, args?.where));
|
|
2548
2682
|
}
|
|
@@ -2567,7 +2701,7 @@ var BaseOperationHandler = class {
|
|
|
2567
2701
|
if (args && "select" in args && args.select) {
|
|
2568
2702
|
query = this.buildFieldSelection(model, query, args.select, model);
|
|
2569
2703
|
} else {
|
|
2570
|
-
query = this.
|
|
2704
|
+
query = this.dialect.buildSelectAllFields(model, query, args?.omit);
|
|
2571
2705
|
}
|
|
2572
2706
|
if (args && "include" in args && args.include) {
|
|
2573
2707
|
query = this.buildFieldSelection(model, query, args.include, model);
|
|
@@ -2580,14 +2714,18 @@ var BaseOperationHandler = class {
|
|
|
2580
2714
|
operation: "read"
|
|
2581
2715
|
}));
|
|
2582
2716
|
let result = [];
|
|
2717
|
+
const queryId = {
|
|
2718
|
+
queryId: `zenstack-${(0, import_cuid2.createId)()}`
|
|
2719
|
+
};
|
|
2720
|
+
const compiled = kysely.getExecutor().compileQuery(query.toOperationNode(), queryId);
|
|
2583
2721
|
try {
|
|
2584
|
-
|
|
2722
|
+
const r = await kysely.getExecutor().executeQuery(compiled, queryId);
|
|
2723
|
+
result = r.rows;
|
|
2585
2724
|
} catch (err) {
|
|
2586
|
-
|
|
2587
|
-
let message = `Failed to execute query: ${err}, sql: ${sql11}`;
|
|
2725
|
+
let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
|
|
2588
2726
|
if (this.options.debug) {
|
|
2589
2727
|
message += `, parameters:
|
|
2590
|
-
${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
2728
|
+
${compiled.parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
2591
2729
|
}
|
|
2592
2730
|
throw new QueryError(message, err);
|
|
2593
2731
|
}
|
|
@@ -2624,12 +2762,16 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
2624
2762
|
}
|
|
2625
2763
|
const fieldDef = this.requireField(model, field);
|
|
2626
2764
|
if (!fieldDef.relation) {
|
|
2627
|
-
result = this.
|
|
2765
|
+
result = this.dialect.buildSelectField(result, model, parentAlias, field);
|
|
2628
2766
|
} else {
|
|
2629
2767
|
if (!fieldDef.array && !fieldDef.optional && payload.where) {
|
|
2630
2768
|
throw new QueryError(`Field "${field}" doesn't support filtering`);
|
|
2631
2769
|
}
|
|
2632
|
-
|
|
2770
|
+
if (fieldDef.originModel) {
|
|
2771
|
+
result = this.dialect.buildRelationSelection(result, fieldDef.originModel, field, fieldDef.originModel, payload);
|
|
2772
|
+
} else {
|
|
2773
|
+
result = this.dialect.buildRelationSelection(result, model, field, parentAlias, payload);
|
|
2774
|
+
}
|
|
2633
2775
|
}
|
|
2634
2776
|
}
|
|
2635
2777
|
return result;
|
|
@@ -2662,18 +2804,6 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
2662
2804
|
query = query.select((eb2) => this.dialect.buildJsonObject(eb2, jsonObject).as("_count"));
|
|
2663
2805
|
return query;
|
|
2664
2806
|
}
|
|
2665
|
-
buildSelectAllScalarFields(model, query, omit) {
|
|
2666
|
-
const modelDef = this.requireModel(model);
|
|
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);
|
|
2668
|
-
}
|
|
2669
|
-
selectField(query, model, modelAlias, field) {
|
|
2670
|
-
const fieldDef = this.requireField(model, field);
|
|
2671
|
-
if (!fieldDef.computed) {
|
|
2672
|
-
return query.select(import_kysely8.sql.ref(`${modelAlias}.${field}`).as(field));
|
|
2673
|
-
} else {
|
|
2674
|
-
return query.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(field));
|
|
2675
|
-
}
|
|
2676
|
-
}
|
|
2677
2807
|
buildCursorFilter(model, query, cursor, orderBy, negateOrderBy) {
|
|
2678
2808
|
if (!orderBy) {
|
|
2679
2809
|
orderBy = makeDefaultOrderBy(this.schema, model);
|
|
@@ -2696,9 +2826,12 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
2696
2826
|
result = result.where((eb2) => eb2.or(filters));
|
|
2697
2827
|
return result;
|
|
2698
2828
|
}
|
|
2699
|
-
async create(kysely, model, data, fromRelation) {
|
|
2829
|
+
async create(kysely, model, data, fromRelation, creatingForDelegate = false) {
|
|
2700
2830
|
const modelDef = this.requireModel(model);
|
|
2701
|
-
|
|
2831
|
+
if (modelDef.isDelegate && !creatingForDelegate) {
|
|
2832
|
+
throw new QueryError(`Model "${this.model}" is a delegate and cannot be created directly.`);
|
|
2833
|
+
}
|
|
2834
|
+
let createFields = {};
|
|
2702
2835
|
let parentUpdateTask = void 0;
|
|
2703
2836
|
let m2m = void 0;
|
|
2704
2837
|
if (fromRelation) {
|
|
@@ -2717,7 +2850,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
2717
2850
|
model: fromRelation.model,
|
|
2718
2851
|
operation: "update"
|
|
2719
2852
|
}));
|
|
2720
|
-
return
|
|
2853
|
+
return this.executeQuery(kysely, query2, "update");
|
|
2721
2854
|
}, "parentUpdateTask");
|
|
2722
2855
|
}
|
|
2723
2856
|
}
|
|
@@ -2746,13 +2879,17 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
2746
2879
|
}
|
|
2747
2880
|
}
|
|
2748
2881
|
}
|
|
2882
|
+
if (modelDef.baseModel) {
|
|
2883
|
+
const baseCreateResult = await this.processBaseModelCreate(kysely, modelDef.baseModel, createFields, model);
|
|
2884
|
+
createFields = baseCreateResult.remainingFields;
|
|
2885
|
+
}
|
|
2749
2886
|
const updatedData = this.fillGeneratedValues(modelDef, createFields);
|
|
2750
2887
|
const idFields = getIdFields(this.schema, model);
|
|
2751
|
-
const query = kysely.insertInto(model).values(updatedData).returning(idFields).modifyEnd(this.makeContextComment({
|
|
2888
|
+
const query = kysely.insertInto(model).$if(Object.keys(updatedData).length === 0, (qb) => qb.defaultValues()).$if(Object.keys(updatedData).length > 0, (qb) => qb.values(updatedData)).returning(idFields).modifyEnd(this.makeContextComment({
|
|
2752
2889
|
model,
|
|
2753
2890
|
operation: "create"
|
|
2754
2891
|
}));
|
|
2755
|
-
const createdEntity = await
|
|
2892
|
+
const createdEntity = await this.executeQueryTakeFirst(kysely, query, "create");
|
|
2756
2893
|
if (Object.keys(postCreateRelations).length > 0) {
|
|
2757
2894
|
const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
|
|
2758
2895
|
return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
|
|
@@ -2767,6 +2904,28 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
2767
2904
|
}
|
|
2768
2905
|
return createdEntity;
|
|
2769
2906
|
}
|
|
2907
|
+
async processBaseModelCreate(kysely, model, createFields, forModel) {
|
|
2908
|
+
const thisCreateFields = {};
|
|
2909
|
+
const remainingFields = {};
|
|
2910
|
+
Object.entries(createFields).forEach(([field, value]) => {
|
|
2911
|
+
const fieldDef = this.getField(model, field);
|
|
2912
|
+
if (fieldDef) {
|
|
2913
|
+
thisCreateFields[field] = value;
|
|
2914
|
+
} else {
|
|
2915
|
+
remainingFields[field] = value;
|
|
2916
|
+
}
|
|
2917
|
+
});
|
|
2918
|
+
const discriminatorField = getDiscriminatorField(this.schema, model);
|
|
2919
|
+
(0, import_common_helpers8.invariant)(discriminatorField, `Base model "${model}" must have a discriminator field`);
|
|
2920
|
+
thisCreateFields[discriminatorField] = forModel;
|
|
2921
|
+
const baseEntity = await this.create(kysely, model, thisCreateFields, void 0, true);
|
|
2922
|
+
const idValues = extractIdFields(baseEntity, this.schema, model);
|
|
2923
|
+
Object.assign(remainingFields, idValues);
|
|
2924
|
+
return {
|
|
2925
|
+
baseEntity,
|
|
2926
|
+
remainingFields
|
|
2927
|
+
};
|
|
2928
|
+
}
|
|
2770
2929
|
buildFkAssignments(model, relationField, entity) {
|
|
2771
2930
|
const parentFkFields = {};
|
|
2772
2931
|
(0, import_common_helpers8.invariant)(relationField, "parentField must be defined if parentModel is defined");
|
|
@@ -2841,7 +3000,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
2841
3000
|
case "connect": {
|
|
2842
3001
|
const referencedPkFields = relationField.relation.references;
|
|
2843
3002
|
(0, import_common_helpers8.invariant)(referencedPkFields, "relation must have fields info");
|
|
2844
|
-
const extractedFks =
|
|
3003
|
+
const extractedFks = extractFields2(subPayload, referencedPkFields);
|
|
2845
3004
|
if (Object.keys(extractedFks).length === referencedPkFields.length) {
|
|
2846
3005
|
result = extractedFks;
|
|
2847
3006
|
} else {
|
|
@@ -2936,7 +3095,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
2936
3095
|
}
|
|
2937
3096
|
relationKeyPairs = keyPairs;
|
|
2938
3097
|
}
|
|
2939
|
-
|
|
3098
|
+
let createData = enumerate(input.data).map((item) => {
|
|
2940
3099
|
const newItem = {};
|
|
2941
3100
|
for (const [name, value] of Object.entries(item)) {
|
|
2942
3101
|
const fieldDef = this.requireField(model, name);
|
|
@@ -2950,14 +3109,21 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
2950
3109
|
}
|
|
2951
3110
|
return this.fillGeneratedValues(modelDef, newItem);
|
|
2952
3111
|
});
|
|
3112
|
+
if (modelDef.baseModel) {
|
|
3113
|
+
if (input.skipDuplicates) {
|
|
3114
|
+
throw new QueryError('"skipDuplicates" options is not supported for polymorphic models');
|
|
3115
|
+
}
|
|
3116
|
+
const baseCreateResult = await this.processBaseModelCreateMany(kysely, modelDef.baseModel, createData, !!input.skipDuplicates, model);
|
|
3117
|
+
createData = baseCreateResult.remainingFieldRows;
|
|
3118
|
+
}
|
|
2953
3119
|
const query = kysely.insertInto(model).values(createData).$if(!!input.skipDuplicates, (qb) => qb.onConflict((oc) => oc.doNothing())).modifyEnd(this.makeContextComment({
|
|
2954
3120
|
model,
|
|
2955
3121
|
operation: "create"
|
|
2956
3122
|
}));
|
|
2957
3123
|
if (!returnData) {
|
|
2958
|
-
const result = await
|
|
3124
|
+
const result = await this.executeQuery(kysely, query, "createMany");
|
|
2959
3125
|
return {
|
|
2960
|
-
count: Number(result.
|
|
3126
|
+
count: Number(result.numAffectedRows)
|
|
2961
3127
|
};
|
|
2962
3128
|
} else {
|
|
2963
3129
|
const idFields = getIdFields(this.schema, model);
|
|
@@ -2965,10 +3131,46 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
2965
3131
|
return result;
|
|
2966
3132
|
}
|
|
2967
3133
|
}
|
|
3134
|
+
async processBaseModelCreateMany(kysely, model, createRows, skipDuplicates, forModel) {
|
|
3135
|
+
const thisCreateRows = [];
|
|
3136
|
+
const remainingFieldRows = [];
|
|
3137
|
+
const discriminatorField = getDiscriminatorField(this.schema, model);
|
|
3138
|
+
(0, import_common_helpers8.invariant)(discriminatorField, `Base model "${model}" must have a discriminator field`);
|
|
3139
|
+
for (const createFields of createRows) {
|
|
3140
|
+
const thisCreateFields = {};
|
|
3141
|
+
const remainingFields = {};
|
|
3142
|
+
Object.entries(createFields).forEach(([field, value]) => {
|
|
3143
|
+
const fieldDef = this.getField(model, field);
|
|
3144
|
+
if (fieldDef) {
|
|
3145
|
+
thisCreateFields[field] = value;
|
|
3146
|
+
} else {
|
|
3147
|
+
remainingFields[field] = value;
|
|
3148
|
+
}
|
|
3149
|
+
});
|
|
3150
|
+
thisCreateFields[discriminatorField] = forModel;
|
|
3151
|
+
thisCreateRows.push(thisCreateFields);
|
|
3152
|
+
remainingFieldRows.push(remainingFields);
|
|
3153
|
+
}
|
|
3154
|
+
const baseEntities = await this.createMany(kysely, model, {
|
|
3155
|
+
data: thisCreateRows,
|
|
3156
|
+
skipDuplicates
|
|
3157
|
+
}, true);
|
|
3158
|
+
for (let i = 0; i < baseEntities.length; i++) {
|
|
3159
|
+
const idValues = extractIdFields(baseEntities[i], this.schema, model);
|
|
3160
|
+
Object.assign(remainingFieldRows[i], idValues);
|
|
3161
|
+
}
|
|
3162
|
+
return {
|
|
3163
|
+
baseEntities,
|
|
3164
|
+
remainingFieldRows
|
|
3165
|
+
};
|
|
3166
|
+
}
|
|
2968
3167
|
fillGeneratedValues(modelDef, data) {
|
|
2969
3168
|
const fields = modelDef.fields;
|
|
2970
3169
|
const values = clone(data);
|
|
2971
|
-
for (const field
|
|
3170
|
+
for (const [field, fieldDef] of Object.entries(fields)) {
|
|
3171
|
+
if (fieldDef.originModel) {
|
|
3172
|
+
continue;
|
|
3173
|
+
}
|
|
2972
3174
|
if (!(field in data)) {
|
|
2973
3175
|
if (typeof fields[field]?.default === "object" && "kind" in fields[field].default) {
|
|
2974
3176
|
const generated = this.evalGenerator(fields[field].default);
|
|
@@ -3045,28 +3247,33 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3045
3247
|
}
|
|
3046
3248
|
}
|
|
3047
3249
|
if (Object.keys(finalData).length === 0) {
|
|
3048
|
-
|
|
3049
|
-
|
|
3250
|
+
return combinedWhere;
|
|
3251
|
+
}
|
|
3252
|
+
let needIdRead = false;
|
|
3253
|
+
if (modelDef.baseModel && !this.isIdFilter(model, combinedWhere)) {
|
|
3254
|
+
needIdRead = true;
|
|
3255
|
+
}
|
|
3256
|
+
if (needIdRead) {
|
|
3257
|
+
const readResult = await this.readUnique(kysely, model, {
|
|
3258
|
+
where: combinedWhere,
|
|
3259
|
+
select: this.makeIdSelect(model)
|
|
3050
3260
|
});
|
|
3051
|
-
if (!
|
|
3261
|
+
if (!readResult && throwIfNotFound) {
|
|
3052
3262
|
throw new NotFoundError(model);
|
|
3053
3263
|
}
|
|
3054
|
-
|
|
3264
|
+
combinedWhere = readResult;
|
|
3265
|
+
}
|
|
3266
|
+
if (modelDef.baseModel) {
|
|
3267
|
+
const baseUpdateResult = await this.processBaseModelUpdate(kysely, modelDef.baseModel, combinedWhere, finalData, throwIfNotFound);
|
|
3268
|
+
finalData = baseUpdateResult.remainingFields;
|
|
3269
|
+
combinedWhere = baseUpdateResult.baseEntity;
|
|
3055
3270
|
}
|
|
3056
3271
|
const updateFields = {};
|
|
3057
3272
|
let thisEntity = void 0;
|
|
3058
3273
|
for (const field in finalData) {
|
|
3059
3274
|
const fieldDef = this.requireField(model, field);
|
|
3060
3275
|
if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
|
|
3061
|
-
|
|
3062
|
-
updateFields[field] = this.transformIncrementalUpdate(model, field, fieldDef, finalData[field]);
|
|
3063
|
-
continue;
|
|
3064
|
-
}
|
|
3065
|
-
if (fieldDef.array && typeof finalData[field] === "object" && !Array.isArray(finalData[field]) && finalData[field]) {
|
|
3066
|
-
updateFields[field] = this.transformScalarListUpdate(model, field, fieldDef, finalData[field]);
|
|
3067
|
-
continue;
|
|
3068
|
-
}
|
|
3069
|
-
updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type, !!fieldDef.array);
|
|
3276
|
+
updateFields[field] = this.processScalarFieldUpdateData(model, field, finalData);
|
|
3070
3277
|
} else {
|
|
3071
3278
|
if (!allowRelationUpdate) {
|
|
3072
3279
|
throw new QueryError(`Relation update not allowed for field "${field}"`);
|
|
@@ -3088,16 +3295,14 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3088
3295
|
}
|
|
3089
3296
|
}
|
|
3090
3297
|
if (Object.keys(updateFields).length === 0) {
|
|
3091
|
-
return
|
|
3092
|
-
where: combinedWhere
|
|
3093
|
-
});
|
|
3298
|
+
return combinedWhere;
|
|
3094
3299
|
} else {
|
|
3095
3300
|
const idFields = getIdFields(this.schema, model);
|
|
3096
3301
|
const query = kysely.updateTable(model).where((eb) => this.dialect.buildFilter(eb, model, model, combinedWhere)).set(updateFields).returning(idFields).modifyEnd(this.makeContextComment({
|
|
3097
3302
|
model,
|
|
3098
3303
|
operation: "update"
|
|
3099
3304
|
}));
|
|
3100
|
-
const updatedEntity = await
|
|
3305
|
+
const updatedEntity = await this.executeQueryTakeFirst(kysely, query, "update");
|
|
3101
3306
|
if (!updatedEntity) {
|
|
3102
3307
|
if (throwIfNotFound) {
|
|
3103
3308
|
throw new NotFoundError(model);
|
|
@@ -3108,6 +3313,55 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3108
3313
|
return updatedEntity;
|
|
3109
3314
|
}
|
|
3110
3315
|
}
|
|
3316
|
+
processScalarFieldUpdateData(model, field, data) {
|
|
3317
|
+
const fieldDef = this.requireField(model, field);
|
|
3318
|
+
if (this.isNumericIncrementalUpdate(fieldDef, data[field])) {
|
|
3319
|
+
return this.transformIncrementalUpdate(model, field, fieldDef, data[field]);
|
|
3320
|
+
}
|
|
3321
|
+
if (fieldDef.array && typeof data[field] === "object" && !Array.isArray(data[field]) && data[field]) {
|
|
3322
|
+
return this.transformScalarListUpdate(model, field, fieldDef, data[field]);
|
|
3323
|
+
}
|
|
3324
|
+
return this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
|
|
3325
|
+
}
|
|
3326
|
+
isNumericIncrementalUpdate(fieldDef, value) {
|
|
3327
|
+
if (!this.isNumericField(fieldDef)) {
|
|
3328
|
+
return false;
|
|
3329
|
+
}
|
|
3330
|
+
if (typeof value !== "object" || !value) {
|
|
3331
|
+
return false;
|
|
3332
|
+
}
|
|
3333
|
+
return [
|
|
3334
|
+
"increment",
|
|
3335
|
+
"decrement",
|
|
3336
|
+
"multiply",
|
|
3337
|
+
"divide",
|
|
3338
|
+
"set"
|
|
3339
|
+
].some((key) => key in value);
|
|
3340
|
+
}
|
|
3341
|
+
isIdFilter(model, filter) {
|
|
3342
|
+
if (!filter || typeof filter !== "object") {
|
|
3343
|
+
return false;
|
|
3344
|
+
}
|
|
3345
|
+
const idFields = getIdFields(this.schema, model);
|
|
3346
|
+
return idFields.length === Object.keys(filter).length && idFields.every((field) => field in filter);
|
|
3347
|
+
}
|
|
3348
|
+
async processBaseModelUpdate(kysely, model, where, updateFields, throwIfNotFound) {
|
|
3349
|
+
const thisUpdateFields = {};
|
|
3350
|
+
const remainingFields = {};
|
|
3351
|
+
Object.entries(updateFields).forEach(([field, value]) => {
|
|
3352
|
+
const fieldDef = this.getField(model, field);
|
|
3353
|
+
if (fieldDef) {
|
|
3354
|
+
thisUpdateFields[field] = value;
|
|
3355
|
+
} else {
|
|
3356
|
+
remainingFields[field] = value;
|
|
3357
|
+
}
|
|
3358
|
+
});
|
|
3359
|
+
const baseEntity = await this.update(kysely, model, where, thisUpdateFields, void 0, void 0, throwIfNotFound);
|
|
3360
|
+
return {
|
|
3361
|
+
baseEntity,
|
|
3362
|
+
remainingFields
|
|
3363
|
+
};
|
|
3364
|
+
}
|
|
3111
3365
|
transformIncrementalUpdate(model, field, fieldDef, payload) {
|
|
3112
3366
|
(0, import_common_helpers8.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
|
|
3113
3367
|
const key = Object.keys(payload)[0];
|
|
@@ -3136,7 +3390,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3136
3390
|
makeContextComment(context) {
|
|
3137
3391
|
return import_kysely8.sql.raw(`${CONTEXT_COMMENT_PREFIX}${JSON.stringify(context)}`);
|
|
3138
3392
|
}
|
|
3139
|
-
async updateMany(kysely, model, where, data, limit, returnData) {
|
|
3393
|
+
async updateMany(kysely, model, where, data, limit, returnData, filterModel) {
|
|
3140
3394
|
if (typeof data !== "object") {
|
|
3141
3395
|
throw new InternalError("data must be an object");
|
|
3142
3396
|
}
|
|
@@ -3145,34 +3399,52 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3145
3399
|
count: 0
|
|
3146
3400
|
};
|
|
3147
3401
|
}
|
|
3148
|
-
const
|
|
3402
|
+
const modelDef = this.requireModel(model);
|
|
3403
|
+
if (modelDef.baseModel && limit !== void 0) {
|
|
3404
|
+
throw new QueryError("Updating with a limit is not supported for polymorphic models");
|
|
3405
|
+
}
|
|
3406
|
+
filterModel ??= model;
|
|
3407
|
+
let updateFields = {};
|
|
3149
3408
|
for (const field in data) {
|
|
3150
|
-
const fieldDef = this.requireField(model, field);
|
|
3151
3409
|
if (isRelationField(this.schema, model, field)) {
|
|
3152
3410
|
continue;
|
|
3153
3411
|
}
|
|
3154
|
-
updateFields[field] = this.
|
|
3412
|
+
updateFields[field] = this.processScalarFieldUpdateData(model, field, data);
|
|
3413
|
+
}
|
|
3414
|
+
let shouldFallbackToIdFilter = false;
|
|
3415
|
+
if (limit !== void 0 && !this.dialect.supportsUpdateWithLimit) {
|
|
3416
|
+
shouldFallbackToIdFilter = true;
|
|
3417
|
+
}
|
|
3418
|
+
if (modelDef.isDelegate || modelDef.baseModel) {
|
|
3419
|
+
shouldFallbackToIdFilter = true;
|
|
3420
|
+
}
|
|
3421
|
+
let resultFromBaseModel = void 0;
|
|
3422
|
+
if (modelDef.baseModel) {
|
|
3423
|
+
const baseResult = await this.processBaseModelUpdateMany(kysely, modelDef.baseModel, where, updateFields, filterModel);
|
|
3424
|
+
updateFields = baseResult.remainingFields;
|
|
3425
|
+
resultFromBaseModel = baseResult.baseResult;
|
|
3426
|
+
}
|
|
3427
|
+
if (Object.keys(updateFields).length === 0) {
|
|
3428
|
+
return resultFromBaseModel ?? (returnData ? [] : {
|
|
3429
|
+
count: 0
|
|
3430
|
+
});
|
|
3155
3431
|
}
|
|
3156
3432
|
let query = kysely.updateTable(model).set(updateFields);
|
|
3157
|
-
if (
|
|
3158
|
-
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
|
|
3433
|
+
if (!shouldFallbackToIdFilter) {
|
|
3434
|
+
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where)).$if(limit !== void 0, (qb) => qb.limit(limit));
|
|
3159
3435
|
} else {
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
query = query.where((eb) => eb(eb.refTuple(
|
|
3164
|
-
...this.buildIdFieldRefs(kysely, model)
|
|
3165
|
-
), "in", kysely.selectFrom(model).where((eb2) => this.dialect.buildFilter(eb2, model, model, where)).select(this.buildIdFieldRefs(kysely, model)).limit(limit)));
|
|
3166
|
-
}
|
|
3436
|
+
query = query.where((eb) => eb(eb.refTuple(
|
|
3437
|
+
...this.buildIdFieldRefs(kysely, model)
|
|
3438
|
+
), "in", this.dialect.buildSelectModel(eb, filterModel).where(this.dialect.buildFilter(eb, filterModel, filterModel, where)).select(this.buildIdFieldRefs(kysely, filterModel)).$if(limit !== void 0, (qb) => qb.limit(limit))));
|
|
3167
3439
|
}
|
|
3168
3440
|
query = query.modifyEnd(this.makeContextComment({
|
|
3169
3441
|
model,
|
|
3170
3442
|
operation: "update"
|
|
3171
3443
|
}));
|
|
3172
3444
|
if (!returnData) {
|
|
3173
|
-
const result = await
|
|
3445
|
+
const result = await this.executeQuery(kysely, query, "update");
|
|
3174
3446
|
return {
|
|
3175
|
-
count: Number(result.
|
|
3447
|
+
count: Number(result.numAffectedRows)
|
|
3176
3448
|
};
|
|
3177
3449
|
} else {
|
|
3178
3450
|
const idFields = getIdFields(this.schema, model);
|
|
@@ -3180,9 +3452,26 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3180
3452
|
return result;
|
|
3181
3453
|
}
|
|
3182
3454
|
}
|
|
3455
|
+
async processBaseModelUpdateMany(kysely, model, where, updateFields, filterModel) {
|
|
3456
|
+
const thisUpdateFields = {};
|
|
3457
|
+
const remainingFields = {};
|
|
3458
|
+
Object.entries(updateFields).forEach(([field, value]) => {
|
|
3459
|
+
const fieldDef = this.getField(model, field);
|
|
3460
|
+
if (fieldDef) {
|
|
3461
|
+
thisUpdateFields[field] = value;
|
|
3462
|
+
} else {
|
|
3463
|
+
remainingFields[field] = value;
|
|
3464
|
+
}
|
|
3465
|
+
});
|
|
3466
|
+
const baseResult = await this.updateMany(kysely, model, where, thisUpdateFields, void 0, false, filterModel);
|
|
3467
|
+
return {
|
|
3468
|
+
baseResult,
|
|
3469
|
+
remainingFields
|
|
3470
|
+
};
|
|
3471
|
+
}
|
|
3183
3472
|
buildIdFieldRefs(kysely, model) {
|
|
3184
3473
|
const idFields = getIdFields(this.schema, model);
|
|
3185
|
-
return idFields.map((f) => kysely.dynamic.ref(f));
|
|
3474
|
+
return idFields.map((f) => kysely.dynamic.ref(`${model}.${f}`));
|
|
3186
3475
|
}
|
|
3187
3476
|
async processRelationUpdates(kysely, model, field, fieldDef, parentIds, args, throwIfNotFound) {
|
|
3188
3477
|
const tasks = [];
|
|
@@ -3300,7 +3589,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3300
3589
|
model: fromRelation.model,
|
|
3301
3590
|
operation: "update"
|
|
3302
3591
|
}));
|
|
3303
|
-
updateResult = await
|
|
3592
|
+
updateResult = await this.executeQuery(kysely, query, "connect");
|
|
3304
3593
|
} else {
|
|
3305
3594
|
const relationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3306
3595
|
if (!relationFieldDef.array) {
|
|
@@ -3311,7 +3600,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3311
3600
|
model: fromRelation.model,
|
|
3312
3601
|
operation: "update"
|
|
3313
3602
|
}));
|
|
3314
|
-
await
|
|
3603
|
+
await this.executeQuery(kysely, query2, "disconnect");
|
|
3315
3604
|
}
|
|
3316
3605
|
const query = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
|
|
3317
3606
|
...acc,
|
|
@@ -3320,9 +3609,9 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3320
3609
|
model,
|
|
3321
3610
|
operation: "update"
|
|
3322
3611
|
}));
|
|
3323
|
-
updateResult = await
|
|
3612
|
+
updateResult = await this.executeQuery(kysely, query, "connect");
|
|
3324
3613
|
}
|
|
3325
|
-
if (_data.length > updateResult.
|
|
3614
|
+
if (_data.length > updateResult.numAffectedRows) {
|
|
3326
3615
|
throw new NotFoundError(model);
|
|
3327
3616
|
}
|
|
3328
3617
|
}
|
|
@@ -3390,7 +3679,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3390
3679
|
model: fromRelation.model,
|
|
3391
3680
|
operation: "update"
|
|
3392
3681
|
}));
|
|
3393
|
-
await
|
|
3682
|
+
await this.executeQuery(kysely, query, "disconnect");
|
|
3394
3683
|
} else {
|
|
3395
3684
|
const query = kysely.updateTable(model).where(eb.and([
|
|
3396
3685
|
// fk filter
|
|
@@ -3407,7 +3696,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3407
3696
|
model,
|
|
3408
3697
|
operation: "update"
|
|
3409
3698
|
}));
|
|
3410
|
-
await
|
|
3699
|
+
await this.executeQuery(kysely, query, "disconnect");
|
|
3411
3700
|
}
|
|
3412
3701
|
}
|
|
3413
3702
|
}
|
|
@@ -3445,7 +3734,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3445
3734
|
model,
|
|
3446
3735
|
operation: "update"
|
|
3447
3736
|
}));
|
|
3448
|
-
await
|
|
3737
|
+
await this.executeQuery(kysely, query, "disconnect");
|
|
3449
3738
|
if (_data.length > 0) {
|
|
3450
3739
|
const query2 = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
|
|
3451
3740
|
...acc,
|
|
@@ -3454,8 +3743,8 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3454
3743
|
model,
|
|
3455
3744
|
operation: "update"
|
|
3456
3745
|
}));
|
|
3457
|
-
const r = await
|
|
3458
|
-
if (_data.length > r.
|
|
3746
|
+
const r = await this.executeQuery(kysely, query2, "connect");
|
|
3747
|
+
if (_data.length > r.numAffectedRows) {
|
|
3459
3748
|
throw new NotFoundError(model);
|
|
3460
3749
|
}
|
|
3461
3750
|
}
|
|
@@ -3496,7 +3785,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3496
3785
|
OR: deleteConditions
|
|
3497
3786
|
}
|
|
3498
3787
|
]
|
|
3499
|
-
}
|
|
3788
|
+
});
|
|
3500
3789
|
} else {
|
|
3501
3790
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3502
3791
|
if (ownedByModel) {
|
|
@@ -3519,7 +3808,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3519
3808
|
OR: deleteConditions
|
|
3520
3809
|
}
|
|
3521
3810
|
]
|
|
3522
|
-
}
|
|
3811
|
+
});
|
|
3523
3812
|
} else {
|
|
3524
3813
|
deleteResult = await this.delete(kysely, model, {
|
|
3525
3814
|
AND: [
|
|
@@ -3531,7 +3820,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3531
3820
|
OR: deleteConditions
|
|
3532
3821
|
}
|
|
3533
3822
|
]
|
|
3534
|
-
}
|
|
3823
|
+
});
|
|
3535
3824
|
}
|
|
3536
3825
|
}
|
|
3537
3826
|
if (throwForNotFound && expectedDeleteCount > deleteResult.count) {
|
|
@@ -3542,33 +3831,59 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3542
3831
|
return enumerate(data).map((item) => flattenCompoundUniqueFilters(this.schema, model, item));
|
|
3543
3832
|
}
|
|
3544
3833
|
// #endregion
|
|
3545
|
-
async delete(kysely, model, where, limit,
|
|
3834
|
+
async delete(kysely, model, where, limit, filterModel) {
|
|
3835
|
+
filterModel ??= model;
|
|
3836
|
+
const modelDef = this.requireModel(model);
|
|
3837
|
+
if (modelDef.baseModel) {
|
|
3838
|
+
if (limit !== void 0) {
|
|
3839
|
+
throw new QueryError("Deleting with a limit is not supported for polymorphic models");
|
|
3840
|
+
}
|
|
3841
|
+
return this.processBaseModelDelete(kysely, modelDef.baseModel, where, limit, filterModel);
|
|
3842
|
+
}
|
|
3546
3843
|
let query = kysely.deleteFrom(model);
|
|
3547
|
-
|
|
3844
|
+
let needIdFilter = false;
|
|
3845
|
+
if (limit !== void 0 && !this.dialect.supportsDeleteWithLimit) {
|
|
3846
|
+
needIdFilter = true;
|
|
3847
|
+
}
|
|
3848
|
+
if (modelDef.isDelegate || modelDef.baseModel) {
|
|
3849
|
+
needIdFilter = true;
|
|
3850
|
+
}
|
|
3851
|
+
if (!needIdFilter) {
|
|
3548
3852
|
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
|
|
3549
3853
|
} else {
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
query = query.where((eb) => eb(eb.refTuple(
|
|
3554
|
-
...this.buildIdFieldRefs(kysely, model)
|
|
3555
|
-
), "in", kysely.selectFrom(model).where((eb2) => this.dialect.buildFilter(eb2, model, model, where)).select(this.buildIdFieldRefs(kysely, model)).limit(limit)));
|
|
3556
|
-
}
|
|
3854
|
+
query = query.where((eb) => eb(eb.refTuple(
|
|
3855
|
+
...this.buildIdFieldRefs(kysely, model)
|
|
3856
|
+
), "in", this.dialect.buildSelectModel(eb, filterModel).where((eb2) => this.dialect.buildFilter(eb2, filterModel, filterModel, where)).select(this.buildIdFieldRefs(kysely, filterModel)).$if(limit !== void 0, (qb) => qb.limit(limit))));
|
|
3557
3857
|
}
|
|
3858
|
+
await this.processDelegateRelationDelete(kysely, modelDef, where, limit);
|
|
3558
3859
|
query = query.modifyEnd(this.makeContextComment({
|
|
3559
3860
|
model,
|
|
3560
3861
|
operation: "delete"
|
|
3561
3862
|
}));
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
}
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3863
|
+
const result = await this.executeQuery(kysely, query, "delete");
|
|
3864
|
+
return {
|
|
3865
|
+
count: Number(result.numAffectedRows)
|
|
3866
|
+
};
|
|
3867
|
+
}
|
|
3868
|
+
async processDelegateRelationDelete(kysely, modelDef, where, limit) {
|
|
3869
|
+
for (const fieldDef of Object.values(modelDef.fields)) {
|
|
3870
|
+
if (fieldDef.relation && fieldDef.relation.opposite) {
|
|
3871
|
+
const oppositeModelDef = this.requireModel(fieldDef.type);
|
|
3872
|
+
const oppositeRelation = this.requireField(fieldDef.type, fieldDef.relation.opposite);
|
|
3873
|
+
if (oppositeModelDef.baseModel && oppositeRelation.relation?.onDelete === "Cascade") {
|
|
3874
|
+
if (limit !== void 0) {
|
|
3875
|
+
throw new QueryError("Deleting with a limit is not supported for polymorphic models");
|
|
3876
|
+
}
|
|
3877
|
+
await this.delete(kysely, fieldDef.type, {
|
|
3878
|
+
[fieldDef.relation.opposite]: where
|
|
3879
|
+
}, void 0);
|
|
3880
|
+
}
|
|
3881
|
+
}
|
|
3570
3882
|
}
|
|
3571
3883
|
}
|
|
3884
|
+
async processBaseModelDelete(kysely, model, where, limit, filterModel) {
|
|
3885
|
+
return this.delete(kysely, model, where, limit, filterModel);
|
|
3886
|
+
}
|
|
3572
3887
|
makeIdSelect(model) {
|
|
3573
3888
|
const modelDef = this.requireModel(model);
|
|
3574
3889
|
return modelDef.idFields.reduce((acc, f) => {
|
|
@@ -3602,9 +3917,7 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3602
3917
|
return callback(this.kysely);
|
|
3603
3918
|
} else {
|
|
3604
3919
|
let txBuilder = this.kysely.transaction();
|
|
3605
|
-
|
|
3606
|
-
txBuilder = txBuilder.setIsolationLevel(isolationLevel);
|
|
3607
|
-
}
|
|
3920
|
+
txBuilder = txBuilder.setIsolationLevel(isolationLevel ?? "repeatable read");
|
|
3608
3921
|
return txBuilder.execute(callback);
|
|
3609
3922
|
}
|
|
3610
3923
|
}
|
|
@@ -3646,6 +3959,25 @@ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
|
|
|
3646
3959
|
}
|
|
3647
3960
|
}
|
|
3648
3961
|
}
|
|
3962
|
+
makeQueryId(operation) {
|
|
3963
|
+
return {
|
|
3964
|
+
queryId: `${operation}-${(0, import_cuid2.createId)()}`
|
|
3965
|
+
};
|
|
3966
|
+
}
|
|
3967
|
+
executeQuery(kysely, query, operation) {
|
|
3968
|
+
return kysely.executeQuery(query.compile(), this.makeQueryId(operation));
|
|
3969
|
+
}
|
|
3970
|
+
async executeQueryTakeFirst(kysely, query, operation) {
|
|
3971
|
+
const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
|
|
3972
|
+
return result.rows[0];
|
|
3973
|
+
}
|
|
3974
|
+
async executeQueryTakeFirstOrThrow(kysely, query, operation) {
|
|
3975
|
+
const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
|
|
3976
|
+
if (result.rows.length === 0) {
|
|
3977
|
+
throw new QueryError("No rows found");
|
|
3978
|
+
}
|
|
3979
|
+
return result.rows[0];
|
|
3980
|
+
}
|
|
3649
3981
|
};
|
|
3650
3982
|
|
|
3651
3983
|
// src/client/crud/operations/aggregate.ts
|
|
@@ -3657,7 +3989,22 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3657
3989
|
const normalizedArgs = this.normalizeArgs(args);
|
|
3658
3990
|
const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
|
|
3659
3991
|
let query = this.kysely.selectFrom((eb) => {
|
|
3660
|
-
let subQuery =
|
|
3992
|
+
let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
3993
|
+
const selectedFields = [];
|
|
3994
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3995
|
+
if (key.startsWith("_") && value && typeof value === "object") {
|
|
3996
|
+
Object.entries(value).filter(([field]) => field !== "_all").filter(([, val]) => val === true).forEach(([field]) => {
|
|
3997
|
+
if (!selectedFields.includes(field)) selectedFields.push(field);
|
|
3998
|
+
});
|
|
3999
|
+
}
|
|
4000
|
+
}
|
|
4001
|
+
if (selectedFields.length > 0) {
|
|
4002
|
+
for (const field of selectedFields) {
|
|
4003
|
+
subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, field);
|
|
4004
|
+
}
|
|
4005
|
+
} else {
|
|
4006
|
+
subQuery = subQuery.select(() => eb.lit(1).as("_all"));
|
|
4007
|
+
}
|
|
3661
4008
|
const skip = parsedArgs?.skip;
|
|
3662
4009
|
let take = parsedArgs?.take;
|
|
3663
4010
|
let negateOrderBy = false;
|
|
@@ -3703,9 +4050,9 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3703
4050
|
}
|
|
3704
4051
|
}
|
|
3705
4052
|
}
|
|
3706
|
-
const result = await
|
|
4053
|
+
const result = await this.executeQuery(this.kysely, query, "aggregate");
|
|
3707
4054
|
const ret = {};
|
|
3708
|
-
for (const [key, value] of Object.entries(result)) {
|
|
4055
|
+
for (const [key, value] of Object.entries(result.rows[0])) {
|
|
3709
4056
|
if (key === "_count") {
|
|
3710
4057
|
ret[key] = value;
|
|
3711
4058
|
continue;
|
|
@@ -3750,18 +4097,29 @@ var CountOperationHandler = class extends BaseOperationHandler {
|
|
|
3750
4097
|
async handle(_operation, args) {
|
|
3751
4098
|
const normalizedArgs = this.normalizeArgs(args);
|
|
3752
4099
|
const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
|
|
4100
|
+
const subQueryName = "$sub";
|
|
3753
4101
|
let query = this.kysely.selectFrom((eb) => {
|
|
3754
|
-
let subQuery =
|
|
4102
|
+
let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
4103
|
+
if (parsedArgs?.select && typeof parsedArgs.select === "object") {
|
|
4104
|
+
for (const [key, value] of Object.entries(parsedArgs.select)) {
|
|
4105
|
+
if (key !== "_all" && value === true) {
|
|
4106
|
+
subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, key);
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
} else {
|
|
4110
|
+
subQuery = subQuery.select(() => eb.lit(1).as("_all"));
|
|
4111
|
+
}
|
|
3755
4112
|
subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
|
|
3756
|
-
return subQuery.as(
|
|
4113
|
+
return subQuery.as(subQueryName);
|
|
3757
4114
|
});
|
|
3758
4115
|
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(`$
|
|
3760
|
-
|
|
4116
|
+
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(`${subQueryName}.${key}`)), "integer").as(key)));
|
|
4117
|
+
const result = await this.executeQuery(this.kysely, query, "count");
|
|
4118
|
+
return result.rows[0];
|
|
3761
4119
|
} else {
|
|
3762
4120
|
query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
|
|
3763
|
-
const result = await
|
|
3764
|
-
return result.count;
|
|
4121
|
+
const result = await this.executeQuery(this.kysely, query, "count");
|
|
4122
|
+
return result.rows[0].count;
|
|
3765
4123
|
}
|
|
3766
4124
|
}
|
|
3767
4125
|
};
|
|
@@ -3840,15 +4198,19 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
|
3840
4198
|
if (!existing) {
|
|
3841
4199
|
throw new NotFoundError(this.model);
|
|
3842
4200
|
}
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
4201
|
+
await this.safeTransaction(async (tx) => {
|
|
4202
|
+
const result = await this.delete(tx, this.model, args.where);
|
|
4203
|
+
if (result.count === 0) {
|
|
4204
|
+
throw new NotFoundError(this.model);
|
|
4205
|
+
}
|
|
4206
|
+
});
|
|
3847
4207
|
return existing;
|
|
3848
4208
|
}
|
|
3849
4209
|
async runDeleteMany(args) {
|
|
3850
|
-
|
|
3851
|
-
|
|
4210
|
+
return await this.safeTransaction(async (tx) => {
|
|
4211
|
+
const result = await this.delete(tx, this.model, args?.where, args?.limit);
|
|
4212
|
+
return result;
|
|
4213
|
+
});
|
|
3852
4214
|
}
|
|
3853
4215
|
};
|
|
3854
4216
|
|
|
@@ -3936,8 +4298,8 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
|
|
|
3936
4298
|
}
|
|
3937
4299
|
}
|
|
3938
4300
|
}
|
|
3939
|
-
const result = await
|
|
3940
|
-
return result.map((row) => this.postProcessRow(row));
|
|
4301
|
+
const result = await this.executeQuery(this.kysely, query, "groupBy");
|
|
4302
|
+
return result.rows.map((row) => this.postProcessRow(row));
|
|
3941
4303
|
}
|
|
3942
4304
|
postProcessRow(row) {
|
|
3943
4305
|
const ret = {};
|
|
@@ -3989,22 +4351,35 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3989
4351
|
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();
|
|
3990
4352
|
}
|
|
3991
4353
|
async runUpdate(args) {
|
|
3992
|
-
const
|
|
3993
|
-
const
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4354
|
+
const readBackResult = await this.safeTransaction(async (tx) => {
|
|
4355
|
+
const updateResult = await this.update(tx, this.model, args.where, args.data);
|
|
4356
|
+
const readFilter = updateResult ?? args.where;
|
|
4357
|
+
let readBackResult2 = void 0;
|
|
4358
|
+
try {
|
|
4359
|
+
readBackResult2 = await this.readUnique(tx, this.model, {
|
|
4360
|
+
select: args.select,
|
|
4361
|
+
include: args.include,
|
|
4362
|
+
omit: args.omit,
|
|
4363
|
+
where: readFilter
|
|
4364
|
+
});
|
|
4365
|
+
} catch {
|
|
4366
|
+
}
|
|
4367
|
+
return readBackResult2;
|
|
4000
4368
|
});
|
|
4001
|
-
if (!
|
|
4002
|
-
|
|
4369
|
+
if (!readBackResult) {
|
|
4370
|
+
if (this.hasPolicyEnabled) {
|
|
4371
|
+
throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
|
|
4372
|
+
} else {
|
|
4373
|
+
return null;
|
|
4374
|
+
}
|
|
4375
|
+
} else {
|
|
4376
|
+
return readBackResult;
|
|
4003
4377
|
}
|
|
4004
|
-
return result;
|
|
4005
4378
|
}
|
|
4006
4379
|
async runUpdateMany(args) {
|
|
4007
|
-
return this.
|
|
4380
|
+
return this.safeTransaction(async (tx) => {
|
|
4381
|
+
return this.updateMany(tx, this.model, args.where, args.data, args.limit, false);
|
|
4382
|
+
});
|
|
4008
4383
|
}
|
|
4009
4384
|
async runUpdateManyAndReturn(args) {
|
|
4010
4385
|
if (!args) {
|
|
@@ -4143,17 +4518,45 @@ var InputValidator = class {
|
|
|
4143
4518
|
return result;
|
|
4144
4519
|
}
|
|
4145
4520
|
makePrimitiveSchema(type) {
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
import_zod.z.
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4521
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
4522
|
+
return this.makeTypeDefSchema(type);
|
|
4523
|
+
} else {
|
|
4524
|
+
return (0, import_ts_pattern14.match)(type).with("String", () => import_zod.z.string()).with("Int", () => import_zod.z.number()).with("Float", () => import_zod.z.number()).with("Boolean", () => import_zod.z.boolean()).with("BigInt", () => import_zod.z.union([
|
|
4525
|
+
import_zod.z.number(),
|
|
4526
|
+
import_zod.z.bigint()
|
|
4527
|
+
])).with("Decimal", () => import_zod.z.union([
|
|
4528
|
+
import_zod.z.number(),
|
|
4529
|
+
import_zod.z.instanceof(import_decimal.default),
|
|
4530
|
+
import_zod.z.string()
|
|
4531
|
+
])).with("DateTime", () => import_zod.z.union([
|
|
4532
|
+
import_zod.z.date(),
|
|
4533
|
+
import_zod.z.string().datetime()
|
|
4534
|
+
])).with("Bytes", () => import_zod.z.instanceof(Uint8Array)).otherwise(() => import_zod.z.unknown());
|
|
4535
|
+
}
|
|
4536
|
+
}
|
|
4537
|
+
makeTypeDefSchema(type) {
|
|
4538
|
+
const key = `$typedef-${type}`;
|
|
4539
|
+
let schema = this.schemaCache.get(key);
|
|
4540
|
+
if (schema) {
|
|
4541
|
+
return schema;
|
|
4542
|
+
}
|
|
4543
|
+
const typeDef = this.schema.typeDefs?.[type];
|
|
4544
|
+
(0, import_common_helpers9.invariant)(typeDef, `Type definition "${type}" not found in schema`);
|
|
4545
|
+
schema = import_zod.z.looseObject(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
|
|
4546
|
+
let fieldSchema = this.makePrimitiveSchema(def.type);
|
|
4547
|
+
if (def.array) {
|
|
4548
|
+
fieldSchema = fieldSchema.array();
|
|
4549
|
+
}
|
|
4550
|
+
if (def.optional) {
|
|
4551
|
+
fieldSchema = fieldSchema.optional();
|
|
4552
|
+
}
|
|
4553
|
+
return [
|
|
4554
|
+
field,
|
|
4555
|
+
fieldSchema
|
|
4556
|
+
];
|
|
4557
|
+
})));
|
|
4558
|
+
this.schemaCache.set(key, schema);
|
|
4559
|
+
return schema;
|
|
4157
4560
|
}
|
|
4158
4561
|
makeWhereSchema(model, unique, withoutRelationFields = false) {
|
|
4159
4562
|
const modelDef = getModel(this.schema, model);
|
|
@@ -4275,8 +4678,14 @@ var InputValidator = class {
|
|
|
4275
4678
|
});
|
|
4276
4679
|
}
|
|
4277
4680
|
makePrimitiveFilterSchema(type, optional) {
|
|
4681
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
4682
|
+
return this.makeTypeDefFilterSchema(type, optional);
|
|
4683
|
+
}
|
|
4278
4684
|
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();
|
|
4279
4685
|
}
|
|
4686
|
+
makeTypeDefFilterSchema(_type, _optional) {
|
|
4687
|
+
return import_zod.z.never();
|
|
4688
|
+
}
|
|
4280
4689
|
makeDateTimeFilterSchema(optional) {
|
|
4281
4690
|
return this.makeCommonPrimitiveFilterSchema(import_zod.z.union([
|
|
4282
4691
|
import_zod.z.string().datetime(),
|
|
@@ -4481,6 +4890,9 @@ var InputValidator = class {
|
|
|
4481
4890
|
if (fieldDef.computed) {
|
|
4482
4891
|
return;
|
|
4483
4892
|
}
|
|
4893
|
+
if (this.isDelegateDiscriminator(fieldDef)) {
|
|
4894
|
+
return;
|
|
4895
|
+
}
|
|
4484
4896
|
if (fieldDef.relation) {
|
|
4485
4897
|
if (withoutRelationFields) {
|
|
4486
4898
|
return;
|
|
@@ -4553,6 +4965,13 @@ var InputValidator = class {
|
|
|
4553
4965
|
]);
|
|
4554
4966
|
}
|
|
4555
4967
|
}
|
|
4968
|
+
isDelegateDiscriminator(fieldDef) {
|
|
4969
|
+
if (!fieldDef.originModel) {
|
|
4970
|
+
return false;
|
|
4971
|
+
}
|
|
4972
|
+
const discriminatorField = getDiscriminatorField(this.schema, fieldDef.originModel);
|
|
4973
|
+
return discriminatorField === fieldDef.name;
|
|
4974
|
+
}
|
|
4556
4975
|
makeRelationManipulationSchema(fieldDef, withoutFields, mode) {
|
|
4557
4976
|
const fieldType = fieldDef.type;
|
|
4558
4977
|
const array = !!fieldDef.array;
|
|
@@ -4883,11 +5302,11 @@ var ZenStackDriver = class {
|
|
|
4883
5302
|
}
|
|
4884
5303
|
#driver;
|
|
4885
5304
|
#log;
|
|
4886
|
-
txConnection;
|
|
4887
5305
|
#initPromise;
|
|
4888
5306
|
#initDone;
|
|
4889
5307
|
#destroyPromise;
|
|
4890
5308
|
#connections = /* @__PURE__ */ new WeakSet();
|
|
5309
|
+
#txConnections = /* @__PURE__ */ new WeakMap();
|
|
4891
5310
|
constructor(driver, log) {
|
|
4892
5311
|
this.#initDone = false;
|
|
4893
5312
|
this.#driver = driver;
|
|
@@ -4928,21 +5347,30 @@ var ZenStackDriver = class {
|
|
|
4928
5347
|
}
|
|
4929
5348
|
async beginTransaction(connection, settings) {
|
|
4930
5349
|
const result = await this.#driver.beginTransaction(connection, settings);
|
|
4931
|
-
this.
|
|
5350
|
+
this.#txConnections.set(connection, []);
|
|
4932
5351
|
return result;
|
|
4933
5352
|
}
|
|
4934
|
-
commitTransaction(connection) {
|
|
5353
|
+
async commitTransaction(connection) {
|
|
4935
5354
|
try {
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
this.
|
|
5355
|
+
const result = await this.#driver.commitTransaction(connection);
|
|
5356
|
+
const callbacks = this.#txConnections.get(connection);
|
|
5357
|
+
this.#txConnections.delete(connection);
|
|
5358
|
+
if (callbacks) {
|
|
5359
|
+
for (const callback of callbacks) {
|
|
5360
|
+
await callback();
|
|
5361
|
+
}
|
|
5362
|
+
}
|
|
5363
|
+
return result;
|
|
5364
|
+
} catch (err) {
|
|
5365
|
+
this.#txConnections.delete(connection);
|
|
5366
|
+
throw err;
|
|
4939
5367
|
}
|
|
4940
5368
|
}
|
|
4941
|
-
rollbackTransaction(connection) {
|
|
5369
|
+
async rollbackTransaction(connection) {
|
|
4942
5370
|
try {
|
|
4943
|
-
return this.#driver.rollbackTransaction(connection);
|
|
5371
|
+
return await this.#driver.rollbackTransaction(connection);
|
|
4944
5372
|
} finally {
|
|
4945
|
-
this.
|
|
5373
|
+
this.#txConnections.delete(connection);
|
|
4946
5374
|
}
|
|
4947
5375
|
}
|
|
4948
5376
|
async destroy() {
|
|
@@ -5020,6 +5448,22 @@ var ZenStackDriver = class {
|
|
|
5020
5448
|
#calculateDurationMillis(startTime) {
|
|
5021
5449
|
return performanceNow() - startTime;
|
|
5022
5450
|
}
|
|
5451
|
+
isTransactionConnection(connection) {
|
|
5452
|
+
return this.#txConnections.has(connection);
|
|
5453
|
+
}
|
|
5454
|
+
registerTransactionCommitCallback(connection, callback) {
|
|
5455
|
+
if (!this.#txConnections.has(connection)) {
|
|
5456
|
+
return;
|
|
5457
|
+
}
|
|
5458
|
+
const callbacks = this.#txConnections.get(connection);
|
|
5459
|
+
if (callbacks) {
|
|
5460
|
+
callbacks.push(callback);
|
|
5461
|
+
} else {
|
|
5462
|
+
this.#txConnections.set(connection, [
|
|
5463
|
+
callback
|
|
5464
|
+
]);
|
|
5465
|
+
}
|
|
5466
|
+
}
|
|
5023
5467
|
};
|
|
5024
5468
|
function performanceNow() {
|
|
5025
5469
|
if (typeof performance !== "undefined" && typeof performance.now === "function") {
|
|
@@ -5236,7 +5680,7 @@ var QueryNameMapper = class extends import_kysely12.OperationNodeTransformer {
|
|
|
5236
5680
|
this.requireCurrentModel(contextNode);
|
|
5237
5681
|
model = model ?? this.currentModel;
|
|
5238
5682
|
const modelDef = requireModel(this.schema, model);
|
|
5239
|
-
const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed).map(([fieldName]) => fieldName);
|
|
5683
|
+
const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed && !fieldDef.originModel).map(([fieldName]) => fieldName);
|
|
5240
5684
|
return scalarFields;
|
|
5241
5685
|
}
|
|
5242
5686
|
};
|
|
@@ -5261,7 +5705,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5261
5705
|
get options() {
|
|
5262
5706
|
return this.client.$options;
|
|
5263
5707
|
}
|
|
5264
|
-
async executeQuery(compiledQuery,
|
|
5708
|
+
async executeQuery(compiledQuery, _queryId) {
|
|
5265
5709
|
let queryNode = compiledQuery.query;
|
|
5266
5710
|
let mutationInterceptionInfo;
|
|
5267
5711
|
if (this.isMutationNode(queryNode) && this.hasMutationHooks) {
|
|
@@ -5272,7 +5716,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5272
5716
|
await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
|
|
5273
5717
|
}
|
|
5274
5718
|
const oldQueryNode = queryNode;
|
|
5275
|
-
if ((import_kysely13.InsertQueryNode.is(queryNode) || import_kysely13.
|
|
5719
|
+
if ((import_kysely13.InsertQueryNode.is(queryNode) || import_kysely13.UpdateQueryNode.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
|
|
5276
5720
|
queryNode = {
|
|
5277
5721
|
...queryNode,
|
|
5278
5722
|
returning: import_kysely13.ReturningNode.create([
|
|
@@ -5281,34 +5725,49 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5281
5725
|
};
|
|
5282
5726
|
}
|
|
5283
5727
|
const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
|
|
5284
|
-
const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams
|
|
5728
|
+
const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams);
|
|
5285
5729
|
if (this.isMutationNode(queryNode)) {
|
|
5286
|
-
await this.
|
|
5730
|
+
await this.callAfterMutationHooks(result.result, queryNode, mutationInterceptionInfo, result.connection);
|
|
5287
5731
|
}
|
|
5288
5732
|
if (oldQueryNode !== queryNode) {
|
|
5289
5733
|
}
|
|
5290
|
-
return result;
|
|
5734
|
+
return result.result;
|
|
5291
5735
|
}, "task");
|
|
5292
5736
|
return task();
|
|
5293
5737
|
}
|
|
5294
|
-
proceedQueryWithKyselyInterceptors(queryNode, parameters
|
|
5295
|
-
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters
|
|
5296
|
-
const hooks =
|
|
5738
|
+
proceedQueryWithKyselyInterceptors(queryNode, parameters) {
|
|
5739
|
+
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters), "proceed");
|
|
5740
|
+
const hooks = [];
|
|
5741
|
+
for (const plugin of this.client.$options.plugins ?? []) {
|
|
5742
|
+
if (plugin.onKyselyQuery) {
|
|
5743
|
+
hooks.push(plugin.onKyselyQuery.bind(plugin));
|
|
5744
|
+
}
|
|
5745
|
+
}
|
|
5297
5746
|
for (const hook of hooks) {
|
|
5298
5747
|
const _proceed = proceed;
|
|
5299
|
-
proceed = /* @__PURE__ */ __name((query) => {
|
|
5300
|
-
|
|
5748
|
+
proceed = /* @__PURE__ */ __name(async (query) => {
|
|
5749
|
+
let connection;
|
|
5750
|
+
const _p = /* @__PURE__ */ __name(async (q) => {
|
|
5751
|
+
const r = await _proceed(q);
|
|
5752
|
+
connection = r.connection;
|
|
5753
|
+
return r.result;
|
|
5754
|
+
}, "_p");
|
|
5755
|
+
const hookResult = await hook({
|
|
5301
5756
|
client: this.client,
|
|
5302
5757
|
schema: this.client.$schema,
|
|
5303
5758
|
kysely: this.kysely,
|
|
5304
5759
|
query,
|
|
5305
|
-
proceed:
|
|
5760
|
+
proceed: _p
|
|
5306
5761
|
});
|
|
5762
|
+
return {
|
|
5763
|
+
result: hookResult,
|
|
5764
|
+
connection
|
|
5765
|
+
};
|
|
5307
5766
|
}, "proceed");
|
|
5308
5767
|
}
|
|
5309
5768
|
return proceed(queryNode);
|
|
5310
5769
|
}
|
|
5311
|
-
async proceedQuery(query, parameters
|
|
5770
|
+
async proceedQuery(query, parameters) {
|
|
5312
5771
|
const finalQuery = this.nameMapper.transformNode(query);
|
|
5313
5772
|
let compiled = this.compileQuery(finalQuery);
|
|
5314
5773
|
if (parameters) {
|
|
@@ -5318,7 +5777,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
|
|
|
5318
5777
|
};
|
|
5319
5778
|
}
|
|
5320
5779
|
try {
|
|
5321
|
-
return await
|
|
5780
|
+
return await this.provideConnection(async (connection) => {
|
|
5781
|
+
const result = await connection.executeQuery(compiled);
|
|
5782
|
+
return {
|
|
5783
|
+
result,
|
|
5784
|
+
connection
|
|
5785
|
+
};
|
|
5786
|
+
});
|
|
5322
5787
|
} catch (err) {
|
|
5323
5788
|
let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
|
|
5324
5789
|
if (this.options.debug) {
|
|
@@ -5421,10 +5886,11 @@ ${compiled.parameters.map((p) => (0, import_node_util2.inspect)(p)).join("\n")}`
|
|
|
5421
5886
|
return;
|
|
5422
5887
|
}
|
|
5423
5888
|
if (this.options.plugins) {
|
|
5889
|
+
const mutationModel = this.getMutationModel(queryNode);
|
|
5424
5890
|
for (const plugin of this.options.plugins) {
|
|
5425
5891
|
if (plugin.beforeEntityMutation) {
|
|
5426
5892
|
await plugin.beforeEntityMutation({
|
|
5427
|
-
model:
|
|
5893
|
+
model: mutationModel,
|
|
5428
5894
|
action: mutationInterceptionInfo.action,
|
|
5429
5895
|
queryNode,
|
|
5430
5896
|
entities: mutationInterceptionInfo.beforeMutationEntities
|
|
@@ -5433,30 +5899,45 @@ ${compiled.parameters.map((p) => (0, import_node_util2.inspect)(p)).join("\n")}`
|
|
|
5433
5899
|
}
|
|
5434
5900
|
}
|
|
5435
5901
|
}
|
|
5436
|
-
async
|
|
5902
|
+
async callAfterMutationHooks(queryResult, queryNode, mutationInterceptionInfo, connection) {
|
|
5437
5903
|
if (!mutationInterceptionInfo?.intercept) {
|
|
5438
5904
|
return;
|
|
5439
5905
|
}
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5906
|
+
const hooks = [];
|
|
5907
|
+
for (const plugin of this.options.plugins ?? []) {
|
|
5908
|
+
if (plugin.afterEntityMutation) {
|
|
5909
|
+
hooks.push(plugin.afterEntityMutation.bind(plugin));
|
|
5910
|
+
}
|
|
5911
|
+
}
|
|
5912
|
+
if (hooks.length === 0) {
|
|
5913
|
+
return;
|
|
5914
|
+
}
|
|
5915
|
+
const mutationModel = this.getMutationModel(queryNode);
|
|
5916
|
+
const inTransaction = this.driver.isTransactionConnection(connection);
|
|
5917
|
+
for (const hook of hooks) {
|
|
5918
|
+
let afterMutationEntities = void 0;
|
|
5919
|
+
if (mutationInterceptionInfo.loadAfterMutationEntity) {
|
|
5920
|
+
if (import_kysely13.InsertQueryNode.is(queryNode) || import_kysely13.UpdateQueryNode.is(queryNode)) {
|
|
5921
|
+
afterMutationEntities = queryResult.rows;
|
|
5922
|
+
}
|
|
5923
|
+
}
|
|
5924
|
+
const action = /* @__PURE__ */ __name(async () => {
|
|
5925
|
+
try {
|
|
5926
|
+
await hook({
|
|
5927
|
+
model: mutationModel,
|
|
5454
5928
|
action: mutationInterceptionInfo.action,
|
|
5455
5929
|
queryNode,
|
|
5456
5930
|
beforeMutationEntities: mutationInterceptionInfo.beforeMutationEntities,
|
|
5457
5931
|
afterMutationEntities
|
|
5458
5932
|
});
|
|
5933
|
+
} catch (err) {
|
|
5934
|
+
console.error(`Error in afterEntityMutation hook for model "${mutationModel}": ${err}`);
|
|
5459
5935
|
}
|
|
5936
|
+
}, "action");
|
|
5937
|
+
if (inTransaction) {
|
|
5938
|
+
this.driver.registerTransactionCommitCallback(connection, action);
|
|
5939
|
+
} else {
|
|
5940
|
+
await action();
|
|
5460
5941
|
}
|
|
5461
5942
|
}
|
|
5462
5943
|
}
|
|
@@ -5653,7 +6134,7 @@ var SchemaDbPusher = class {
|
|
|
5653
6134
|
}
|
|
5654
6135
|
}
|
|
5655
6136
|
table = this.addPrimaryKeyConstraint(table, model, modelDef);
|
|
5656
|
-
table = this.addUniqueConstraint(table, modelDef);
|
|
6137
|
+
table = this.addUniqueConstraint(table, model, modelDef);
|
|
5657
6138
|
return table;
|
|
5658
6139
|
}
|
|
5659
6140
|
isComputedField(fieldDef) {
|
|
@@ -5670,7 +6151,7 @@ var SchemaDbPusher = class {
|
|
|
5670
6151
|
}
|
|
5671
6152
|
return table;
|
|
5672
6153
|
}
|
|
5673
|
-
addUniqueConstraint(table, modelDef) {
|
|
6154
|
+
addUniqueConstraint(table, model, modelDef) {
|
|
5674
6155
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
5675
6156
|
(0, import_common_helpers11.invariant)(typeof value === "object", "expecting an object");
|
|
5676
6157
|
if ("type" in value) {
|
|
@@ -5678,8 +6159,11 @@ var SchemaDbPusher = class {
|
|
|
5678
6159
|
if (fieldDef.unique) {
|
|
5679
6160
|
continue;
|
|
5680
6161
|
}
|
|
6162
|
+
table = table.addUniqueConstraint(`unique_${model}_${key}`, [
|
|
6163
|
+
key
|
|
6164
|
+
]);
|
|
5681
6165
|
} else {
|
|
5682
|
-
table = table.addUniqueConstraint(`unique_${key}`, Object.keys(value));
|
|
6166
|
+
table = table.addUniqueConstraint(`unique_${model}_${key}`, Object.keys(value));
|
|
5683
6167
|
}
|
|
5684
6168
|
}
|
|
5685
6169
|
return table;
|
|
@@ -5822,6 +6306,21 @@ var ResultProcessor = class {
|
|
|
5822
6306
|
data[key] = typeof value === "string" ? JSON.parse(value) : value;
|
|
5823
6307
|
continue;
|
|
5824
6308
|
}
|
|
6309
|
+
if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
|
|
6310
|
+
if (value) {
|
|
6311
|
+
const subRow = this.transformJson(value);
|
|
6312
|
+
const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
|
|
6313
|
+
const idValues = getIdValues(this.schema, subModel, subRow);
|
|
6314
|
+
if (Object.values(idValues).some((v) => v === null || v === void 0)) {
|
|
6315
|
+
delete data[key];
|
|
6316
|
+
continue;
|
|
6317
|
+
}
|
|
6318
|
+
const processedSubRow = this.processRow(subRow, subModel);
|
|
6319
|
+
Object.assign(data, processedSubRow);
|
|
6320
|
+
}
|
|
6321
|
+
delete data[key];
|
|
6322
|
+
continue;
|
|
6323
|
+
}
|
|
5825
6324
|
const fieldDef = getField(this.schema, model, key);
|
|
5826
6325
|
if (!fieldDef) {
|
|
5827
6326
|
continue;
|
|
@@ -5861,7 +6360,11 @@ var ResultProcessor = class {
|
|
|
5861
6360
|
return this.doProcessResult(relationData, fieldDef.type);
|
|
5862
6361
|
}
|
|
5863
6362
|
transformScalar(value, type) {
|
|
5864
|
-
|
|
6363
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
6364
|
+
return this.transformJson(value);
|
|
6365
|
+
} else {
|
|
6366
|
+
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);
|
|
6367
|
+
}
|
|
5865
6368
|
}
|
|
5866
6369
|
transformDecimal(value) {
|
|
5867
6370
|
if (value instanceof import_decimal2.default) {
|
|
@@ -6073,19 +6576,26 @@ var ClientImpl = class _ClientImpl {
|
|
|
6073
6576
|
await new SchemaDbPusher(this.schema, this.kysely).push();
|
|
6074
6577
|
}
|
|
6075
6578
|
$use(plugin) {
|
|
6579
|
+
const newPlugins = [
|
|
6580
|
+
...this.$options.plugins ?? [],
|
|
6581
|
+
plugin
|
|
6582
|
+
];
|
|
6076
6583
|
const newOptions = {
|
|
6077
6584
|
...this.options,
|
|
6078
|
-
plugins:
|
|
6079
|
-
...this.options.plugins ?? [],
|
|
6080
|
-
plugin
|
|
6081
|
-
]
|
|
6585
|
+
plugins: newPlugins
|
|
6082
6586
|
};
|
|
6083
6587
|
return new _ClientImpl(this.schema, newOptions, this);
|
|
6084
6588
|
}
|
|
6085
6589
|
$unuse(pluginId) {
|
|
6590
|
+
const newPlugins = [];
|
|
6591
|
+
for (const plugin of this.options.plugins ?? []) {
|
|
6592
|
+
if (plugin.id !== pluginId) {
|
|
6593
|
+
newPlugins.push(plugin);
|
|
6594
|
+
}
|
|
6595
|
+
}
|
|
6086
6596
|
const newOptions = {
|
|
6087
6597
|
...this.options,
|
|
6088
|
-
plugins:
|
|
6598
|
+
plugins: newPlugins
|
|
6089
6599
|
};
|
|
6090
6600
|
return new _ClientImpl(this.schema, newOptions, this);
|
|
6091
6601
|
}
|