@zenstackhq/runtime 3.0.0-alpha.2 → 3.0.0-alpha.20
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-XFKcwhq7.d.cts} +970 -785
- package/dist/{contract-DguafRNB.d.ts → contract-XFKcwhq7.d.ts} +970 -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 +1774 -892
- 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 +1724 -847
- package/dist/index.js.map +1 -1
- package/dist/plugins/{policy.cjs → policy/index.cjs} +463 -266
- 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} +435 -228
- 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 sql10 } 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";
|
|
427
|
+
import { invariant as invariant7, isPlainObject as isPlainObject3 } from "@zenstackhq/common-helpers";
|
|
283
428
|
import { expressionBuilder as expressionBuilder2, 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
|
|
483
|
+
import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
|
|
316
484
|
import { sql } from "kysely";
|
|
317
|
-
import
|
|
318
|
-
import { match, P } from "ts-pattern";
|
|
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 = buildFieldRef(this.schema, fieldDef.originModel ?? model, key, this.options, 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, sql.ref(`${modelAlias}.${k}`), field), sql.raw(this.negateSort(v, negated)));
|
|
676
874
|
}
|
|
677
875
|
continue;
|
|
678
876
|
}
|
|
@@ -705,7 +903,7 @@ var BaseCrudDialect = class {
|
|
|
705
903
|
invariant(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
706
904
|
const sort = this.negateSort(value._count, negated);
|
|
707
905
|
result = result.orderBy((eb) => {
|
|
708
|
-
let subQuery =
|
|
906
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
709
907
|
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
|
|
710
908
|
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right)))));
|
|
711
909
|
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
@@ -724,14 +922,90 @@ var BaseCrudDialect = class {
|
|
|
724
922
|
});
|
|
725
923
|
return result;
|
|
726
924
|
}
|
|
925
|
+
buildSelectAllFields(model, query, omit) {
|
|
926
|
+
const modelDef = requireModel(this.schema, model);
|
|
927
|
+
let result = query;
|
|
928
|
+
for (const field of Object.keys(modelDef.fields)) {
|
|
929
|
+
if (isRelationField(this.schema, model, field)) {
|
|
930
|
+
continue;
|
|
931
|
+
}
|
|
932
|
+
if (omit?.[field] === true) {
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
935
|
+
result = this.buildSelectField(result, model, model, field);
|
|
936
|
+
}
|
|
937
|
+
const descendants = getDelegateDescendantModels(this.schema, model);
|
|
938
|
+
for (const subModel of descendants) {
|
|
939
|
+
result = this.buildDelegateJoin(model, subModel.name, result);
|
|
940
|
+
result = result.select((eb) => {
|
|
941
|
+
const jsonObject = {};
|
|
942
|
+
for (const field of Object.keys(subModel.fields)) {
|
|
943
|
+
if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
|
|
947
|
+
}
|
|
948
|
+
return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
return result;
|
|
952
|
+
}
|
|
953
|
+
buildSelectField(query, model, modelAlias, field) {
|
|
954
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
955
|
+
if (fieldDef.computed) {
|
|
956
|
+
return query.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(field));
|
|
957
|
+
} else if (!fieldDef.originModel) {
|
|
958
|
+
return query.select(sql.ref(`${modelAlias}.${field}`).as(field));
|
|
959
|
+
} else {
|
|
960
|
+
return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
buildDelegateJoin(thisModel, otherModel, query) {
|
|
964
|
+
const idFields = getIdFields(this.schema, thisModel);
|
|
965
|
+
query = query.leftJoin(otherModel, (qb) => {
|
|
966
|
+
for (const idField of idFields) {
|
|
967
|
+
qb = qb.onRef(`${thisModel}.${idField}`, "=", `${otherModel}.${idField}`);
|
|
968
|
+
}
|
|
969
|
+
return qb;
|
|
970
|
+
});
|
|
971
|
+
return query;
|
|
972
|
+
}
|
|
973
|
+
buildCountJson(model, eb, parentAlias, payload) {
|
|
974
|
+
const modelDef = requireModel(this.schema, model);
|
|
975
|
+
const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
|
|
976
|
+
const selections = payload === true ? {
|
|
977
|
+
select: toManyRelations.reduce((acc, [field]) => {
|
|
978
|
+
acc[field] = true;
|
|
979
|
+
return acc;
|
|
980
|
+
}, {})
|
|
981
|
+
} : payload;
|
|
982
|
+
const jsonObject = {};
|
|
983
|
+
for (const [field, value] of Object.entries(selections.select)) {
|
|
984
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
985
|
+
const fieldModel = fieldDef.type;
|
|
986
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
987
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
988
|
+
for (const [left, right] of joinPairs) {
|
|
989
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
990
|
+
}
|
|
991
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
992
|
+
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
993
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
994
|
+
}
|
|
995
|
+
jsonObject[field] = fieldCountQuery;
|
|
996
|
+
}
|
|
997
|
+
return this.buildJsonObject(eb, jsonObject);
|
|
998
|
+
}
|
|
999
|
+
// #endregion
|
|
1000
|
+
// #region utils
|
|
727
1001
|
negateSort(sort, negated) {
|
|
728
1002
|
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
729
1003
|
}
|
|
730
1004
|
true(eb) {
|
|
731
|
-
return eb.lit(this.transformPrimitive(true, "Boolean"));
|
|
1005
|
+
return eb.lit(this.transformPrimitive(true, "Boolean", false));
|
|
732
1006
|
}
|
|
733
1007
|
false(eb) {
|
|
734
|
-
return eb.lit(this.transformPrimitive(false, "Boolean"));
|
|
1008
|
+
return eb.lit(this.transformPrimitive(false, "Boolean", false));
|
|
735
1009
|
}
|
|
736
1010
|
isTrue(expression) {
|
|
737
1011
|
const node = expression.toOperationNode();
|
|
@@ -780,14 +1054,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
780
1054
|
get provider() {
|
|
781
1055
|
return "postgresql";
|
|
782
1056
|
}
|
|
783
|
-
transformPrimitive(value, type) {
|
|
1057
|
+
transformPrimitive(value, type, forArrayField) {
|
|
784
1058
|
if (value === void 0) {
|
|
785
1059
|
return value;
|
|
786
1060
|
}
|
|
787
1061
|
if (Array.isArray(value)) {
|
|
788
|
-
|
|
1062
|
+
if (type === "Json" && !forArrayField) {
|
|
1063
|
+
return JSON.stringify(value);
|
|
1064
|
+
} else {
|
|
1065
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
1066
|
+
}
|
|
789
1067
|
} else {
|
|
790
|
-
return
|
|
1068
|
+
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
1069
|
}
|
|
792
1070
|
}
|
|
793
1071
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -801,7 +1079,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
801
1079
|
const joinTableName = `${parentName}$${relationField}`;
|
|
802
1080
|
let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
|
|
803
1081
|
result = eb.selectFrom(() => {
|
|
804
|
-
let subQuery =
|
|
1082
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
1083
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
805
1084
|
if (payload && typeof payload === "object") {
|
|
806
1085
|
if (payload.where) {
|
|
807
1086
|
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
@@ -845,34 +1124,57 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
845
1124
|
});
|
|
846
1125
|
return qb;
|
|
847
1126
|
}
|
|
848
|
-
buildRelationObjectArgs(relationModel, relationField, eb, payload,
|
|
1127
|
+
buildRelationObjectArgs(relationModel, relationField, eb, payload, parentAlias) {
|
|
849
1128
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
850
1129
|
const objArgs = [];
|
|
1130
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1131
|
+
if (descendantModels.length > 0) {
|
|
1132
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1133
|
+
sql2.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1134
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1135
|
+
]).flatMap((v) => v));
|
|
1136
|
+
}
|
|
851
1137
|
if (payload === true || !payload.select) {
|
|
852
1138
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
853
1139
|
sql2.lit(field),
|
|
854
1140
|
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
855
1141
|
]).flatMap((v) => v));
|
|
856
1142
|
} else if (payload.select) {
|
|
857
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) =>
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1143
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1144
|
+
if (field === "_count") {
|
|
1145
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1146
|
+
return [
|
|
1147
|
+
sql2.lit(field),
|
|
1148
|
+
subJson
|
|
1149
|
+
];
|
|
1150
|
+
} else {
|
|
1151
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1152
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
|
|
1153
|
+
return [
|
|
1154
|
+
sql2.lit(field),
|
|
1155
|
+
fieldValue
|
|
1156
|
+
];
|
|
1157
|
+
}
|
|
1158
|
+
}).flatMap((v) => v));
|
|
861
1159
|
}
|
|
862
1160
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
863
1161
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
864
1162
|
sql2.lit(field),
|
|
865
|
-
|
|
1163
|
+
// reference the synthesized JSON field
|
|
1164
|
+
eb.ref(`${parentAlias}$${relationField}$${field}.$j`)
|
|
866
1165
|
]).flatMap((v) => v));
|
|
867
1166
|
}
|
|
868
1167
|
return objArgs;
|
|
869
1168
|
}
|
|
870
|
-
buildRelationJoins(
|
|
1169
|
+
buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
|
|
871
1170
|
let result = qb;
|
|
872
|
-
if (typeof payload === "object"
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1171
|
+
if (typeof payload === "object") {
|
|
1172
|
+
const selectInclude = payload.include ?? payload.select;
|
|
1173
|
+
if (selectInclude && typeof selectInclude === "object") {
|
|
1174
|
+
Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
|
|
1175
|
+
result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
876
1178
|
}
|
|
877
1179
|
return result;
|
|
878
1180
|
}
|
|
@@ -912,12 +1214,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
912
1214
|
return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
|
|
913
1215
|
}
|
|
914
1216
|
}
|
|
1217
|
+
get supportInsertWithDefault() {
|
|
1218
|
+
return true;
|
|
1219
|
+
}
|
|
915
1220
|
};
|
|
916
1221
|
|
|
917
1222
|
// src/client/crud/dialects/sqlite.ts
|
|
1223
|
+
import { invariant as invariant3 } from "@zenstackhq/common-helpers";
|
|
918
1224
|
import { sql as sql3 } from "kysely";
|
|
919
|
-
import
|
|
920
|
-
import { match as match3 } from "ts-pattern";
|
|
1225
|
+
import { match as match4 } from "ts-pattern";
|
|
921
1226
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
922
1227
|
static {
|
|
923
1228
|
__name(this, "SqliteCrudDialect");
|
|
@@ -925,26 +1230,31 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
925
1230
|
get provider() {
|
|
926
1231
|
return "sqlite";
|
|
927
1232
|
}
|
|
928
|
-
transformPrimitive(value, type) {
|
|
1233
|
+
transformPrimitive(value, type, _forArrayField) {
|
|
929
1234
|
if (value === void 0) {
|
|
930
1235
|
return value;
|
|
931
1236
|
}
|
|
932
1237
|
if (Array.isArray(value)) {
|
|
933
|
-
return value.map((v) => this.transformPrimitive(v, type));
|
|
1238
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
934
1239
|
} else {
|
|
935
|
-
|
|
1240
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1241
|
+
return JSON.stringify(value);
|
|
1242
|
+
} else {
|
|
1243
|
+
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);
|
|
1244
|
+
}
|
|
936
1245
|
}
|
|
937
1246
|
}
|
|
938
1247
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
939
1248
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
940
1249
|
}
|
|
941
|
-
buildRelationJSON(model, eb, relationField,
|
|
1250
|
+
buildRelationJSON(model, eb, relationField, parentAlias, payload) {
|
|
942
1251
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
943
1252
|
const relationModel = relationFieldDef.type;
|
|
944
1253
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
945
|
-
const subQueryName = `${
|
|
1254
|
+
const subQueryName = `${parentAlias}$${relationField}`;
|
|
946
1255
|
let tbl = eb.selectFrom(() => {
|
|
947
|
-
let subQuery =
|
|
1256
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
1257
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
948
1258
|
if (payload && typeof payload === "object") {
|
|
949
1259
|
if (payload.where) {
|
|
950
1260
|
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
@@ -965,14 +1275,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
965
1275
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
966
1276
|
invariant3(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
967
1277
|
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(`${
|
|
1278
|
+
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
1279
|
} else {
|
|
970
1280
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
971
1281
|
keyPairs.forEach(({ fk, pk }) => {
|
|
972
1282
|
if (ownedByModel) {
|
|
973
|
-
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${
|
|
1283
|
+
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentAlias}.${fk}`);
|
|
974
1284
|
} else {
|
|
975
|
-
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${
|
|
1285
|
+
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentAlias}.${pk}`);
|
|
976
1286
|
}
|
|
977
1287
|
});
|
|
978
1288
|
}
|
|
@@ -980,6 +1290,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
980
1290
|
});
|
|
981
1291
|
tbl = tbl.select(() => {
|
|
982
1292
|
const objArgs = [];
|
|
1293
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1294
|
+
if (descendantModels.length > 0) {
|
|
1295
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1296
|
+
sql3.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1297
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1298
|
+
]).flatMap((v) => v));
|
|
1299
|
+
}
|
|
983
1300
|
if (payload === true || !payload.select) {
|
|
984
1301
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
985
1302
|
sql3.lit(field),
|
|
@@ -987,160 +1304,92 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
987
1304
|
]).flatMap((v) => v));
|
|
988
1305
|
} else if (payload.select) {
|
|
989
1306
|
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);
|
|
1307
|
+
if (field === "_count") {
|
|
1308
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
993
1309
|
return [
|
|
994
1310
|
sql3.lit(field),
|
|
995
1311
|
subJson
|
|
996
1312
|
];
|
|
997
1313
|
} else {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1314
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1315
|
+
if (fieldDef.relation) {
|
|
1316
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1317
|
+
return [
|
|
1318
|
+
sql3.lit(field),
|
|
1319
|
+
subJson
|
|
1320
|
+
];
|
|
1321
|
+
} else {
|
|
1322
|
+
return [
|
|
1323
|
+
sql3.lit(field),
|
|
1324
|
+
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
1325
|
+
];
|
|
1326
|
+
}
|
|
1002
1327
|
}
|
|
1003
1328
|
}).flatMap((v) => v));
|
|
1004
1329
|
}
|
|
1005
1330
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
1006
1331
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
1007
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${
|
|
1332
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1008
1333
|
return [
|
|
1009
1334
|
sql3.lit(field),
|
|
1010
1335
|
subJson
|
|
1011
1336
|
];
|
|
1012
1337
|
}).flatMap((v) => v));
|
|
1013
1338
|
}
|
|
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")
|
|
1339
|
+
if (relationFieldDef.array) {
|
|
1340
|
+
return eb.fn.coalesce(sql3`json_group_array(json_object(${sql3.join(objArgs)}))`, sql3`json_array()`).as("$j");
|
|
1341
|
+
} else {
|
|
1342
|
+
return sql3`json_object(${sql3.join(objArgs)})`.as("data");
|
|
1343
|
+
}
|
|
1344
|
+
});
|
|
1345
|
+
return tbl;
|
|
1346
|
+
}
|
|
1347
|
+
buildSkipTake(query, skip, take) {
|
|
1348
|
+
if (take !== void 0) {
|
|
1349
|
+
query = query.limit(take);
|
|
1350
|
+
}
|
|
1351
|
+
if (skip !== void 0) {
|
|
1352
|
+
query = query.offset(skip);
|
|
1353
|
+
if (take === void 0) {
|
|
1354
|
+
query = query.limit(-1);
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
return query;
|
|
1358
|
+
}
|
|
1359
|
+
buildJsonObject(eb, value) {
|
|
1360
|
+
return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
|
|
1361
|
+
sql3.lit(key),
|
|
1362
|
+
value2
|
|
1363
|
+
]));
|
|
1364
|
+
}
|
|
1365
|
+
get supportsUpdateWithLimit() {
|
|
1366
|
+
return false;
|
|
1367
|
+
}
|
|
1368
|
+
get supportsDeleteWithLimit() {
|
|
1369
|
+
return false;
|
|
1370
|
+
}
|
|
1371
|
+
get supportsDistinctOn() {
|
|
1372
|
+
return false;
|
|
1373
|
+
}
|
|
1374
|
+
buildArrayLength(eb, array) {
|
|
1375
|
+
return eb.fn("json_array_length", [
|
|
1376
|
+
array
|
|
1377
|
+
]);
|
|
1378
|
+
}
|
|
1379
|
+
buildArrayLiteralSQL(_values) {
|
|
1380
|
+
throw new Error("SQLite does not support array literals");
|
|
1381
|
+
}
|
|
1382
|
+
get supportInsertWithDefault() {
|
|
1383
|
+
return false;
|
|
1384
|
+
}
|
|
1142
1385
|
};
|
|
1143
1386
|
|
|
1387
|
+
// src/client/crud/dialects/index.ts
|
|
1388
|
+
function getCrudDialect(schema, options) {
|
|
1389
|
+
return match5(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
|
|
1390
|
+
}
|
|
1391
|
+
__name(getCrudDialect, "getCrudDialect");
|
|
1392
|
+
|
|
1144
1393
|
// src/utils/default-operation-node-visitor.ts
|
|
1145
1394
|
import { OperationNodeVisitor } from "kysely";
|
|
1146
1395
|
var DefaultOperationNodeVisitor = class extends OperationNodeVisitor {
|
|
@@ -1460,19 +1709,19 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1460
1709
|
};
|
|
1461
1710
|
|
|
1462
1711
|
// src/plugins/policy/expression-transformer.ts
|
|
1712
|
+
import { invariant as invariant5 } from "@zenstackhq/common-helpers";
|
|
1463
1713
|
import { AliasNode as AliasNode2, BinaryOperationNode as BinaryOperationNode2, ColumnNode, expressionBuilder, FromNode, FunctionNode as FunctionNode2, IdentifierNode, OperatorNode as OperatorNode2, ReferenceNode as ReferenceNode2, SelectionNode, SelectQueryNode, TableNode as TableNode2, ValueListNode, ValueNode as ValueNode2, WhereNode } from "kysely";
|
|
1464
|
-
import
|
|
1465
|
-
import { match as match6 } from "ts-pattern";
|
|
1714
|
+
import { match as match7 } from "ts-pattern";
|
|
1466
1715
|
|
|
1467
1716
|
// src/plugins/policy/expression-evaluator.ts
|
|
1468
|
-
import invariant4 from "
|
|
1469
|
-
import { match as
|
|
1717
|
+
import { invariant as invariant4 } from "@zenstackhq/common-helpers";
|
|
1718
|
+
import { match as match6 } from "ts-pattern";
|
|
1470
1719
|
var ExpressionEvaluator = class {
|
|
1471
1720
|
static {
|
|
1472
1721
|
__name(this, "ExpressionEvaluator");
|
|
1473
1722
|
}
|
|
1474
1723
|
evaluate(expression, context) {
|
|
1475
|
-
const result =
|
|
1724
|
+
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
1725
|
return result ?? null;
|
|
1477
1726
|
}
|
|
1478
1727
|
evaluateCall(expr2, context) {
|
|
@@ -1483,7 +1732,7 @@ var ExpressionEvaluator = class {
|
|
|
1483
1732
|
}
|
|
1484
1733
|
}
|
|
1485
1734
|
evaluateUnary(expr2, context) {
|
|
1486
|
-
return
|
|
1735
|
+
return match6(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
|
|
1487
1736
|
}
|
|
1488
1737
|
evaluateMember(expr2, context) {
|
|
1489
1738
|
let val = this.evaluate(expr2.receiver, context);
|
|
@@ -1507,7 +1756,7 @@ var ExpressionEvaluator = class {
|
|
|
1507
1756
|
}
|
|
1508
1757
|
const left = this.evaluate(expr2.left, context);
|
|
1509
1758
|
const right = this.evaluate(expr2.right, context);
|
|
1510
|
-
return
|
|
1759
|
+
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
1760
|
const _right = right ?? [];
|
|
1512
1761
|
invariant4(Array.isArray(_right), 'expected array for "in" operator');
|
|
1513
1762
|
return _right.includes(left);
|
|
@@ -1521,7 +1770,7 @@ var ExpressionEvaluator = class {
|
|
|
1521
1770
|
return false;
|
|
1522
1771
|
}
|
|
1523
1772
|
invariant4(Array.isArray(left), "expected array");
|
|
1524
|
-
return
|
|
1773
|
+
return match6(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1525
1774
|
...context,
|
|
1526
1775
|
thisValue: item
|
|
1527
1776
|
}))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
|
|
@@ -1537,11 +1786,11 @@ var ExpressionEvaluator = class {
|
|
|
1537
1786
|
// src/plugins/policy/utils.ts
|
|
1538
1787
|
import { AliasNode, AndNode, BinaryOperationNode, FunctionNode, OperatorNode, OrNode, ParensNode, ReferenceNode, TableNode, UnaryOperationNode, ValueNode } from "kysely";
|
|
1539
1788
|
function trueNode(dialect) {
|
|
1540
|
-
return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
|
|
1789
|
+
return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1541
1790
|
}
|
|
1542
1791
|
__name(trueNode, "trueNode");
|
|
1543
1792
|
function falseNode(dialect) {
|
|
1544
|
-
return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
|
|
1793
|
+
return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1545
1794
|
}
|
|
1546
1795
|
__name(falseNode, "falseNode");
|
|
1547
1796
|
function isTrueNode(node) {
|
|
@@ -1775,7 +2024,7 @@ var ExpressionTransformer = class {
|
|
|
1775
2024
|
const count = FunctionNode2.create("count", [
|
|
1776
2025
|
ValueNode2.createImmediate(1)
|
|
1777
2026
|
]);
|
|
1778
|
-
const predicateResult =
|
|
2027
|
+
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
2028
|
return this.transform(expr2.left, {
|
|
1780
2029
|
...context,
|
|
1781
2030
|
memberSelect: SelectionNode.create(AliasNode2.create(predicateResult, IdentifierNode.create("$t"))),
|
|
@@ -1799,14 +2048,14 @@ var ExpressionTransformer = class {
|
|
|
1799
2048
|
}
|
|
1800
2049
|
}
|
|
1801
2050
|
transformValue(value, type) {
|
|
1802
|
-
return ValueNode2.create(this.dialect.transformPrimitive(value, type) ?? null);
|
|
2051
|
+
return ValueNode2.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
1803
2052
|
}
|
|
1804
2053
|
_unary(expr2, context) {
|
|
1805
2054
|
invariant5(expr2.op === "!", 'only "!" operator is supported');
|
|
1806
2055
|
return BinaryOperationNode2.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
|
|
1807
2056
|
}
|
|
1808
2057
|
transformOperator(op) {
|
|
1809
|
-
const mappedOp =
|
|
2058
|
+
const mappedOp = match7(op).with("==", () => "=").otherwise(() => op);
|
|
1810
2059
|
return OperatorNode2.create(mappedOp);
|
|
1811
2060
|
}
|
|
1812
2061
|
_call(expr2, context) {
|
|
@@ -2042,7 +2291,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2042
2291
|
get kysely() {
|
|
2043
2292
|
return this.client.$qb;
|
|
2044
2293
|
}
|
|
2045
|
-
async handle(node, proceed
|
|
2294
|
+
async handle(node, proceed) {
|
|
2046
2295
|
if (!this.isCrudQueryNode(node)) {
|
|
2047
2296
|
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
2048
2297
|
}
|
|
@@ -2062,27 +2311,20 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2062
2311
|
if (!mutationRequiresTransaction && !node.returning) {
|
|
2063
2312
|
return proceed(this.transformNode(node));
|
|
2064
2313
|
}
|
|
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;
|
|
2314
|
+
if (InsertQueryNode.is(node)) {
|
|
2315
|
+
await this.enforcePreCreatePolicy(node, proceed);
|
|
2316
|
+
}
|
|
2317
|
+
const transformedNode = this.transformNode(node);
|
|
2318
|
+
const result = await proceed(transformedNode);
|
|
2319
|
+
if (!this.onlyReturningId(node)) {
|
|
2320
|
+
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2321
|
+
if (readBackResult.rows.length !== result.rows.length) {
|
|
2322
|
+
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
2080
2323
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2324
|
+
return readBackResult;
|
|
2325
|
+
} else {
|
|
2326
|
+
return result;
|
|
2084
2327
|
}
|
|
2085
|
-
return result;
|
|
2086
2328
|
}
|
|
2087
2329
|
onlyReturningId(node) {
|
|
2088
2330
|
if (!node.returning) {
|
|
@@ -2143,11 +2385,11 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2143
2385
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2144
2386
|
invariant6(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2145
2387
|
result.push({
|
|
2146
|
-
node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
|
|
2388
|
+
node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2147
2389
|
raw: item.value
|
|
2148
2390
|
});
|
|
2149
2391
|
} else {
|
|
2150
|
-
const value = this.dialect.transformPrimitive(item, fieldDef.type);
|
|
2392
|
+
const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
2151
2393
|
if (Array.isArray(value)) {
|
|
2152
2394
|
result.push({
|
|
2153
2395
|
node: RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
@@ -2216,7 +2458,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2216
2458
|
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
2459
|
}
|
|
2218
2460
|
getMutationModel(node) {
|
|
2219
|
-
const r =
|
|
2461
|
+
const r = match8(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
|
|
2220
2462
|
if (node2.from.froms.length !== 1) {
|
|
2221
2463
|
throw new InternalError("Only one from table is supported for delete");
|
|
2222
2464
|
}
|
|
@@ -2378,14 +2620,23 @@ var PolicyPlugin = class {
|
|
|
2378
2620
|
get description() {
|
|
2379
2621
|
return "Enforces access policies defined in the schema.";
|
|
2380
2622
|
}
|
|
2381
|
-
onKyselyQuery({
|
|
2623
|
+
onKyselyQuery({
|
|
2624
|
+
query,
|
|
2625
|
+
client,
|
|
2626
|
+
proceed
|
|
2627
|
+
/*, transaction*/
|
|
2628
|
+
}) {
|
|
2382
2629
|
const handler = new PolicyHandler(client);
|
|
2383
|
-
return handler.handle(
|
|
2630
|
+
return handler.handle(
|
|
2631
|
+
query,
|
|
2632
|
+
proceed
|
|
2633
|
+
/*, transaction*/
|
|
2634
|
+
);
|
|
2384
2635
|
}
|
|
2385
2636
|
};
|
|
2386
2637
|
|
|
2387
2638
|
// src/utils/clone.ts
|
|
2388
|
-
import { isPlainObject as isPlainObject2 } from "
|
|
2639
|
+
import { isPlainObject as isPlainObject2 } from "@zenstackhq/common-helpers";
|
|
2389
2640
|
function clone(value) {
|
|
2390
2641
|
if (Array.isArray(value)) {
|
|
2391
2642
|
return value.map((v) => clone(v));
|
|
@@ -2404,28 +2655,6 @@ function clone(value) {
|
|
|
2404
2655
|
}
|
|
2405
2656
|
__name(clone, "clone");
|
|
2406
2657
|
|
|
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
2658
|
// src/client/crud/operations/base.ts
|
|
2430
2659
|
var BaseOperationHandler = class {
|
|
2431
2660
|
static {
|
|
@@ -2469,17 +2698,17 @@ var BaseOperationHandler = class {
|
|
|
2469
2698
|
getField(model, field) {
|
|
2470
2699
|
return getField(this.schema, model, field);
|
|
2471
2700
|
}
|
|
2472
|
-
exists(kysely, model, filter) {
|
|
2701
|
+
async exists(kysely, model, filter) {
|
|
2473
2702
|
const idFields = getIdFields(this.schema, model);
|
|
2474
2703
|
const _filter = flattenCompoundUniqueFilters(this.schema, model, filter);
|
|
2475
2704
|
const query = kysely.selectFrom(model).where((eb) => eb.and(_filter)).select(idFields.map((f) => kysely.dynamic.ref(f))).limit(1).modifyEnd(this.makeContextComment({
|
|
2476
2705
|
model,
|
|
2477
2706
|
operation: "read"
|
|
2478
2707
|
}));
|
|
2479
|
-
return
|
|
2708
|
+
return this.executeQueryTakeFirst(kysely, query, "exists");
|
|
2480
2709
|
}
|
|
2481
2710
|
async read(kysely, model, args) {
|
|
2482
|
-
let query =
|
|
2711
|
+
let query = this.dialect.buildSelectModel(expressionBuilder2(), model);
|
|
2483
2712
|
if (args?.where) {
|
|
2484
2713
|
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, args?.where));
|
|
2485
2714
|
}
|
|
@@ -2499,15 +2728,16 @@ var BaseOperationHandler = class {
|
|
|
2499
2728
|
query = query.distinctOn(distinct.map((f) => sql4.ref(`${model}.${f}`)));
|
|
2500
2729
|
} else {
|
|
2501
2730
|
inMemoryDistinct = distinct;
|
|
2731
|
+
query = distinct.reduce((acc, field) => acc.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(`$distinct$${field}`)), query);
|
|
2502
2732
|
}
|
|
2503
2733
|
}
|
|
2504
|
-
if (args
|
|
2505
|
-
query = this.buildFieldSelection(model, query, args
|
|
2734
|
+
if (args && "select" in args && args.select) {
|
|
2735
|
+
query = this.buildFieldSelection(model, query, args.select, model);
|
|
2506
2736
|
} else {
|
|
2507
|
-
query = this.
|
|
2737
|
+
query = this.dialect.buildSelectAllFields(model, query, args?.omit);
|
|
2508
2738
|
}
|
|
2509
|
-
if (args
|
|
2510
|
-
query = this.buildFieldSelection(model, query, args
|
|
2739
|
+
if (args && "include" in args && args.include) {
|
|
2740
|
+
query = this.buildFieldSelection(model, query, args.include, model);
|
|
2511
2741
|
}
|
|
2512
2742
|
if (args?.cursor) {
|
|
2513
2743
|
query = this.buildCursorFilter(model, query, args.cursor, args.orderBy, negateOrderBy);
|
|
@@ -2517,23 +2747,35 @@ var BaseOperationHandler = class {
|
|
|
2517
2747
|
operation: "read"
|
|
2518
2748
|
}));
|
|
2519
2749
|
let result = [];
|
|
2750
|
+
const queryId = {
|
|
2751
|
+
queryId: `zenstack-${createId()}`
|
|
2752
|
+
};
|
|
2753
|
+
const compiled = kysely.getExecutor().compileQuery(query.toOperationNode(), queryId);
|
|
2520
2754
|
try {
|
|
2521
|
-
|
|
2755
|
+
const r = await kysely.getExecutor().executeQuery(compiled, queryId);
|
|
2756
|
+
result = r.rows;
|
|
2522
2757
|
} catch (err) {
|
|
2523
|
-
|
|
2524
|
-
|
|
2758
|
+
let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
|
|
2759
|
+
if (this.options.debug) {
|
|
2760
|
+
message += `, parameters:
|
|
2761
|
+
${compiled.parameters.map((p) => inspect(p)).join("\n")}`;
|
|
2762
|
+
}
|
|
2763
|
+
throw new QueryError(message, err);
|
|
2525
2764
|
}
|
|
2526
2765
|
if (inMemoryDistinct) {
|
|
2527
2766
|
const distinctResult = [];
|
|
2528
2767
|
const seen = /* @__PURE__ */ new Set();
|
|
2529
2768
|
for (const r of result) {
|
|
2530
|
-
const key = safeJSONStringify(inMemoryDistinct.map((f) => r[f]));
|
|
2769
|
+
const key = safeJSONStringify(inMemoryDistinct.map((f) => r[`$distinct$${f}`]));
|
|
2531
2770
|
if (!seen.has(key)) {
|
|
2532
2771
|
distinctResult.push(r);
|
|
2533
2772
|
seen.add(key);
|
|
2534
2773
|
}
|
|
2535
2774
|
}
|
|
2536
2775
|
result = distinctResult;
|
|
2776
|
+
for (const r of result) {
|
|
2777
|
+
Object.keys(r).filter((k) => k.startsWith("$distinct$")).forEach((k) => delete r[k]);
|
|
2778
|
+
}
|
|
2537
2779
|
}
|
|
2538
2780
|
return result;
|
|
2539
2781
|
}
|
|
@@ -2556,65 +2798,22 @@ var BaseOperationHandler = class {
|
|
|
2556
2798
|
}
|
|
2557
2799
|
const fieldDef = this.requireField(model, field);
|
|
2558
2800
|
if (!fieldDef.relation) {
|
|
2559
|
-
result = this.
|
|
2801
|
+
result = this.dialect.buildSelectField(result, model, parentAlias, field);
|
|
2560
2802
|
} else {
|
|
2561
2803
|
if (!fieldDef.array && !fieldDef.optional && payload.where) {
|
|
2562
2804
|
throw new QueryError(`Field "${field}" doesn't support filtering`);
|
|
2563
2805
|
}
|
|
2564
|
-
|
|
2806
|
+
if (fieldDef.originModel) {
|
|
2807
|
+
result = this.dialect.buildRelationSelection(result, fieldDef.originModel, field, fieldDef.originModel, payload);
|
|
2808
|
+
} else {
|
|
2809
|
+
result = this.dialect.buildRelationSelection(result, model, field, parentAlias, payload);
|
|
2810
|
+
}
|
|
2565
2811
|
}
|
|
2566
2812
|
}
|
|
2567
2813
|
return result;
|
|
2568
2814
|
}
|
|
2569
2815
|
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
|
-
}
|
|
2816
|
+
return query.select((eb) => this.dialect.buildCountJson(model, eb, parentAlias, payload).as("_count"));
|
|
2618
2817
|
}
|
|
2619
2818
|
buildCursorFilter(model, query, cursor, orderBy, negateOrderBy) {
|
|
2620
2819
|
if (!orderBy) {
|
|
@@ -2638,9 +2837,12 @@ var BaseOperationHandler = class {
|
|
|
2638
2837
|
result = result.where((eb2) => eb2.or(filters));
|
|
2639
2838
|
return result;
|
|
2640
2839
|
}
|
|
2641
|
-
async create(kysely, model, data, fromRelation) {
|
|
2840
|
+
async create(kysely, model, data, fromRelation, creatingForDelegate = false) {
|
|
2642
2841
|
const modelDef = this.requireModel(model);
|
|
2643
|
-
|
|
2842
|
+
if (modelDef.isDelegate && !creatingForDelegate) {
|
|
2843
|
+
throw new QueryError(`Model "${this.model}" is a delegate and cannot be created directly.`);
|
|
2844
|
+
}
|
|
2845
|
+
let createFields = {};
|
|
2644
2846
|
let parentUpdateTask = void 0;
|
|
2645
2847
|
let m2m = void 0;
|
|
2646
2848
|
if (fromRelation) {
|
|
@@ -2659,7 +2861,7 @@ var BaseOperationHandler = class {
|
|
|
2659
2861
|
model: fromRelation.model,
|
|
2660
2862
|
operation: "update"
|
|
2661
2863
|
}));
|
|
2662
|
-
return
|
|
2864
|
+
return this.executeQuery(kysely, query2, "update");
|
|
2663
2865
|
}, "parentUpdateTask");
|
|
2664
2866
|
}
|
|
2665
2867
|
}
|
|
@@ -2669,14 +2871,14 @@ var BaseOperationHandler = class {
|
|
|
2669
2871
|
const fieldDef = this.requireField(model, field);
|
|
2670
2872
|
if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
|
|
2671
2873
|
if (fieldDef.array && value && typeof value === "object" && "set" in value && Array.isArray(value.set)) {
|
|
2672
|
-
createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type);
|
|
2874
|
+
createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type, true);
|
|
2673
2875
|
} else {
|
|
2674
|
-
createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type);
|
|
2876
|
+
createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
2675
2877
|
}
|
|
2676
2878
|
} else {
|
|
2677
2879
|
const subM2M = getManyToManyRelation(this.schema, model, field);
|
|
2678
2880
|
if (!subM2M && fieldDef.relation?.fields && fieldDef.relation?.references) {
|
|
2679
|
-
const fkValues = await this.
|
|
2881
|
+
const fkValues = await this.processOwnedRelationForCreate(kysely, fieldDef, value);
|
|
2680
2882
|
for (let i = 0; i < fieldDef.relation.fields.length; i++) {
|
|
2681
2883
|
createFields[fieldDef.relation.fields[i]] = fkValues[fieldDef.relation.references[i]];
|
|
2682
2884
|
}
|
|
@@ -2688,16 +2890,20 @@ var BaseOperationHandler = class {
|
|
|
2688
2890
|
}
|
|
2689
2891
|
}
|
|
2690
2892
|
}
|
|
2893
|
+
if (modelDef.baseModel) {
|
|
2894
|
+
const baseCreateResult = await this.processBaseModelCreate(kysely, modelDef.baseModel, createFields, model);
|
|
2895
|
+
createFields = baseCreateResult.remainingFields;
|
|
2896
|
+
}
|
|
2691
2897
|
const updatedData = this.fillGeneratedValues(modelDef, createFields);
|
|
2692
2898
|
const idFields = getIdFields(this.schema, model);
|
|
2693
|
-
const query = kysely.insertInto(model).values(updatedData).returning(idFields).modifyEnd(this.makeContextComment({
|
|
2899
|
+
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
2900
|
model,
|
|
2695
2901
|
operation: "create"
|
|
2696
2902
|
}));
|
|
2697
|
-
const createdEntity = await
|
|
2903
|
+
const createdEntity = await this.executeQueryTakeFirst(kysely, query, "create");
|
|
2698
2904
|
if (Object.keys(postCreateRelations).length > 0) {
|
|
2699
2905
|
const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
|
|
2700
|
-
return this.
|
|
2906
|
+
return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
|
|
2701
2907
|
});
|
|
2702
2908
|
await Promise.all(relationPromises);
|
|
2703
2909
|
}
|
|
@@ -2709,6 +2915,28 @@ var BaseOperationHandler = class {
|
|
|
2709
2915
|
}
|
|
2710
2916
|
return createdEntity;
|
|
2711
2917
|
}
|
|
2918
|
+
async processBaseModelCreate(kysely, model, createFields, forModel) {
|
|
2919
|
+
const thisCreateFields = {};
|
|
2920
|
+
const remainingFields = {};
|
|
2921
|
+
Object.entries(createFields).forEach(([field, value]) => {
|
|
2922
|
+
const fieldDef = this.getField(model, field);
|
|
2923
|
+
if (fieldDef) {
|
|
2924
|
+
thisCreateFields[field] = value;
|
|
2925
|
+
} else {
|
|
2926
|
+
remainingFields[field] = value;
|
|
2927
|
+
}
|
|
2928
|
+
});
|
|
2929
|
+
const discriminatorField = getDiscriminatorField(this.schema, model);
|
|
2930
|
+
invariant7(discriminatorField, `Base model "${model}" must have a discriminator field`);
|
|
2931
|
+
thisCreateFields[discriminatorField] = forModel;
|
|
2932
|
+
const baseEntity = await this.create(kysely, model, thisCreateFields, void 0, true);
|
|
2933
|
+
const idValues = extractIdFields(baseEntity, this.schema, model);
|
|
2934
|
+
Object.assign(remainingFields, idValues);
|
|
2935
|
+
return {
|
|
2936
|
+
baseEntity,
|
|
2937
|
+
remainingFields
|
|
2938
|
+
};
|
|
2939
|
+
}
|
|
2712
2940
|
buildFkAssignments(model, relationField, entity) {
|
|
2713
2941
|
const parentFkFields = {};
|
|
2714
2942
|
invariant7(relationField, "parentField must be defined if parentModel is defined");
|
|
@@ -2764,7 +2992,7 @@ var BaseOperationHandler = class {
|
|
|
2764
2992
|
const eb = expressionBuilder2();
|
|
2765
2993
|
return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
|
|
2766
2994
|
}
|
|
2767
|
-
async
|
|
2995
|
+
async processOwnedRelationForCreate(kysely, relationField, payload) {
|
|
2768
2996
|
if (!payload) {
|
|
2769
2997
|
return;
|
|
2770
2998
|
}
|
|
@@ -2814,21 +3042,27 @@ var BaseOperationHandler = class {
|
|
|
2814
3042
|
}
|
|
2815
3043
|
return result;
|
|
2816
3044
|
}
|
|
2817
|
-
|
|
3045
|
+
processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
|
|
2818
3046
|
const relationFieldDef = this.requireField(contextModel, relationFieldName);
|
|
2819
3047
|
const relationModel = relationFieldDef.type;
|
|
2820
3048
|
const tasks = [];
|
|
3049
|
+
const fromRelationContext = {
|
|
3050
|
+
model: contextModel,
|
|
3051
|
+
field: relationFieldName,
|
|
3052
|
+
ids: parentEntity
|
|
3053
|
+
};
|
|
2821
3054
|
for (const [action, subPayload] of Object.entries(payload)) {
|
|
2822
3055
|
if (!subPayload) {
|
|
2823
3056
|
continue;
|
|
2824
3057
|
}
|
|
2825
3058
|
switch (action) {
|
|
2826
3059
|
case "create": {
|
|
2827
|
-
tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item,
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
3060
|
+
tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, fromRelationContext)));
|
|
3061
|
+
break;
|
|
3062
|
+
}
|
|
3063
|
+
case "createMany": {
|
|
3064
|
+
invariant7(relationFieldDef.array, "relation must be an array for createMany");
|
|
3065
|
+
tasks.push(this.createMany(kysely, relationModel, subPayload, false, fromRelationContext));
|
|
2832
3066
|
break;
|
|
2833
3067
|
}
|
|
2834
3068
|
case "connect": {
|
|
@@ -2858,6 +3092,11 @@ var BaseOperationHandler = class {
|
|
|
2858
3092
|
return Promise.all(tasks);
|
|
2859
3093
|
}
|
|
2860
3094
|
async createMany(kysely, model, input, returnData, fromRelation) {
|
|
3095
|
+
if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
|
|
3096
|
+
return returnData ? [] : {
|
|
3097
|
+
count: 0
|
|
3098
|
+
};
|
|
3099
|
+
}
|
|
2861
3100
|
const modelDef = this.requireModel(model);
|
|
2862
3101
|
let relationKeyPairs = [];
|
|
2863
3102
|
if (fromRelation) {
|
|
@@ -2867,12 +3106,12 @@ var BaseOperationHandler = class {
|
|
|
2867
3106
|
}
|
|
2868
3107
|
relationKeyPairs = keyPairs;
|
|
2869
3108
|
}
|
|
2870
|
-
|
|
3109
|
+
let createData = enumerate(input.data).map((item) => {
|
|
2871
3110
|
const newItem = {};
|
|
2872
3111
|
for (const [name, value] of Object.entries(item)) {
|
|
2873
3112
|
const fieldDef = this.requireField(model, name);
|
|
2874
3113
|
invariant7(!fieldDef.relation, "createMany does not support relations");
|
|
2875
|
-
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type);
|
|
3114
|
+
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
2876
3115
|
}
|
|
2877
3116
|
if (fromRelation) {
|
|
2878
3117
|
for (const { fk, pk } of relationKeyPairs) {
|
|
@@ -2881,14 +3120,44 @@ var BaseOperationHandler = class {
|
|
|
2881
3120
|
}
|
|
2882
3121
|
return this.fillGeneratedValues(modelDef, newItem);
|
|
2883
3122
|
});
|
|
3123
|
+
if (!this.dialect.supportInsertWithDefault) {
|
|
3124
|
+
const allPassedFields = createData.reduce((acc, item) => {
|
|
3125
|
+
Object.keys(item).forEach((field) => {
|
|
3126
|
+
if (!acc.includes(field)) {
|
|
3127
|
+
acc.push(field);
|
|
3128
|
+
}
|
|
3129
|
+
});
|
|
3130
|
+
return acc;
|
|
3131
|
+
}, []);
|
|
3132
|
+
for (const item of createData) {
|
|
3133
|
+
if (Object.keys(item).length === allPassedFields.length) {
|
|
3134
|
+
continue;
|
|
3135
|
+
}
|
|
3136
|
+
for (const field of allPassedFields) {
|
|
3137
|
+
if (!(field in item)) {
|
|
3138
|
+
const fieldDef = this.requireField(model, field);
|
|
3139
|
+
if (fieldDef.default !== void 0 && fieldDef.default !== null && typeof fieldDef.default !== "object") {
|
|
3140
|
+
item[field] = this.dialect.transformPrimitive(fieldDef.default, fieldDef.type, !!fieldDef.array);
|
|
3141
|
+
}
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
if (modelDef.baseModel) {
|
|
3147
|
+
if (input.skipDuplicates) {
|
|
3148
|
+
throw new QueryError('"skipDuplicates" options is not supported for polymorphic models');
|
|
3149
|
+
}
|
|
3150
|
+
const baseCreateResult = await this.processBaseModelCreateMany(kysely, modelDef.baseModel, createData, !!input.skipDuplicates, model);
|
|
3151
|
+
createData = baseCreateResult.remainingFieldRows;
|
|
3152
|
+
}
|
|
2884
3153
|
const query = kysely.insertInto(model).values(createData).$if(!!input.skipDuplicates, (qb) => qb.onConflict((oc) => oc.doNothing())).modifyEnd(this.makeContextComment({
|
|
2885
3154
|
model,
|
|
2886
3155
|
operation: "create"
|
|
2887
3156
|
}));
|
|
2888
3157
|
if (!returnData) {
|
|
2889
|
-
const result = await
|
|
3158
|
+
const result = await this.executeQuery(kysely, query, "createMany");
|
|
2890
3159
|
return {
|
|
2891
|
-
count: Number(result.
|
|
3160
|
+
count: Number(result.numAffectedRows)
|
|
2892
3161
|
};
|
|
2893
3162
|
} else {
|
|
2894
3163
|
const idFields = getIdFields(this.schema, model);
|
|
@@ -2896,10 +3165,46 @@ var BaseOperationHandler = class {
|
|
|
2896
3165
|
return result;
|
|
2897
3166
|
}
|
|
2898
3167
|
}
|
|
3168
|
+
async processBaseModelCreateMany(kysely, model, createRows, skipDuplicates, forModel) {
|
|
3169
|
+
const thisCreateRows = [];
|
|
3170
|
+
const remainingFieldRows = [];
|
|
3171
|
+
const discriminatorField = getDiscriminatorField(this.schema, model);
|
|
3172
|
+
invariant7(discriminatorField, `Base model "${model}" must have a discriminator field`);
|
|
3173
|
+
for (const createFields of createRows) {
|
|
3174
|
+
const thisCreateFields = {};
|
|
3175
|
+
const remainingFields = {};
|
|
3176
|
+
Object.entries(createFields).forEach(([field, value]) => {
|
|
3177
|
+
const fieldDef = this.getField(model, field);
|
|
3178
|
+
if (fieldDef) {
|
|
3179
|
+
thisCreateFields[field] = value;
|
|
3180
|
+
} else {
|
|
3181
|
+
remainingFields[field] = value;
|
|
3182
|
+
}
|
|
3183
|
+
});
|
|
3184
|
+
thisCreateFields[discriminatorField] = forModel;
|
|
3185
|
+
thisCreateRows.push(thisCreateFields);
|
|
3186
|
+
remainingFieldRows.push(remainingFields);
|
|
3187
|
+
}
|
|
3188
|
+
const baseEntities = await this.createMany(kysely, model, {
|
|
3189
|
+
data: thisCreateRows,
|
|
3190
|
+
skipDuplicates
|
|
3191
|
+
}, true);
|
|
3192
|
+
for (let i = 0; i < baseEntities.length; i++) {
|
|
3193
|
+
const idValues = extractIdFields(baseEntities[i], this.schema, model);
|
|
3194
|
+
Object.assign(remainingFieldRows[i], idValues);
|
|
3195
|
+
}
|
|
3196
|
+
return {
|
|
3197
|
+
baseEntities,
|
|
3198
|
+
remainingFieldRows
|
|
3199
|
+
};
|
|
3200
|
+
}
|
|
2899
3201
|
fillGeneratedValues(modelDef, data) {
|
|
2900
3202
|
const fields = modelDef.fields;
|
|
2901
3203
|
const values = clone(data);
|
|
2902
|
-
for (const field
|
|
3204
|
+
for (const [field, fieldDef] of Object.entries(fields)) {
|
|
3205
|
+
if (fieldDef.originModel) {
|
|
3206
|
+
continue;
|
|
3207
|
+
}
|
|
2903
3208
|
if (!(field in data)) {
|
|
2904
3209
|
if (typeof fields[field]?.default === "object" && "kind" in fields[field].default) {
|
|
2905
3210
|
const generated = this.evalGenerator(fields[field].default);
|
|
@@ -2907,7 +3212,7 @@ var BaseOperationHandler = class {
|
|
|
2907
3212
|
values[field] = generated;
|
|
2908
3213
|
}
|
|
2909
3214
|
} else if (fields[field]?.updatedAt) {
|
|
2910
|
-
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
|
|
3215
|
+
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
2911
3216
|
}
|
|
2912
3217
|
}
|
|
2913
3218
|
}
|
|
@@ -2915,7 +3220,7 @@ var BaseOperationHandler = class {
|
|
|
2915
3220
|
}
|
|
2916
3221
|
evalGenerator(defaultValue) {
|
|
2917
3222
|
if (ExpressionUtils.isCall(defaultValue)) {
|
|
2918
|
-
return
|
|
3223
|
+
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
3224
|
} else if (ExpressionUtils.isMember(defaultValue) && ExpressionUtils.isCall(defaultValue.receiver) && defaultValue.receiver.function === "auth") {
|
|
2920
3225
|
let val = this.client.$auth;
|
|
2921
3226
|
for (const member of defaultValue.members) {
|
|
@@ -2972,32 +3277,37 @@ var BaseOperationHandler = class {
|
|
|
2972
3277
|
if (finalData === data) {
|
|
2973
3278
|
finalData = clone(data);
|
|
2974
3279
|
}
|
|
2975
|
-
finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
|
|
3280
|
+
finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
2976
3281
|
}
|
|
2977
3282
|
}
|
|
2978
3283
|
if (Object.keys(finalData).length === 0) {
|
|
2979
|
-
|
|
2980
|
-
|
|
3284
|
+
return combinedWhere;
|
|
3285
|
+
}
|
|
3286
|
+
let needIdRead = false;
|
|
3287
|
+
if (modelDef.baseModel && !this.isIdFilter(model, combinedWhere)) {
|
|
3288
|
+
needIdRead = true;
|
|
3289
|
+
}
|
|
3290
|
+
if (needIdRead) {
|
|
3291
|
+
const readResult = await this.readUnique(kysely, model, {
|
|
3292
|
+
where: combinedWhere,
|
|
3293
|
+
select: this.makeIdSelect(model)
|
|
2981
3294
|
});
|
|
2982
|
-
if (!
|
|
3295
|
+
if (!readResult && throwIfNotFound) {
|
|
2983
3296
|
throw new NotFoundError(model);
|
|
2984
3297
|
}
|
|
2985
|
-
|
|
3298
|
+
combinedWhere = readResult;
|
|
3299
|
+
}
|
|
3300
|
+
if (modelDef.baseModel) {
|
|
3301
|
+
const baseUpdateResult = await this.processBaseModelUpdate(kysely, modelDef.baseModel, combinedWhere, finalData, throwIfNotFound);
|
|
3302
|
+
finalData = baseUpdateResult.remainingFields;
|
|
3303
|
+
combinedWhere = baseUpdateResult.baseEntity;
|
|
2986
3304
|
}
|
|
2987
3305
|
const updateFields = {};
|
|
2988
3306
|
let thisEntity = void 0;
|
|
2989
3307
|
for (const field in finalData) {
|
|
2990
3308
|
const fieldDef = this.requireField(model, field);
|
|
2991
3309
|
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);
|
|
3310
|
+
updateFields[field] = this.processScalarFieldUpdateData(model, field, finalData);
|
|
3001
3311
|
} else {
|
|
3002
3312
|
if (!allowRelationUpdate) {
|
|
3003
3313
|
throw new QueryError(`Relation update not allowed for field "${field}"`);
|
|
@@ -3019,16 +3329,14 @@ var BaseOperationHandler = class {
|
|
|
3019
3329
|
}
|
|
3020
3330
|
}
|
|
3021
3331
|
if (Object.keys(updateFields).length === 0) {
|
|
3022
|
-
return
|
|
3023
|
-
where: combinedWhere
|
|
3024
|
-
});
|
|
3332
|
+
return combinedWhere;
|
|
3025
3333
|
} else {
|
|
3026
3334
|
const idFields = getIdFields(this.schema, model);
|
|
3027
3335
|
const query = kysely.updateTable(model).where((eb) => this.dialect.buildFilter(eb, model, model, combinedWhere)).set(updateFields).returning(idFields).modifyEnd(this.makeContextComment({
|
|
3028
3336
|
model,
|
|
3029
3337
|
operation: "update"
|
|
3030
3338
|
}));
|
|
3031
|
-
const updatedEntity = await
|
|
3339
|
+
const updatedEntity = await this.executeQueryTakeFirst(kysely, query, "update");
|
|
3032
3340
|
if (!updatedEntity) {
|
|
3033
3341
|
if (throwIfNotFound) {
|
|
3034
3342
|
throw new NotFoundError(model);
|
|
@@ -3039,23 +3347,72 @@ var BaseOperationHandler = class {
|
|
|
3039
3347
|
return updatedEntity;
|
|
3040
3348
|
}
|
|
3041
3349
|
}
|
|
3350
|
+
processScalarFieldUpdateData(model, field, data) {
|
|
3351
|
+
const fieldDef = this.requireField(model, field);
|
|
3352
|
+
if (this.isNumericIncrementalUpdate(fieldDef, data[field])) {
|
|
3353
|
+
return this.transformIncrementalUpdate(model, field, fieldDef, data[field]);
|
|
3354
|
+
}
|
|
3355
|
+
if (fieldDef.array && typeof data[field] === "object" && !Array.isArray(data[field]) && data[field]) {
|
|
3356
|
+
return this.transformScalarListUpdate(model, field, fieldDef, data[field]);
|
|
3357
|
+
}
|
|
3358
|
+
return this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
|
|
3359
|
+
}
|
|
3360
|
+
isNumericIncrementalUpdate(fieldDef, value) {
|
|
3361
|
+
if (!this.isNumericField(fieldDef)) {
|
|
3362
|
+
return false;
|
|
3363
|
+
}
|
|
3364
|
+
if (typeof value !== "object" || !value) {
|
|
3365
|
+
return false;
|
|
3366
|
+
}
|
|
3367
|
+
return [
|
|
3368
|
+
"increment",
|
|
3369
|
+
"decrement",
|
|
3370
|
+
"multiply",
|
|
3371
|
+
"divide",
|
|
3372
|
+
"set"
|
|
3373
|
+
].some((key) => key in value);
|
|
3374
|
+
}
|
|
3375
|
+
isIdFilter(model, filter) {
|
|
3376
|
+
if (!filter || typeof filter !== "object") {
|
|
3377
|
+
return false;
|
|
3378
|
+
}
|
|
3379
|
+
const idFields = getIdFields(this.schema, model);
|
|
3380
|
+
return idFields.length === Object.keys(filter).length && idFields.every((field) => field in filter);
|
|
3381
|
+
}
|
|
3382
|
+
async processBaseModelUpdate(kysely, model, where, updateFields, throwIfNotFound) {
|
|
3383
|
+
const thisUpdateFields = {};
|
|
3384
|
+
const remainingFields = {};
|
|
3385
|
+
Object.entries(updateFields).forEach(([field, value]) => {
|
|
3386
|
+
const fieldDef = this.getField(model, field);
|
|
3387
|
+
if (fieldDef) {
|
|
3388
|
+
thisUpdateFields[field] = value;
|
|
3389
|
+
} else {
|
|
3390
|
+
remainingFields[field] = value;
|
|
3391
|
+
}
|
|
3392
|
+
});
|
|
3393
|
+
const baseEntity = await this.update(kysely, model, where, thisUpdateFields, void 0, void 0, throwIfNotFound);
|
|
3394
|
+
return {
|
|
3395
|
+
baseEntity,
|
|
3396
|
+
remainingFields
|
|
3397
|
+
};
|
|
3398
|
+
}
|
|
3042
3399
|
transformIncrementalUpdate(model, field, fieldDef, payload) {
|
|
3043
3400
|
invariant7(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
|
|
3044
3401
|
const key = Object.keys(payload)[0];
|
|
3045
|
-
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
|
|
3402
|
+
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
|
|
3046
3403
|
const eb = expressionBuilder2();
|
|
3047
3404
|
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
|
|
3048
|
-
return
|
|
3405
|
+
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
3406
|
throw new InternalError(`Invalid incremental update operation: ${key}`);
|
|
3050
3407
|
});
|
|
3051
3408
|
}
|
|
3052
3409
|
transformScalarListUpdate(model, field, fieldDef, payload) {
|
|
3053
3410
|
invariant7(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
|
|
3054
3411
|
const key = Object.keys(payload)[0];
|
|
3055
|
-
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
|
|
3412
|
+
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
|
|
3056
3413
|
const eb = expressionBuilder2();
|
|
3057
3414
|
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
|
|
3058
|
-
return
|
|
3415
|
+
return match9(key).with("set", () => value).with("push", () => {
|
|
3059
3416
|
return eb(fieldRef, "||", eb.val(ensureArray(value)));
|
|
3060
3417
|
}).otherwise(() => {
|
|
3061
3418
|
throw new InternalError(`Invalid array update operation: ${key}`);
|
|
@@ -3067,7 +3424,7 @@ var BaseOperationHandler = class {
|
|
|
3067
3424
|
makeContextComment(context) {
|
|
3068
3425
|
return sql4.raw(`${CONTEXT_COMMENT_PREFIX}${JSON.stringify(context)}`);
|
|
3069
3426
|
}
|
|
3070
|
-
async updateMany(kysely, model, where, data, limit, returnData) {
|
|
3427
|
+
async updateMany(kysely, model, where, data, limit, returnData, filterModel) {
|
|
3071
3428
|
if (typeof data !== "object") {
|
|
3072
3429
|
throw new InternalError("data must be an object");
|
|
3073
3430
|
}
|
|
@@ -3076,49 +3433,79 @@ var BaseOperationHandler = class {
|
|
|
3076
3433
|
count: 0
|
|
3077
3434
|
};
|
|
3078
3435
|
}
|
|
3079
|
-
const
|
|
3436
|
+
const modelDef = this.requireModel(model);
|
|
3437
|
+
if (modelDef.baseModel && limit !== void 0) {
|
|
3438
|
+
throw new QueryError("Updating with a limit is not supported for polymorphic models");
|
|
3439
|
+
}
|
|
3440
|
+
filterModel ??= model;
|
|
3441
|
+
let updateFields = {};
|
|
3080
3442
|
for (const field in data) {
|
|
3081
|
-
const fieldDef = this.requireField(model, field);
|
|
3082
3443
|
if (isRelationField(this.schema, model, field)) {
|
|
3083
3444
|
continue;
|
|
3084
3445
|
}
|
|
3085
|
-
updateFields[field] = this.
|
|
3446
|
+
updateFields[field] = this.processScalarFieldUpdateData(model, field, data);
|
|
3447
|
+
}
|
|
3448
|
+
let shouldFallbackToIdFilter = false;
|
|
3449
|
+
if (limit !== void 0 && !this.dialect.supportsUpdateWithLimit) {
|
|
3450
|
+
shouldFallbackToIdFilter = true;
|
|
3451
|
+
}
|
|
3452
|
+
if (modelDef.isDelegate || modelDef.baseModel) {
|
|
3453
|
+
shouldFallbackToIdFilter = true;
|
|
3454
|
+
}
|
|
3455
|
+
let resultFromBaseModel = void 0;
|
|
3456
|
+
if (modelDef.baseModel) {
|
|
3457
|
+
const baseResult = await this.processBaseModelUpdateMany(kysely, modelDef.baseModel, where, updateFields, filterModel);
|
|
3458
|
+
updateFields = baseResult.remainingFields;
|
|
3459
|
+
resultFromBaseModel = baseResult.baseResult;
|
|
3460
|
+
}
|
|
3461
|
+
if (Object.keys(updateFields).length === 0) {
|
|
3462
|
+
return resultFromBaseModel ?? (returnData ? [] : {
|
|
3463
|
+
count: 0
|
|
3464
|
+
});
|
|
3086
3465
|
}
|
|
3087
3466
|
let query = kysely.updateTable(model).set(updateFields);
|
|
3088
|
-
if (
|
|
3089
|
-
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
|
|
3467
|
+
if (!shouldFallbackToIdFilter) {
|
|
3468
|
+
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where)).$if(limit !== void 0, (qb) => qb.limit(limit));
|
|
3090
3469
|
} 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
|
-
}
|
|
3470
|
+
query = query.where((eb) => eb(eb.refTuple(
|
|
3471
|
+
...this.buildIdFieldRefs(kysely, model)
|
|
3472
|
+
), "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
3473
|
}
|
|
3099
3474
|
query = query.modifyEnd(this.makeContextComment({
|
|
3100
3475
|
model,
|
|
3101
3476
|
operation: "update"
|
|
3102
3477
|
}));
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3478
|
+
if (!returnData) {
|
|
3479
|
+
const result = await this.executeQuery(kysely, query, "update");
|
|
3480
|
+
return {
|
|
3481
|
+
count: Number(result.numAffectedRows)
|
|
3482
|
+
};
|
|
3483
|
+
} else {
|
|
3484
|
+
const idFields = getIdFields(this.schema, model);
|
|
3485
|
+
const result = await query.returning(idFields).execute();
|
|
3486
|
+
return result;
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
async processBaseModelUpdateMany(kysely, model, where, updateFields, filterModel) {
|
|
3490
|
+
const thisUpdateFields = {};
|
|
3491
|
+
const remainingFields = {};
|
|
3492
|
+
Object.entries(updateFields).forEach(([field, value]) => {
|
|
3493
|
+
const fieldDef = this.getField(model, field);
|
|
3494
|
+
if (fieldDef) {
|
|
3495
|
+
thisUpdateFields[field] = value;
|
|
3109
3496
|
} else {
|
|
3110
|
-
|
|
3111
|
-
const result = await query.returning(idFields).execute();
|
|
3112
|
-
return result;
|
|
3497
|
+
remainingFields[field] = value;
|
|
3113
3498
|
}
|
|
3114
|
-
}
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3499
|
+
});
|
|
3500
|
+
const baseResult = await this.updateMany(kysely, model, where, thisUpdateFields, void 0, false, filterModel);
|
|
3501
|
+
return {
|
|
3502
|
+
baseResult,
|
|
3503
|
+
remainingFields
|
|
3504
|
+
};
|
|
3118
3505
|
}
|
|
3119
3506
|
buildIdFieldRefs(kysely, model) {
|
|
3120
3507
|
const idFields = getIdFields(this.schema, model);
|
|
3121
|
-
return idFields.map((f) => kysely.dynamic.ref(f));
|
|
3508
|
+
return idFields.map((f) => kysely.dynamic.ref(`${model}.${f}`));
|
|
3122
3509
|
}
|
|
3123
3510
|
async processRelationUpdates(kysely, model, field, fieldDef, parentIds, args, throwIfNotFound) {
|
|
3124
3511
|
const tasks = [];
|
|
@@ -3236,7 +3623,7 @@ var BaseOperationHandler = class {
|
|
|
3236
3623
|
model: fromRelation.model,
|
|
3237
3624
|
operation: "update"
|
|
3238
3625
|
}));
|
|
3239
|
-
updateResult = await
|
|
3626
|
+
updateResult = await this.executeQuery(kysely, query, "connect");
|
|
3240
3627
|
} else {
|
|
3241
3628
|
const relationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3242
3629
|
if (!relationFieldDef.array) {
|
|
@@ -3247,7 +3634,7 @@ var BaseOperationHandler = class {
|
|
|
3247
3634
|
model: fromRelation.model,
|
|
3248
3635
|
operation: "update"
|
|
3249
3636
|
}));
|
|
3250
|
-
await
|
|
3637
|
+
await this.executeQuery(kysely, query2, "disconnect");
|
|
3251
3638
|
}
|
|
3252
3639
|
const query = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
|
|
3253
3640
|
...acc,
|
|
@@ -3256,9 +3643,9 @@ var BaseOperationHandler = class {
|
|
|
3256
3643
|
model,
|
|
3257
3644
|
operation: "update"
|
|
3258
3645
|
}));
|
|
3259
|
-
updateResult = await
|
|
3646
|
+
updateResult = await this.executeQuery(kysely, query, "connect");
|
|
3260
3647
|
}
|
|
3261
|
-
if (_data.length > updateResult.
|
|
3648
|
+
if (_data.length > updateResult.numAffectedRows) {
|
|
3262
3649
|
throw new NotFoundError(model);
|
|
3263
3650
|
}
|
|
3264
3651
|
}
|
|
@@ -3326,7 +3713,7 @@ var BaseOperationHandler = class {
|
|
|
3326
3713
|
model: fromRelation.model,
|
|
3327
3714
|
operation: "update"
|
|
3328
3715
|
}));
|
|
3329
|
-
await
|
|
3716
|
+
await this.executeQuery(kysely, query, "disconnect");
|
|
3330
3717
|
} else {
|
|
3331
3718
|
const query = kysely.updateTable(model).where(eb.and([
|
|
3332
3719
|
// fk filter
|
|
@@ -3343,7 +3730,7 @@ var BaseOperationHandler = class {
|
|
|
3343
3730
|
model,
|
|
3344
3731
|
operation: "update"
|
|
3345
3732
|
}));
|
|
3346
|
-
await
|
|
3733
|
+
await this.executeQuery(kysely, query, "disconnect");
|
|
3347
3734
|
}
|
|
3348
3735
|
}
|
|
3349
3736
|
}
|
|
@@ -3381,7 +3768,7 @@ var BaseOperationHandler = class {
|
|
|
3381
3768
|
model,
|
|
3382
3769
|
operation: "update"
|
|
3383
3770
|
}));
|
|
3384
|
-
await
|
|
3771
|
+
await this.executeQuery(kysely, query, "disconnect");
|
|
3385
3772
|
if (_data.length > 0) {
|
|
3386
3773
|
const query2 = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
|
|
3387
3774
|
...acc,
|
|
@@ -3390,8 +3777,8 @@ var BaseOperationHandler = class {
|
|
|
3390
3777
|
model,
|
|
3391
3778
|
operation: "update"
|
|
3392
3779
|
}));
|
|
3393
|
-
const r = await
|
|
3394
|
-
if (_data.length > r.
|
|
3780
|
+
const r = await this.executeQuery(kysely, query2, "connect");
|
|
3781
|
+
if (_data.length > r.numAffectedRows) {
|
|
3395
3782
|
throw new NotFoundError(model);
|
|
3396
3783
|
}
|
|
3397
3784
|
}
|
|
@@ -3432,7 +3819,7 @@ var BaseOperationHandler = class {
|
|
|
3432
3819
|
OR: deleteConditions
|
|
3433
3820
|
}
|
|
3434
3821
|
]
|
|
3435
|
-
}
|
|
3822
|
+
});
|
|
3436
3823
|
} else {
|
|
3437
3824
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3438
3825
|
if (ownedByModel) {
|
|
@@ -3455,7 +3842,7 @@ var BaseOperationHandler = class {
|
|
|
3455
3842
|
OR: deleteConditions
|
|
3456
3843
|
}
|
|
3457
3844
|
]
|
|
3458
|
-
}
|
|
3845
|
+
});
|
|
3459
3846
|
} else {
|
|
3460
3847
|
deleteResult = await this.delete(kysely, model, {
|
|
3461
3848
|
AND: [
|
|
@@ -3467,7 +3854,7 @@ var BaseOperationHandler = class {
|
|
|
3467
3854
|
OR: deleteConditions
|
|
3468
3855
|
}
|
|
3469
3856
|
]
|
|
3470
|
-
}
|
|
3857
|
+
});
|
|
3471
3858
|
}
|
|
3472
3859
|
}
|
|
3473
3860
|
if (throwForNotFound && expectedDeleteCount > deleteResult.count) {
|
|
@@ -3478,33 +3865,59 @@ var BaseOperationHandler = class {
|
|
|
3478
3865
|
return enumerate(data).map((item) => flattenCompoundUniqueFilters(this.schema, model, item));
|
|
3479
3866
|
}
|
|
3480
3867
|
// #endregion
|
|
3481
|
-
async delete(kysely, model, where, limit,
|
|
3868
|
+
async delete(kysely, model, where, limit, filterModel) {
|
|
3869
|
+
filterModel ??= model;
|
|
3870
|
+
const modelDef = this.requireModel(model);
|
|
3871
|
+
if (modelDef.baseModel) {
|
|
3872
|
+
if (limit !== void 0) {
|
|
3873
|
+
throw new QueryError("Deleting with a limit is not supported for polymorphic models");
|
|
3874
|
+
}
|
|
3875
|
+
return this.processBaseModelDelete(kysely, modelDef.baseModel, where, limit, filterModel);
|
|
3876
|
+
}
|
|
3482
3877
|
let query = kysely.deleteFrom(model);
|
|
3483
|
-
|
|
3878
|
+
let needIdFilter = false;
|
|
3879
|
+
if (limit !== void 0 && !this.dialect.supportsDeleteWithLimit) {
|
|
3880
|
+
needIdFilter = true;
|
|
3881
|
+
}
|
|
3882
|
+
if (modelDef.isDelegate || modelDef.baseModel) {
|
|
3883
|
+
needIdFilter = true;
|
|
3884
|
+
}
|
|
3885
|
+
if (!needIdFilter) {
|
|
3484
3886
|
query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
|
|
3485
3887
|
} 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
|
-
}
|
|
3888
|
+
query = query.where((eb) => eb(eb.refTuple(
|
|
3889
|
+
...this.buildIdFieldRefs(kysely, model)
|
|
3890
|
+
), "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
3891
|
}
|
|
3892
|
+
await this.processDelegateRelationDelete(kysely, modelDef, where, limit);
|
|
3494
3893
|
query = query.modifyEnd(this.makeContextComment({
|
|
3495
3894
|
model,
|
|
3496
3895
|
operation: "delete"
|
|
3497
3896
|
}));
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
}
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3897
|
+
const result = await this.executeQuery(kysely, query, "delete");
|
|
3898
|
+
return {
|
|
3899
|
+
count: Number(result.numAffectedRows)
|
|
3900
|
+
};
|
|
3901
|
+
}
|
|
3902
|
+
async processDelegateRelationDelete(kysely, modelDef, where, limit) {
|
|
3903
|
+
for (const fieldDef of Object.values(modelDef.fields)) {
|
|
3904
|
+
if (fieldDef.relation && fieldDef.relation.opposite) {
|
|
3905
|
+
const oppositeModelDef = this.requireModel(fieldDef.type);
|
|
3906
|
+
const oppositeRelation = this.requireField(fieldDef.type, fieldDef.relation.opposite);
|
|
3907
|
+
if (oppositeModelDef.baseModel && oppositeRelation.relation?.onDelete === "Cascade") {
|
|
3908
|
+
if (limit !== void 0) {
|
|
3909
|
+
throw new QueryError("Deleting with a limit is not supported for polymorphic models");
|
|
3910
|
+
}
|
|
3911
|
+
await this.delete(kysely, fieldDef.type, {
|
|
3912
|
+
[fieldDef.relation.opposite]: where
|
|
3913
|
+
}, void 0);
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3506
3916
|
}
|
|
3507
3917
|
}
|
|
3918
|
+
async processBaseModelDelete(kysely, model, where, limit, filterModel) {
|
|
3919
|
+
return this.delete(kysely, model, where, limit, filterModel);
|
|
3920
|
+
}
|
|
3508
3921
|
makeIdSelect(model) {
|
|
3509
3922
|
const modelDef = this.requireModel(model);
|
|
3510
3923
|
return modelDef.idFields.reduce((acc, f) => {
|
|
@@ -3513,7 +3926,7 @@ var BaseOperationHandler = class {
|
|
|
3513
3926
|
}, {});
|
|
3514
3927
|
}
|
|
3515
3928
|
trimResult(data, args) {
|
|
3516
|
-
if (!args.select) {
|
|
3929
|
+
if (!("select" in args) || !args.select) {
|
|
3517
3930
|
return data;
|
|
3518
3931
|
}
|
|
3519
3932
|
return Object.keys(args.select).reduce((acc, field) => {
|
|
@@ -3523,9 +3936,9 @@ var BaseOperationHandler = class {
|
|
|
3523
3936
|
}
|
|
3524
3937
|
needReturnRelations(model, args) {
|
|
3525
3938
|
let returnRelation = false;
|
|
3526
|
-
if (args.include) {
|
|
3939
|
+
if ("include" in args && args.include) {
|
|
3527
3940
|
returnRelation = Object.keys(args.include).length > 0;
|
|
3528
|
-
} else if (args.select) {
|
|
3941
|
+
} else if ("select" in args && args.select) {
|
|
3529
3942
|
returnRelation = Object.entries(args.select).some(([K, v]) => {
|
|
3530
3943
|
const fieldDef = this.requireField(model, K);
|
|
3531
3944
|
return fieldDef.relation && v;
|
|
@@ -3533,11 +3946,13 @@ var BaseOperationHandler = class {
|
|
|
3533
3946
|
}
|
|
3534
3947
|
return returnRelation;
|
|
3535
3948
|
}
|
|
3536
|
-
async safeTransaction(callback) {
|
|
3949
|
+
async safeTransaction(callback, isolationLevel) {
|
|
3537
3950
|
if (this.kysely.isTransaction) {
|
|
3538
3951
|
return callback(this.kysely);
|
|
3539
3952
|
} else {
|
|
3540
|
-
|
|
3953
|
+
let txBuilder = this.kysely.transaction();
|
|
3954
|
+
txBuilder = txBuilder.setIsolationLevel(isolationLevel ?? "repeatable read");
|
|
3955
|
+
return txBuilder.execute(callback);
|
|
3541
3956
|
}
|
|
3542
3957
|
}
|
|
3543
3958
|
// Given a unique filter of a model, return the entity ids by trying to
|
|
@@ -3552,9 +3967,50 @@ var BaseOperationHandler = class {
|
|
|
3552
3967
|
) {
|
|
3553
3968
|
return uniqueFilter;
|
|
3554
3969
|
}
|
|
3555
|
-
return this.readUnique(kysely, model, {
|
|
3556
|
-
where: uniqueFilter
|
|
3557
|
-
});
|
|
3970
|
+
return this.readUnique(kysely, model, {
|
|
3971
|
+
where: uniqueFilter
|
|
3972
|
+
});
|
|
3973
|
+
}
|
|
3974
|
+
/**
|
|
3975
|
+
* Normalize input args to strip `undefined` fields
|
|
3976
|
+
*/
|
|
3977
|
+
normalizeArgs(args) {
|
|
3978
|
+
if (!args) {
|
|
3979
|
+
return;
|
|
3980
|
+
}
|
|
3981
|
+
const newArgs = clone(args);
|
|
3982
|
+
this.doNormalizeArgs(newArgs);
|
|
3983
|
+
return newArgs;
|
|
3984
|
+
}
|
|
3985
|
+
doNormalizeArgs(args) {
|
|
3986
|
+
if (args && typeof args === "object") {
|
|
3987
|
+
for (const [key, value] of Object.entries(args)) {
|
|
3988
|
+
if (value === void 0) {
|
|
3989
|
+
delete args[key];
|
|
3990
|
+
} else if (value && isPlainObject3(value)) {
|
|
3991
|
+
this.doNormalizeArgs(value);
|
|
3992
|
+
}
|
|
3993
|
+
}
|
|
3994
|
+
}
|
|
3995
|
+
}
|
|
3996
|
+
makeQueryId(operation) {
|
|
3997
|
+
return {
|
|
3998
|
+
queryId: `${operation}-${createId()}`
|
|
3999
|
+
};
|
|
4000
|
+
}
|
|
4001
|
+
executeQuery(kysely, query, operation) {
|
|
4002
|
+
return kysely.executeQuery(query.compile(), this.makeQueryId(operation));
|
|
4003
|
+
}
|
|
4004
|
+
async executeQueryTakeFirst(kysely, query, operation) {
|
|
4005
|
+
const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
|
|
4006
|
+
return result.rows[0];
|
|
4007
|
+
}
|
|
4008
|
+
async executeQueryTakeFirstOrThrow(kysely, query, operation) {
|
|
4009
|
+
const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
|
|
4010
|
+
if (result.rows.length === 0) {
|
|
4011
|
+
throw new QueryError("No rows found");
|
|
4012
|
+
}
|
|
4013
|
+
return result.rows[0];
|
|
3558
4014
|
}
|
|
3559
4015
|
};
|
|
3560
4016
|
|
|
@@ -3564,21 +4020,37 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3564
4020
|
__name(this, "AggregateOperationHandler");
|
|
3565
4021
|
}
|
|
3566
4022
|
async handle(_operation, args) {
|
|
3567
|
-
const
|
|
4023
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4024
|
+
const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
|
|
3568
4025
|
let query = this.kysely.selectFrom((eb) => {
|
|
3569
|
-
let subQuery =
|
|
3570
|
-
const
|
|
3571
|
-
|
|
4026
|
+
let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
4027
|
+
const selectedFields = [];
|
|
4028
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
4029
|
+
if (key.startsWith("_") && value && typeof value === "object") {
|
|
4030
|
+
Object.entries(value).filter(([field]) => field !== "_all").filter(([, val]) => val === true).forEach(([field]) => {
|
|
4031
|
+
if (!selectedFields.includes(field)) selectedFields.push(field);
|
|
4032
|
+
});
|
|
4033
|
+
}
|
|
4034
|
+
}
|
|
4035
|
+
if (selectedFields.length > 0) {
|
|
4036
|
+
for (const field of selectedFields) {
|
|
4037
|
+
subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, field);
|
|
4038
|
+
}
|
|
4039
|
+
} else {
|
|
4040
|
+
subQuery = subQuery.select(() => eb.lit(1).as("_all"));
|
|
4041
|
+
}
|
|
4042
|
+
const skip = parsedArgs?.skip;
|
|
4043
|
+
let take = parsedArgs?.take;
|
|
3572
4044
|
let negateOrderBy = false;
|
|
3573
4045
|
if (take !== void 0 && take < 0) {
|
|
3574
4046
|
negateOrderBy = true;
|
|
3575
4047
|
take = -take;
|
|
3576
4048
|
}
|
|
3577
4049
|
subQuery = this.dialect.buildSkipTake(subQuery, skip, take);
|
|
3578
|
-
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model,
|
|
4050
|
+
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, parsedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
3579
4051
|
return subQuery.as("$sub");
|
|
3580
4052
|
});
|
|
3581
|
-
for (const [key, value] of Object.entries(
|
|
4053
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3582
4054
|
switch (key) {
|
|
3583
4055
|
case "_count": {
|
|
3584
4056
|
if (value === true) {
|
|
@@ -3603,7 +4075,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3603
4075
|
Object.entries(value).forEach(([field, val]) => {
|
|
3604
4076
|
if (val === true) {
|
|
3605
4077
|
query = query.select((eb) => {
|
|
3606
|
-
const fn =
|
|
4078
|
+
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
4079
|
return fn(sql5.ref(`$sub.${field}`)).as(`${key}.${field}`);
|
|
3608
4080
|
});
|
|
3609
4081
|
}
|
|
@@ -3612,9 +4084,9 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3612
4084
|
}
|
|
3613
4085
|
}
|
|
3614
4086
|
}
|
|
3615
|
-
const result = await
|
|
4087
|
+
const result = await this.executeQuery(this.kysely, query, "aggregate");
|
|
3616
4088
|
const ret = {};
|
|
3617
|
-
for (const [key, value] of Object.entries(result)) {
|
|
4089
|
+
for (const [key, value] of Object.entries(result.rows[0])) {
|
|
3618
4090
|
if (key === "_count") {
|
|
3619
4091
|
ret[key] = value;
|
|
3620
4092
|
continue;
|
|
@@ -3636,7 +4108,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
3636
4108
|
val = parseFloat(val);
|
|
3637
4109
|
} else {
|
|
3638
4110
|
if (op === "_sum" || op === "_min" || op === "_max") {
|
|
3639
|
-
val =
|
|
4111
|
+
val = match10(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
|
|
3640
4112
|
}
|
|
3641
4113
|
}
|
|
3642
4114
|
}
|
|
@@ -3657,34 +4129,47 @@ var CountOperationHandler = class extends BaseOperationHandler {
|
|
|
3657
4129
|
__name(this, "CountOperationHandler");
|
|
3658
4130
|
}
|
|
3659
4131
|
async handle(_operation, args) {
|
|
3660
|
-
const
|
|
4132
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4133
|
+
const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
|
|
4134
|
+
const subQueryName = "$sub";
|
|
3661
4135
|
let query = this.kysely.selectFrom((eb) => {
|
|
3662
|
-
let subQuery =
|
|
3663
|
-
|
|
3664
|
-
|
|
4136
|
+
let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
4137
|
+
if (parsedArgs?.select && typeof parsedArgs.select === "object") {
|
|
4138
|
+
for (const [key, value] of Object.entries(parsedArgs.select)) {
|
|
4139
|
+
if (key !== "_all" && value === true) {
|
|
4140
|
+
subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, key);
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4143
|
+
} else {
|
|
4144
|
+
subQuery = subQuery.select(() => eb.lit(1).as("_all"));
|
|
4145
|
+
}
|
|
4146
|
+
subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
|
|
4147
|
+
return subQuery.as(subQueryName);
|
|
3665
4148
|
});
|
|
3666
|
-
if (
|
|
3667
|
-
query = query.select((eb) => Object.keys(
|
|
3668
|
-
|
|
4149
|
+
if (parsedArgs?.select && typeof parsedArgs.select === "object") {
|
|
4150
|
+
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)));
|
|
4151
|
+
const result = await this.executeQuery(this.kysely, query, "count");
|
|
4152
|
+
return result.rows[0];
|
|
3669
4153
|
} else {
|
|
3670
4154
|
query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
|
|
3671
|
-
const result = await
|
|
3672
|
-
return result.count;
|
|
4155
|
+
const result = await this.executeQuery(this.kysely, query, "count");
|
|
4156
|
+
return result.rows[0].count;
|
|
3673
4157
|
}
|
|
3674
4158
|
}
|
|
3675
4159
|
};
|
|
3676
4160
|
|
|
3677
4161
|
// src/client/crud/operations/create.ts
|
|
3678
|
-
import { match as
|
|
4162
|
+
import { match as match11 } from "ts-pattern";
|
|
3679
4163
|
var CreateOperationHandler = class extends BaseOperationHandler {
|
|
3680
4164
|
static {
|
|
3681
4165
|
__name(this, "CreateOperationHandler");
|
|
3682
4166
|
}
|
|
3683
4167
|
async handle(operation, args) {
|
|
3684
|
-
|
|
3685
|
-
|
|
4168
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4169
|
+
return match11(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, normalizedArgs))).with("createMany", () => {
|
|
4170
|
+
return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, normalizedArgs));
|
|
3686
4171
|
}).with("createManyAndReturn", () => {
|
|
3687
|
-
return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model,
|
|
4172
|
+
return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, normalizedArgs));
|
|
3688
4173
|
}).exhaustive();
|
|
3689
4174
|
}
|
|
3690
4175
|
async runCreate(args) {
|
|
@@ -3728,13 +4213,14 @@ var CreateOperationHandler = class extends BaseOperationHandler {
|
|
|
3728
4213
|
};
|
|
3729
4214
|
|
|
3730
4215
|
// src/client/crud/operations/delete.ts
|
|
3731
|
-
import { match as
|
|
4216
|
+
import { match as match12 } from "ts-pattern";
|
|
3732
4217
|
var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
3733
4218
|
static {
|
|
3734
4219
|
__name(this, "DeleteOperationHandler");
|
|
3735
4220
|
}
|
|
3736
4221
|
async handle(operation, args) {
|
|
3737
|
-
|
|
4222
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4223
|
+
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
4224
|
}
|
|
3739
4225
|
async runDelete(args) {
|
|
3740
4226
|
const existing = await this.readUnique(this.kysely, this.model, {
|
|
@@ -3746,15 +4232,19 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
|
3746
4232
|
if (!existing) {
|
|
3747
4233
|
throw new NotFoundError(this.model);
|
|
3748
4234
|
}
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
4235
|
+
await this.safeTransaction(async (tx) => {
|
|
4236
|
+
const result = await this.delete(tx, this.model, args.where);
|
|
4237
|
+
if (result.count === 0) {
|
|
4238
|
+
throw new NotFoundError(this.model);
|
|
4239
|
+
}
|
|
4240
|
+
});
|
|
3753
4241
|
return existing;
|
|
3754
4242
|
}
|
|
3755
4243
|
async runDeleteMany(args) {
|
|
3756
|
-
|
|
3757
|
-
|
|
4244
|
+
return await this.safeTransaction(async (tx) => {
|
|
4245
|
+
const result = await this.delete(tx, this.model, args?.where, args?.limit);
|
|
4246
|
+
return result;
|
|
4247
|
+
});
|
|
3758
4248
|
}
|
|
3759
4249
|
};
|
|
3760
4250
|
|
|
@@ -3764,7 +4254,8 @@ var FindOperationHandler = class extends BaseOperationHandler {
|
|
|
3764
4254
|
__name(this, "FindOperationHandler");
|
|
3765
4255
|
}
|
|
3766
4256
|
async handle(operation, args, validateArgs = true) {
|
|
3767
|
-
const
|
|
4257
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4258
|
+
const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", normalizedArgs) : normalizedArgs;
|
|
3768
4259
|
const result = await this.read(this.client.$qb, this.model, parsedArgs);
|
|
3769
4260
|
const finalResult = operation === "findMany" ? result : result[0] ?? null;
|
|
3770
4261
|
return finalResult;
|
|
@@ -3773,17 +4264,18 @@ var FindOperationHandler = class extends BaseOperationHandler {
|
|
|
3773
4264
|
|
|
3774
4265
|
// src/client/crud/operations/group-by.ts
|
|
3775
4266
|
import { sql as sql7 } from "kysely";
|
|
3776
|
-
import { match as
|
|
3777
|
-
var
|
|
4267
|
+
import { match as match13 } from "ts-pattern";
|
|
4268
|
+
var GroupByOperationHandler = class extends BaseOperationHandler {
|
|
3778
4269
|
static {
|
|
3779
|
-
__name(this, "
|
|
4270
|
+
__name(this, "GroupByOperationHandler");
|
|
3780
4271
|
}
|
|
3781
4272
|
async handle(_operation, args) {
|
|
3782
|
-
const
|
|
4273
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4274
|
+
const parsedArgs = this.inputValidator.validateGroupByArgs(this.model, normalizedArgs);
|
|
3783
4275
|
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 =
|
|
4276
|
+
let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
|
|
4277
|
+
const skip = parsedArgs?.skip;
|
|
4278
|
+
let take = parsedArgs?.take;
|
|
3787
4279
|
let negateOrderBy = false;
|
|
3788
4280
|
if (take !== void 0 && take < 0) {
|
|
3789
4281
|
negateOrderBy = true;
|
|
@@ -3793,20 +4285,20 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3793
4285
|
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
3794
4286
|
return subQuery.as("$sub");
|
|
3795
4287
|
});
|
|
3796
|
-
const bys = typeof
|
|
3797
|
-
|
|
3798
|
-
] :
|
|
3799
|
-
query = query.groupBy(bys);
|
|
3800
|
-
if (
|
|
3801
|
-
query = this.dialect.buildOrderBy(query, this.model, "$sub",
|
|
4288
|
+
const bys = typeof parsedArgs.by === "string" ? [
|
|
4289
|
+
parsedArgs.by
|
|
4290
|
+
] : parsedArgs.by;
|
|
4291
|
+
query = query.groupBy(bys.map((by) => sql7.ref(`$sub.${by}`)));
|
|
4292
|
+
if (parsedArgs.orderBy) {
|
|
4293
|
+
query = this.dialect.buildOrderBy(query, this.model, "$sub", parsedArgs.orderBy, false, false);
|
|
3802
4294
|
}
|
|
3803
|
-
if (
|
|
3804
|
-
query = query.having((
|
|
4295
|
+
if (parsedArgs.having) {
|
|
4296
|
+
query = query.having((eb) => this.dialect.buildFilter(eb, this.model, "$sub", parsedArgs.having));
|
|
3805
4297
|
}
|
|
3806
4298
|
for (const by of bys) {
|
|
3807
4299
|
query = query.select(() => sql7.ref(`$sub.${by}`).as(by));
|
|
3808
4300
|
}
|
|
3809
|
-
for (const [key, value] of Object.entries(
|
|
4301
|
+
for (const [key, value] of Object.entries(parsedArgs)) {
|
|
3810
4302
|
switch (key) {
|
|
3811
4303
|
case "_count": {
|
|
3812
4304
|
if (value === true) {
|
|
@@ -3831,7 +4323,7 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3831
4323
|
Object.entries(value).forEach(([field, val]) => {
|
|
3832
4324
|
if (val === true) {
|
|
3833
4325
|
query = query.select((eb) => {
|
|
3834
|
-
const fn =
|
|
4326
|
+
const fn = match13(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
|
|
3835
4327
|
return fn(sql7.ref(`$sub.${field}`)).as(`${key}.${field}`);
|
|
3836
4328
|
});
|
|
3837
4329
|
}
|
|
@@ -3840,8 +4332,8 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3840
4332
|
}
|
|
3841
4333
|
}
|
|
3842
4334
|
}
|
|
3843
|
-
const result = await
|
|
3844
|
-
return result.map((row) => this.postProcessRow(row));
|
|
4335
|
+
const result = await this.executeQuery(this.kysely, query, "groupBy");
|
|
4336
|
+
return result.rows.map((row) => this.postProcessRow(row));
|
|
3845
4337
|
}
|
|
3846
4338
|
postProcessRow(row) {
|
|
3847
4339
|
const ret = {};
|
|
@@ -3868,7 +4360,7 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3868
4360
|
val = parseFloat(val);
|
|
3869
4361
|
} else {
|
|
3870
4362
|
if (op === "_sum" || op === "_min" || op === "_max") {
|
|
3871
|
-
val =
|
|
4363
|
+
val = match13(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
|
|
3872
4364
|
}
|
|
3873
4365
|
}
|
|
3874
4366
|
}
|
|
@@ -3883,31 +4375,45 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
|
|
|
3883
4375
|
};
|
|
3884
4376
|
|
|
3885
4377
|
// src/client/crud/operations/update.ts
|
|
3886
|
-
import { match as
|
|
4378
|
+
import { match as match14 } from "ts-pattern";
|
|
3887
4379
|
var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
3888
4380
|
static {
|
|
3889
4381
|
__name(this, "UpdateOperationHandler");
|
|
3890
4382
|
}
|
|
3891
4383
|
async handle(operation, args) {
|
|
3892
|
-
|
|
4384
|
+
const normalizedArgs = this.normalizeArgs(args);
|
|
4385
|
+
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
4386
|
}
|
|
3894
4387
|
async runUpdate(args) {
|
|
3895
|
-
const
|
|
3896
|
-
const
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
4388
|
+
const readBackResult = await this.safeTransaction(async (tx) => {
|
|
4389
|
+
const updateResult = await this.update(tx, this.model, args.where, args.data);
|
|
4390
|
+
const readFilter = updateResult ?? args.where;
|
|
4391
|
+
let readBackResult2 = void 0;
|
|
4392
|
+
try {
|
|
4393
|
+
readBackResult2 = await this.readUnique(tx, this.model, {
|
|
4394
|
+
select: args.select,
|
|
4395
|
+
include: args.include,
|
|
4396
|
+
omit: args.omit,
|
|
4397
|
+
where: readFilter
|
|
4398
|
+
});
|
|
4399
|
+
} catch {
|
|
4400
|
+
}
|
|
4401
|
+
return readBackResult2;
|
|
3903
4402
|
});
|
|
3904
|
-
if (!
|
|
3905
|
-
|
|
4403
|
+
if (!readBackResult) {
|
|
4404
|
+
if (this.hasPolicyEnabled) {
|
|
4405
|
+
throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
|
|
4406
|
+
} else {
|
|
4407
|
+
return null;
|
|
4408
|
+
}
|
|
4409
|
+
} else {
|
|
4410
|
+
return readBackResult;
|
|
3906
4411
|
}
|
|
3907
|
-
return result;
|
|
3908
4412
|
}
|
|
3909
4413
|
async runUpdateMany(args) {
|
|
3910
|
-
return this.
|
|
4414
|
+
return this.safeTransaction(async (tx) => {
|
|
4415
|
+
return this.updateMany(tx, this.model, args.where, args.data, args.limit, false);
|
|
4416
|
+
});
|
|
3911
4417
|
}
|
|
3912
4418
|
async runUpdateManyAndReturn(args) {
|
|
3913
4419
|
if (!args) {
|
|
@@ -3945,19 +4451,19 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3945
4451
|
};
|
|
3946
4452
|
|
|
3947
4453
|
// src/client/crud/validator.ts
|
|
4454
|
+
import { invariant as invariant8 } from "@zenstackhq/common-helpers";
|
|
3948
4455
|
import Decimal from "decimal.js";
|
|
3949
4456
|
import stableStringify from "json-stable-stringify";
|
|
3950
|
-
import { match as
|
|
4457
|
+
import { match as match15, P as P2 } from "ts-pattern";
|
|
3951
4458
|
import { z } from "zod";
|
|
3952
4459
|
var InputValidator = class {
|
|
3953
4460
|
static {
|
|
3954
4461
|
__name(this, "InputValidator");
|
|
3955
4462
|
}
|
|
3956
4463
|
schema;
|
|
3957
|
-
schemaCache;
|
|
4464
|
+
schemaCache = /* @__PURE__ */ new Map();
|
|
3958
4465
|
constructor(schema) {
|
|
3959
4466
|
this.schema = schema;
|
|
3960
|
-
this.schemaCache = /* @__PURE__ */ new Map();
|
|
3961
4467
|
}
|
|
3962
4468
|
validateFindArgs(model, unique, args) {
|
|
3963
4469
|
return this.validate(model, "find", {
|
|
@@ -4014,7 +4520,7 @@ var InputValidator = class {
|
|
|
4014
4520
|
}
|
|
4015
4521
|
const { error } = schema.safeParse(args);
|
|
4016
4522
|
if (error) {
|
|
4017
|
-
throw new
|
|
4523
|
+
throw new InputValidationError(`Invalid ${operation} args: ${error.message}`, error);
|
|
4018
4524
|
}
|
|
4019
4525
|
return args;
|
|
4020
4526
|
}
|
|
@@ -4033,11 +4539,11 @@ var InputValidator = class {
|
|
|
4033
4539
|
fields["distinct"] = this.makeDistinctSchema(model).optional();
|
|
4034
4540
|
fields["cursor"] = this.makeCursorSchema(model).optional();
|
|
4035
4541
|
if (options.collection) {
|
|
4036
|
-
fields["skip"] =
|
|
4037
|
-
fields["take"] =
|
|
4542
|
+
fields["skip"] = this.makeSkipSchema().optional();
|
|
4543
|
+
fields["take"] = this.makeTakeSchema().optional();
|
|
4038
4544
|
fields["orderBy"] = this.orArray(this.makeOrderBySchema(model, true, false), true).optional();
|
|
4039
4545
|
}
|
|
4040
|
-
let result = z.
|
|
4546
|
+
let result = z.strictObject(fields);
|
|
4041
4547
|
result = this.refineForSelectIncludeMutuallyExclusive(result);
|
|
4042
4548
|
result = this.refineForSelectOmitMutuallyExclusive(result);
|
|
4043
4549
|
if (!options.unique) {
|
|
@@ -4046,22 +4552,50 @@ var InputValidator = class {
|
|
|
4046
4552
|
return result;
|
|
4047
4553
|
}
|
|
4048
4554
|
makePrimitiveSchema(type) {
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
z.
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4555
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
4556
|
+
return this.makeTypeDefSchema(type);
|
|
4557
|
+
} else {
|
|
4558
|
+
return match15(type).with("String", () => z.string()).with("Int", () => z.int()).with("Float", () => z.number()).with("Boolean", () => z.boolean()).with("BigInt", () => z.union([
|
|
4559
|
+
z.int(),
|
|
4560
|
+
z.bigint()
|
|
4561
|
+
])).with("Decimal", () => z.union([
|
|
4562
|
+
z.number(),
|
|
4563
|
+
z.instanceof(Decimal),
|
|
4564
|
+
z.string()
|
|
4565
|
+
])).with("DateTime", () => z.union([
|
|
4566
|
+
z.date(),
|
|
4567
|
+
z.string().datetime()
|
|
4568
|
+
])).with("Bytes", () => z.instanceof(Uint8Array)).otherwise(() => z.unknown());
|
|
4569
|
+
}
|
|
4570
|
+
}
|
|
4571
|
+
makeTypeDefSchema(type) {
|
|
4572
|
+
const key = `$typedef-${type}`;
|
|
4573
|
+
let schema = this.schemaCache.get(key);
|
|
4574
|
+
if (schema) {
|
|
4575
|
+
return schema;
|
|
4576
|
+
}
|
|
4577
|
+
const typeDef = this.schema.typeDefs?.[type];
|
|
4578
|
+
invariant8(typeDef, `Type definition "${type}" not found in schema`);
|
|
4579
|
+
schema = z.looseObject(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
|
|
4580
|
+
let fieldSchema = this.makePrimitiveSchema(def.type);
|
|
4581
|
+
if (def.array) {
|
|
4582
|
+
fieldSchema = fieldSchema.array();
|
|
4583
|
+
}
|
|
4584
|
+
if (def.optional) {
|
|
4585
|
+
fieldSchema = fieldSchema.optional();
|
|
4586
|
+
}
|
|
4587
|
+
return [
|
|
4588
|
+
field,
|
|
4589
|
+
fieldSchema
|
|
4590
|
+
];
|
|
4591
|
+
})));
|
|
4592
|
+
this.schemaCache.set(key, schema);
|
|
4593
|
+
return schema;
|
|
4594
|
+
}
|
|
4595
|
+
makeWhereSchema(model, unique, withoutRelationFields = false, withAggregations = false) {
|
|
4062
4596
|
const modelDef = getModel(this.schema, model);
|
|
4063
4597
|
if (!modelDef) {
|
|
4064
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
4598
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
4065
4599
|
}
|
|
4066
4600
|
const fields = {};
|
|
4067
4601
|
for (const field of Object.keys(modelDef.fields)) {
|
|
@@ -4076,7 +4610,7 @@ var InputValidator = class {
|
|
|
4076
4610
|
if (fieldDef.array) {
|
|
4077
4611
|
fieldSchema = z.union([
|
|
4078
4612
|
fieldSchema,
|
|
4079
|
-
z.
|
|
4613
|
+
z.strictObject({
|
|
4080
4614
|
some: fieldSchema.optional(),
|
|
4081
4615
|
every: fieldSchema.optional(),
|
|
4082
4616
|
none: fieldSchema.optional()
|
|
@@ -4085,7 +4619,7 @@ var InputValidator = class {
|
|
|
4085
4619
|
} else {
|
|
4086
4620
|
fieldSchema = z.union([
|
|
4087
4621
|
fieldSchema,
|
|
4088
|
-
z.
|
|
4622
|
+
z.strictObject({
|
|
4089
4623
|
is: fieldSchema.optional(),
|
|
4090
4624
|
isNot: fieldSchema.optional()
|
|
4091
4625
|
})
|
|
@@ -4095,12 +4629,12 @@ var InputValidator = class {
|
|
|
4095
4629
|
const enumDef = getEnum(this.schema, fieldDef.type);
|
|
4096
4630
|
if (enumDef) {
|
|
4097
4631
|
if (Object.keys(enumDef).length > 0) {
|
|
4098
|
-
fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional);
|
|
4632
|
+
fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, withAggregations);
|
|
4099
4633
|
}
|
|
4100
4634
|
} else if (fieldDef.array) {
|
|
4101
4635
|
fieldSchema = this.makeArrayFilterSchema(fieldDef.type);
|
|
4102
4636
|
} else {
|
|
4103
|
-
fieldSchema = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional);
|
|
4637
|
+
fieldSchema = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional, withAggregations);
|
|
4104
4638
|
}
|
|
4105
4639
|
}
|
|
4106
4640
|
if (fieldSchema) {
|
|
@@ -4111,18 +4645,32 @@ var InputValidator = class {
|
|
|
4111
4645
|
const uniqueFields = getUniqueFields(this.schema, model);
|
|
4112
4646
|
for (const uniqueField of uniqueFields) {
|
|
4113
4647
|
if ("defs" in uniqueField) {
|
|
4114
|
-
fields[uniqueField.name] = z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) =>
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4648
|
+
fields[uniqueField.name] = z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
|
|
4649
|
+
invariant8(!def.relation, "unique field cannot be a relation");
|
|
4650
|
+
let fieldSchema;
|
|
4651
|
+
const enumDef = getEnum(this.schema, def.type);
|
|
4652
|
+
if (enumDef) {
|
|
4653
|
+
if (Object.keys(enumDef).length > 0) {
|
|
4654
|
+
fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional, false);
|
|
4655
|
+
} else {
|
|
4656
|
+
fieldSchema = z.never();
|
|
4657
|
+
}
|
|
4658
|
+
} else {
|
|
4659
|
+
fieldSchema = this.makePrimitiveFilterSchema(def.type, !!def.optional, false);
|
|
4660
|
+
}
|
|
4661
|
+
return [
|
|
4662
|
+
key,
|
|
4663
|
+
fieldSchema
|
|
4664
|
+
];
|
|
4665
|
+
}))).optional();
|
|
4118
4666
|
}
|
|
4119
4667
|
}
|
|
4120
4668
|
}
|
|
4121
|
-
fields["$expr"] = z.
|
|
4669
|
+
fields["$expr"] = z.custom((v) => typeof v === "function").optional();
|
|
4122
4670
|
fields["AND"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
|
|
4123
4671
|
fields["OR"] = z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)).array().optional();
|
|
4124
4672
|
fields["NOT"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
|
|
4125
|
-
const baseWhere = z.
|
|
4673
|
+
const baseWhere = z.strictObject(fields);
|
|
4126
4674
|
let result = baseWhere;
|
|
4127
4675
|
if (unique) {
|
|
4128
4676
|
const uniqueFields = getUniqueFields(this.schema, model);
|
|
@@ -4141,21 +4689,25 @@ var InputValidator = class {
|
|
|
4141
4689
|
}
|
|
4142
4690
|
return result;
|
|
4143
4691
|
}
|
|
4144
|
-
makeEnumFilterSchema(enumDef, optional) {
|
|
4692
|
+
makeEnumFilterSchema(enumDef, optional, withAggregations) {
|
|
4145
4693
|
const baseSchema = z.enum(Object.keys(enumDef));
|
|
4146
|
-
const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.lazy(() => this.makeEnumFilterSchema(enumDef, optional))
|
|
4694
|
+
const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.lazy(() => this.makeEnumFilterSchema(enumDef, optional, withAggregations)), [
|
|
4695
|
+
"equals",
|
|
4696
|
+
"in",
|
|
4697
|
+
"notIn",
|
|
4698
|
+
"not"
|
|
4699
|
+
], withAggregations ? [
|
|
4700
|
+
"_count",
|
|
4701
|
+
"_min",
|
|
4702
|
+
"_max"
|
|
4703
|
+
] : void 0);
|
|
4147
4704
|
return z.union([
|
|
4148
4705
|
this.nullableIf(baseSchema, optional),
|
|
4149
|
-
z.
|
|
4150
|
-
equals: components.equals,
|
|
4151
|
-
in: components.in,
|
|
4152
|
-
notIn: components.notIn,
|
|
4153
|
-
not: components.not
|
|
4154
|
-
})
|
|
4706
|
+
z.strictObject(components)
|
|
4155
4707
|
]);
|
|
4156
4708
|
}
|
|
4157
4709
|
makeArrayFilterSchema(type) {
|
|
4158
|
-
return z.
|
|
4710
|
+
return z.strictObject({
|
|
4159
4711
|
equals: this.makePrimitiveSchema(type).array().optional(),
|
|
4160
4712
|
has: this.makePrimitiveSchema(type).optional(),
|
|
4161
4713
|
hasEvery: this.makePrimitiveSchema(type).array().optional(),
|
|
@@ -4163,39 +4715,59 @@ var InputValidator = class {
|
|
|
4163
4715
|
isEmpty: z.boolean().optional()
|
|
4164
4716
|
});
|
|
4165
4717
|
}
|
|
4166
|
-
makePrimitiveFilterSchema(type, optional) {
|
|
4167
|
-
|
|
4718
|
+
makePrimitiveFilterSchema(type, optional, withAggregations) {
|
|
4719
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
4720
|
+
return this.makeTypeDefFilterSchema(type, optional);
|
|
4721
|
+
}
|
|
4722
|
+
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();
|
|
4723
|
+
}
|
|
4724
|
+
makeTypeDefFilterSchema(_type, _optional) {
|
|
4725
|
+
return z.never();
|
|
4168
4726
|
}
|
|
4169
|
-
makeDateTimeFilterSchema(optional) {
|
|
4727
|
+
makeDateTimeFilterSchema(optional, withAggregations) {
|
|
4170
4728
|
return this.makeCommonPrimitiveFilterSchema(z.union([
|
|
4171
|
-
z.
|
|
4729
|
+
z.iso.datetime(),
|
|
4172
4730
|
z.date()
|
|
4173
|
-
]), optional, () => z.lazy(() => this.makeDateTimeFilterSchema(optional))
|
|
4174
|
-
|
|
4175
|
-
|
|
4731
|
+
]), optional, () => z.lazy(() => this.makeDateTimeFilterSchema(optional, withAggregations)), withAggregations ? [
|
|
4732
|
+
"_count",
|
|
4733
|
+
"_min",
|
|
4734
|
+
"_max"
|
|
4735
|
+
] : void 0);
|
|
4736
|
+
}
|
|
4737
|
+
makeBooleanFilterSchema(optional, withAggregations) {
|
|
4738
|
+
const components = this.makeCommonPrimitiveFilterComponents(z.boolean(), optional, () => z.lazy(() => this.makeBooleanFilterSchema(optional, withAggregations)), [
|
|
4739
|
+
"equals",
|
|
4740
|
+
"not"
|
|
4741
|
+
], withAggregations ? [
|
|
4742
|
+
"_count",
|
|
4743
|
+
"_min",
|
|
4744
|
+
"_max"
|
|
4745
|
+
] : void 0);
|
|
4176
4746
|
return z.union([
|
|
4177
4747
|
this.nullableIf(z.boolean(), optional),
|
|
4178
|
-
z.
|
|
4179
|
-
equals: this.nullableIf(z.boolean(), optional).optional(),
|
|
4180
|
-
not: z.lazy(() => this.makeBooleanFilterSchema(optional)).optional()
|
|
4181
|
-
})
|
|
4748
|
+
z.strictObject(components)
|
|
4182
4749
|
]);
|
|
4183
4750
|
}
|
|
4184
|
-
makeBytesFilterSchema(optional) {
|
|
4751
|
+
makeBytesFilterSchema(optional, withAggregations) {
|
|
4185
4752
|
const baseSchema = z.instanceof(Uint8Array);
|
|
4186
|
-
const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.instanceof(Uint8Array)
|
|
4753
|
+
const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.instanceof(Uint8Array), [
|
|
4754
|
+
"equals",
|
|
4755
|
+
"in",
|
|
4756
|
+
"notIn",
|
|
4757
|
+
"not"
|
|
4758
|
+
], withAggregations ? [
|
|
4759
|
+
"_count",
|
|
4760
|
+
"_min",
|
|
4761
|
+
"_max"
|
|
4762
|
+
] : void 0);
|
|
4187
4763
|
return z.union([
|
|
4188
4764
|
this.nullableIf(baseSchema, optional),
|
|
4189
|
-
z.
|
|
4190
|
-
equals: components.equals,
|
|
4191
|
-
in: components.in,
|
|
4192
|
-
notIn: components.notIn,
|
|
4193
|
-
not: components.not
|
|
4194
|
-
})
|
|
4765
|
+
z.strictObject(components)
|
|
4195
4766
|
]);
|
|
4196
4767
|
}
|
|
4197
|
-
makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis) {
|
|
4198
|
-
|
|
4768
|
+
makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis, supportedOperators = void 0, withAggregations = void 0) {
|
|
4769
|
+
const commonAggSchema = /* @__PURE__ */ __name(() => this.makeCommonPrimitiveFilterSchema(baseSchema, false, makeThis, void 0).optional(), "commonAggSchema");
|
|
4770
|
+
let result = {
|
|
4199
4771
|
equals: this.nullableIf(baseSchema.optional(), optional),
|
|
4200
4772
|
notEquals: this.nullableIf(baseSchema.optional(), optional),
|
|
4201
4773
|
in: baseSchema.array().optional(),
|
|
@@ -4204,20 +4776,70 @@ var InputValidator = class {
|
|
|
4204
4776
|
lte: baseSchema.optional(),
|
|
4205
4777
|
gt: baseSchema.optional(),
|
|
4206
4778
|
gte: baseSchema.optional(),
|
|
4207
|
-
not: makeThis().optional()
|
|
4779
|
+
not: makeThis().optional(),
|
|
4780
|
+
...withAggregations?.includes("_count") ? {
|
|
4781
|
+
_count: this.makeNumberFilterSchema(z.int(), false, false).optional()
|
|
4782
|
+
} : {},
|
|
4783
|
+
...withAggregations?.includes("_avg") ? {
|
|
4784
|
+
_avg: commonAggSchema()
|
|
4785
|
+
} : {},
|
|
4786
|
+
...withAggregations?.includes("_sum") ? {
|
|
4787
|
+
_sum: commonAggSchema()
|
|
4788
|
+
} : {},
|
|
4789
|
+
...withAggregations?.includes("_min") ? {
|
|
4790
|
+
_min: commonAggSchema()
|
|
4791
|
+
} : {},
|
|
4792
|
+
...withAggregations?.includes("_max") ? {
|
|
4793
|
+
_max: commonAggSchema()
|
|
4794
|
+
} : {}
|
|
4208
4795
|
};
|
|
4796
|
+
if (supportedOperators) {
|
|
4797
|
+
const keys = [
|
|
4798
|
+
...supportedOperators,
|
|
4799
|
+
...withAggregations ?? []
|
|
4800
|
+
];
|
|
4801
|
+
result = extractFields(result, keys);
|
|
4802
|
+
}
|
|
4803
|
+
return result;
|
|
4209
4804
|
}
|
|
4210
|
-
makeCommonPrimitiveFilterSchema(baseSchema, optional, makeThis) {
|
|
4805
|
+
makeCommonPrimitiveFilterSchema(baseSchema, optional, makeThis, withAggregations = void 0) {
|
|
4211
4806
|
return z.union([
|
|
4212
4807
|
this.nullableIf(baseSchema, optional),
|
|
4213
|
-
z.
|
|
4808
|
+
z.strictObject(this.makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis, void 0, withAggregations))
|
|
4214
4809
|
]);
|
|
4215
4810
|
}
|
|
4216
|
-
makeNumberFilterSchema(baseSchema, optional) {
|
|
4217
|
-
return this.makeCommonPrimitiveFilterSchema(baseSchema, optional, () => z.lazy(() => this.makeNumberFilterSchema(baseSchema, optional))
|
|
4811
|
+
makeNumberFilterSchema(baseSchema, optional, withAggregations) {
|
|
4812
|
+
return this.makeCommonPrimitiveFilterSchema(baseSchema, optional, () => z.lazy(() => this.makeNumberFilterSchema(baseSchema, optional, withAggregations)), withAggregations ? [
|
|
4813
|
+
"_count",
|
|
4814
|
+
"_avg",
|
|
4815
|
+
"_sum",
|
|
4816
|
+
"_min",
|
|
4817
|
+
"_max"
|
|
4818
|
+
] : void 0);
|
|
4819
|
+
}
|
|
4820
|
+
makeStringFilterSchema(optional, withAggregations) {
|
|
4821
|
+
return z.union([
|
|
4822
|
+
this.nullableIf(z.string(), optional),
|
|
4823
|
+
z.strictObject({
|
|
4824
|
+
...this.makeCommonPrimitiveFilterComponents(z.string(), optional, () => z.lazy(() => this.makeStringFilterSchema(optional, withAggregations)), void 0, withAggregations ? [
|
|
4825
|
+
"_count",
|
|
4826
|
+
"_min",
|
|
4827
|
+
"_max"
|
|
4828
|
+
] : void 0),
|
|
4829
|
+
startsWith: z.string().optional(),
|
|
4830
|
+
endsWith: z.string().optional(),
|
|
4831
|
+
contains: z.string().optional(),
|
|
4832
|
+
...this.providerSupportsCaseSensitivity ? {
|
|
4833
|
+
mode: this.makeStringModeSchema().optional()
|
|
4834
|
+
} : {}
|
|
4835
|
+
})
|
|
4836
|
+
]);
|
|
4218
4837
|
}
|
|
4219
|
-
|
|
4220
|
-
return
|
|
4838
|
+
makeStringModeSchema() {
|
|
4839
|
+
return z.union([
|
|
4840
|
+
z.literal("default"),
|
|
4841
|
+
z.literal("insensitive")
|
|
4842
|
+
]);
|
|
4221
4843
|
}
|
|
4222
4844
|
makeSelectSchema(model) {
|
|
4223
4845
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4227,7 +4849,7 @@ var InputValidator = class {
|
|
|
4227
4849
|
if (fieldDef.relation) {
|
|
4228
4850
|
fields[field] = z.union([
|
|
4229
4851
|
z.literal(true),
|
|
4230
|
-
z.
|
|
4852
|
+
z.strictObject({
|
|
4231
4853
|
select: z.lazy(() => this.makeSelectSchema(fieldDef.type)).optional(),
|
|
4232
4854
|
include: z.lazy(() => this.makeIncludeSchema(fieldDef.type)).optional()
|
|
4233
4855
|
})
|
|
@@ -4236,22 +4858,24 @@ var InputValidator = class {
|
|
|
4236
4858
|
fields[field] = z.boolean().optional();
|
|
4237
4859
|
}
|
|
4238
4860
|
}
|
|
4239
|
-
const toManyRelations = Object.
|
|
4861
|
+
const toManyRelations = Object.values(modelDef.fields).filter((def) => def.relation && def.array);
|
|
4240
4862
|
if (toManyRelations.length > 0) {
|
|
4241
4863
|
fields["_count"] = z.union([
|
|
4242
4864
|
z.literal(true),
|
|
4243
|
-
z.
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
z.
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4865
|
+
z.strictObject({
|
|
4866
|
+
select: z.strictObject(toManyRelations.reduce((acc, fieldDef) => ({
|
|
4867
|
+
...acc,
|
|
4868
|
+
[fieldDef.name]: z.union([
|
|
4869
|
+
z.boolean(),
|
|
4870
|
+
z.strictObject({
|
|
4871
|
+
where: this.makeWhereSchema(fieldDef.type, false, false)
|
|
4872
|
+
})
|
|
4873
|
+
]).optional()
|
|
4874
|
+
}), {}))
|
|
4875
|
+
})
|
|
4252
4876
|
]).optional();
|
|
4253
4877
|
}
|
|
4254
|
-
return z.
|
|
4878
|
+
return z.strictObject(fields);
|
|
4255
4879
|
}
|
|
4256
4880
|
makeOmitSchema(model) {
|
|
4257
4881
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4262,7 +4886,7 @@ var InputValidator = class {
|
|
|
4262
4886
|
fields[field] = z.boolean().optional();
|
|
4263
4887
|
}
|
|
4264
4888
|
}
|
|
4265
|
-
return z.
|
|
4889
|
+
return z.strictObject(fields);
|
|
4266
4890
|
}
|
|
4267
4891
|
makeIncludeSchema(model) {
|
|
4268
4892
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4272,15 +4896,20 @@ var InputValidator = class {
|
|
|
4272
4896
|
if (fieldDef.relation) {
|
|
4273
4897
|
fields[field] = z.union([
|
|
4274
4898
|
z.literal(true),
|
|
4275
|
-
z.
|
|
4899
|
+
z.strictObject({
|
|
4276
4900
|
select: z.lazy(() => this.makeSelectSchema(fieldDef.type)).optional(),
|
|
4277
4901
|
include: z.lazy(() => this.makeIncludeSchema(fieldDef.type)).optional(),
|
|
4278
|
-
|
|
4902
|
+
omit: z.lazy(() => this.makeOmitSchema(fieldDef.type)).optional(),
|
|
4903
|
+
where: z.lazy(() => this.makeWhereSchema(fieldDef.type, false)).optional(),
|
|
4904
|
+
orderBy: z.lazy(() => this.makeOrderBySchema(fieldDef.type, true, false)).optional(),
|
|
4905
|
+
skip: this.makeSkipSchema().optional(),
|
|
4906
|
+
take: this.makeTakeSchema().optional(),
|
|
4907
|
+
distinct: this.makeDistinctSchema(fieldDef.type).optional()
|
|
4279
4908
|
})
|
|
4280
4909
|
]).optional();
|
|
4281
4910
|
}
|
|
4282
4911
|
}
|
|
4283
|
-
return z.
|
|
4912
|
+
return z.strictObject(fields);
|
|
4284
4913
|
}
|
|
4285
4914
|
makeOrderBySchema(model, withRelation, WithAggregation) {
|
|
4286
4915
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4293,13 +4922,21 @@ var InputValidator = class {
|
|
|
4293
4922
|
const fieldDef = requireField(this.schema, model, field);
|
|
4294
4923
|
if (fieldDef.relation) {
|
|
4295
4924
|
if (withRelation) {
|
|
4296
|
-
fields[field] = z.lazy(() =>
|
|
4925
|
+
fields[field] = z.lazy(() => {
|
|
4926
|
+
let relationOrderBy = this.makeOrderBySchema(fieldDef.type, withRelation, WithAggregation);
|
|
4927
|
+
if (fieldDef.array) {
|
|
4928
|
+
relationOrderBy = relationOrderBy.extend({
|
|
4929
|
+
_count: sort
|
|
4930
|
+
});
|
|
4931
|
+
}
|
|
4932
|
+
return relationOrderBy.optional();
|
|
4933
|
+
});
|
|
4297
4934
|
}
|
|
4298
4935
|
} else {
|
|
4299
4936
|
if (fieldDef.optional) {
|
|
4300
4937
|
fields[field] = z.union([
|
|
4301
4938
|
sort,
|
|
4302
|
-
z.
|
|
4939
|
+
z.strictObject({
|
|
4303
4940
|
sort,
|
|
4304
4941
|
nulls: z.union([
|
|
4305
4942
|
z.literal("first"),
|
|
@@ -4324,7 +4961,7 @@ var InputValidator = class {
|
|
|
4324
4961
|
fields[agg] = z.lazy(() => this.makeOrderBySchema(model, true, false).optional());
|
|
4325
4962
|
}
|
|
4326
4963
|
}
|
|
4327
|
-
return z.
|
|
4964
|
+
return z.strictObject(fields);
|
|
4328
4965
|
}
|
|
4329
4966
|
makeDistinctSchema(model) {
|
|
4330
4967
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4343,7 +4980,7 @@ var InputValidator = class {
|
|
|
4343
4980
|
select: this.makeSelectSchema(model).optional(),
|
|
4344
4981
|
include: this.makeIncludeSchema(model).optional(),
|
|
4345
4982
|
omit: this.makeOmitSchema(model).optional()
|
|
4346
|
-
})
|
|
4983
|
+
});
|
|
4347
4984
|
return this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
4348
4985
|
}
|
|
4349
4986
|
makeCreateManySchema(model) {
|
|
@@ -4351,15 +4988,15 @@ var InputValidator = class {
|
|
|
4351
4988
|
}
|
|
4352
4989
|
makeCreateManyAndReturnSchema(model) {
|
|
4353
4990
|
const base = this.makeCreateManyDataSchema(model, []);
|
|
4354
|
-
const result = base.merge(z.
|
|
4991
|
+
const result = base.merge(z.strictObject({
|
|
4355
4992
|
select: this.makeSelectSchema(model).optional(),
|
|
4356
4993
|
omit: this.makeOmitSchema(model).optional()
|
|
4357
4994
|
}));
|
|
4358
4995
|
return this.refineForSelectOmitMutuallyExclusive(result).optional();
|
|
4359
4996
|
}
|
|
4360
4997
|
makeCreateDataSchema(model, canBeArray, withoutFields = [], withoutRelationFields = false) {
|
|
4361
|
-
const
|
|
4362
|
-
const
|
|
4998
|
+
const uncheckedVariantFields = {};
|
|
4999
|
+
const checkedVariantFields = {};
|
|
4363
5000
|
const modelDef = requireModel(this.schema, model);
|
|
4364
5001
|
const hasRelation = !withoutRelationFields && Object.entries(modelDef.fields).some(([f, def]) => !withoutFields.includes(f) && def.relation);
|
|
4365
5002
|
Object.keys(modelDef.fields).forEach((field) => {
|
|
@@ -4370,6 +5007,9 @@ var InputValidator = class {
|
|
|
4370
5007
|
if (fieldDef.computed) {
|
|
4371
5008
|
return;
|
|
4372
5009
|
}
|
|
5010
|
+
if (this.isDelegateDiscriminator(fieldDef)) {
|
|
5011
|
+
return;
|
|
5012
|
+
}
|
|
4373
5013
|
if (fieldDef.relation) {
|
|
4374
5014
|
if (withoutRelationFields) {
|
|
4375
5015
|
return;
|
|
@@ -4401,13 +5041,16 @@ var InputValidator = class {
|
|
|
4401
5041
|
if (fieldDef.optional && !fieldDef.array) {
|
|
4402
5042
|
fieldSchema = fieldSchema.nullable();
|
|
4403
5043
|
}
|
|
4404
|
-
|
|
5044
|
+
checkedVariantFields[field] = fieldSchema;
|
|
5045
|
+
if (fieldDef.array || !fieldDef.relation.references) {
|
|
5046
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
5047
|
+
}
|
|
4405
5048
|
} else {
|
|
4406
5049
|
let fieldSchema = this.makePrimitiveSchema(fieldDef.type);
|
|
4407
5050
|
if (fieldDef.array) {
|
|
4408
5051
|
fieldSchema = z.union([
|
|
4409
5052
|
z.array(fieldSchema),
|
|
4410
|
-
z.
|
|
5053
|
+
z.strictObject({
|
|
4411
5054
|
set: z.array(fieldSchema)
|
|
4412
5055
|
})
|
|
4413
5056
|
]).optional();
|
|
@@ -4418,27 +5061,34 @@ var InputValidator = class {
|
|
|
4418
5061
|
if (fieldDef.optional) {
|
|
4419
5062
|
fieldSchema = fieldSchema.nullable();
|
|
4420
5063
|
}
|
|
4421
|
-
|
|
5064
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4422
5065
|
if (!fieldDef.foreignKeyFor) {
|
|
4423
|
-
|
|
5066
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4424
5067
|
}
|
|
4425
5068
|
}
|
|
4426
5069
|
});
|
|
4427
5070
|
if (!hasRelation) {
|
|
4428
|
-
return this.orArray(z.
|
|
5071
|
+
return this.orArray(z.strictObject(uncheckedVariantFields), canBeArray);
|
|
4429
5072
|
} else {
|
|
4430
5073
|
return z.union([
|
|
4431
|
-
z.
|
|
4432
|
-
z.
|
|
5074
|
+
z.strictObject(uncheckedVariantFields),
|
|
5075
|
+
z.strictObject(checkedVariantFields),
|
|
4433
5076
|
...canBeArray ? [
|
|
4434
|
-
z.array(z.
|
|
5077
|
+
z.array(z.strictObject(uncheckedVariantFields))
|
|
4435
5078
|
] : [],
|
|
4436
5079
|
...canBeArray ? [
|
|
4437
|
-
z.array(z.
|
|
5080
|
+
z.array(z.strictObject(checkedVariantFields))
|
|
4438
5081
|
] : []
|
|
4439
5082
|
]);
|
|
4440
5083
|
}
|
|
4441
5084
|
}
|
|
5085
|
+
isDelegateDiscriminator(fieldDef) {
|
|
5086
|
+
if (!fieldDef.originModel) {
|
|
5087
|
+
return false;
|
|
5088
|
+
}
|
|
5089
|
+
const discriminatorField = getDiscriminatorField(this.schema, fieldDef.originModel);
|
|
5090
|
+
return discriminatorField === fieldDef.name;
|
|
5091
|
+
}
|
|
4442
5092
|
makeRelationManipulationSchema(fieldDef, withoutFields, mode) {
|
|
4443
5093
|
const fieldType = fieldDef.type;
|
|
4444
5094
|
const array = !!fieldDef.array;
|
|
@@ -4455,31 +5105,31 @@ var InputValidator = class {
|
|
|
4455
5105
|
fields["disconnect"] = this.makeDisconnectDataSchema(fieldType, array).optional();
|
|
4456
5106
|
fields["delete"] = this.makeDeleteRelationDataSchema(fieldType, array, true).optional();
|
|
4457
5107
|
}
|
|
4458
|
-
fields["update"] = array ? this.orArray(z.
|
|
5108
|
+
fields["update"] = array ? this.orArray(z.strictObject({
|
|
4459
5109
|
where: this.makeWhereSchema(fieldType, true),
|
|
4460
5110
|
data: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
4461
5111
|
}), true).optional() : z.union([
|
|
4462
|
-
z.
|
|
5112
|
+
z.strictObject({
|
|
4463
5113
|
where: this.makeWhereSchema(fieldType, true),
|
|
4464
5114
|
data: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
4465
5115
|
}),
|
|
4466
5116
|
this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
4467
5117
|
]).optional();
|
|
4468
|
-
fields["upsert"] = this.orArray(z.
|
|
5118
|
+
fields["upsert"] = this.orArray(z.strictObject({
|
|
4469
5119
|
where: this.makeWhereSchema(fieldType, true),
|
|
4470
5120
|
create: this.makeCreateDataSchema(fieldType, false, withoutFields),
|
|
4471
5121
|
update: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
4472
5122
|
}), true).optional();
|
|
4473
5123
|
if (array) {
|
|
4474
5124
|
fields["set"] = this.makeSetDataSchema(fieldType, true).optional();
|
|
4475
|
-
fields["updateMany"] = this.orArray(z.
|
|
5125
|
+
fields["updateMany"] = this.orArray(z.strictObject({
|
|
4476
5126
|
where: this.makeWhereSchema(fieldType, false, true),
|
|
4477
5127
|
data: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
4478
5128
|
}), true).optional();
|
|
4479
5129
|
fields["deleteMany"] = this.makeDeleteRelationDataSchema(fieldType, true, false).optional();
|
|
4480
5130
|
}
|
|
4481
5131
|
}
|
|
4482
|
-
return z.
|
|
5132
|
+
return z.strictObject(fields);
|
|
4483
5133
|
}
|
|
4484
5134
|
makeSetDataSchema(model, canBeArray) {
|
|
4485
5135
|
return this.orArray(this.makeWhereSchema(model, true), canBeArray);
|
|
@@ -4509,13 +5159,13 @@ var InputValidator = class {
|
|
|
4509
5159
|
return this.orArray(z.object({
|
|
4510
5160
|
where: whereSchema,
|
|
4511
5161
|
create: createSchema
|
|
4512
|
-
})
|
|
5162
|
+
}), canBeArray);
|
|
4513
5163
|
}
|
|
4514
5164
|
makeCreateManyDataSchema(model, withoutFields) {
|
|
4515
5165
|
return z.object({
|
|
4516
5166
|
data: this.makeCreateDataSchema(model, true, withoutFields, true),
|
|
4517
5167
|
skipDuplicates: z.boolean().optional()
|
|
4518
|
-
})
|
|
5168
|
+
});
|
|
4519
5169
|
}
|
|
4520
5170
|
// #endregion
|
|
4521
5171
|
// #region Update
|
|
@@ -4526,19 +5176,19 @@ var InputValidator = class {
|
|
|
4526
5176
|
select: this.makeSelectSchema(model).optional(),
|
|
4527
5177
|
include: this.makeIncludeSchema(model).optional(),
|
|
4528
5178
|
omit: this.makeOmitSchema(model).optional()
|
|
4529
|
-
})
|
|
5179
|
+
});
|
|
4530
5180
|
return this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
4531
5181
|
}
|
|
4532
5182
|
makeUpdateManySchema(model) {
|
|
4533
5183
|
return z.object({
|
|
4534
5184
|
where: this.makeWhereSchema(model, false).optional(),
|
|
4535
5185
|
data: this.makeUpdateDataSchema(model, [], true),
|
|
4536
|
-
limit: z.
|
|
4537
|
-
})
|
|
5186
|
+
limit: z.int().nonnegative().optional()
|
|
5187
|
+
});
|
|
4538
5188
|
}
|
|
4539
5189
|
makeUpdateManyAndReturnSchema(model) {
|
|
4540
5190
|
const base = this.makeUpdateManySchema(model);
|
|
4541
|
-
const result = base.merge(z.
|
|
5191
|
+
const result = base.merge(z.strictObject({
|
|
4542
5192
|
select: this.makeSelectSchema(model).optional(),
|
|
4543
5193
|
omit: this.makeOmitSchema(model).optional()
|
|
4544
5194
|
}));
|
|
@@ -4552,12 +5202,12 @@ var InputValidator = class {
|
|
|
4552
5202
|
select: this.makeSelectSchema(model).optional(),
|
|
4553
5203
|
include: this.makeIncludeSchema(model).optional(),
|
|
4554
5204
|
omit: this.makeOmitSchema(model).optional()
|
|
4555
|
-
})
|
|
5205
|
+
});
|
|
4556
5206
|
return this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
4557
5207
|
}
|
|
4558
5208
|
makeUpdateDataSchema(model, withoutFields = [], withoutRelationFields = false) {
|
|
4559
|
-
const
|
|
4560
|
-
const
|
|
5209
|
+
const uncheckedVariantFields = {};
|
|
5210
|
+
const checkedVariantFields = {};
|
|
4561
5211
|
const modelDef = requireModel(this.schema, model);
|
|
4562
5212
|
const hasRelation = Object.entries(modelDef.fields).some(([key, value]) => value.relation && !withoutFields.includes(key));
|
|
4563
5213
|
Object.keys(modelDef.fields).forEach((field) => {
|
|
@@ -4582,7 +5232,10 @@ var InputValidator = class {
|
|
|
4582
5232
|
if (fieldDef.optional && !fieldDef.array) {
|
|
4583
5233
|
fieldSchema = fieldSchema.nullable();
|
|
4584
5234
|
}
|
|
4585
|
-
|
|
5235
|
+
checkedVariantFields[field] = fieldSchema;
|
|
5236
|
+
if (fieldDef.array || !fieldDef.relation.references) {
|
|
5237
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
5238
|
+
}
|
|
4586
5239
|
} else {
|
|
4587
5240
|
let fieldSchema = this.makePrimitiveSchema(fieldDef.type).optional();
|
|
4588
5241
|
if (this.isNumericField(fieldDef)) {
|
|
@@ -4609,18 +5262,18 @@ var InputValidator = class {
|
|
|
4609
5262
|
if (fieldDef.optional) {
|
|
4610
5263
|
fieldSchema = fieldSchema.nullable();
|
|
4611
5264
|
}
|
|
4612
|
-
|
|
5265
|
+
uncheckedVariantFields[field] = fieldSchema;
|
|
4613
5266
|
if (!fieldDef.foreignKeyFor) {
|
|
4614
|
-
|
|
5267
|
+
checkedVariantFields[field] = fieldSchema;
|
|
4615
5268
|
}
|
|
4616
5269
|
}
|
|
4617
5270
|
});
|
|
4618
5271
|
if (!hasRelation) {
|
|
4619
|
-
return z.
|
|
5272
|
+
return z.strictObject(uncheckedVariantFields);
|
|
4620
5273
|
} else {
|
|
4621
5274
|
return z.union([
|
|
4622
|
-
z.
|
|
4623
|
-
z.
|
|
5275
|
+
z.strictObject(uncheckedVariantFields),
|
|
5276
|
+
z.strictObject(checkedVariantFields)
|
|
4624
5277
|
]);
|
|
4625
5278
|
}
|
|
4626
5279
|
}
|
|
@@ -4631,25 +5284,25 @@ var InputValidator = class {
|
|
|
4631
5284
|
where: this.makeWhereSchema(model, true),
|
|
4632
5285
|
select: this.makeSelectSchema(model).optional(),
|
|
4633
5286
|
include: this.makeIncludeSchema(model).optional()
|
|
4634
|
-
})
|
|
5287
|
+
});
|
|
4635
5288
|
return this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
4636
5289
|
}
|
|
4637
5290
|
makeDeleteManySchema(model) {
|
|
4638
5291
|
return z.object({
|
|
4639
5292
|
where: this.makeWhereSchema(model, false).optional(),
|
|
4640
|
-
limit: z.
|
|
4641
|
-
}).
|
|
5293
|
+
limit: z.int().nonnegative().optional()
|
|
5294
|
+
}).optional();
|
|
4642
5295
|
}
|
|
4643
5296
|
// #endregion
|
|
4644
5297
|
// #region Count
|
|
4645
5298
|
makeCountSchema(model) {
|
|
4646
5299
|
return z.object({
|
|
4647
5300
|
where: this.makeWhereSchema(model, false).optional(),
|
|
4648
|
-
skip:
|
|
4649
|
-
take:
|
|
5301
|
+
skip: this.makeSkipSchema().optional(),
|
|
5302
|
+
take: this.makeTakeSchema().optional(),
|
|
4650
5303
|
orderBy: this.orArray(this.makeOrderBySchema(model, true, false), true).optional(),
|
|
4651
5304
|
select: this.makeCountAggregateInputSchema(model).optional()
|
|
4652
|
-
}).
|
|
5305
|
+
}).optional();
|
|
4653
5306
|
}
|
|
4654
5307
|
makeCountAggregateInputSchema(model) {
|
|
4655
5308
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -4661,7 +5314,7 @@ var InputValidator = class {
|
|
|
4661
5314
|
acc[field] = z.literal(true).optional();
|
|
4662
5315
|
return acc;
|
|
4663
5316
|
}, {})
|
|
4664
|
-
})
|
|
5317
|
+
})
|
|
4665
5318
|
]);
|
|
4666
5319
|
}
|
|
4667
5320
|
// #endregion
|
|
@@ -4669,19 +5322,19 @@ var InputValidator = class {
|
|
|
4669
5322
|
makeAggregateSchema(model) {
|
|
4670
5323
|
return z.object({
|
|
4671
5324
|
where: this.makeWhereSchema(model, false).optional(),
|
|
4672
|
-
skip:
|
|
4673
|
-
take:
|
|
5325
|
+
skip: this.makeSkipSchema().optional(),
|
|
5326
|
+
take: this.makeTakeSchema().optional(),
|
|
4674
5327
|
orderBy: this.orArray(this.makeOrderBySchema(model, true, false), true).optional(),
|
|
4675
5328
|
_count: this.makeCountAggregateInputSchema(model).optional(),
|
|
4676
5329
|
_avg: this.makeSumAvgInputSchema(model).optional(),
|
|
4677
5330
|
_sum: this.makeSumAvgInputSchema(model).optional(),
|
|
4678
5331
|
_min: this.makeMinMaxInputSchema(model).optional(),
|
|
4679
5332
|
_max: this.makeMinMaxInputSchema(model).optional()
|
|
4680
|
-
}).
|
|
5333
|
+
}).optional();
|
|
4681
5334
|
}
|
|
4682
5335
|
makeSumAvgInputSchema(model) {
|
|
4683
5336
|
const modelDef = requireModel(this.schema, model);
|
|
4684
|
-
return z.
|
|
5337
|
+
return z.strictObject(Object.keys(modelDef.fields).reduce((acc, field) => {
|
|
4685
5338
|
const fieldDef = requireField(this.schema, model, field);
|
|
4686
5339
|
if (this.isNumericField(fieldDef)) {
|
|
4687
5340
|
acc[field] = z.literal(true).optional();
|
|
@@ -4691,7 +5344,7 @@ var InputValidator = class {
|
|
|
4691
5344
|
}
|
|
4692
5345
|
makeMinMaxInputSchema(model) {
|
|
4693
5346
|
const modelDef = requireModel(this.schema, model);
|
|
4694
|
-
return z.
|
|
5347
|
+
return z.strictObject(Object.keys(modelDef.fields).reduce((acc, field) => {
|
|
4695
5348
|
const fieldDef = requireField(this.schema, model, field);
|
|
4696
5349
|
if (!fieldDef.relation && !fieldDef.array) {
|
|
4697
5350
|
acc[field] = z.literal(true).optional();
|
|
@@ -4706,30 +5359,42 @@ var InputValidator = class {
|
|
|
4706
5359
|
where: this.makeWhereSchema(model, false).optional(),
|
|
4707
5360
|
orderBy: this.orArray(this.makeOrderBySchema(model, false, true), true).optional(),
|
|
4708
5361
|
by: this.orArray(z.enum(nonRelationFields), true),
|
|
4709
|
-
having: this.
|
|
4710
|
-
skip:
|
|
4711
|
-
take:
|
|
5362
|
+
having: this.makeHavingSchema(model).optional(),
|
|
5363
|
+
skip: this.makeSkipSchema().optional(),
|
|
5364
|
+
take: this.makeTakeSchema().optional(),
|
|
4712
5365
|
_count: this.makeCountAggregateInputSchema(model).optional(),
|
|
4713
5366
|
_avg: this.makeSumAvgInputSchema(model).optional(),
|
|
4714
5367
|
_sum: this.makeSumAvgInputSchema(model).optional(),
|
|
4715
5368
|
_min: this.makeMinMaxInputSchema(model).optional(),
|
|
4716
5369
|
_max: this.makeMinMaxInputSchema(model).optional()
|
|
4717
|
-
})
|
|
5370
|
+
});
|
|
4718
5371
|
schema = schema.refine((value) => {
|
|
4719
5372
|
const bys = typeof value.by === "string" ? [
|
|
4720
5373
|
value.by
|
|
4721
5374
|
] : value.by;
|
|
4722
|
-
if (value.having &&
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
5375
|
+
if (value.having && typeof value.having === "object") {
|
|
5376
|
+
for (const [key, val] of Object.entries(value.having)) {
|
|
5377
|
+
if (AGGREGATE_OPERATORS.includes(key)) {
|
|
5378
|
+
continue;
|
|
5379
|
+
}
|
|
5380
|
+
if (bys.includes(key)) {
|
|
5381
|
+
continue;
|
|
5382
|
+
}
|
|
5383
|
+
if (!val || typeof val !== "object") {
|
|
5384
|
+
return false;
|
|
5385
|
+
}
|
|
5386
|
+
if (!this.onlyAggregationFields(val)) {
|
|
5387
|
+
return false;
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
4726
5390
|
}
|
|
5391
|
+
return true;
|
|
4727
5392
|
}, 'fields in "having" must be in "by"');
|
|
4728
5393
|
schema = schema.refine((value) => {
|
|
4729
5394
|
const bys = typeof value.by === "string" ? [
|
|
4730
5395
|
value.by
|
|
4731
5396
|
] : value.by;
|
|
4732
|
-
if (value.orderBy && Object.keys(value.orderBy).filter((f) => !
|
|
5397
|
+
if (value.orderBy && Object.keys(value.orderBy).filter((f) => !AGGREGATE_OPERATORS.includes(f)).some((key) => !bys.includes(key))) {
|
|
4733
5398
|
return false;
|
|
4734
5399
|
} else {
|
|
4735
5400
|
return true;
|
|
@@ -4737,8 +5402,31 @@ var InputValidator = class {
|
|
|
4737
5402
|
}, 'fields in "orderBy" must be in "by"');
|
|
4738
5403
|
return schema;
|
|
4739
5404
|
}
|
|
5405
|
+
onlyAggregationFields(val) {
|
|
5406
|
+
for (const [key, value] of Object.entries(val)) {
|
|
5407
|
+
if (AGGREGATE_OPERATORS.includes(key)) {
|
|
5408
|
+
continue;
|
|
5409
|
+
}
|
|
5410
|
+
if (LOGICAL_COMBINATORS.includes(key)) {
|
|
5411
|
+
if (enumerate(value).every((v) => this.onlyAggregationFields(v))) {
|
|
5412
|
+
continue;
|
|
5413
|
+
}
|
|
5414
|
+
}
|
|
5415
|
+
return false;
|
|
5416
|
+
}
|
|
5417
|
+
return true;
|
|
5418
|
+
}
|
|
5419
|
+
makeHavingSchema(model) {
|
|
5420
|
+
return this.makeWhereSchema(model, false, true, true);
|
|
5421
|
+
}
|
|
4740
5422
|
// #endregion
|
|
4741
5423
|
// #region Helpers
|
|
5424
|
+
makeSkipSchema() {
|
|
5425
|
+
return z.int().nonnegative();
|
|
5426
|
+
}
|
|
5427
|
+
makeTakeSchema() {
|
|
5428
|
+
return z.int();
|
|
5429
|
+
}
|
|
4742
5430
|
refineForSelectIncludeMutuallyExclusive(schema) {
|
|
4743
5431
|
return schema.refine((value) => !(value["select"] && value["include"]), '"select" and "include" cannot be used together');
|
|
4744
5432
|
}
|
|
@@ -4757,6 +5445,9 @@ var InputValidator = class {
|
|
|
4757
5445
|
isNumericField(fieldDef) {
|
|
4758
5446
|
return NUMERIC_FIELD_TYPES.includes(fieldDef.type) && !fieldDef.array;
|
|
4759
5447
|
}
|
|
5448
|
+
get providerSupportsCaseSensitivity() {
|
|
5449
|
+
return this.schema.provider.type === "postgresql";
|
|
5450
|
+
}
|
|
4760
5451
|
};
|
|
4761
5452
|
|
|
4762
5453
|
// src/client/executor/zenstack-driver.ts
|
|
@@ -4766,11 +5457,11 @@ var ZenStackDriver = class {
|
|
|
4766
5457
|
}
|
|
4767
5458
|
#driver;
|
|
4768
5459
|
#log;
|
|
4769
|
-
txConnection;
|
|
4770
5460
|
#initPromise;
|
|
4771
5461
|
#initDone;
|
|
4772
5462
|
#destroyPromise;
|
|
4773
5463
|
#connections = /* @__PURE__ */ new WeakSet();
|
|
5464
|
+
#txConnections = /* @__PURE__ */ new WeakMap();
|
|
4774
5465
|
constructor(driver, log) {
|
|
4775
5466
|
this.#initDone = false;
|
|
4776
5467
|
this.#driver = driver;
|
|
@@ -4811,21 +5502,30 @@ var ZenStackDriver = class {
|
|
|
4811
5502
|
}
|
|
4812
5503
|
async beginTransaction(connection, settings) {
|
|
4813
5504
|
const result = await this.#driver.beginTransaction(connection, settings);
|
|
4814
|
-
this.
|
|
5505
|
+
this.#txConnections.set(connection, []);
|
|
4815
5506
|
return result;
|
|
4816
5507
|
}
|
|
4817
|
-
commitTransaction(connection) {
|
|
5508
|
+
async commitTransaction(connection) {
|
|
4818
5509
|
try {
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
this.
|
|
5510
|
+
const result = await this.#driver.commitTransaction(connection);
|
|
5511
|
+
const callbacks = this.#txConnections.get(connection);
|
|
5512
|
+
this.#txConnections.delete(connection);
|
|
5513
|
+
if (callbacks) {
|
|
5514
|
+
for (const callback of callbacks) {
|
|
5515
|
+
await callback();
|
|
5516
|
+
}
|
|
5517
|
+
}
|
|
5518
|
+
return result;
|
|
5519
|
+
} catch (err) {
|
|
5520
|
+
this.#txConnections.delete(connection);
|
|
5521
|
+
throw err;
|
|
4822
5522
|
}
|
|
4823
5523
|
}
|
|
4824
|
-
rollbackTransaction(connection) {
|
|
5524
|
+
async rollbackTransaction(connection) {
|
|
4825
5525
|
try {
|
|
4826
|
-
return this.#driver.rollbackTransaction(connection);
|
|
5526
|
+
return await this.#driver.rollbackTransaction(connection);
|
|
4827
5527
|
} finally {
|
|
4828
|
-
this.
|
|
5528
|
+
this.#txConnections.delete(connection);
|
|
4829
5529
|
}
|
|
4830
5530
|
}
|
|
4831
5531
|
async destroy() {
|
|
@@ -4903,6 +5603,22 @@ var ZenStackDriver = class {
|
|
|
4903
5603
|
#calculateDurationMillis(startTime) {
|
|
4904
5604
|
return performanceNow() - startTime;
|
|
4905
5605
|
}
|
|
5606
|
+
isTransactionConnection(connection) {
|
|
5607
|
+
return this.#txConnections.has(connection);
|
|
5608
|
+
}
|
|
5609
|
+
registerTransactionCommitCallback(connection, callback) {
|
|
5610
|
+
if (!this.#txConnections.has(connection)) {
|
|
5611
|
+
return;
|
|
5612
|
+
}
|
|
5613
|
+
const callbacks = this.#txConnections.get(connection);
|
|
5614
|
+
if (callbacks) {
|
|
5615
|
+
callbacks.push(callback);
|
|
5616
|
+
} else {
|
|
5617
|
+
this.#txConnections.set(connection, [
|
|
5618
|
+
callback
|
|
5619
|
+
]);
|
|
5620
|
+
}
|
|
5621
|
+
}
|
|
4906
5622
|
};
|
|
4907
5623
|
function performanceNow() {
|
|
4908
5624
|
if (typeof performance !== "undefined" && typeof performance.now === "function") {
|
|
@@ -4914,9 +5630,10 @@ function performanceNow() {
|
|
|
4914
5630
|
__name(performanceNow, "performanceNow");
|
|
4915
5631
|
|
|
4916
5632
|
// 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,
|
|
5633
|
+
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
5634
|
import { nanoid as nanoid2 } from "nanoid";
|
|
4919
|
-
import {
|
|
5635
|
+
import { inspect as inspect2 } from "util";
|
|
5636
|
+
import { match as match16 } from "ts-pattern";
|
|
4920
5637
|
|
|
4921
5638
|
// src/client/executor/name-mapper.ts
|
|
4922
5639
|
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 +5642,11 @@ var QueryNameMapper = class extends OperationNodeTransformer2 {
|
|
|
4925
5642
|
__name(this, "QueryNameMapper");
|
|
4926
5643
|
}
|
|
4927
5644
|
schema;
|
|
4928
|
-
modelToTableMap;
|
|
4929
|
-
fieldToColumnMap;
|
|
4930
|
-
modelStack;
|
|
5645
|
+
modelToTableMap = /* @__PURE__ */ new Map();
|
|
5646
|
+
fieldToColumnMap = /* @__PURE__ */ new Map();
|
|
5647
|
+
modelStack = [];
|
|
4931
5648
|
constructor(schema) {
|
|
4932
|
-
super(), this.schema = schema
|
|
5649
|
+
super(), this.schema = schema;
|
|
4933
5650
|
for (const [modelName, modelDef] of Object.entries(schema.models)) {
|
|
4934
5651
|
const mappedName = this.getMappedName(modelDef);
|
|
4935
5652
|
if (mappedName) {
|
|
@@ -5118,7 +5835,7 @@ var QueryNameMapper = class extends OperationNodeTransformer2 {
|
|
|
5118
5835
|
this.requireCurrentModel(contextNode);
|
|
5119
5836
|
model = model ?? this.currentModel;
|
|
5120
5837
|
const modelDef = requireModel(this.schema, model);
|
|
5121
|
-
const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed).map(([fieldName]) => fieldName);
|
|
5838
|
+
const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed && !fieldDef.originModel).map(([fieldName]) => fieldName);
|
|
5122
5839
|
return scalarFields;
|
|
5123
5840
|
}
|
|
5124
5841
|
};
|
|
@@ -5143,16 +5860,18 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5143
5860
|
get options() {
|
|
5144
5861
|
return this.client.$options;
|
|
5145
5862
|
}
|
|
5146
|
-
async executeQuery(compiledQuery,
|
|
5863
|
+
async executeQuery(compiledQuery, _queryId) {
|
|
5147
5864
|
let queryNode = compiledQuery.query;
|
|
5148
5865
|
let mutationInterceptionInfo;
|
|
5149
5866
|
if (this.isMutationNode(queryNode) && this.hasMutationHooks) {
|
|
5150
5867
|
mutationInterceptionInfo = await this.callMutationInterceptionFilters(queryNode);
|
|
5151
5868
|
}
|
|
5152
5869
|
const task = /* @__PURE__ */ __name(async () => {
|
|
5153
|
-
|
|
5870
|
+
if (this.isMutationNode(queryNode)) {
|
|
5871
|
+
await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
|
|
5872
|
+
}
|
|
5154
5873
|
const oldQueryNode = queryNode;
|
|
5155
|
-
if ((InsertQueryNode2.is(queryNode) ||
|
|
5874
|
+
if ((InsertQueryNode2.is(queryNode) || UpdateQueryNode2.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
|
|
5156
5875
|
queryNode = {
|
|
5157
5876
|
...queryNode,
|
|
5158
5877
|
returning: ReturningNode3.create([
|
|
@@ -5160,42 +5879,73 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5160
5879
|
])
|
|
5161
5880
|
};
|
|
5162
5881
|
}
|
|
5163
|
-
const
|
|
5164
|
-
await this.
|
|
5882
|
+
const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
|
|
5883
|
+
const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams);
|
|
5884
|
+
if (this.isMutationNode(queryNode)) {
|
|
5885
|
+
await this.callAfterMutationHooks(result.result, queryNode, mutationInterceptionInfo, result.connection);
|
|
5886
|
+
}
|
|
5165
5887
|
if (oldQueryNode !== queryNode) {
|
|
5166
5888
|
}
|
|
5167
|
-
return result;
|
|
5889
|
+
return result.result;
|
|
5168
5890
|
}, "task");
|
|
5169
|
-
return
|
|
5170
|
-
}
|
|
5171
|
-
proceedQueryWithKyselyInterceptors(queryNode,
|
|
5172
|
-
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q,
|
|
5173
|
-
const
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5891
|
+
return task();
|
|
5892
|
+
}
|
|
5893
|
+
proceedQueryWithKyselyInterceptors(queryNode, parameters) {
|
|
5894
|
+
let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters), "proceed");
|
|
5895
|
+
const hooks = [];
|
|
5896
|
+
for (const plugin of this.client.$options.plugins ?? []) {
|
|
5897
|
+
if (plugin.onKyselyQuery) {
|
|
5898
|
+
hooks.push(plugin.onKyselyQuery.bind(plugin));
|
|
5899
|
+
}
|
|
5900
|
+
}
|
|
5177
5901
|
for (const hook of hooks) {
|
|
5178
5902
|
const _proceed = proceed;
|
|
5179
|
-
proceed = /* @__PURE__ */ __name((query) => {
|
|
5180
|
-
|
|
5903
|
+
proceed = /* @__PURE__ */ __name(async (query) => {
|
|
5904
|
+
let connection;
|
|
5905
|
+
const _p = /* @__PURE__ */ __name(async (q) => {
|
|
5906
|
+
const r = await _proceed(q);
|
|
5907
|
+
connection = r.connection;
|
|
5908
|
+
return r.result;
|
|
5909
|
+
}, "_p");
|
|
5910
|
+
const hookResult = await hook({
|
|
5181
5911
|
client: this.client,
|
|
5182
5912
|
schema: this.client.$schema,
|
|
5183
5913
|
kysely: this.kysely,
|
|
5184
5914
|
query,
|
|
5185
|
-
proceed:
|
|
5186
|
-
transaction: makeTx(_proceed)
|
|
5915
|
+
proceed: _p
|
|
5187
5916
|
});
|
|
5917
|
+
return {
|
|
5918
|
+
result: hookResult,
|
|
5919
|
+
connection
|
|
5920
|
+
};
|
|
5188
5921
|
}, "proceed");
|
|
5189
5922
|
}
|
|
5190
5923
|
return proceed(queryNode);
|
|
5191
5924
|
}
|
|
5192
|
-
async proceedQuery(query,
|
|
5925
|
+
async proceedQuery(query, parameters) {
|
|
5193
5926
|
const finalQuery = this.nameMapper.transformNode(query);
|
|
5194
|
-
|
|
5927
|
+
let compiled = this.compileQuery(finalQuery);
|
|
5928
|
+
if (parameters) {
|
|
5929
|
+
compiled = {
|
|
5930
|
+
...compiled,
|
|
5931
|
+
parameters
|
|
5932
|
+
};
|
|
5933
|
+
}
|
|
5195
5934
|
try {
|
|
5196
|
-
return
|
|
5935
|
+
return await this.provideConnection(async (connection) => {
|
|
5936
|
+
const result = await connection.executeQuery(compiled);
|
|
5937
|
+
return {
|
|
5938
|
+
result,
|
|
5939
|
+
connection
|
|
5940
|
+
};
|
|
5941
|
+
});
|
|
5197
5942
|
} catch (err) {
|
|
5198
|
-
|
|
5943
|
+
let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
|
|
5944
|
+
if (this.options.debug) {
|
|
5945
|
+
message += `, parameters:
|
|
5946
|
+
${compiled.parameters.map((p) => inspect2(p)).join("\n")}`;
|
|
5947
|
+
}
|
|
5948
|
+
throw new QueryError(message, err);
|
|
5199
5949
|
}
|
|
5200
5950
|
}
|
|
5201
5951
|
isMutationNode(queryNode) {
|
|
@@ -5223,30 +5973,15 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5223
5973
|
return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, []);
|
|
5224
5974
|
}
|
|
5225
5975
|
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
|
-
}
|
|
5976
|
+
const newExecutor = new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
|
|
5977
|
+
newExecutor.client = this.client.withExecutor(newExecutor);
|
|
5978
|
+
return newExecutor;
|
|
5244
5979
|
}
|
|
5245
5980
|
get hasMutationHooks() {
|
|
5246
5981
|
return this.client.$options.plugins?.some((plugin) => plugin.beforeEntityMutation || plugin.afterEntityMutation);
|
|
5247
5982
|
}
|
|
5248
5983
|
getMutationModel(queryNode) {
|
|
5249
|
-
return
|
|
5984
|
+
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
5985
|
if (node.from.froms.length !== 1) {
|
|
5251
5986
|
throw new InternalError(`Delete query must have exactly one from table`);
|
|
5252
5987
|
}
|
|
@@ -5262,7 +5997,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5262
5997
|
const result = {
|
|
5263
5998
|
intercept: false
|
|
5264
5999
|
};
|
|
5265
|
-
const { action, where } =
|
|
6000
|
+
const { action, where } = match16(queryNode).when(InsertQueryNode2.is, () => ({
|
|
5266
6001
|
action: "create",
|
|
5267
6002
|
where: void 0
|
|
5268
6003
|
})).when(UpdateQueryNode2.is, (node) => ({
|
|
@@ -5282,14 +6017,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5282
6017
|
queryNode
|
|
5283
6018
|
});
|
|
5284
6019
|
result.intercept ||= filterResult.intercept;
|
|
5285
|
-
result.useTransactionForMutation ||= filterResult.useTransactionForMutation;
|
|
5286
6020
|
result.loadBeforeMutationEntity ||= filterResult.loadBeforeMutationEntity;
|
|
5287
6021
|
result.loadAfterMutationEntity ||= filterResult.loadAfterMutationEntity;
|
|
5288
6022
|
}
|
|
5289
6023
|
}
|
|
5290
6024
|
let beforeMutationEntities;
|
|
5291
6025
|
if (result.loadBeforeMutationEntity && (UpdateQueryNode2.is(queryNode) || DeleteQueryNode2.is(queryNode))) {
|
|
5292
|
-
beforeMutationEntities = await this.loadEntities(
|
|
6026
|
+
beforeMutationEntities = await this.loadEntities(mutationModel, where);
|
|
5293
6027
|
}
|
|
5294
6028
|
return {
|
|
5295
6029
|
...result,
|
|
@@ -5302,16 +6036,16 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5302
6036
|
return void 0;
|
|
5303
6037
|
}
|
|
5304
6038
|
}
|
|
5305
|
-
callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
6039
|
+
async callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
|
|
5306
6040
|
if (!mutationInterceptionInfo?.intercept) {
|
|
5307
6041
|
return;
|
|
5308
6042
|
}
|
|
5309
6043
|
if (this.options.plugins) {
|
|
6044
|
+
const mutationModel = this.getMutationModel(queryNode);
|
|
5310
6045
|
for (const plugin of this.options.plugins) {
|
|
5311
6046
|
if (plugin.beforeEntityMutation) {
|
|
5312
|
-
plugin.beforeEntityMutation({
|
|
5313
|
-
|
|
5314
|
-
model: this.getMutationModel(queryNode),
|
|
6047
|
+
await plugin.beforeEntityMutation({
|
|
6048
|
+
model: mutationModel,
|
|
5315
6049
|
action: mutationInterceptionInfo.action,
|
|
5316
6050
|
queryNode,
|
|
5317
6051
|
entities: mutationInterceptionInfo.beforeMutationEntities
|
|
@@ -5320,44 +6054,59 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5320
6054
|
}
|
|
5321
6055
|
}
|
|
5322
6056
|
}
|
|
5323
|
-
async
|
|
6057
|
+
async callAfterMutationHooks(queryResult, queryNode, mutationInterceptionInfo, connection) {
|
|
5324
6058
|
if (!mutationInterceptionInfo?.intercept) {
|
|
5325
6059
|
return;
|
|
5326
6060
|
}
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
6061
|
+
const hooks = [];
|
|
6062
|
+
for (const plugin of this.options.plugins ?? []) {
|
|
6063
|
+
if (plugin.afterEntityMutation) {
|
|
6064
|
+
hooks.push(plugin.afterEntityMutation.bind(plugin));
|
|
6065
|
+
}
|
|
6066
|
+
}
|
|
6067
|
+
if (hooks.length === 0) {
|
|
6068
|
+
return;
|
|
6069
|
+
}
|
|
6070
|
+
const mutationModel = this.getMutationModel(queryNode);
|
|
6071
|
+
const inTransaction = this.driver.isTransactionConnection(connection);
|
|
6072
|
+
for (const hook of hooks) {
|
|
6073
|
+
let afterMutationEntities = void 0;
|
|
6074
|
+
if (mutationInterceptionInfo.loadAfterMutationEntity) {
|
|
6075
|
+
if (InsertQueryNode2.is(queryNode) || UpdateQueryNode2.is(queryNode)) {
|
|
6076
|
+
afterMutationEntities = queryResult.rows;
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
6079
|
+
const action = /* @__PURE__ */ __name(async () => {
|
|
6080
|
+
try {
|
|
6081
|
+
await hook({
|
|
6082
|
+
model: mutationModel,
|
|
5341
6083
|
action: mutationInterceptionInfo.action,
|
|
5342
6084
|
queryNode,
|
|
5343
6085
|
beforeMutationEntities: mutationInterceptionInfo.beforeMutationEntities,
|
|
5344
6086
|
afterMutationEntities
|
|
5345
6087
|
});
|
|
6088
|
+
} catch (err) {
|
|
6089
|
+
console.error(`Error in afterEntityMutation hook for model "${mutationModel}": ${err}`);
|
|
5346
6090
|
}
|
|
6091
|
+
}, "action");
|
|
6092
|
+
if (inTransaction) {
|
|
6093
|
+
this.driver.registerTransactionCommitCallback(connection, action);
|
|
6094
|
+
} else {
|
|
6095
|
+
await action();
|
|
5347
6096
|
}
|
|
5348
6097
|
}
|
|
5349
6098
|
}
|
|
5350
|
-
async loadEntities(
|
|
5351
|
-
const selectQuery = kysely.selectFrom(model).selectAll();
|
|
6099
|
+
async loadEntities(model, where) {
|
|
6100
|
+
const selectQuery = this.kysely.selectFrom(model).selectAll();
|
|
5352
6101
|
let selectQueryNode = selectQuery.toOperationNode();
|
|
5353
6102
|
selectQueryNode = {
|
|
5354
6103
|
...selectQueryNode,
|
|
5355
6104
|
where: this.andNodes(selectQueryNode.where, where)
|
|
5356
6105
|
};
|
|
5357
|
-
const compiled =
|
|
6106
|
+
const compiled = this.compileQuery(selectQueryNode);
|
|
6107
|
+
const result = await this.executeQuery(compiled, {
|
|
5358
6108
|
queryId: `zenstack-${nanoid2()}`
|
|
5359
6109
|
});
|
|
5360
|
-
const result = await kysely.executeQuery(compiled);
|
|
5361
6110
|
return result.rows;
|
|
5362
6111
|
}
|
|
5363
6112
|
andNodes(condition1, condition2) {
|
|
@@ -5386,9 +6135,9 @@ __export(functions_exports, {
|
|
|
5386
6135
|
search: () => search,
|
|
5387
6136
|
startsWith: () => startsWith
|
|
5388
6137
|
});
|
|
6138
|
+
import { invariant as invariant9, lowerCaseFirst, upperCaseFirst } from "@zenstackhq/common-helpers";
|
|
5389
6139
|
import { sql as sql8, ValueNode as ValueNode4 } from "kysely";
|
|
5390
|
-
import
|
|
5391
|
-
import { match as match16 } from "ts-pattern";
|
|
6140
|
+
import { match as match17 } from "ts-pattern";
|
|
5392
6141
|
var contains = /* @__PURE__ */ __name((eb, args) => {
|
|
5393
6142
|
const [field, search2, caseInsensitive = false] = args;
|
|
5394
6143
|
if (!field) {
|
|
@@ -5473,7 +6222,7 @@ var isEmpty = /* @__PURE__ */ __name((eb, args, { dialect }) => {
|
|
|
5473
6222
|
return eb(dialect.buildArrayLength(eb, field), "=", sql8.lit(0));
|
|
5474
6223
|
}, "isEmpty");
|
|
5475
6224
|
var now = /* @__PURE__ */ __name((eb, _args, { dialect }) => {
|
|
5476
|
-
return
|
|
6225
|
+
return match17(dialect.provider).with("postgresql", () => eb.fn("now")).with("sqlite", () => sql8.raw("CURRENT_TIMESTAMP")).exhaustive();
|
|
5477
6226
|
}, "now");
|
|
5478
6227
|
var currentModel = /* @__PURE__ */ __name((_eb, args, { model }) => {
|
|
5479
6228
|
let result = model;
|
|
@@ -5493,8 +6242,8 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
|
5493
6242
|
}, "currentOperation");
|
|
5494
6243
|
function processCasing(casing, result, model) {
|
|
5495
6244
|
const opNode = casing.toOperationNode();
|
|
5496
|
-
|
|
5497
|
-
result =
|
|
6245
|
+
invariant9(ValueNode4.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
|
|
6246
|
+
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
6247
|
throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
|
|
5499
6248
|
});
|
|
5500
6249
|
return result;
|
|
@@ -5502,9 +6251,9 @@ function processCasing(casing, result, model) {
|
|
|
5502
6251
|
__name(processCasing, "processCasing");
|
|
5503
6252
|
|
|
5504
6253
|
// src/client/helpers/schema-db-pusher.ts
|
|
6254
|
+
import { invariant as invariant10 } from "@zenstackhq/common-helpers";
|
|
5505
6255
|
import { sql as sql9 } from "kysely";
|
|
5506
|
-
import
|
|
5507
|
-
import { match as match17 } from "ts-pattern";
|
|
6256
|
+
import { match as match18 } from "ts-pattern";
|
|
5508
6257
|
var SchemaDbPusher = class {
|
|
5509
6258
|
static {
|
|
5510
6259
|
__name(this, "SchemaDbPusher");
|
|
@@ -5535,14 +6284,17 @@ var SchemaDbPusher = class {
|
|
|
5535
6284
|
for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
|
|
5536
6285
|
if (fieldDef.relation) {
|
|
5537
6286
|
table = this.addForeignKeyConstraint(table, model, fieldName, fieldDef);
|
|
5538
|
-
} else {
|
|
6287
|
+
} else if (!this.isComputedField(fieldDef)) {
|
|
5539
6288
|
table = this.createModelField(table, fieldName, fieldDef, modelDef);
|
|
5540
6289
|
}
|
|
5541
6290
|
}
|
|
5542
6291
|
table = this.addPrimaryKeyConstraint(table, model, modelDef);
|
|
5543
|
-
table = this.addUniqueConstraint(table, modelDef);
|
|
6292
|
+
table = this.addUniqueConstraint(table, model, modelDef);
|
|
5544
6293
|
return table;
|
|
5545
6294
|
}
|
|
6295
|
+
isComputedField(fieldDef) {
|
|
6296
|
+
return fieldDef.attributes?.some((a) => a.name === "@computed");
|
|
6297
|
+
}
|
|
5546
6298
|
addPrimaryKeyConstraint(table, model, modelDef) {
|
|
5547
6299
|
if (modelDef.idFields.length === 1) {
|
|
5548
6300
|
if (Object.values(modelDef.fields).some((f) => f.id)) {
|
|
@@ -5554,16 +6306,19 @@ var SchemaDbPusher = class {
|
|
|
5554
6306
|
}
|
|
5555
6307
|
return table;
|
|
5556
6308
|
}
|
|
5557
|
-
addUniqueConstraint(table, modelDef) {
|
|
6309
|
+
addUniqueConstraint(table, model, modelDef) {
|
|
5558
6310
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
5559
|
-
|
|
6311
|
+
invariant10(typeof value === "object", "expecting an object");
|
|
5560
6312
|
if ("type" in value) {
|
|
5561
6313
|
const fieldDef = modelDef.fields[key];
|
|
5562
6314
|
if (fieldDef.unique) {
|
|
5563
6315
|
continue;
|
|
5564
6316
|
}
|
|
6317
|
+
table = table.addUniqueConstraint(`unique_${model}_${key}`, [
|
|
6318
|
+
key
|
|
6319
|
+
]);
|
|
5565
6320
|
} else {
|
|
5566
|
-
table = table.addUniqueConstraint(`unique_${key}`, Object.keys(value));
|
|
6321
|
+
table = table.addUniqueConstraint(`unique_${model}_${key}`, Object.keys(value));
|
|
5567
6322
|
}
|
|
5568
6323
|
}
|
|
5569
6324
|
return table;
|
|
@@ -5602,7 +6357,7 @@ var SchemaDbPusher = class {
|
|
|
5602
6357
|
return "serial";
|
|
5603
6358
|
}
|
|
5604
6359
|
const type = fieldDef.type;
|
|
5605
|
-
const result =
|
|
6360
|
+
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
6361
|
throw new Error(`Unsupported field type: ${type}`);
|
|
5607
6362
|
});
|
|
5608
6363
|
if (fieldDef.array) {
|
|
@@ -5615,7 +6370,7 @@ var SchemaDbPusher = class {
|
|
|
5615
6370
|
return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
|
|
5616
6371
|
}
|
|
5617
6372
|
addForeignKeyConstraint(table, model, fieldName, fieldDef) {
|
|
5618
|
-
|
|
6373
|
+
invariant10(fieldDef.relation, "field must be a relation");
|
|
5619
6374
|
if (!fieldDef.relation.fields || !fieldDef.relation.references) {
|
|
5620
6375
|
return table;
|
|
5621
6376
|
}
|
|
@@ -5631,16 +6386,16 @@ var SchemaDbPusher = class {
|
|
|
5631
6386
|
return table;
|
|
5632
6387
|
}
|
|
5633
6388
|
mapCascadeAction(action) {
|
|
5634
|
-
return
|
|
6389
|
+
return match18(action).with("SetNull", () => "set null").with("Cascade", () => "cascade").with("Restrict", () => "restrict").with("NoAction", () => "no action").with("SetDefault", () => "set default").exhaustive();
|
|
5635
6390
|
}
|
|
5636
6391
|
};
|
|
5637
6392
|
|
|
5638
6393
|
// src/client/promise.ts
|
|
5639
|
-
function
|
|
6394
|
+
function createZenStackPromise(callback) {
|
|
5640
6395
|
let promise;
|
|
5641
|
-
const cb = /* @__PURE__ */ __name(() => {
|
|
6396
|
+
const cb = /* @__PURE__ */ __name((txClient) => {
|
|
5642
6397
|
try {
|
|
5643
|
-
return promise ??= valueToPromise(callback());
|
|
6398
|
+
return promise ??= valueToPromise(callback(txClient));
|
|
5644
6399
|
} catch (err) {
|
|
5645
6400
|
return Promise.reject(err);
|
|
5646
6401
|
}
|
|
@@ -5655,10 +6410,11 @@ function createDeferredPromise(callback) {
|
|
|
5655
6410
|
finally(onFinally) {
|
|
5656
6411
|
return cb().finally(onFinally);
|
|
5657
6412
|
},
|
|
6413
|
+
cb,
|
|
5658
6414
|
[Symbol.toStringTag]: "ZenStackPromise"
|
|
5659
6415
|
};
|
|
5660
6416
|
}
|
|
5661
|
-
__name(
|
|
6417
|
+
__name(createZenStackPromise, "createZenStackPromise");
|
|
5662
6418
|
function valueToPromise(thing) {
|
|
5663
6419
|
if (typeof thing === "object" && typeof thing?.then === "function") {
|
|
5664
6420
|
return thing;
|
|
@@ -5669,9 +6425,9 @@ function valueToPromise(thing) {
|
|
|
5669
6425
|
__name(valueToPromise, "valueToPromise");
|
|
5670
6426
|
|
|
5671
6427
|
// src/client/result-processor.ts
|
|
6428
|
+
import { invariant as invariant11 } from "@zenstackhq/common-helpers";
|
|
5672
6429
|
import Decimal2 from "decimal.js";
|
|
5673
|
-
import
|
|
5674
|
-
import { match as match18 } from "ts-pattern";
|
|
6430
|
+
import { match as match19 } from "ts-pattern";
|
|
5675
6431
|
var ResultProcessor = class {
|
|
5676
6432
|
static {
|
|
5677
6433
|
__name(this, "ResultProcessor");
|
|
@@ -5705,6 +6461,21 @@ var ResultProcessor = class {
|
|
|
5705
6461
|
data[key] = typeof value === "string" ? JSON.parse(value) : value;
|
|
5706
6462
|
continue;
|
|
5707
6463
|
}
|
|
6464
|
+
if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
|
|
6465
|
+
if (value) {
|
|
6466
|
+
const subRow = this.transformJson(value);
|
|
6467
|
+
const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
|
|
6468
|
+
const idValues = getIdValues(this.schema, subModel, subRow);
|
|
6469
|
+
if (Object.values(idValues).some((v) => v === null || v === void 0)) {
|
|
6470
|
+
delete data[key];
|
|
6471
|
+
continue;
|
|
6472
|
+
}
|
|
6473
|
+
const processedSubRow = this.processRow(subRow, subModel);
|
|
6474
|
+
Object.assign(data, processedSubRow);
|
|
6475
|
+
}
|
|
6476
|
+
delete data[key];
|
|
6477
|
+
continue;
|
|
6478
|
+
}
|
|
5708
6479
|
const fieldDef = getField(this.schema, model, key);
|
|
5709
6480
|
if (!fieldDef) {
|
|
5710
6481
|
continue;
|
|
@@ -5744,20 +6515,24 @@ var ResultProcessor = class {
|
|
|
5744
6515
|
return this.doProcessResult(relationData, fieldDef.type);
|
|
5745
6516
|
}
|
|
5746
6517
|
transformScalar(value, type) {
|
|
5747
|
-
|
|
6518
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
6519
|
+
return this.transformJson(value);
|
|
6520
|
+
} else {
|
|
6521
|
+
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);
|
|
6522
|
+
}
|
|
5748
6523
|
}
|
|
5749
6524
|
transformDecimal(value) {
|
|
5750
6525
|
if (value instanceof Decimal2) {
|
|
5751
6526
|
return value;
|
|
5752
6527
|
}
|
|
5753
|
-
|
|
6528
|
+
invariant11(typeof value === "string" || typeof value === "number" || value instanceof Decimal2, `Expected string, number or Decimal, got ${typeof value}`);
|
|
5754
6529
|
return new Decimal2(value);
|
|
5755
6530
|
}
|
|
5756
6531
|
transformBigInt(value) {
|
|
5757
6532
|
if (typeof value === "bigint") {
|
|
5758
6533
|
return value;
|
|
5759
6534
|
}
|
|
5760
|
-
|
|
6535
|
+
invariant11(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
5761
6536
|
return BigInt(value);
|
|
5762
6537
|
}
|
|
5763
6538
|
transformBoolean(value) {
|
|
@@ -5776,6 +6551,9 @@ var ResultProcessor = class {
|
|
|
5776
6551
|
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
5777
6552
|
}
|
|
5778
6553
|
fixReversedResult(data, model, args) {
|
|
6554
|
+
if (!data) {
|
|
6555
|
+
return;
|
|
6556
|
+
}
|
|
5779
6557
|
if (Array.isArray(data) && typeof args === "object" && args && args.take !== void 0 && args.take < 0) {
|
|
5780
6558
|
data.reverse();
|
|
5781
6559
|
}
|
|
@@ -5789,13 +6567,19 @@ var ResultProcessor = class {
|
|
|
5789
6567
|
continue;
|
|
5790
6568
|
}
|
|
5791
6569
|
const fieldDef = getField(this.schema, model, field);
|
|
5792
|
-
if (!fieldDef
|
|
6570
|
+
if (!fieldDef || !fieldDef.relation || !fieldDef.array) {
|
|
5793
6571
|
continue;
|
|
5794
6572
|
}
|
|
5795
6573
|
this.fixReversedResult(row[field], fieldDef.type, value);
|
|
5796
6574
|
}
|
|
5797
6575
|
}
|
|
5798
6576
|
}
|
|
6577
|
+
transformJson(value) {
|
|
6578
|
+
return match19(this.schema.provider.type).with("sqlite", () => {
|
|
6579
|
+
invariant11(typeof value === "string", "Expected string, got " + typeof value);
|
|
6580
|
+
return JSON.parse(value);
|
|
6581
|
+
}).otherwise(() => value);
|
|
6582
|
+
}
|
|
5799
6583
|
};
|
|
5800
6584
|
|
|
5801
6585
|
// src/client/client-impl.ts
|
|
@@ -5814,7 +6598,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
5814
6598
|
$schema;
|
|
5815
6599
|
kyselyProps;
|
|
5816
6600
|
auth;
|
|
5817
|
-
constructor(schema, options, baseClient) {
|
|
6601
|
+
constructor(schema, options, baseClient, executor) {
|
|
5818
6602
|
this.schema = schema;
|
|
5819
6603
|
this.options = options;
|
|
5820
6604
|
this.$schema = schema;
|
|
@@ -5826,24 +6610,23 @@ var ClientImpl = class _ClientImpl {
|
|
|
5826
6610
|
if (baseClient) {
|
|
5827
6611
|
this.kyselyProps = {
|
|
5828
6612
|
...baseClient.kyselyProps,
|
|
5829
|
-
executor: new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
|
|
6613
|
+
executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
|
|
5830
6614
|
};
|
|
5831
6615
|
this.kyselyRaw = baseClient.kyselyRaw;
|
|
6616
|
+
this.auth = baseClient.auth;
|
|
5832
6617
|
} else {
|
|
5833
|
-
const
|
|
5834
|
-
const
|
|
5835
|
-
const
|
|
5836
|
-
const adapter = dialect.createAdapter();
|
|
6618
|
+
const driver = new ZenStackDriver(options.dialect.createDriver(), new Log(this.$options.log ?? []));
|
|
6619
|
+
const compiler = options.dialect.createQueryCompiler();
|
|
6620
|
+
const adapter = options.dialect.createAdapter();
|
|
5837
6621
|
const connectionProvider = new DefaultConnectionProvider(driver);
|
|
5838
|
-
const executor = new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider);
|
|
5839
6622
|
this.kyselyProps = {
|
|
5840
6623
|
config: {
|
|
5841
|
-
dialect,
|
|
6624
|
+
dialect: options.dialect,
|
|
5842
6625
|
log: this.$options.log
|
|
5843
6626
|
},
|
|
5844
|
-
dialect,
|
|
6627
|
+
dialect: options.dialect,
|
|
5845
6628
|
driver,
|
|
5846
|
-
executor
|
|
6629
|
+
executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
|
|
5847
6630
|
};
|
|
5848
6631
|
this.kyselyRaw = new Kysely({
|
|
5849
6632
|
...this.kyselyProps,
|
|
@@ -5859,31 +6642,58 @@ var ClientImpl = class _ClientImpl {
|
|
|
5859
6642
|
get $qbRaw() {
|
|
5860
6643
|
return this.kyselyRaw;
|
|
5861
6644
|
}
|
|
5862
|
-
|
|
5863
|
-
return
|
|
6645
|
+
get isTransaction() {
|
|
6646
|
+
return this.kysely.isTransaction;
|
|
5864
6647
|
}
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
};
|
|
5871
|
-
return new PostgresDialect(mergedConfig);
|
|
6648
|
+
/**
|
|
6649
|
+
* Create a new client with a new query executor.
|
|
6650
|
+
*/
|
|
6651
|
+
withExecutor(executor) {
|
|
6652
|
+
return new _ClientImpl(this.schema, this.$options, this, executor);
|
|
5872
6653
|
}
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
}
|
|
5879
|
-
|
|
6654
|
+
// implementation
|
|
6655
|
+
async $transaction(input, options) {
|
|
6656
|
+
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");
|
|
6657
|
+
if (typeof input === "function") {
|
|
6658
|
+
return this.interactiveTransaction(input, options);
|
|
6659
|
+
} else {
|
|
6660
|
+
return this.sequentialTransaction(input, options);
|
|
6661
|
+
}
|
|
6662
|
+
}
|
|
6663
|
+
async interactiveTransaction(callback, options) {
|
|
6664
|
+
if (this.kysely.isTransaction) {
|
|
6665
|
+
return callback(this);
|
|
6666
|
+
} else {
|
|
6667
|
+
let txBuilder = this.kysely.transaction();
|
|
6668
|
+
if (options?.isolationLevel) {
|
|
6669
|
+
txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
|
|
6670
|
+
}
|
|
6671
|
+
return txBuilder.execute((tx) => {
|
|
6672
|
+
const txClient = new _ClientImpl(this.schema, this.$options, this);
|
|
6673
|
+
txClient.kysely = tx;
|
|
6674
|
+
return callback(txClient);
|
|
6675
|
+
});
|
|
6676
|
+
}
|
|
5880
6677
|
}
|
|
5881
|
-
async
|
|
5882
|
-
|
|
5883
|
-
const txClient = new _ClientImpl(this.schema, this.$options);
|
|
6678
|
+
async sequentialTransaction(arg, options) {
|
|
6679
|
+
const execute = /* @__PURE__ */ __name(async (tx) => {
|
|
6680
|
+
const txClient = new _ClientImpl(this.schema, this.$options, this);
|
|
5884
6681
|
txClient.kysely = tx;
|
|
5885
|
-
|
|
5886
|
-
|
|
6682
|
+
const result = [];
|
|
6683
|
+
for (const promise of arg) {
|
|
6684
|
+
result.push(await promise.cb(txClient));
|
|
6685
|
+
}
|
|
6686
|
+
return result;
|
|
6687
|
+
}, "execute");
|
|
6688
|
+
if (this.kysely.isTransaction) {
|
|
6689
|
+
return execute(this.kysely);
|
|
6690
|
+
} else {
|
|
6691
|
+
let txBuilder = this.kysely.transaction();
|
|
6692
|
+
if (options?.isolationLevel) {
|
|
6693
|
+
txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
|
|
6694
|
+
}
|
|
6695
|
+
return txBuilder.execute((tx) => execute(tx));
|
|
6696
|
+
}
|
|
5887
6697
|
}
|
|
5888
6698
|
get $procedures() {
|
|
5889
6699
|
return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
|
|
@@ -5911,12 +6721,26 @@ var ClientImpl = class _ClientImpl {
|
|
|
5911
6721
|
await new SchemaDbPusher(this.schema, this.kysely).push();
|
|
5912
6722
|
}
|
|
5913
6723
|
$use(plugin) {
|
|
6724
|
+
const newPlugins = [
|
|
6725
|
+
...this.$options.plugins ?? [],
|
|
6726
|
+
plugin
|
|
6727
|
+
];
|
|
5914
6728
|
const newOptions = {
|
|
5915
6729
|
...this.options,
|
|
5916
|
-
plugins:
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
6730
|
+
plugins: newPlugins
|
|
6731
|
+
};
|
|
6732
|
+
return new _ClientImpl(this.schema, newOptions, this);
|
|
6733
|
+
}
|
|
6734
|
+
$unuse(pluginId) {
|
|
6735
|
+
const newPlugins = [];
|
|
6736
|
+
for (const plugin of this.options.plugins ?? []) {
|
|
6737
|
+
if (plugin.id !== pluginId) {
|
|
6738
|
+
newPlugins.push(plugin);
|
|
6739
|
+
}
|
|
6740
|
+
}
|
|
6741
|
+
const newOptions = {
|
|
6742
|
+
...this.options,
|
|
6743
|
+
plugins: newPlugins
|
|
5920
6744
|
};
|
|
5921
6745
|
return new _ClientImpl(this.schema, newOptions, this);
|
|
5922
6746
|
}
|
|
@@ -5938,6 +6762,39 @@ var ClientImpl = class _ClientImpl {
|
|
|
5938
6762
|
get $auth() {
|
|
5939
6763
|
return this.auth;
|
|
5940
6764
|
}
|
|
6765
|
+
$executeRaw(query, ...values) {
|
|
6766
|
+
return createZenStackPromise(async () => {
|
|
6767
|
+
const result = await sql10(query, ...values).execute(this.kysely);
|
|
6768
|
+
return Number(result.numAffectedRows ?? 0);
|
|
6769
|
+
});
|
|
6770
|
+
}
|
|
6771
|
+
$executeRawUnsafe(query, ...values) {
|
|
6772
|
+
return createZenStackPromise(async () => {
|
|
6773
|
+
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
6774
|
+
const result = await this.kysely.executeQuery(compiledQuery);
|
|
6775
|
+
return Number(result.numAffectedRows ?? 0);
|
|
6776
|
+
});
|
|
6777
|
+
}
|
|
6778
|
+
$queryRaw(query, ...values) {
|
|
6779
|
+
return createZenStackPromise(async () => {
|
|
6780
|
+
const result = await sql10(query, ...values).execute(this.kysely);
|
|
6781
|
+
return result.rows;
|
|
6782
|
+
});
|
|
6783
|
+
}
|
|
6784
|
+
$queryRawUnsafe(query, ...values) {
|
|
6785
|
+
return createZenStackPromise(async () => {
|
|
6786
|
+
const compiledQuery = this.createRawCompiledQuery(query, values);
|
|
6787
|
+
const result = await this.kysely.executeQuery(compiledQuery);
|
|
6788
|
+
return result.rows;
|
|
6789
|
+
});
|
|
6790
|
+
}
|
|
6791
|
+
createRawCompiledQuery(query, values) {
|
|
6792
|
+
const q = CompiledQuery.raw(query, values);
|
|
6793
|
+
return {
|
|
6794
|
+
...q,
|
|
6795
|
+
$raw: true
|
|
6796
|
+
};
|
|
6797
|
+
}
|
|
5941
6798
|
};
|
|
5942
6799
|
function createClientProxy(client) {
|
|
5943
6800
|
const inputValidator = new InputValidator(client.$schema);
|
|
@@ -5960,9 +6817,9 @@ function createClientProxy(client) {
|
|
|
5960
6817
|
__name(createClientProxy, "createClientProxy");
|
|
5961
6818
|
function createModelCrudHandler(client, model, inputValidator, resultProcessor) {
|
|
5962
6819
|
const createPromise = /* @__PURE__ */ __name((operation, args, handler, postProcess = false, throwIfNoResult = false) => {
|
|
5963
|
-
return
|
|
5964
|
-
let proceed = /* @__PURE__ */ __name(async (_args
|
|
5965
|
-
const _handler =
|
|
6820
|
+
return createZenStackPromise(async (txClient) => {
|
|
6821
|
+
let proceed = /* @__PURE__ */ __name(async (_args) => {
|
|
6822
|
+
const _handler = txClient ? handler.withClient(txClient) : handler;
|
|
5966
6823
|
const r = await _handler.handle(operation, _args ?? args);
|
|
5967
6824
|
if (!r && throwIfNoResult) {
|
|
5968
6825
|
throw new NotFoundError(model);
|
|
@@ -5975,22 +6832,31 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
5975
6832
|
}
|
|
5976
6833
|
return result;
|
|
5977
6834
|
}, "proceed");
|
|
5978
|
-
const context = {
|
|
5979
|
-
client,
|
|
5980
|
-
model,
|
|
5981
|
-
operation,
|
|
5982
|
-
queryArgs: args
|
|
5983
|
-
};
|
|
5984
6835
|
const plugins = [
|
|
5985
6836
|
...client.$options.plugins ?? []
|
|
5986
6837
|
];
|
|
5987
6838
|
for (const plugin of plugins) {
|
|
5988
|
-
if (plugin.onQuery) {
|
|
5989
|
-
const
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
6839
|
+
if (plugin.onQuery && typeof plugin.onQuery === "object") {
|
|
6840
|
+
for (const [_model, modelHooks] of Object.entries(plugin.onQuery)) {
|
|
6841
|
+
if (_model === lowerCaseFirst2(model) || _model === "$allModels") {
|
|
6842
|
+
if (modelHooks && typeof modelHooks === "object") {
|
|
6843
|
+
for (const [op, opHooks] of Object.entries(modelHooks)) {
|
|
6844
|
+
if (op === operation || op === "$allOperations") {
|
|
6845
|
+
if (typeof opHooks === "function") {
|
|
6846
|
+
const _proceed = proceed;
|
|
6847
|
+
proceed = /* @__PURE__ */ __name(() => opHooks({
|
|
6848
|
+
client,
|
|
6849
|
+
model,
|
|
6850
|
+
operation,
|
|
6851
|
+
args,
|
|
6852
|
+
query: _proceed
|
|
6853
|
+
}), "proceed");
|
|
6854
|
+
}
|
|
6855
|
+
}
|
|
6856
|
+
}
|
|
6857
|
+
}
|
|
6858
|
+
}
|
|
6859
|
+
}
|
|
5994
6860
|
}
|
|
5995
6861
|
}
|
|
5996
6862
|
return proceed(args);
|
|
@@ -6046,12 +6912,23 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
6046
6912
|
return createPromise("aggregate", args, new AggregateOperationHandler(client, model, inputValidator), false);
|
|
6047
6913
|
}, "aggregate"),
|
|
6048
6914
|
groupBy: /* @__PURE__ */ __name((args) => {
|
|
6049
|
-
return createPromise("groupBy", args, new
|
|
6915
|
+
return createPromise("groupBy", args, new GroupByOperationHandler(client, model, inputValidator), true);
|
|
6050
6916
|
}, "groupBy")
|
|
6051
6917
|
};
|
|
6052
6918
|
}
|
|
6053
6919
|
__name(createModelCrudHandler, "createModelCrudHandler");
|
|
6920
|
+
|
|
6921
|
+
// src/client/plugin.ts
|
|
6922
|
+
function definePlugin(plugin) {
|
|
6923
|
+
return plugin;
|
|
6924
|
+
}
|
|
6925
|
+
__name(definePlugin, "definePlugin");
|
|
6054
6926
|
export {
|
|
6055
|
-
|
|
6927
|
+
InputValidationError,
|
|
6928
|
+
InternalError,
|
|
6929
|
+
NotFoundError,
|
|
6930
|
+
QueryError,
|
|
6931
|
+
ZenStackClient,
|
|
6932
|
+
definePlugin
|
|
6056
6933
|
};
|
|
6057
6934
|
//# sourceMappingURL=index.js.map
|