@zenstackhq/runtime 3.0.0-alpha.9 → 3.0.0-beta.2
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-BiU0iYAh.d.cts → contract-CusA0mQO.d.cts} +388 -297
- package/dist/{contract-BiU0iYAh.d.ts → contract-CusA0mQO.d.ts} +388 -297
- 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 +2208 -1204
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -5
- package/dist/index.d.ts +4 -5
- package/dist/index.js +2135 -1132
- package/dist/index.js.map +1 -1
- package/dist/plugins/{policy.cjs → policy/index.cjs} +565 -272
- package/dist/plugins/policy/index.cjs.map +1 -0
- package/dist/plugins/{policy.d.ts → policy/index.d.cts} +1 -1
- package/dist/plugins/{policy.d.cts → policy/index.d.ts} +1 -1
- package/dist/plugins/{policy.js → policy/index.js} +568 -275
- 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 -14
- package/dist/plugins/policy.cjs.map +0 -1
- package/dist/plugins/policy.js.map +0 -1
|
@@ -41,15 +41,115 @@ var RejectedByPolicyError = class extends Error {
|
|
|
41
41
|
// src/plugins/policy/policy-handler.ts
|
|
42
42
|
var import_common_helpers6 = require("@zenstackhq/common-helpers");
|
|
43
43
|
var import_kysely7 = require("kysely");
|
|
44
|
-
var
|
|
44
|
+
var import_ts_pattern8 = require("ts-pattern");
|
|
45
45
|
|
|
46
46
|
// src/client/crud/dialects/index.ts
|
|
47
|
-
var
|
|
47
|
+
var import_ts_pattern5 = require("ts-pattern");
|
|
48
48
|
|
|
49
49
|
// src/client/crud/dialects/postgresql.ts
|
|
50
50
|
var import_common_helpers2 = require("@zenstackhq/common-helpers");
|
|
51
51
|
var import_kysely2 = require("kysely");
|
|
52
|
-
var
|
|
52
|
+
var import_ts_pattern3 = require("ts-pattern");
|
|
53
|
+
|
|
54
|
+
// src/client/constants.ts
|
|
55
|
+
var DELEGATE_JOINED_FIELD_PREFIX = "$delegate$";
|
|
56
|
+
var LOGICAL_COMBINATORS = [
|
|
57
|
+
"AND",
|
|
58
|
+
"OR",
|
|
59
|
+
"NOT"
|
|
60
|
+
];
|
|
61
|
+
var AGGREGATE_OPERATORS = [
|
|
62
|
+
"_count",
|
|
63
|
+
"_sum",
|
|
64
|
+
"_avg",
|
|
65
|
+
"_min",
|
|
66
|
+
"_max"
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
// src/client/query-utils.ts
|
|
70
|
+
var import_ts_pattern = require("ts-pattern");
|
|
71
|
+
|
|
72
|
+
// src/schema/expression.ts
|
|
73
|
+
var ExpressionUtils = {
|
|
74
|
+
literal: /* @__PURE__ */ __name((value) => {
|
|
75
|
+
return {
|
|
76
|
+
kind: "literal",
|
|
77
|
+
value
|
|
78
|
+
};
|
|
79
|
+
}, "literal"),
|
|
80
|
+
array: /* @__PURE__ */ __name((items) => {
|
|
81
|
+
return {
|
|
82
|
+
kind: "array",
|
|
83
|
+
items
|
|
84
|
+
};
|
|
85
|
+
}, "array"),
|
|
86
|
+
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
87
|
+
return {
|
|
88
|
+
kind: "call",
|
|
89
|
+
function: functionName,
|
|
90
|
+
args
|
|
91
|
+
};
|
|
92
|
+
}, "call"),
|
|
93
|
+
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
94
|
+
return {
|
|
95
|
+
kind: "binary",
|
|
96
|
+
op,
|
|
97
|
+
left,
|
|
98
|
+
right
|
|
99
|
+
};
|
|
100
|
+
}, "binary"),
|
|
101
|
+
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
102
|
+
return {
|
|
103
|
+
kind: "unary",
|
|
104
|
+
op,
|
|
105
|
+
operand
|
|
106
|
+
};
|
|
107
|
+
}, "unary"),
|
|
108
|
+
field: /* @__PURE__ */ __name((field) => {
|
|
109
|
+
return {
|
|
110
|
+
kind: "field",
|
|
111
|
+
field
|
|
112
|
+
};
|
|
113
|
+
}, "field"),
|
|
114
|
+
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
115
|
+
return {
|
|
116
|
+
kind: "member",
|
|
117
|
+
receiver,
|
|
118
|
+
members
|
|
119
|
+
};
|
|
120
|
+
}, "member"),
|
|
121
|
+
_this: /* @__PURE__ */ __name(() => {
|
|
122
|
+
return {
|
|
123
|
+
kind: "this"
|
|
124
|
+
};
|
|
125
|
+
}, "_this"),
|
|
126
|
+
_null: /* @__PURE__ */ __name(() => {
|
|
127
|
+
return {
|
|
128
|
+
kind: "null"
|
|
129
|
+
};
|
|
130
|
+
}, "_null"),
|
|
131
|
+
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
132
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
133
|
+
}, "and"),
|
|
134
|
+
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
135
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
136
|
+
}, "or"),
|
|
137
|
+
is: /* @__PURE__ */ __name((value, kind) => {
|
|
138
|
+
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
139
|
+
}, "is"),
|
|
140
|
+
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
141
|
+
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
142
|
+
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
143
|
+
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
144
|
+
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
145
|
+
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
146
|
+
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
147
|
+
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
148
|
+
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember"),
|
|
149
|
+
getLiteralValue: /* @__PURE__ */ __name((expr2) => {
|
|
150
|
+
return ExpressionUtils.isLiteral(expr2) ? expr2.value : void 0;
|
|
151
|
+
}, "getLiteralValue")
|
|
152
|
+
};
|
|
53
153
|
|
|
54
154
|
// src/client/errors.ts
|
|
55
155
|
var QueryError = class extends Error {
|
|
@@ -66,9 +166,6 @@ var InternalError = class extends Error {
|
|
|
66
166
|
static {
|
|
67
167
|
__name(this, "InternalError");
|
|
68
168
|
}
|
|
69
|
-
constructor(message) {
|
|
70
|
-
super(message);
|
|
71
|
-
}
|
|
72
169
|
};
|
|
73
170
|
|
|
74
171
|
// src/client/query-utils.ts
|
|
@@ -143,10 +240,15 @@ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
|
143
240
|
}
|
|
144
241
|
__name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
|
|
145
242
|
function isRelationField(schema, model, field) {
|
|
146
|
-
const fieldDef =
|
|
147
|
-
return !!fieldDef
|
|
243
|
+
const fieldDef = getField(schema, model, field);
|
|
244
|
+
return !!fieldDef?.relation;
|
|
148
245
|
}
|
|
149
246
|
__name(isRelationField, "isRelationField");
|
|
247
|
+
function isInheritedField(schema, model, field) {
|
|
248
|
+
const fieldDef = getField(schema, model, field);
|
|
249
|
+
return !!fieldDef?.originModel;
|
|
250
|
+
}
|
|
251
|
+
__name(isInheritedField, "isInheritedField");
|
|
150
252
|
function getUniqueFields(schema, model) {
|
|
151
253
|
const modelDef = requireModel(schema, model);
|
|
152
254
|
const result = [];
|
|
@@ -172,11 +274,14 @@ function getUniqueFields(schema, model) {
|
|
|
172
274
|
return result;
|
|
173
275
|
}
|
|
174
276
|
__name(getUniqueFields, "getUniqueFields");
|
|
175
|
-
function buildFieldRef(schema, model, field, options, eb, modelAlias) {
|
|
277
|
+
function buildFieldRef(schema, model, field, options, eb, modelAlias, inlineComputedField = true) {
|
|
176
278
|
const fieldDef = requireField(schema, model, field);
|
|
177
279
|
if (!fieldDef.computed) {
|
|
178
280
|
return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
|
|
179
281
|
} else {
|
|
282
|
+
if (!inlineComputedField) {
|
|
283
|
+
return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
|
|
284
|
+
}
|
|
180
285
|
let computer;
|
|
181
286
|
if ("computedFields" in options) {
|
|
182
287
|
const computedFields = options.computedFields;
|
|
@@ -185,7 +290,9 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias) {
|
|
|
185
290
|
if (!computer) {
|
|
186
291
|
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
187
292
|
}
|
|
188
|
-
return computer(eb
|
|
293
|
+
return computer(eb, {
|
|
294
|
+
currentModel: modelAlias
|
|
295
|
+
});
|
|
189
296
|
}
|
|
190
297
|
}
|
|
191
298
|
__name(buildFieldRef, "buildFieldRef");
|
|
@@ -228,11 +335,33 @@ function getManyToManyRelation(schema, model, field) {
|
|
|
228
335
|
model,
|
|
229
336
|
fieldDef.type
|
|
230
337
|
].sort();
|
|
338
|
+
let orderedFK;
|
|
339
|
+
if (model !== fieldDef.type) {
|
|
340
|
+
orderedFK = sortedModelNames[0] === model ? [
|
|
341
|
+
"A",
|
|
342
|
+
"B"
|
|
343
|
+
] : [
|
|
344
|
+
"B",
|
|
345
|
+
"A"
|
|
346
|
+
];
|
|
347
|
+
} else {
|
|
348
|
+
const sortedFieldNames = [
|
|
349
|
+
field,
|
|
350
|
+
oppositeFieldDef.name
|
|
351
|
+
].sort();
|
|
352
|
+
orderedFK = sortedFieldNames[0] === field ? [
|
|
353
|
+
"A",
|
|
354
|
+
"B"
|
|
355
|
+
] : [
|
|
356
|
+
"B",
|
|
357
|
+
"A"
|
|
358
|
+
];
|
|
359
|
+
}
|
|
231
360
|
return {
|
|
232
|
-
parentFkName:
|
|
361
|
+
parentFkName: orderedFK[0],
|
|
233
362
|
otherModel: fieldDef.type,
|
|
234
363
|
otherField: fieldDef.relation.opposite,
|
|
235
|
-
otherFkName:
|
|
364
|
+
otherFkName: orderedFK[1],
|
|
236
365
|
joinTable: fieldDef.relation.name ? `_${fieldDef.relation.name}` : `_${sortedModelNames[0]}To${sortedModelNames[1]}`
|
|
237
366
|
};
|
|
238
367
|
} else {
|
|
@@ -260,11 +389,38 @@ function flattenCompoundUniqueFilters(schema, model, filter) {
|
|
|
260
389
|
return result;
|
|
261
390
|
}
|
|
262
391
|
__name(flattenCompoundUniqueFilters, "flattenCompoundUniqueFilters");
|
|
392
|
+
function ensureArray(value) {
|
|
393
|
+
if (Array.isArray(value)) {
|
|
394
|
+
return value;
|
|
395
|
+
} else {
|
|
396
|
+
return [
|
|
397
|
+
value
|
|
398
|
+
];
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
__name(ensureArray, "ensureArray");
|
|
402
|
+
function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */ new Set()) {
|
|
403
|
+
const subModels = Object.values(schema.models).filter((m) => m.baseModel === model);
|
|
404
|
+
subModels.forEach((def) => {
|
|
405
|
+
if (!collected.has(def)) {
|
|
406
|
+
collected.add(def);
|
|
407
|
+
getDelegateDescendantModels(schema, def.name, collected);
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
return [
|
|
411
|
+
...collected
|
|
412
|
+
];
|
|
413
|
+
}
|
|
414
|
+
__name(getDelegateDescendantModels, "getDelegateDescendantModels");
|
|
415
|
+
function aggregate(eb, expr2, op) {
|
|
416
|
+
return (0, import_ts_pattern.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();
|
|
417
|
+
}
|
|
418
|
+
__name(aggregate, "aggregate");
|
|
263
419
|
|
|
264
420
|
// src/client/crud/dialects/base.ts
|
|
265
421
|
var import_common_helpers = require("@zenstackhq/common-helpers");
|
|
266
422
|
var import_kysely = require("kysely");
|
|
267
|
-
var
|
|
423
|
+
var import_ts_pattern2 = require("ts-pattern");
|
|
268
424
|
|
|
269
425
|
// src/utils/enumerate.ts
|
|
270
426
|
function enumerate(x) {
|
|
@@ -294,6 +450,44 @@ var BaseCrudDialect = class {
|
|
|
294
450
|
transformPrimitive(value, _type, _forArrayField) {
|
|
295
451
|
return value;
|
|
296
452
|
}
|
|
453
|
+
// #region common query builders
|
|
454
|
+
buildSelectModel(eb, model, modelAlias) {
|
|
455
|
+
const modelDef = requireModel(this.schema, model);
|
|
456
|
+
let result = eb.selectFrom(model === modelAlias ? model : `${model} as ${modelAlias}`);
|
|
457
|
+
let joinBase = modelDef.baseModel;
|
|
458
|
+
while (joinBase) {
|
|
459
|
+
result = this.buildDelegateJoin(model, modelAlias, joinBase, result);
|
|
460
|
+
joinBase = requireModel(this.schema, joinBase).baseModel;
|
|
461
|
+
}
|
|
462
|
+
return result;
|
|
463
|
+
}
|
|
464
|
+
buildFilterSortTake(model, args, query, modelAlias) {
|
|
465
|
+
let result = query;
|
|
466
|
+
if (args.where) {
|
|
467
|
+
result = result.where((eb) => this.buildFilter(eb, model, modelAlias, args?.where));
|
|
468
|
+
}
|
|
469
|
+
let negateOrderBy = false;
|
|
470
|
+
const skip = args.skip;
|
|
471
|
+
let take = args.take;
|
|
472
|
+
if (take !== void 0 && take < 0) {
|
|
473
|
+
negateOrderBy = true;
|
|
474
|
+
take = -take;
|
|
475
|
+
}
|
|
476
|
+
result = this.buildSkipTake(result, skip, take);
|
|
477
|
+
result = this.buildOrderBy(result, model, modelAlias, args.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
478
|
+
if ("distinct" in args && args.distinct) {
|
|
479
|
+
const distinct = ensureArray(args.distinct);
|
|
480
|
+
if (this.supportsDistinctOn) {
|
|
481
|
+
result = result.distinctOn(distinct.map((f) => import_kysely.sql.ref(`${modelAlias}.${f}`)));
|
|
482
|
+
} else {
|
|
483
|
+
throw new QueryError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
if (args.cursor) {
|
|
487
|
+
result = this.buildCursorFilter(model, result, args.cursor, args.orderBy, negateOrderBy, modelAlias);
|
|
488
|
+
}
|
|
489
|
+
return result;
|
|
490
|
+
}
|
|
297
491
|
buildFilter(eb, model, modelAlias, where) {
|
|
298
492
|
if (where === true || where === void 0) {
|
|
299
493
|
return this.true(eb);
|
|
@@ -310,17 +504,20 @@ var BaseCrudDialect = class {
|
|
|
310
504
|
if (key.startsWith("$")) {
|
|
311
505
|
continue;
|
|
312
506
|
}
|
|
313
|
-
if (key
|
|
507
|
+
if (this.isLogicalCombinator(key)) {
|
|
314
508
|
result = this.and(eb, result, this.buildCompositeFilter(eb, model, modelAlias, key, payload));
|
|
315
509
|
continue;
|
|
316
510
|
}
|
|
317
511
|
const fieldDef = requireField(this.schema, model, key);
|
|
318
512
|
if (fieldDef.relation) {
|
|
319
513
|
result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
320
|
-
} else if (fieldDef.array) {
|
|
321
|
-
result = this.and(eb, result, this.buildArrayFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
322
514
|
} else {
|
|
323
|
-
|
|
515
|
+
const fieldRef = this.fieldRef(fieldDef.originModel ?? model, key, eb, fieldDef.originModel ?? modelAlias);
|
|
516
|
+
if (fieldDef.array) {
|
|
517
|
+
result = this.and(eb, result, this.buildArrayFilter(eb, fieldRef, fieldDef, payload));
|
|
518
|
+
} else {
|
|
519
|
+
result = this.and(eb, result, this.buildPrimitiveFilter(eb, fieldRef, fieldDef, payload));
|
|
520
|
+
}
|
|
324
521
|
}
|
|
325
522
|
}
|
|
326
523
|
if ("$expr" in _where && typeof _where["$expr"] === "function") {
|
|
@@ -328,8 +525,32 @@ var BaseCrudDialect = class {
|
|
|
328
525
|
}
|
|
329
526
|
return result;
|
|
330
527
|
}
|
|
528
|
+
buildCursorFilter(model, query, cursor, orderBy, negateOrderBy, modelAlias) {
|
|
529
|
+
const _orderBy = orderBy ?? makeDefaultOrderBy(this.schema, model);
|
|
530
|
+
const orderByItems = ensureArray(_orderBy).flatMap((obj) => Object.entries(obj));
|
|
531
|
+
const eb = (0, import_kysely.expressionBuilder)();
|
|
532
|
+
const subQueryAlias = `${model}$cursor$sub`;
|
|
533
|
+
const cursorFilter = this.buildFilter(eb, model, subQueryAlias, cursor);
|
|
534
|
+
let result = query;
|
|
535
|
+
const filters = [];
|
|
536
|
+
for (let i = orderByItems.length - 1; i >= 0; i--) {
|
|
537
|
+
const andFilters = [];
|
|
538
|
+
for (let j = 0; j <= i; j++) {
|
|
539
|
+
const [field, order] = orderByItems[j];
|
|
540
|
+
const _order = negateOrderBy ? order === "asc" ? "desc" : "asc" : order;
|
|
541
|
+
const op = j === i ? _order === "asc" ? ">=" : "<=" : "=";
|
|
542
|
+
andFilters.push(eb(eb.ref(`${modelAlias}.${field}`), op, this.buildSelectModel(eb, model, subQueryAlias).select(`${subQueryAlias}.${field}`).where(cursorFilter)));
|
|
543
|
+
}
|
|
544
|
+
filters.push(eb.and(andFilters));
|
|
545
|
+
}
|
|
546
|
+
result = result.where((eb2) => eb2.or(filters));
|
|
547
|
+
return result;
|
|
548
|
+
}
|
|
549
|
+
isLogicalCombinator(key) {
|
|
550
|
+
return LOGICAL_COMBINATORS.includes(key);
|
|
551
|
+
}
|
|
331
552
|
buildCompositeFilter(eb, model, modelAlias, key, payload) {
|
|
332
|
-
return (0,
|
|
553
|
+
return (0, import_ts_pattern2.match)(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();
|
|
333
554
|
}
|
|
334
555
|
buildRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
335
556
|
if (!fieldDef.array) {
|
|
@@ -338,19 +559,26 @@ var BaseCrudDialect = class {
|
|
|
338
559
|
return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
|
|
339
560
|
}
|
|
340
561
|
}
|
|
341
|
-
buildToOneRelationFilter(eb, model,
|
|
562
|
+
buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
342
563
|
if (payload === null) {
|
|
343
564
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
344
|
-
if (ownedByModel) {
|
|
345
|
-
return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely.sql.ref(`${
|
|
565
|
+
if (ownedByModel && !fieldDef.originModel) {
|
|
566
|
+
return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely.sql.ref(`${modelAlias}.${fk}`), "is", null)));
|
|
346
567
|
} else {
|
|
347
|
-
return this.buildToOneRelationFilter(eb, model,
|
|
568
|
+
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
|
|
348
569
|
is: null
|
|
349
570
|
});
|
|
350
571
|
}
|
|
351
572
|
}
|
|
352
|
-
const joinAlias = `${
|
|
353
|
-
const joinPairs = buildJoinPairs(
|
|
573
|
+
const joinAlias = `${modelAlias}$${field}`;
|
|
574
|
+
const joinPairs = buildJoinPairs(
|
|
575
|
+
this.schema,
|
|
576
|
+
model,
|
|
577
|
+
// if field is from a base, use the base model to join
|
|
578
|
+
fieldDef.originModel ?? modelAlias,
|
|
579
|
+
field,
|
|
580
|
+
joinAlias
|
|
581
|
+
);
|
|
354
582
|
const filterResultField = `${field}$filter`;
|
|
355
583
|
const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
|
|
356
584
|
const conditions = [];
|
|
@@ -380,25 +608,26 @@ var BaseCrudDialect = class {
|
|
|
380
608
|
}
|
|
381
609
|
return this.and(eb, ...conditions);
|
|
382
610
|
}
|
|
383
|
-
buildToManyRelationFilter(eb, model,
|
|
611
|
+
buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
384
612
|
if (payload === null) {
|
|
385
|
-
return eb(import_kysely.sql.ref(`${
|
|
613
|
+
return eb(import_kysely.sql.ref(`${modelAlias}.${field}`), "is", null);
|
|
386
614
|
}
|
|
387
615
|
const relationModel = fieldDef.type;
|
|
616
|
+
const relationFilterSelectAlias = `${modelAlias}$${field}$filter`;
|
|
388
617
|
const buildPkFkWhereRefs = /* @__PURE__ */ __name((eb2) => {
|
|
389
618
|
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
390
619
|
if (m2m) {
|
|
391
620
|
const modelIdField = getIdFields(this.schema, model)[0];
|
|
392
621
|
const relationIdField = getIdFields(this.schema, relationModel)[0];
|
|
393
|
-
return eb2(import_kysely.sql.ref(`${
|
|
622
|
+
return eb2(import_kysely.sql.ref(`${relationFilterSelectAlias}.${relationIdField}`), "in", eb2.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(import_kysely.sql.ref(`${m2m.joinTable}.${m2m.parentFkName}`), "=", import_kysely.sql.ref(`${modelAlias}.${modelIdField}`)));
|
|
394
623
|
} else {
|
|
395
624
|
const relationKeyPairs = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
396
625
|
let result2 = this.true(eb2);
|
|
397
626
|
for (const { fk, pk } of relationKeyPairs.keyPairs) {
|
|
398
627
|
if (relationKeyPairs.ownedByModel) {
|
|
399
|
-
result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${
|
|
628
|
+
result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${modelAlias}.${fk}`), "=", import_kysely.sql.ref(`${relationFilterSelectAlias}.${pk}`)));
|
|
400
629
|
} else {
|
|
401
|
-
result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${
|
|
630
|
+
result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${modelAlias}.${pk}`), "=", import_kysely.sql.ref(`${relationFilterSelectAlias}.${fk}`)));
|
|
402
631
|
}
|
|
403
632
|
}
|
|
404
633
|
return result2;
|
|
@@ -411,25 +640,24 @@ var BaseCrudDialect = class {
|
|
|
411
640
|
}
|
|
412
641
|
switch (key) {
|
|
413
642
|
case "some": {
|
|
414
|
-
result = this.and(eb, result, eb(
|
|
643
|
+
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));
|
|
415
644
|
break;
|
|
416
645
|
}
|
|
417
646
|
case "every": {
|
|
418
|
-
result = this.and(eb, result, eb(
|
|
647
|
+
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));
|
|
419
648
|
break;
|
|
420
649
|
}
|
|
421
650
|
case "none": {
|
|
422
|
-
result = this.and(eb, result, eb(
|
|
651
|
+
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));
|
|
423
652
|
break;
|
|
424
653
|
}
|
|
425
654
|
}
|
|
426
655
|
}
|
|
427
656
|
return result;
|
|
428
657
|
}
|
|
429
|
-
buildArrayFilter(eb,
|
|
658
|
+
buildArrayFilter(eb, fieldRef, fieldDef, payload) {
|
|
430
659
|
const clauses = [];
|
|
431
660
|
const fieldType = fieldDef.type;
|
|
432
|
-
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
|
|
433
661
|
for (const [key, _value] of Object.entries(payload)) {
|
|
434
662
|
if (_value === void 0) {
|
|
435
663
|
continue;
|
|
@@ -465,14 +693,14 @@ var BaseCrudDialect = class {
|
|
|
465
693
|
}
|
|
466
694
|
return this.and(eb, ...clauses);
|
|
467
695
|
}
|
|
468
|
-
buildPrimitiveFilter(eb,
|
|
696
|
+
buildPrimitiveFilter(eb, fieldRef, fieldDef, payload) {
|
|
469
697
|
if (payload === null) {
|
|
470
|
-
return eb(
|
|
698
|
+
return eb(fieldRef, "is", null);
|
|
471
699
|
}
|
|
472
700
|
if (isEnum(this.schema, fieldDef.type)) {
|
|
473
|
-
return this.buildEnumFilter(eb,
|
|
701
|
+
return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
|
|
474
702
|
}
|
|
475
|
-
return (0,
|
|
703
|
+
return (0, import_ts_pattern2.match)(fieldDef.type).with("String", () => this.buildStringFilter(eb, fieldRef, payload)).with(import_ts_pattern2.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", () => {
|
|
476
704
|
throw new InternalError("JSON filters are not supported yet");
|
|
477
705
|
}).with("Unsupported", () => {
|
|
478
706
|
throw new QueryError(`Unsupported field cannot be used in filters`);
|
|
@@ -481,7 +709,7 @@ var BaseCrudDialect = class {
|
|
|
481
709
|
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
482
710
|
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
483
711
|
}
|
|
484
|
-
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
|
|
712
|
+
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
485
713
|
if (payload === null || !(0, import_common_helpers.isPlainObject)(payload)) {
|
|
486
714
|
return {
|
|
487
715
|
conditions: [
|
|
@@ -496,8 +724,11 @@ var BaseCrudDialect = class {
|
|
|
496
724
|
if (onlyForKeys && !onlyForKeys.includes(op)) {
|
|
497
725
|
continue;
|
|
498
726
|
}
|
|
727
|
+
if (excludeKeys.includes(op)) {
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
499
730
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
500
|
-
const condition = (0,
|
|
731
|
+
const condition = (0, import_ts_pattern2.match)(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
501
732
|
(0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
502
733
|
if (rhs.length === 0) {
|
|
503
734
|
return this.false(eb);
|
|
@@ -511,7 +742,11 @@ var BaseCrudDialect = class {
|
|
|
511
742
|
} else {
|
|
512
743
|
return eb.not(eb(lhs, "in", rhs));
|
|
513
744
|
}
|
|
514
|
-
}).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))).
|
|
745
|
+
}).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(import_ts_pattern2.P.union(...AGGREGATE_OPERATORS), (op2) => {
|
|
746
|
+
const innerResult = this.buildStandardFilter(eb, type, value, aggregate(eb, lhs, op2), getRhs, recurse, throwIfInvalid);
|
|
747
|
+
consumedKeys.push(...innerResult.consumedKeys);
|
|
748
|
+
return this.and(eb, ...innerResult.conditions);
|
|
749
|
+
}).otherwise(() => {
|
|
515
750
|
if (throwIfInvalid) {
|
|
516
751
|
throw new QueryError(`Invalid filter key: ${op}`);
|
|
517
752
|
} else {
|
|
@@ -528,24 +763,21 @@ var BaseCrudDialect = class {
|
|
|
528
763
|
consumedKeys
|
|
529
764
|
};
|
|
530
765
|
}
|
|
531
|
-
buildStringFilter(eb,
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
if (payload && typeof payload === "object" && "mode" in payload && payload.mode === "insensitive") {
|
|
536
|
-
insensitive = true;
|
|
537
|
-
fieldRef = eb.fn("lower", [
|
|
538
|
-
fieldRef
|
|
539
|
-
]);
|
|
766
|
+
buildStringFilter(eb, fieldRef, payload) {
|
|
767
|
+
let mode;
|
|
768
|
+
if (payload && typeof payload === "object" && "mode" in payload) {
|
|
769
|
+
mode = payload.mode;
|
|
540
770
|
}
|
|
541
|
-
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload,
|
|
771
|
+
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, mode === "insensitive" ? eb.fn("lower", [
|
|
772
|
+
fieldRef
|
|
773
|
+
]) : fieldRef, (value) => this.prepStringCasing(eb, value, mode), (value) => this.buildStringFilter(eb, fieldRef, value));
|
|
542
774
|
if (payload && typeof payload === "object") {
|
|
543
775
|
for (const [key, value] of Object.entries(payload)) {
|
|
544
776
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
545
777
|
continue;
|
|
546
778
|
}
|
|
547
|
-
const condition = (0,
|
|
548
|
-
throw new
|
|
779
|
+
const condition = (0, import_ts_pattern2.match)(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely.sql.val(`%${value}%`)) : eb(fieldRef, "like", import_kysely.sql.val(`%${value}%`))).with("startsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely.sql.val(`${value}%`)) : eb(fieldRef, "like", import_kysely.sql.val(`${value}%`))).with("endsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely.sql.val(`%${value}`)) : eb(fieldRef, "like", import_kysely.sql.val(`%${value}`))).otherwise(() => {
|
|
780
|
+
throw new QueryError(`Invalid string filter key: ${key}`);
|
|
549
781
|
});
|
|
550
782
|
if (condition) {
|
|
551
783
|
conditions.push(condition);
|
|
@@ -554,34 +786,37 @@ var BaseCrudDialect = class {
|
|
|
554
786
|
}
|
|
555
787
|
return this.and(eb, ...conditions);
|
|
556
788
|
}
|
|
557
|
-
prepStringCasing(eb, value,
|
|
789
|
+
prepStringCasing(eb, value, mode) {
|
|
790
|
+
if (!mode || mode === "default") {
|
|
791
|
+
return value === null ? value : import_kysely.sql.val(value);
|
|
792
|
+
}
|
|
558
793
|
if (typeof value === "string") {
|
|
559
|
-
return
|
|
560
|
-
import_kysely.sql.
|
|
561
|
-
])
|
|
794
|
+
return eb.fn("lower", [
|
|
795
|
+
import_kysely.sql.val(value)
|
|
796
|
+
]);
|
|
562
797
|
} else if (Array.isArray(value)) {
|
|
563
|
-
return value.map((v) => this.prepStringCasing(eb, v,
|
|
798
|
+
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
564
799
|
} else {
|
|
565
|
-
return value === null ? null : import_kysely.sql.
|
|
800
|
+
return value === null ? null : import_kysely.sql.val(value);
|
|
566
801
|
}
|
|
567
802
|
}
|
|
568
|
-
buildNumberFilter(eb,
|
|
569
|
-
const { conditions } = this.buildStandardFilter(eb, type, payload,
|
|
803
|
+
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
804
|
+
const { conditions } = this.buildStandardFilter(eb, type, payload, fieldRef, (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, fieldRef, type, value));
|
|
570
805
|
return this.and(eb, ...conditions);
|
|
571
806
|
}
|
|
572
|
-
buildBooleanFilter(eb,
|
|
573
|
-
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload,
|
|
807
|
+
buildBooleanFilter(eb, fieldRef, payload) {
|
|
808
|
+
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, fieldRef, (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, fieldRef, value), true, [
|
|
574
809
|
"equals",
|
|
575
810
|
"not"
|
|
576
811
|
]);
|
|
577
812
|
return this.and(eb, ...conditions);
|
|
578
813
|
}
|
|
579
|
-
buildDateTimeFilter(eb,
|
|
580
|
-
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload,
|
|
814
|
+
buildDateTimeFilter(eb, fieldRef, payload) {
|
|
815
|
+
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, fieldRef, (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, fieldRef, value), true);
|
|
581
816
|
return this.and(eb, ...conditions);
|
|
582
817
|
}
|
|
583
|
-
buildBytesFilter(eb,
|
|
584
|
-
const conditions = this.buildStandardFilter(eb, "Bytes", payload,
|
|
818
|
+
buildBytesFilter(eb, fieldRef, payload) {
|
|
819
|
+
const conditions = this.buildStandardFilter(eb, "Bytes", payload, fieldRef, (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, fieldRef, value), true, [
|
|
585
820
|
"equals",
|
|
586
821
|
"in",
|
|
587
822
|
"notIn",
|
|
@@ -589,8 +824,8 @@ var BaseCrudDialect = class {
|
|
|
589
824
|
]);
|
|
590
825
|
return this.and(eb, ...conditions.conditions);
|
|
591
826
|
}
|
|
592
|
-
buildEnumFilter(eb,
|
|
593
|
-
const conditions = this.buildStandardFilter(eb, "String", payload,
|
|
827
|
+
buildEnumFilter(eb, fieldRef, fieldDef, payload) {
|
|
828
|
+
const conditions = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => value, (value) => this.buildEnumFilter(eb, fieldRef, fieldDef, value), true, [
|
|
594
829
|
"equals",
|
|
595
830
|
"in",
|
|
596
831
|
"notIn",
|
|
@@ -622,9 +857,7 @@ var BaseCrudDialect = class {
|
|
|
622
857
|
(0, import_common_helpers.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
623
858
|
for (const [k, v] of Object.entries(value)) {
|
|
624
859
|
(0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
625
|
-
result = result.orderBy((eb) => eb.
|
|
626
|
-
import_kysely.sql.ref(k)
|
|
627
|
-
]), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
860
|
+
result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
628
861
|
}
|
|
629
862
|
continue;
|
|
630
863
|
}
|
|
@@ -633,7 +866,7 @@ var BaseCrudDialect = class {
|
|
|
633
866
|
(0, import_common_helpers.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
|
|
634
867
|
for (const [k, v] of Object.entries(value)) {
|
|
635
868
|
(0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
636
|
-
result = result.orderBy((eb) => eb.fn.count(
|
|
869
|
+
result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
637
870
|
}
|
|
638
871
|
continue;
|
|
639
872
|
}
|
|
@@ -642,10 +875,11 @@ var BaseCrudDialect = class {
|
|
|
642
875
|
}
|
|
643
876
|
const fieldDef = requireField(this.schema, model, field);
|
|
644
877
|
if (!fieldDef.relation) {
|
|
878
|
+
const fieldRef = this.fieldRef(model, field, (0, import_kysely.expressionBuilder)(), modelAlias);
|
|
645
879
|
if (value === "asc" || value === "desc") {
|
|
646
|
-
result = result.orderBy(
|
|
880
|
+
result = result.orderBy(fieldRef, this.negateSort(value, negated));
|
|
647
881
|
} else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
|
|
648
|
-
result = result.orderBy(
|
|
882
|
+
result = result.orderBy(fieldRef, import_kysely.sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
|
|
649
883
|
}
|
|
650
884
|
} else {
|
|
651
885
|
const relationModel = fieldDef.type;
|
|
@@ -657,8 +891,9 @@ var BaseCrudDialect = class {
|
|
|
657
891
|
(0, import_common_helpers.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
658
892
|
const sort = this.negateSort(value._count, negated);
|
|
659
893
|
result = result.orderBy((eb) => {
|
|
660
|
-
|
|
661
|
-
|
|
894
|
+
const subQueryAlias = `${modelAlias}$orderBy$${field}$count`;
|
|
895
|
+
let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
|
|
896
|
+
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, subQueryAlias);
|
|
662
897
|
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right)))));
|
|
663
898
|
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
664
899
|
return subQuery;
|
|
@@ -676,6 +911,92 @@ var BaseCrudDialect = class {
|
|
|
676
911
|
});
|
|
677
912
|
return result;
|
|
678
913
|
}
|
|
914
|
+
buildSelectAllFields(model, query, omit, modelAlias) {
|
|
915
|
+
const modelDef = requireModel(this.schema, model);
|
|
916
|
+
let result = query;
|
|
917
|
+
for (const field of Object.keys(modelDef.fields)) {
|
|
918
|
+
if (isRelationField(this.schema, model, field)) {
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
921
|
+
if (omit?.[field] === true) {
|
|
922
|
+
continue;
|
|
923
|
+
}
|
|
924
|
+
result = this.buildSelectField(result, model, modelAlias, field);
|
|
925
|
+
}
|
|
926
|
+
const descendants = getDelegateDescendantModels(this.schema, model);
|
|
927
|
+
for (const subModel of descendants) {
|
|
928
|
+
result = this.buildDelegateJoin(model, modelAlias, subModel.name, result);
|
|
929
|
+
result = result.select((eb) => {
|
|
930
|
+
const jsonObject = {};
|
|
931
|
+
for (const field of Object.keys(subModel.fields)) {
|
|
932
|
+
if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
935
|
+
jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
|
|
936
|
+
}
|
|
937
|
+
return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
return result;
|
|
941
|
+
}
|
|
942
|
+
buildModelSelect(eb, model, subQueryAlias, payload, selectAllFields) {
|
|
943
|
+
let subQuery = this.buildSelectModel(eb, model, subQueryAlias);
|
|
944
|
+
if (selectAllFields) {
|
|
945
|
+
subQuery = this.buildSelectAllFields(model, subQuery, typeof payload === "object" ? payload?.omit : void 0, subQueryAlias);
|
|
946
|
+
}
|
|
947
|
+
if (payload && typeof payload === "object") {
|
|
948
|
+
subQuery = this.buildFilterSortTake(model, payload, subQuery, subQueryAlias);
|
|
949
|
+
}
|
|
950
|
+
return subQuery;
|
|
951
|
+
}
|
|
952
|
+
buildSelectField(query, model, modelAlias, field) {
|
|
953
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
954
|
+
if (fieldDef.computed) {
|
|
955
|
+
return query.select((eb) => this.fieldRef(model, field, eb, modelAlias).as(field));
|
|
956
|
+
} else if (!fieldDef.originModel) {
|
|
957
|
+
return query.select(import_kysely.sql.ref(`${modelAlias}.${field}`).as(field));
|
|
958
|
+
} else {
|
|
959
|
+
return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
buildDelegateJoin(thisModel, thisModelAlias, otherModelAlias, query) {
|
|
963
|
+
const idFields = getIdFields(this.schema, thisModel);
|
|
964
|
+
query = query.leftJoin(otherModelAlias, (qb) => {
|
|
965
|
+
for (const idField of idFields) {
|
|
966
|
+
qb = qb.onRef(`${thisModelAlias}.${idField}`, "=", `${otherModelAlias}.${idField}`);
|
|
967
|
+
}
|
|
968
|
+
return qb;
|
|
969
|
+
});
|
|
970
|
+
return query;
|
|
971
|
+
}
|
|
972
|
+
buildCountJson(model, eb, parentAlias, payload) {
|
|
973
|
+
const modelDef = requireModel(this.schema, model);
|
|
974
|
+
const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
|
|
975
|
+
const selections = payload === true ? {
|
|
976
|
+
select: toManyRelations.reduce((acc, [field]) => {
|
|
977
|
+
acc[field] = true;
|
|
978
|
+
return acc;
|
|
979
|
+
}, {})
|
|
980
|
+
} : payload;
|
|
981
|
+
const jsonObject = {};
|
|
982
|
+
for (const [field, value] of Object.entries(selections.select)) {
|
|
983
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
984
|
+
const fieldModel = fieldDef.type;
|
|
985
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
986
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
987
|
+
for (const [left, right] of joinPairs) {
|
|
988
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
989
|
+
}
|
|
990
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
991
|
+
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
992
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
993
|
+
}
|
|
994
|
+
jsonObject[field] = fieldCountQuery;
|
|
995
|
+
}
|
|
996
|
+
return this.buildJsonObject(eb, jsonObject);
|
|
997
|
+
}
|
|
998
|
+
// #endregion
|
|
999
|
+
// #region utils
|
|
679
1000
|
negateSort(sort, negated) {
|
|
680
1001
|
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
681
1002
|
}
|
|
@@ -722,6 +1043,21 @@ var BaseCrudDialect = class {
|
|
|
722
1043
|
not(eb, ...args) {
|
|
723
1044
|
return eb.not(this.and(eb, ...args));
|
|
724
1045
|
}
|
|
1046
|
+
fieldRef(model, field, eb, modelAlias, inlineComputedField = true) {
|
|
1047
|
+
return buildFieldRef(this.schema, model, field, this.options, eb, modelAlias, inlineComputedField);
|
|
1048
|
+
}
|
|
1049
|
+
canJoinWithoutNestedSelect(modelDef, payload) {
|
|
1050
|
+
if (modelDef.computedFields) {
|
|
1051
|
+
return false;
|
|
1052
|
+
}
|
|
1053
|
+
if (modelDef.baseModel || modelDef.isDelegate) {
|
|
1054
|
+
return false;
|
|
1055
|
+
}
|
|
1056
|
+
if (typeof payload === "object" && (payload.orderBy || payload.skip !== void 0 || payload.take !== void 0 || payload.cursor || payload.distinct)) {
|
|
1057
|
+
return false;
|
|
1058
|
+
}
|
|
1059
|
+
return true;
|
|
1060
|
+
}
|
|
725
1061
|
};
|
|
726
1062
|
|
|
727
1063
|
// src/client/crud/dialects/postgresql.ts
|
|
@@ -743,98 +1079,110 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
743
1079
|
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
744
1080
|
}
|
|
745
1081
|
} else {
|
|
746
|
-
return (0,
|
|
1082
|
+
return (0, import_ts_pattern3.match)(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
|
|
747
1083
|
}
|
|
748
1084
|
}
|
|
749
1085
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
750
|
-
const
|
|
751
|
-
|
|
1086
|
+
const relationResultName = `${parentAlias}$${relationField}`;
|
|
1087
|
+
const joinedQuery = this.buildRelationJSON(model, query, relationField, parentAlias, payload, relationResultName);
|
|
1088
|
+
return joinedQuery.select(`${relationResultName}.$data as ${relationField}`);
|
|
752
1089
|
}
|
|
753
|
-
buildRelationJSON(model, qb, relationField,
|
|
1090
|
+
buildRelationJSON(model, qb, relationField, parentAlias, payload, resultName) {
|
|
754
1091
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
755
1092
|
const relationModel = relationFieldDef.type;
|
|
756
1093
|
return qb.leftJoinLateral((eb) => {
|
|
757
|
-
const
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
subQuery = this.buildOrderBy(subQuery, relationModel, relationModel, payload.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
774
|
-
}
|
|
775
|
-
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
776
|
-
if (m2m) {
|
|
777
|
-
const parentIds = getIdFields(this.schema, model);
|
|
778
|
-
const relationIds = getIdFields(this.schema, relationModel);
|
|
779
|
-
(0, import_common_helpers2.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
780
|
-
(0, import_common_helpers2.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
781
|
-
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}`)));
|
|
782
|
-
} else {
|
|
783
|
-
const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField, relationModel);
|
|
784
|
-
subQuery = subQuery.where((eb2) => this.and(eb2, ...joinPairs.map(([left, right]) => eb2(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right)))));
|
|
785
|
-
}
|
|
786
|
-
return subQuery.as(joinTableName);
|
|
787
|
-
});
|
|
788
|
-
result = this.buildRelationObjectSelect(relationModel, relationField, relationFieldDef, result, payload, parentName);
|
|
789
|
-
result = this.buildRelationJoins(relationModel, relationField, result, payload, parentName);
|
|
790
|
-
return result.as(joinTableName);
|
|
1094
|
+
const relationSelectName = `${resultName}$sub`;
|
|
1095
|
+
const relationModelDef = requireModel(this.schema, relationModel);
|
|
1096
|
+
let tbl;
|
|
1097
|
+
if (this.canJoinWithoutNestedSelect(relationModelDef, payload)) {
|
|
1098
|
+
tbl = this.buildModelSelect(eb, relationModel, relationSelectName, payload, false);
|
|
1099
|
+
tbl = this.buildRelationJoinFilter(tbl, model, relationField, relationModel, relationSelectName, parentAlias);
|
|
1100
|
+
} else {
|
|
1101
|
+
tbl = eb.selectFrom(() => {
|
|
1102
|
+
let subQuery = this.buildModelSelect(eb, relationModel, `${relationSelectName}$t`, payload, true);
|
|
1103
|
+
subQuery = this.buildRelationJoinFilter(subQuery, model, relationField, relationModel, `${relationSelectName}$t`, parentAlias);
|
|
1104
|
+
return subQuery.as(relationSelectName);
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
tbl = this.buildRelationObjectSelect(relationModel, relationSelectName, relationFieldDef, tbl, payload, resultName);
|
|
1108
|
+
tbl = this.buildRelationJoins(tbl, relationModel, relationSelectName, payload, resultName);
|
|
1109
|
+
return tbl.as(resultName);
|
|
791
1110
|
}, (join) => join.onTrue());
|
|
792
1111
|
}
|
|
793
|
-
|
|
1112
|
+
buildRelationJoinFilter(query, model, relationField, relationModel, relationModelAlias, parentAlias) {
|
|
1113
|
+
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
1114
|
+
if (m2m) {
|
|
1115
|
+
const parentIds = getIdFields(this.schema, model);
|
|
1116
|
+
const relationIds = getIdFields(this.schema, relationModel);
|
|
1117
|
+
(0, import_common_helpers2.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1118
|
+
(0, import_common_helpers2.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1119
|
+
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}`)));
|
|
1120
|
+
} else {
|
|
1121
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, relationField, relationModelAlias);
|
|
1122
|
+
query = query.where((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right)))));
|
|
1123
|
+
}
|
|
1124
|
+
return query;
|
|
1125
|
+
}
|
|
1126
|
+
buildRelationObjectSelect(relationModel, relationModelAlias, relationFieldDef, qb, payload, parentResultName) {
|
|
794
1127
|
qb = qb.select((eb) => {
|
|
795
|
-
const objArgs = this.buildRelationObjectArgs(relationModel,
|
|
1128
|
+
const objArgs = this.buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName);
|
|
796
1129
|
if (relationFieldDef.array) {
|
|
797
|
-
return eb.fn.coalesce(import_kysely2.sql`jsonb_agg(jsonb_build_object(${import_kysely2.sql.join(objArgs)}))`, import_kysely2.sql`'[]'::jsonb`).as("$
|
|
1130
|
+
return eb.fn.coalesce(import_kysely2.sql`jsonb_agg(jsonb_build_object(${import_kysely2.sql.join(objArgs)}))`, import_kysely2.sql`'[]'::jsonb`).as("$data");
|
|
798
1131
|
} else {
|
|
799
|
-
return import_kysely2.sql`jsonb_build_object(${import_kysely2.sql.join(objArgs)})`.as("$
|
|
1132
|
+
return import_kysely2.sql`jsonb_build_object(${import_kysely2.sql.join(objArgs)})`.as("$data");
|
|
800
1133
|
}
|
|
801
1134
|
});
|
|
802
1135
|
return qb;
|
|
803
1136
|
}
|
|
804
|
-
buildRelationObjectArgs(relationModel,
|
|
1137
|
+
buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName) {
|
|
805
1138
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
806
1139
|
const objArgs = [];
|
|
1140
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1141
|
+
if (descendantModels.length > 0) {
|
|
1142
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1143
|
+
import_kysely2.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1144
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1145
|
+
]).flatMap((v) => v));
|
|
1146
|
+
}
|
|
807
1147
|
if (payload === true || !payload.select) {
|
|
808
1148
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
809
1149
|
import_kysely2.sql.lit(field),
|
|
810
|
-
|
|
1150
|
+
this.fieldRef(relationModel, field, eb, relationModelAlias, false)
|
|
811
1151
|
]).flatMap((v) => v));
|
|
812
1152
|
} else if (payload.select) {
|
|
813
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => {
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
1153
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1154
|
+
if (field === "_count") {
|
|
1155
|
+
const subJson = this.buildCountJson(relationModel, eb, relationModelAlias, value);
|
|
1156
|
+
return [
|
|
1157
|
+
import_kysely2.sql.lit(field),
|
|
1158
|
+
subJson
|
|
1159
|
+
];
|
|
1160
|
+
} else {
|
|
1161
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1162
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentResultName}$${field}.$data`) : this.fieldRef(relationModel, field, eb, relationModelAlias, false);
|
|
1163
|
+
return [
|
|
1164
|
+
import_kysely2.sql.lit(field),
|
|
1165
|
+
fieldValue
|
|
1166
|
+
];
|
|
1167
|
+
}
|
|
820
1168
|
}).flatMap((v) => v));
|
|
821
1169
|
}
|
|
822
1170
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
823
1171
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
824
1172
|
import_kysely2.sql.lit(field),
|
|
825
1173
|
// reference the synthesized JSON field
|
|
826
|
-
eb.ref(`${
|
|
1174
|
+
eb.ref(`${parentResultName}$${field}.$data`)
|
|
827
1175
|
]).flatMap((v) => v));
|
|
828
1176
|
}
|
|
829
1177
|
return objArgs;
|
|
830
1178
|
}
|
|
831
|
-
buildRelationJoins(
|
|
832
|
-
let result =
|
|
1179
|
+
buildRelationJoins(query, relationModel, relationModelAlias, payload, parentResultName) {
|
|
1180
|
+
let result = query;
|
|
833
1181
|
if (typeof payload === "object") {
|
|
834
1182
|
const selectInclude = payload.include ?? payload.select;
|
|
835
1183
|
if (selectInclude && typeof selectInclude === "object") {
|
|
836
1184
|
Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
|
|
837
|
-
result = this.buildRelationJSON(relationModel, result, field, `${
|
|
1185
|
+
result = this.buildRelationJSON(relationModel, result, field, relationModelAlias, value, `${parentResultName}$${field}`);
|
|
838
1186
|
});
|
|
839
1187
|
}
|
|
840
1188
|
}
|
|
@@ -876,12 +1224,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
876
1224
|
return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
|
|
877
1225
|
}
|
|
878
1226
|
}
|
|
1227
|
+
get supportInsertWithDefault() {
|
|
1228
|
+
return true;
|
|
1229
|
+
}
|
|
879
1230
|
};
|
|
880
1231
|
|
|
881
1232
|
// src/client/crud/dialects/sqlite.ts
|
|
882
1233
|
var import_common_helpers3 = require("@zenstackhq/common-helpers");
|
|
883
1234
|
var import_kysely3 = require("kysely");
|
|
884
|
-
var
|
|
1235
|
+
var import_ts_pattern4 = require("ts-pattern");
|
|
885
1236
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
886
1237
|
static {
|
|
887
1238
|
__name(this, "SqliteCrudDialect");
|
|
@@ -896,79 +1247,75 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
896
1247
|
if (Array.isArray(value)) {
|
|
897
1248
|
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
898
1249
|
} else {
|
|
899
|
-
|
|
1250
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1251
|
+
return JSON.stringify(value);
|
|
1252
|
+
} else {
|
|
1253
|
+
return (0, import_ts_pattern4.match)(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).with("Json", () => JSON.stringify(value)).otherwise(() => value);
|
|
1254
|
+
}
|
|
900
1255
|
}
|
|
901
1256
|
}
|
|
902
1257
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
903
1258
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
904
1259
|
}
|
|
905
|
-
buildRelationJSON(model, eb, relationField,
|
|
1260
|
+
buildRelationJSON(model, eb, relationField, parentAlias, payload) {
|
|
906
1261
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
907
1262
|
const relationModel = relationFieldDef.type;
|
|
908
1263
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
909
|
-
const subQueryName = `${
|
|
910
|
-
let tbl
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
const
|
|
917
|
-
let
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
}
|
|
923
|
-
subQuery = this.buildSkipTake(subQuery, skip, take);
|
|
924
|
-
subQuery = this.buildOrderBy(subQuery, relationModel, relationModel, payload.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
925
|
-
}
|
|
926
|
-
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
927
|
-
if (m2m) {
|
|
928
|
-
const parentIds = getIdFields(this.schema, model);
|
|
929
|
-
const relationIds = getIdFields(this.schema, relationModel);
|
|
930
|
-
(0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
931
|
-
(0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
932
|
-
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}`)));
|
|
933
|
-
} else {
|
|
934
|
-
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
935
|
-
keyPairs.forEach(({ fk, pk }) => {
|
|
936
|
-
if (ownedByModel) {
|
|
937
|
-
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentName}.${fk}`);
|
|
938
|
-
} else {
|
|
939
|
-
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentName}.${pk}`);
|
|
940
|
-
}
|
|
941
|
-
});
|
|
942
|
-
}
|
|
943
|
-
return subQuery.as(subQueryName);
|
|
944
|
-
});
|
|
1264
|
+
const subQueryName = `${parentAlias}$${relationField}`;
|
|
1265
|
+
let tbl;
|
|
1266
|
+
if (this.canJoinWithoutNestedSelect(relationModelDef, payload)) {
|
|
1267
|
+
tbl = this.buildModelSelect(eb, relationModel, subQueryName, payload, false);
|
|
1268
|
+
tbl = this.buildRelationJoinFilter(tbl, model, relationField, subQueryName, parentAlias);
|
|
1269
|
+
} else {
|
|
1270
|
+
tbl = eb.selectFrom(() => {
|
|
1271
|
+
const selectModelAlias = `${parentAlias}$${relationField}$sub`;
|
|
1272
|
+
let selectModelQuery = this.buildModelSelect(eb, relationModel, selectModelAlias, payload, true);
|
|
1273
|
+
selectModelQuery = this.buildRelationJoinFilter(selectModelQuery, model, relationField, selectModelAlias, parentAlias);
|
|
1274
|
+
return selectModelQuery.as(subQueryName);
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
945
1277
|
tbl = tbl.select(() => {
|
|
946
1278
|
const objArgs = [];
|
|
1279
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1280
|
+
if (descendantModels.length > 0) {
|
|
1281
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1282
|
+
import_kysely3.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1283
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1284
|
+
]).flatMap((v) => v));
|
|
1285
|
+
}
|
|
947
1286
|
if (payload === true || !payload.select) {
|
|
948
1287
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
949
1288
|
import_kysely3.sql.lit(field),
|
|
950
|
-
|
|
1289
|
+
this.fieldRef(relationModel, field, eb, subQueryName, false)
|
|
951
1290
|
]).flatMap((v) => v));
|
|
952
1291
|
} else if (payload.select) {
|
|
953
1292
|
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
|
|
1293
|
+
if (field === "_count") {
|
|
1294
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
957
1295
|
return [
|
|
958
1296
|
import_kysely3.sql.lit(field),
|
|
959
1297
|
subJson
|
|
960
1298
|
];
|
|
961
1299
|
} else {
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1300
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1301
|
+
if (fieldDef.relation) {
|
|
1302
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1303
|
+
return [
|
|
1304
|
+
import_kysely3.sql.lit(field),
|
|
1305
|
+
subJson
|
|
1306
|
+
];
|
|
1307
|
+
} else {
|
|
1308
|
+
return [
|
|
1309
|
+
import_kysely3.sql.lit(field),
|
|
1310
|
+
this.fieldRef(relationModel, field, eb, subQueryName, false)
|
|
1311
|
+
];
|
|
1312
|
+
}
|
|
966
1313
|
}
|
|
967
1314
|
}).flatMap((v) => v));
|
|
968
1315
|
}
|
|
969
1316
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
970
1317
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
971
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${
|
|
1318
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
972
1319
|
return [
|
|
973
1320
|
import_kysely3.sql.lit(field),
|
|
974
1321
|
subJson
|
|
@@ -976,13 +1323,35 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
976
1323
|
}).flatMap((v) => v));
|
|
977
1324
|
}
|
|
978
1325
|
if (relationFieldDef.array) {
|
|
979
|
-
return eb.fn.coalesce(import_kysely3.sql`json_group_array(json_object(${import_kysely3.sql.join(objArgs)}))`, import_kysely3.sql`json_array()`).as("$
|
|
1326
|
+
return eb.fn.coalesce(import_kysely3.sql`json_group_array(json_object(${import_kysely3.sql.join(objArgs)}))`, import_kysely3.sql`json_array()`).as("$data");
|
|
980
1327
|
} else {
|
|
981
|
-
return import_kysely3.sql`json_object(${import_kysely3.sql.join(objArgs)})`.as("data");
|
|
1328
|
+
return import_kysely3.sql`json_object(${import_kysely3.sql.join(objArgs)})`.as("$data");
|
|
982
1329
|
}
|
|
983
1330
|
});
|
|
984
1331
|
return tbl;
|
|
985
1332
|
}
|
|
1333
|
+
buildRelationJoinFilter(selectModelQuery, model, relationField, relationModelAlias, parentAlias) {
|
|
1334
|
+
const fieldDef = requireField(this.schema, model, relationField);
|
|
1335
|
+
const relationModel = fieldDef.type;
|
|
1336
|
+
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
1337
|
+
if (m2m) {
|
|
1338
|
+
const parentIds = getIdFields(this.schema, model);
|
|
1339
|
+
const relationIds = getIdFields(this.schema, relationModel);
|
|
1340
|
+
(0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1341
|
+
(0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1342
|
+
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}`)));
|
|
1343
|
+
} else {
|
|
1344
|
+
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
1345
|
+
keyPairs.forEach(({ fk, pk }) => {
|
|
1346
|
+
if (ownedByModel) {
|
|
1347
|
+
selectModelQuery = selectModelQuery.whereRef(`${relationModelAlias}.${pk}`, "=", `${parentAlias}.${fk}`);
|
|
1348
|
+
} else {
|
|
1349
|
+
selectModelQuery = selectModelQuery.whereRef(`${relationModelAlias}.${fk}`, "=", `${parentAlias}.${pk}`);
|
|
1350
|
+
}
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
return selectModelQuery;
|
|
1354
|
+
}
|
|
986
1355
|
buildSkipTake(query, skip, take) {
|
|
987
1356
|
if (take !== void 0) {
|
|
988
1357
|
query = query.limit(take);
|
|
@@ -1018,93 +1387,17 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1018
1387
|
buildArrayLiteralSQL(_values) {
|
|
1019
1388
|
throw new Error("SQLite does not support array literals");
|
|
1020
1389
|
}
|
|
1390
|
+
get supportInsertWithDefault() {
|
|
1391
|
+
return false;
|
|
1392
|
+
}
|
|
1021
1393
|
};
|
|
1022
1394
|
|
|
1023
1395
|
// src/client/crud/dialects/index.ts
|
|
1024
1396
|
function getCrudDialect(schema, options) {
|
|
1025
|
-
return (0,
|
|
1397
|
+
return (0, import_ts_pattern5.match)(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
|
|
1026
1398
|
}
|
|
1027
1399
|
__name(getCrudDialect, "getCrudDialect");
|
|
1028
1400
|
|
|
1029
|
-
// src/schema/expression.ts
|
|
1030
|
-
var ExpressionUtils = {
|
|
1031
|
-
literal: /* @__PURE__ */ __name((value) => {
|
|
1032
|
-
return {
|
|
1033
|
-
kind: "literal",
|
|
1034
|
-
value
|
|
1035
|
-
};
|
|
1036
|
-
}, "literal"),
|
|
1037
|
-
array: /* @__PURE__ */ __name((items) => {
|
|
1038
|
-
return {
|
|
1039
|
-
kind: "array",
|
|
1040
|
-
items
|
|
1041
|
-
};
|
|
1042
|
-
}, "array"),
|
|
1043
|
-
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
1044
|
-
return {
|
|
1045
|
-
kind: "call",
|
|
1046
|
-
function: functionName,
|
|
1047
|
-
args
|
|
1048
|
-
};
|
|
1049
|
-
}, "call"),
|
|
1050
|
-
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
1051
|
-
return {
|
|
1052
|
-
kind: "binary",
|
|
1053
|
-
op,
|
|
1054
|
-
left,
|
|
1055
|
-
right
|
|
1056
|
-
};
|
|
1057
|
-
}, "binary"),
|
|
1058
|
-
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
1059
|
-
return {
|
|
1060
|
-
kind: "unary",
|
|
1061
|
-
op,
|
|
1062
|
-
operand
|
|
1063
|
-
};
|
|
1064
|
-
}, "unary"),
|
|
1065
|
-
field: /* @__PURE__ */ __name((field) => {
|
|
1066
|
-
return {
|
|
1067
|
-
kind: "field",
|
|
1068
|
-
field
|
|
1069
|
-
};
|
|
1070
|
-
}, "field"),
|
|
1071
|
-
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
1072
|
-
return {
|
|
1073
|
-
kind: "member",
|
|
1074
|
-
receiver,
|
|
1075
|
-
members
|
|
1076
|
-
};
|
|
1077
|
-
}, "member"),
|
|
1078
|
-
_this: /* @__PURE__ */ __name(() => {
|
|
1079
|
-
return {
|
|
1080
|
-
kind: "this"
|
|
1081
|
-
};
|
|
1082
|
-
}, "_this"),
|
|
1083
|
-
_null: /* @__PURE__ */ __name(() => {
|
|
1084
|
-
return {
|
|
1085
|
-
kind: "null"
|
|
1086
|
-
};
|
|
1087
|
-
}, "_null"),
|
|
1088
|
-
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1089
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
1090
|
-
}, "and"),
|
|
1091
|
-
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1092
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
1093
|
-
}, "or"),
|
|
1094
|
-
is: /* @__PURE__ */ __name((value, kind) => {
|
|
1095
|
-
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
1096
|
-
}, "is"),
|
|
1097
|
-
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
1098
|
-
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
1099
|
-
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
1100
|
-
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
1101
|
-
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
1102
|
-
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
1103
|
-
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
1104
|
-
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
1105
|
-
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
|
|
1106
|
-
};
|
|
1107
|
-
|
|
1108
1401
|
// src/utils/default-operation-node-visitor.ts
|
|
1109
1402
|
var import_kysely4 = require("kysely");
|
|
1110
1403
|
var DefaultOperationNodeVisitor = class extends import_kysely4.OperationNodeVisitor {
|
|
@@ -1426,17 +1719,17 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1426
1719
|
// src/plugins/policy/expression-transformer.ts
|
|
1427
1720
|
var import_common_helpers5 = require("@zenstackhq/common-helpers");
|
|
1428
1721
|
var import_kysely6 = require("kysely");
|
|
1429
|
-
var
|
|
1722
|
+
var import_ts_pattern7 = require("ts-pattern");
|
|
1430
1723
|
|
|
1431
1724
|
// src/plugins/policy/expression-evaluator.ts
|
|
1432
1725
|
var import_common_helpers4 = require("@zenstackhq/common-helpers");
|
|
1433
|
-
var
|
|
1726
|
+
var import_ts_pattern6 = require("ts-pattern");
|
|
1434
1727
|
var ExpressionEvaluator = class {
|
|
1435
1728
|
static {
|
|
1436
1729
|
__name(this, "ExpressionEvaluator");
|
|
1437
1730
|
}
|
|
1438
1731
|
evaluate(expression, context) {
|
|
1439
|
-
const result = (0,
|
|
1732
|
+
const result = (0, import_ts_pattern6.match)(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();
|
|
1440
1733
|
return result ?? null;
|
|
1441
1734
|
}
|
|
1442
1735
|
evaluateCall(expr2, context) {
|
|
@@ -1447,7 +1740,7 @@ var ExpressionEvaluator = class {
|
|
|
1447
1740
|
}
|
|
1448
1741
|
}
|
|
1449
1742
|
evaluateUnary(expr2, context) {
|
|
1450
|
-
return (0,
|
|
1743
|
+
return (0, import_ts_pattern6.match)(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
|
|
1451
1744
|
}
|
|
1452
1745
|
evaluateMember(expr2, context) {
|
|
1453
1746
|
let val = this.evaluate(expr2.receiver, context);
|
|
@@ -1471,7 +1764,7 @@ var ExpressionEvaluator = class {
|
|
|
1471
1764
|
}
|
|
1472
1765
|
const left = this.evaluate(expr2.left, context);
|
|
1473
1766
|
const right = this.evaluate(expr2.right, context);
|
|
1474
|
-
return (0,
|
|
1767
|
+
return (0, import_ts_pattern6.match)(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", () => {
|
|
1475
1768
|
const _right = right ?? [];
|
|
1476
1769
|
(0, import_common_helpers4.invariant)(Array.isArray(_right), 'expected array for "in" operator');
|
|
1477
1770
|
return _right.includes(left);
|
|
@@ -1485,7 +1778,7 @@ var ExpressionEvaluator = class {
|
|
|
1485
1778
|
return false;
|
|
1486
1779
|
}
|
|
1487
1780
|
(0, import_common_helpers4.invariant)(Array.isArray(left), "expected array");
|
|
1488
|
-
return (0,
|
|
1781
|
+
return (0, import_ts_pattern6.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1489
1782
|
...context,
|
|
1490
1783
|
thisValue: item
|
|
1491
1784
|
}))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
|
|
@@ -1739,7 +2032,7 @@ var ExpressionTransformer = class {
|
|
|
1739
2032
|
const count = import_kysely6.FunctionNode.create("count", [
|
|
1740
2033
|
import_kysely6.ValueNode.createImmediate(1)
|
|
1741
2034
|
]);
|
|
1742
|
-
const predicateResult = (0,
|
|
2035
|
+
const predicateResult = (0, import_ts_pattern7.match)(expr2.op).with("?", () => import_kysely6.BinaryOperationNode.create(count, import_kysely6.OperatorNode.create(">"), import_kysely6.ValueNode.createImmediate(0))).with("!", () => import_kysely6.BinaryOperationNode.create(count, import_kysely6.OperatorNode.create("="), import_kysely6.ValueNode.createImmediate(0))).with("^", () => import_kysely6.BinaryOperationNode.create(count, import_kysely6.OperatorNode.create("="), import_kysely6.ValueNode.createImmediate(0))).exhaustive();
|
|
1743
2036
|
return this.transform(expr2.left, {
|
|
1744
2037
|
...context,
|
|
1745
2038
|
memberSelect: import_kysely6.SelectionNode.create(import_kysely6.AliasNode.create(predicateResult, import_kysely6.IdentifierNode.create("$t"))),
|
|
@@ -1770,7 +2063,7 @@ var ExpressionTransformer = class {
|
|
|
1770
2063
|
return import_kysely6.BinaryOperationNode.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
|
|
1771
2064
|
}
|
|
1772
2065
|
transformOperator(op) {
|
|
1773
|
-
const mappedOp = (0,
|
|
2066
|
+
const mappedOp = (0, import_ts_pattern7.match)(op).with("==", () => "=").otherwise(() => op);
|
|
1774
2067
|
return import_kysely6.OperatorNode.create(mappedOp);
|
|
1775
2068
|
}
|
|
1776
2069
|
_call(expr2, context) {
|
|
@@ -2173,7 +2466,7 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2173
2466
|
return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => import_kysely7.BinaryOperationNode.create(import_kysely7.ColumnNode.create(field), import_kysely7.OperatorNode.create("="), import_kysely7.ValueNode.create(row[field]))))));
|
|
2174
2467
|
}
|
|
2175
2468
|
getMutationModel(node) {
|
|
2176
|
-
const r = (0,
|
|
2469
|
+
const r = (0, import_ts_pattern8.match)(node).when(import_kysely7.InsertQueryNode.is, (node2) => getTableName(node2.into)).when(import_kysely7.UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(import_kysely7.DeleteQueryNode.is, (node2) => {
|
|
2177
2470
|
if (node2.from.froms.length !== 1) {
|
|
2178
2471
|
throw new InternalError("Only one from table is supported for delete");
|
|
2179
2472
|
}
|
|
@@ -2354,4 +2647,4 @@ var PolicyPlugin = class {
|
|
|
2354
2647
|
PolicyPlugin,
|
|
2355
2648
|
RejectedByPolicyError
|
|
2356
2649
|
});
|
|
2357
|
-
//# sourceMappingURL=
|
|
2650
|
+
//# sourceMappingURL=index.cjs.map
|