@zenstackhq/runtime 3.0.0-alpha.8 → 3.0.0-beta.1
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-BnvK1nW0.d.cts → contract-CusA0mQO.d.cts} +447 -314
- package/dist/{contract-BnvK1nW0.d.ts → contract-CusA0mQO.d.ts} +447 -314
- package/dist/helpers.cjs +31 -0
- 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 +2523 -1385
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -5
- package/dist/index.d.ts +29 -5
- package/dist/index.js +2382 -1250
- package/dist/index.js.map +1 -1
- package/dist/plugins/{policy.cjs → policy/index.cjs} +628 -310
- package/dist/plugins/policy/index.cjs.map +1 -0
- package/dist/plugins/{policy.d.ts → policy/index.d.cts} +2 -2
- package/dist/plugins/{policy.d.cts → policy/index.d.ts} +2 -2
- package/dist/plugins/{policy.js → policy/index.js} +631 -313
- package/dist/plugins/policy/index.js.map +1 -0
- package/dist/plugins/policy/plugin.zmodel +33 -0
- package/dist/schema.cjs +4 -1
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +1 -0
- package/dist/schema.d.ts +1 -0
- package/dist/schema.js +4 -1
- package/dist/schema.js.map +1 -1
- package/package.json +28 -24
- package/dist/client.cjs +0 -6150
- package/dist/client.cjs.map +0 -1
- package/dist/client.d.cts +0 -17
- package/dist/client.d.ts +0 -17
- package/dist/client.js +0 -6115
- package/dist/client.js.map +0 -1
- package/dist/plugins/policy.cjs.map +0 -1
- package/dist/plugins/policy.js.map +0 -1
|
@@ -16,32 +16,131 @@ var RejectedByPolicyError = class extends Error {
|
|
|
16
16
|
// src/plugins/policy/policy-handler.ts
|
|
17
17
|
import { invariant as invariant6 } from "@zenstackhq/common-helpers";
|
|
18
18
|
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";
|
|
19
|
-
import { match as
|
|
19
|
+
import { match as match8 } from "ts-pattern";
|
|
20
20
|
|
|
21
21
|
// src/client/crud/dialects/index.ts
|
|
22
|
-
import { match as
|
|
22
|
+
import { match as match5 } from "ts-pattern";
|
|
23
23
|
|
|
24
24
|
// src/client/crud/dialects/postgresql.ts
|
|
25
25
|
import { invariant as invariant2 } from "@zenstackhq/common-helpers";
|
|
26
26
|
import { sql as sql2 } from "kysely";
|
|
27
|
-
import { match as
|
|
27
|
+
import { match as match3 } from "ts-pattern";
|
|
28
|
+
|
|
29
|
+
// src/client/constants.ts
|
|
30
|
+
var DELEGATE_JOINED_FIELD_PREFIX = "$delegate$";
|
|
31
|
+
var LOGICAL_COMBINATORS = [
|
|
32
|
+
"AND",
|
|
33
|
+
"OR",
|
|
34
|
+
"NOT"
|
|
35
|
+
];
|
|
36
|
+
var AGGREGATE_OPERATORS = [
|
|
37
|
+
"_count",
|
|
38
|
+
"_sum",
|
|
39
|
+
"_avg",
|
|
40
|
+
"_min",
|
|
41
|
+
"_max"
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
// src/client/query-utils.ts
|
|
45
|
+
import { match } from "ts-pattern";
|
|
46
|
+
|
|
47
|
+
// src/schema/expression.ts
|
|
48
|
+
var ExpressionUtils = {
|
|
49
|
+
literal: /* @__PURE__ */ __name((value) => {
|
|
50
|
+
return {
|
|
51
|
+
kind: "literal",
|
|
52
|
+
value
|
|
53
|
+
};
|
|
54
|
+
}, "literal"),
|
|
55
|
+
array: /* @__PURE__ */ __name((items) => {
|
|
56
|
+
return {
|
|
57
|
+
kind: "array",
|
|
58
|
+
items
|
|
59
|
+
};
|
|
60
|
+
}, "array"),
|
|
61
|
+
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
62
|
+
return {
|
|
63
|
+
kind: "call",
|
|
64
|
+
function: functionName,
|
|
65
|
+
args
|
|
66
|
+
};
|
|
67
|
+
}, "call"),
|
|
68
|
+
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
69
|
+
return {
|
|
70
|
+
kind: "binary",
|
|
71
|
+
op,
|
|
72
|
+
left,
|
|
73
|
+
right
|
|
74
|
+
};
|
|
75
|
+
}, "binary"),
|
|
76
|
+
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
77
|
+
return {
|
|
78
|
+
kind: "unary",
|
|
79
|
+
op,
|
|
80
|
+
operand
|
|
81
|
+
};
|
|
82
|
+
}, "unary"),
|
|
83
|
+
field: /* @__PURE__ */ __name((field) => {
|
|
84
|
+
return {
|
|
85
|
+
kind: "field",
|
|
86
|
+
field
|
|
87
|
+
};
|
|
88
|
+
}, "field"),
|
|
89
|
+
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
90
|
+
return {
|
|
91
|
+
kind: "member",
|
|
92
|
+
receiver,
|
|
93
|
+
members
|
|
94
|
+
};
|
|
95
|
+
}, "member"),
|
|
96
|
+
_this: /* @__PURE__ */ __name(() => {
|
|
97
|
+
return {
|
|
98
|
+
kind: "this"
|
|
99
|
+
};
|
|
100
|
+
}, "_this"),
|
|
101
|
+
_null: /* @__PURE__ */ __name(() => {
|
|
102
|
+
return {
|
|
103
|
+
kind: "null"
|
|
104
|
+
};
|
|
105
|
+
}, "_null"),
|
|
106
|
+
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
107
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
108
|
+
}, "and"),
|
|
109
|
+
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
110
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
111
|
+
}, "or"),
|
|
112
|
+
is: /* @__PURE__ */ __name((value, kind) => {
|
|
113
|
+
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
114
|
+
}, "is"),
|
|
115
|
+
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
116
|
+
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
117
|
+
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
118
|
+
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
119
|
+
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
120
|
+
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
121
|
+
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
122
|
+
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
123
|
+
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember"),
|
|
124
|
+
getLiteralValue: /* @__PURE__ */ __name((expr2) => {
|
|
125
|
+
return ExpressionUtils.isLiteral(expr2) ? expr2.value : void 0;
|
|
126
|
+
}, "getLiteralValue")
|
|
127
|
+
};
|
|
28
128
|
|
|
29
129
|
// src/client/errors.ts
|
|
30
130
|
var QueryError = class extends Error {
|
|
31
131
|
static {
|
|
32
132
|
__name(this, "QueryError");
|
|
33
133
|
}
|
|
34
|
-
constructor(message) {
|
|
35
|
-
super(message
|
|
134
|
+
constructor(message, cause) {
|
|
135
|
+
super(message, {
|
|
136
|
+
cause
|
|
137
|
+
});
|
|
36
138
|
}
|
|
37
139
|
};
|
|
38
140
|
var InternalError = class extends Error {
|
|
39
141
|
static {
|
|
40
142
|
__name(this, "InternalError");
|
|
41
143
|
}
|
|
42
|
-
constructor(message) {
|
|
43
|
-
super(message);
|
|
44
|
-
}
|
|
45
144
|
};
|
|
46
145
|
|
|
47
146
|
// src/client/query-utils.ts
|
|
@@ -52,7 +151,7 @@ __name(getModel, "getModel");
|
|
|
52
151
|
function requireModel(schema, model) {
|
|
53
152
|
const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
|
|
54
153
|
if (!matchedName) {
|
|
55
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
154
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
56
155
|
}
|
|
57
156
|
return schema.models[matchedName];
|
|
58
157
|
}
|
|
@@ -115,6 +214,16 @@ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
|
115
214
|
}
|
|
116
215
|
}
|
|
117
216
|
__name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
|
|
217
|
+
function isRelationField(schema, model, field) {
|
|
218
|
+
const fieldDef = getField(schema, model, field);
|
|
219
|
+
return !!fieldDef?.relation;
|
|
220
|
+
}
|
|
221
|
+
__name(isRelationField, "isRelationField");
|
|
222
|
+
function isInheritedField(schema, model, field) {
|
|
223
|
+
const fieldDef = getField(schema, model, field);
|
|
224
|
+
return !!fieldDef?.originModel;
|
|
225
|
+
}
|
|
226
|
+
__name(isInheritedField, "isInheritedField");
|
|
118
227
|
function getUniqueFields(schema, model) {
|
|
119
228
|
const modelDef = requireModel(schema, model);
|
|
120
229
|
const result = [];
|
|
@@ -140,20 +249,25 @@ function getUniqueFields(schema, model) {
|
|
|
140
249
|
return result;
|
|
141
250
|
}
|
|
142
251
|
__name(getUniqueFields, "getUniqueFields");
|
|
143
|
-
function buildFieldRef(schema, model, field, options, eb, modelAlias) {
|
|
252
|
+
function buildFieldRef(schema, model, field, options, eb, modelAlias, inlineComputedField = true) {
|
|
144
253
|
const fieldDef = requireField(schema, model, field);
|
|
145
254
|
if (!fieldDef.computed) {
|
|
146
255
|
return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
|
|
147
256
|
} else {
|
|
257
|
+
if (!inlineComputedField) {
|
|
258
|
+
return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
|
|
259
|
+
}
|
|
148
260
|
let computer;
|
|
149
261
|
if ("computedFields" in options) {
|
|
150
262
|
const computedFields = options.computedFields;
|
|
151
263
|
computer = computedFields?.[model]?.[field];
|
|
152
264
|
}
|
|
153
265
|
if (!computer) {
|
|
154
|
-
throw new QueryError(`Computed field "${field}" implementation not provided`);
|
|
266
|
+
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
155
267
|
}
|
|
156
|
-
return computer(eb
|
|
268
|
+
return computer(eb, {
|
|
269
|
+
currentModel: modelAlias
|
|
270
|
+
});
|
|
157
271
|
}
|
|
158
272
|
}
|
|
159
273
|
__name(buildFieldRef, "buildFieldRef");
|
|
@@ -196,11 +310,33 @@ function getManyToManyRelation(schema, model, field) {
|
|
|
196
310
|
model,
|
|
197
311
|
fieldDef.type
|
|
198
312
|
].sort();
|
|
313
|
+
let orderedFK;
|
|
314
|
+
if (model !== fieldDef.type) {
|
|
315
|
+
orderedFK = sortedModelNames[0] === model ? [
|
|
316
|
+
"A",
|
|
317
|
+
"B"
|
|
318
|
+
] : [
|
|
319
|
+
"B",
|
|
320
|
+
"A"
|
|
321
|
+
];
|
|
322
|
+
} else {
|
|
323
|
+
const sortedFieldNames = [
|
|
324
|
+
field,
|
|
325
|
+
oppositeFieldDef.name
|
|
326
|
+
].sort();
|
|
327
|
+
orderedFK = sortedFieldNames[0] === field ? [
|
|
328
|
+
"A",
|
|
329
|
+
"B"
|
|
330
|
+
] : [
|
|
331
|
+
"B",
|
|
332
|
+
"A"
|
|
333
|
+
];
|
|
334
|
+
}
|
|
199
335
|
return {
|
|
200
|
-
parentFkName:
|
|
336
|
+
parentFkName: orderedFK[0],
|
|
201
337
|
otherModel: fieldDef.type,
|
|
202
338
|
otherField: fieldDef.relation.opposite,
|
|
203
|
-
otherFkName:
|
|
339
|
+
otherFkName: orderedFK[1],
|
|
204
340
|
joinTable: fieldDef.relation.name ? `_${fieldDef.relation.name}` : `_${sortedModelNames[0]}To${sortedModelNames[1]}`
|
|
205
341
|
};
|
|
206
342
|
} else {
|
|
@@ -228,11 +364,38 @@ function flattenCompoundUniqueFilters(schema, model, filter) {
|
|
|
228
364
|
return result;
|
|
229
365
|
}
|
|
230
366
|
__name(flattenCompoundUniqueFilters, "flattenCompoundUniqueFilters");
|
|
367
|
+
function ensureArray(value) {
|
|
368
|
+
if (Array.isArray(value)) {
|
|
369
|
+
return value;
|
|
370
|
+
} else {
|
|
371
|
+
return [
|
|
372
|
+
value
|
|
373
|
+
];
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
__name(ensureArray, "ensureArray");
|
|
377
|
+
function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */ new Set()) {
|
|
378
|
+
const subModels = Object.values(schema.models).filter((m) => m.baseModel === model);
|
|
379
|
+
subModels.forEach((def) => {
|
|
380
|
+
if (!collected.has(def)) {
|
|
381
|
+
collected.add(def);
|
|
382
|
+
getDelegateDescendantModels(schema, def.name, collected);
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
return [
|
|
386
|
+
...collected
|
|
387
|
+
];
|
|
388
|
+
}
|
|
389
|
+
__name(getDelegateDescendantModels, "getDelegateDescendantModels");
|
|
390
|
+
function aggregate(eb, expr2, op) {
|
|
391
|
+
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();
|
|
392
|
+
}
|
|
393
|
+
__name(aggregate, "aggregate");
|
|
231
394
|
|
|
232
395
|
// src/client/crud/dialects/base.ts
|
|
233
396
|
import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
|
|
234
|
-
import { sql } from "kysely";
|
|
235
|
-
import { match, P } from "ts-pattern";
|
|
397
|
+
import { expressionBuilder, sql } from "kysely";
|
|
398
|
+
import { match as match2, P } from "ts-pattern";
|
|
236
399
|
|
|
237
400
|
// src/utils/enumerate.ts
|
|
238
401
|
function enumerate(x) {
|
|
@@ -259,9 +422,47 @@ var BaseCrudDialect = class {
|
|
|
259
422
|
this.schema = schema;
|
|
260
423
|
this.options = options;
|
|
261
424
|
}
|
|
262
|
-
transformPrimitive(value, _type) {
|
|
425
|
+
transformPrimitive(value, _type, _forArrayField) {
|
|
263
426
|
return value;
|
|
264
427
|
}
|
|
428
|
+
// #region common query builders
|
|
429
|
+
buildSelectModel(eb, model, modelAlias) {
|
|
430
|
+
const modelDef = requireModel(this.schema, model);
|
|
431
|
+
let result = eb.selectFrom(model === modelAlias ? model : `${model} as ${modelAlias}`);
|
|
432
|
+
let joinBase = modelDef.baseModel;
|
|
433
|
+
while (joinBase) {
|
|
434
|
+
result = this.buildDelegateJoin(model, modelAlias, joinBase, result);
|
|
435
|
+
joinBase = requireModel(this.schema, joinBase).baseModel;
|
|
436
|
+
}
|
|
437
|
+
return result;
|
|
438
|
+
}
|
|
439
|
+
buildFilterSortTake(model, args, query, modelAlias) {
|
|
440
|
+
let result = query;
|
|
441
|
+
if (args.where) {
|
|
442
|
+
result = result.where((eb) => this.buildFilter(eb, model, modelAlias, args?.where));
|
|
443
|
+
}
|
|
444
|
+
let negateOrderBy = false;
|
|
445
|
+
const skip = args.skip;
|
|
446
|
+
let take = args.take;
|
|
447
|
+
if (take !== void 0 && take < 0) {
|
|
448
|
+
negateOrderBy = true;
|
|
449
|
+
take = -take;
|
|
450
|
+
}
|
|
451
|
+
result = this.buildSkipTake(result, skip, take);
|
|
452
|
+
result = this.buildOrderBy(result, model, modelAlias, args.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
453
|
+
if ("distinct" in args && args.distinct) {
|
|
454
|
+
const distinct = ensureArray(args.distinct);
|
|
455
|
+
if (this.supportsDistinctOn) {
|
|
456
|
+
result = result.distinctOn(distinct.map((f) => sql.ref(`${modelAlias}.${f}`)));
|
|
457
|
+
} else {
|
|
458
|
+
throw new QueryError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
if (args.cursor) {
|
|
462
|
+
result = this.buildCursorFilter(model, result, args.cursor, args.orderBy, negateOrderBy, modelAlias);
|
|
463
|
+
}
|
|
464
|
+
return result;
|
|
465
|
+
}
|
|
265
466
|
buildFilter(eb, model, modelAlias, where) {
|
|
266
467
|
if (where === true || where === void 0) {
|
|
267
468
|
return this.true(eb);
|
|
@@ -278,17 +479,20 @@ var BaseCrudDialect = class {
|
|
|
278
479
|
if (key.startsWith("$")) {
|
|
279
480
|
continue;
|
|
280
481
|
}
|
|
281
|
-
if (key
|
|
482
|
+
if (this.isLogicalCombinator(key)) {
|
|
282
483
|
result = this.and(eb, result, this.buildCompositeFilter(eb, model, modelAlias, key, payload));
|
|
283
484
|
continue;
|
|
284
485
|
}
|
|
285
486
|
const fieldDef = requireField(this.schema, model, key);
|
|
286
487
|
if (fieldDef.relation) {
|
|
287
488
|
result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
288
|
-
} else if (fieldDef.array) {
|
|
289
|
-
result = this.and(eb, result, this.buildArrayFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
290
489
|
} else {
|
|
291
|
-
|
|
490
|
+
const fieldRef = this.fieldRef(fieldDef.originModel ?? model, key, eb, fieldDef.originModel ?? modelAlias);
|
|
491
|
+
if (fieldDef.array) {
|
|
492
|
+
result = this.and(eb, result, this.buildArrayFilter(eb, fieldRef, fieldDef, payload));
|
|
493
|
+
} else {
|
|
494
|
+
result = this.and(eb, result, this.buildPrimitiveFilter(eb, fieldRef, fieldDef, payload));
|
|
495
|
+
}
|
|
292
496
|
}
|
|
293
497
|
}
|
|
294
498
|
if ("$expr" in _where && typeof _where["$expr"] === "function") {
|
|
@@ -296,8 +500,32 @@ var BaseCrudDialect = class {
|
|
|
296
500
|
}
|
|
297
501
|
return result;
|
|
298
502
|
}
|
|
503
|
+
buildCursorFilter(model, query, cursor, orderBy, negateOrderBy, modelAlias) {
|
|
504
|
+
const _orderBy = orderBy ?? makeDefaultOrderBy(this.schema, model);
|
|
505
|
+
const orderByItems = ensureArray(_orderBy).flatMap((obj) => Object.entries(obj));
|
|
506
|
+
const eb = expressionBuilder();
|
|
507
|
+
const subQueryAlias = `${model}$cursor$sub`;
|
|
508
|
+
const cursorFilter = this.buildFilter(eb, model, subQueryAlias, cursor);
|
|
509
|
+
let result = query;
|
|
510
|
+
const filters = [];
|
|
511
|
+
for (let i = orderByItems.length - 1; i >= 0; i--) {
|
|
512
|
+
const andFilters = [];
|
|
513
|
+
for (let j = 0; j <= i; j++) {
|
|
514
|
+
const [field, order] = orderByItems[j];
|
|
515
|
+
const _order = negateOrderBy ? order === "asc" ? "desc" : "asc" : order;
|
|
516
|
+
const op = j === i ? _order === "asc" ? ">=" : "<=" : "=";
|
|
517
|
+
andFilters.push(eb(eb.ref(`${modelAlias}.${field}`), op, this.buildSelectModel(eb, model, subQueryAlias).select(`${subQueryAlias}.${field}`).where(cursorFilter)));
|
|
518
|
+
}
|
|
519
|
+
filters.push(eb.and(andFilters));
|
|
520
|
+
}
|
|
521
|
+
result = result.where((eb2) => eb2.or(filters));
|
|
522
|
+
return result;
|
|
523
|
+
}
|
|
524
|
+
isLogicalCombinator(key) {
|
|
525
|
+
return LOGICAL_COMBINATORS.includes(key);
|
|
526
|
+
}
|
|
299
527
|
buildCompositeFilter(eb, model, modelAlias, key, payload) {
|
|
300
|
-
return
|
|
528
|
+
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();
|
|
301
529
|
}
|
|
302
530
|
buildRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
303
531
|
if (!fieldDef.array) {
|
|
@@ -306,19 +534,26 @@ var BaseCrudDialect = class {
|
|
|
306
534
|
return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
|
|
307
535
|
}
|
|
308
536
|
}
|
|
309
|
-
buildToOneRelationFilter(eb, model,
|
|
537
|
+
buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
310
538
|
if (payload === null) {
|
|
311
539
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
312
|
-
if (ownedByModel) {
|
|
313
|
-
return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${
|
|
540
|
+
if (ownedByModel && !fieldDef.originModel) {
|
|
541
|
+
return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${modelAlias}.${fk}`), "is", null)));
|
|
314
542
|
} else {
|
|
315
|
-
return this.buildToOneRelationFilter(eb, model,
|
|
543
|
+
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
|
|
316
544
|
is: null
|
|
317
545
|
});
|
|
318
546
|
}
|
|
319
547
|
}
|
|
320
|
-
const joinAlias = `${
|
|
321
|
-
const joinPairs = buildJoinPairs(
|
|
548
|
+
const joinAlias = `${modelAlias}$${field}`;
|
|
549
|
+
const joinPairs = buildJoinPairs(
|
|
550
|
+
this.schema,
|
|
551
|
+
model,
|
|
552
|
+
// if field is from a base, use the base model to join
|
|
553
|
+
fieldDef.originModel ?? modelAlias,
|
|
554
|
+
field,
|
|
555
|
+
joinAlias
|
|
556
|
+
);
|
|
322
557
|
const filterResultField = `${field}$filter`;
|
|
323
558
|
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));
|
|
324
559
|
const conditions = [];
|
|
@@ -348,25 +583,26 @@ var BaseCrudDialect = class {
|
|
|
348
583
|
}
|
|
349
584
|
return this.and(eb, ...conditions);
|
|
350
585
|
}
|
|
351
|
-
buildToManyRelationFilter(eb, model,
|
|
586
|
+
buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
352
587
|
if (payload === null) {
|
|
353
|
-
return eb(sql.ref(`${
|
|
588
|
+
return eb(sql.ref(`${modelAlias}.${field}`), "is", null);
|
|
354
589
|
}
|
|
355
590
|
const relationModel = fieldDef.type;
|
|
591
|
+
const relationFilterSelectAlias = `${modelAlias}$${field}$filter`;
|
|
356
592
|
const buildPkFkWhereRefs = /* @__PURE__ */ __name((eb2) => {
|
|
357
593
|
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
358
594
|
if (m2m) {
|
|
359
595
|
const modelIdField = getIdFields(this.schema, model)[0];
|
|
360
596
|
const relationIdField = getIdFields(this.schema, relationModel)[0];
|
|
361
|
-
return eb2(sql.ref(`${
|
|
597
|
+
return eb2(sql.ref(`${relationFilterSelectAlias}.${relationIdField}`), "in", eb2.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(sql.ref(`${m2m.joinTable}.${m2m.parentFkName}`), "=", sql.ref(`${modelAlias}.${modelIdField}`)));
|
|
362
598
|
} else {
|
|
363
599
|
const relationKeyPairs = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
364
600
|
let result2 = this.true(eb2);
|
|
365
601
|
for (const { fk, pk } of relationKeyPairs.keyPairs) {
|
|
366
602
|
if (relationKeyPairs.ownedByModel) {
|
|
367
|
-
result2 = this.and(eb2, result2, eb2(sql.ref(`${
|
|
603
|
+
result2 = this.and(eb2, result2, eb2(sql.ref(`${modelAlias}.${fk}`), "=", sql.ref(`${relationFilterSelectAlias}.${pk}`)));
|
|
368
604
|
} else {
|
|
369
|
-
result2 = this.and(eb2, result2, eb2(sql.ref(`${
|
|
605
|
+
result2 = this.and(eb2, result2, eb2(sql.ref(`${modelAlias}.${pk}`), "=", sql.ref(`${relationFilterSelectAlias}.${fk}`)));
|
|
370
606
|
}
|
|
371
607
|
}
|
|
372
608
|
return result2;
|
|
@@ -379,30 +615,29 @@ var BaseCrudDialect = class {
|
|
|
379
615
|
}
|
|
380
616
|
switch (key) {
|
|
381
617
|
case "some": {
|
|
382
|
-
result = this.and(eb, result, eb(
|
|
618
|
+
result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel, relationFilterSelectAlias).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationFilterSelectAlias, subPayload)), ">", 0));
|
|
383
619
|
break;
|
|
384
620
|
}
|
|
385
621
|
case "every": {
|
|
386
|
-
result = this.and(eb, result, eb(
|
|
622
|
+
result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel, relationFilterSelectAlias).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => eb1.not(this.buildFilter(eb1, relationModel, relationFilterSelectAlias, subPayload))), "=", 0));
|
|
387
623
|
break;
|
|
388
624
|
}
|
|
389
625
|
case "none": {
|
|
390
|
-
result = this.and(eb, result, eb(
|
|
626
|
+
result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel, relationFilterSelectAlias).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationFilterSelectAlias, subPayload)), "=", 0));
|
|
391
627
|
break;
|
|
392
628
|
}
|
|
393
629
|
}
|
|
394
630
|
}
|
|
395
631
|
return result;
|
|
396
632
|
}
|
|
397
|
-
buildArrayFilter(eb,
|
|
633
|
+
buildArrayFilter(eb, fieldRef, fieldDef, payload) {
|
|
398
634
|
const clauses = [];
|
|
399
635
|
const fieldType = fieldDef.type;
|
|
400
|
-
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
|
|
401
636
|
for (const [key, _value] of Object.entries(payload)) {
|
|
402
637
|
if (_value === void 0) {
|
|
403
638
|
continue;
|
|
404
639
|
}
|
|
405
|
-
const value = this.transformPrimitive(_value, fieldType);
|
|
640
|
+
const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
|
|
406
641
|
switch (key) {
|
|
407
642
|
case "equals": {
|
|
408
643
|
clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
|
|
@@ -433,19 +668,23 @@ var BaseCrudDialect = class {
|
|
|
433
668
|
}
|
|
434
669
|
return this.and(eb, ...clauses);
|
|
435
670
|
}
|
|
436
|
-
buildPrimitiveFilter(eb,
|
|
671
|
+
buildPrimitiveFilter(eb, fieldRef, fieldDef, payload) {
|
|
437
672
|
if (payload === null) {
|
|
438
|
-
return eb(
|
|
673
|
+
return eb(fieldRef, "is", null);
|
|
439
674
|
}
|
|
440
675
|
if (isEnum(this.schema, fieldDef.type)) {
|
|
441
|
-
return this.buildEnumFilter(eb,
|
|
676
|
+
return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
|
|
442
677
|
}
|
|
443
|
-
return
|
|
678
|
+
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", () => {
|
|
679
|
+
throw new InternalError("JSON filters are not supported yet");
|
|
680
|
+
}).with("Unsupported", () => {
|
|
681
|
+
throw new QueryError(`Unsupported field cannot be used in filters`);
|
|
682
|
+
}).exhaustive();
|
|
444
683
|
}
|
|
445
684
|
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
446
|
-
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
|
|
685
|
+
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
447
686
|
}
|
|
448
|
-
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
|
|
687
|
+
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
449
688
|
if (payload === null || !isPlainObject(payload)) {
|
|
450
689
|
return {
|
|
451
690
|
conditions: [
|
|
@@ -460,8 +699,11 @@ var BaseCrudDialect = class {
|
|
|
460
699
|
if (onlyForKeys && !onlyForKeys.includes(op)) {
|
|
461
700
|
continue;
|
|
462
701
|
}
|
|
702
|
+
if (excludeKeys.includes(op)) {
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
463
705
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
464
|
-
const condition =
|
|
706
|
+
const condition = match2(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
465
707
|
invariant(Array.isArray(rhs), "right hand side must be an array");
|
|
466
708
|
if (rhs.length === 0) {
|
|
467
709
|
return this.false(eb);
|
|
@@ -475,7 +717,11 @@ var BaseCrudDialect = class {
|
|
|
475
717
|
} else {
|
|
476
718
|
return eb.not(eb(lhs, "in", rhs));
|
|
477
719
|
}
|
|
478
|
-
}).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))).
|
|
720
|
+
}).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) => {
|
|
721
|
+
const innerResult = this.buildStandardFilter(eb, type, value, aggregate(eb, lhs, op2), getRhs, recurse, throwIfInvalid);
|
|
722
|
+
consumedKeys.push(...innerResult.consumedKeys);
|
|
723
|
+
return this.and(eb, ...innerResult.conditions);
|
|
724
|
+
}).otherwise(() => {
|
|
479
725
|
if (throwIfInvalid) {
|
|
480
726
|
throw new QueryError(`Invalid filter key: ${op}`);
|
|
481
727
|
} else {
|
|
@@ -492,24 +738,21 @@ var BaseCrudDialect = class {
|
|
|
492
738
|
consumedKeys
|
|
493
739
|
};
|
|
494
740
|
}
|
|
495
|
-
buildStringFilter(eb,
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
if (payload && typeof payload === "object" && "mode" in payload && payload.mode === "insensitive") {
|
|
500
|
-
insensitive = true;
|
|
501
|
-
fieldRef = eb.fn("lower", [
|
|
502
|
-
fieldRef
|
|
503
|
-
]);
|
|
741
|
+
buildStringFilter(eb, fieldRef, payload) {
|
|
742
|
+
let mode;
|
|
743
|
+
if (payload && typeof payload === "object" && "mode" in payload) {
|
|
744
|
+
mode = payload.mode;
|
|
504
745
|
}
|
|
505
|
-
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload,
|
|
746
|
+
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, mode === "insensitive" ? eb.fn("lower", [
|
|
747
|
+
fieldRef
|
|
748
|
+
]) : fieldRef, (value) => this.prepStringCasing(eb, value, mode), (value) => this.buildStringFilter(eb, fieldRef, value));
|
|
506
749
|
if (payload && typeof payload === "object") {
|
|
507
750
|
for (const [key, value] of Object.entries(payload)) {
|
|
508
751
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
509
752
|
continue;
|
|
510
753
|
}
|
|
511
|
-
const condition =
|
|
512
|
-
throw new
|
|
754
|
+
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(() => {
|
|
755
|
+
throw new QueryError(`Invalid string filter key: ${key}`);
|
|
513
756
|
});
|
|
514
757
|
if (condition) {
|
|
515
758
|
conditions.push(condition);
|
|
@@ -518,34 +761,37 @@ var BaseCrudDialect = class {
|
|
|
518
761
|
}
|
|
519
762
|
return this.and(eb, ...conditions);
|
|
520
763
|
}
|
|
521
|
-
prepStringCasing(eb, value,
|
|
764
|
+
prepStringCasing(eb, value, mode) {
|
|
765
|
+
if (!mode || mode === "default") {
|
|
766
|
+
return value === null ? value : sql.val(value);
|
|
767
|
+
}
|
|
522
768
|
if (typeof value === "string") {
|
|
523
|
-
return
|
|
524
|
-
sql.
|
|
525
|
-
])
|
|
769
|
+
return eb.fn("lower", [
|
|
770
|
+
sql.val(value)
|
|
771
|
+
]);
|
|
526
772
|
} else if (Array.isArray(value)) {
|
|
527
|
-
return value.map((v) => this.prepStringCasing(eb, v,
|
|
773
|
+
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
528
774
|
} else {
|
|
529
|
-
return value === null ? null : sql.
|
|
775
|
+
return value === null ? null : sql.val(value);
|
|
530
776
|
}
|
|
531
777
|
}
|
|
532
|
-
buildNumberFilter(eb,
|
|
533
|
-
const { conditions } = this.buildStandardFilter(eb, type, payload,
|
|
778
|
+
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
779
|
+
const { conditions } = this.buildStandardFilter(eb, type, payload, fieldRef, (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, fieldRef, type, value));
|
|
534
780
|
return this.and(eb, ...conditions);
|
|
535
781
|
}
|
|
536
|
-
buildBooleanFilter(eb,
|
|
537
|
-
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload,
|
|
782
|
+
buildBooleanFilter(eb, fieldRef, payload) {
|
|
783
|
+
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, fieldRef, (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, fieldRef, value), true, [
|
|
538
784
|
"equals",
|
|
539
785
|
"not"
|
|
540
786
|
]);
|
|
541
787
|
return this.and(eb, ...conditions);
|
|
542
788
|
}
|
|
543
|
-
buildDateTimeFilter(eb,
|
|
544
|
-
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload,
|
|
789
|
+
buildDateTimeFilter(eb, fieldRef, payload) {
|
|
790
|
+
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, fieldRef, (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, fieldRef, value), true);
|
|
545
791
|
return this.and(eb, ...conditions);
|
|
546
792
|
}
|
|
547
|
-
buildBytesFilter(eb,
|
|
548
|
-
const conditions = this.buildStandardFilter(eb, "Bytes", payload,
|
|
793
|
+
buildBytesFilter(eb, fieldRef, payload) {
|
|
794
|
+
const conditions = this.buildStandardFilter(eb, "Bytes", payload, fieldRef, (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, fieldRef, value), true, [
|
|
549
795
|
"equals",
|
|
550
796
|
"in",
|
|
551
797
|
"notIn",
|
|
@@ -553,8 +799,8 @@ var BaseCrudDialect = class {
|
|
|
553
799
|
]);
|
|
554
800
|
return this.and(eb, ...conditions.conditions);
|
|
555
801
|
}
|
|
556
|
-
buildEnumFilter(eb,
|
|
557
|
-
const conditions = this.buildStandardFilter(eb, "String", payload,
|
|
802
|
+
buildEnumFilter(eb, fieldRef, fieldDef, payload) {
|
|
803
|
+
const conditions = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => value, (value) => this.buildEnumFilter(eb, fieldRef, fieldDef, value), true, [
|
|
558
804
|
"equals",
|
|
559
805
|
"in",
|
|
560
806
|
"notIn",
|
|
@@ -586,9 +832,7 @@ var BaseCrudDialect = class {
|
|
|
586
832
|
invariant(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
587
833
|
for (const [k, v] of Object.entries(value)) {
|
|
588
834
|
invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
589
|
-
result = result.orderBy((eb) => eb.
|
|
590
|
-
sql.ref(k)
|
|
591
|
-
]), sql.raw(this.negateSort(v, negated)));
|
|
835
|
+
result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field), sql.raw(this.negateSort(v, negated)));
|
|
592
836
|
}
|
|
593
837
|
continue;
|
|
594
838
|
}
|
|
@@ -597,7 +841,7 @@ var BaseCrudDialect = class {
|
|
|
597
841
|
invariant(value && typeof value === "object", 'invalid orderBy value for field "_count"');
|
|
598
842
|
for (const [k, v] of Object.entries(value)) {
|
|
599
843
|
invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
600
|
-
result = result.orderBy((eb) => eb.fn.count(
|
|
844
|
+
result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), sql.raw(this.negateSort(v, negated)));
|
|
601
845
|
}
|
|
602
846
|
continue;
|
|
603
847
|
}
|
|
@@ -606,10 +850,11 @@ var BaseCrudDialect = class {
|
|
|
606
850
|
}
|
|
607
851
|
const fieldDef = requireField(this.schema, model, field);
|
|
608
852
|
if (!fieldDef.relation) {
|
|
853
|
+
const fieldRef = this.fieldRef(model, field, expressionBuilder(), modelAlias);
|
|
609
854
|
if (value === "asc" || value === "desc") {
|
|
610
|
-
result = result.orderBy(
|
|
855
|
+
result = result.orderBy(fieldRef, this.negateSort(value, negated));
|
|
611
856
|
} else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
|
|
612
|
-
result = result.orderBy(
|
|
857
|
+
result = result.orderBy(fieldRef, sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
|
|
613
858
|
}
|
|
614
859
|
} else {
|
|
615
860
|
const relationModel = fieldDef.type;
|
|
@@ -621,8 +866,9 @@ var BaseCrudDialect = class {
|
|
|
621
866
|
invariant(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
622
867
|
const sort = this.negateSort(value._count, negated);
|
|
623
868
|
result = result.orderBy((eb) => {
|
|
624
|
-
|
|
625
|
-
|
|
869
|
+
const subQueryAlias = `${modelAlias}$orderBy$${field}$count`;
|
|
870
|
+
let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
|
|
871
|
+
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, subQueryAlias);
|
|
626
872
|
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right)))));
|
|
627
873
|
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
628
874
|
return subQuery;
|
|
@@ -640,14 +886,100 @@ var BaseCrudDialect = class {
|
|
|
640
886
|
});
|
|
641
887
|
return result;
|
|
642
888
|
}
|
|
889
|
+
buildSelectAllFields(model, query, omit, modelAlias) {
|
|
890
|
+
const modelDef = requireModel(this.schema, model);
|
|
891
|
+
let result = query;
|
|
892
|
+
for (const field of Object.keys(modelDef.fields)) {
|
|
893
|
+
if (isRelationField(this.schema, model, field)) {
|
|
894
|
+
continue;
|
|
895
|
+
}
|
|
896
|
+
if (omit?.[field] === true) {
|
|
897
|
+
continue;
|
|
898
|
+
}
|
|
899
|
+
result = this.buildSelectField(result, model, modelAlias, field);
|
|
900
|
+
}
|
|
901
|
+
const descendants = getDelegateDescendantModels(this.schema, model);
|
|
902
|
+
for (const subModel of descendants) {
|
|
903
|
+
result = this.buildDelegateJoin(model, modelAlias, subModel.name, result);
|
|
904
|
+
result = result.select((eb) => {
|
|
905
|
+
const jsonObject = {};
|
|
906
|
+
for (const field of Object.keys(subModel.fields)) {
|
|
907
|
+
if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
|
|
908
|
+
continue;
|
|
909
|
+
}
|
|
910
|
+
jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
|
|
911
|
+
}
|
|
912
|
+
return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
return result;
|
|
916
|
+
}
|
|
917
|
+
buildModelSelect(eb, model, subQueryAlias, payload, selectAllFields) {
|
|
918
|
+
let subQuery = this.buildSelectModel(eb, model, subQueryAlias);
|
|
919
|
+
if (selectAllFields) {
|
|
920
|
+
subQuery = this.buildSelectAllFields(model, subQuery, typeof payload === "object" ? payload?.omit : void 0, subQueryAlias);
|
|
921
|
+
}
|
|
922
|
+
if (payload && typeof payload === "object") {
|
|
923
|
+
subQuery = this.buildFilterSortTake(model, payload, subQuery, subQueryAlias);
|
|
924
|
+
}
|
|
925
|
+
return subQuery;
|
|
926
|
+
}
|
|
927
|
+
buildSelectField(query, model, modelAlias, field) {
|
|
928
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
929
|
+
if (fieldDef.computed) {
|
|
930
|
+
return query.select((eb) => this.fieldRef(model, field, eb, modelAlias).as(field));
|
|
931
|
+
} else if (!fieldDef.originModel) {
|
|
932
|
+
return query.select(sql.ref(`${modelAlias}.${field}`).as(field));
|
|
933
|
+
} else {
|
|
934
|
+
return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
buildDelegateJoin(thisModel, thisModelAlias, otherModelAlias, query) {
|
|
938
|
+
const idFields = getIdFields(this.schema, thisModel);
|
|
939
|
+
query = query.leftJoin(otherModelAlias, (qb) => {
|
|
940
|
+
for (const idField of idFields) {
|
|
941
|
+
qb = qb.onRef(`${thisModelAlias}.${idField}`, "=", `${otherModelAlias}.${idField}`);
|
|
942
|
+
}
|
|
943
|
+
return qb;
|
|
944
|
+
});
|
|
945
|
+
return query;
|
|
946
|
+
}
|
|
947
|
+
buildCountJson(model, eb, parentAlias, payload) {
|
|
948
|
+
const modelDef = requireModel(this.schema, model);
|
|
949
|
+
const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
|
|
950
|
+
const selections = payload === true ? {
|
|
951
|
+
select: toManyRelations.reduce((acc, [field]) => {
|
|
952
|
+
acc[field] = true;
|
|
953
|
+
return acc;
|
|
954
|
+
}, {})
|
|
955
|
+
} : payload;
|
|
956
|
+
const jsonObject = {};
|
|
957
|
+
for (const [field, value] of Object.entries(selections.select)) {
|
|
958
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
959
|
+
const fieldModel = fieldDef.type;
|
|
960
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
961
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
962
|
+
for (const [left, right] of joinPairs) {
|
|
963
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
964
|
+
}
|
|
965
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
966
|
+
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
967
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
968
|
+
}
|
|
969
|
+
jsonObject[field] = fieldCountQuery;
|
|
970
|
+
}
|
|
971
|
+
return this.buildJsonObject(eb, jsonObject);
|
|
972
|
+
}
|
|
973
|
+
// #endregion
|
|
974
|
+
// #region utils
|
|
643
975
|
negateSort(sort, negated) {
|
|
644
976
|
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
645
977
|
}
|
|
646
978
|
true(eb) {
|
|
647
|
-
return eb.lit(this.transformPrimitive(true, "Boolean"));
|
|
979
|
+
return eb.lit(this.transformPrimitive(true, "Boolean", false));
|
|
648
980
|
}
|
|
649
981
|
false(eb) {
|
|
650
|
-
return eb.lit(this.transformPrimitive(false, "Boolean"));
|
|
982
|
+
return eb.lit(this.transformPrimitive(false, "Boolean", false));
|
|
651
983
|
}
|
|
652
984
|
isTrue(expression) {
|
|
653
985
|
const node = expression.toOperationNode();
|
|
@@ -686,6 +1018,21 @@ var BaseCrudDialect = class {
|
|
|
686
1018
|
not(eb, ...args) {
|
|
687
1019
|
return eb.not(this.and(eb, ...args));
|
|
688
1020
|
}
|
|
1021
|
+
fieldRef(model, field, eb, modelAlias, inlineComputedField = true) {
|
|
1022
|
+
return buildFieldRef(this.schema, model, field, this.options, eb, modelAlias, inlineComputedField);
|
|
1023
|
+
}
|
|
1024
|
+
canJoinWithoutNestedSelect(modelDef, payload) {
|
|
1025
|
+
if (modelDef.computedFields) {
|
|
1026
|
+
return false;
|
|
1027
|
+
}
|
|
1028
|
+
if (modelDef.baseModel || modelDef.isDelegate) {
|
|
1029
|
+
return false;
|
|
1030
|
+
}
|
|
1031
|
+
if (typeof payload === "object" && (payload.orderBy || payload.skip !== void 0 || payload.take !== void 0 || payload.cursor || payload.distinct)) {
|
|
1032
|
+
return false;
|
|
1033
|
+
}
|
|
1034
|
+
return true;
|
|
1035
|
+
}
|
|
689
1036
|
};
|
|
690
1037
|
|
|
691
1038
|
// src/client/crud/dialects/postgresql.ts
|
|
@@ -696,99 +1043,123 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
696
1043
|
get provider() {
|
|
697
1044
|
return "postgresql";
|
|
698
1045
|
}
|
|
699
|
-
transformPrimitive(value, type) {
|
|
1046
|
+
transformPrimitive(value, type, forArrayField) {
|
|
700
1047
|
if (value === void 0) {
|
|
701
1048
|
return value;
|
|
702
1049
|
}
|
|
703
1050
|
if (Array.isArray(value)) {
|
|
704
|
-
|
|
1051
|
+
if (type === "Json" && !forArrayField) {
|
|
1052
|
+
return JSON.stringify(value);
|
|
1053
|
+
} else {
|
|
1054
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
1055
|
+
}
|
|
705
1056
|
} else {
|
|
706
|
-
return
|
|
1057
|
+
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);
|
|
707
1058
|
}
|
|
708
1059
|
}
|
|
709
1060
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
710
|
-
const
|
|
711
|
-
|
|
1061
|
+
const relationResultName = `${parentAlias}$${relationField}`;
|
|
1062
|
+
const joinedQuery = this.buildRelationJSON(model, query, relationField, parentAlias, payload, relationResultName);
|
|
1063
|
+
return joinedQuery.select(`${relationResultName}.$data as ${relationField}`);
|
|
712
1064
|
}
|
|
713
|
-
buildRelationJSON(model, qb, relationField,
|
|
1065
|
+
buildRelationJSON(model, qb, relationField, parentAlias, payload, resultName) {
|
|
714
1066
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
715
1067
|
const relationModel = relationFieldDef.type;
|
|
716
1068
|
return qb.leftJoinLateral((eb) => {
|
|
717
|
-
const
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
subQuery = this.buildOrderBy(subQuery, relationModel, relationModel, payload.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
734
|
-
}
|
|
735
|
-
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
736
|
-
if (m2m) {
|
|
737
|
-
const parentIds = getIdFields(this.schema, model);
|
|
738
|
-
const relationIds = getIdFields(this.schema, relationModel);
|
|
739
|
-
invariant2(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
740
|
-
invariant2(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
741
|
-
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentName}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
742
|
-
} else {
|
|
743
|
-
const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField, relationModel);
|
|
744
|
-
subQuery = subQuery.where((eb2) => this.and(eb2, ...joinPairs.map(([left, right]) => eb2(sql2.ref(left), "=", sql2.ref(right)))));
|
|
745
|
-
}
|
|
746
|
-
return subQuery.as(joinTableName);
|
|
747
|
-
});
|
|
748
|
-
result = this.buildRelationObjectSelect(relationModel, relationField, relationFieldDef, result, payload, parentName);
|
|
749
|
-
result = this.buildRelationJoins(relationModel, relationField, result, payload, parentName);
|
|
750
|
-
return result.as(joinTableName);
|
|
1069
|
+
const relationSelectName = `${resultName}$sub`;
|
|
1070
|
+
const relationModelDef = requireModel(this.schema, relationModel);
|
|
1071
|
+
let tbl;
|
|
1072
|
+
if (this.canJoinWithoutNestedSelect(relationModelDef, payload)) {
|
|
1073
|
+
tbl = this.buildModelSelect(eb, relationModel, relationSelectName, payload, false);
|
|
1074
|
+
tbl = this.buildRelationJoinFilter(tbl, model, relationField, relationModel, relationSelectName, parentAlias);
|
|
1075
|
+
} else {
|
|
1076
|
+
tbl = eb.selectFrom(() => {
|
|
1077
|
+
let subQuery = this.buildModelSelect(eb, relationModel, `${relationSelectName}$t`, payload, true);
|
|
1078
|
+
subQuery = this.buildRelationJoinFilter(subQuery, model, relationField, relationModel, `${relationSelectName}$t`, parentAlias);
|
|
1079
|
+
return subQuery.as(relationSelectName);
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
tbl = this.buildRelationObjectSelect(relationModel, relationSelectName, relationFieldDef, tbl, payload, resultName);
|
|
1083
|
+
tbl = this.buildRelationJoins(tbl, relationModel, relationSelectName, payload, resultName);
|
|
1084
|
+
return tbl.as(resultName);
|
|
751
1085
|
}, (join) => join.onTrue());
|
|
752
1086
|
}
|
|
753
|
-
|
|
1087
|
+
buildRelationJoinFilter(query, model, relationField, relationModel, relationModelAlias, parentAlias) {
|
|
1088
|
+
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
1089
|
+
if (m2m) {
|
|
1090
|
+
const parentIds = getIdFields(this.schema, model);
|
|
1091
|
+
const relationIds = getIdFields(this.schema, relationModel);
|
|
1092
|
+
invariant2(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1093
|
+
invariant2(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1094
|
+
query = query.where((eb) => eb(eb.ref(`${relationModelAlias}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
1095
|
+
} else {
|
|
1096
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, relationField, relationModelAlias);
|
|
1097
|
+
query = query.where((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql2.ref(left), "=", sql2.ref(right)))));
|
|
1098
|
+
}
|
|
1099
|
+
return query;
|
|
1100
|
+
}
|
|
1101
|
+
buildRelationObjectSelect(relationModel, relationModelAlias, relationFieldDef, qb, payload, parentResultName) {
|
|
754
1102
|
qb = qb.select((eb) => {
|
|
755
|
-
const objArgs = this.buildRelationObjectArgs(relationModel,
|
|
1103
|
+
const objArgs = this.buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName);
|
|
756
1104
|
if (relationFieldDef.array) {
|
|
757
|
-
return eb.fn.coalesce(sql2`jsonb_agg(jsonb_build_object(${sql2.join(objArgs)}))`, sql2`'[]'::jsonb`).as("$
|
|
1105
|
+
return eb.fn.coalesce(sql2`jsonb_agg(jsonb_build_object(${sql2.join(objArgs)}))`, sql2`'[]'::jsonb`).as("$data");
|
|
758
1106
|
} else {
|
|
759
|
-
return sql2`jsonb_build_object(${sql2.join(objArgs)})`.as("$
|
|
1107
|
+
return sql2`jsonb_build_object(${sql2.join(objArgs)})`.as("$data");
|
|
760
1108
|
}
|
|
761
1109
|
});
|
|
762
1110
|
return qb;
|
|
763
1111
|
}
|
|
764
|
-
buildRelationObjectArgs(relationModel,
|
|
1112
|
+
buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName) {
|
|
765
1113
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
766
1114
|
const objArgs = [];
|
|
1115
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1116
|
+
if (descendantModels.length > 0) {
|
|
1117
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1118
|
+
sql2.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1119
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1120
|
+
]).flatMap((v) => v));
|
|
1121
|
+
}
|
|
767
1122
|
if (payload === true || !payload.select) {
|
|
768
1123
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
769
1124
|
sql2.lit(field),
|
|
770
|
-
|
|
1125
|
+
this.fieldRef(relationModel, field, eb, relationModelAlias, false)
|
|
771
1126
|
]).flatMap((v) => v));
|
|
772
1127
|
} else if (payload.select) {
|
|
773
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) =>
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
1128
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1129
|
+
if (field === "_count") {
|
|
1130
|
+
const subJson = this.buildCountJson(relationModel, eb, relationModelAlias, value);
|
|
1131
|
+
return [
|
|
1132
|
+
sql2.lit(field),
|
|
1133
|
+
subJson
|
|
1134
|
+
];
|
|
1135
|
+
} else {
|
|
1136
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1137
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentResultName}$${field}.$data`) : this.fieldRef(relationModel, field, eb, relationModelAlias, false);
|
|
1138
|
+
return [
|
|
1139
|
+
sql2.lit(field),
|
|
1140
|
+
fieldValue
|
|
1141
|
+
];
|
|
1142
|
+
}
|
|
1143
|
+
}).flatMap((v) => v));
|
|
777
1144
|
}
|
|
778
1145
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
779
1146
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
780
1147
|
sql2.lit(field),
|
|
781
|
-
|
|
1148
|
+
// reference the synthesized JSON field
|
|
1149
|
+
eb.ref(`${parentResultName}$${field}.$data`)
|
|
782
1150
|
]).flatMap((v) => v));
|
|
783
1151
|
}
|
|
784
1152
|
return objArgs;
|
|
785
1153
|
}
|
|
786
|
-
buildRelationJoins(
|
|
787
|
-
let result =
|
|
788
|
-
if (typeof payload === "object"
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
1154
|
+
buildRelationJoins(query, relationModel, relationModelAlias, payload, parentResultName) {
|
|
1155
|
+
let result = query;
|
|
1156
|
+
if (typeof payload === "object") {
|
|
1157
|
+
const selectInclude = payload.include ?? payload.select;
|
|
1158
|
+
if (selectInclude && typeof selectInclude === "object") {
|
|
1159
|
+
Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
|
|
1160
|
+
result = this.buildRelationJSON(relationModel, result, field, relationModelAlias, value, `${parentResultName}$${field}`);
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
792
1163
|
}
|
|
793
1164
|
return result;
|
|
794
1165
|
}
|
|
@@ -828,12 +1199,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
828
1199
|
return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
|
|
829
1200
|
}
|
|
830
1201
|
}
|
|
1202
|
+
get supportInsertWithDefault() {
|
|
1203
|
+
return true;
|
|
1204
|
+
}
|
|
831
1205
|
};
|
|
832
1206
|
|
|
833
1207
|
// src/client/crud/dialects/sqlite.ts
|
|
834
1208
|
import { invariant as invariant3 } from "@zenstackhq/common-helpers";
|
|
835
1209
|
import { sql as sql3 } from "kysely";
|
|
836
|
-
import { match as
|
|
1210
|
+
import { match as match4 } from "ts-pattern";
|
|
837
1211
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
838
1212
|
static {
|
|
839
1213
|
__name(this, "SqliteCrudDialect");
|
|
@@ -841,86 +1215,82 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
841
1215
|
get provider() {
|
|
842
1216
|
return "sqlite";
|
|
843
1217
|
}
|
|
844
|
-
transformPrimitive(value, type) {
|
|
1218
|
+
transformPrimitive(value, type, _forArrayField) {
|
|
845
1219
|
if (value === void 0) {
|
|
846
1220
|
return value;
|
|
847
1221
|
}
|
|
848
1222
|
if (Array.isArray(value)) {
|
|
849
|
-
return value.map((v) => this.transformPrimitive(v, type));
|
|
1223
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
850
1224
|
} else {
|
|
851
|
-
|
|
1225
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1226
|
+
return JSON.stringify(value);
|
|
1227
|
+
} else {
|
|
1228
|
+
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);
|
|
1229
|
+
}
|
|
852
1230
|
}
|
|
853
1231
|
}
|
|
854
1232
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
855
1233
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
856
1234
|
}
|
|
857
|
-
buildRelationJSON(model, eb, relationField,
|
|
1235
|
+
buildRelationJSON(model, eb, relationField, parentAlias, payload) {
|
|
858
1236
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
859
1237
|
const relationModel = relationFieldDef.type;
|
|
860
1238
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
861
|
-
const subQueryName = `${
|
|
862
|
-
let tbl
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
const
|
|
869
|
-
let
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
}
|
|
875
|
-
subQuery = this.buildSkipTake(subQuery, skip, take);
|
|
876
|
-
subQuery = this.buildOrderBy(subQuery, relationModel, relationModel, payload.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
877
|
-
}
|
|
878
|
-
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
879
|
-
if (m2m) {
|
|
880
|
-
const parentIds = getIdFields(this.schema, model);
|
|
881
|
-
const relationIds = getIdFields(this.schema, relationModel);
|
|
882
|
-
invariant3(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
883
|
-
invariant3(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
884
|
-
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentName}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
885
|
-
} else {
|
|
886
|
-
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
887
|
-
keyPairs.forEach(({ fk, pk }) => {
|
|
888
|
-
if (ownedByModel) {
|
|
889
|
-
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentName}.${fk}`);
|
|
890
|
-
} else {
|
|
891
|
-
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentName}.${pk}`);
|
|
892
|
-
}
|
|
893
|
-
});
|
|
894
|
-
}
|
|
895
|
-
return subQuery.as(subQueryName);
|
|
896
|
-
});
|
|
1239
|
+
const subQueryName = `${parentAlias}$${relationField}`;
|
|
1240
|
+
let tbl;
|
|
1241
|
+
if (this.canJoinWithoutNestedSelect(relationModelDef, payload)) {
|
|
1242
|
+
tbl = this.buildModelSelect(eb, relationModel, subQueryName, payload, false);
|
|
1243
|
+
tbl = this.buildRelationJoinFilter(tbl, model, relationField, subQueryName, parentAlias);
|
|
1244
|
+
} else {
|
|
1245
|
+
tbl = eb.selectFrom(() => {
|
|
1246
|
+
const selectModelAlias = `${parentAlias}$${relationField}$sub`;
|
|
1247
|
+
let selectModelQuery = this.buildModelSelect(eb, relationModel, selectModelAlias, payload, true);
|
|
1248
|
+
selectModelQuery = this.buildRelationJoinFilter(selectModelQuery, model, relationField, selectModelAlias, parentAlias);
|
|
1249
|
+
return selectModelQuery.as(subQueryName);
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
897
1252
|
tbl = tbl.select(() => {
|
|
898
1253
|
const objArgs = [];
|
|
1254
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1255
|
+
if (descendantModels.length > 0) {
|
|
1256
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1257
|
+
sql3.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1258
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1259
|
+
]).flatMap((v) => v));
|
|
1260
|
+
}
|
|
899
1261
|
if (payload === true || !payload.select) {
|
|
900
1262
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
901
1263
|
sql3.lit(field),
|
|
902
|
-
|
|
1264
|
+
this.fieldRef(relationModel, field, eb, subQueryName, false)
|
|
903
1265
|
]).flatMap((v) => v));
|
|
904
1266
|
} else if (payload.select) {
|
|
905
1267
|
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
|
|
1268
|
+
if (field === "_count") {
|
|
1269
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
909
1270
|
return [
|
|
910
1271
|
sql3.lit(field),
|
|
911
1272
|
subJson
|
|
912
1273
|
];
|
|
913
1274
|
} else {
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
1275
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1276
|
+
if (fieldDef.relation) {
|
|
1277
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1278
|
+
return [
|
|
1279
|
+
sql3.lit(field),
|
|
1280
|
+
subJson
|
|
1281
|
+
];
|
|
1282
|
+
} else {
|
|
1283
|
+
return [
|
|
1284
|
+
sql3.lit(field),
|
|
1285
|
+
this.fieldRef(relationModel, field, eb, subQueryName, false)
|
|
1286
|
+
];
|
|
1287
|
+
}
|
|
918
1288
|
}
|
|
919
1289
|
}).flatMap((v) => v));
|
|
920
1290
|
}
|
|
921
1291
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
922
1292
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
923
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${
|
|
1293
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
924
1294
|
return [
|
|
925
1295
|
sql3.lit(field),
|
|
926
1296
|
subJson
|
|
@@ -928,13 +1298,35 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
928
1298
|
}).flatMap((v) => v));
|
|
929
1299
|
}
|
|
930
1300
|
if (relationFieldDef.array) {
|
|
931
|
-
return eb.fn.coalesce(sql3`json_group_array(json_object(${sql3.join(objArgs)}))`, sql3`json_array()`).as("$
|
|
1301
|
+
return eb.fn.coalesce(sql3`json_group_array(json_object(${sql3.join(objArgs)}))`, sql3`json_array()`).as("$data");
|
|
932
1302
|
} else {
|
|
933
|
-
return sql3`json_object(${sql3.join(objArgs)})`.as("data");
|
|
1303
|
+
return sql3`json_object(${sql3.join(objArgs)})`.as("$data");
|
|
934
1304
|
}
|
|
935
1305
|
});
|
|
936
1306
|
return tbl;
|
|
937
1307
|
}
|
|
1308
|
+
buildRelationJoinFilter(selectModelQuery, model, relationField, relationModelAlias, parentAlias) {
|
|
1309
|
+
const fieldDef = requireField(this.schema, model, relationField);
|
|
1310
|
+
const relationModel = fieldDef.type;
|
|
1311
|
+
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
1312
|
+
if (m2m) {
|
|
1313
|
+
const parentIds = getIdFields(this.schema, model);
|
|
1314
|
+
const relationIds = getIdFields(this.schema, relationModel);
|
|
1315
|
+
invariant3(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1316
|
+
invariant3(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1317
|
+
selectModelQuery = selectModelQuery.where((eb) => eb(eb.ref(`${relationModelAlias}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
1318
|
+
} else {
|
|
1319
|
+
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
1320
|
+
keyPairs.forEach(({ fk, pk }) => {
|
|
1321
|
+
if (ownedByModel) {
|
|
1322
|
+
selectModelQuery = selectModelQuery.whereRef(`${relationModelAlias}.${pk}`, "=", `${parentAlias}.${fk}`);
|
|
1323
|
+
} else {
|
|
1324
|
+
selectModelQuery = selectModelQuery.whereRef(`${relationModelAlias}.${fk}`, "=", `${parentAlias}.${pk}`);
|
|
1325
|
+
}
|
|
1326
|
+
});
|
|
1327
|
+
}
|
|
1328
|
+
return selectModelQuery;
|
|
1329
|
+
}
|
|
938
1330
|
buildSkipTake(query, skip, take) {
|
|
939
1331
|
if (take !== void 0) {
|
|
940
1332
|
query = query.limit(take);
|
|
@@ -970,93 +1362,17 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
970
1362
|
buildArrayLiteralSQL(_values) {
|
|
971
1363
|
throw new Error("SQLite does not support array literals");
|
|
972
1364
|
}
|
|
1365
|
+
get supportInsertWithDefault() {
|
|
1366
|
+
return false;
|
|
1367
|
+
}
|
|
973
1368
|
};
|
|
974
1369
|
|
|
975
1370
|
// src/client/crud/dialects/index.ts
|
|
976
1371
|
function getCrudDialect(schema, options) {
|
|
977
|
-
return
|
|
1372
|
+
return match5(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
|
|
978
1373
|
}
|
|
979
1374
|
__name(getCrudDialect, "getCrudDialect");
|
|
980
1375
|
|
|
981
|
-
// src/schema/expression.ts
|
|
982
|
-
var ExpressionUtils = {
|
|
983
|
-
literal: /* @__PURE__ */ __name((value) => {
|
|
984
|
-
return {
|
|
985
|
-
kind: "literal",
|
|
986
|
-
value
|
|
987
|
-
};
|
|
988
|
-
}, "literal"),
|
|
989
|
-
array: /* @__PURE__ */ __name((items) => {
|
|
990
|
-
return {
|
|
991
|
-
kind: "array",
|
|
992
|
-
items
|
|
993
|
-
};
|
|
994
|
-
}, "array"),
|
|
995
|
-
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
996
|
-
return {
|
|
997
|
-
kind: "call",
|
|
998
|
-
function: functionName,
|
|
999
|
-
args
|
|
1000
|
-
};
|
|
1001
|
-
}, "call"),
|
|
1002
|
-
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
1003
|
-
return {
|
|
1004
|
-
kind: "binary",
|
|
1005
|
-
op,
|
|
1006
|
-
left,
|
|
1007
|
-
right
|
|
1008
|
-
};
|
|
1009
|
-
}, "binary"),
|
|
1010
|
-
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
1011
|
-
return {
|
|
1012
|
-
kind: "unary",
|
|
1013
|
-
op,
|
|
1014
|
-
operand
|
|
1015
|
-
};
|
|
1016
|
-
}, "unary"),
|
|
1017
|
-
field: /* @__PURE__ */ __name((field) => {
|
|
1018
|
-
return {
|
|
1019
|
-
kind: "field",
|
|
1020
|
-
field
|
|
1021
|
-
};
|
|
1022
|
-
}, "field"),
|
|
1023
|
-
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
1024
|
-
return {
|
|
1025
|
-
kind: "member",
|
|
1026
|
-
receiver,
|
|
1027
|
-
members
|
|
1028
|
-
};
|
|
1029
|
-
}, "member"),
|
|
1030
|
-
_this: /* @__PURE__ */ __name(() => {
|
|
1031
|
-
return {
|
|
1032
|
-
kind: "this"
|
|
1033
|
-
};
|
|
1034
|
-
}, "_this"),
|
|
1035
|
-
_null: /* @__PURE__ */ __name(() => {
|
|
1036
|
-
return {
|
|
1037
|
-
kind: "null"
|
|
1038
|
-
};
|
|
1039
|
-
}, "_null"),
|
|
1040
|
-
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1041
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
1042
|
-
}, "and"),
|
|
1043
|
-
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1044
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
1045
|
-
}, "or"),
|
|
1046
|
-
is: /* @__PURE__ */ __name((value, kind) => {
|
|
1047
|
-
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
1048
|
-
}, "is"),
|
|
1049
|
-
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
1050
|
-
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
1051
|
-
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
1052
|
-
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
1053
|
-
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
1054
|
-
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
1055
|
-
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
1056
|
-
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
1057
|
-
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
|
|
1058
|
-
};
|
|
1059
|
-
|
|
1060
1376
|
// src/utils/default-operation-node-visitor.ts
|
|
1061
1377
|
import { OperationNodeVisitor } from "kysely";
|
|
1062
1378
|
var DefaultOperationNodeVisitor = class extends OperationNodeVisitor {
|
|
@@ -1377,18 +1693,18 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1377
1693
|
|
|
1378
1694
|
// src/plugins/policy/expression-transformer.ts
|
|
1379
1695
|
import { invariant as invariant5 } from "@zenstackhq/common-helpers";
|
|
1380
|
-
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";
|
|
1381
|
-
import { match as
|
|
1696
|
+
import { AliasNode as AliasNode2, BinaryOperationNode as BinaryOperationNode2, ColumnNode, expressionBuilder as expressionBuilder2, FromNode, FunctionNode as FunctionNode2, IdentifierNode, OperatorNode as OperatorNode2, ReferenceNode as ReferenceNode2, SelectionNode, SelectQueryNode, TableNode as TableNode2, ValueListNode, ValueNode as ValueNode2, WhereNode } from "kysely";
|
|
1697
|
+
import { match as match7 } from "ts-pattern";
|
|
1382
1698
|
|
|
1383
1699
|
// src/plugins/policy/expression-evaluator.ts
|
|
1384
1700
|
import { invariant as invariant4 } from "@zenstackhq/common-helpers";
|
|
1385
|
-
import { match as
|
|
1701
|
+
import { match as match6 } from "ts-pattern";
|
|
1386
1702
|
var ExpressionEvaluator = class {
|
|
1387
1703
|
static {
|
|
1388
1704
|
__name(this, "ExpressionEvaluator");
|
|
1389
1705
|
}
|
|
1390
1706
|
evaluate(expression, context) {
|
|
1391
|
-
const result =
|
|
1707
|
+
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();
|
|
1392
1708
|
return result ?? null;
|
|
1393
1709
|
}
|
|
1394
1710
|
evaluateCall(expr2, context) {
|
|
@@ -1399,7 +1715,7 @@ var ExpressionEvaluator = class {
|
|
|
1399
1715
|
}
|
|
1400
1716
|
}
|
|
1401
1717
|
evaluateUnary(expr2, context) {
|
|
1402
|
-
return
|
|
1718
|
+
return match6(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
|
|
1403
1719
|
}
|
|
1404
1720
|
evaluateMember(expr2, context) {
|
|
1405
1721
|
let val = this.evaluate(expr2.receiver, context);
|
|
@@ -1423,7 +1739,7 @@ var ExpressionEvaluator = class {
|
|
|
1423
1739
|
}
|
|
1424
1740
|
const left = this.evaluate(expr2.left, context);
|
|
1425
1741
|
const right = this.evaluate(expr2.right, context);
|
|
1426
|
-
return
|
|
1742
|
+
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", () => {
|
|
1427
1743
|
const _right = right ?? [];
|
|
1428
1744
|
invariant4(Array.isArray(_right), 'expected array for "in" operator');
|
|
1429
1745
|
return _right.includes(left);
|
|
@@ -1437,7 +1753,7 @@ var ExpressionEvaluator = class {
|
|
|
1437
1753
|
return false;
|
|
1438
1754
|
}
|
|
1439
1755
|
invariant4(Array.isArray(left), "expected array");
|
|
1440
|
-
return
|
|
1756
|
+
return match6(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1441
1757
|
...context,
|
|
1442
1758
|
thisValue: item
|
|
1443
1759
|
}))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
|
|
@@ -1453,11 +1769,11 @@ var ExpressionEvaluator = class {
|
|
|
1453
1769
|
// src/plugins/policy/utils.ts
|
|
1454
1770
|
import { AliasNode, AndNode, BinaryOperationNode, FunctionNode, OperatorNode, OrNode, ParensNode, ReferenceNode, TableNode, UnaryOperationNode, ValueNode } from "kysely";
|
|
1455
1771
|
function trueNode(dialect) {
|
|
1456
|
-
return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
|
|
1772
|
+
return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1457
1773
|
}
|
|
1458
1774
|
__name(trueNode, "trueNode");
|
|
1459
1775
|
function falseNode(dialect) {
|
|
1460
|
-
return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
|
|
1776
|
+
return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1461
1777
|
}
|
|
1462
1778
|
__name(falseNode, "falseNode");
|
|
1463
1779
|
function isTrueNode(node) {
|
|
@@ -1691,7 +2007,7 @@ var ExpressionTransformer = class {
|
|
|
1691
2007
|
const count = FunctionNode2.create("count", [
|
|
1692
2008
|
ValueNode2.createImmediate(1)
|
|
1693
2009
|
]);
|
|
1694
|
-
const predicateResult =
|
|
2010
|
+
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();
|
|
1695
2011
|
return this.transform(expr2.left, {
|
|
1696
2012
|
...context,
|
|
1697
2013
|
memberSelect: SelectionNode.create(AliasNode2.create(predicateResult, IdentifierNode.create("$t"))),
|
|
@@ -1715,14 +2031,14 @@ var ExpressionTransformer = class {
|
|
|
1715
2031
|
}
|
|
1716
2032
|
}
|
|
1717
2033
|
transformValue(value, type) {
|
|
1718
|
-
return ValueNode2.create(this.dialect.transformPrimitive(value, type) ?? null);
|
|
2034
|
+
return ValueNode2.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
1719
2035
|
}
|
|
1720
2036
|
_unary(expr2, context) {
|
|
1721
2037
|
invariant5(expr2.op === "!", 'only "!" operator is supported');
|
|
1722
2038
|
return BinaryOperationNode2.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
|
|
1723
2039
|
}
|
|
1724
2040
|
transformOperator(op) {
|
|
1725
|
-
const mappedOp =
|
|
2041
|
+
const mappedOp = match7(op).with("==", () => "=").otherwise(() => op);
|
|
1726
2042
|
return OperatorNode2.create(mappedOp);
|
|
1727
2043
|
}
|
|
1728
2044
|
_call(expr2, context) {
|
|
@@ -1734,7 +2050,7 @@ var ExpressionTransformer = class {
|
|
|
1734
2050
|
if (!func) {
|
|
1735
2051
|
throw new QueryError(`Function not implemented: ${expr2.function}`);
|
|
1736
2052
|
}
|
|
1737
|
-
const eb =
|
|
2053
|
+
const eb = expressionBuilder2();
|
|
1738
2054
|
return func(eb, (expr2.args ?? []).map((arg) => this.transformCallArg(eb, arg, context)), {
|
|
1739
2055
|
dialect: this.dialect,
|
|
1740
2056
|
model: context.model,
|
|
@@ -1958,7 +2274,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
1958
2274
|
get kysely() {
|
|
1959
2275
|
return this.client.$qb;
|
|
1960
2276
|
}
|
|
1961
|
-
async handle(node, proceed
|
|
2277
|
+
async handle(node, proceed) {
|
|
1962
2278
|
if (!this.isCrudQueryNode(node)) {
|
|
1963
2279
|
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
1964
2280
|
}
|
|
@@ -1978,27 +2294,20 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
1978
2294
|
if (!mutationRequiresTransaction && !node.returning) {
|
|
1979
2295
|
return proceed(this.transformNode(node));
|
|
1980
2296
|
}
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
const
|
|
1988
|
-
if (
|
|
1989
|
-
|
|
1990
|
-
if (readBackResult.rows.length !== result2.rows.length) {
|
|
1991
|
-
readBackError = true;
|
|
1992
|
-
}
|
|
1993
|
-
return readBackResult;
|
|
1994
|
-
} else {
|
|
1995
|
-
return result2;
|
|
2297
|
+
if (InsertQueryNode.is(node)) {
|
|
2298
|
+
await this.enforcePreCreatePolicy(node, proceed);
|
|
2299
|
+
}
|
|
2300
|
+
const transformedNode = this.transformNode(node);
|
|
2301
|
+
const result = await proceed(transformedNode);
|
|
2302
|
+
if (!this.onlyReturningId(node)) {
|
|
2303
|
+
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2304
|
+
if (readBackResult.rows.length !== result.rows.length) {
|
|
2305
|
+
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
1996
2306
|
}
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2307
|
+
return readBackResult;
|
|
2308
|
+
} else {
|
|
2309
|
+
return result;
|
|
2000
2310
|
}
|
|
2001
|
-
return result;
|
|
2002
2311
|
}
|
|
2003
2312
|
onlyReturningId(node) {
|
|
2004
2313
|
if (!node.returning) {
|
|
@@ -2059,11 +2368,11 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2059
2368
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2060
2369
|
invariant6(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2061
2370
|
result.push({
|
|
2062
|
-
node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
|
|
2371
|
+
node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2063
2372
|
raw: item.value
|
|
2064
2373
|
});
|
|
2065
2374
|
} else {
|
|
2066
|
-
const value = this.dialect.transformPrimitive(item, fieldDef.type);
|
|
2375
|
+
const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
2067
2376
|
if (Array.isArray(value)) {
|
|
2068
2377
|
result.push({
|
|
2069
2378
|
node: RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
@@ -2132,7 +2441,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2132
2441
|
return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => BinaryOperationNode3.create(ColumnNode2.create(field), OperatorNode3.create("="), ValueNode3.create(row[field]))))));
|
|
2133
2442
|
}
|
|
2134
2443
|
getMutationModel(node) {
|
|
2135
|
-
const r =
|
|
2444
|
+
const r = match8(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
|
|
2136
2445
|
if (node2.from.froms.length !== 1) {
|
|
2137
2446
|
throw new InternalError("Only one from table is supported for delete");
|
|
2138
2447
|
}
|
|
@@ -2294,13 +2603,22 @@ var PolicyPlugin = class {
|
|
|
2294
2603
|
get description() {
|
|
2295
2604
|
return "Enforces access policies defined in the schema.";
|
|
2296
2605
|
}
|
|
2297
|
-
onKyselyQuery({
|
|
2606
|
+
onKyselyQuery({
|
|
2607
|
+
query,
|
|
2608
|
+
client,
|
|
2609
|
+
proceed
|
|
2610
|
+
/*, transaction*/
|
|
2611
|
+
}) {
|
|
2298
2612
|
const handler = new PolicyHandler(client);
|
|
2299
|
-
return handler.handle(
|
|
2613
|
+
return handler.handle(
|
|
2614
|
+
query,
|
|
2615
|
+
proceed
|
|
2616
|
+
/*, transaction*/
|
|
2617
|
+
);
|
|
2300
2618
|
}
|
|
2301
2619
|
};
|
|
2302
2620
|
export {
|
|
2303
2621
|
PolicyPlugin,
|
|
2304
2622
|
RejectedByPolicyError
|
|
2305
2623
|
};
|
|
2306
|
-
//# sourceMappingURL=
|
|
2624
|
+
//# sourceMappingURL=index.js.map
|