@zenstackhq/runtime 3.0.0-alpha.11 → 3.0.0-alpha.13
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-BQGRBbOU.d.cts → contract-CBOBlAuw.d.cts} +82 -51
- package/dist/{contract-BQGRBbOU.d.ts → contract-CBOBlAuw.d.ts} +82 -51
- package/dist/index.cjs +664 -243
- 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 +664 -243
- 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 {
|
|
@@ -2542,7 +2676,7 @@ var BaseOperationHandler = class {
|
|
|
2542
2676
|
return query.executeTakeFirst();
|
|
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) {
|
|
@@ -2746,9 +2879,13 @@ ${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
|
}));
|
|
@@ -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,6 +3109,13 @@ ${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"
|
|
@@ -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,9 +3295,7 @@ ${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({
|
|
@@ -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,25 +3399,43 @@ ${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,
|
|
@@ -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 = [];
|
|
@@ -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 query.executeTakeFirstOrThrow();
|
|
3864
|
+
return {
|
|
3865
|
+
count: Number(result.numDeletedRows)
|
|
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
|
}
|
|
@@ -3657,7 +3970,22 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3657
3970
|
const normalizedArgs = this.normalizeArgs(args);
|
|
3658
3971
|
const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
|
|
3659
3972
|
let query = this.kysely.selectFrom((eb) => {
|
|
3660
|
-
let subQuery =
|
|
3973
|
+
let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
3974
|
+
const selectedFields = [];
|
|
3975
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3976
|
+
if (key.startsWith("_") && value && typeof value === "object") {
|
|
3977
|
+
Object.entries(value).filter(([field]) => field !== "_all").filter(([, val]) => val === true).forEach(([field]) => {
|
|
3978
|
+
if (!selectedFields.includes(field)) selectedFields.push(field);
|
|
3979
|
+
});
|
|
3980
|
+
}
|
|
3981
|
+
}
|
|
3982
|
+
if (selectedFields.length > 0) {
|
|
3983
|
+
for (const field of selectedFields) {
|
|
3984
|
+
subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, field);
|
|
3985
|
+
}
|
|
3986
|
+
} else {
|
|
3987
|
+
subQuery = subQuery.select(() => eb.lit(1).as("_all"));
|
|
3988
|
+
}
|
|
3661
3989
|
const skip = parsedArgs?.skip;
|
|
3662
3990
|
let take = parsedArgs?.take;
|
|
3663
3991
|
let negateOrderBy = false;
|
|
@@ -3750,13 +4078,23 @@ var CountOperationHandler = class extends BaseOperationHandler {
|
|
|
3750
4078
|
async handle(_operation, args) {
|
|
3751
4079
|
const normalizedArgs = this.normalizeArgs(args);
|
|
3752
4080
|
const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
|
|
4081
|
+
const subQueryName = "$sub";
|
|
3753
4082
|
let query = this.kysely.selectFrom((eb) => {
|
|
3754
|
-
let subQuery =
|
|
4083
|
+
let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
4084
|
+
if (parsedArgs?.select && typeof parsedArgs.select === "object") {
|
|
4085
|
+
for (const [key, value] of Object.entries(parsedArgs.select)) {
|
|
4086
|
+
if (key !== "_all" && value === true) {
|
|
4087
|
+
subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, key);
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
4090
|
+
} else {
|
|
4091
|
+
subQuery = subQuery.select(() => eb.lit(1).as("_all"));
|
|
4092
|
+
}
|
|
3755
4093
|
subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
|
|
3756
|
-
return subQuery.as(
|
|
4094
|
+
return subQuery.as(subQueryName);
|
|
3757
4095
|
});
|
|
3758
4096
|
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(`$
|
|
4097
|
+
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)));
|
|
3760
4098
|
return query.executeTakeFirstOrThrow();
|
|
3761
4099
|
} else {
|
|
3762
4100
|
query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
|
|
@@ -3840,15 +4178,19 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
|
3840
4178
|
if (!existing) {
|
|
3841
4179
|
throw new NotFoundError(this.model);
|
|
3842
4180
|
}
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
4181
|
+
await this.safeTransaction(async (tx) => {
|
|
4182
|
+
const result = await this.delete(tx, this.model, args.where, void 0);
|
|
4183
|
+
if (result.count === 0) {
|
|
4184
|
+
throw new NotFoundError(this.model);
|
|
4185
|
+
}
|
|
4186
|
+
});
|
|
3847
4187
|
return existing;
|
|
3848
4188
|
}
|
|
3849
4189
|
async runDeleteMany(args) {
|
|
3850
|
-
|
|
3851
|
-
|
|
4190
|
+
return await this.safeTransaction(async (tx) => {
|
|
4191
|
+
const result = await this.delete(tx, this.model, args?.where, args?.limit);
|
|
4192
|
+
return result;
|
|
4193
|
+
});
|
|
3852
4194
|
}
|
|
3853
4195
|
};
|
|
3854
4196
|
|
|
@@ -3989,22 +4331,35 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3989
4331
|
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
4332
|
}
|
|
3991
4333
|
async runUpdate(args) {
|
|
3992
|
-
const
|
|
3993
|
-
const
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4334
|
+
const readBackResult = await this.safeTransaction(async (tx) => {
|
|
4335
|
+
const updateResult = await this.update(tx, this.model, args.where, args.data);
|
|
4336
|
+
const readFilter = updateResult ?? args.where;
|
|
4337
|
+
let readBackResult2 = void 0;
|
|
4338
|
+
try {
|
|
4339
|
+
readBackResult2 = await this.readUnique(tx, this.model, {
|
|
4340
|
+
select: args.select,
|
|
4341
|
+
include: args.include,
|
|
4342
|
+
omit: args.omit,
|
|
4343
|
+
where: readFilter
|
|
4344
|
+
});
|
|
4345
|
+
} catch {
|
|
4346
|
+
}
|
|
4347
|
+
return readBackResult2;
|
|
4000
4348
|
});
|
|
4001
|
-
if (!
|
|
4002
|
-
|
|
4349
|
+
if (!readBackResult) {
|
|
4350
|
+
if (this.hasPolicyEnabled) {
|
|
4351
|
+
throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
|
|
4352
|
+
} else {
|
|
4353
|
+
return null;
|
|
4354
|
+
}
|
|
4355
|
+
} else {
|
|
4356
|
+
return readBackResult;
|
|
4003
4357
|
}
|
|
4004
|
-
return result;
|
|
4005
4358
|
}
|
|
4006
4359
|
async runUpdateMany(args) {
|
|
4007
|
-
return this.
|
|
4360
|
+
return this.safeTransaction(async (tx) => {
|
|
4361
|
+
return this.updateMany(tx, this.model, args.where, args.data, args.limit, false);
|
|
4362
|
+
});
|
|
4008
4363
|
}
|
|
4009
4364
|
async runUpdateManyAndReturn(args) {
|
|
4010
4365
|
if (!args) {
|
|
@@ -4143,17 +4498,45 @@ var InputValidator = class {
|
|
|
4143
4498
|
return result;
|
|
4144
4499
|
}
|
|
4145
4500
|
makePrimitiveSchema(type) {
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
import_zod.z.
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4501
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
4502
|
+
return this.makeTypeDefSchema(type);
|
|
4503
|
+
} else {
|
|
4504
|
+
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([
|
|
4505
|
+
import_zod.z.number(),
|
|
4506
|
+
import_zod.z.bigint()
|
|
4507
|
+
])).with("Decimal", () => import_zod.z.union([
|
|
4508
|
+
import_zod.z.number(),
|
|
4509
|
+
import_zod.z.instanceof(import_decimal.default),
|
|
4510
|
+
import_zod.z.string()
|
|
4511
|
+
])).with("DateTime", () => import_zod.z.union([
|
|
4512
|
+
import_zod.z.date(),
|
|
4513
|
+
import_zod.z.string().datetime()
|
|
4514
|
+
])).with("Bytes", () => import_zod.z.instanceof(Uint8Array)).otherwise(() => import_zod.z.unknown());
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
makeTypeDefSchema(type) {
|
|
4518
|
+
const key = `$typedef-${type}`;
|
|
4519
|
+
let schema = this.schemaCache.get(key);
|
|
4520
|
+
if (schema) {
|
|
4521
|
+
return schema;
|
|
4522
|
+
}
|
|
4523
|
+
const typeDef = this.schema.typeDefs?.[type];
|
|
4524
|
+
(0, import_common_helpers9.invariant)(typeDef, `Type definition "${type}" not found in schema`);
|
|
4525
|
+
schema = import_zod.z.looseObject(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
|
|
4526
|
+
let fieldSchema = this.makePrimitiveSchema(def.type);
|
|
4527
|
+
if (def.array) {
|
|
4528
|
+
fieldSchema = fieldSchema.array();
|
|
4529
|
+
}
|
|
4530
|
+
if (def.optional) {
|
|
4531
|
+
fieldSchema = fieldSchema.optional();
|
|
4532
|
+
}
|
|
4533
|
+
return [
|
|
4534
|
+
field,
|
|
4535
|
+
fieldSchema
|
|
4536
|
+
];
|
|
4537
|
+
})));
|
|
4538
|
+
this.schemaCache.set(key, schema);
|
|
4539
|
+
return schema;
|
|
4157
4540
|
}
|
|
4158
4541
|
makeWhereSchema(model, unique, withoutRelationFields = false) {
|
|
4159
4542
|
const modelDef = getModel(this.schema, model);
|
|
@@ -4275,8 +4658,14 @@ var InputValidator = class {
|
|
|
4275
4658
|
});
|
|
4276
4659
|
}
|
|
4277
4660
|
makePrimitiveFilterSchema(type, optional) {
|
|
4661
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
4662
|
+
return this.makeTypeDefFilterSchema(type, optional);
|
|
4663
|
+
}
|
|
4278
4664
|
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
4665
|
}
|
|
4666
|
+
makeTypeDefFilterSchema(_type, _optional) {
|
|
4667
|
+
return import_zod.z.never();
|
|
4668
|
+
}
|
|
4280
4669
|
makeDateTimeFilterSchema(optional) {
|
|
4281
4670
|
return this.makeCommonPrimitiveFilterSchema(import_zod.z.union([
|
|
4282
4671
|
import_zod.z.string().datetime(),
|
|
@@ -4481,6 +4870,9 @@ var InputValidator = class {
|
|
|
4481
4870
|
if (fieldDef.computed) {
|
|
4482
4871
|
return;
|
|
4483
4872
|
}
|
|
4873
|
+
if (this.isDelegateDiscriminator(fieldDef)) {
|
|
4874
|
+
return;
|
|
4875
|
+
}
|
|
4484
4876
|
if (fieldDef.relation) {
|
|
4485
4877
|
if (withoutRelationFields) {
|
|
4486
4878
|
return;
|
|
@@ -4553,6 +4945,13 @@ var InputValidator = class {
|
|
|
4553
4945
|
]);
|
|
4554
4946
|
}
|
|
4555
4947
|
}
|
|
4948
|
+
isDelegateDiscriminator(fieldDef) {
|
|
4949
|
+
if (!fieldDef.originModel) {
|
|
4950
|
+
return false;
|
|
4951
|
+
}
|
|
4952
|
+
const discriminatorField = getDiscriminatorField(this.schema, fieldDef.originModel);
|
|
4953
|
+
return discriminatorField === fieldDef.name;
|
|
4954
|
+
}
|
|
4556
4955
|
makeRelationManipulationSchema(fieldDef, withoutFields, mode) {
|
|
4557
4956
|
const fieldType = fieldDef.type;
|
|
4558
4957
|
const array = !!fieldDef.array;
|
|
@@ -5236,7 +5635,7 @@ var QueryNameMapper = class extends import_kysely12.OperationNodeTransformer {
|
|
|
5236
5635
|
this.requireCurrentModel(contextNode);
|
|
5237
5636
|
model = model ?? this.currentModel;
|
|
5238
5637
|
const modelDef = requireModel(this.schema, model);
|
|
5239
|
-
const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed).map(([fieldName]) => fieldName);
|
|
5638
|
+
const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed && !fieldDef.originModel).map(([fieldName]) => fieldName);
|
|
5240
5639
|
return scalarFields;
|
|
5241
5640
|
}
|
|
5242
5641
|
};
|
|
@@ -5653,7 +6052,7 @@ var SchemaDbPusher = class {
|
|
|
5653
6052
|
}
|
|
5654
6053
|
}
|
|
5655
6054
|
table = this.addPrimaryKeyConstraint(table, model, modelDef);
|
|
5656
|
-
table = this.addUniqueConstraint(table, modelDef);
|
|
6055
|
+
table = this.addUniqueConstraint(table, model, modelDef);
|
|
5657
6056
|
return table;
|
|
5658
6057
|
}
|
|
5659
6058
|
isComputedField(fieldDef) {
|
|
@@ -5670,7 +6069,7 @@ var SchemaDbPusher = class {
|
|
|
5670
6069
|
}
|
|
5671
6070
|
return table;
|
|
5672
6071
|
}
|
|
5673
|
-
addUniqueConstraint(table, modelDef) {
|
|
6072
|
+
addUniqueConstraint(table, model, modelDef) {
|
|
5674
6073
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
5675
6074
|
(0, import_common_helpers11.invariant)(typeof value === "object", "expecting an object");
|
|
5676
6075
|
if ("type" in value) {
|
|
@@ -5678,8 +6077,11 @@ var SchemaDbPusher = class {
|
|
|
5678
6077
|
if (fieldDef.unique) {
|
|
5679
6078
|
continue;
|
|
5680
6079
|
}
|
|
6080
|
+
table = table.addUniqueConstraint(`unique_${model}_${key}`, [
|
|
6081
|
+
key
|
|
6082
|
+
]);
|
|
5681
6083
|
} else {
|
|
5682
|
-
table = table.addUniqueConstraint(`unique_${key}`, Object.keys(value));
|
|
6084
|
+
table = table.addUniqueConstraint(`unique_${model}_${key}`, Object.keys(value));
|
|
5683
6085
|
}
|
|
5684
6086
|
}
|
|
5685
6087
|
return table;
|
|
@@ -5822,6 +6224,21 @@ var ResultProcessor = class {
|
|
|
5822
6224
|
data[key] = typeof value === "string" ? JSON.parse(value) : value;
|
|
5823
6225
|
continue;
|
|
5824
6226
|
}
|
|
6227
|
+
if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
|
|
6228
|
+
if (value) {
|
|
6229
|
+
const subRow = this.transformJson(value);
|
|
6230
|
+
const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
|
|
6231
|
+
const idValues = getIdValues(this.schema, subModel, subRow);
|
|
6232
|
+
if (Object.values(idValues).some((v) => v === null || v === void 0)) {
|
|
6233
|
+
delete data[key];
|
|
6234
|
+
continue;
|
|
6235
|
+
}
|
|
6236
|
+
const processedSubRow = this.processRow(subRow, subModel);
|
|
6237
|
+
Object.assign(data, processedSubRow);
|
|
6238
|
+
}
|
|
6239
|
+
delete data[key];
|
|
6240
|
+
continue;
|
|
6241
|
+
}
|
|
5825
6242
|
const fieldDef = getField(this.schema, model, key);
|
|
5826
6243
|
if (!fieldDef) {
|
|
5827
6244
|
continue;
|
|
@@ -5861,7 +6278,11 @@ var ResultProcessor = class {
|
|
|
5861
6278
|
return this.doProcessResult(relationData, fieldDef.type);
|
|
5862
6279
|
}
|
|
5863
6280
|
transformScalar(value, type) {
|
|
5864
|
-
|
|
6281
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
6282
|
+
return this.transformJson(value);
|
|
6283
|
+
} else {
|
|
6284
|
+
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);
|
|
6285
|
+
}
|
|
5865
6286
|
}
|
|
5866
6287
|
transformDecimal(value) {
|
|
5867
6288
|
if (value instanceof import_decimal2.default) {
|