@zenstackhq/runtime 3.0.0-alpha.2 → 3.0.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{contract-DguafRNB.d.cts → contract-D8U59Syb.d.cts} +971 -785
- package/dist/{contract-DguafRNB.d.ts → contract-D8U59Syb.d.ts} +971 -785
- package/dist/{utils/pg-utils.cjs → helpers.cjs} +8 -16
- package/dist/helpers.cjs.map +1 -0
- package/dist/helpers.d.cts +1 -0
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +6 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.cjs +1787 -903
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -6
- package/dist/index.d.ts +28 -6
- package/dist/index.js +1758 -879
- package/dist/index.js.map +1 -1
- package/dist/plugins/{policy.cjs → policy/index.cjs} +472 -271
- package/dist/plugins/policy/index.cjs.map +1 -0
- package/dist/plugins/{policy.d.ts → policy/index.d.cts} +2 -4
- package/dist/plugins/{policy.d.cts → policy/index.d.ts} +2 -4
- package/dist/plugins/{policy.js → policy/index.js} +447 -236
- package/dist/plugins/policy/index.js.map +1 -0
- package/dist/plugins/policy/plugin.zmodel +33 -0
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js.map +1 -1
- package/package.json +27 -49
- package/dist/client.cjs +0 -6094
- package/dist/client.cjs.map +0 -1
- package/dist/client.d.cts +0 -19
- package/dist/client.d.ts +0 -19
- package/dist/client.js +0 -6060
- package/dist/client.js.map +0 -1
- package/dist/plugins/policy.cjs.map +0 -1
- package/dist/plugins/policy.js.map +0 -1
- package/dist/utils/pg-utils.cjs.map +0 -1
- package/dist/utils/pg-utils.d.cts +0 -8
- package/dist/utils/pg-utils.d.ts +0 -8
- package/dist/utils/pg-utils.js +0 -16
- package/dist/utils/pg-utils.js.map +0 -1
- package/dist/utils/sqlite-utils.cjs +0 -55
- package/dist/utils/sqlite-utils.cjs.map +0 -1
- package/dist/utils/sqlite-utils.d.cts +0 -8
- package/dist/utils/sqlite-utils.d.ts +0 -8
- package/dist/utils/sqlite-utils.js +0 -22
- package/dist/utils/sqlite-utils.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -6,29 +6,133 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// src/client/client-impl.ts
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { invariant as invariant12, lowerCaseFirst as lowerCaseFirst2 } from "@zenstackhq/common-helpers";
|
|
10
|
+
import { CompiledQuery, DefaultConnectionProvider, DefaultQueryExecutor as DefaultQueryExecutor2, Kysely, Log, sql as sql9 } from "kysely";
|
|
11
11
|
|
|
12
12
|
// src/client/crud/operations/aggregate.ts
|
|
13
13
|
import { sql as sql5 } from "kysely";
|
|
14
|
-
import { match as
|
|
14
|
+
import { match as match10 } from "ts-pattern";
|
|
15
|
+
|
|
16
|
+
// src/client/query-utils.ts
|
|
17
|
+
import { match } from "ts-pattern";
|
|
18
|
+
|
|
19
|
+
// src/schema/expression.ts
|
|
20
|
+
var ExpressionUtils = {
|
|
21
|
+
literal: /* @__PURE__ */ __name((value) => {
|
|
22
|
+
return {
|
|
23
|
+
kind: "literal",
|
|
24
|
+
value
|
|
25
|
+
};
|
|
26
|
+
}, "literal"),
|
|
27
|
+
array: /* @__PURE__ */ __name((items) => {
|
|
28
|
+
return {
|
|
29
|
+
kind: "array",
|
|
30
|
+
items
|
|
31
|
+
};
|
|
32
|
+
}, "array"),
|
|
33
|
+
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
34
|
+
return {
|
|
35
|
+
kind: "call",
|
|
36
|
+
function: functionName,
|
|
37
|
+
args
|
|
38
|
+
};
|
|
39
|
+
}, "call"),
|
|
40
|
+
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
41
|
+
return {
|
|
42
|
+
kind: "binary",
|
|
43
|
+
op,
|
|
44
|
+
left,
|
|
45
|
+
right
|
|
46
|
+
};
|
|
47
|
+
}, "binary"),
|
|
48
|
+
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
49
|
+
return {
|
|
50
|
+
kind: "unary",
|
|
51
|
+
op,
|
|
52
|
+
operand
|
|
53
|
+
};
|
|
54
|
+
}, "unary"),
|
|
55
|
+
field: /* @__PURE__ */ __name((field) => {
|
|
56
|
+
return {
|
|
57
|
+
kind: "field",
|
|
58
|
+
field
|
|
59
|
+
};
|
|
60
|
+
}, "field"),
|
|
61
|
+
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
62
|
+
return {
|
|
63
|
+
kind: "member",
|
|
64
|
+
receiver,
|
|
65
|
+
members
|
|
66
|
+
};
|
|
67
|
+
}, "member"),
|
|
68
|
+
_this: /* @__PURE__ */ __name(() => {
|
|
69
|
+
return {
|
|
70
|
+
kind: "this"
|
|
71
|
+
};
|
|
72
|
+
}, "_this"),
|
|
73
|
+
_null: /* @__PURE__ */ __name(() => {
|
|
74
|
+
return {
|
|
75
|
+
kind: "null"
|
|
76
|
+
};
|
|
77
|
+
}, "_null"),
|
|
78
|
+
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
79
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
80
|
+
}, "and"),
|
|
81
|
+
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
82
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
83
|
+
}, "or"),
|
|
84
|
+
is: /* @__PURE__ */ __name((value, kind) => {
|
|
85
|
+
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
86
|
+
}, "is"),
|
|
87
|
+
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
88
|
+
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
89
|
+
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
90
|
+
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
91
|
+
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
92
|
+
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
93
|
+
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
94
|
+
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
95
|
+
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// src/utils/object-utils.ts
|
|
99
|
+
function extractFields(obj, fields) {
|
|
100
|
+
return Object.fromEntries(Object.entries(obj).filter(([key]) => fields.includes(key)));
|
|
101
|
+
}
|
|
102
|
+
__name(extractFields, "extractFields");
|
|
103
|
+
function fieldsToSelectObject(fields) {
|
|
104
|
+
return Object.fromEntries(fields.map((f) => [
|
|
105
|
+
f,
|
|
106
|
+
true
|
|
107
|
+
]));
|
|
108
|
+
}
|
|
109
|
+
__name(fieldsToSelectObject, "fieldsToSelectObject");
|
|
15
110
|
|
|
16
111
|
// src/client/errors.ts
|
|
112
|
+
var InputValidationError = class extends Error {
|
|
113
|
+
static {
|
|
114
|
+
__name(this, "InputValidationError");
|
|
115
|
+
}
|
|
116
|
+
constructor(message, cause) {
|
|
117
|
+
super(message, {
|
|
118
|
+
cause
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
};
|
|
17
122
|
var QueryError = class extends Error {
|
|
18
123
|
static {
|
|
19
124
|
__name(this, "QueryError");
|
|
20
125
|
}
|
|
21
|
-
constructor(message) {
|
|
22
|
-
super(message
|
|
126
|
+
constructor(message, cause) {
|
|
127
|
+
super(message, {
|
|
128
|
+
cause
|
|
129
|
+
});
|
|
23
130
|
}
|
|
24
131
|
};
|
|
25
132
|
var InternalError = class extends Error {
|
|
26
133
|
static {
|
|
27
134
|
__name(this, "InternalError");
|
|
28
135
|
}
|
|
29
|
-
constructor(message) {
|
|
30
|
-
super(message);
|
|
31
|
-
}
|
|
32
136
|
};
|
|
33
137
|
var NotFoundError = class extends Error {
|
|
34
138
|
static {
|
|
@@ -47,7 +151,7 @@ __name(getModel, "getModel");
|
|
|
47
151
|
function requireModel(schema, model) {
|
|
48
152
|
const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
|
|
49
153
|
if (!matchedName) {
|
|
50
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
154
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
51
155
|
}
|
|
52
156
|
return schema.models[matchedName];
|
|
53
157
|
}
|
|
@@ -111,20 +215,25 @@ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
|
111
215
|
}
|
|
112
216
|
__name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
|
|
113
217
|
function isScalarField(schema, model, field) {
|
|
114
|
-
const fieldDef =
|
|
115
|
-
return !fieldDef
|
|
218
|
+
const fieldDef = getField(schema, model, field);
|
|
219
|
+
return !fieldDef?.relation && !fieldDef?.foreignKeyFor;
|
|
116
220
|
}
|
|
117
221
|
__name(isScalarField, "isScalarField");
|
|
118
222
|
function isForeignKeyField(schema, model, field) {
|
|
119
|
-
const fieldDef =
|
|
120
|
-
return !!fieldDef
|
|
223
|
+
const fieldDef = getField(schema, model, field);
|
|
224
|
+
return !!fieldDef?.foreignKeyFor;
|
|
121
225
|
}
|
|
122
226
|
__name(isForeignKeyField, "isForeignKeyField");
|
|
123
227
|
function isRelationField(schema, model, field) {
|
|
124
|
-
const fieldDef =
|
|
125
|
-
return !!fieldDef
|
|
228
|
+
const fieldDef = getField(schema, model, field);
|
|
229
|
+
return !!fieldDef?.relation;
|
|
126
230
|
}
|
|
127
231
|
__name(isRelationField, "isRelationField");
|
|
232
|
+
function isInheritedField(schema, model, field) {
|
|
233
|
+
const fieldDef = getField(schema, model, field);
|
|
234
|
+
return !!fieldDef?.originModel;
|
|
235
|
+
}
|
|
236
|
+
__name(isInheritedField, "isInheritedField");
|
|
128
237
|
function getUniqueFields(schema, model) {
|
|
129
238
|
const modelDef = requireModel(schema, model);
|
|
130
239
|
const result = [];
|
|
@@ -172,7 +281,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias) {
|
|
|
172
281
|
computer = computedFields?.[model]?.[field];
|
|
173
282
|
}
|
|
174
283
|
if (!computer) {
|
|
175
|
-
throw new QueryError(`Computed field "${field}" implementation not provided`);
|
|
284
|
+
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
176
285
|
}
|
|
177
286
|
return computer(eb);
|
|
178
287
|
}
|
|
@@ -277,13 +386,49 @@ function safeJSONStringify(value) {
|
|
|
277
386
|
});
|
|
278
387
|
}
|
|
279
388
|
__name(safeJSONStringify, "safeJSONStringify");
|
|
389
|
+
function extractIdFields(entity, schema, model) {
|
|
390
|
+
const idFields = getIdFields(schema, model);
|
|
391
|
+
return extractFields(entity, idFields);
|
|
392
|
+
}
|
|
393
|
+
__name(extractIdFields, "extractIdFields");
|
|
394
|
+
function getDiscriminatorField(schema, model) {
|
|
395
|
+
const modelDef = requireModel(schema, model);
|
|
396
|
+
const delegateAttr = modelDef.attributes?.find((attr) => attr.name === "@@delegate");
|
|
397
|
+
if (!delegateAttr) {
|
|
398
|
+
return void 0;
|
|
399
|
+
}
|
|
400
|
+
const discriminator = delegateAttr.args?.find((arg) => arg.name === "discriminator");
|
|
401
|
+
if (!discriminator || !ExpressionUtils.isField(discriminator.value)) {
|
|
402
|
+
throw new InternalError(`Discriminator field not defined for model "${model}"`);
|
|
403
|
+
}
|
|
404
|
+
return discriminator.value.field;
|
|
405
|
+
}
|
|
406
|
+
__name(getDiscriminatorField, "getDiscriminatorField");
|
|
407
|
+
function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */ new Set()) {
|
|
408
|
+
const subModels = Object.values(schema.models).filter((m) => m.baseModel === model);
|
|
409
|
+
subModels.forEach((def) => {
|
|
410
|
+
if (!collected.has(def)) {
|
|
411
|
+
collected.add(def);
|
|
412
|
+
getDelegateDescendantModels(schema, def.name, collected);
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
return [
|
|
416
|
+
...collected
|
|
417
|
+
];
|
|
418
|
+
}
|
|
419
|
+
__name(getDelegateDescendantModels, "getDelegateDescendantModels");
|
|
420
|
+
function aggregate(eb, expr2, op) {
|
|
421
|
+
return match(op).with("_count", () => eb.fn.count(expr2)).with("_sum", () => eb.fn.sum(expr2)).with("_avg", () => eb.fn.avg(expr2)).with("_min", () => eb.fn.min(expr2)).with("_max", () => eb.fn.max(expr2)).exhaustive();
|
|
422
|
+
}
|
|
423
|
+
__name(aggregate, "aggregate");
|
|
280
424
|
|
|
281
425
|
// src/client/crud/operations/base.ts
|
|
282
426
|
import { createId } from "@paralleldrive/cuid2";
|
|
283
|
-
import {
|
|
427
|
+
import { invariant as invariant7, isPlainObject as isPlainObject3 } from "@zenstackhq/common-helpers";
|
|
428
|
+
import { expressionBuilder as expressionBuilder3, sql as sql4 } from "kysely";
|
|
284
429
|
import { nanoid } from "nanoid";
|
|
285
|
-
import
|
|
286
|
-
import { match as
|
|
430
|
+
import { inspect } from "util";
|
|
431
|
+
import { match as match9 } from "ts-pattern";
|
|
287
432
|
import { ulid } from "ulid";
|
|
288
433
|
import * as uuid from "uuid";
|
|
289
434
|
|
|
@@ -300,22 +445,44 @@ var RejectedByPolicyError = class extends Error {
|
|
|
300
445
|
};
|
|
301
446
|
|
|
302
447
|
// src/plugins/policy/policy-handler.ts
|
|
448
|
+
import { invariant as invariant6 } from "@zenstackhq/common-helpers";
|
|
303
449
|
import { AliasNode as AliasNode3, BinaryOperationNode as BinaryOperationNode3, ColumnNode as ColumnNode2, DeleteQueryNode, FromNode as FromNode2, IdentifierNode as IdentifierNode2, InsertQueryNode, OperationNodeTransformer, OperatorNode as OperatorNode3, PrimitiveValueListNode, RawNode, ReturningNode, SelectionNode as SelectionNode2, SelectQueryNode as SelectQueryNode2, TableNode as TableNode3, UpdateQueryNode, ValueNode as ValueNode3, ValuesNode, WhereNode as WhereNode2 } from "kysely";
|
|
304
|
-
import
|
|
305
|
-
import { match as match7 } from "ts-pattern";
|
|
450
|
+
import { match as match8 } from "ts-pattern";
|
|
306
451
|
|
|
307
452
|
// src/client/crud/dialects/index.ts
|
|
308
|
-
import { match as
|
|
453
|
+
import { match as match5 } from "ts-pattern";
|
|
309
454
|
|
|
310
455
|
// src/client/crud/dialects/postgresql.ts
|
|
456
|
+
import { invariant as invariant2 } from "@zenstackhq/common-helpers";
|
|
311
457
|
import { sql as sql2 } from "kysely";
|
|
312
|
-
import
|
|
313
|
-
|
|
458
|
+
import { match as match3 } from "ts-pattern";
|
|
459
|
+
|
|
460
|
+
// src/client/constants.ts
|
|
461
|
+
var CONTEXT_COMMENT_PREFIX = "-- $$context:";
|
|
462
|
+
var NUMERIC_FIELD_TYPES = [
|
|
463
|
+
"Int",
|
|
464
|
+
"Float",
|
|
465
|
+
"BigInt",
|
|
466
|
+
"Decimal"
|
|
467
|
+
];
|
|
468
|
+
var DELEGATE_JOINED_FIELD_PREFIX = "$delegate$";
|
|
469
|
+
var LOGICAL_COMBINATORS = [
|
|
470
|
+
"AND",
|
|
471
|
+
"OR",
|
|
472
|
+
"NOT"
|
|
473
|
+
];
|
|
474
|
+
var AGGREGATE_OPERATORS = [
|
|
475
|
+
"_count",
|
|
476
|
+
"_sum",
|
|
477
|
+
"_avg",
|
|
478
|
+
"_min",
|
|
479
|
+
"_max"
|
|
480
|
+
];
|
|
314
481
|
|
|
315
482
|
// src/client/crud/dialects/base.ts
|
|
316
|
-
import {
|
|
317
|
-
import
|
|
318
|
-
import { match, P } from "ts-pattern";
|
|
483
|
+
import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
|
|
484
|
+
import { expressionBuilder, sql } from "kysely";
|
|
485
|
+
import { match as match2, P } from "ts-pattern";
|
|
319
486
|
|
|
320
487
|
// src/utils/enumerate.ts
|
|
321
488
|
function enumerate(x) {
|
|
@@ -332,7 +499,6 @@ function enumerate(x) {
|
|
|
332
499
|
__name(enumerate, "enumerate");
|
|
333
500
|
|
|
334
501
|
// src/client/crud/dialects/base.ts
|
|
335
|
-
import { isPlainObject } from "is-plain-object";
|
|
336
502
|
var BaseCrudDialect = class {
|
|
337
503
|
static {
|
|
338
504
|
__name(this, "BaseCrudDialect");
|
|
@@ -343,9 +509,20 @@ var BaseCrudDialect = class {
|
|
|
343
509
|
this.schema = schema;
|
|
344
510
|
this.options = options;
|
|
345
511
|
}
|
|
346
|
-
transformPrimitive(value, _type) {
|
|
512
|
+
transformPrimitive(value, _type, _forArrayField) {
|
|
347
513
|
return value;
|
|
348
514
|
}
|
|
515
|
+
// #region common query builders
|
|
516
|
+
buildSelectModel(eb, model) {
|
|
517
|
+
const modelDef = requireModel(this.schema, model);
|
|
518
|
+
let result = eb.selectFrom(model);
|
|
519
|
+
let joinBase = modelDef.baseModel;
|
|
520
|
+
while (joinBase) {
|
|
521
|
+
result = this.buildDelegateJoin(model, joinBase, result);
|
|
522
|
+
joinBase = requireModel(this.schema, joinBase).baseModel;
|
|
523
|
+
}
|
|
524
|
+
return result;
|
|
525
|
+
}
|
|
349
526
|
buildFilter(eb, model, modelAlias, where) {
|
|
350
527
|
if (where === true || where === void 0) {
|
|
351
528
|
return this.true(eb);
|
|
@@ -362,17 +539,20 @@ var BaseCrudDialect = class {
|
|
|
362
539
|
if (key.startsWith("$")) {
|
|
363
540
|
continue;
|
|
364
541
|
}
|
|
365
|
-
if (key
|
|
542
|
+
if (this.isLogicalCombinator(key)) {
|
|
366
543
|
result = this.and(eb, result, this.buildCompositeFilter(eb, model, modelAlias, key, payload));
|
|
367
544
|
continue;
|
|
368
545
|
}
|
|
369
546
|
const fieldDef = requireField(this.schema, model, key);
|
|
370
547
|
if (fieldDef.relation) {
|
|
371
548
|
result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
372
|
-
} else if (fieldDef.array) {
|
|
373
|
-
result = this.and(eb, result, this.buildArrayFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
374
549
|
} else {
|
|
375
|
-
|
|
550
|
+
const fieldRef = this.fieldRef(fieldDef.originModel ?? model, key, eb, fieldDef.originModel ?? modelAlias);
|
|
551
|
+
if (fieldDef.array) {
|
|
552
|
+
result = this.and(eb, result, this.buildArrayFilter(eb, fieldRef, fieldDef, payload));
|
|
553
|
+
} else {
|
|
554
|
+
result = this.and(eb, result, this.buildPrimitiveFilter(eb, fieldRef, fieldDef, payload));
|
|
555
|
+
}
|
|
376
556
|
}
|
|
377
557
|
}
|
|
378
558
|
if ("$expr" in _where && typeof _where["$expr"] === "function") {
|
|
@@ -380,8 +560,11 @@ var BaseCrudDialect = class {
|
|
|
380
560
|
}
|
|
381
561
|
return result;
|
|
382
562
|
}
|
|
563
|
+
isLogicalCombinator(key) {
|
|
564
|
+
return LOGICAL_COMBINATORS.includes(key);
|
|
565
|
+
}
|
|
383
566
|
buildCompositeFilter(eb, model, modelAlias, key, payload) {
|
|
384
|
-
return
|
|
567
|
+
return match2(key).with("AND", () => this.and(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("OR", () => this.or(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("NOT", () => eb.not(this.buildCompositeFilter(eb, model, modelAlias, "AND", payload))).exhaustive();
|
|
385
568
|
}
|
|
386
569
|
buildRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
387
570
|
if (!fieldDef.array) {
|
|
@@ -390,19 +573,26 @@ var BaseCrudDialect = class {
|
|
|
390
573
|
return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
|
|
391
574
|
}
|
|
392
575
|
}
|
|
393
|
-
buildToOneRelationFilter(eb, model,
|
|
576
|
+
buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
394
577
|
if (payload === null) {
|
|
395
578
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
396
|
-
if (ownedByModel) {
|
|
397
|
-
return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${
|
|
579
|
+
if (ownedByModel && !fieldDef.originModel) {
|
|
580
|
+
return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${modelAlias}.${fk}`), "is", null)));
|
|
398
581
|
} else {
|
|
399
|
-
return this.buildToOneRelationFilter(eb, model,
|
|
582
|
+
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
|
|
400
583
|
is: null
|
|
401
584
|
});
|
|
402
585
|
}
|
|
403
586
|
}
|
|
404
|
-
const joinAlias = `${
|
|
405
|
-
const joinPairs = buildJoinPairs(
|
|
587
|
+
const joinAlias = `${modelAlias}$${field}`;
|
|
588
|
+
const joinPairs = buildJoinPairs(
|
|
589
|
+
this.schema,
|
|
590
|
+
model,
|
|
591
|
+
// if field is from a base, use the base model to join
|
|
592
|
+
fieldDef.originModel ?? modelAlias,
|
|
593
|
+
field,
|
|
594
|
+
joinAlias
|
|
595
|
+
);
|
|
406
596
|
const filterResultField = `${field}$filter`;
|
|
407
597
|
const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
|
|
408
598
|
const conditions = [];
|
|
@@ -463,30 +653,29 @@ var BaseCrudDialect = class {
|
|
|
463
653
|
}
|
|
464
654
|
switch (key) {
|
|
465
655
|
case "some": {
|
|
466
|
-
result = this.and(eb, result, eb(
|
|
656
|
+
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));
|
|
467
657
|
break;
|
|
468
658
|
}
|
|
469
659
|
case "every": {
|
|
470
|
-
result = this.and(eb, result, eb(
|
|
660
|
+
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));
|
|
471
661
|
break;
|
|
472
662
|
}
|
|
473
663
|
case "none": {
|
|
474
|
-
result = this.and(eb, result, eb(
|
|
664
|
+
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));
|
|
475
665
|
break;
|
|
476
666
|
}
|
|
477
667
|
}
|
|
478
668
|
}
|
|
479
669
|
return result;
|
|
480
670
|
}
|
|
481
|
-
buildArrayFilter(eb,
|
|
671
|
+
buildArrayFilter(eb, fieldRef, fieldDef, payload) {
|
|
482
672
|
const clauses = [];
|
|
483
673
|
const fieldType = fieldDef.type;
|
|
484
|
-
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
|
|
485
674
|
for (const [key, _value] of Object.entries(payload)) {
|
|
486
675
|
if (_value === void 0) {
|
|
487
676
|
continue;
|
|
488
677
|
}
|
|
489
|
-
const value = this.transformPrimitive(_value, fieldType);
|
|
678
|
+
const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
|
|
490
679
|
switch (key) {
|
|
491
680
|
case "equals": {
|
|
492
681
|
clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
|
|
@@ -517,19 +706,23 @@ var BaseCrudDialect = class {
|
|
|
517
706
|
}
|
|
518
707
|
return this.and(eb, ...clauses);
|
|
519
708
|
}
|
|
520
|
-
buildPrimitiveFilter(eb,
|
|
709
|
+
buildPrimitiveFilter(eb, fieldRef, fieldDef, payload) {
|
|
521
710
|
if (payload === null) {
|
|
522
|
-
return eb(
|
|
711
|
+
return eb(fieldRef, "is", null);
|
|
523
712
|
}
|
|
524
713
|
if (isEnum(this.schema, fieldDef.type)) {
|
|
525
|
-
return this.buildEnumFilter(eb,
|
|
714
|
+
return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
|
|
526
715
|
}
|
|
527
|
-
return
|
|
716
|
+
return match2(fieldDef.type).with("String", () => this.buildStringFilter(eb, fieldRef, payload)).with(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", () => {
|
|
717
|
+
throw new InternalError("JSON filters are not supported yet");
|
|
718
|
+
}).with("Unsupported", () => {
|
|
719
|
+
throw new QueryError(`Unsupported field cannot be used in filters`);
|
|
720
|
+
}).exhaustive();
|
|
528
721
|
}
|
|
529
722
|
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
530
|
-
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
|
|
723
|
+
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
531
724
|
}
|
|
532
|
-
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
|
|
725
|
+
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
533
726
|
if (payload === null || !isPlainObject(payload)) {
|
|
534
727
|
return {
|
|
535
728
|
conditions: [
|
|
@@ -544,8 +737,11 @@ var BaseCrudDialect = class {
|
|
|
544
737
|
if (onlyForKeys && !onlyForKeys.includes(op)) {
|
|
545
738
|
continue;
|
|
546
739
|
}
|
|
740
|
+
if (excludeKeys.includes(op)) {
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
547
743
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
548
|
-
const condition =
|
|
744
|
+
const condition = match2(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
549
745
|
invariant(Array.isArray(rhs), "right hand side must be an array");
|
|
550
746
|
if (rhs.length === 0) {
|
|
551
747
|
return this.false(eb);
|
|
@@ -559,7 +755,11 @@ var BaseCrudDialect = class {
|
|
|
559
755
|
} else {
|
|
560
756
|
return eb.not(eb(lhs, "in", rhs));
|
|
561
757
|
}
|
|
562
|
-
}).with("lt", () => eb(lhs, "<", rhs)).with("lte", () => eb(lhs, "<=", rhs)).with("gt", () => eb(lhs, ">", rhs)).with("gte", () => eb(lhs, ">=", rhs)).with("not", () => eb.not(recurse(value))).
|
|
758
|
+
}).with("lt", () => eb(lhs, "<", rhs)).with("lte", () => eb(lhs, "<=", rhs)).with("gt", () => eb(lhs, ">", rhs)).with("gte", () => eb(lhs, ">=", rhs)).with("not", () => eb.not(recurse(value))).with(P.union(...AGGREGATE_OPERATORS), (op2) => {
|
|
759
|
+
const innerResult = this.buildStandardFilter(eb, type, value, aggregate(eb, lhs, op2), getRhs, recurse, throwIfInvalid);
|
|
760
|
+
consumedKeys.push(...innerResult.consumedKeys);
|
|
761
|
+
return this.and(eb, ...innerResult.conditions);
|
|
762
|
+
}).otherwise(() => {
|
|
563
763
|
if (throwIfInvalid) {
|
|
564
764
|
throw new QueryError(`Invalid filter key: ${op}`);
|
|
565
765
|
} else {
|
|
@@ -576,24 +776,21 @@ var BaseCrudDialect = class {
|
|
|
576
776
|
consumedKeys
|
|
577
777
|
};
|
|
578
778
|
}
|
|
579
|
-
buildStringFilter(eb,
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
if (payload && typeof payload === "object" && "mode" in payload && payload.mode === "insensitive") {
|
|
584
|
-
insensitive = true;
|
|
585
|
-
fieldRef = eb.fn("lower", [
|
|
586
|
-
fieldRef
|
|
587
|
-
]);
|
|
779
|
+
buildStringFilter(eb, fieldRef, payload) {
|
|
780
|
+
let mode;
|
|
781
|
+
if (payload && typeof payload === "object" && "mode" in payload) {
|
|
782
|
+
mode = payload.mode;
|
|
588
783
|
}
|
|
589
|
-
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload,
|
|
784
|
+
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, mode === "insensitive" ? eb.fn("lower", [
|
|
785
|
+
fieldRef
|
|
786
|
+
]) : fieldRef, (value) => this.prepStringCasing(eb, value, mode), (value) => this.buildStringFilter(eb, fieldRef, value));
|
|
590
787
|
if (payload && typeof payload === "object") {
|
|
591
788
|
for (const [key, value] of Object.entries(payload)) {
|
|
592
789
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
593
790
|
continue;
|
|
594
791
|
}
|
|
595
|
-
const condition =
|
|
596
|
-
throw new
|
|
792
|
+
const condition = match2(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`%${value}%`)) : eb(fieldRef, "like", sql.val(`%${value}%`))).with("startsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`${value}%`)) : eb(fieldRef, "like", sql.val(`${value}%`))).with("endsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`%${value}`)) : eb(fieldRef, "like", sql.val(`%${value}`))).otherwise(() => {
|
|
793
|
+
throw new QueryError(`Invalid string filter key: ${key}`);
|
|
597
794
|
});
|
|
598
795
|
if (condition) {
|
|
599
796
|
conditions.push(condition);
|
|
@@ -602,34 +799,37 @@ var BaseCrudDialect = class {
|
|
|
602
799
|
}
|
|
603
800
|
return this.and(eb, ...conditions);
|
|
604
801
|
}
|
|
605
|
-
prepStringCasing(eb, value,
|
|
802
|
+
prepStringCasing(eb, value, mode) {
|
|
803
|
+
if (!mode || mode === "default") {
|
|
804
|
+
return value === null ? value : sql.val(value);
|
|
805
|
+
}
|
|
606
806
|
if (typeof value === "string") {
|
|
607
|
-
return
|
|
608
|
-
sql.
|
|
609
|
-
])
|
|
807
|
+
return eb.fn("lower", [
|
|
808
|
+
sql.val(value)
|
|
809
|
+
]);
|
|
610
810
|
} else if (Array.isArray(value)) {
|
|
611
|
-
return value.map((v) => this.prepStringCasing(eb, v,
|
|
811
|
+
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
612
812
|
} else {
|
|
613
|
-
return value === null ? null : sql.
|
|
813
|
+
return value === null ? null : sql.val(value);
|
|
614
814
|
}
|
|
615
815
|
}
|
|
616
|
-
buildNumberFilter(eb,
|
|
617
|
-
const { conditions } = this.buildStandardFilter(eb, type, payload,
|
|
816
|
+
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
817
|
+
const { conditions } = this.buildStandardFilter(eb, type, payload, fieldRef, (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, fieldRef, type, value));
|
|
618
818
|
return this.and(eb, ...conditions);
|
|
619
819
|
}
|
|
620
|
-
buildBooleanFilter(eb,
|
|
621
|
-
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload,
|
|
820
|
+
buildBooleanFilter(eb, fieldRef, payload) {
|
|
821
|
+
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, fieldRef, (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, fieldRef, value), true, [
|
|
622
822
|
"equals",
|
|
623
823
|
"not"
|
|
624
824
|
]);
|
|
625
825
|
return this.and(eb, ...conditions);
|
|
626
826
|
}
|
|
627
|
-
buildDateTimeFilter(eb,
|
|
628
|
-
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload,
|
|
827
|
+
buildDateTimeFilter(eb, fieldRef, payload) {
|
|
828
|
+
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, fieldRef, (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, fieldRef, value), true);
|
|
629
829
|
return this.and(eb, ...conditions);
|
|
630
830
|
}
|
|
631
|
-
buildBytesFilter(eb,
|
|
632
|
-
const conditions = this.buildStandardFilter(eb, "Bytes", payload,
|
|
831
|
+
buildBytesFilter(eb, fieldRef, payload) {
|
|
832
|
+
const conditions = this.buildStandardFilter(eb, "Bytes", payload, fieldRef, (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, fieldRef, value), true, [
|
|
633
833
|
"equals",
|
|
634
834
|
"in",
|
|
635
835
|
"notIn",
|
|
@@ -637,8 +837,8 @@ var BaseCrudDialect = class {
|
|
|
637
837
|
]);
|
|
638
838
|
return this.and(eb, ...conditions.conditions);
|
|
639
839
|
}
|
|
640
|
-
buildEnumFilter(eb,
|
|
641
|
-
const conditions = this.buildStandardFilter(eb, "String", payload,
|
|
840
|
+
buildEnumFilter(eb, fieldRef, fieldDef, payload) {
|
|
841
|
+
const conditions = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => value, (value) => this.buildEnumFilter(eb, fieldRef, fieldDef, value), true, [
|
|
642
842
|
"equals",
|
|
643
843
|
"in",
|
|
644
844
|
"notIn",
|
|
@@ -670,9 +870,7 @@ var BaseCrudDialect = class {
|
|
|
670
870
|
invariant(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
671
871
|
for (const [k, v] of Object.entries(value)) {
|
|
672
872
|
invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
673
|
-
result = result.orderBy((eb) => eb.
|
|
674
|
-
sql.ref(k)
|
|
675
|
-
]), sql.raw(this.negateSort(v, negated)));
|
|
873
|
+
result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field), sql.raw(this.negateSort(v, negated)));
|
|
676
874
|
}
|
|
677
875
|
continue;
|
|
678
876
|
}
|
|
@@ -681,7 +879,7 @@ var BaseCrudDialect = class {
|
|
|
681
879
|
invariant(value && typeof value === "object", 'invalid orderBy value for field "_count"');
|
|
682
880
|
for (const [k, v] of Object.entries(value)) {
|
|
683
881
|
invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
684
|
-
result = result.orderBy((eb) => eb.fn.count(
|
|
882
|
+
result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), sql.raw(this.negateSort(v, negated)));
|
|
685
883
|
}
|
|
686
884
|
continue;
|
|
687
885
|
}
|
|
@@ -690,10 +888,11 @@ var BaseCrudDialect = class {
|
|
|
690
888
|
}
|
|
691
889
|
const fieldDef = requireField(this.schema, model, field);
|
|
692
890
|
if (!fieldDef.relation) {
|
|
891
|
+
const fieldRef = this.fieldRef(model, field, expressionBuilder(), modelAlias);
|
|
693
892
|
if (value === "asc" || value === "desc") {
|
|
694
|
-
result = result.orderBy(
|
|
893
|
+
result = result.orderBy(fieldRef, this.negateSort(value, negated));
|
|
695
894
|
} else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
|
|
696
|
-
result = result.orderBy(
|
|
895
|
+
result = result.orderBy(fieldRef, sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
|
|
697
896
|
}
|
|
698
897
|
} else {
|
|
699
898
|
const relationModel = fieldDef.type;
|
|
@@ -705,7 +904,7 @@ var BaseCrudDialect = class {
|
|
|
705
904
|
invariant(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
706
905
|
const sort = this.negateSort(value._count, negated);
|
|
707
906
|
result = result.orderBy((eb) => {
|
|
708
|
-
let subQuery =
|
|
907
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
709
908
|
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
|
|
710
909
|
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right)))));
|
|
711
910
|
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
@@ -724,14 +923,90 @@ var BaseCrudDialect = class {
|
|
|
724
923
|
});
|
|
725
924
|
return result;
|
|
726
925
|
}
|
|
926
|
+
buildSelectAllFields(model, query, omit) {
|
|
927
|
+
const modelDef = requireModel(this.schema, model);
|
|
928
|
+
let result = query;
|
|
929
|
+
for (const field of Object.keys(modelDef.fields)) {
|
|
930
|
+
if (isRelationField(this.schema, model, field)) {
|
|
931
|
+
continue;
|
|
932
|
+
}
|
|
933
|
+
if (omit?.[field] === true) {
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
936
|
+
result = this.buildSelectField(result, model, model, field);
|
|
937
|
+
}
|
|
938
|
+
const descendants = getDelegateDescendantModels(this.schema, model);
|
|
939
|
+
for (const subModel of descendants) {
|
|
940
|
+
result = this.buildDelegateJoin(model, subModel.name, result);
|
|
941
|
+
result = result.select((eb) => {
|
|
942
|
+
const jsonObject = {};
|
|
943
|
+
for (const field of Object.keys(subModel.fields)) {
|
|
944
|
+
if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
|
|
945
|
+
continue;
|
|
946
|
+
}
|
|
947
|
+
jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
|
|
948
|
+
}
|
|
949
|
+
return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
return result;
|
|
953
|
+
}
|
|
954
|
+
buildSelectField(query, model, modelAlias, field) {
|
|
955
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
956
|
+
if (fieldDef.computed) {
|
|
957
|
+
return query.select((eb) => this.fieldRef(model, field, eb, modelAlias).as(field));
|
|
958
|
+
} else if (!fieldDef.originModel) {
|
|
959
|
+
return query.select(sql.ref(`${modelAlias}.${field}`).as(field));
|
|
960
|
+
} else {
|
|
961
|
+
return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
buildDelegateJoin(thisModel, otherModel, query) {
|
|
965
|
+
const idFields = getIdFields(this.schema, thisModel);
|
|
966
|
+
query = query.leftJoin(otherModel, (qb) => {
|
|
967
|
+
for (const idField of idFields) {
|
|
968
|
+
qb = qb.onRef(`${thisModel}.${idField}`, "=", `${otherModel}.${idField}`);
|
|
969
|
+
}
|
|
970
|
+
return qb;
|
|
971
|
+
});
|
|
972
|
+
return query;
|
|
973
|
+
}
|
|
974
|
+
buildCountJson(model, eb, parentAlias, payload) {
|
|
975
|
+
const modelDef = requireModel(this.schema, model);
|
|
976
|
+
const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
|
|
977
|
+
const selections = payload === true ? {
|
|
978
|
+
select: toManyRelations.reduce((acc, [field]) => {
|
|
979
|
+
acc[field] = true;
|
|
980
|
+
return acc;
|
|
981
|
+
}, {})
|
|
982
|
+
} : payload;
|
|
983
|
+
const jsonObject = {};
|
|
984
|
+
for (const [field, value] of Object.entries(selections.select)) {
|
|
985
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
986
|
+
const fieldModel = fieldDef.type;
|
|
987
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
988
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
989
|
+
for (const [left, right] of joinPairs) {
|
|
990
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
991
|
+
}
|
|
992
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
993
|
+
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
994
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
995
|
+
}
|
|
996
|
+
jsonObject[field] = fieldCountQuery;
|
|
997
|
+
}
|
|
998
|
+
return this.buildJsonObject(eb, jsonObject);
|
|
999
|
+
}
|
|
1000
|
+
// #endregion
|
|
1001
|
+
// #region utils
|
|
727
1002
|
negateSort(sort, negated) {
|
|
728
1003
|
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
729
1004
|
}
|
|
730
1005
|
true(eb) {
|
|
731
|
-
return eb.lit(this.transformPrimitive(true, "Boolean"));
|
|
1006
|
+
return eb.lit(this.transformPrimitive(true, "Boolean", false));
|
|
732
1007
|
}
|
|
733
1008
|
false(eb) {
|
|
734
|
-
return eb.lit(this.transformPrimitive(false, "Boolean"));
|
|
1009
|
+
return eb.lit(this.transformPrimitive(false, "Boolean", false));
|
|
735
1010
|
}
|
|
736
1011
|
isTrue(expression) {
|
|
737
1012
|
const node = expression.toOperationNode();
|
|
@@ -770,6 +1045,9 @@ var BaseCrudDialect = class {
|
|
|
770
1045
|
not(eb, ...args) {
|
|
771
1046
|
return eb.not(this.and(eb, ...args));
|
|
772
1047
|
}
|
|
1048
|
+
fieldRef(model, field, eb, modelAlias) {
|
|
1049
|
+
return buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
|
|
1050
|
+
}
|
|
773
1051
|
};
|
|
774
1052
|
|
|
775
1053
|
// src/client/crud/dialects/postgresql.ts
|
|
@@ -780,14 +1058,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
780
1058
|
get provider() {
|
|
781
1059
|
return "postgresql";
|
|
782
1060
|
}
|
|
783
|
-
transformPrimitive(value, type) {
|
|
1061
|
+
transformPrimitive(value, type, forArrayField) {
|
|
784
1062
|
if (value === void 0) {
|
|
785
1063
|
return value;
|
|
786
1064
|
}
|
|
787
1065
|
if (Array.isArray(value)) {
|
|
788
|
-
|
|
1066
|
+
if (type === "Json" && !forArrayField) {
|
|
1067
|
+
return JSON.stringify(value);
|
|
1068
|
+
} else {
|
|
1069
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
1070
|
+
}
|
|
789
1071
|
} else {
|
|
790
|
-
return
|
|
1072
|
+
return match3(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
|
|
791
1073
|
}
|
|
792
1074
|
}
|
|
793
1075
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -801,7 +1083,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
801
1083
|
const joinTableName = `${parentName}$${relationField}`;
|
|
802
1084
|
let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
|
|
803
1085
|
result = eb.selectFrom(() => {
|
|
804
|
-
let subQuery =
|
|
1086
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
1087
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
805
1088
|
if (payload && typeof payload === "object") {
|
|
806
1089
|
if (payload.where) {
|
|
807
1090
|
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
@@ -845,34 +1128,57 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
845
1128
|
});
|
|
846
1129
|
return qb;
|
|
847
1130
|
}
|
|
848
|
-
buildRelationObjectArgs(relationModel, relationField, eb, payload,
|
|
1131
|
+
buildRelationObjectArgs(relationModel, relationField, eb, payload, parentAlias) {
|
|
849
1132
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
850
1133
|
const objArgs = [];
|
|
1134
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1135
|
+
if (descendantModels.length > 0) {
|
|
1136
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1137
|
+
sql2.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1138
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1139
|
+
]).flatMap((v) => v));
|
|
1140
|
+
}
|
|
851
1141
|
if (payload === true || !payload.select) {
|
|
852
1142
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
853
1143
|
sql2.lit(field),
|
|
854
|
-
|
|
1144
|
+
this.fieldRef(relationModel, field, eb)
|
|
855
1145
|
]).flatMap((v) => v));
|
|
856
1146
|
} else if (payload.select) {
|
|
857
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) =>
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1147
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1148
|
+
if (field === "_count") {
|
|
1149
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1150
|
+
return [
|
|
1151
|
+
sql2.lit(field),
|
|
1152
|
+
subJson
|
|
1153
|
+
];
|
|
1154
|
+
} else {
|
|
1155
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1156
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : this.fieldRef(relationModel, field, eb);
|
|
1157
|
+
return [
|
|
1158
|
+
sql2.lit(field),
|
|
1159
|
+
fieldValue
|
|
1160
|
+
];
|
|
1161
|
+
}
|
|
1162
|
+
}).flatMap((v) => v));
|
|
861
1163
|
}
|
|
862
1164
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
863
1165
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
864
1166
|
sql2.lit(field),
|
|
865
|
-
|
|
1167
|
+
// reference the synthesized JSON field
|
|
1168
|
+
eb.ref(`${parentAlias}$${relationField}$${field}.$j`)
|
|
866
1169
|
]).flatMap((v) => v));
|
|
867
1170
|
}
|
|
868
1171
|
return objArgs;
|
|
869
1172
|
}
|
|
870
|
-
buildRelationJoins(
|
|
1173
|
+
buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
|
|
871
1174
|
let result = qb;
|
|
872
|
-
if (typeof payload === "object"
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1175
|
+
if (typeof payload === "object") {
|
|
1176
|
+
const selectInclude = payload.include ?? payload.select;
|
|
1177
|
+
if (selectInclude && typeof selectInclude === "object") {
|
|
1178
|
+
Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
|
|
1179
|
+
result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
876
1182
|
}
|
|
877
1183
|
return result;
|
|
878
1184
|
}
|
|
@@ -912,12 +1218,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
912
1218
|
return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
|
|
913
1219
|
}
|
|
914
1220
|
}
|
|
1221
|
+
get supportInsertWithDefault() {
|
|
1222
|
+
return true;
|
|
1223
|
+
}
|
|
915
1224
|
};
|
|
916
1225
|
|
|
917
1226
|
// src/client/crud/dialects/sqlite.ts
|
|
1227
|
+
import { invariant as invariant3 } from "@zenstackhq/common-helpers";
|
|
918
1228
|
import { sql as sql3 } from "kysely";
|
|
919
|
-
import
|
|
920
|
-
import { match as match3 } from "ts-pattern";
|
|
1229
|
+
import { match as match4 } from "ts-pattern";
|
|
921
1230
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
922
1231
|
static {
|
|
923
1232
|
__name(this, "SqliteCrudDialect");
|
|
@@ -925,26 +1234,31 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
925
1234
|
get provider() {
|
|
926
1235
|
return "sqlite";
|
|
927
1236
|
}
|
|
928
|
-
transformPrimitive(value, type) {
|
|
1237
|
+
transformPrimitive(value, type, _forArrayField) {
|
|
929
1238
|
if (value === void 0) {
|
|
930
1239
|
return value;
|
|
931
1240
|
}
|
|
932
1241
|
if (Array.isArray(value)) {
|
|
933
|
-
return value.map((v) => this.transformPrimitive(v, type));
|
|
1242
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
934
1243
|
} else {
|
|
935
|
-
|
|
1244
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1245
|
+
return JSON.stringify(value);
|
|
1246
|
+
} else {
|
|
1247
|
+
return match4(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);
|
|
1248
|
+
}
|
|
936
1249
|
}
|
|
937
1250
|
}
|
|
938
1251
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
939
1252
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
940
1253
|
}
|
|
941
|
-
buildRelationJSON(model, eb, relationField,
|
|
1254
|
+
buildRelationJSON(model, eb, relationField, parentAlias, payload) {
|
|
942
1255
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
943
1256
|
const relationModel = relationFieldDef.type;
|
|
944
1257
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
945
|
-
const subQueryName = `${
|
|
1258
|
+
const subQueryName = `${parentAlias}$${relationField}`;
|
|
946
1259
|
let tbl = eb.selectFrom(() => {
|
|
947
|
-
let subQuery =
|
|
1260
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
1261
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
948
1262
|
if (payload && typeof payload === "object") {
|
|
949
1263
|
if (payload.where) {
|
|
950
1264
|
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
@@ -965,14 +1279,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
965
1279
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
966
1280
|
invariant3(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
967
1281
|
invariant3(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
968
|
-
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${
|
|
1282
|
+
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
969
1283
|
} else {
|
|
970
1284
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
971
1285
|
keyPairs.forEach(({ fk, pk }) => {
|
|
972
1286
|
if (ownedByModel) {
|
|
973
|
-
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${
|
|
1287
|
+
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentAlias}.${fk}`);
|
|
974
1288
|
} else {
|
|
975
|
-
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${
|
|
1289
|
+
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentAlias}.${pk}`);
|
|
976
1290
|
}
|
|
977
1291
|
});
|
|
978
1292
|
}
|
|
@@ -980,167 +1294,106 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
980
1294
|
});
|
|
981
1295
|
tbl = tbl.select(() => {
|
|
982
1296
|
const objArgs = [];
|
|
1297
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1298
|
+
if (descendantModels.length > 0) {
|
|
1299
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1300
|
+
sql3.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1301
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1302
|
+
]).flatMap((v) => v));
|
|
1303
|
+
}
|
|
983
1304
|
if (payload === true || !payload.select) {
|
|
984
1305
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
985
1306
|
sql3.lit(field),
|
|
986
|
-
|
|
1307
|
+
this.fieldRef(relationModel, field, eb)
|
|
987
1308
|
]).flatMap((v) => v));
|
|
988
1309
|
} else if (payload.select) {
|
|
989
1310
|
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
|
|
1311
|
+
if (field === "_count") {
|
|
1312
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
993
1313
|
return [
|
|
994
1314
|
sql3.lit(field),
|
|
995
1315
|
subJson
|
|
996
1316
|
];
|
|
997
1317
|
} else {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1318
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1319
|
+
if (fieldDef.relation) {
|
|
1320
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1321
|
+
return [
|
|
1322
|
+
sql3.lit(field),
|
|
1323
|
+
subJson
|
|
1324
|
+
];
|
|
1325
|
+
} else {
|
|
1326
|
+
return [
|
|
1327
|
+
sql3.lit(field),
|
|
1328
|
+
this.fieldRef(relationModel, field, eb)
|
|
1329
|
+
];
|
|
1330
|
+
}
|
|
1002
1331
|
}
|
|
1003
1332
|
}).flatMap((v) => v));
|
|
1004
1333
|
}
|
|
1005
1334
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
1006
1335
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
1007
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${
|
|
1336
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1008
1337
|
return [
|
|
1009
1338
|
sql3.lit(field),
|
|
1010
1339
|
subJson
|
|
1011
1340
|
];
|
|
1012
1341
|
}).flatMap((v) => v));
|
|
1013
1342
|
}
|
|
1014
|
-
if (relationFieldDef.array) {
|
|
1015
|
-
return eb.fn.coalesce(sql3`json_group_array(json_object(${sql3.join(objArgs)}))`, sql3`json_array()`).as("$j");
|
|
1016
|
-
} else {
|
|
1017
|
-
return sql3`json_object(${sql3.join(objArgs)})`.as("data");
|
|
1018
|
-
}
|
|
1019
|
-
});
|
|
1020
|
-
return tbl;
|
|
1021
|
-
}
|
|
1022
|
-
buildSkipTake(query, skip, take) {
|
|
1023
|
-
if (take !== void 0) {
|
|
1024
|
-
query = query.limit(take);
|
|
1025
|
-
}
|
|
1026
|
-
if (skip !== void 0) {
|
|
1027
|
-
query = query.offset(skip);
|
|
1028
|
-
if (take === void 0) {
|
|
1029
|
-
query = query.limit(-1);
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
return query;
|
|
1033
|
-
}
|
|
1034
|
-
buildJsonObject(eb, value) {
|
|
1035
|
-
return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
|
|
1036
|
-
sql3.lit(key),
|
|
1037
|
-
value2
|
|
1038
|
-
]));
|
|
1039
|
-
}
|
|
1040
|
-
get supportsUpdateWithLimit() {
|
|
1041
|
-
return false;
|
|
1042
|
-
}
|
|
1043
|
-
get supportsDeleteWithLimit() {
|
|
1044
|
-
return false;
|
|
1045
|
-
}
|
|
1046
|
-
get supportsDistinctOn() {
|
|
1047
|
-
return false;
|
|
1048
|
-
}
|
|
1049
|
-
buildArrayLength(eb, array) {
|
|
1050
|
-
return eb.fn("json_array_length", [
|
|
1051
|
-
array
|
|
1052
|
-
]);
|
|
1053
|
-
}
|
|
1054
|
-
buildArrayLiteralSQL(_values) {
|
|
1055
|
-
throw new Error("SQLite does not support array literals");
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
function getCrudDialect(schema, options) {
|
|
1061
|
-
return match4(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
|
|
1062
|
-
}
|
|
1063
|
-
__name(getCrudDialect, "getCrudDialect");
|
|
1064
|
-
|
|
1065
|
-
// src/schema/expression.ts
|
|
1066
|
-
var ExpressionUtils = {
|
|
1067
|
-
literal: /* @__PURE__ */ __name((value) => {
|
|
1068
|
-
return {
|
|
1069
|
-
kind: "literal",
|
|
1070
|
-
value
|
|
1071
|
-
};
|
|
1072
|
-
}, "literal"),
|
|
1073
|
-
array: /* @__PURE__ */ __name((items) => {
|
|
1074
|
-
return {
|
|
1075
|
-
kind: "array",
|
|
1076
|
-
items
|
|
1077
|
-
};
|
|
1078
|
-
}, "array"),
|
|
1079
|
-
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
1080
|
-
return {
|
|
1081
|
-
kind: "call",
|
|
1082
|
-
function: functionName,
|
|
1083
|
-
args
|
|
1084
|
-
};
|
|
1085
|
-
}, "call"),
|
|
1086
|
-
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
1087
|
-
return {
|
|
1088
|
-
kind: "binary",
|
|
1089
|
-
op,
|
|
1090
|
-
left,
|
|
1091
|
-
right
|
|
1092
|
-
};
|
|
1093
|
-
}, "binary"),
|
|
1094
|
-
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
1095
|
-
return {
|
|
1096
|
-
kind: "unary",
|
|
1097
|
-
op,
|
|
1098
|
-
operand
|
|
1099
|
-
};
|
|
1100
|
-
}, "unary"),
|
|
1101
|
-
field: /* @__PURE__ */ __name((field) => {
|
|
1102
|
-
return {
|
|
1103
|
-
kind: "field",
|
|
1104
|
-
field
|
|
1105
|
-
};
|
|
1106
|
-
}, "field"),
|
|
1107
|
-
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
1108
|
-
return {
|
|
1109
|
-
kind: "member",
|
|
1110
|
-
receiver,
|
|
1111
|
-
members
|
|
1112
|
-
};
|
|
1113
|
-
}, "member"),
|
|
1114
|
-
_this: /* @__PURE__ */ __name(() => {
|
|
1115
|
-
return {
|
|
1116
|
-
kind: "this"
|
|
1117
|
-
};
|
|
1118
|
-
}, "_this"),
|
|
1119
|
-
_null: /* @__PURE__ */ __name(() => {
|
|
1120
|
-
return {
|
|
1121
|
-
kind: "null"
|
|
1122
|
-
};
|
|
1123
|
-
}, "_null"),
|
|
1124
|
-
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1125
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
1126
|
-
}, "and"),
|
|
1127
|
-
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1128
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
1129
|
-
}, "or"),
|
|
1130
|
-
is: /* @__PURE__ */ __name((value, kind) => {
|
|
1131
|
-
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
1132
|
-
}, "is"),
|
|
1133
|
-
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
1134
|
-
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
1135
|
-
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
1136
|
-
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
1137
|
-
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
1138
|
-
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
1139
|
-
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
1140
|
-
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
1141
|
-
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
|
|
1343
|
+
if (relationFieldDef.array) {
|
|
1344
|
+
return eb.fn.coalesce(sql3`json_group_array(json_object(${sql3.join(objArgs)}))`, sql3`json_array()`).as("$j");
|
|
1345
|
+
} else {
|
|
1346
|
+
return sql3`json_object(${sql3.join(objArgs)})`.as("data");
|
|
1347
|
+
}
|
|
1348
|
+
});
|
|
1349
|
+
return tbl;
|
|
1350
|
+
}
|
|
1351
|
+
buildSkipTake(query, skip, take) {
|
|
1352
|
+
if (take !== void 0) {
|
|
1353
|
+
query = query.limit(take);
|
|
1354
|
+
}
|
|
1355
|
+
if (skip !== void 0) {
|
|
1356
|
+
query = query.offset(skip);
|
|
1357
|
+
if (take === void 0) {
|
|
1358
|
+
query = query.limit(-1);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
return query;
|
|
1362
|
+
}
|
|
1363
|
+
buildJsonObject(eb, value) {
|
|
1364
|
+
return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
|
|
1365
|
+
sql3.lit(key),
|
|
1366
|
+
value2
|
|
1367
|
+
]));
|
|
1368
|
+
}
|
|
1369
|
+
get supportsUpdateWithLimit() {
|
|
1370
|
+
return false;
|
|
1371
|
+
}
|
|
1372
|
+
get supportsDeleteWithLimit() {
|
|
1373
|
+
return false;
|
|
1374
|
+
}
|
|
1375
|
+
get supportsDistinctOn() {
|
|
1376
|
+
return false;
|
|
1377
|
+
}
|
|
1378
|
+
buildArrayLength(eb, array) {
|
|
1379
|
+
return eb.fn("json_array_length", [
|
|
1380
|
+
array
|
|
1381
|
+
]);
|
|
1382
|
+
}
|
|
1383
|
+
buildArrayLiteralSQL(_values) {
|
|
1384
|
+
throw new Error("SQLite does not support array literals");
|
|
1385
|
+
}
|
|
1386
|
+
get supportInsertWithDefault() {
|
|
1387
|
+
return false;
|
|
1388
|
+
}
|
|
1142
1389
|
};
|
|
1143
1390
|
|
|
1391
|
+
// src/client/crud/dialects/index.ts
|
|
1392
|
+
function getCrudDialect(schema, options) {
|
|
1393
|
+
return match5(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
|
|
1394
|
+
}
|
|
1395
|
+
__name(getCrudDialect, "getCrudDialect");
|
|
1396
|
+
|
|
1144
1397
|
// src/utils/default-operation-node-visitor.ts
|
|
1145
1398
|
import { OperationNodeVisitor } from "kysely";
|
|
1146
1399
|
var DefaultOperationNodeVisitor = class extends OperationNodeVisitor {
|
|
@@ -1460,19 +1713,19 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1460
1713
|
};
|
|
1461
1714
|
|
|
1462
1715
|
// src/plugins/policy/expression-transformer.ts
|
|
1463
|
-
import {
|
|
1464
|
-
import
|
|
1465
|
-
import { match as
|
|
1716
|
+
import { invariant as invariant5 } from "@zenstackhq/common-helpers";
|
|
1717
|
+
import { AliasNode as AliasNode2, BinaryOperationNode as BinaryOperationNode2, ColumnNode, expressionBuilder as expressionBuilder2, FromNode, FunctionNode as FunctionNode2, IdentifierNode, OperatorNode as OperatorNode2, ReferenceNode as ReferenceNode2, SelectionNode, SelectQueryNode, TableNode as TableNode2, ValueListNode, ValueNode as ValueNode2, WhereNode } from "kysely";
|
|
1718
|
+
import { match as match7 } from "ts-pattern";
|
|
1466
1719
|
|
|
1467
1720
|
// src/plugins/policy/expression-evaluator.ts
|
|
1468
|
-
import invariant4 from "
|
|
1469
|
-
import { match as
|
|
1721
|
+
import { invariant as invariant4 } from "@zenstackhq/common-helpers";
|
|
1722
|
+
import { match as match6 } from "ts-pattern";
|
|
1470
1723
|
var ExpressionEvaluator = class {
|
|
1471
1724
|
static {
|
|
1472
1725
|
__name(this, "ExpressionEvaluator");
|
|
1473
1726
|
}
|
|
1474
1727
|
evaluate(expression, context) {
|
|
1475
|
-
const result =
|
|
1728
|
+
const result = match6(expression).when(ExpressionUtils.isArray, (expr2) => this.evaluateArray(expr2, context)).when(ExpressionUtils.isBinary, (expr2) => this.evaluateBinary(expr2, context)).when(ExpressionUtils.isField, (expr2) => this.evaluateField(expr2, context)).when(ExpressionUtils.isLiteral, (expr2) => this.evaluateLiteral(expr2)).when(ExpressionUtils.isMember, (expr2) => this.evaluateMember(expr2, context)).when(ExpressionUtils.isUnary, (expr2) => this.evaluateUnary(expr2, context)).when(ExpressionUtils.isCall, (expr2) => this.evaluateCall(expr2, context)).when(ExpressionUtils.isThis, () => context.thisValue).when(ExpressionUtils.isNull, () => null).exhaustive();
|
|
1476
1729
|
return result ?? null;
|
|
1477
1730
|
}
|
|
1478
1731
|
evaluateCall(expr2, context) {
|
|
@@ -1483,7 +1736,7 @@ var ExpressionEvaluator = class {
|
|
|
1483
1736
|
}
|
|
1484
1737
|
}
|
|
1485
1738
|
evaluateUnary(expr2, context) {
|
|
1486
|
-
return
|
|
1739
|
+
return match6(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
|
|
1487
1740
|
}
|
|
1488
1741
|
evaluateMember(expr2, context) {
|
|
1489
1742
|
let val = this.evaluate(expr2.receiver, context);
|
|
@@ -1507,7 +1760,7 @@ var ExpressionEvaluator = class {
|
|
|
1507
1760
|
}
|
|
1508
1761
|
const left = this.evaluate(expr2.left, context);
|
|
1509
1762
|
const right = this.evaluate(expr2.right, context);
|
|
1510
|
-
return
|
|
1763
|
+
return match6(expr2.op).with("==", () => left === right).with("!=", () => left !== right).with(">", () => left > right).with(">=", () => left >= right).with("<", () => left < right).with("<=", () => left <= right).with("&&", () => left && right).with("||", () => left || right).with("in", () => {
|
|
1511
1764
|
const _right = right ?? [];
|
|
1512
1765
|
invariant4(Array.isArray(_right), 'expected array for "in" operator');
|
|
1513
1766
|
return _right.includes(left);
|
|
@@ -1521,7 +1774,7 @@ var ExpressionEvaluator = class {
|
|
|
1521
1774
|
return false;
|
|
1522
1775
|
}
|
|
1523
1776
|
invariant4(Array.isArray(left), "expected array");
|
|
1524
|
-
return
|
|
1777
|
+
return match6(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1525
1778
|
...context,
|
|
1526
1779
|
thisValue: item
|
|
1527
1780
|
}))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
|
|
@@ -1537,11 +1790,11 @@ var ExpressionEvaluator = class {
|
|
|
1537
1790
|
// src/plugins/policy/utils.ts
|
|
1538
1791
|
import { AliasNode, AndNode, BinaryOperationNode, FunctionNode, OperatorNode, OrNode, ParensNode, ReferenceNode, TableNode, UnaryOperationNode, ValueNode } from "kysely";
|
|
1539
1792
|
function trueNode(dialect) {
|
|
1540
|
-
return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
|
|
1793
|
+
return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1541
1794
|
}
|
|
1542
1795
|
__name(trueNode, "trueNode");
|
|
1543
1796
|
function falseNode(dialect) {
|
|
1544
|
-
return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
|
|
1797
|
+
return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1545
1798
|
}
|
|
1546
1799
|
__name(falseNode, "falseNode");
|
|
1547
1800
|
function isTrueNode(node) {
|
|
@@ -1775,7 +2028,7 @@ var ExpressionTransformer = class {
|
|
|
1775
2028
|
const count = FunctionNode2.create("count", [
|
|
1776
2029
|
ValueNode2.createImmediate(1)
|
|
1777
2030
|
]);
|
|
1778
|
-
const predicateResult =
|
|
2031
|
+
const predicateResult = match7(expr2.op).with("?", () => BinaryOperationNode2.create(count, OperatorNode2.create(">"), ValueNode2.createImmediate(0))).with("!", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).with("^", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).exhaustive();
|
|
1779
2032
|
return this.transform(expr2.left, {
|
|
1780
2033
|
...context,
|
|
1781
2034
|
memberSelect: SelectionNode.create(AliasNode2.create(predicateResult, IdentifierNode.create("$t"))),
|
|
@@ -1799,14 +2052,14 @@ var ExpressionTransformer = class {
|
|
|
1799
2052
|
}
|
|
1800
2053
|
}
|
|
1801
2054
|
transformValue(value, type) {
|
|
1802
|
-
return ValueNode2.create(this.dialect.transformPrimitive(value, type) ?? null);
|
|
2055
|
+
return ValueNode2.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
1803
2056
|
}
|
|
1804
2057
|
_unary(expr2, context) {
|
|
1805
2058
|
invariant5(expr2.op === "!", 'only "!" operator is supported');
|
|
1806
2059
|
return BinaryOperationNode2.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
|
|
1807
2060
|
}
|
|
1808
2061
|
transformOperator(op) {
|
|
1809
|
-
const mappedOp =
|
|
2062
|
+
const mappedOp = match7(op).with("==", () => "=").otherwise(() => op);
|
|
1810
2063
|
return OperatorNode2.create(mappedOp);
|
|
1811
2064
|
}
|
|
1812
2065
|
_call(expr2, context) {
|
|
@@ -1818,7 +2071,7 @@ var ExpressionTransformer = class {
|
|
|
1818
2071
|
if (!func) {
|
|
1819
2072
|
throw new QueryError(`Function not implemented: ${expr2.function}`);
|
|
1820
2073
|
}
|
|
1821
|
-
const eb =
|
|
2074
|
+
const eb = expressionBuilder2();
|
|
1822
2075
|
return func(eb, (expr2.args ?? []).map((arg) => this.transformCallArg(eb, arg, context)), {
|
|
1823
2076
|
dialect: this.dialect,
|
|
1824
2077
|
model: context.model,
|
|
@@ -2042,7 +2295,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2042
2295
|
get kysely() {
|
|
2043
2296
|
return this.client.$qb;
|
|
2044
2297
|
}
|
|
2045
|
-
async handle(node, proceed
|
|
2298
|
+
async handle(node, proceed) {
|
|
2046
2299
|
if (!this.isCrudQueryNode(node)) {
|
|
2047
2300
|
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
2048
2301
|
}
|
|
@@ -2062,27 +2315,20 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2062
2315
|
if (!mutationRequiresTransaction && !node.returning) {
|
|
2063
2316
|
return proceed(this.transformNode(node));
|
|
2064
2317
|
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
const
|
|
2072
|
-
if (
|
|
2073
|
-
|
|
2074
|
-
if (readBackResult.rows.length !== result2.rows.length) {
|
|
2075
|
-
readBackError = true;
|
|
2076
|
-
}
|
|
2077
|
-
return readBackResult;
|
|
2078
|
-
} else {
|
|
2079
|
-
return result2;
|
|
2318
|
+
if (InsertQueryNode.is(node)) {
|
|
2319
|
+
await this.enforcePreCreatePolicy(node, proceed);
|
|
2320
|
+
}
|
|
2321
|
+
const transformedNode = this.transformNode(node);
|
|
2322
|
+
const result = await proceed(transformedNode);
|
|
2323
|
+
if (!this.onlyReturningId(node)) {
|
|
2324
|
+
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2325
|
+
if (readBackResult.rows.length !== result.rows.length) {
|
|
2326
|
+
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
2080
2327
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2328
|
+
return readBackResult;
|
|
2329
|
+
} else {
|
|
2330
|
+
return result;
|
|
2084
2331
|
}
|
|
2085
|
-
return result;
|
|
2086
2332
|
}
|
|
2087
2333
|
onlyReturningId(node) {
|
|
2088
2334
|
if (!node.returning) {
|
|
@@ -2143,11 +2389,11 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2143
2389
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2144
2390
|
invariant6(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2145
2391
|
result.push({
|
|
2146
|
-
node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
|
|
2392
|
+
node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2147
2393
|
raw: item.value
|
|
2148
2394
|
});
|
|
2149
2395
|
} else {
|
|
2150
|
-
const value = this.dialect.transformPrimitive(item, fieldDef.type);
|
|
2396
|
+
const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
2151
2397
|
if (Array.isArray(value)) {
|
|
2152
2398
|
result.push({
|
|
2153
2399
|
node: RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
@@ -2216,7 +2462,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2216
2462
|
return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => BinaryOperationNode3.create(ColumnNode2.create(field), OperatorNode3.create("="), ValueNode3.create(row[field]))))));
|
|
2217
2463
|
}
|
|
2218
2464
|
getMutationModel(node) {
|
|
2219
|
-
const r =
|
|
2465
|
+
const r = match8(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
|
|
2220
2466
|
if (node2.from.froms.length !== 1) {
|
|
2221
2467
|
throw new InternalError("Only one from table is supported for delete");
|
|
2222
2468
|
}
|
|
@@ -2378,14 +2624,23 @@ var PolicyPlugin = class {
|
|
|
2378
2624
|
get description() {
|
|
2379
2625
|
return "Enforces access policies defined in the schema.";
|
|
2380
2626
|
}
|
|
2381
|
-
onKyselyQuery({
|
|
2627
|
+
onKyselyQuery({
|
|
2628
|
+
query,
|
|
2629
|
+
client,
|
|
2630
|
+
proceed
|
|
2631
|
+
/*, transaction*/
|
|
2632
|
+
}) {
|
|
2382
2633
|
const handler = new PolicyHandler(client);
|
|
2383
|
-
return handler.handle(
|
|
2634
|
+
return handler.handle(
|
|
2635
|
+
query,
|
|
2636
|
+
proceed
|
|
2637
|
+
/*, transaction*/
|
|
2638
|
+
);
|
|
2384
2639
|
}
|
|
2385
2640
|
};
|
|
2386
2641
|
|
|
2387
2642
|
// src/utils/clone.ts
|
|
2388
|
-
import { isPlainObject as isPlainObject2 } from "
|
|
2643
|
+
import { isPlainObject as isPlainObject2 } from "@zenstackhq/common-helpers";
|
|
2389
2644
|
function clone(value) {
|
|
2390
2645
|
if (Array.isArray(value)) {
|
|
2391
2646
|
return value.map((v) => clone(v));
|
|
@@ -2404,28 +2659,6 @@ function clone(value) {
|
|
|
2404
2659
|
}
|
|
2405
2660
|
__name(clone, "clone");
|
|
2406
2661
|
|
|
2407
|
-
// src/utils/object-utils.ts
|
|
2408
|
-
function extractFields(obj, fields) {
|
|
2409
|
-
return Object.fromEntries(Object.entries(obj).filter(([key]) => fields.includes(key)));
|
|
2410
|
-
}
|
|
2411
|
-
__name(extractFields, "extractFields");
|
|
2412
|
-
function fieldsToSelectObject(fields) {
|
|
2413
|
-
return Object.fromEntries(fields.map((f) => [
|
|
2414
|
-
f,
|
|
2415
|
-
true
|
|
2416
|
-
]));
|
|
2417
|
-
}
|
|
2418
|
-
__name(fieldsToSelectObject, "fieldsToSelectObject");
|
|
2419
|
-
|
|
2420
|
-
// src/client/constants.ts
|
|
2421
|
-
var CONTEXT_COMMENT_PREFIX = "-- $$context:";
|
|
2422
|
-
var NUMERIC_FIELD_TYPES = [
|
|
2423
|
-
"Int",
|
|
2424
|
-
"Float",
|
|
2425
|
-
"BigInt",
|
|
2426
|
-
"Decimal"
|
|
2427
|
-
];
|
|
2428
|
-
|
|
2429
2662
|
// src/client/crud/operations/base.ts
|
|
2430
2663
|
var BaseOperationHandler = class {
|
|
2431
2664
|
static {
|
|
@@ -2469,17 +2702,17 @@ var BaseOperationHandler = class {
|
|
|
2469
2702
|
getField(model, field) {
|
|
2470
2703
|
return getField(this.schema, model, field);
|
|
2471
2704
|
}
|
|
2472
|
-
exists(kysely, model, filter) {
|
|
2705
|
+
async exists(kysely, model, filter) {
|
|
2473
2706
|
const idFields = getIdFields(this.schema, model);
|
|
2474
2707
|
const _filter = flattenCompoundUniqueFilters(this.schema, model, filter);
|
|
2475
2708
|
const query = kysely.selectFrom(model).where((eb) => eb.and(_filter)).select(idFields.map((f) => kysely.dynamic.ref(f))).limit(1).modifyEnd(this.makeContextComment({
|
|
2476
2709
|
model,
|
|
2477
2710
|
operation: "read"
|
|
2478
2711
|
}));
|
|
2479
|
-
return
|
|
2712
|
+
return this.executeQueryTakeFirst(kysely, query, "exists");
|
|
2480
2713
|
}
|
|
2481
2714
|
async read(kysely, model, args) {
|
|
2482
|
-
let query =
|
|
2715
|
+
let query = this.dialect.buildSelectModel(expressionBuilder3(), model);
|
|
2483
2716
|
if (args?.where) {
|
|
2484
2717
|
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, args?.where));
|
|
2485
2718
|
}
|
|
@@ -2499,15 +2732,16 @@ var BaseOperationHandler = class {
|
|
|
2499
2732
|
query = query.distinctOn(distinct.map((f) => sql4.ref(`${model}.${f}`)));
|
|
2500
2733
|
} else {
|
|
2501
2734
|
inMemoryDistinct = distinct;
|
|
2735
|
+
query = distinct.reduce((acc, field) => acc.select((eb) => this.dialect.fieldRef(model, field, eb).as(`$distinct$${field}`)), query);
|
|
2502
2736
|
}
|
|
2503
2737
|
}
|
|
2504
|
-
if (args
|
|
2505
|
-
query = this.buildFieldSelection(model, query, args
|
|
2738
|
+
if (args && "select" in args && args.select) {
|
|
2739
|
+
query = this.buildFieldSelection(model, query, args.select, model);
|
|
2506
2740
|
} else {
|
|
2507
|
-
query = this.
|
|
2741
|
+
query = this.dialect.buildSelectAllFields(model, query, args?.omit);
|
|
2508
2742
|
}
|
|
2509
|
-
if (args
|
|
2510
|
-
query = this.buildFieldSelection(model, query, args
|
|
2743
|
+
if (args && "include" in args && args.include) {
|
|
2744
|
+
query = this.buildFieldSelection(model, query, args.include, model);
|
|
2511
2745
|
}
|
|
2512
2746
|
if (args?.cursor) {
|
|
2513
2747
|
query = this.buildCursorFilter(model, query, args.cursor, args.orderBy, negateOrderBy);
|
|
@@ -2517,23 +2751,35 @@ var BaseOperationHandler = class {
|
|
|
2517
2751
|
operation: "read"
|
|
2518
2752
|
}));
|
|
2519
2753
|
let result = [];
|
|
2754
|
+
const queryId = {
|
|
2755
|
+
queryId: `zenstack-${createId()}`
|
|
2756
|
+
};
|
|
2757
|
+
const compiled = kysely.getExecutor().compileQuery(query.toOperationNode(), queryId);
|
|
2520
2758
|
try {
|
|
2521
|
-
|
|
2759
|
+
const r = await kysely.getExecutor().executeQuery(compiled, queryId);
|
|
2760
|
+
result = r.rows;
|
|
2522
2761
|
} catch (err) {
|
|
2523
|
-
|
|
2524
|
-
|
|
2762
|
+
let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
|
|
2763
|
+
if (this.options.debug) {
|
|
2764
|
+
message += `, parameters:
|
|
2765
|
+
${compiled.parameters.map((p) => inspect(p)).join("\n")}`;
|
|
2766
|
+
}
|
|
2767
|
+
throw new QueryError(message, err);
|
|
2525
2768
|
}
|
|
2526
2769
|
if (inMemoryDistinct) {
|
|
2527
2770
|
const distinctResult = [];
|
|
2528
2771
|
const seen = /* @__PURE__ */ new Set();
|
|
2529
2772
|
for (const r of result) {
|
|
2530
|
-
const key = safeJSONStringify(inMemoryDistinct.map((f) => r[f]));
|
|
2773
|
+
const key = safeJSONStringify(inMemoryDistinct.map((f) => r[`$distinct$${f}`]));
|
|
2531
2774
|
if (!seen.has(key)) {
|
|
2532
2775
|
distinctResult.push(r);
|
|
2533
2776
|
seen.add(key);
|
|
2534
2777
|
}
|
|
2535
2778
|
}
|
|
2536
2779
|
result = distinctResult;
|
|
2780
|
+
for (const r of result) {
|
|
2781
|
+
Object.keys(r).filter((k) => k.startsWith("$distinct$")).forEach((k) => delete r[k]);
|
|
2782
|
+
}
|
|
2537
2783
|
}
|
|
2538
2784
|
return result;
|
|
2539
2785
|
}
|
|
@@ -2556,72 +2802,29 @@ var BaseOperationHandler = class {
|
|
|
2556
2802
|
}
|
|
2557
2803
|
const fieldDef = this.requireField(model, field);
|
|
2558
2804
|
if (!fieldDef.relation) {
|
|
2559
|
-
result = this.
|
|
2805
|
+
result = this.dialect.buildSelectField(result, model, parentAlias, field);
|
|
2560
2806
|
} else {
|
|
2561
2807
|
if (!fieldDef.array && !fieldDef.optional && payload.where) {
|
|
2562
2808
|
throw new QueryError(`Field "${field}" doesn't support filtering`);
|
|
2563
2809
|
}
|
|
2564
|
-
|
|
2810
|
+
if (fieldDef.originModel) {
|
|
2811
|
+
result = this.dialect.buildRelationSelection(result, fieldDef.originModel, field, fieldDef.originModel, payload);
|
|
2812
|
+
} else {
|
|
2813
|
+
result = this.dialect.buildRelationSelection(result, model, field, parentAlias, payload);
|
|
2814
|
+
}
|
|
2565
2815
|
}
|
|
2566
2816
|
}
|
|
2567
2817
|
return result;
|
|
2568
2818
|
}
|
|
2569
2819
|
buildCountSelection(query, model, parentAlias, payload) {
|
|
2570
|
-
|
|
2571
|
-
const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
|
|
2572
|
-
const selections = payload === true ? {
|
|
2573
|
-
select: toManyRelations.reduce((acc, [field]) => {
|
|
2574
|
-
acc[field] = true;
|
|
2575
|
-
return acc;
|
|
2576
|
-
}, {})
|
|
2577
|
-
} : payload;
|
|
2578
|
-
const eb = expressionBuilder2();
|
|
2579
|
-
const jsonObject = {};
|
|
2580
|
-
for (const [field, value] of Object.entries(selections.select)) {
|
|
2581
|
-
const fieldDef = requireField(this.schema, model, field);
|
|
2582
|
-
const fieldModel = fieldDef.type;
|
|
2583
|
-
const jointTable = `${parentAlias}$${field}$count`;
|
|
2584
|
-
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, jointTable);
|
|
2585
|
-
query = query.leftJoin((eb2) => {
|
|
2586
|
-
let result = eb2.selectFrom(fieldModel).selectAll();
|
|
2587
|
-
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
2588
|
-
const filter = this.dialect.buildFilter(eb2, fieldModel, fieldModel, value.where);
|
|
2589
|
-
result = result.where(filter);
|
|
2590
|
-
}
|
|
2591
|
-
return result.as(jointTable);
|
|
2592
|
-
}, (join) => {
|
|
2593
|
-
for (const [left, right] of joinPairs) {
|
|
2594
|
-
join = join.onRef(left, "=", right);
|
|
2595
|
-
}
|
|
2596
|
-
return join;
|
|
2597
|
-
});
|
|
2598
|
-
jsonObject[field] = this.countIdDistinct(eb, fieldDef.type, jointTable);
|
|
2599
|
-
}
|
|
2600
|
-
query = query.select((eb2) => this.dialect.buildJsonObject(eb2, jsonObject).as("_count"));
|
|
2601
|
-
return query;
|
|
2602
|
-
}
|
|
2603
|
-
countIdDistinct(eb, model, table) {
|
|
2604
|
-
const idFields = getIdFields(this.schema, model);
|
|
2605
|
-
return eb.fn.count(sql4.join(idFields.map((f) => sql4.ref(`${table}.${f}`)))).distinct();
|
|
2606
|
-
}
|
|
2607
|
-
buildSelectAllScalarFields(model, query, omit) {
|
|
2608
|
-
const modelDef = this.requireModel(model);
|
|
2609
|
-
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);
|
|
2610
|
-
}
|
|
2611
|
-
selectField(query, model, modelAlias, field) {
|
|
2612
|
-
const fieldDef = this.requireField(model, field);
|
|
2613
|
-
if (!fieldDef.computed) {
|
|
2614
|
-
return query.select(sql4.ref(`${modelAlias}.${field}`).as(field));
|
|
2615
|
-
} else {
|
|
2616
|
-
return query.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(field));
|
|
2617
|
-
}
|
|
2820
|
+
return query.select((eb) => this.dialect.buildCountJson(model, eb, parentAlias, payload).as("_count"));
|
|
2618
2821
|
}
|
|
2619
2822
|
buildCursorFilter(model, query, cursor, orderBy, negateOrderBy) {
|
|
2620
2823
|
if (!orderBy) {
|
|
2621
2824
|
orderBy = makeDefaultOrderBy(this.schema, model);
|
|
2622
2825
|
}
|
|
2623
2826
|
const orderByItems = ensureArray(orderBy).flatMap((obj) => Object.entries(obj));
|
|
2624
|
-
const eb =
|
|
2827
|
+
const eb = expressionBuilder3();
|
|
2625
2828
|
const cursorFilter = this.dialect.buildFilter(eb, model, model, cursor);
|
|
2626
2829
|
let result = query;
|
|
2627
2830
|
const filters = [];
|
|
@@ -2638,9 +2841,12 @@ var BaseOperationHandler = class {
|
|
|
2638
2841
|
result = result.where((eb2) => eb2.or(filters));
|
|
2639
2842
|
return result;
|
|
2640
2843
|
}
|
|
2641
|
-
async create(kysely, model, data, fromRelation) {
|
|
2844
|
+
async create(kysely, model, data, fromRelation, creatingForDelegate = false) {
|
|
2642
2845
|
const modelDef = this.requireModel(model);
|
|
2643
|
-
|
|
2846
|
+
if (modelDef.isDelegate && !creatingForDelegate) {
|
|
2847
|
+
throw new QueryError(`Model "${this.model}" is a delegate and cannot be created directly.`);
|
|
2848
|
+
}
|
|
2849
|
+
let createFields = {};
|
|
2644
2850
|
let parentUpdateTask = void 0;
|
|
2645
2851
|
let m2m = void 0;
|
|
2646
2852
|
if (fromRelation) {
|
|
@@ -2659,7 +2865,7 @@ var BaseOperationHandler = class {
|
|
|
2659
2865
|
model: fromRelation.model,
|
|
2660
2866
|
operation: "update"
|
|
2661
2867
|
}));
|
|
2662
|
-
return
|
|
2868
|
+
return this.executeQuery(kysely, query2, "update");
|
|
2663
2869
|
}, "parentUpdateTask");
|
|
2664
2870
|
}
|
|
2665
2871
|
}
|
|
@@ -2669,14 +2875,14 @@ var BaseOperationHandler = class {
|
|
|
2669
2875
|
const fieldDef = this.requireField(model, field);
|
|
2670
2876
|
if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
|
|
2671
2877
|
if (fieldDef.array && value && typeof value === "object" && "set" in value && Array.isArray(value.set)) {
|
|
2672
|
-
createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type);
|
|
2878
|
+
createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type, true);
|
|
2673
2879
|
} else {
|
|
2674
|
-
createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type);
|
|
2880
|
+
createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
2675
2881
|
}
|
|
2676
2882
|
} else {
|
|
2677
2883
|
const subM2M = getManyToManyRelation(this.schema, model, field);
|
|
2678
2884
|
if (!subM2M && fieldDef.relation?.fields && fieldDef.relation?.references) {
|
|
2679
|
-
const fkValues = await this.
|
|
2885
|
+
const fkValues = await this.processOwnedRelationForCreate(kysely, fieldDef, value);
|
|
2680
2886
|
for (let i = 0; i < fieldDef.relation.fields.length; i++) {
|
|
2681
2887
|
createFields[fieldDef.relation.fields[i]] = fkValues[fieldDef.relation.references[i]];
|
|
2682
2888
|
}
|
|
@@ -2688,16 +2894,20 @@ var BaseOperationHandler = class {
|
|
|
2688
2894
|
}
|
|
2689
2895
|
}
|
|
2690
2896
|
}
|
|
2897
|
+
if (modelDef.baseModel) {
|
|
2898
|
+
const baseCreateResult = await this.processBaseModelCreate(kysely, modelDef.baseModel, createFields, model);
|
|
2899
|
+
createFields = baseCreateResult.remainingFields;
|
|
2900
|
+
}
|
|
2691
2901
|
const updatedData = this.fillGeneratedValues(modelDef, createFields);
|
|
2692
2902
|
const idFields = getIdFields(this.schema, model);
|
|
2693
|
-
const query = kysely.insertInto(model).values(updatedData).returning(idFields).modifyEnd(this.makeContextComment({
|
|
2903
|
+
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({
|
|
2694
2904
|
model,
|
|
2695
2905
|
operation: "create"
|
|
2696
2906
|
}));
|
|
2697
|
-
const createdEntity = await
|
|
2907
|
+
const createdEntity = await this.executeQueryTakeFirst(kysely, query, "create");
|
|
2698
2908
|
if (Object.keys(postCreateRelations).length > 0) {
|
|
2699
2909
|
const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
|
|
2700
|
-
return this.
|
|
2910
|
+
return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
|
|
2701
2911
|
});
|
|
2702
2912
|
await Promise.all(relationPromises);
|
|
2703
2913
|
}
|
|
@@ -2709,6 +2919,28 @@ var BaseOperationHandler = class {
|
|
|
2709
2919
|
}
|
|
2710
2920
|
return createdEntity;
|
|
2711
2921
|
}
|
|
2922
|
+
async processBaseModelCreate(kysely, model, createFields, forModel) {
|
|
2923
|
+
const thisCreateFields = {};
|
|
2924
|
+
const remainingFields = {};
|
|
2925
|
+
Object.entries(createFields).forEach(([field, value]) => {
|
|
2926
|
+
const fieldDef = this.getField(model, field);
|
|
2927
|
+
if (fieldDef) {
|
|
2928
|
+
thisCreateFields[field] = value;
|
|
2929
|
+
} else {
|
|
2930
|
+
remainingFields[field] = value;
|
|
2931
|
+
}
|
|
2932
|
+
});
|
|
2933
|
+
const discriminatorField = getDiscriminatorField(this.schema, model);
|
|
2934
|
+
invariant7(discriminatorField, `Base model "${model}" must have a discriminator field`);
|
|
2935
|
+
thisCreateFields[discriminatorField] = forModel;
|
|
2936
|
+
const baseEntity = await this.create(kysely, model, thisCreateFields, void 0, true);
|
|
2937
|
+
const idValues = extractIdFields(baseEntity, this.schema, model);
|
|
2938
|
+
Object.assign(remainingFields, idValues);
|
|
2939
|
+
return {
|
|
2940
|
+
baseEntity,
|
|
2941
|
+
remainingFields
|
|
2942
|
+
};
|
|
2943
|
+
}
|
|
2712
2944
|
buildFkAssignments(model, relationField, entity) {
|
|
2713
2945
|
const parentFkFields = {};
|
|
2714
2946
|
invariant7(relationField, "parentField must be defined if parentModel is defined");
|
|
@@ -2751,7 +2983,7 @@ var BaseOperationHandler = class {
|
|
|
2751
2983
|
]).doNothing()).execute();
|
|
2752
2984
|
return result[0];
|
|
2753
2985
|
} else {
|
|
2754
|
-
const eb =
|
|
2986
|
+
const eb = expressionBuilder3();
|
|
2755
2987
|
const result = await kysely.deleteFrom(joinTable).where(eb(`${joinTable}.A`, "=", sortedRecords[0].entity[firstIds[0]])).where(eb(`${joinTable}.B`, "=", sortedRecords[1].entity[secondIds[0]])).execute();
|
|
2756
2988
|
return result[0];
|
|
2757
2989
|
}
|
|
@@ -2761,10 +2993,10 @@ var BaseOperationHandler = class {
|
|
|
2761
2993
|
const parentId = Object.values(parentIds)[0];
|
|
2762
2994
|
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
2763
2995
|
invariant7(m2m, "not a many-to-many relation");
|
|
2764
|
-
const eb =
|
|
2996
|
+
const eb = expressionBuilder3();
|
|
2765
2997
|
return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
|
|
2766
2998
|
}
|
|
2767
|
-
async
|
|
2999
|
+
async processOwnedRelationForCreate(kysely, relationField, payload) {
|
|
2768
3000
|
if (!payload) {
|
|
2769
3001
|
return;
|
|
2770
3002
|
}
|
|
@@ -2814,21 +3046,27 @@ var BaseOperationHandler = class {
|
|
|
2814
3046
|
}
|
|
2815
3047
|
return result;
|
|
2816
3048
|
}
|
|
2817
|
-
|
|
3049
|
+
processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
|
|
2818
3050
|
const relationFieldDef = this.requireField(contextModel, relationFieldName);
|
|
2819
3051
|
const relationModel = relationFieldDef.type;
|
|
2820
3052
|
const tasks = [];
|
|
3053
|
+
const fromRelationContext = {
|
|
3054
|
+
model: contextModel,
|
|
3055
|
+
field: relationFieldName,
|
|
3056
|
+
ids: parentEntity
|
|
3057
|
+
};
|
|
2821
3058
|
for (const [action, subPayload] of Object.entries(payload)) {
|
|
2822
3059
|
if (!subPayload) {
|
|
2823
3060
|
continue;
|
|
2824
3061
|
}
|
|
2825
3062
|
switch (action) {
|
|
2826
3063
|
case "create": {
|
|
2827
|
-
tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item,
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
3064
|
+
tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, fromRelationContext)));
|
|
3065
|
+
break;
|
|
3066
|
+
}
|
|
3067
|
+
case "createMany": {
|
|
3068
|
+
invariant7(relationFieldDef.array, "relation must be an array for createMany");
|
|
3069
|
+
tasks.push(this.createMany(kysely, relationModel, subPayload, false, fromRelationContext));
|
|
2832
3070
|
break;
|
|
2833
3071
|
}
|
|
2834
3072
|
case "connect": {
|
|
@@ -2858,6 +3096,11 @@ var BaseOperationHandler = class {
|
|
|
2858
3096
|
return Promise.all(tasks);
|
|
2859
3097
|
}
|
|
2860
3098
|
async createMany(kysely, model, input, returnData, fromRelation) {
|
|
3099
|
+
if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
|
|
3100
|
+
return returnData ? [] : {
|
|
3101
|
+
count: 0
|
|
3102
|
+
};
|
|
3103
|
+
}
|
|
2861
3104
|
const modelDef = this.requireModel(model);
|
|
2862
3105
|
let relationKeyPairs = [];
|
|
2863
3106
|
if (fromRelation) {
|
|
@@ -2867,12 +3110,12 @@ var BaseOperationHandler = class {
|
|
|
2867
3110
|
}
|
|
2868
3111
|
relationKeyPairs = keyPairs;
|
|
2869
3112
|
}
|
|
2870
|
-
|
|
3113
|
+
let createData = enumerate(input.data).map((item) => {
|
|
2871
3114
|
const newItem = {};
|
|
2872
3115
|
for (const [name, value] of Object.entries(item)) {
|
|
2873
3116
|
const fieldDef = this.requireField(model, name);
|
|
2874
3117
|
invariant7(!fieldDef.relation, "createMany does not support relations");
|
|
2875
|
-
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type);
|
|
3118
|
+
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
2876
3119
|
}
|
|
2877
3120
|
if (fromRelation) {
|
|
2878
3121
|
for (const { fk, pk } of relationKeyPairs) {
|
|
@@ -2881,14 +3124,44 @@ var BaseOperationHandler = class {
|
|
|
2881
3124
|
}
|
|
2882
3125
|
return this.fillGeneratedValues(modelDef, newItem);
|
|
2883
3126
|
});
|
|
3127
|
+
if (!this.dialect.supportInsertWithDefault) {
|
|
3128
|
+
const allPassedFields = createData.reduce((acc, item) => {
|
|
3129
|
+
Object.keys(item).forEach((field) => {
|
|
3130
|
+
if (!acc.includes(field)) {
|
|
3131
|
+
acc.push(field);
|
|
3132
|
+
}
|
|
3133
|
+
});
|
|
3134
|
+
return acc;
|
|
3135
|
+
}, []);
|
|
3136
|
+
for (const item of createData) {
|
|
3137
|
+
if (Object.keys(item).length === allPassedFields.length) {
|
|
3138
|
+
continue;
|
|
3139
|
+
}
|
|
3140
|
+
for (const field of allPassedFields) {
|
|
3141
|
+
if (!(field in item)) {
|
|
3142
|
+
const fieldDef = this.requireField(model, field);
|
|
3143
|
+
if (fieldDef.default !== void 0 && fieldDef.default !== null && typeof fieldDef.default !== "object") {
|
|
3144
|
+
item[field] = this.dialect.transformPrimitive(fieldDef.default, fieldDef.type, !!fieldDef.array);
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
if (modelDef.baseModel) {
|
|
3151
|
+
if (input.skipDuplicates) {
|
|
3152
|
+
throw new QueryError('"skipDuplicates" options is not supported for polymorphic models');
|
|
3153
|
+
}
|
|
3154
|
+
const baseCreateResult = await this.processBaseModelCreateMany(kysely, modelDef.baseModel, createData, !!input.skipDuplicates, model);
|
|
3155
|
+
createData = baseCreateResult.remainingFieldRows;
|
|
3156
|
+
}
|
|
2884
3157
|
const query = kysely.insertInto(model).values(createData).$if(!!input.skipDuplicates, (qb) => qb.onConflict((oc) => oc.doNothing())).modifyEnd(this.makeContextComment({
|
|
2885
3158
|
model,
|
|
2886
3159
|
operation: "create"
|
|
2887
3160
|
}));
|
|
2888
3161
|
if (!returnData) {
|
|
2889
|
-
const result = await
|
|
3162
|
+
const result = await this.executeQuery(kysely, query, "createMany");
|
|
2890
3163
|
return {
|
|
2891
|
-
count: Number(result.
|
|
3164
|
+
count: Number(result.numAffectedRows)
|
|
2892
3165
|
};
|
|
2893
3166
|
} else {
|
|
2894
3167
|
const idFields = getIdFields(this.schema, model);
|
|
@@ -2896,10 +3169,46 @@ var BaseOperationHandler = class {
|
|
|
2896
3169
|
return result;
|
|
2897
3170
|
}
|
|
2898
3171
|
}
|
|
3172
|
+
async processBaseModelCreateMany(kysely, model, createRows, skipDuplicates, forModel) {
|
|
3173
|
+
const thisCreateRows = [];
|
|
3174
|
+
const remainingFieldRows = [];
|
|
3175
|
+
const discriminatorField = getDiscriminatorField(this.schema, model);
|
|
3176
|
+
invariant7(discriminatorField, `Base model "${model}" must have a discriminator field`);
|
|
3177
|
+
for (const createFields of createRows) {
|
|
3178
|
+
const thisCreateFields = {};
|
|
3179
|
+
const remainingFields = {};
|
|
3180
|
+
Object.entries(createFields).forEach(([field, value]) => {
|
|
3181
|
+
const fieldDef = this.getField(model, field);
|
|
3182
|
+
if (fieldDef) {
|
|
3183
|
+
thisCreateFields[field] = value;
|
|
3184
|
+
} else {
|
|
3185
|
+
remainingFields[field] = value;
|
|
3186
|
+
}
|
|
3187
|
+
});
|
|
3188
|
+
thisCreateFields[discriminatorField] = forModel;
|
|
3189
|
+
thisCreateRows.push(thisCreateFields);
|
|
3190
|
+
remainingFieldRows.push(remainingFields);
|
|
3191
|
+
}
|
|
3192
|
+
const baseEntities = await this.createMany(kysely, model, {
|
|
3193
|
+
data: thisCreateRows,
|
|
3194
|
+
skipDuplicates
|
|
3195
|
+
}, true);
|
|
3196
|
+
for (let i = 0; i < baseEntities.length; i++) {
|
|
3197
|
+
const idValues = extractIdFields(baseEntities[i], this.schema, model);
|
|
3198
|
+
Object.assign(remainingFieldRows[i], idValues);
|
|
3199
|
+
}
|
|
3200
|
+
return {
|
|
3201
|
+
baseEntities,
|
|
3202
|
+
remainingFieldRows
|
|
3203
|
+
};
|
|
3204
|
+
}
|
|
2899
3205
|
fillGeneratedValues(modelDef, data) {
|
|
2900
3206
|
const fields = modelDef.fields;
|
|
2901
3207
|
const values = clone(data);
|
|
2902
|
-
for (const field
|
|
3208
|
+
for (const [field, fieldDef] of Object.entries(fields)) {
|
|
3209
|
+
if (fieldDef.originModel) {
|
|
3210
|
+
continue;
|
|
3211
|
+
}
|
|
2903
3212
|
if (!(field in data)) {
|
|
2904
3213
|
if (typeof fields[field]?.default === "object" && "kind" in fields[field].default) {
|
|
2905
3214
|
const generated = this.evalGenerator(fields[field].default);
|
|
@@ -2907,7 +3216,7 @@ var BaseOperationHandler = class {
|
|
|
2907
3216
|
values[field] = generated;
|
|
2908
3217
|
}
|
|
2909
3218
|
} else if (fields[field]?.updatedAt) {
|
|
2910
|
-
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
|
|
3219
|
+
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
2911
3220
|
}
|
|
2912
3221
|
}
|
|
2913
3222
|
}
|
|
@@ -2915,7 +3224,7 @@ var BaseOperationHandler = class {
|
|
|
2915
3224
|
}
|
|
2916
3225
|
evalGenerator(defaultValue) {
|
|
2917
3226
|
if (ExpressionUtils.isCall(defaultValue)) {
|
|
2918
|
-
return
|
|
3227
|
+
return match9(defaultValue.function).with("cuid", () => createId()).with("uuid", () => defaultValue.args?.[0] && ExpressionUtils.isLiteral(defaultValue.args?.[0]) && defaultValue.args[0].value === 7 ? uuid.v7() : uuid.v4()).with("nanoid", () => defaultValue.args?.[0] && ExpressionUtils.isLiteral(defaultValue.args[0]) && typeof defaultValue.args[0].value === "number" ? nanoid(defaultValue.args[0].value) : nanoid()).with("ulid", () => ulid()).otherwise(() => void 0);
|
|
2919
3228
|
} else if (ExpressionUtils.isMember(defaultValue) && ExpressionUtils.isCall(defaultValue.receiver) && defaultValue.receiver.function === "auth") {
|
|
2920
3229
|
let val = this.client.$auth;
|
|
2921
3230
|
for (const member of defaultValue.members) {
|
|
@@ -2972,32 +3281,37 @@ var BaseOperationHandler = class {
|
|
|
2972
3281
|
if (finalData === data) {
|
|
2973
3282
|
finalData = clone(data);
|
|
2974
3283
|
}
|
|
2975
|
-
finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
|
|
3284
|
+
finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
2976
3285
|
}
|
|
2977
3286
|
}
|
|
2978
3287
|
if (Object.keys(finalData).length === 0) {
|
|
2979
|
-
|
|
2980
|
-
|
|
3288
|
+
return combinedWhere;
|
|
3289
|
+
}
|
|
3290
|
+
let needIdRead = false;
|
|
3291
|
+
if (modelDef.baseModel && !this.isIdFilter(model, combinedWhere)) {
|
|
3292
|
+
needIdRead = true;
|
|
3293
|
+
}
|
|
3294
|
+
if (needIdRead) {
|
|
3295
|
+
const readResult = await this.readUnique(kysely, model, {
|
|
3296
|
+
where: combinedWhere,
|
|
3297
|
+
select: this.makeIdSelect(model)
|
|
2981
3298
|
});
|
|
2982
|
-
if (!
|
|
3299
|
+
if (!readResult && throwIfNotFound) {
|
|
2983
3300
|
throw new NotFoundError(model);
|
|
2984
3301
|
}
|
|
2985
|
-
|
|
3302
|
+
combinedWhere = readResult;
|
|
3303
|
+
}
|
|
3304
|
+
if (modelDef.baseModel) {
|
|
3305
|
+
const baseUpdateResult = await this.processBaseModelUpdate(kysely, modelDef.baseModel, combinedWhere, finalData, throwIfNotFound);
|
|
3306
|
+
finalData = baseUpdateResult.remainingFields;
|
|
3307
|
+
combinedWhere = baseUpdateResult.baseEntity;
|
|
2986
3308
|
}
|
|
2987
3309
|
const updateFields = {};
|
|
2988
3310
|
let thisEntity = void 0;
|
|
2989
3311
|
for (const field in finalData) {
|
|
2990
3312
|
const fieldDef = this.requireField(model, field);
|
|
2991
3313
|
if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
|
|
2992
|
-
|
|
2993
|
-
updateFields[field] = this.transformIncrementalUpdate(model, field, fieldDef, finalData[field]);
|
|
2994
|
-
continue;
|
|
2995
|
-
}
|
|
2996
|
-
if (fieldDef.array && typeof finalData[field] === "object" && !Array.isArray(finalData[field]) && finalData[field]) {
|
|
2997
|
-
updateFields[field] = this.transformScalarListUpdate(model, field, fieldDef, finalData[field]);
|
|
2998
|
-
continue;
|
|
2999
|
-
}
|
|
3000
|
-
updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type);
|
|
3314
|
+
updateFields[field] = this.processScalarFieldUpdateData(model, field, finalData);
|
|
3001
3315
|
} else {
|
|
3002
3316
|
if (!allowRelationUpdate) {
|
|
3003
3317
|
throw new QueryError(`Relation update not allowed for field "${field}"`);
|
|
@@ -3019,16 +3333,14 @@ var BaseOperationHandler = class {
|
|
|
3019
3333
|
}
|
|
3020
3334
|
}
|
|
3021
3335
|
if (Object.keys(updateFields).length === 0) {
|
|
3022
|
-
return
|
|
3023
|
-
where: combinedWhere
|
|
3024
|
-
});
|
|
3336
|
+
return combinedWhere;
|
|
3025
3337
|
} else {
|
|
3026
3338
|
const idFields = getIdFields(this.schema, model);
|
|
3027
3339
|
const query = kysely.updateTable(model).where((eb) => this.dialect.buildFilter(eb, model, model, combinedWhere)).set(updateFields).returning(idFields).modifyEnd(this.makeContextComment({
|
|
3028
3340
|
model,
|
|
3029
3341
|
operation: "update"
|
|
3030
3342
|
}));
|
|
3031
|
-
const updatedEntity = await
|
|
3343
|
+
const updatedEntity = await this.executeQueryTakeFirst(kysely, query, "update");
|
|
3032
3344
|
if (!updatedEntity) {
|
|
3033
3345
|
if (throwIfNotFound) {
|
|
3034
3346
|
throw new NotFoundError(model);
|
|
@@ -3039,23 +3351,72 @@ var BaseOperationHandler = class {
|
|
|
3039
3351
|
return updatedEntity;
|
|
3040
3352
|
}
|
|
3041
3353
|
}
|
|
3354
|
+
processScalarFieldUpdateData(model, field, data) {
|
|
3355
|
+
const fieldDef = this.requireField(model, field);
|
|
3356
|
+
if (this.isNumericIncrementalUpdate(fieldDef, data[field])) {
|
|
3357
|
+
return this.transformIncrementalUpdate(model, field, fieldDef, data[field]);
|
|
3358
|
+
}
|
|
3359
|
+
if (fieldDef.array && typeof data[field] === "object" && !Array.isArray(data[field]) && data[field]) {
|
|
3360
|
+
return this.transformScalarListUpdate(model, field, fieldDef, data[field]);
|
|
3361
|
+
}
|
|
3362
|
+
return this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
|
|
3363
|
+
}
|
|
3364
|
+
isNumericIncrementalUpdate(fieldDef, value) {
|
|
3365
|
+
if (!this.isNumericField(fieldDef)) {
|
|
3366
|
+
return false;
|
|
3367
|
+
}
|
|
3368
|
+
if (typeof value !== "object" || !value) {
|
|
3369
|
+
return false;
|
|
3370
|
+
}
|
|
3371
|
+
return [
|
|
3372
|
+
"increment",
|
|
3373
|
+
"decrement",
|
|
3374
|
+
"multiply",
|
|
3375
|
+
"divide",
|
|
3376
|
+
"set"
|
|
3377
|
+
].some((key) => key in value);
|
|
3378
|
+
}
|
|
3379
|
+
isIdFilter(model, filter) {
|
|
3380
|
+
if (!filter || typeof filter !== "object") {
|
|
3381
|
+
return false;
|
|
3382
|
+
}
|
|
3383
|
+
const idFields = getIdFields(this.schema, model);
|
|
3384
|
+
return idFields.length === Object.keys(filter).length && idFields.every((field) => field in filter);
|
|
3385
|
+
}
|
|
3386
|
+
async processBaseModelUpdate(kysely, model, where, updateFields, throwIfNotFound) {
|
|
3387
|
+
const thisUpdateFields = {};
|
|
3388
|
+
const remainingFields = {};
|
|
3389
|
+
Object.entries(updateFields).forEach(([field, value]) => {
|
|
3390
|
+
const fieldDef = this.getField(model, field);
|
|
3391
|
+
if (fieldDef) {
|
|
3392
|
+
thisUpdateFields[field] = value;
|
|
3393
|
+
} else {
|
|
3394
|
+
remainingFields[field] = value;
|
|
3395
|
+
}
|
|
3396
|
+
});
|
|
3397
|
+
const baseEntity = await this.update(kysely, model, where, thisUpdateFields, void 0, void 0, throwIfNotFound);
|
|
3398
|
+
return {
|
|
3399
|
+
baseEntity,
|
|
3400
|
+
remainingFields
|
|
3401
|
+
};
|
|
3402
|
+
}
|
|
3042
3403
|
transformIncrementalUpdate(model, field, fieldDef, payload) {
|
|
3043
3404
|
invariant7(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
|
|
3044
3405
|
const key = Object.keys(payload)[0];
|
|
3045
|
-
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
|
|
3046
|
-
const eb =
|
|
3047
|
-
const fieldRef =
|
|
3048
|
-
return
|
|
3406
|
+
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
|
|
3407
|
+
const eb = expressionBuilder3();
|
|
3408
|
+
const fieldRef = this.dialect.fieldRef(model, field, eb);
|
|
3409
|
+
return match9(key).with("set", () => value).with("increment", () => eb(fieldRef, "+", value)).with("decrement", () => eb(fieldRef, "-", value)).with("multiply", () => eb(fieldRef, "*", value)).with("divide", () => eb(fieldRef, "/", value)).otherwise(() => {
|
|
3049
3410
|
throw new InternalError(`Invalid incremental update operation: ${key}`);
|
|
3050
3411
|
});
|
|
3051
3412
|
}
|
|
3052
3413
|
transformScalarListUpdate(model, field, fieldDef, payload) {
|
|
3053
3414
|
invariant7(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
|
|
3054
3415
|
const key = Object.keys(payload)[0];
|
|
3055
|
-
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
|
|
3056
|
-
const eb =
|
|
3057
|
-
const fieldRef =
|
|
3058
|
-
return
|
|
3416
|
+
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
|
|
3417
|
+
const eb = expressionBuilder3();
|
|
3418
|
+
const fieldRef = this.dialect.fieldRef(model, field, eb);
|
|
3419
|
+
return match9(key).with("set", () => value).with("push", () => {
|
|
3059
3420
|
return eb(fieldRef, "||", eb.val(ensureArray(value)));
|
|
3060
3421
|
}).otherwise(() => {
|
|
3061
3422
|
throw new InternalError(`Invalid array update operation: ${key}`);
|
|
@@ -3067,7 +3428,7 @@ var BaseOperationHandler = class {
|
|
|
3067
3428
|
makeContextComment(context) {
|
|
3068
3429
|
return sql4.raw(`${CONTEXT_COMMENT_PREFIX}${JSON.stringify(context)}`);
|
|
3069
3430
|
}
|
|
3070
|
-
async updateMany(kysely, model, where, data, limit, returnData) {
|
|
3431
|
+
async updateMany(kysely, model, where, data, limit, returnData, filterModel) {
|
|
3071
3432
|
if (typeof data !== "object") {
|
|
3072
3433
|
throw new InternalError("data must be an object");
|
|
3073
3434
|
}
|
|
@@ -3076,49 +3437,79 @@ var BaseOperationHandler = class {
|
|
|
3076
3437
|
count: 0
|
|
3077
3438
|
};
|
|
3078
3439
|
}
|
|
3079
|
-
const
|
|
3440
|
+
const modelDef = this.requireModel(model);
|
|
3441
|
+
if (modelDef.baseModel && limit !== void 0) {
|
|
3442
|
+
throw new QueryError("Updating with a limit is not supported for polymorphic models");
|
|
3443
|
+
}
|
|
3444
|
+
filterModel ??= model;
|
|
3445
|
+
let updateFields = {};
|
|
3080
3446
|
for (const field in data) {
|
|
3081
|
-
const fieldDef = this.requireField(model, field);
|
|
3082
3447
|
if (isRelationField(this.schema, model, field)) {
|
|
3083
3448
|
continue;
|
|
3084
3449
|
}
|
|
3085
|
-
updateFields[field] = this.
|
|
3450
|
+
updateFields[field] = this.processScalarFieldUpdateData(model, field, data);
|
|
3451
|
+
}
|
|
3452
|
+
let shouldFallbackToIdFilter = false;
|
|
3453
|
+
if (limit !== void 0 && !this.dialect.supportsUpdateWithLimit) {
|
|
3454
|
+
shouldFallbackToIdFilter = true;
|
|
3455
|
+
}
|
|
3456
|
+
if (modelDef.isDelegate || modelDef.baseModel) {
|
|
3457
|
+
shouldFallbackToIdFilter = true;
|
|
3458
|
+
}
|
|
3459
|
+
let resultFromBaseModel = void 0;
|
|
3460
|
+
if (modelDef.baseModel) {
|
|
3461
|
+
const baseResult = await this.processBaseModelUpdateMany(kysely, modelDef.baseModel, where, updateFields, filterModel);
|
|
3462
|
+
updateFields = baseResult.remainingFields;
|
|
3463
|
+
resultFromBaseModel = baseResult.baseResult;
|
|
3464
|
+
}
|
|
3465
|
+
if (Object.keys(updateFields).length === 0) {
|
|
3466
|
+
return resultFromBaseModel ?? (returnData ? [] : {
|
|
3467
|
+
count: 0
|
|
3468
|
+
});
|
|
3086
3469
|
}
|
|
3087
3470
|
let query = kysely.updateTable(model).set(updateFields);
|
|
3088
|
-
if (
|
|
3089
|
-
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
|
|
3471
|
+
if (!shouldFallbackToIdFilter) {
|
|
3472
|
+
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where)).$if(limit !== void 0, (qb) => qb.limit(limit));
|
|
3090
3473
|
} else {
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
query = query.where((eb) => eb(eb.refTuple(
|
|
3095
|
-
...this.buildIdFieldRefs(kysely, model)
|
|
3096
|
-
), "in", kysely.selectFrom(model).where((eb2) => this.dialect.buildFilter(eb2, model, model, where)).select(this.buildIdFieldRefs(kysely, model)).limit(limit)));
|
|
3097
|
-
}
|
|
3474
|
+
query = query.where((eb) => eb(eb.refTuple(
|
|
3475
|
+
...this.buildIdFieldRefs(kysely, model)
|
|
3476
|
+
), "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))));
|
|
3098
3477
|
}
|
|
3099
3478
|
query = query.modifyEnd(this.makeContextComment({
|
|
3100
3479
|
model,
|
|
3101
3480
|
operation: "update"
|
|
3102
3481
|
}));
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3482
|
+
if (!returnData) {
|
|
3483
|
+
const result = await this.executeQuery(kysely, query, "update");
|
|
3484
|
+
return {
|
|
3485
|
+
count: Number(result.numAffectedRows)
|
|
3486
|
+
};
|
|
3487
|
+
} else {
|
|
3488
|
+
const idFields = getIdFields(this.schema, model);
|
|
3489
|
+
const result = await query.returning(idFields).execute();
|
|
3490
|
+
return result;
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
async processBaseModelUpdateMany(kysely, model, where, updateFields, filterModel) {
|
|
3494
|
+
const thisUpdateFields = {};
|
|
3495
|
+
const remainingFields = {};
|
|
3496
|
+
Object.entries(updateFields).forEach(([field, value]) => {
|
|
3497
|
+
const fieldDef = this.getField(model, field);
|
|
3498
|
+
if (fieldDef) {
|
|
3499
|
+
thisUpdateFields[field] = value;
|
|
3109
3500
|
} else {
|
|
3110
|
-
|
|
3111
|
-
const result = await query.returning(idFields).execute();
|
|
3112
|
-
return result;
|
|
3501
|
+
remainingFields[field] = value;
|
|
3113
3502
|
}
|
|
3114
|
-
}
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3503
|
+
});
|
|
3504
|
+
const baseResult = await this.updateMany(kysely, model, where, thisUpdateFields, void 0, false, filterModel);
|
|
3505
|
+
return {
|
|
3506
|
+
baseResult,
|
|
3507
|
+
remainingFields
|
|
3508
|
+
};
|
|
3118
3509
|
}
|
|
3119
3510
|
buildIdFieldRefs(kysely, model) {
|
|
3120
3511
|
const idFields = getIdFields(this.schema, model);
|
|
3121
|
-
return idFields.map((f) => kysely.dynamic.ref(f));
|
|
3512
|
+
return idFields.map((f) => kysely.dynamic.ref(`${model}.${f}`));
|
|
3122
3513
|
}
|
|
3123
3514
|
async processRelationUpdates(kysely, model, field, fieldDef, parentIds, args, throwIfNotFound) {
|
|
3124
3515
|
const tasks = [];
|
|
@@ -3236,7 +3627,7 @@ var BaseOperationHandler = class {
|
|
|
3236
3627
|
model: fromRelation.model,
|
|
3237
3628
|
operation: "update"
|
|
3238
3629
|
}));
|
|
3239
|
-
updateResult = await
|
|
3630
|
+
updateResult = await this.executeQuery(kysely, query, "connect");
|
|
3240
3631
|
} else {
|
|
3241
3632
|
const relationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3242
3633
|
if (!relationFieldDef.array) {
|
|
@@ -3247,7 +3638,7 @@ var BaseOperationHandler = class {
|
|
|
3247
3638
|
model: fromRelation.model,
|
|
3248
3639
|
operation: "update"
|
|
3249
3640
|
}));
|
|
3250
|
-
await
|
|
3641
|
+
await this.executeQuery(kysely, query2, "disconnect");
|
|
3251
3642
|
}
|
|
3252
3643
|
const query = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
|
|
3253
3644
|
...acc,
|
|
@@ -3256,9 +3647,9 @@ var BaseOperationHandler = class {
|
|
|
3256
3647
|
model,
|
|
3257
3648
|
operation: "update"
|
|
3258
3649
|
}));
|
|
3259
|
-
updateResult = await
|
|
3650
|
+
updateResult = await this.executeQuery(kysely, query, "connect");
|
|
3260
3651
|
}
|
|
3261
|
-
if (_data.length > updateResult.
|
|
3652
|
+
if (_data.length > updateResult.numAffectedRows) {
|
|
3262
3653
|
throw new NotFoundError(model);
|
|
3263
3654
|
}
|
|
3264
3655
|
}
|
|
@@ -3310,7 +3701,7 @@ var BaseOperationHandler = class {
|
|
|
3310
3701
|
await Promise.all(actions);
|
|
3311
3702
|
} else {
|
|
3312
3703
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3313
|
-
const eb =
|
|
3704
|
+
const eb = expressionBuilder3();
|
|
3314
3705
|
if (ownedByModel) {
|
|
3315
3706
|
invariant7(disconnectConditions.length === 1, "only one entity can be disconnected");
|
|
3316
3707
|
const condition = disconnectConditions[0];
|
|
@@ -3326,7 +3717,7 @@ var BaseOperationHandler = class {
|
|
|
3326
3717
|
model: fromRelation.model,
|
|
3327
3718
|
operation: "update"
|
|
3328
3719
|
}));
|
|
3329
|
-
await
|
|
3720
|
+
await this.executeQuery(kysely, query, "disconnect");
|
|
3330
3721
|
} else {
|
|
3331
3722
|
const query = kysely.updateTable(model).where(eb.and([
|
|
3332
3723
|
// fk filter
|
|
@@ -3343,7 +3734,7 @@ var BaseOperationHandler = class {
|
|
|
3343
3734
|
model,
|
|
3344
3735
|
operation: "update"
|
|
3345
3736
|
}));
|
|
3346
|
-
await
|
|
3737
|
+
await this.executeQuery(kysely, query, "disconnect");
|
|
3347
3738
|
}
|
|
3348
3739
|
}
|
|
3349
3740
|
}
|
|
@@ -3381,7 +3772,7 @@ var BaseOperationHandler = class {
|
|
|
3381
3772
|
model,
|
|
3382
3773
|
operation: "update"
|
|
3383
3774
|
}));
|
|
3384
|
-
await
|
|
3775
|
+
await this.executeQuery(kysely, query, "disconnect");
|
|
3385
3776
|
if (_data.length > 0) {
|
|
3386
3777
|
const query2 = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
|
|
3387
3778
|
...acc,
|
|
@@ -3390,8 +3781,8 @@ var BaseOperationHandler = class {
|
|
|
3390
3781
|
model,
|
|
3391
3782
|
operation: "update"
|
|
3392
3783
|
}));
|
|
3393
|
-
const r = await
|
|
3394
|
-
if (_data.length > r.
|
|
3784
|
+
const r = await this.executeQuery(kysely, query2, "connect");
|
|
3785
|
+
if (_data.length > r.numAffectedRows) {
|
|
3395
3786
|
throw new NotFoundError(model);
|
|
3396
3787
|
}
|
|
3397
3788
|
}
|
|
@@ -3432,7 +3823,7 @@ var BaseOperationHandler = class {
|
|
|
3432
3823
|
OR: deleteConditions
|
|
3433
3824
|
}
|
|
3434
3825
|
]
|
|
3435
|
-
}
|
|
3826
|
+
});
|
|
3436
3827
|
} else {
|
|
3437
3828
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3438
3829
|
if (ownedByModel) {
|
|
@@ -3455,7 +3846,7 @@ var BaseOperationHandler = class {
|
|
|
3455
3846
|
OR: deleteConditions
|
|
3456
3847
|
}
|
|
3457
3848
|
]
|
|
3458
|
-
}
|
|
3849
|
+
});
|
|
3459
3850
|
} else {
|
|
3460
3851
|
deleteResult = await this.delete(kysely, model, {
|
|
3461
3852
|
AND: [
|
|
@@ -3467,7 +3858,7 @@ var BaseOperationHandler = class {
|
|
|
3467
3858
|
OR: deleteConditions
|
|
3468
3859
|
}
|
|
3469
3860
|
]
|
|
3470
|
-
}
|
|
3861
|
+
});
|
|
3471
3862
|
}
|
|
3472
3863
|
}
|
|
3473
3864
|
if (throwForNotFound && expectedDeleteCount > deleteResult.count) {
|
|
@@ -3478,33 +3869,59 @@ var BaseOperationHandler = class {
|
|
|
3478
3869
|
return enumerate(data).map((item) => flattenCompoundUniqueFilters(this.schema, model, item));
|
|
3479
3870
|
}
|
|
3480
3871
|
// #endregion
|
|
3481
|
-
async delete(kysely, model, where, limit,
|
|
3872
|
+
async delete(kysely, model, where, limit, filterModel) {
|
|
3873
|
+
filterModel ??= model;
|
|
3874
|
+
const modelDef = this.requireModel(model);
|
|
3875
|
+
if (modelDef.baseModel) {
|
|
3876
|
+
if (limit !== void 0) {
|
|
3877
|
+
throw new QueryError("Deleting with a limit is not supported for polymorphic models");
|
|
3878
|
+
}
|
|
3879
|
+
return this.processBaseModelDelete(kysely, modelDef.baseModel, where, limit, filterModel);
|
|
3880
|
+
}
|
|
3482
3881
|
let query = kysely.deleteFrom(model);
|
|
3483
|
-
|
|
3882
|
+
let needIdFilter = false;
|
|
3883
|
+
if (limit !== void 0 && !this.dialect.supportsDeleteWithLimit) {
|
|
3884
|
+
needIdFilter = true;
|
|
3885
|
+
}
|
|
3886
|
+
if (modelDef.isDelegate || modelDef.baseModel) {
|
|
3887
|
+
needIdFilter = true;
|
|
3888
|
+
}
|
|
3889
|
+
if (!needIdFilter) {
|
|
3484
3890
|
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
|
|
3485
3891
|
} else {
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
query = query.where((eb) => eb(eb.refTuple(
|
|
3490
|
-
...this.buildIdFieldRefs(kysely, model)
|
|
3491
|
-
), "in", kysely.selectFrom(model).where((eb2) => this.dialect.buildFilter(eb2, model, model, where)).select(this.buildIdFieldRefs(kysely, model)).limit(limit)));
|
|
3492
|
-
}
|
|
3892
|
+
query = query.where((eb) => eb(eb.refTuple(
|
|
3893
|
+
...this.buildIdFieldRefs(kysely, model)
|
|
3894
|
+
), "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))));
|
|
3493
3895
|
}
|
|
3896
|
+
await this.processDelegateRelationDelete(kysely, modelDef, where, limit);
|
|
3494
3897
|
query = query.modifyEnd(this.makeContextComment({
|
|
3495
3898
|
model,
|
|
3496
3899
|
operation: "delete"
|
|
3497
3900
|
}));
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
}
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3901
|
+
const result = await this.executeQuery(kysely, query, "delete");
|
|
3902
|
+
return {
|
|
3903
|
+
count: Number(result.numAffectedRows)
|
|
3904
|
+
};
|
|
3905
|
+
}
|
|
3906
|
+
async processDelegateRelationDelete(kysely, modelDef, where, limit) {
|
|
3907
|
+
for (const fieldDef of Object.values(modelDef.fields)) {
|
|
3908
|
+
if (fieldDef.relation && fieldDef.relation.opposite) {
|
|
3909
|
+
const oppositeModelDef = this.requireModel(fieldDef.type);
|
|
3910
|
+
const oppositeRelation = this.requireField(fieldDef.type, fieldDef.relation.opposite);
|
|
3911
|
+
if (oppositeModelDef.baseModel && oppositeRelation.relation?.onDelete === "Cascade") {
|
|
3912
|
+
if (limit !== void 0) {
|
|
3913
|
+
throw new QueryError("Deleting with a limit is not supported for polymorphic models");
|
|
3914
|
+
}
|
|
3915
|
+
await this.delete(kysely, fieldDef.type, {
|
|
3916
|
+
[fieldDef.relation.opposite]: where
|
|
3917
|
+
}, void 0);
|
|
3918
|
+
}
|
|
3919
|
+
}
|
|
3506
3920
|
}
|
|
3507
3921
|
}
|
|
3922
|
+
async processBaseModelDelete(kysely, model, where, limit, filterModel) {
|
|
3923
|
+
return this.delete(kysely, model, where, limit, filterModel);
|
|
3924
|
+
}
|
|
3508
3925
|
makeIdSelect(model) {
|
|
3509
3926
|
const modelDef = this.requireModel(model);
|
|
3510
3927
|
return modelDef.idFields.reduce((acc, f) => {
|
|
@@ -3513,7 +3930,7 @@ var BaseOperationHandler = class {
|
|
|
3513
3930
|
}, {});
|
|
3514
3931
|
}
|
|
3515
3932
|
trimResult(data, args) {
|
|
3516
|
-
if (!args.select) {
|
|
3933
|
+
if (!("select" in args) || !args.select) {
|
|
3517
3934
|
return data;
|
|
3518
3935
|
}
|
|
3519
3936
|
return Object.keys(args.select).reduce((acc, field) => {
|
|
@@ -3523,9 +3940,9 @@ var BaseOperationHandler = class {
|
|
|
3523
3940
|
}
|
|
3524
3941
|
needReturnRelations(model, args) {
|
|
3525
3942
|
let returnRelation = false;
|
|
3526
|
-
if (args.include) {
|
|
3943
|
+
if ("include" in args && args.include) {
|
|
3527
3944
|
returnRelation = Object.keys(args.include).length > 0;
|
|
3528
|
-
} else if (args.select) {
|
|
3945
|
+
} else if ("select" in args && args.select) {
|
|
3529
3946
|
returnRelation = Object.entries(args.select).some(([K, v]) => {
|
|
3530
3947
|
const fieldDef = this.requireField(model, K);
|
|
3531
3948
|
return fieldDef.relation && v;
|
|
@@ -3533,11 +3950,13 @@ var BaseOperationHandler = class {
|
|
|
3533
3950
|
}
|
|
3534
3951
|
return returnRelation;
|
|
3535
3952
|
}
|
|
3536
|
-
async safeTransaction(callback) {
|
|
3953
|
+
async safeTransaction(callback, isolationLevel) {
|
|
3537
3954
|
if (this.kysely.isTransaction) {
|
|
3538
3955
|
return callback(this.kysely);
|
|
3539
3956
|
} else {
|
|
3540
|
-
|
|
3957
|
+
let txBuilder = this.kysely.transaction();
|
|
3958
|
+
txBuilder = txBuilder.setIsolationLevel(isolationLevel ?? "repeatable read");
|
|
3959
|
+
return txBuilder.execute(callback);
|
|
3541
3960
|
}
|
|
3542
3961
|
}
|
|
3543
3962
|
// Given a unique filter of a model, return the entity ids by trying to
|
|
@@ -3556,6 +3975,47 @@ var BaseOperationHandler = class {
|
|
|
3556
3975
|
where: uniqueFilter
|
|
3557
3976
|
});
|
|
3558
3977
|
}
|
|
3978
|
+
/**
|
|
3979
|
+
* Normalize input args to strip `undefined` fields
|
|
3980
|
+
*/
|
|
3981
|
+
normalizeArgs(args) {
|
|
3982
|
+
if (!args) {
|
|
3983
|
+
return;
|
|
3984
|
+
}
|
|
3985
|
+
const newArgs = clone(args);
|
|
3986
|
+
this.doNormalizeArgs(newArgs);
|
|
3987
|
+
return newArgs;
|
|
3988
|
+
}
|
|
3989
|
+
doNormalizeArgs(args) {
|
|
3990
|
+
if (args && typeof args === "object") {
|
|
3991
|
+
for (const [key, value] of Object.entries(args)) {
|
|
3992
|
+
if (value === void 0) {
|
|
3993
|
+
delete args[key];
|
|
3994
|
+
} else if (value && isPlainObject3(value)) {
|
|
3995
|
+
this.doNormalizeArgs(value);
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
}
|
|
3999
|
+
}
|
|
4000
|
+
makeQueryId(operation) {
|
|
4001
|
+
return {
|
|
4002
|
+
queryId: `${operation}-${createId()}`
|
|
4003
|
+
};
|
|
4004
|
+
}
|
|
4005
|
+
executeQuery(kysely, query, operation) {
|
|
4006
|
+
return kysely.executeQuery(query.compile(), this.makeQueryId(operation));
|
|
4007
|
+
}
|
|
4008
|
+
async executeQueryTakeFirst(kysely, query, operation) {
|
|
4009
|
+
const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
|
|
4010
|
+
return result.rows[0];
|
|
4011
|
+
}
|
|
4012
|
+
async executeQueryTakeFirstOrThrow(kysely, query, operation) {
|
|
4013
|
+
const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
|
|
4014
|
+
if (result.rows.length === 0) {
|
|
4015
|
+
throw new QueryError("No rows found");
|
|
4016
|
+
}
|
|
4017
|
+
return result.rows[0];
|
|
4018
|
+
}
|
|
3559
4019
|
};
|
|
3560
4020
|
|
|
3561
4021
|
// src/client/crud/operations/aggregate.ts
|
|
@@ -3564,21 +4024,37 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3564
4024
|
__name(this, "AggregateOperationHandler");
|
|
3565
4025
|
}
|
|
3566
4026
|
async handle(_operation, args) {
|
|
3567
|
-
const
|
|
4027
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4028
|
+
const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
|
|
3568
4029
|
let query = this.kysely.selectFrom((eb) => {
|
|
3569
|
-
let subQuery =
|
|
3570
|
-
const
|
|
3571
|
-
|
|
4030
|
+
let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
4031
|
+
const selectedFields = [];
|
|
4032
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
4033
|
+
if (key.startsWith("_") && value && typeof value === "object") {
|
|
4034
|
+
Object.entries(value).filter(([field]) => field !== "_all").filter(([, val]) => val === true).forEach(([field]) => {
|
|
4035
|
+
if (!selectedFields.includes(field)) selectedFields.push(field);
|
|
4036
|
+
});
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
if (selectedFields.length > 0) {
|
|
4040
|
+
for (const field of selectedFields) {
|
|
4041
|
+
subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, field);
|
|
4042
|
+
}
|
|
4043
|
+
} else {
|
|
4044
|
+
subQuery = subQuery.select(() => eb.lit(1).as("_all"));
|
|
4045
|
+
}
|
|
4046
|
+
const skip = parsedArgs?.skip;
|
|
4047
|
+
let take = parsedArgs?.take;
|
|
3572
4048
|
let negateOrderBy = false;
|
|
3573
4049
|
if (take !== void 0 && take < 0) {
|
|
3574
4050
|
negateOrderBy = true;
|
|
3575
4051
|
take = -take;
|
|
3576
4052
|
}
|
|
3577
4053
|
subQuery = this.dialect.buildSkipTake(subQuery, skip, take);
|
|
3578
|
-
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model,
|
|
4054
|
+
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, parsedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
3579
4055
|
return subQuery.as("$sub");
|
|
3580
4056
|
});
|
|
3581
|
-
for (const [key, value] of Object.entries(
|
|
4057
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3582
4058
|
switch (key) {
|
|
3583
4059
|
case "_count": {
|
|
3584
4060
|
if (value === true) {
|
|
@@ -3603,7 +4079,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3603
4079
|
Object.entries(value).forEach(([field, val]) => {
|
|
3604
4080
|
if (val === true) {
|
|
3605
4081
|
query = query.select((eb) => {
|
|
3606
|
-
const fn =
|
|
4082
|
+
const fn = match10(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
|
|
3607
4083
|
return fn(sql5.ref(`$sub.${field}`)).as(`${key}.${field}`);
|
|
3608
4084
|
});
|
|
3609
4085
|
}
|
|
@@ -3612,9 +4088,9 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3612
4088
|
}
|
|
3613
4089
|
}
|
|
3614
4090
|
}
|
|
3615
|
-
const result = await
|
|
4091
|
+
const result = await this.executeQuery(this.kysely, query, "aggregate");
|
|
3616
4092
|
const ret = {};
|
|
3617
|
-
for (const [key, value] of Object.entries(result)) {
|
|
4093
|
+
for (const [key, value] of Object.entries(result.rows[0])) {
|
|
3618
4094
|
if (key === "_count") {
|
|
3619
4095
|
ret[key] = value;
|
|
3620
4096
|
continue;
|
|
@@ -3636,7 +4112,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3636
4112
|
val = parseFloat(val);
|
|
3637
4113
|
} else {
|
|
3638
4114
|
if (op === "_sum" || op === "_min" || op === "_max") {
|
|
3639
|
-
val =
|
|
4115
|
+
val = match10(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
|
|
3640
4116
|
}
|
|
3641
4117
|
}
|
|
3642
4118
|
}
|
|
@@ -3657,34 +4133,47 @@ var CountOperationHandler = class extends BaseOperationHandler {
|
|
|
3657
4133
|
__name(this, "CountOperationHandler");
|
|
3658
4134
|
}
|
|
3659
4135
|
async handle(_operation, args) {
|
|
3660
|
-
const
|
|
4136
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4137
|
+
const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
|
|
4138
|
+
const subQueryName = "$sub";
|
|
3661
4139
|
let query = this.kysely.selectFrom((eb) => {
|
|
3662
|
-
let subQuery =
|
|
3663
|
-
|
|
3664
|
-
|
|
4140
|
+
let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
4141
|
+
if (parsedArgs?.select && typeof parsedArgs.select === "object") {
|
|
4142
|
+
for (const [key, value] of Object.entries(parsedArgs.select)) {
|
|
4143
|
+
if (key !== "_all" && value === true) {
|
|
4144
|
+
subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, key);
|
|
4145
|
+
}
|
|
4146
|
+
}
|
|
4147
|
+
} else {
|
|
4148
|
+
subQuery = subQuery.select(() => eb.lit(1).as("_all"));
|
|
4149
|
+
}
|
|
4150
|
+
subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
|
|
4151
|
+
return subQuery.as(subQueryName);
|
|
3665
4152
|
});
|
|
3666
|
-
if (
|
|
3667
|
-
query = query.select((eb) => Object.keys(
|
|
3668
|
-
|
|
4153
|
+
if (parsedArgs?.select && typeof parsedArgs.select === "object") {
|
|
4154
|
+
query = query.select((eb) => Object.keys(parsedArgs.select).map((key) => key === "_all" ? eb.cast(eb.fn.countAll(), "integer").as("_all") : eb.cast(eb.fn.count(sql6.ref(`${subQueryName}.${key}`)), "integer").as(key)));
|
|
4155
|
+
const result = await this.executeQuery(this.kysely, query, "count");
|
|
4156
|
+
return result.rows[0];
|
|
3669
4157
|
} else {
|
|
3670
4158
|
query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
|
|
3671
|
-
const result = await
|
|
3672
|
-
return result.count;
|
|
4159
|
+
const result = await this.executeQuery(this.kysely, query, "count");
|
|
4160
|
+
return result.rows[0].count;
|
|
3673
4161
|
}
|
|
3674
4162
|
}
|
|
3675
4163
|
};
|
|
3676
4164
|
|
|
3677
4165
|
// src/client/crud/operations/create.ts
|
|
3678
|
-
import { match as
|
|
4166
|
+
import { match as match11 } from "ts-pattern";
|
|
3679
4167
|
var CreateOperationHandler = class extends BaseOperationHandler {
|
|
3680
4168
|
static {
|
|
3681
4169
|
__name(this, "CreateOperationHandler");
|
|
3682
4170
|
}
|
|
3683
4171
|
async handle(operation, args) {
|
|
3684
|
-
|
|
3685
|
-
|
|
4172
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4173
|
+
return match11(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, normalizedArgs))).with("createMany", () => {
|
|
4174
|
+
return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, normalizedArgs));
|
|
3686
4175
|
}).with("createManyAndReturn", () => {
|
|
3687
|
-
return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model,
|
|
4176
|
+
return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, normalizedArgs));
|
|
3688
4177
|
}).exhaustive();
|
|
3689
4178
|
}
|
|
3690
4179
|
async runCreate(args) {
|
|
@@ -3728,13 +4217,14 @@ var CreateOperationHandler = class extends BaseOperationHandler {
|
|
|
3728
4217
|
};
|
|
3729
4218
|
|
|
3730
4219
|
// src/client/crud/operations/delete.ts
|
|
3731
|
-
import { match as
|
|
4220
|
+
import { match as match12 } from "ts-pattern";
|
|
3732
4221
|
var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
3733
4222
|
static {
|
|
3734
4223
|
__name(this, "DeleteOperationHandler");
|
|
3735
4224
|
}
|
|
3736
4225
|
async handle(operation, args) {
|
|
3737
|
-
|
|
4226
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4227
|
+
return match12(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, normalizedArgs))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, normalizedArgs))).exhaustive();
|
|
3738
4228
|
}
|
|
3739
4229
|
async runDelete(args) {
|
|
3740
4230
|
const existing = await this.readUnique(this.kysely, this.model, {
|
|
@@ -3746,15 +4236,19 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
|
3746
4236
|
if (!existing) {
|
|
3747
4237
|
throw new NotFoundError(this.model);
|
|
3748
4238
|
}
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
4239
|
+
await this.safeTransaction(async (tx) => {
|
|
4240
|
+
const result = await this.delete(tx, this.model, args.where);
|
|
4241
|
+
if (result.count === 0) {
|
|
4242
|
+
throw new NotFoundError(this.model);
|
|
4243
|
+
}
|
|
4244
|
+
});
|
|
3753
4245
|
return existing;
|
|
3754
4246
|
}
|
|
3755
4247
|
async runDeleteMany(args) {
|
|
3756
|
-
|
|
3757
|
-
|
|
4248
|
+
return await this.safeTransaction(async (tx) => {
|
|
4249
|
+
const result = await this.delete(tx, this.model, args?.where, args?.limit);
|
|
4250
|
+
return result;
|
|
4251
|
+
});
|
|
3758
4252
|
}
|
|
3759
4253
|
};
|
|
3760
4254
|
|
|
@@ -3764,7 +4258,8 @@ var FindOperationHandler = class extends BaseOperationHandler {
|
|
|
3764
4258
|
__name(this, "FindOperationHandler");
|
|
3765
4259
|
}
|
|
3766
4260
|
async handle(operation, args, validateArgs = true) {
|
|
3767
|
-
const
|
|
4261
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4262
|
+
const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", normalizedArgs) : normalizedArgs;
|
|
3768
4263
|
const result = await this.read(this.client.$qb, this.model, parsedArgs);
|
|
3769
4264
|
const finalResult = operation === "findMany" ? result : result[0] ?? null;
|
|
3770
4265
|
return finalResult;
|
|
@@ -3772,18 +4267,19 @@ var FindOperationHandler = class extends BaseOperationHandler {
|
|
|
3772
4267
|
};
|
|
3773
4268
|
|
|
3774
4269
|
// src/client/crud/operations/group-by.ts
|
|
3775
|
-
import {
|
|
3776
|
-
import { match as
|
|
3777
|
-
var
|
|
4270
|
+
import { expressionBuilder as expressionBuilder4 } from "kysely";
|
|
4271
|
+
import { match as match13 } from "ts-pattern";
|
|
4272
|
+
var GroupByOperationHandler = class extends BaseOperationHandler {
|
|
3778
4273
|
static {
|
|
3779
|
-
__name(this, "
|
|
4274
|
+
__name(this, "GroupByOperationHandler");
|
|
3780
4275
|
}
|
|
3781
4276
|
async handle(_operation, args) {
|
|
3782
|
-
const
|
|
4277
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4278
|
+
const parsedArgs = this.inputValidator.validateGroupByArgs(this.model, normalizedArgs);
|
|
3783
4279
|
let query = this.kysely.selectFrom((eb) => {
|
|
3784
|
-
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model,
|
|
3785
|
-
const skip =
|
|
3786
|
-
let take =
|
|
4280
|
+
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
4281
|
+
const skip = parsedArgs?.skip;
|
|
4282
|
+
let take = parsedArgs?.take;
|
|
3787
4283
|
let negateOrderBy = false;
|
|
3788
4284
|
if (take !== void 0 && take < 0) {
|
|
3789
4285
|
negateOrderBy = true;
|
|
@@ -3793,20 +4289,21 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3793
4289
|
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
3794
4290
|
return subQuery.as("$sub");
|
|
3795
4291
|
});
|
|
3796
|
-
const
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
4292
|
+
const fieldRef = /* @__PURE__ */ __name((field) => this.dialect.fieldRef(this.model, field, expressionBuilder4(), "$sub"), "fieldRef");
|
|
4293
|
+
const bys = typeof parsedArgs.by === "string" ? [
|
|
4294
|
+
parsedArgs.by
|
|
4295
|
+
] : parsedArgs.by;
|
|
4296
|
+
query = query.groupBy(bys.map((by) => fieldRef(by)));
|
|
4297
|
+
if (parsedArgs.orderBy) {
|
|
4298
|
+
query = this.dialect.buildOrderBy(query, this.model, "$sub", parsedArgs.orderBy, false, false);
|
|
3802
4299
|
}
|
|
3803
|
-
if (
|
|
3804
|
-
query = query.having((
|
|
4300
|
+
if (parsedArgs.having) {
|
|
4301
|
+
query = query.having((eb) => this.dialect.buildFilter(eb, this.model, "$sub", parsedArgs.having));
|
|
3805
4302
|
}
|
|
3806
4303
|
for (const by of bys) {
|
|
3807
|
-
query = query.select(() =>
|
|
4304
|
+
query = query.select(() => fieldRef(by).as(by));
|
|
3808
4305
|
}
|
|
3809
|
-
for (const [key, value] of Object.entries(
|
|
4306
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3810
4307
|
switch (key) {
|
|
3811
4308
|
case "_count": {
|
|
3812
4309
|
if (value === true) {
|
|
@@ -3817,7 +4314,7 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3817
4314
|
if (field === "_all") {
|
|
3818
4315
|
query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as(`_count._all`));
|
|
3819
4316
|
} else {
|
|
3820
|
-
query = query.select((eb) => eb.cast(eb.fn.count(
|
|
4317
|
+
query = query.select((eb) => eb.cast(eb.fn.count(fieldRef(field)), "integer").as(`${key}.${field}`));
|
|
3821
4318
|
}
|
|
3822
4319
|
}
|
|
3823
4320
|
});
|
|
@@ -3830,18 +4327,15 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3830
4327
|
case "_min": {
|
|
3831
4328
|
Object.entries(value).forEach(([field, val]) => {
|
|
3832
4329
|
if (val === true) {
|
|
3833
|
-
query = query.select((eb) => {
|
|
3834
|
-
const fn = match12(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
|
|
3835
|
-
return fn(sql7.ref(`$sub.${field}`)).as(`${key}.${field}`);
|
|
3836
|
-
});
|
|
4330
|
+
query = query.select((eb) => aggregate(eb, fieldRef(field), key).as(`${key}.${field}`));
|
|
3837
4331
|
}
|
|
3838
4332
|
});
|
|
3839
4333
|
break;
|
|
3840
4334
|
}
|
|
3841
4335
|
}
|
|
3842
4336
|
}
|
|
3843
|
-
const result = await
|
|
3844
|
-
return result.map((row) => this.postProcessRow(row));
|
|
4337
|
+
const result = await this.executeQuery(this.kysely, query, "groupBy");
|
|
4338
|
+
return result.rows.map((row) => this.postProcessRow(row));
|
|
3845
4339
|
}
|
|
3846
4340
|
postProcessRow(row) {
|
|
3847
4341
|
const ret = {};
|
|
@@ -3868,7 +4362,7 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3868
4362
|
val = parseFloat(val);
|
|
3869
4363
|
} else {
|
|
3870
4364
|
if (op === "_sum" || op === "_min" || op === "_max") {
|
|
3871
|
-
val =
|
|
4365
|
+
val = match13(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
|
|
3872
4366
|
}
|
|
3873
4367
|
}
|
|
3874
4368
|
}
|
|
@@ -3883,31 +4377,45 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3883
4377
|
};
|
|
3884
4378
|
|
|
3885
4379
|
// src/client/crud/operations/update.ts
|
|
3886
|
-
import { match as
|
|
4380
|
+
import { match as match14 } from "ts-pattern";
|
|
3887
4381
|
var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
3888
4382
|
static {
|
|
3889
4383
|
__name(this, "UpdateOperationHandler");
|
|
3890
4384
|
}
|
|
3891
4385
|
async handle(operation, args) {
|
|
3892
|
-
|
|
4386
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4387
|
+
return match14(operation).with("update", () => this.runUpdate(this.inputValidator.validateUpdateArgs(this.model, normalizedArgs))).with("updateMany", () => this.runUpdateMany(this.inputValidator.validateUpdateManyArgs(this.model, normalizedArgs))).with("updateManyAndReturn", () => this.runUpdateManyAndReturn(this.inputValidator.validateUpdateManyAndReturnArgs(this.model, normalizedArgs))).with("upsert", () => this.runUpsert(this.inputValidator.validateUpsertArgs(this.model, normalizedArgs))).exhaustive();
|
|
3893
4388
|
}
|
|
3894
4389
|
async runUpdate(args) {
|
|
3895
|
-
const
|
|
3896
|
-
const
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
4390
|
+
const readBackResult = await this.safeTransaction(async (tx) => {
|
|
4391
|
+
const updateResult = await this.update(tx, this.model, args.where, args.data);
|
|
4392
|
+
const readFilter = updateResult ?? args.where;
|
|
4393
|
+
let readBackResult2 = void 0;
|
|
4394
|
+
try {
|
|
4395
|
+
readBackResult2 = await this.readUnique(tx, this.model, {
|
|
4396
|
+
select: args.select,
|
|
4397
|
+
include: args.include,
|
|
4398
|
+
omit: args.omit,
|
|
4399
|
+
where: readFilter
|
|
4400
|
+
});
|
|
4401
|
+
} catch {
|
|
4402
|
+
}
|
|
4403
|
+
return readBackResult2;
|
|
3903
4404
|
});
|
|
3904
|
-
if (!
|
|
3905
|
-
|
|
4405
|
+
if (!readBackResult) {
|
|
4406
|
+
if (this.hasPolicyEnabled) {
|
|
4407
|
+
throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
|
|
4408
|
+
} else {
|
|
4409
|
+
return null;
|
|
4410
|
+
}
|
|
4411
|
+
} else {
|
|
4412
|
+
return readBackResult;
|
|
3906
4413
|
}
|
|
3907
|
-
return result;
|
|
3908
4414
|
}
|
|
3909
4415
|
async runUpdateMany(args) {
|
|
3910
|
-
return this.
|
|
4416
|
+
return this.safeTransaction(async (tx) => {
|
|
4417
|
+
return this.updateMany(tx, this.model, args.where, args.data, args.limit, false);
|
|
4418
|
+
});
|
|
3911
4419
|
}
|
|
3912
4420
|
async runUpdateManyAndReturn(args) {
|
|
3913
4421
|
if (!args) {
|
|
@@ -3945,19 +4453,19 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3945
4453
|
};
|
|
3946
4454
|
|
|
3947
4455
|
// src/client/crud/validator.ts
|
|
4456
|
+
import { invariant as invariant8 } from "@zenstackhq/common-helpers";
|
|
3948
4457
|
import Decimal from "decimal.js";
|
|
3949
4458
|
import stableStringify from "json-stable-stringify";
|
|
3950
|
-
import { match as
|
|
4459
|
+
import { match as match15, P as P2 } from "ts-pattern";
|
|
3951
4460
|
import { z } from "zod";
|
|
3952
4461
|
var InputValidator = class {
|
|
3953
4462
|
static {
|
|
3954
4463
|
__name(this, "InputValidator");
|
|
3955
4464
|
}
|
|
3956
4465
|
schema;
|
|
3957
|
-
schemaCache;
|
|
4466
|
+
schemaCache = /* @__PURE__ */ new Map();
|
|
3958
4467
|
constructor(schema) {
|
|
3959
4468
|
this.schema = schema;
|
|
3960
|
-
this.schemaCache = /* @__PURE__ */ new Map();
|
|
3961
4469
|
}
|
|
3962
4470
|
validateFindArgs(model, unique, args) {
|
|
3963
4471
|
return this.validate(model, "find", {
|
|
@@ -4014,7 +4522,7 @@ var InputValidator = class {
|
|
|
4014
4522
|
}
|
|
4015
4523
|
const { error } = schema.safeParse(args);
|
|
4016
4524
|
if (error) {
|
|
4017
|
-
throw new
|
|
4525
|
+
throw new InputValidationError(`Invalid ${operation} args: ${error.message}`, error);
|
|
4018
4526
|
}
|
|
4019
4527
|
return args;
|
|
4020
4528
|
}
|
|
@@ -4033,11 +4541,11 @@ var InputValidator = class {
|
|
|
4033
4541
|
fields["distinct"] = this.makeDistinctSchema(model).optional();
|
|
4034
4542
|
fields["cursor"] = this.makeCursorSchema(model).optional();
|
|
4035
4543
|
if (options.collection) {
|
|
4036
|
-
fields["skip"] =
|
|
4037
|
-
fields["take"] =
|
|
4544
|
+
fields["skip"] = this.makeSkipSchema().optional();
|
|
4545
|
+
fields["take"] = this.makeTakeSchema().optional();
|
|
4038
4546
|
fields["orderBy"] = this.orArray(this.makeOrderBySchema(model, true, false), true).optional();
|
|
4039
4547
|
}
|
|
4040
|
-
let result = z.
|
|
4548
|
+
let result = z.strictObject(fields);
|
|
4041
4549
|
result = this.refineForSelectIncludeMutuallyExclusive(result);
|
|
4042
4550
|
result = this.refineForSelectOmitMutuallyExclusive(result);
|
|
4043
4551
|
if (!options.unique) {
|
|
@@ -4046,22 +4554,50 @@ var InputValidator = class {
|
|
|
4046
4554
|
return result;
|
|
4047
4555
|
}
|
|
4048
4556
|
makePrimitiveSchema(type) {
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
z.
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4557
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
4558
|
+
return this.makeTypeDefSchema(type);
|
|
4559
|
+
} else {
|
|
4560
|
+
return match15(type).with("String", () => z.string()).with("Int", () => z.int()).with("Float", () => z.number()).with("Boolean", () => z.boolean()).with("BigInt", () => z.union([
|
|
4561
|
+
z.int(),
|
|
4562
|
+
z.bigint()
|
|
4563
|
+
])).with("Decimal", () => z.union([
|
|
4564
|
+
z.number(),
|
|
4565
|
+
z.instanceof(Decimal),
|
|
4566
|
+
z.string()
|
|
4567
|
+
])).with("DateTime", () => z.union([
|
|
4568
|
+
z.date(),
|
|
4569
|
+
z.string().datetime()
|
|
4570
|
+
])).with("Bytes", () => z.instanceof(Uint8Array)).otherwise(() => z.unknown());
|
|
4571
|
+
}
|
|
4572
|
+
}
|
|
4573
|
+
makeTypeDefSchema(type) {
|
|
4574
|
+
const key = `$typedef-${type}`;
|
|
4575
|
+
let schema = this.schemaCache.get(key);
|
|
4576
|
+
if (schema) {
|
|
4577
|
+
return schema;
|
|
4578
|
+
}
|
|
4579
|
+
const typeDef = this.schema.typeDefs?.[type];
|
|
4580
|
+
invariant8(typeDef, `Type definition "${type}" not found in schema`);
|
|
4581
|
+
schema = z.looseObject(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
|
|
4582
|
+
let fieldSchema = this.makePrimitiveSchema(def.type);
|
|
4583
|
+
if (def.array) {
|
|
4584
|
+
fieldSchema = fieldSchema.array();
|
|
4585
|
+
}
|
|
4586
|
+
if (def.optional) {
|
|
4587
|
+
fieldSchema = fieldSchema.optional();
|
|
4588
|
+
}
|
|
4589
|
+
return [
|
|
4590
|
+
field,
|
|
4591
|
+
fieldSchema
|
|
4592
|
+
];
|
|
4593
|
+
})));
|
|
4594
|
+
this.schemaCache.set(key, schema);
|
|
4595
|
+
return schema;
|
|
4596
|
+
}
|
|
4597
|
+
makeWhereSchema(model, unique, withoutRelationFields = false, withAggregations = false) {
|
|
4062
4598
|
const modelDef = getModel(this.schema, model);
|
|
4063
4599
|
if (!modelDef) {
|
|
4064
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
4600
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
4065
4601
|
}
|
|
4066
4602
|
const fields = {};
|
|
4067
4603
|
for (const field of Object.keys(modelDef.fields)) {
|
|
@@ -4076,7 +4612,7 @@ var InputValidator = class {
|
|
|
4076
4612
|
if (fieldDef.array) {
|
|
4077
4613
|
fieldSchema = z.union([
|
|
4078
4614
|
fieldSchema,
|
|
4079
|
-
z.
|
|
4615
|
+
z.strictObject({
|
|
4080
4616
|
some: fieldSchema.optional(),
|
|
4081
4617
|
every: fieldSchema.optional(),
|
|
4082
4618
|
none: fieldSchema.optional()
|
|
@@ -4085,7 +4621,7 @@ var InputValidator = class {
|
|
|
4085
4621
|
} else {
|
|
4086
4622
|
fieldSchema = z.union([
|
|
4087
4623
|
fieldSchema,
|
|
4088
|
-
z.
|
|
4624
|
+
z.strictObject({
|
|
4089
4625
|
is: fieldSchema.optional(),
|
|
4090
4626
|
isNot: fieldSchema.optional()
|
|
4091
4627
|
})
|
|
@@ -4095,12 +4631,12 @@ var InputValidator = class {
|
|
|
4095
4631
|
const enumDef = getEnum(this.schema, fieldDef.type);
|
|
4096
4632
|
if (enumDef) {
|
|
4097
4633
|
if (Object.keys(enumDef).length > 0) {
|
|
4098
|
-
fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional);
|
|
4634
|
+
fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, withAggregations);
|
|
4099
4635
|
}
|
|
4100
4636
|
} else if (fieldDef.array) {
|
|
4101
4637
|
fieldSchema = this.makeArrayFilterSchema(fieldDef.type);
|
|
4102
4638
|
} else {
|
|
4103
|
-
fieldSchema = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional);
|
|
4639
|
+
fieldSchema = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional, withAggregations);
|
|
4104
4640
|
}
|
|
4105
4641
|
}
|
|
4106
4642
|
if (fieldSchema) {
|
|
@@ -4111,18 +4647,32 @@ var InputValidator = class {
|
|
|
4111
4647
|
const uniqueFields = getUniqueFields(this.schema, model);
|
|
4112
4648
|
for (const uniqueField of uniqueFields) {
|
|
4113
4649
|
if ("defs" in uniqueField) {
|
|
4114
|
-
fields[uniqueField.name] = z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) =>
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4650
|
+
fields[uniqueField.name] = z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
|
|
4651
|
+
invariant8(!def.relation, "unique field cannot be a relation");
|
|
4652
|
+
let fieldSchema;
|
|
4653
|
+
const enumDef = getEnum(this.schema, def.type);
|
|
4654
|
+
if (enumDef) {
|
|
4655
|
+
if (Object.keys(enumDef).length > 0) {
|
|
4656
|
+
fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional, false);
|
|
4657
|
+
} else {
|
|
4658
|
+
fieldSchema = z.never();
|
|
4659
|
+
}
|
|
4660
|
+
} else {
|
|
4661
|
+
fieldSchema = this.makePrimitiveFilterSchema(def.type, !!def.optional, false);
|
|
4662
|
+
}
|
|
4663
|
+
return [
|
|
4664
|
+
key,
|
|
4665
|
+
fieldSchema
|
|
4666
|
+
];
|
|
4667
|
+
}))).optional();
|
|
4118
4668
|
}
|
|
4119
4669
|
}
|
|
4120
4670
|
}
|
|
4121
|
-
fields["$expr"] = z.
|
|
4671
|
+
fields["$expr"] = z.custom((v) => typeof v === "function").optional();
|
|
4122
4672
|
fields["AND"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
|
|
4123
4673
|
fields["OR"] = z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)).array().optional();
|
|
4124
4674
|
fields["NOT"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
|
|
4125
|
-
const baseWhere = z.
|
|
4675
|
+
const baseWhere = z.strictObject(fields);
|
|
4126
4676
|
let result = baseWhere;
|
|
4127
4677
|
if (unique) {
|
|
4128
4678
|
const uniqueFields = getUniqueFields(this.schema, model);
|
|
@@ -4141,21 +4691,25 @@ var InputValidator = class {
|
|
|
4141
4691
|
}
|
|
4142
4692
|
return result;
|
|
4143
4693
|
}
|
|
4144
|
-
makeEnumFilterSchema(enumDef, optional) {
|
|
4694
|
+
makeEnumFilterSchema(enumDef, optional, withAggregations) {
|
|
4145
4695
|
const baseSchema = z.enum(Object.keys(enumDef));
|
|
4146
|
-
const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.lazy(() => this.makeEnumFilterSchema(enumDef, optional))
|
|
4696
|
+
const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.lazy(() => this.makeEnumFilterSchema(enumDef, optional, withAggregations)), [
|
|
4697
|
+
"equals",
|
|
4698
|
+
"in",
|
|
4699
|
+
"notIn",
|
|
4700
|
+
"not"
|
|
4701
|
+
], withAggregations ? [
|
|
4702
|
+
"_count",
|
|
4703
|
+
"_min",
|
|
4704
|
+
"_max"
|
|
4705
|
+
] : void 0);
|
|
4147
4706
|
return z.union([
|
|
4148
4707
|
this.nullableIf(baseSchema, optional),
|
|
4149
|
-
z.
|
|
4150
|
-
equals: components.equals,
|
|
4151
|
-
in: components.in,
|
|
4152
|
-
notIn: components.notIn,
|
|
4153
|
-
not: components.not
|
|
4154
|
-
})
|
|
4708
|
+
z.strictObject(components)
|
|
4155
4709
|
]);
|
|
4156
4710
|
}
|
|
4157
4711
|
makeArrayFilterSchema(type) {
|
|
4158
|
-
return z.
|
|
4712
|
+
return z.strictObject({
|
|
4159
4713
|
equals: this.makePrimitiveSchema(type).array().optional(),
|
|
4160
4714
|
has: this.makePrimitiveSchema(type).optional(),
|
|
4161
4715
|
hasEvery: this.makePrimitiveSchema(type).array().optional(),
|
|
@@ -4163,39 +4717,59 @@ var InputValidator = class {
|
|
|
4163
4717
|
isEmpty: z.boolean().optional()
|
|
4164
4718
|
});
|
|
4165
4719
|
}
|
|
4166
|
-
makePrimitiveFilterSchema(type, optional) {
|
|
4167
|
-
|
|
4720
|
+
makePrimitiveFilterSchema(type, optional, withAggregations) {
|
|
4721
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
4722
|
+
return this.makeTypeDefFilterSchema(type, optional);
|
|
4723
|
+
}
|
|
4724
|
+
return match15(type).with("String", () => this.makeStringFilterSchema(optional, withAggregations)).with(P2.union("Int", "Float", "Decimal", "BigInt"), (type2) => this.makeNumberFilterSchema(this.makePrimitiveSchema(type2), optional, withAggregations)).with("Boolean", () => this.makeBooleanFilterSchema(optional, withAggregations)).with("DateTime", () => this.makeDateTimeFilterSchema(optional, withAggregations)).with("Bytes", () => this.makeBytesFilterSchema(optional, withAggregations)).with("Json", () => z.any()).with("Unsupported", () => z.never()).exhaustive();
|
|
4725
|
+
}
|
|
4726
|
+
makeTypeDefFilterSchema(_type, _optional) {
|
|
4727
|
+
return z.never();
|
|
4168
4728
|
}
|
|
4169
|
-
makeDateTimeFilterSchema(optional) {
|
|
4729
|
+
makeDateTimeFilterSchema(optional, withAggregations) {
|
|
4170
4730
|
return this.makeCommonPrimitiveFilterSchema(z.union([
|
|
4171
|
-
z.
|
|
4731
|
+
z.iso.datetime(),
|
|
4172
4732
|
z.date()
|
|
4173
|
-
]), optional, () => z.lazy(() => this.makeDateTimeFilterSchema(optional))
|
|
4174
|
-
|
|
4175
|
-
|
|
4733
|
+
]), optional, () => z.lazy(() => this.makeDateTimeFilterSchema(optional, withAggregations)), withAggregations ? [
|
|
4734
|
+
"_count",
|
|
4735
|
+
"_min",
|
|
4736
|
+
"_max"
|
|
4737
|
+
] : void 0);
|
|
4738
|
+
}
|
|
4739
|
+
makeBooleanFilterSchema(optional, withAggregations) {
|
|
4740
|
+
const components = this.makeCommonPrimitiveFilterComponents(z.boolean(), optional, () => z.lazy(() => this.makeBooleanFilterSchema(optional, withAggregations)), [
|
|
4741
|
+
"equals",
|
|
4742
|
+
"not"
|
|
4743
|
+
], withAggregations ? [
|
|
4744
|
+
"_count",
|
|
4745
|
+
"_min",
|
|
4746
|
+
"_max"
|
|
4747
|
+
] : void 0);
|
|
4176
4748
|
return z.union([
|
|
4177
4749
|
this.nullableIf(z.boolean(), optional),
|
|
4178
|
-
z.
|
|
4179
|
-
equals: this.nullableIf(z.boolean(), optional).optional(),
|
|
4180
|
-
not: z.lazy(() => this.makeBooleanFilterSchema(optional)).optional()
|
|
4181
|
-
})
|
|
4750
|
+
z.strictObject(components)
|
|
4182
4751
|
]);
|
|
4183
4752
|
}
|
|
4184
|
-
makeBytesFilterSchema(optional) {
|
|
4753
|
+
makeBytesFilterSchema(optional, withAggregations) {
|
|
4185
4754
|
const baseSchema = z.instanceof(Uint8Array);
|
|
4186
|
-
const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.instanceof(Uint8Array)
|
|
4755
|
+
const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.instanceof(Uint8Array), [
|
|
4756
|
+
"equals",
|
|
4757
|
+
"in",
|
|
4758
|
+
"notIn",
|
|
4759
|
+
"not"
|
|
4760
|
+
], withAggregations ? [
|
|
4761
|
+
"_count",
|
|
4762
|
+
"_min",
|
|
4763
|
+
"_max"
|
|
4764
|
+
] : void 0);
|
|
4187
4765
|
return z.union([
|
|
4188
4766
|
this.nullableIf(baseSchema, optional),
|
|
4189
|
-
z.
|
|
4190
|
-
equals: components.equals,
|
|
4191
|
-
in: components.in,
|
|
4192
|
-
notIn: components.notIn,
|
|
4193
|
-
not: components.not
|
|
4194
|
-
})
|
|
4767
|
+
z.strictObject(components)
|
|
4195
4768
|
]);
|
|
4196
4769
|
}
|
|
4197
|
-
makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis) {
|
|
4198
|
-
|
|
4770
|
+
makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis, supportedOperators = void 0, withAggregations = void 0) {
|
|
4771
|
+
const commonAggSchema = /* @__PURE__ */ __name(() => this.makeCommonPrimitiveFilterSchema(baseSchema, false, makeThis, void 0).optional(), "commonAggSchema");
|
|
4772
|
+
let result = {
|
|
4199
4773
|
equals: this.nullableIf(baseSchema.optional(), optional),
|
|
4200
4774
|
notEquals: this.nullableIf(baseSchema.optional(), optional),
|
|
4201
4775
|
in: baseSchema.array().optional(),
|
|
@@ -4204,20 +4778,70 @@ var InputValidator = class {
|
|
|
4204
4778
|
lte: baseSchema.optional(),
|
|
4205
4779
|
gt: baseSchema.optional(),
|
|
4206
4780
|
gte: baseSchema.optional(),
|
|
4207
|
-
not: makeThis().optional()
|
|
4781
|
+
not: makeThis().optional(),
|
|
4782
|
+
...withAggregations?.includes("_count") ? {
|
|
4783
|
+
_count: this.makeNumberFilterSchema(z.int(), false, false).optional()
|
|
4784
|
+
} : {},
|
|
4785
|
+
...withAggregations?.includes("_avg") ? {
|
|
4786
|
+
_avg: commonAggSchema()
|
|
4787
|
+
} : {},
|
|
4788
|
+
...withAggregations?.includes("_sum") ? {
|
|
4789
|
+
_sum: commonAggSchema()
|
|
4790
|
+
} : {},
|
|
4791
|
+
...withAggregations?.includes("_min") ? {
|
|
4792
|
+
_min: commonAggSchema()
|
|
4793
|
+
} : {},
|
|
4794
|
+
...withAggregations?.includes("_max") ? {
|
|
4795
|
+
_max: commonAggSchema()
|
|
4796
|
+
} : {}
|
|
4208
4797
|
};
|
|
4798
|
+
if (supportedOperators) {
|
|
4799
|
+
const keys = [
|
|
4800
|
+
...supportedOperators,
|
|
4801
|
+
...withAggregations ?? []
|
|
4802
|
+
];
|
|
4803
|
+
result = extractFields(result, keys);
|
|
4804
|
+
}
|
|
4805
|
+
return result;
|
|
4209
4806
|
}
|
|
4210
|
-
makeCommonPrimitiveFilterSchema(baseSchema, optional, makeThis) {
|
|
4807
|
+
makeCommonPrimitiveFilterSchema(baseSchema, optional, makeThis, withAggregations = void 0) {
|
|
4211
4808
|
return z.union([
|
|
4212
4809
|
this.nullableIf(baseSchema, optional),
|
|
4213
|
-
z.
|
|
4810
|
+
z.strictObject(this.makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis, void 0, withAggregations))
|
|
4214
4811
|
]);
|
|
4215
4812
|
}
|
|
4216
|
-
makeNumberFilterSchema(baseSchema, optional) {
|
|
4217
|
-
return this.makeCommonPrimitiveFilterSchema(baseSchema, optional, () => z.lazy(() => this.makeNumberFilterSchema(baseSchema, optional))
|
|
4813
|
+
makeNumberFilterSchema(baseSchema, optional, withAggregations) {
|
|
4814
|
+
return this.makeCommonPrimitiveFilterSchema(baseSchema, optional, () => z.lazy(() => this.makeNumberFilterSchema(baseSchema, optional, withAggregations)), withAggregations ? [
|
|
4815
|
+
"_count",
|
|
4816
|
+
"_avg",
|
|
4817
|
+
"_sum",
|
|
4818
|
+
"_min",
|
|
4819
|
+
"_max"
|
|
4820
|
+
] : void 0);
|
|
4821
|
+
}
|
|
4822
|
+
makeStringFilterSchema(optional, withAggregations) {
|
|
4823
|
+
return z.union([
|
|
4824
|
+
this.nullableIf(z.string(), optional),
|
|
4825
|
+
z.strictObject({
|
|
4826
|
+
...this.makeCommonPrimitiveFilterComponents(z.string(), optional, () => z.lazy(() => this.makeStringFilterSchema(optional, withAggregations)), void 0, withAggregations ? [
|
|
4827
|
+
"_count",
|
|
4828
|
+
"_min",
|
|
4829
|
+
"_max"
|
|
4830
|
+
] : void 0),
|
|
4831
|
+
startsWith: z.string().optional(),
|
|
4832
|
+
endsWith: z.string().optional(),
|
|
4833
|
+
contains: z.string().optional(),
|
|
4834
|
+
...this.providerSupportsCaseSensitivity ? {
|
|
4835
|
+
mode: this.makeStringModeSchema().optional()
|
|
4836
|
+
} : {}
|
|
4837
|
+
})
|
|
4838
|
+
]);
|
|
4218
4839
|
}
|
|
4219
|
-
|
|
4220
|
-
return
|
|
4840
|
+
makeStringModeSchema() {
|
|
4841
|
+
return z.union([
|
|
4842
|
+
z.literal("default"),
|
|
4843
|
+
z.literal("insensitive")
|
|
4844
|
+
]);
|
|
4221
4845
|
}
|
|
4222
4846
|
makeSelectSchema(model) {
|
|
4223
4847
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4227,7 +4851,7 @@ var InputValidator = class {
|
|
|
4227
4851
|
if (fieldDef.relation) {
|
|
4228
4852
|
fields[field] = z.union([
|
|
4229
4853
|
z.literal(true),
|
|
4230
|
-
z.
|
|
4854
|
+
z.strictObject({
|
|
4231
4855
|
select: z.lazy(() => this.makeSelectSchema(fieldDef.type)).optional(),
|
|
4232
4856
|
include: z.lazy(() => this.makeIncludeSchema(fieldDef.type)).optional()
|
|
4233
4857
|
})
|
|
@@ -4236,22 +4860,24 @@ var InputValidator = class {
|
|
|
4236
4860
|
fields[field] = z.boolean().optional();
|
|
4237
4861
|
}
|
|
4238
4862
|
}
|
|
4239
|
-
const toManyRelations = Object.
|
|
4863
|
+
const toManyRelations = Object.values(modelDef.fields).filter((def) => def.relation && def.array);
|
|
4240
4864
|
if (toManyRelations.length > 0) {
|
|
4241
4865
|
fields["_count"] = z.union([
|
|
4242
4866
|
z.literal(true),
|
|
4243
|
-
z.
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
z.
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4867
|
+
z.strictObject({
|
|
4868
|
+
select: z.strictObject(toManyRelations.reduce((acc, fieldDef) => ({
|
|
4869
|
+
...acc,
|
|
4870
|
+
[fieldDef.name]: z.union([
|
|
4871
|
+
z.boolean(),
|
|
4872
|
+
z.strictObject({
|
|
4873
|
+
where: this.makeWhereSchema(fieldDef.type, false, false)
|
|
4874
|
+
})
|
|
4875
|
+
]).optional()
|
|
4876
|
+
}), {}))
|
|
4877
|
+
})
|
|
4252
4878
|
]).optional();
|
|
4253
4879
|
}
|
|
4254
|
-
return z.
|
|
4880
|
+
return z.strictObject(fields);
|
|
4255
4881
|
}
|
|
4256
4882
|
makeOmitSchema(model) {
|
|
4257
4883
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4262,7 +4888,7 @@ var InputValidator = class {
|
|
|
4262
4888
|
fields[field] = z.boolean().optional();
|
|
4263
4889
|
}
|
|
4264
4890
|
}
|
|
4265
|
-
return z.
|
|
4891
|
+
return z.strictObject(fields);
|
|
4266
4892
|
}
|
|
4267
4893
|
makeIncludeSchema(model) {
|
|
4268
4894
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4272,15 +4898,20 @@ var InputValidator = class {
|
|
|
4272
4898
|
if (fieldDef.relation) {
|
|
4273
4899
|
fields[field] = z.union([
|
|
4274
4900
|
z.literal(true),
|
|
4275
|
-
z.
|
|
4901
|
+
z.strictObject({
|
|
4276
4902
|
select: z.lazy(() => this.makeSelectSchema(fieldDef.type)).optional(),
|
|
4277
4903
|
include: z.lazy(() => this.makeIncludeSchema(fieldDef.type)).optional(),
|
|
4278
|
-
|
|
4904
|
+
omit: z.lazy(() => this.makeOmitSchema(fieldDef.type)).optional(),
|
|
4905
|
+
where: z.lazy(() => this.makeWhereSchema(fieldDef.type, false)).optional(),
|
|
4906
|
+
orderBy: z.lazy(() => this.makeOrderBySchema(fieldDef.type, true, false)).optional(),
|
|
4907
|
+
skip: this.makeSkipSchema().optional(),
|
|
4908
|
+
take: this.makeTakeSchema().optional(),
|
|
4909
|
+
distinct: this.makeDistinctSchema(fieldDef.type).optional()
|
|
4279
4910
|
})
|
|
4280
4911
|
]).optional();
|
|
4281
4912
|
}
|
|
4282
4913
|
}
|
|
4283
|
-
return z.
|
|
4914
|
+
return z.strictObject(fields);
|
|
4284
4915
|
}
|
|
4285
4916
|
makeOrderBySchema(model, withRelation, WithAggregation) {
|
|
4286
4917
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4293,13 +4924,21 @@ var InputValidator = class {
|
|
|
4293
4924
|
const fieldDef = requireField(this.schema, model, field);
|
|
4294
4925
|
if (fieldDef.relation) {
|
|
4295
4926
|
if (withRelation) {
|
|
4296
|
-
fields[field] = z.lazy(() =>
|
|
4927
|
+
fields[field] = z.lazy(() => {
|
|
4928
|
+
let relationOrderBy = this.makeOrderBySchema(fieldDef.type, withRelation, WithAggregation);
|
|
4929
|
+
if (fieldDef.array) {
|
|
4930
|
+
relationOrderBy = relationOrderBy.extend({
|
|
4931
|
+
_count: sort
|
|
4932
|
+
});
|
|
4933
|
+
}
|
|
4934
|
+
return relationOrderBy.optional();
|
|
4935
|
+
});
|
|
4297
4936
|
}
|
|
4298
4937
|
} else {
|
|
4299
4938
|
if (fieldDef.optional) {
|
|
4300
4939
|
fields[field] = z.union([
|
|
4301
4940
|
sort,
|
|
4302
|
-
z.
|
|
4941
|
+
z.strictObject({
|
|
4303
4942
|
sort,
|
|
4304
4943
|
nulls: z.union([
|
|
4305
4944
|
z.literal("first"),
|
|
@@ -4324,7 +4963,7 @@ var InputValidator = class {
|
|
|
4324
4963
|
fields[agg] = z.lazy(() => this.makeOrderBySchema(model, true, false).optional());
|
|
4325
4964
|
}
|
|
4326
4965
|
}
|
|
4327
|
-
return z.
|
|
4966
|
+
return z.strictObject(fields);
|
|
4328
4967
|
}
|
|
4329
4968
|
makeDistinctSchema(model) {
|
|
4330
4969
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4343,7 +4982,7 @@ var InputValidator = class {
|
|
|
4343
4982
|
select: this.makeSelectSchema(model).optional(),
|
|
4344
4983
|
include: this.makeIncludeSchema(model).optional(),
|
|
4345
4984
|
omit: this.makeOmitSchema(model).optional()
|
|
4346
|
-
})
|
|
4985
|
+
});
|
|
4347
4986
|
return this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
4348
4987
|
}
|
|
4349
4988
|
makeCreateManySchema(model) {
|
|
@@ -4351,15 +4990,15 @@ var InputValidator = class {
|
|
|
4351
4990
|
}
|
|
4352
4991
|
makeCreateManyAndReturnSchema(model) {
|
|
4353
4992
|
const base = this.makeCreateManyDataSchema(model, []);
|
|
4354
|
-
const result = base.merge(z.
|
|
4993
|
+
const result = base.merge(z.strictObject({
|
|
4355
4994
|
select: this.makeSelectSchema(model).optional(),
|
|
4356
4995
|
omit: this.makeOmitSchema(model).optional()
|
|
4357
4996
|
}));
|
|
4358
4997
|
return this.refineForSelectOmitMutuallyExclusive(result).optional();
|
|
4359
4998
|
}
|
|
4360
4999
|
makeCreateDataSchema(model, canBeArray, withoutFields = [], withoutRelationFields = false) {
|
|
4361
|
-
const
|
|
4362
|
-
const
|
|
5000
|
+
const uncheckedVariantFields = {};
|
|
5001
|
+
const checkedVariantFields = {};
|
|
4363
5002
|
const modelDef = requireModel(this.schema, model);
|
|
4364
5003
|
const hasRelation = !withoutRelationFields && Object.entries(modelDef.fields).some(([f, def]) => !withoutFields.includes(f) && def.relation);
|
|
4365
5004
|
Object.keys(modelDef.fields).forEach((field) => {
|
|
@@ -4370,6 +5009,9 @@ var InputValidator = class {
|
|
|
4370
5009
|
if (fieldDef.computed) {
|
|
4371
5010
|
return;
|
|
4372
5011
|
}
|
|
5012
|
+
if (this.isDelegateDiscriminator(fieldDef)) {
|
|
5013
|
+
return;
|
|
5014
|
+
}
|
|
4373
5015
|
if (fieldDef.relation) {
|
|
4374
5016
|
if (withoutRelationFields) {
|
|
4375
5017
|
return;
|
|
@@ -4401,13 +5043,16 @@ var InputValidator = class {
|
|
|
4401
5043
|
if (fieldDef.optional && !fieldDef.array) {
|
|
4402
5044
|
fieldSchema = fieldSchema.nullable();
|
|
4403
5045
|
}
|
|
4404
|
-
|
|
5046
|
+
checkedVariantFields[field] = fieldSchema;
|
|
5047
|
+
if (fieldDef.array || !fieldDef.relation.references) {
|
|
5048
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
5049
|
+
}
|
|
4405
5050
|
} else {
|
|
4406
5051
|
let fieldSchema = this.makePrimitiveSchema(fieldDef.type);
|
|
4407
5052
|
if (fieldDef.array) {
|
|
4408
5053
|
fieldSchema = z.union([
|
|
4409
5054
|
z.array(fieldSchema),
|
|
4410
|
-
z.
|
|
5055
|
+
z.strictObject({
|
|
4411
5056
|
set: z.array(fieldSchema)
|
|
4412
5057
|
})
|
|
4413
5058
|
]).optional();
|
|
@@ -4418,27 +5063,34 @@ var InputValidator = class {
|
|
|
4418
5063
|
if (fieldDef.optional) {
|
|
4419
5064
|
fieldSchema = fieldSchema.nullable();
|
|
4420
5065
|
}
|
|
4421
|
-
|
|
5066
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4422
5067
|
if (!fieldDef.foreignKeyFor) {
|
|
4423
|
-
|
|
5068
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4424
5069
|
}
|
|
4425
5070
|
}
|
|
4426
5071
|
});
|
|
4427
5072
|
if (!hasRelation) {
|
|
4428
|
-
return this.orArray(z.
|
|
5073
|
+
return this.orArray(z.strictObject(uncheckedVariantFields), canBeArray);
|
|
4429
5074
|
} else {
|
|
4430
5075
|
return z.union([
|
|
4431
|
-
z.
|
|
4432
|
-
z.
|
|
5076
|
+
z.strictObject(uncheckedVariantFields),
|
|
5077
|
+
z.strictObject(checkedVariantFields),
|
|
4433
5078
|
...canBeArray ? [
|
|
4434
|
-
z.array(z.
|
|
5079
|
+
z.array(z.strictObject(uncheckedVariantFields))
|
|
4435
5080
|
] : [],
|
|
4436
5081
|
...canBeArray ? [
|
|
4437
|
-
z.array(z.
|
|
5082
|
+
z.array(z.strictObject(checkedVariantFields))
|
|
4438
5083
|
] : []
|
|
4439
5084
|
]);
|
|
4440
5085
|
}
|
|
4441
5086
|
}
|
|
5087
|
+
isDelegateDiscriminator(fieldDef) {
|
|
5088
|
+
if (!fieldDef.originModel) {
|
|
5089
|
+
return false;
|
|
5090
|
+
}
|
|
5091
|
+
const discriminatorField = getDiscriminatorField(this.schema, fieldDef.originModel);
|
|
5092
|
+
return discriminatorField === fieldDef.name;
|
|
5093
|
+
}
|
|
4442
5094
|
makeRelationManipulationSchema(fieldDef, withoutFields, mode) {
|
|
4443
5095
|
const fieldType = fieldDef.type;
|
|
4444
5096
|
const array = !!fieldDef.array;
|
|
@@ -4455,31 +5107,31 @@ var InputValidator = class {
|
|
|
4455
5107
|
fields["disconnect"] = this.makeDisconnectDataSchema(fieldType, array).optional();
|
|
4456
5108
|
fields["delete"] = this.makeDeleteRelationDataSchema(fieldType, array, true).optional();
|
|
4457
5109
|
}
|
|
4458
|
-
fields["update"] = array ? this.orArray(z.
|
|
5110
|
+
fields["update"] = array ? this.orArray(z.strictObject({
|
|
4459
5111
|
where: this.makeWhereSchema(fieldType, true),
|
|
4460
5112
|
data: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
4461
5113
|
}), true).optional() : z.union([
|
|
4462
|
-
z.
|
|
5114
|
+
z.strictObject({
|
|
4463
5115
|
where: this.makeWhereSchema(fieldType, true),
|
|
4464
5116
|
data: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
4465
5117
|
}),
|
|
4466
5118
|
this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
4467
5119
|
]).optional();
|
|
4468
|
-
fields["upsert"] = this.orArray(z.
|
|
5120
|
+
fields["upsert"] = this.orArray(z.strictObject({
|
|
4469
5121
|
where: this.makeWhereSchema(fieldType, true),
|
|
4470
5122
|
create: this.makeCreateDataSchema(fieldType, false, withoutFields),
|
|
4471
5123
|
update: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
4472
5124
|
}), true).optional();
|
|
4473
5125
|
if (array) {
|
|
4474
5126
|
fields["set"] = this.makeSetDataSchema(fieldType, true).optional();
|
|
4475
|
-
fields["updateMany"] = this.orArray(z.
|
|
5127
|
+
fields["updateMany"] = this.orArray(z.strictObject({
|
|
4476
5128
|
where: this.makeWhereSchema(fieldType, false, true),
|
|
4477
5129
|
data: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
4478
5130
|
}), true).optional();
|
|
4479
5131
|
fields["deleteMany"] = this.makeDeleteRelationDataSchema(fieldType, true, false).optional();
|
|
4480
5132
|
}
|
|
4481
5133
|
}
|
|
4482
|
-
return z.
|
|
5134
|
+
return z.strictObject(fields);
|
|
4483
5135
|
}
|
|
4484
5136
|
makeSetDataSchema(model, canBeArray) {
|
|
4485
5137
|
return this.orArray(this.makeWhereSchema(model, true), canBeArray);
|
|
@@ -4509,13 +5161,13 @@ var InputValidator = class {
|
|
|
4509
5161
|
return this.orArray(z.object({
|
|
4510
5162
|
where: whereSchema,
|
|
4511
5163
|
create: createSchema
|
|
4512
|
-
})
|
|
5164
|
+
}), canBeArray);
|
|
4513
5165
|
}
|
|
4514
5166
|
makeCreateManyDataSchema(model, withoutFields) {
|
|
4515
5167
|
return z.object({
|
|
4516
5168
|
data: this.makeCreateDataSchema(model, true, withoutFields, true),
|
|
4517
5169
|
skipDuplicates: z.boolean().optional()
|
|
4518
|
-
})
|
|
5170
|
+
});
|
|
4519
5171
|
}
|
|
4520
5172
|
// #endregion
|
|
4521
5173
|
// #region Update
|
|
@@ -4526,19 +5178,19 @@ var InputValidator = class {
|
|
|
4526
5178
|
select: this.makeSelectSchema(model).optional(),
|
|
4527
5179
|
include: this.makeIncludeSchema(model).optional(),
|
|
4528
5180
|
omit: this.makeOmitSchema(model).optional()
|
|
4529
|
-
})
|
|
5181
|
+
});
|
|
4530
5182
|
return this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
4531
5183
|
}
|
|
4532
5184
|
makeUpdateManySchema(model) {
|
|
4533
5185
|
return z.object({
|
|
4534
5186
|
where: this.makeWhereSchema(model, false).optional(),
|
|
4535
5187
|
data: this.makeUpdateDataSchema(model, [], true),
|
|
4536
|
-
limit: z.
|
|
4537
|
-
})
|
|
5188
|
+
limit: z.int().nonnegative().optional()
|
|
5189
|
+
});
|
|
4538
5190
|
}
|
|
4539
5191
|
makeUpdateManyAndReturnSchema(model) {
|
|
4540
5192
|
const base = this.makeUpdateManySchema(model);
|
|
4541
|
-
const result = base.merge(z.
|
|
5193
|
+
const result = base.merge(z.strictObject({
|
|
4542
5194
|
select: this.makeSelectSchema(model).optional(),
|
|
4543
5195
|
omit: this.makeOmitSchema(model).optional()
|
|
4544
5196
|
}));
|
|
@@ -4552,12 +5204,12 @@ var InputValidator = class {
|
|
|
4552
5204
|
select: this.makeSelectSchema(model).optional(),
|
|
4553
5205
|
include: this.makeIncludeSchema(model).optional(),
|
|
4554
5206
|
omit: this.makeOmitSchema(model).optional()
|
|
4555
|
-
})
|
|
5207
|
+
});
|
|
4556
5208
|
return this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
4557
5209
|
}
|
|
4558
5210
|
makeUpdateDataSchema(model, withoutFields = [], withoutRelationFields = false) {
|
|
4559
|
-
const
|
|
4560
|
-
const
|
|
5211
|
+
const uncheckedVariantFields = {};
|
|
5212
|
+
const checkedVariantFields = {};
|
|
4561
5213
|
const modelDef = requireModel(this.schema, model);
|
|
4562
5214
|
const hasRelation = Object.entries(modelDef.fields).some(([key, value]) => value.relation && !withoutFields.includes(key));
|
|
4563
5215
|
Object.keys(modelDef.fields).forEach((field) => {
|
|
@@ -4582,7 +5234,10 @@ var InputValidator = class {
|
|
|
4582
5234
|
if (fieldDef.optional && !fieldDef.array) {
|
|
4583
5235
|
fieldSchema = fieldSchema.nullable();
|
|
4584
5236
|
}
|
|
4585
|
-
|
|
5237
|
+
checkedVariantFields[field] = fieldSchema;
|
|
5238
|
+
if (fieldDef.array || !fieldDef.relation.references) {
|
|
5239
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
5240
|
+
}
|
|
4586
5241
|
} else {
|
|
4587
5242
|
let fieldSchema = this.makePrimitiveSchema(fieldDef.type).optional();
|
|
4588
5243
|
if (this.isNumericField(fieldDef)) {
|
|
@@ -4609,18 +5264,18 @@ var InputValidator = class {
|
|
|
4609
5264
|
if (fieldDef.optional) {
|
|
4610
5265
|
fieldSchema = fieldSchema.nullable();
|
|
4611
5266
|
}
|
|
4612
|
-
|
|
5267
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4613
5268
|
if (!fieldDef.foreignKeyFor) {
|
|
4614
|
-
|
|
5269
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4615
5270
|
}
|
|
4616
5271
|
}
|
|
4617
5272
|
});
|
|
4618
5273
|
if (!hasRelation) {
|
|
4619
|
-
return z.
|
|
5274
|
+
return z.strictObject(uncheckedVariantFields);
|
|
4620
5275
|
} else {
|
|
4621
5276
|
return z.union([
|
|
4622
|
-
z.
|
|
4623
|
-
z.
|
|
5277
|
+
z.strictObject(uncheckedVariantFields),
|
|
5278
|
+
z.strictObject(checkedVariantFields)
|
|
4624
5279
|
]);
|
|
4625
5280
|
}
|
|
4626
5281
|
}
|
|
@@ -4631,25 +5286,25 @@ var InputValidator = class {
|
|
|
4631
5286
|
where: this.makeWhereSchema(model, true),
|
|
4632
5287
|
select: this.makeSelectSchema(model).optional(),
|
|
4633
5288
|
include: this.makeIncludeSchema(model).optional()
|
|
4634
|
-
})
|
|
5289
|
+
});
|
|
4635
5290
|
return this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
4636
5291
|
}
|
|
4637
5292
|
makeDeleteManySchema(model) {
|
|
4638
5293
|
return z.object({
|
|
4639
5294
|
where: this.makeWhereSchema(model, false).optional(),
|
|
4640
|
-
limit: z.
|
|
4641
|
-
}).
|
|
5295
|
+
limit: z.int().nonnegative().optional()
|
|
5296
|
+
}).optional();
|
|
4642
5297
|
}
|
|
4643
5298
|
// #endregion
|
|
4644
5299
|
// #region Count
|
|
4645
5300
|
makeCountSchema(model) {
|
|
4646
5301
|
return z.object({
|
|
4647
5302
|
where: this.makeWhereSchema(model, false).optional(),
|
|
4648
|
-
skip:
|
|
4649
|
-
take:
|
|
5303
|
+
skip: this.makeSkipSchema().optional(),
|
|
5304
|
+
take: this.makeTakeSchema().optional(),
|
|
4650
5305
|
orderBy: this.orArray(this.makeOrderBySchema(model, true, false), true).optional(),
|
|
4651
5306
|
select: this.makeCountAggregateInputSchema(model).optional()
|
|
4652
|
-
}).
|
|
5307
|
+
}).optional();
|
|
4653
5308
|
}
|
|
4654
5309
|
makeCountAggregateInputSchema(model) {
|
|
4655
5310
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4661,7 +5316,7 @@ var InputValidator = class {
|
|
|
4661
5316
|
acc[field] = z.literal(true).optional();
|
|
4662
5317
|
return acc;
|
|
4663
5318
|
}, {})
|
|
4664
|
-
})
|
|
5319
|
+
})
|
|
4665
5320
|
]);
|
|
4666
5321
|
}
|
|
4667
5322
|
// #endregion
|
|
@@ -4669,19 +5324,19 @@ var InputValidator = class {
|
|
|
4669
5324
|
makeAggregateSchema(model) {
|
|
4670
5325
|
return z.object({
|
|
4671
5326
|
where: this.makeWhereSchema(model, false).optional(),
|
|
4672
|
-
skip:
|
|
4673
|
-
take:
|
|
5327
|
+
skip: this.makeSkipSchema().optional(),
|
|
5328
|
+
take: this.makeTakeSchema().optional(),
|
|
4674
5329
|
orderBy: this.orArray(this.makeOrderBySchema(model, true, false), true).optional(),
|
|
4675
5330
|
_count: this.makeCountAggregateInputSchema(model).optional(),
|
|
4676
5331
|
_avg: this.makeSumAvgInputSchema(model).optional(),
|
|
4677
5332
|
_sum: this.makeSumAvgInputSchema(model).optional(),
|
|
4678
5333
|
_min: this.makeMinMaxInputSchema(model).optional(),
|
|
4679
5334
|
_max: this.makeMinMaxInputSchema(model).optional()
|
|
4680
|
-
}).
|
|
5335
|
+
}).optional();
|
|
4681
5336
|
}
|
|
4682
5337
|
makeSumAvgInputSchema(model) {
|
|
4683
5338
|
const modelDef = requireModel(this.schema, model);
|
|
4684
|
-
return z.
|
|
5339
|
+
return z.strictObject(Object.keys(modelDef.fields).reduce((acc, field) => {
|
|
4685
5340
|
const fieldDef = requireField(this.schema, model, field);
|
|
4686
5341
|
if (this.isNumericField(fieldDef)) {
|
|
4687
5342
|
acc[field] = z.literal(true).optional();
|
|
@@ -4691,7 +5346,7 @@ var InputValidator = class {
|
|
|
4691
5346
|
}
|
|
4692
5347
|
makeMinMaxInputSchema(model) {
|
|
4693
5348
|
const modelDef = requireModel(this.schema, model);
|
|
4694
|
-
return z.
|
|
5349
|
+
return z.strictObject(Object.keys(modelDef.fields).reduce((acc, field) => {
|
|
4695
5350
|
const fieldDef = requireField(this.schema, model, field);
|
|
4696
5351
|
if (!fieldDef.relation && !fieldDef.array) {
|
|
4697
5352
|
acc[field] = z.literal(true).optional();
|
|
@@ -4706,30 +5361,42 @@ var InputValidator = class {
|
|
|
4706
5361
|
where: this.makeWhereSchema(model, false).optional(),
|
|
4707
5362
|
orderBy: this.orArray(this.makeOrderBySchema(model, false, true), true).optional(),
|
|
4708
5363
|
by: this.orArray(z.enum(nonRelationFields), true),
|
|
4709
|
-
having: this.
|
|
4710
|
-
skip:
|
|
4711
|
-
take:
|
|
5364
|
+
having: this.makeHavingSchema(model).optional(),
|
|
5365
|
+
skip: this.makeSkipSchema().optional(),
|
|
5366
|
+
take: this.makeTakeSchema().optional(),
|
|
4712
5367
|
_count: this.makeCountAggregateInputSchema(model).optional(),
|
|
4713
5368
|
_avg: this.makeSumAvgInputSchema(model).optional(),
|
|
4714
5369
|
_sum: this.makeSumAvgInputSchema(model).optional(),
|
|
4715
5370
|
_min: this.makeMinMaxInputSchema(model).optional(),
|
|
4716
5371
|
_max: this.makeMinMaxInputSchema(model).optional()
|
|
4717
|
-
})
|
|
5372
|
+
});
|
|
4718
5373
|
schema = schema.refine((value) => {
|
|
4719
5374
|
const bys = typeof value.by === "string" ? [
|
|
4720
5375
|
value.by
|
|
4721
5376
|
] : value.by;
|
|
4722
|
-
if (value.having &&
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
5377
|
+
if (value.having && typeof value.having === "object") {
|
|
5378
|
+
for (const [key, val] of Object.entries(value.having)) {
|
|
5379
|
+
if (AGGREGATE_OPERATORS.includes(key)) {
|
|
5380
|
+
continue;
|
|
5381
|
+
}
|
|
5382
|
+
if (bys.includes(key)) {
|
|
5383
|
+
continue;
|
|
5384
|
+
}
|
|
5385
|
+
if (!val || typeof val !== "object") {
|
|
5386
|
+
return false;
|
|
5387
|
+
}
|
|
5388
|
+
if (!this.onlyAggregationFields(val)) {
|
|
5389
|
+
return false;
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
4726
5392
|
}
|
|
5393
|
+
return true;
|
|
4727
5394
|
}, 'fields in "having" must be in "by"');
|
|
4728
5395
|
schema = schema.refine((value) => {
|
|
4729
5396
|
const bys = typeof value.by === "string" ? [
|
|
4730
5397
|
value.by
|
|
4731
5398
|
] : value.by;
|
|
4732
|
-
if (value.orderBy && Object.keys(value.orderBy).filter((f) => !
|
|
5399
|
+
if (value.orderBy && Object.keys(value.orderBy).filter((f) => !AGGREGATE_OPERATORS.includes(f)).some((key) => !bys.includes(key))) {
|
|
4733
5400
|
return false;
|
|
4734
5401
|
} else {
|
|
4735
5402
|
return true;
|
|
@@ -4737,8 +5404,31 @@ var InputValidator = class {
|
|
|
4737
5404
|
}, 'fields in "orderBy" must be in "by"');
|
|
4738
5405
|
return schema;
|
|
4739
5406
|
}
|
|
5407
|
+
onlyAggregationFields(val) {
|
|
5408
|
+
for (const [key, value] of Object.entries(val)) {
|
|
5409
|
+
if (AGGREGATE_OPERATORS.includes(key)) {
|
|
5410
|
+
continue;
|
|
5411
|
+
}
|
|
5412
|
+
if (LOGICAL_COMBINATORS.includes(key)) {
|
|
5413
|
+
if (enumerate(value).every((v) => this.onlyAggregationFields(v))) {
|
|
5414
|
+
continue;
|
|
5415
|
+
}
|
|
5416
|
+
}
|
|
5417
|
+
return false;
|
|
5418
|
+
}
|
|
5419
|
+
return true;
|
|
5420
|
+
}
|
|
5421
|
+
makeHavingSchema(model) {
|
|
5422
|
+
return this.makeWhereSchema(model, false, true, true);
|
|
5423
|
+
}
|
|
4740
5424
|
// #endregion
|
|
4741
5425
|
// #region Helpers
|
|
5426
|
+
makeSkipSchema() {
|
|
5427
|
+
return z.int().nonnegative();
|
|
5428
|
+
}
|
|
5429
|
+
makeTakeSchema() {
|
|
5430
|
+
return z.int();
|
|
5431
|
+
}
|
|
4742
5432
|
refineForSelectIncludeMutuallyExclusive(schema) {
|
|
4743
5433
|
return schema.refine((value) => !(value["select"] && value["include"]), '"select" and "include" cannot be used together');
|
|
4744
5434
|
}
|
|
@@ -4757,6 +5447,9 @@ var InputValidator = class {
|
|
|
4757
5447
|
isNumericField(fieldDef) {
|
|
4758
5448
|
return NUMERIC_FIELD_TYPES.includes(fieldDef.type) && !fieldDef.array;
|
|
4759
5449
|
}
|
|
5450
|
+
get providerSupportsCaseSensitivity() {
|
|
5451
|
+
return this.schema.provider.type === "postgresql";
|
|
5452
|
+
}
|
|
4760
5453
|
};
|
|
4761
5454
|
|
|
4762
5455
|
// src/client/executor/zenstack-driver.ts
|
|
@@ -4766,11 +5459,11 @@ var ZenStackDriver = class {
|
|
|
4766
5459
|
}
|
|
4767
5460
|
#driver;
|
|
4768
5461
|
#log;
|
|
4769
|
-
txConnection;
|
|
4770
5462
|
#initPromise;
|
|
4771
5463
|
#initDone;
|
|
4772
5464
|
#destroyPromise;
|
|
4773
5465
|
#connections = /* @__PURE__ */ new WeakSet();
|
|
5466
|
+
#txConnections = /* @__PURE__ */ new WeakMap();
|
|
4774
5467
|
constructor(driver, log) {
|
|
4775
5468
|
this.#initDone = false;
|
|
4776
5469
|
this.#driver = driver;
|
|
@@ -4811,21 +5504,30 @@ var ZenStackDriver = class {
|
|
|
4811
5504
|
}
|
|
4812
5505
|
async beginTransaction(connection, settings) {
|
|
4813
5506
|
const result = await this.#driver.beginTransaction(connection, settings);
|
|
4814
|
-
this.
|
|
5507
|
+
this.#txConnections.set(connection, []);
|
|
4815
5508
|
return result;
|
|
4816
5509
|
}
|
|
4817
|
-
commitTransaction(connection) {
|
|
5510
|
+
async commitTransaction(connection) {
|
|
4818
5511
|
try {
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
this.
|
|
5512
|
+
const result = await this.#driver.commitTransaction(connection);
|
|
5513
|
+
const callbacks = this.#txConnections.get(connection);
|
|
5514
|
+
this.#txConnections.delete(connection);
|
|
5515
|
+
if (callbacks) {
|
|
5516
|
+
for (const callback of callbacks) {
|
|
5517
|
+
await callback();
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
return result;
|
|
5521
|
+
} catch (err) {
|
|
5522
|
+
this.#txConnections.delete(connection);
|
|
5523
|
+
throw err;
|
|
4822
5524
|
}
|
|
4823
5525
|
}
|
|
4824
|
-
rollbackTransaction(connection) {
|
|
5526
|
+
async rollbackTransaction(connection) {
|
|
4825
5527
|
try {
|
|
4826
|
-
return this.#driver.rollbackTransaction(connection);
|
|
5528
|
+
return await this.#driver.rollbackTransaction(connection);
|
|
4827
5529
|
} finally {
|
|
4828
|
-
this.
|
|
5530
|
+
this.#txConnections.delete(connection);
|
|
4829
5531
|
}
|
|
4830
5532
|
}
|
|
4831
5533
|
async destroy() {
|
|
@@ -4903,6 +5605,22 @@ var ZenStackDriver = class {
|
|
|
4903
5605
|
#calculateDurationMillis(startTime) {
|
|
4904
5606
|
return performanceNow() - startTime;
|
|
4905
5607
|
}
|
|
5608
|
+
isTransactionConnection(connection) {
|
|
5609
|
+
return this.#txConnections.has(connection);
|
|
5610
|
+
}
|
|
5611
|
+
registerTransactionCommitCallback(connection, callback) {
|
|
5612
|
+
if (!this.#txConnections.has(connection)) {
|
|
5613
|
+
return;
|
|
5614
|
+
}
|
|
5615
|
+
const callbacks = this.#txConnections.get(connection);
|
|
5616
|
+
if (callbacks) {
|
|
5617
|
+
callbacks.push(callback);
|
|
5618
|
+
} else {
|
|
5619
|
+
this.#txConnections.set(connection, [
|
|
5620
|
+
callback
|
|
5621
|
+
]);
|
|
5622
|
+
}
|
|
5623
|
+
}
|
|
4906
5624
|
};
|
|
4907
5625
|
function performanceNow() {
|
|
4908
5626
|
if (typeof performance !== "undefined" && typeof performance.now === "function") {
|
|
@@ -4914,9 +5632,10 @@ function performanceNow() {
|
|
|
4914
5632
|
__name(performanceNow, "performanceNow");
|
|
4915
5633
|
|
|
4916
5634
|
// src/client/executor/zenstack-query-executor.ts
|
|
4917
|
-
import { AndNode as AndNode2, DefaultQueryExecutor, DeleteQueryNode as DeleteQueryNode2, InsertQueryNode as InsertQueryNode2, ReturningNode as ReturningNode3, SelectionNode as SelectionNode4,
|
|
5635
|
+
import { AndNode as AndNode2, DefaultQueryExecutor, DeleteQueryNode as DeleteQueryNode2, InsertQueryNode as InsertQueryNode2, ReturningNode as ReturningNode3, SelectionNode as SelectionNode4, UpdateQueryNode as UpdateQueryNode2, WhereNode as WhereNode3 } from "kysely";
|
|
4918
5636
|
import { nanoid as nanoid2 } from "nanoid";
|
|
4919
|
-
import {
|
|
5637
|
+
import { inspect as inspect2 } from "util";
|
|
5638
|
+
import { match as match16 } from "ts-pattern";
|
|
4920
5639
|
|
|
4921
5640
|
// src/client/executor/name-mapper.ts
|
|
4922
5641
|
import { AliasNode as AliasNode4, ColumnNode as ColumnNode3, IdentifierNode as IdentifierNode3, OperationNodeTransformer as OperationNodeTransformer2, ReferenceNode as ReferenceNode3, ReturningNode as ReturningNode2, SelectAllNode, SelectionNode as SelectionNode3, TableNode as TableNode4 } from "kysely";
|
|
@@ -4925,11 +5644,11 @@ var QueryNameMapper = class extends OperationNodeTransformer2 {
|
|
|
4925
5644
|
__name(this, "QueryNameMapper");
|
|
4926
5645
|
}
|
|
4927
5646
|
schema;
|
|
4928
|
-
modelToTableMap;
|
|
4929
|
-
fieldToColumnMap;
|
|
4930
|
-
modelStack;
|
|
5647
|
+
modelToTableMap = /* @__PURE__ */ new Map();
|
|
5648
|
+
fieldToColumnMap = /* @__PURE__ */ new Map();
|
|
5649
|
+
modelStack = [];
|
|
4931
5650
|
constructor(schema) {
|
|
4932
|
-
super(), this.schema = schema
|
|
5651
|
+
super(), this.schema = schema;
|
|
4933
5652
|
for (const [modelName, modelDef] of Object.entries(schema.models)) {
|
|
4934
5653
|
const mappedName = this.getMappedName(modelDef);
|
|
4935
5654
|
if (mappedName) {
|
|
@@ -5118,7 +5837,7 @@ var QueryNameMapper = class extends OperationNodeTransformer2 {
|
|
|
5118
5837
|
this.requireCurrentModel(contextNode);
|
|
5119
5838
|
model = model ?? this.currentModel;
|
|
5120
5839
|
const modelDef = requireModel(this.schema, model);
|
|
5121
|
-
const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed).map(([fieldName]) => fieldName);
|
|
5840
|
+
const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed && !fieldDef.originModel).map(([fieldName]) => fieldName);
|
|
5122
5841
|
return scalarFields;
|
|
5123
5842
|
}
|
|
5124
5843
|
};
|
|
@@ -5143,16 +5862,18 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5143
5862
|
get options() {
|
|
5144
5863
|
return this.client.$options;
|
|
5145
5864
|
}
|
|
5146
|
-
async executeQuery(compiledQuery,
|
|
5865
|
+
async executeQuery(compiledQuery, _queryId) {
|
|
5147
5866
|
let queryNode = compiledQuery.query;
|
|
5148
5867
|
let mutationInterceptionInfo;
|
|
5149
5868
|
if (this.isMutationNode(queryNode) && this.hasMutationHooks) {
|
|
5150
5869
|
mutationInterceptionInfo = await this.callMutationInterceptionFilters(queryNode);
|
|
5151
5870
|
}
|
|
5152
5871
|
const task = /* @__PURE__ */ __name(async () => {
|
|
5153
|
-
|
|
5872
|
+
if (this.isMutationNode(queryNode)) {
|
|
5873
|
+
await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
|
|
5874
|
+
}
|
|
5154
5875
|
const oldQueryNode = queryNode;
|
|
5155
|
-
if ((InsertQueryNode2.is(queryNode) ||
|
|
5876
|
+
if ((InsertQueryNode2.is(queryNode) || UpdateQueryNode2.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
|
|
5156
5877
|
queryNode = {
|
|
5157
5878
|
...queryNode,
|
|
5158
5879
|
returning: ReturningNode3.create([
|
|
@@ -5160,42 +5881,73 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5160
5881
|
])
|
|
5161
5882
|
};
|
|
5162
5883
|
}
|
|
5163
|
-
const
|
|
5164
|
-
await this.
|
|
5884
|
+
const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
|
|
5885
|
+
const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams);
|
|
5886
|
+
if (this.isMutationNode(queryNode)) {
|
|
5887
|
+
await this.callAfterMutationHooks(result.result, queryNode, mutationInterceptionInfo, result.connection);
|
|
5888
|
+
}
|
|
5165
5889
|
if (oldQueryNode !== queryNode) {
|
|
5166
5890
|
}
|
|
5167
|
-
return result;
|
|
5891
|
+
return result.result;
|
|
5168
5892
|
}, "task");
|
|
5169
|
-
return
|
|
5170
|
-
}
|
|
5171
|
-
proceedQueryWithKyselyInterceptors(queryNode,
|
|
5172
|
-
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q,
|
|
5173
|
-
const
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5893
|
+
return task();
|
|
5894
|
+
}
|
|
5895
|
+
proceedQueryWithKyselyInterceptors(queryNode, parameters) {
|
|
5896
|
+
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters), "proceed");
|
|
5897
|
+
const hooks = [];
|
|
5898
|
+
for (const plugin of this.client.$options.plugins ?? []) {
|
|
5899
|
+
if (plugin.onKyselyQuery) {
|
|
5900
|
+
hooks.push(plugin.onKyselyQuery.bind(plugin));
|
|
5901
|
+
}
|
|
5902
|
+
}
|
|
5177
5903
|
for (const hook of hooks) {
|
|
5178
5904
|
const _proceed = proceed;
|
|
5179
|
-
proceed = /* @__PURE__ */ __name((query) => {
|
|
5180
|
-
|
|
5905
|
+
proceed = /* @__PURE__ */ __name(async (query) => {
|
|
5906
|
+
let connection;
|
|
5907
|
+
const _p = /* @__PURE__ */ __name(async (q) => {
|
|
5908
|
+
const r = await _proceed(q);
|
|
5909
|
+
connection = r.connection;
|
|
5910
|
+
return r.result;
|
|
5911
|
+
}, "_p");
|
|
5912
|
+
const hookResult = await hook({
|
|
5181
5913
|
client: this.client,
|
|
5182
5914
|
schema: this.client.$schema,
|
|
5183
5915
|
kysely: this.kysely,
|
|
5184
5916
|
query,
|
|
5185
|
-
proceed:
|
|
5186
|
-
transaction: makeTx(_proceed)
|
|
5917
|
+
proceed: _p
|
|
5187
5918
|
});
|
|
5919
|
+
return {
|
|
5920
|
+
result: hookResult,
|
|
5921
|
+
connection
|
|
5922
|
+
};
|
|
5188
5923
|
}, "proceed");
|
|
5189
5924
|
}
|
|
5190
5925
|
return proceed(queryNode);
|
|
5191
5926
|
}
|
|
5192
|
-
async proceedQuery(query,
|
|
5927
|
+
async proceedQuery(query, parameters) {
|
|
5193
5928
|
const finalQuery = this.nameMapper.transformNode(query);
|
|
5194
|
-
|
|
5929
|
+
let compiled = this.compileQuery(finalQuery);
|
|
5930
|
+
if (parameters) {
|
|
5931
|
+
compiled = {
|
|
5932
|
+
...compiled,
|
|
5933
|
+
parameters
|
|
5934
|
+
};
|
|
5935
|
+
}
|
|
5195
5936
|
try {
|
|
5196
|
-
return
|
|
5937
|
+
return await this.provideConnection(async (connection) => {
|
|
5938
|
+
const result = await connection.executeQuery(compiled);
|
|
5939
|
+
return {
|
|
5940
|
+
result,
|
|
5941
|
+
connection
|
|
5942
|
+
};
|
|
5943
|
+
});
|
|
5197
5944
|
} catch (err) {
|
|
5198
|
-
|
|
5945
|
+
let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
|
|
5946
|
+
if (this.options.debug) {
|
|
5947
|
+
message += `, parameters:
|
|
5948
|
+
${compiled.parameters.map((p) => inspect2(p)).join("\n")}`;
|
|
5949
|
+
}
|
|
5950
|
+
throw new QueryError(message, err);
|
|
5199
5951
|
}
|
|
5200
5952
|
}
|
|
5201
5953
|
isMutationNode(queryNode) {
|
|
@@ -5223,30 +5975,15 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5223
5975
|
return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, []);
|
|
5224
5976
|
}
|
|
5225
5977
|
withConnectionProvider(connectionProvider) {
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
if (!useTransaction || this.driver.txConnection) {
|
|
5230
|
-
return callback();
|
|
5231
|
-
} else {
|
|
5232
|
-
return this.provideConnection(async (connection) => {
|
|
5233
|
-
try {
|
|
5234
|
-
await this.driver.beginTransaction(connection, {});
|
|
5235
|
-
const result = await callback();
|
|
5236
|
-
await this.driver.commitTransaction(connection);
|
|
5237
|
-
return result;
|
|
5238
|
-
} catch (error) {
|
|
5239
|
-
await this.driver.rollbackTransaction(connection);
|
|
5240
|
-
throw error;
|
|
5241
|
-
}
|
|
5242
|
-
});
|
|
5243
|
-
}
|
|
5978
|
+
const newExecutor = new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
|
|
5979
|
+
newExecutor.client = this.client.withExecutor(newExecutor);
|
|
5980
|
+
return newExecutor;
|
|
5244
5981
|
}
|
|
5245
5982
|
get hasMutationHooks() {
|
|
5246
5983
|
return this.client.$options.plugins?.some((plugin) => plugin.beforeEntityMutation || plugin.afterEntityMutation);
|
|
5247
5984
|
}
|
|
5248
5985
|
getMutationModel(queryNode) {
|
|
5249
|
-
return
|
|
5986
|
+
return match16(queryNode).when(InsertQueryNode2.is, (node) => node.into.table.identifier.name).when(UpdateQueryNode2.is, (node) => node.table.table.identifier.name).when(DeleteQueryNode2.is, (node) => {
|
|
5250
5987
|
if (node.from.froms.length !== 1) {
|
|
5251
5988
|
throw new InternalError(`Delete query must have exactly one from table`);
|
|
5252
5989
|
}
|
|
@@ -5262,7 +5999,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5262
5999
|
const result = {
|
|
5263
6000
|
intercept: false
|
|
5264
6001
|
};
|
|
5265
|
-
const { action, where } =
|
|
6002
|
+
const { action, where } = match16(queryNode).when(InsertQueryNode2.is, () => ({
|
|
5266
6003
|
action: "create",
|
|
5267
6004
|
where: void 0
|
|
5268
6005
|
})).when(UpdateQueryNode2.is, (node) => ({
|
|
@@ -5282,14 +6019,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5282
6019
|
queryNode
|
|
5283
6020
|
});
|
|
5284
6021
|
result.intercept ||= filterResult.intercept;
|
|
5285
|
-
result.useTransactionForMutation ||= filterResult.useTransactionForMutation;
|
|
5286
6022
|
result.loadBeforeMutationEntity ||= filterResult.loadBeforeMutationEntity;
|
|
5287
6023
|
result.loadAfterMutationEntity ||= filterResult.loadAfterMutationEntity;
|
|
5288
6024
|
}
|
|
5289
6025
|
}
|
|
5290
6026
|
let beforeMutationEntities;
|
|
5291
6027
|
if (result.loadBeforeMutationEntity && (UpdateQueryNode2.is(queryNode) || DeleteQueryNode2.is(queryNode))) {
|
|
5292
|
-
beforeMutationEntities = await this.loadEntities(
|
|
6028
|
+
beforeMutationEntities = await this.loadEntities(mutationModel, where);
|
|
5293
6029
|
}
|
|
5294
6030
|
return {
|
|
5295
6031
|
...result,
|
|
@@ -5302,16 +6038,16 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5302
6038
|
return void 0;
|
|
5303
6039
|
}
|
|
5304
6040
|
}
|
|
5305
|
-
callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
6041
|
+
async callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
5306
6042
|
if (!mutationInterceptionInfo?.intercept) {
|
|
5307
6043
|
return;
|
|
5308
6044
|
}
|
|
5309
6045
|
if (this.options.plugins) {
|
|
6046
|
+
const mutationModel = this.getMutationModel(queryNode);
|
|
5310
6047
|
for (const plugin of this.options.plugins) {
|
|
5311
6048
|
if (plugin.beforeEntityMutation) {
|
|
5312
|
-
plugin.beforeEntityMutation({
|
|
5313
|
-
|
|
5314
|
-
model: this.getMutationModel(queryNode),
|
|
6049
|
+
await plugin.beforeEntityMutation({
|
|
6050
|
+
model: mutationModel,
|
|
5315
6051
|
action: mutationInterceptionInfo.action,
|
|
5316
6052
|
queryNode,
|
|
5317
6053
|
entities: mutationInterceptionInfo.beforeMutationEntities
|
|
@@ -5320,44 +6056,59 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5320
6056
|
}
|
|
5321
6057
|
}
|
|
5322
6058
|
}
|
|
5323
|
-
async
|
|
6059
|
+
async callAfterMutationHooks(queryResult, queryNode, mutationInterceptionInfo, connection) {
|
|
5324
6060
|
if (!mutationInterceptionInfo?.intercept) {
|
|
5325
6061
|
return;
|
|
5326
6062
|
}
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
6063
|
+
const hooks = [];
|
|
6064
|
+
for (const plugin of this.options.plugins ?? []) {
|
|
6065
|
+
if (plugin.afterEntityMutation) {
|
|
6066
|
+
hooks.push(plugin.afterEntityMutation.bind(plugin));
|
|
6067
|
+
}
|
|
6068
|
+
}
|
|
6069
|
+
if (hooks.length === 0) {
|
|
6070
|
+
return;
|
|
6071
|
+
}
|
|
6072
|
+
const mutationModel = this.getMutationModel(queryNode);
|
|
6073
|
+
const inTransaction = this.driver.isTransactionConnection(connection);
|
|
6074
|
+
for (const hook of hooks) {
|
|
6075
|
+
let afterMutationEntities = void 0;
|
|
6076
|
+
if (mutationInterceptionInfo.loadAfterMutationEntity) {
|
|
6077
|
+
if (InsertQueryNode2.is(queryNode) || UpdateQueryNode2.is(queryNode)) {
|
|
6078
|
+
afterMutationEntities = queryResult.rows;
|
|
6079
|
+
}
|
|
6080
|
+
}
|
|
6081
|
+
const action = /* @__PURE__ */ __name(async () => {
|
|
6082
|
+
try {
|
|
6083
|
+
await hook({
|
|
6084
|
+
model: mutationModel,
|
|
5341
6085
|
action: mutationInterceptionInfo.action,
|
|
5342
6086
|
queryNode,
|
|
5343
6087
|
beforeMutationEntities: mutationInterceptionInfo.beforeMutationEntities,
|
|
5344
6088
|
afterMutationEntities
|
|
5345
6089
|
});
|
|
6090
|
+
} catch (err) {
|
|
6091
|
+
console.error(`Error in afterEntityMutation hook for model "${mutationModel}": ${err}`);
|
|
5346
6092
|
}
|
|
6093
|
+
}, "action");
|
|
6094
|
+
if (inTransaction) {
|
|
6095
|
+
this.driver.registerTransactionCommitCallback(connection, action);
|
|
6096
|
+
} else {
|
|
6097
|
+
await action();
|
|
5347
6098
|
}
|
|
5348
6099
|
}
|
|
5349
6100
|
}
|
|
5350
|
-
async loadEntities(
|
|
5351
|
-
const selectQuery = kysely.selectFrom(model).selectAll();
|
|
6101
|
+
async loadEntities(model, where) {
|
|
6102
|
+
const selectQuery = this.kysely.selectFrom(model).selectAll();
|
|
5352
6103
|
let selectQueryNode = selectQuery.toOperationNode();
|
|
5353
6104
|
selectQueryNode = {
|
|
5354
6105
|
...selectQueryNode,
|
|
5355
6106
|
where: this.andNodes(selectQueryNode.where, where)
|
|
5356
6107
|
};
|
|
5357
|
-
const compiled =
|
|
6108
|
+
const compiled = this.compileQuery(selectQueryNode);
|
|
6109
|
+
const result = await this.executeQuery(compiled, {
|
|
5358
6110
|
queryId: `zenstack-${nanoid2()}`
|
|
5359
6111
|
});
|
|
5360
|
-
const result = await kysely.executeQuery(compiled);
|
|
5361
6112
|
return result.rows;
|
|
5362
6113
|
}
|
|
5363
6114
|
andNodes(condition1, condition2) {
|
|
@@ -5386,9 +6137,9 @@ __export(functions_exports, {
|
|
|
5386
6137
|
search: () => search,
|
|
5387
6138
|
startsWith: () => startsWith
|
|
5388
6139
|
});
|
|
5389
|
-
import {
|
|
5390
|
-
import
|
|
5391
|
-
import { match as
|
|
6140
|
+
import { invariant as invariant9, lowerCaseFirst, upperCaseFirst } from "@zenstackhq/common-helpers";
|
|
6141
|
+
import { sql as sql7, ValueNode as ValueNode4 } from "kysely";
|
|
6142
|
+
import { match as match17 } from "ts-pattern";
|
|
5392
6143
|
var contains = /* @__PURE__ */ __name((eb, args) => {
|
|
5393
6144
|
const [field, search2, caseInsensitive = false] = args;
|
|
5394
6145
|
if (!field) {
|
|
@@ -5398,9 +6149,9 @@ var contains = /* @__PURE__ */ __name((eb, args) => {
|
|
|
5398
6149
|
throw new Error('"search" parameter is required');
|
|
5399
6150
|
}
|
|
5400
6151
|
const searchExpr = eb.fn("CONCAT", [
|
|
5401
|
-
|
|
6152
|
+
sql7.lit("%"),
|
|
5402
6153
|
search2,
|
|
5403
|
-
|
|
6154
|
+
sql7.lit("%")
|
|
5404
6155
|
]);
|
|
5405
6156
|
return eb(field, caseInsensitive ? "ilike" : "like", searchExpr);
|
|
5406
6157
|
}, "contains");
|
|
@@ -5417,7 +6168,7 @@ var startsWith = /* @__PURE__ */ __name((eb, args) => {
|
|
|
5417
6168
|
}
|
|
5418
6169
|
return eb(field, "like", eb.fn("CONCAT", [
|
|
5419
6170
|
search2,
|
|
5420
|
-
|
|
6171
|
+
sql7.lit("%")
|
|
5421
6172
|
]));
|
|
5422
6173
|
}, "startsWith");
|
|
5423
6174
|
var endsWith = /* @__PURE__ */ __name((eb, args) => {
|
|
@@ -5429,7 +6180,7 @@ var endsWith = /* @__PURE__ */ __name((eb, args) => {
|
|
|
5429
6180
|
throw new Error('"search" parameter is required');
|
|
5430
6181
|
}
|
|
5431
6182
|
return eb(field, "like", eb.fn("CONCAT", [
|
|
5432
|
-
|
|
6183
|
+
sql7.lit("%"),
|
|
5433
6184
|
search2
|
|
5434
6185
|
]));
|
|
5435
6186
|
}, "endsWith");
|
|
@@ -5470,10 +6221,10 @@ var isEmpty = /* @__PURE__ */ __name((eb, args, { dialect }) => {
|
|
|
5470
6221
|
if (!field) {
|
|
5471
6222
|
throw new Error('"field" parameter is required');
|
|
5472
6223
|
}
|
|
5473
|
-
return eb(dialect.buildArrayLength(eb, field), "=",
|
|
6224
|
+
return eb(dialect.buildArrayLength(eb, field), "=", sql7.lit(0));
|
|
5474
6225
|
}, "isEmpty");
|
|
5475
6226
|
var now = /* @__PURE__ */ __name((eb, _args, { dialect }) => {
|
|
5476
|
-
return
|
|
6227
|
+
return match17(dialect.provider).with("postgresql", () => eb.fn("now")).with("sqlite", () => sql7.raw("CURRENT_TIMESTAMP")).exhaustive();
|
|
5477
6228
|
}, "now");
|
|
5478
6229
|
var currentModel = /* @__PURE__ */ __name((_eb, args, { model }) => {
|
|
5479
6230
|
let result = model;
|
|
@@ -5481,7 +6232,7 @@ var currentModel = /* @__PURE__ */ __name((_eb, args, { model }) => {
|
|
|
5481
6232
|
if (casing) {
|
|
5482
6233
|
result = processCasing(casing, result, model);
|
|
5483
6234
|
}
|
|
5484
|
-
return
|
|
6235
|
+
return sql7.lit(result);
|
|
5485
6236
|
}, "currentModel");
|
|
5486
6237
|
var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
5487
6238
|
let result = operation;
|
|
@@ -5489,12 +6240,12 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
|
5489
6240
|
if (casing) {
|
|
5490
6241
|
result = processCasing(casing, result, operation);
|
|
5491
6242
|
}
|
|
5492
|
-
return
|
|
6243
|
+
return sql7.lit(result);
|
|
5493
6244
|
}, "currentOperation");
|
|
5494
6245
|
function processCasing(casing, result, model) {
|
|
5495
6246
|
const opNode = casing.toOperationNode();
|
|
5496
|
-
|
|
5497
|
-
result =
|
|
6247
|
+
invariant9(ValueNode4.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
|
|
6248
|
+
result = match17(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => upperCaseFirst(result)).with("uncapitalize", () => lowerCaseFirst(result)).otherwise(() => {
|
|
5498
6249
|
throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
|
|
5499
6250
|
});
|
|
5500
6251
|
return result;
|
|
@@ -5502,9 +6253,9 @@ function processCasing(casing, result, model) {
|
|
|
5502
6253
|
__name(processCasing, "processCasing");
|
|
5503
6254
|
|
|
5504
6255
|
// src/client/helpers/schema-db-pusher.ts
|
|
5505
|
-
import {
|
|
5506
|
-
import
|
|
5507
|
-
import { match as
|
|
6256
|
+
import { invariant as invariant10 } from "@zenstackhq/common-helpers";
|
|
6257
|
+
import { sql as sql8 } from "kysely";
|
|
6258
|
+
import { match as match18 } from "ts-pattern";
|
|
5508
6259
|
var SchemaDbPusher = class {
|
|
5509
6260
|
static {
|
|
5510
6261
|
__name(this, "SchemaDbPusher");
|
|
@@ -5535,14 +6286,17 @@ var SchemaDbPusher = class {
|
|
|
5535
6286
|
for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
|
|
5536
6287
|
if (fieldDef.relation) {
|
|
5537
6288
|
table = this.addForeignKeyConstraint(table, model, fieldName, fieldDef);
|
|
5538
|
-
} else {
|
|
6289
|
+
} else if (!this.isComputedField(fieldDef)) {
|
|
5539
6290
|
table = this.createModelField(table, fieldName, fieldDef, modelDef);
|
|
5540
6291
|
}
|
|
5541
6292
|
}
|
|
5542
6293
|
table = this.addPrimaryKeyConstraint(table, model, modelDef);
|
|
5543
|
-
table = this.addUniqueConstraint(table, modelDef);
|
|
6294
|
+
table = this.addUniqueConstraint(table, model, modelDef);
|
|
5544
6295
|
return table;
|
|
5545
6296
|
}
|
|
6297
|
+
isComputedField(fieldDef) {
|
|
6298
|
+
return fieldDef.attributes?.some((a) => a.name === "@computed");
|
|
6299
|
+
}
|
|
5546
6300
|
addPrimaryKeyConstraint(table, model, modelDef) {
|
|
5547
6301
|
if (modelDef.idFields.length === 1) {
|
|
5548
6302
|
if (Object.values(modelDef.fields).some((f) => f.id)) {
|
|
@@ -5554,16 +6308,19 @@ var SchemaDbPusher = class {
|
|
|
5554
6308
|
}
|
|
5555
6309
|
return table;
|
|
5556
6310
|
}
|
|
5557
|
-
addUniqueConstraint(table, modelDef) {
|
|
6311
|
+
addUniqueConstraint(table, model, modelDef) {
|
|
5558
6312
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
5559
|
-
|
|
6313
|
+
invariant10(typeof value === "object", "expecting an object");
|
|
5560
6314
|
if ("type" in value) {
|
|
5561
6315
|
const fieldDef = modelDef.fields[key];
|
|
5562
6316
|
if (fieldDef.unique) {
|
|
5563
6317
|
continue;
|
|
5564
6318
|
}
|
|
6319
|
+
table = table.addUniqueConstraint(`unique_${model}_${key}`, [
|
|
6320
|
+
key
|
|
6321
|
+
]);
|
|
5565
6322
|
} else {
|
|
5566
|
-
table = table.addUniqueConstraint(`unique_${key}`, Object.keys(value));
|
|
6323
|
+
table = table.addUniqueConstraint(`unique_${model}_${key}`, Object.keys(value));
|
|
5567
6324
|
}
|
|
5568
6325
|
}
|
|
5569
6326
|
return table;
|
|
@@ -5576,7 +6333,7 @@ var SchemaDbPusher = class {
|
|
|
5576
6333
|
if (fieldDef.default !== void 0) {
|
|
5577
6334
|
if (typeof fieldDef.default === "object" && "kind" in fieldDef.default) {
|
|
5578
6335
|
if (ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "now") {
|
|
5579
|
-
col = col.defaultTo(
|
|
6336
|
+
col = col.defaultTo(sql8`CURRENT_TIMESTAMP`);
|
|
5580
6337
|
}
|
|
5581
6338
|
} else {
|
|
5582
6339
|
col = col.defaultTo(fieldDef.default);
|
|
@@ -5596,17 +6353,17 @@ var SchemaDbPusher = class {
|
|
|
5596
6353
|
}
|
|
5597
6354
|
mapFieldType(fieldDef) {
|
|
5598
6355
|
if (this.schema.enums?.[fieldDef.type]) {
|
|
5599
|
-
return this.schema.provider.type === "postgresql" ?
|
|
6356
|
+
return this.schema.provider.type === "postgresql" ? sql8.ref(fieldDef.type) : "text";
|
|
5600
6357
|
}
|
|
5601
6358
|
if (this.isAutoIncrement(fieldDef) && this.schema.provider.type === "postgresql") {
|
|
5602
6359
|
return "serial";
|
|
5603
6360
|
}
|
|
5604
6361
|
const type = fieldDef.type;
|
|
5605
|
-
const result =
|
|
6362
|
+
const result = match18(type).with("String", () => "text").with("Boolean", () => "boolean").with("Int", () => "integer").with("Float", () => "real").with("BigInt", () => "bigint").with("Decimal", () => "decimal").with("DateTime", () => "timestamp").with("Bytes", () => this.schema.provider.type === "postgresql" ? "bytea" : "blob").with("Json", () => "jsonb").otherwise(() => {
|
|
5606
6363
|
throw new Error(`Unsupported field type: ${type}`);
|
|
5607
6364
|
});
|
|
5608
6365
|
if (fieldDef.array) {
|
|
5609
|
-
return
|
|
6366
|
+
return sql8.raw(`${result}[]`);
|
|
5610
6367
|
} else {
|
|
5611
6368
|
return result;
|
|
5612
6369
|
}
|
|
@@ -5615,7 +6372,7 @@ var SchemaDbPusher = class {
|
|
|
5615
6372
|
return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
|
|
5616
6373
|
}
|
|
5617
6374
|
addForeignKeyConstraint(table, model, fieldName, fieldDef) {
|
|
5618
|
-
|
|
6375
|
+
invariant10(fieldDef.relation, "field must be a relation");
|
|
5619
6376
|
if (!fieldDef.relation.fields || !fieldDef.relation.references) {
|
|
5620
6377
|
return table;
|
|
5621
6378
|
}
|
|
@@ -5631,16 +6388,16 @@ var SchemaDbPusher = class {
|
|
|
5631
6388
|
return table;
|
|
5632
6389
|
}
|
|
5633
6390
|
mapCascadeAction(action) {
|
|
5634
|
-
return
|
|
6391
|
+
return match18(action).with("SetNull", () => "set null").with("Cascade", () => "cascade").with("Restrict", () => "restrict").with("NoAction", () => "no action").with("SetDefault", () => "set default").exhaustive();
|
|
5635
6392
|
}
|
|
5636
6393
|
};
|
|
5637
6394
|
|
|
5638
6395
|
// src/client/promise.ts
|
|
5639
|
-
function
|
|
6396
|
+
function createZenStackPromise(callback) {
|
|
5640
6397
|
let promise;
|
|
5641
|
-
const cb = /* @__PURE__ */ __name(() => {
|
|
6398
|
+
const cb = /* @__PURE__ */ __name((txClient) => {
|
|
5642
6399
|
try {
|
|
5643
|
-
return promise ??= valueToPromise(callback());
|
|
6400
|
+
return promise ??= valueToPromise(callback(txClient));
|
|
5644
6401
|
} catch (err) {
|
|
5645
6402
|
return Promise.reject(err);
|
|
5646
6403
|
}
|
|
@@ -5655,10 +6412,11 @@ function createDeferredPromise(callback) {
|
|
|
5655
6412
|
finally(onFinally) {
|
|
5656
6413
|
return cb().finally(onFinally);
|
|
5657
6414
|
},
|
|
6415
|
+
cb,
|
|
5658
6416
|
[Symbol.toStringTag]: "ZenStackPromise"
|
|
5659
6417
|
};
|
|
5660
6418
|
}
|
|
5661
|
-
__name(
|
|
6419
|
+
__name(createZenStackPromise, "createZenStackPromise");
|
|
5662
6420
|
function valueToPromise(thing) {
|
|
5663
6421
|
if (typeof thing === "object" && typeof thing?.then === "function") {
|
|
5664
6422
|
return thing;
|
|
@@ -5669,9 +6427,9 @@ function valueToPromise(thing) {
|
|
|
5669
6427
|
__name(valueToPromise, "valueToPromise");
|
|
5670
6428
|
|
|
5671
6429
|
// src/client/result-processor.ts
|
|
6430
|
+
import { invariant as invariant11 } from "@zenstackhq/common-helpers";
|
|
5672
6431
|
import Decimal2 from "decimal.js";
|
|
5673
|
-
import
|
|
5674
|
-
import { match as match18 } from "ts-pattern";
|
|
6432
|
+
import { match as match19 } from "ts-pattern";
|
|
5675
6433
|
var ResultProcessor = class {
|
|
5676
6434
|
static {
|
|
5677
6435
|
__name(this, "ResultProcessor");
|
|
@@ -5705,6 +6463,21 @@ var ResultProcessor = class {
|
|
|
5705
6463
|
data[key] = typeof value === "string" ? JSON.parse(value) : value;
|
|
5706
6464
|
continue;
|
|
5707
6465
|
}
|
|
6466
|
+
if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
|
|
6467
|
+
if (value) {
|
|
6468
|
+
const subRow = this.transformJson(value);
|
|
6469
|
+
const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
|
|
6470
|
+
const idValues = getIdValues(this.schema, subModel, subRow);
|
|
6471
|
+
if (Object.values(idValues).some((v) => v === null || v === void 0)) {
|
|
6472
|
+
delete data[key];
|
|
6473
|
+
continue;
|
|
6474
|
+
}
|
|
6475
|
+
const processedSubRow = this.processRow(subRow, subModel);
|
|
6476
|
+
Object.assign(data, processedSubRow);
|
|
6477
|
+
}
|
|
6478
|
+
delete data[key];
|
|
6479
|
+
continue;
|
|
6480
|
+
}
|
|
5708
6481
|
const fieldDef = getField(this.schema, model, key);
|
|
5709
6482
|
if (!fieldDef) {
|
|
5710
6483
|
continue;
|
|
@@ -5744,20 +6517,24 @@ var ResultProcessor = class {
|
|
|
5744
6517
|
return this.doProcessResult(relationData, fieldDef.type);
|
|
5745
6518
|
}
|
|
5746
6519
|
transformScalar(value, type) {
|
|
5747
|
-
|
|
6520
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
6521
|
+
return this.transformJson(value);
|
|
6522
|
+
} else {
|
|
6523
|
+
return match19(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);
|
|
6524
|
+
}
|
|
5748
6525
|
}
|
|
5749
6526
|
transformDecimal(value) {
|
|
5750
6527
|
if (value instanceof Decimal2) {
|
|
5751
6528
|
return value;
|
|
5752
6529
|
}
|
|
5753
|
-
|
|
6530
|
+
invariant11(typeof value === "string" || typeof value === "number" || value instanceof Decimal2, `Expected string, number or Decimal, got ${typeof value}`);
|
|
5754
6531
|
return new Decimal2(value);
|
|
5755
6532
|
}
|
|
5756
6533
|
transformBigInt(value) {
|
|
5757
6534
|
if (typeof value === "bigint") {
|
|
5758
6535
|
return value;
|
|
5759
6536
|
}
|
|
5760
|
-
|
|
6537
|
+
invariant11(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
5761
6538
|
return BigInt(value);
|
|
5762
6539
|
}
|
|
5763
6540
|
transformBoolean(value) {
|
|
@@ -5776,6 +6553,9 @@ var ResultProcessor = class {
|
|
|
5776
6553
|
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
5777
6554
|
}
|
|
5778
6555
|
fixReversedResult(data, model, args) {
|
|
6556
|
+
if (!data) {
|
|
6557
|
+
return;
|
|
6558
|
+
}
|
|
5779
6559
|
if (Array.isArray(data) && typeof args === "object" && args && args.take !== void 0 && args.take < 0) {
|
|
5780
6560
|
data.reverse();
|
|
5781
6561
|
}
|
|
@@ -5789,13 +6569,19 @@ var ResultProcessor = class {
|
|
|
5789
6569
|
continue;
|
|
5790
6570
|
}
|
|
5791
6571
|
const fieldDef = getField(this.schema, model, field);
|
|
5792
|
-
if (!fieldDef
|
|
6572
|
+
if (!fieldDef || !fieldDef.relation || !fieldDef.array) {
|
|
5793
6573
|
continue;
|
|
5794
6574
|
}
|
|
5795
6575
|
this.fixReversedResult(row[field], fieldDef.type, value);
|
|
5796
6576
|
}
|
|
5797
6577
|
}
|
|
5798
6578
|
}
|
|
6579
|
+
transformJson(value) {
|
|
6580
|
+
return match19(this.schema.provider.type).with("sqlite", () => {
|
|
6581
|
+
invariant11(typeof value === "string", "Expected string, got " + typeof value);
|
|
6582
|
+
return JSON.parse(value);
|
|
6583
|
+
}).otherwise(() => value);
|
|
6584
|
+
}
|
|
5799
6585
|
};
|
|
5800
6586
|
|
|
5801
6587
|
// src/client/client-impl.ts
|
|
@@ -5814,7 +6600,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
5814
6600
|
$schema;
|
|
5815
6601
|
kyselyProps;
|
|
5816
6602
|
auth;
|
|
5817
|
-
constructor(schema, options, baseClient) {
|
|
6603
|
+
constructor(schema, options, baseClient, executor) {
|
|
5818
6604
|
this.schema = schema;
|
|
5819
6605
|
this.options = options;
|
|
5820
6606
|
this.$schema = schema;
|
|
@@ -5826,24 +6612,23 @@ var ClientImpl = class _ClientImpl {
|
|
|
5826
6612
|
if (baseClient) {
|
|
5827
6613
|
this.kyselyProps = {
|
|
5828
6614
|
...baseClient.kyselyProps,
|
|
5829
|
-
executor: new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
|
|
6615
|
+
executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
|
|
5830
6616
|
};
|
|
5831
6617
|
this.kyselyRaw = baseClient.kyselyRaw;
|
|
6618
|
+
this.auth = baseClient.auth;
|
|
5832
6619
|
} else {
|
|
5833
|
-
const
|
|
5834
|
-
const
|
|
5835
|
-
const
|
|
5836
|
-
const adapter = dialect.createAdapter();
|
|
6620
|
+
const driver = new ZenStackDriver(options.dialect.createDriver(), new Log(this.$options.log ?? []));
|
|
6621
|
+
const compiler = options.dialect.createQueryCompiler();
|
|
6622
|
+
const adapter = options.dialect.createAdapter();
|
|
5837
6623
|
const connectionProvider = new DefaultConnectionProvider(driver);
|
|
5838
|
-
const executor = new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider);
|
|
5839
6624
|
this.kyselyProps = {
|
|
5840
6625
|
config: {
|
|
5841
|
-
dialect,
|
|
6626
|
+
dialect: options.dialect,
|
|
5842
6627
|
log: this.$options.log
|
|
5843
6628
|
},
|
|
5844
|
-
dialect,
|
|
6629
|
+
dialect: options.dialect,
|
|
5845
6630
|
driver,
|
|
5846
|
-
executor
|
|
6631
|
+
executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
|
|
5847
6632
|
};
|
|
5848
6633
|
this.kyselyRaw = new Kysely({
|
|
5849
6634
|
...this.kyselyProps,
|
|
@@ -5859,31 +6644,58 @@ var ClientImpl = class _ClientImpl {
|
|
|
5859
6644
|
get $qbRaw() {
|
|
5860
6645
|
return this.kyselyRaw;
|
|
5861
6646
|
}
|
|
5862
|
-
|
|
5863
|
-
return
|
|
6647
|
+
get isTransaction() {
|
|
6648
|
+
return this.kysely.isTransaction;
|
|
5864
6649
|
}
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
};
|
|
5871
|
-
return new PostgresDialect(mergedConfig);
|
|
6650
|
+
/**
|
|
6651
|
+
* Create a new client with a new query executor.
|
|
6652
|
+
*/
|
|
6653
|
+
withExecutor(executor) {
|
|
6654
|
+
return new _ClientImpl(this.schema, this.$options, this, executor);
|
|
5872
6655
|
}
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
}
|
|
5879
|
-
|
|
6656
|
+
// implementation
|
|
6657
|
+
async $transaction(input, options) {
|
|
6658
|
+
invariant12(typeof input === "function" || Array.isArray(input) && input.every((p) => p.then && p.cb), "Invalid transaction input, expected a function or an array of ZenStackPromise");
|
|
6659
|
+
if (typeof input === "function") {
|
|
6660
|
+
return this.interactiveTransaction(input, options);
|
|
6661
|
+
} else {
|
|
6662
|
+
return this.sequentialTransaction(input, options);
|
|
6663
|
+
}
|
|
6664
|
+
}
|
|
6665
|
+
async interactiveTransaction(callback, options) {
|
|
6666
|
+
if (this.kysely.isTransaction) {
|
|
6667
|
+
return callback(this);
|
|
6668
|
+
} else {
|
|
6669
|
+
let txBuilder = this.kysely.transaction();
|
|
6670
|
+
if (options?.isolationLevel) {
|
|
6671
|
+
txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
|
|
6672
|
+
}
|
|
6673
|
+
return txBuilder.execute((tx) => {
|
|
6674
|
+
const txClient = new _ClientImpl(this.schema, this.$options, this);
|
|
6675
|
+
txClient.kysely = tx;
|
|
6676
|
+
return callback(txClient);
|
|
6677
|
+
});
|
|
6678
|
+
}
|
|
5880
6679
|
}
|
|
5881
|
-
async
|
|
5882
|
-
|
|
5883
|
-
const txClient = new _ClientImpl(this.schema, this.$options);
|
|
6680
|
+
async sequentialTransaction(arg, options) {
|
|
6681
|
+
const execute = /* @__PURE__ */ __name(async (tx) => {
|
|
6682
|
+
const txClient = new _ClientImpl(this.schema, this.$options, this);
|
|
5884
6683
|
txClient.kysely = tx;
|
|
5885
|
-
|
|
5886
|
-
|
|
6684
|
+
const result = [];
|
|
6685
|
+
for (const promise of arg) {
|
|
6686
|
+
result.push(await promise.cb(txClient));
|
|
6687
|
+
}
|
|
6688
|
+
return result;
|
|
6689
|
+
}, "execute");
|
|
6690
|
+
if (this.kysely.isTransaction) {
|
|
6691
|
+
return execute(this.kysely);
|
|
6692
|
+
} else {
|
|
6693
|
+
let txBuilder = this.kysely.transaction();
|
|
6694
|
+
if (options?.isolationLevel) {
|
|
6695
|
+
txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
|
|
6696
|
+
}
|
|
6697
|
+
return txBuilder.execute((tx) => execute(tx));
|
|
6698
|
+
}
|
|
5887
6699
|
}
|
|
5888
6700
|
get $procedures() {
|
|
5889
6701
|
return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
|
|
@@ -5911,12 +6723,26 @@ var ClientImpl = class _ClientImpl {
|
|
|
5911
6723
|
await new SchemaDbPusher(this.schema, this.kysely).push();
|
|
5912
6724
|
}
|
|
5913
6725
|
$use(plugin) {
|
|
6726
|
+
const newPlugins = [
|
|
6727
|
+
...this.$options.plugins ?? [],
|
|
6728
|
+
plugin
|
|
6729
|
+
];
|
|
5914
6730
|
const newOptions = {
|
|
5915
6731
|
...this.options,
|
|
5916
|
-
plugins:
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
6732
|
+
plugins: newPlugins
|
|
6733
|
+
};
|
|
6734
|
+
return new _ClientImpl(this.schema, newOptions, this);
|
|
6735
|
+
}
|
|
6736
|
+
$unuse(pluginId) {
|
|
6737
|
+
const newPlugins = [];
|
|
6738
|
+
for (const plugin of this.options.plugins ?? []) {
|
|
6739
|
+
if (plugin.id !== pluginId) {
|
|
6740
|
+
newPlugins.push(plugin);
|
|
6741
|
+
}
|
|
6742
|
+
}
|
|
6743
|
+
const newOptions = {
|
|
6744
|
+
...this.options,
|
|
6745
|
+
plugins: newPlugins
|
|
5920
6746
|
};
|
|
5921
6747
|
return new _ClientImpl(this.schema, newOptions, this);
|
|
5922
6748
|
}
|
|
@@ -5938,6 +6764,39 @@ var ClientImpl = class _ClientImpl {
|
|
|
5938
6764
|
get $auth() {
|
|
5939
6765
|
return this.auth;
|
|
5940
6766
|
}
|
|
6767
|
+
$executeRaw(query, ...values) {
|
|
6768
|
+
return createZenStackPromise(async () => {
|
|
6769
|
+
const result = await sql9(query, ...values).execute(this.kysely);
|
|
6770
|
+
return Number(result.numAffectedRows ?? 0);
|
|
6771
|
+
});
|
|
6772
|
+
}
|
|
6773
|
+
$executeRawUnsafe(query, ...values) {
|
|
6774
|
+
return createZenStackPromise(async () => {
|
|
6775
|
+
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
6776
|
+
const result = await this.kysely.executeQuery(compiledQuery);
|
|
6777
|
+
return Number(result.numAffectedRows ?? 0);
|
|
6778
|
+
});
|
|
6779
|
+
}
|
|
6780
|
+
$queryRaw(query, ...values) {
|
|
6781
|
+
return createZenStackPromise(async () => {
|
|
6782
|
+
const result = await sql9(query, ...values).execute(this.kysely);
|
|
6783
|
+
return result.rows;
|
|
6784
|
+
});
|
|
6785
|
+
}
|
|
6786
|
+
$queryRawUnsafe(query, ...values) {
|
|
6787
|
+
return createZenStackPromise(async () => {
|
|
6788
|
+
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
6789
|
+
const result = await this.kysely.executeQuery(compiledQuery);
|
|
6790
|
+
return result.rows;
|
|
6791
|
+
});
|
|
6792
|
+
}
|
|
6793
|
+
createRawCompiledQuery(query, values) {
|
|
6794
|
+
const q = CompiledQuery.raw(query, values);
|
|
6795
|
+
return {
|
|
6796
|
+
...q,
|
|
6797
|
+
$raw: true
|
|
6798
|
+
};
|
|
6799
|
+
}
|
|
5941
6800
|
};
|
|
5942
6801
|
function createClientProxy(client) {
|
|
5943
6802
|
const inputValidator = new InputValidator(client.$schema);
|
|
@@ -5960,9 +6819,9 @@ function createClientProxy(client) {
|
|
|
5960
6819
|
__name(createClientProxy, "createClientProxy");
|
|
5961
6820
|
function createModelCrudHandler(client, model, inputValidator, resultProcessor) {
|
|
5962
6821
|
const createPromise = /* @__PURE__ */ __name((operation, args, handler, postProcess = false, throwIfNoResult = false) => {
|
|
5963
|
-
return
|
|
5964
|
-
let proceed = /* @__PURE__ */ __name(async (_args
|
|
5965
|
-
const _handler =
|
|
6822
|
+
return createZenStackPromise(async (txClient) => {
|
|
6823
|
+
let proceed = /* @__PURE__ */ __name(async (_args) => {
|
|
6824
|
+
const _handler = txClient ? handler.withClient(txClient) : handler;
|
|
5966
6825
|
const r = await _handler.handle(operation, _args ?? args);
|
|
5967
6826
|
if (!r && throwIfNoResult) {
|
|
5968
6827
|
throw new NotFoundError(model);
|
|
@@ -5975,22 +6834,31 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
5975
6834
|
}
|
|
5976
6835
|
return result;
|
|
5977
6836
|
}, "proceed");
|
|
5978
|
-
const context = {
|
|
5979
|
-
client,
|
|
5980
|
-
model,
|
|
5981
|
-
operation,
|
|
5982
|
-
queryArgs: args
|
|
5983
|
-
};
|
|
5984
6837
|
const plugins = [
|
|
5985
6838
|
...client.$options.plugins ?? []
|
|
5986
6839
|
];
|
|
5987
6840
|
for (const plugin of plugins) {
|
|
5988
|
-
if (plugin.onQuery) {
|
|
5989
|
-
const
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
6841
|
+
if (plugin.onQuery && typeof plugin.onQuery === "object") {
|
|
6842
|
+
for (const [_model, modelHooks] of Object.entries(plugin.onQuery)) {
|
|
6843
|
+
if (_model === lowerCaseFirst2(model) || _model === "$allModels") {
|
|
6844
|
+
if (modelHooks && typeof modelHooks === "object") {
|
|
6845
|
+
for (const [op, opHooks] of Object.entries(modelHooks)) {
|
|
6846
|
+
if (op === operation || op === "$allOperations") {
|
|
6847
|
+
if (typeof opHooks === "function") {
|
|
6848
|
+
const _proceed = proceed;
|
|
6849
|
+
proceed = /* @__PURE__ */ __name(() => opHooks({
|
|
6850
|
+
client,
|
|
6851
|
+
model,
|
|
6852
|
+
operation,
|
|
6853
|
+
args,
|
|
6854
|
+
query: _proceed
|
|
6855
|
+
}), "proceed");
|
|
6856
|
+
}
|
|
6857
|
+
}
|
|
6858
|
+
}
|
|
6859
|
+
}
|
|
6860
|
+
}
|
|
6861
|
+
}
|
|
5994
6862
|
}
|
|
5995
6863
|
}
|
|
5996
6864
|
return proceed(args);
|
|
@@ -6046,12 +6914,23 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
6046
6914
|
return createPromise("aggregate", args, new AggregateOperationHandler(client, model, inputValidator), false);
|
|
6047
6915
|
}, "aggregate"),
|
|
6048
6916
|
groupBy: /* @__PURE__ */ __name((args) => {
|
|
6049
|
-
return createPromise("groupBy", args, new
|
|
6917
|
+
return createPromise("groupBy", args, new GroupByOperationHandler(client, model, inputValidator), true);
|
|
6050
6918
|
}, "groupBy")
|
|
6051
6919
|
};
|
|
6052
6920
|
}
|
|
6053
6921
|
__name(createModelCrudHandler, "createModelCrudHandler");
|
|
6922
|
+
|
|
6923
|
+
// src/client/plugin.ts
|
|
6924
|
+
function definePlugin(plugin) {
|
|
6925
|
+
return plugin;
|
|
6926
|
+
}
|
|
6927
|
+
__name(definePlugin, "definePlugin");
|
|
6054
6928
|
export {
|
|
6055
|
-
|
|
6929
|
+
InputValidationError,
|
|
6930
|
+
InternalError,
|
|
6931
|
+
NotFoundError,
|
|
6932
|
+
QueryError,
|
|
6933
|
+
ZenStackClient,
|
|
6934
|
+
definePlugin
|
|
6056
6935
|
};
|
|
6057
6936
|
//# sourceMappingURL=index.js.map
|