@zenstackhq/runtime 3.0.0-alpha.3 → 3.0.0-alpha.30
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-0F-AwA7Z.d.cts → contract-DUtKB39c.d.cts} +999 -808
- package/dist/{contract-0F-AwA7Z.d.ts → contract-DUtKB39c.d.ts} +999 -808
- 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 +1940 -1011
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -8
- package/dist/index.d.ts +30 -8
- package/dist/index.js +1910 -987
- package/dist/index.js.map +1 -1
- package/dist/plugins/{policy.cjs → policy/index.cjs} +578 -310
- package/dist/plugins/policy/index.cjs.map +1 -0
- package/dist/plugins/{policy.d.ts → policy/index.d.cts} +2 -4
- package/dist/plugins/{policy.d.cts → policy/index.d.ts} +2 -4
- package/dist/plugins/{policy.js → policy/index.js} +553 -275
- package/dist/plugins/policy/index.js.map +1 -0
- package/dist/plugins/policy/plugin.zmodel +33 -0
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js.map +1 -1
- package/package.json +30 -28
- package/dist/client.cjs +0 -6084
- package/dist/client.cjs.map +0 -1
- package/dist/client.d.cts +0 -19
- package/dist/client.d.ts +0 -19
- package/dist/client.js +0 -6050
- package/dist/client.js.map +0 -1
- package/dist/plugins/policy.cjs.map +0 -1
- package/dist/plugins/policy.js.map +0 -1
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
7
|
var __export = (target, all) => {
|
|
@@ -18,14 +16,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
16
|
}
|
|
19
17
|
return to;
|
|
20
18
|
};
|
|
21
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
-
mod
|
|
28
|
-
));
|
|
29
19
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
20
|
|
|
31
21
|
// src/plugins/policy/index.ts
|
|
@@ -49,34 +39,130 @@ var RejectedByPolicyError = class extends Error {
|
|
|
49
39
|
};
|
|
50
40
|
|
|
51
41
|
// src/plugins/policy/policy-handler.ts
|
|
42
|
+
var import_common_helpers6 = require("@zenstackhq/common-helpers");
|
|
52
43
|
var import_kysely7 = require("kysely");
|
|
53
|
-
var
|
|
54
|
-
var import_ts_pattern7 = require("ts-pattern");
|
|
44
|
+
var import_ts_pattern8 = require("ts-pattern");
|
|
55
45
|
|
|
56
46
|
// src/client/crud/dialects/index.ts
|
|
57
|
-
var
|
|
47
|
+
var import_ts_pattern5 = require("ts-pattern");
|
|
58
48
|
|
|
59
49
|
// src/client/crud/dialects/postgresql.ts
|
|
50
|
+
var import_common_helpers2 = require("@zenstackhq/common-helpers");
|
|
60
51
|
var import_kysely2 = require("kysely");
|
|
61
|
-
var
|
|
62
|
-
|
|
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
|
+
};
|
|
63
150
|
|
|
64
151
|
// src/client/errors.ts
|
|
65
152
|
var QueryError = class extends Error {
|
|
66
153
|
static {
|
|
67
154
|
__name(this, "QueryError");
|
|
68
155
|
}
|
|
69
|
-
constructor(message) {
|
|
70
|
-
super(message
|
|
156
|
+
constructor(message, cause) {
|
|
157
|
+
super(message, {
|
|
158
|
+
cause
|
|
159
|
+
});
|
|
71
160
|
}
|
|
72
161
|
};
|
|
73
162
|
var InternalError = class extends Error {
|
|
74
163
|
static {
|
|
75
164
|
__name(this, "InternalError");
|
|
76
165
|
}
|
|
77
|
-
constructor(message) {
|
|
78
|
-
super(message);
|
|
79
|
-
}
|
|
80
166
|
};
|
|
81
167
|
|
|
82
168
|
// src/client/query-utils.ts
|
|
@@ -87,7 +173,7 @@ __name(getModel, "getModel");
|
|
|
87
173
|
function requireModel(schema, model) {
|
|
88
174
|
const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
|
|
89
175
|
if (!matchedName) {
|
|
90
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
176
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
91
177
|
}
|
|
92
178
|
return schema.models[matchedName];
|
|
93
179
|
}
|
|
@@ -150,6 +236,16 @@ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
|
150
236
|
}
|
|
151
237
|
}
|
|
152
238
|
__name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
|
|
239
|
+
function isRelationField(schema, model, field) {
|
|
240
|
+
const fieldDef = getField(schema, model, field);
|
|
241
|
+
return !!fieldDef?.relation;
|
|
242
|
+
}
|
|
243
|
+
__name(isRelationField, "isRelationField");
|
|
244
|
+
function isInheritedField(schema, model, field) {
|
|
245
|
+
const fieldDef = getField(schema, model, field);
|
|
246
|
+
return !!fieldDef?.originModel;
|
|
247
|
+
}
|
|
248
|
+
__name(isInheritedField, "isInheritedField");
|
|
153
249
|
function getUniqueFields(schema, model) {
|
|
154
250
|
const modelDef = requireModel(schema, model);
|
|
155
251
|
const result = [];
|
|
@@ -175,20 +271,25 @@ function getUniqueFields(schema, model) {
|
|
|
175
271
|
return result;
|
|
176
272
|
}
|
|
177
273
|
__name(getUniqueFields, "getUniqueFields");
|
|
178
|
-
function buildFieldRef(schema, model, field, options, eb, modelAlias) {
|
|
274
|
+
function buildFieldRef(schema, model, field, options, eb, modelAlias, inlineComputedField = true) {
|
|
179
275
|
const fieldDef = requireField(schema, model, field);
|
|
180
276
|
if (!fieldDef.computed) {
|
|
181
277
|
return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
|
|
182
278
|
} else {
|
|
279
|
+
if (!inlineComputedField) {
|
|
280
|
+
return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
|
|
281
|
+
}
|
|
183
282
|
let computer;
|
|
184
283
|
if ("computedFields" in options) {
|
|
185
284
|
const computedFields = options.computedFields;
|
|
186
285
|
computer = computedFields?.[model]?.[field];
|
|
187
286
|
}
|
|
188
287
|
if (!computer) {
|
|
189
|
-
throw new QueryError(`Computed field "${field}" implementation not provided`);
|
|
288
|
+
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
190
289
|
}
|
|
191
|
-
return computer(eb
|
|
290
|
+
return computer(eb, {
|
|
291
|
+
currentModel: modelAlias
|
|
292
|
+
});
|
|
192
293
|
}
|
|
193
294
|
}
|
|
194
295
|
__name(buildFieldRef, "buildFieldRef");
|
|
@@ -231,11 +332,33 @@ function getManyToManyRelation(schema, model, field) {
|
|
|
231
332
|
model,
|
|
232
333
|
fieldDef.type
|
|
233
334
|
].sort();
|
|
335
|
+
let orderedFK;
|
|
336
|
+
if (model !== fieldDef.type) {
|
|
337
|
+
orderedFK = sortedModelNames[0] === model ? [
|
|
338
|
+
"A",
|
|
339
|
+
"B"
|
|
340
|
+
] : [
|
|
341
|
+
"B",
|
|
342
|
+
"A"
|
|
343
|
+
];
|
|
344
|
+
} else {
|
|
345
|
+
const sortedFieldNames = [
|
|
346
|
+
field,
|
|
347
|
+
oppositeFieldDef.name
|
|
348
|
+
].sort();
|
|
349
|
+
orderedFK = sortedFieldNames[0] === field ? [
|
|
350
|
+
"A",
|
|
351
|
+
"B"
|
|
352
|
+
] : [
|
|
353
|
+
"B",
|
|
354
|
+
"A"
|
|
355
|
+
];
|
|
356
|
+
}
|
|
234
357
|
return {
|
|
235
|
-
parentFkName:
|
|
358
|
+
parentFkName: orderedFK[0],
|
|
236
359
|
otherModel: fieldDef.type,
|
|
237
360
|
otherField: fieldDef.relation.opposite,
|
|
238
|
-
otherFkName:
|
|
361
|
+
otherFkName: orderedFK[1],
|
|
239
362
|
joinTable: fieldDef.relation.name ? `_${fieldDef.relation.name}` : `_${sortedModelNames[0]}To${sortedModelNames[1]}`
|
|
240
363
|
};
|
|
241
364
|
} else {
|
|
@@ -263,11 +386,38 @@ function flattenCompoundUniqueFilters(schema, model, filter) {
|
|
|
263
386
|
return result;
|
|
264
387
|
}
|
|
265
388
|
__name(flattenCompoundUniqueFilters, "flattenCompoundUniqueFilters");
|
|
389
|
+
function ensureArray(value) {
|
|
390
|
+
if (Array.isArray(value)) {
|
|
391
|
+
return value;
|
|
392
|
+
} else {
|
|
393
|
+
return [
|
|
394
|
+
value
|
|
395
|
+
];
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
__name(ensureArray, "ensureArray");
|
|
399
|
+
function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */ new Set()) {
|
|
400
|
+
const subModels = Object.values(schema.models).filter((m) => m.baseModel === model);
|
|
401
|
+
subModels.forEach((def) => {
|
|
402
|
+
if (!collected.has(def)) {
|
|
403
|
+
collected.add(def);
|
|
404
|
+
getDelegateDescendantModels(schema, def.name, collected);
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
return [
|
|
408
|
+
...collected
|
|
409
|
+
];
|
|
410
|
+
}
|
|
411
|
+
__name(getDelegateDescendantModels, "getDelegateDescendantModels");
|
|
412
|
+
function aggregate(eb, expr2, op) {
|
|
413
|
+
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();
|
|
414
|
+
}
|
|
415
|
+
__name(aggregate, "aggregate");
|
|
266
416
|
|
|
267
417
|
// src/client/crud/dialects/base.ts
|
|
418
|
+
var import_common_helpers = require("@zenstackhq/common-helpers");
|
|
268
419
|
var import_kysely = require("kysely");
|
|
269
|
-
var
|
|
270
|
-
var import_ts_pattern = require("ts-pattern");
|
|
420
|
+
var import_ts_pattern2 = require("ts-pattern");
|
|
271
421
|
|
|
272
422
|
// src/utils/enumerate.ts
|
|
273
423
|
function enumerate(x) {
|
|
@@ -284,7 +434,6 @@ function enumerate(x) {
|
|
|
284
434
|
__name(enumerate, "enumerate");
|
|
285
435
|
|
|
286
436
|
// src/client/crud/dialects/base.ts
|
|
287
|
-
var import_is_plain_object = require("is-plain-object");
|
|
288
437
|
var BaseCrudDialect = class {
|
|
289
438
|
static {
|
|
290
439
|
__name(this, "BaseCrudDialect");
|
|
@@ -295,9 +444,47 @@ var BaseCrudDialect = class {
|
|
|
295
444
|
this.schema = schema;
|
|
296
445
|
this.options = options;
|
|
297
446
|
}
|
|
298
|
-
transformPrimitive(value, _type) {
|
|
447
|
+
transformPrimitive(value, _type, _forArrayField) {
|
|
299
448
|
return value;
|
|
300
449
|
}
|
|
450
|
+
// #region common query builders
|
|
451
|
+
buildSelectModel(eb, model, modelAlias) {
|
|
452
|
+
const modelDef = requireModel(this.schema, model);
|
|
453
|
+
let result = eb.selectFrom(model === modelAlias ? model : `${model} as ${modelAlias}`);
|
|
454
|
+
let joinBase = modelDef.baseModel;
|
|
455
|
+
while (joinBase) {
|
|
456
|
+
result = this.buildDelegateJoin(model, modelAlias, joinBase, result);
|
|
457
|
+
joinBase = requireModel(this.schema, joinBase).baseModel;
|
|
458
|
+
}
|
|
459
|
+
return result;
|
|
460
|
+
}
|
|
461
|
+
buildFilterSortTake(model, args, query, modelAlias) {
|
|
462
|
+
let result = query;
|
|
463
|
+
if (args.where) {
|
|
464
|
+
result = result.where((eb) => this.buildFilter(eb, model, modelAlias, args?.where));
|
|
465
|
+
}
|
|
466
|
+
let negateOrderBy = false;
|
|
467
|
+
const skip = args.skip;
|
|
468
|
+
let take = args.take;
|
|
469
|
+
if (take !== void 0 && take < 0) {
|
|
470
|
+
negateOrderBy = true;
|
|
471
|
+
take = -take;
|
|
472
|
+
}
|
|
473
|
+
result = this.buildSkipTake(result, skip, take);
|
|
474
|
+
result = this.buildOrderBy(result, model, modelAlias, args.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
475
|
+
if ("distinct" in args && args.distinct) {
|
|
476
|
+
const distinct = ensureArray(args.distinct);
|
|
477
|
+
if (this.supportsDistinctOn) {
|
|
478
|
+
result = result.distinctOn(distinct.map((f) => import_kysely.sql.ref(`${modelAlias}.${f}`)));
|
|
479
|
+
} else {
|
|
480
|
+
throw new QueryError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (args.cursor) {
|
|
484
|
+
result = this.buildCursorFilter(model, result, args.cursor, args.orderBy, negateOrderBy, modelAlias);
|
|
485
|
+
}
|
|
486
|
+
return result;
|
|
487
|
+
}
|
|
301
488
|
buildFilter(eb, model, modelAlias, where) {
|
|
302
489
|
if (where === true || where === void 0) {
|
|
303
490
|
return this.true(eb);
|
|
@@ -314,17 +501,20 @@ var BaseCrudDialect = class {
|
|
|
314
501
|
if (key.startsWith("$")) {
|
|
315
502
|
continue;
|
|
316
503
|
}
|
|
317
|
-
if (key
|
|
504
|
+
if (this.isLogicalCombinator(key)) {
|
|
318
505
|
result = this.and(eb, result, this.buildCompositeFilter(eb, model, modelAlias, key, payload));
|
|
319
506
|
continue;
|
|
320
507
|
}
|
|
321
508
|
const fieldDef = requireField(this.schema, model, key);
|
|
322
509
|
if (fieldDef.relation) {
|
|
323
510
|
result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
324
|
-
} else if (fieldDef.array) {
|
|
325
|
-
result = this.and(eb, result, this.buildArrayFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
326
511
|
} else {
|
|
327
|
-
|
|
512
|
+
const fieldRef = this.fieldRef(fieldDef.originModel ?? model, key, eb, fieldDef.originModel ?? modelAlias);
|
|
513
|
+
if (fieldDef.array) {
|
|
514
|
+
result = this.and(eb, result, this.buildArrayFilter(eb, fieldRef, fieldDef, payload));
|
|
515
|
+
} else {
|
|
516
|
+
result = this.and(eb, result, this.buildPrimitiveFilter(eb, fieldRef, fieldDef, payload));
|
|
517
|
+
}
|
|
328
518
|
}
|
|
329
519
|
}
|
|
330
520
|
if ("$expr" in _where && typeof _where["$expr"] === "function") {
|
|
@@ -332,8 +522,32 @@ var BaseCrudDialect = class {
|
|
|
332
522
|
}
|
|
333
523
|
return result;
|
|
334
524
|
}
|
|
525
|
+
buildCursorFilter(model, query, cursor, orderBy, negateOrderBy, modelAlias) {
|
|
526
|
+
const _orderBy = orderBy ?? makeDefaultOrderBy(this.schema, model);
|
|
527
|
+
const orderByItems = ensureArray(_orderBy).flatMap((obj) => Object.entries(obj));
|
|
528
|
+
const eb = (0, import_kysely.expressionBuilder)();
|
|
529
|
+
const subQueryAlias = `${model}$cursor$sub`;
|
|
530
|
+
const cursorFilter = this.buildFilter(eb, model, subQueryAlias, cursor);
|
|
531
|
+
let result = query;
|
|
532
|
+
const filters = [];
|
|
533
|
+
for (let i = orderByItems.length - 1; i >= 0; i--) {
|
|
534
|
+
const andFilters = [];
|
|
535
|
+
for (let j = 0; j <= i; j++) {
|
|
536
|
+
const [field, order] = orderByItems[j];
|
|
537
|
+
const _order = negateOrderBy ? order === "asc" ? "desc" : "asc" : order;
|
|
538
|
+
const op = j === i ? _order === "asc" ? ">=" : "<=" : "=";
|
|
539
|
+
andFilters.push(eb(eb.ref(`${modelAlias}.${field}`), op, this.buildSelectModel(eb, model, subQueryAlias).select(`${subQueryAlias}.${field}`).where(cursorFilter)));
|
|
540
|
+
}
|
|
541
|
+
filters.push(eb.and(andFilters));
|
|
542
|
+
}
|
|
543
|
+
result = result.where((eb2) => eb2.or(filters));
|
|
544
|
+
return result;
|
|
545
|
+
}
|
|
546
|
+
isLogicalCombinator(key) {
|
|
547
|
+
return LOGICAL_COMBINATORS.includes(key);
|
|
548
|
+
}
|
|
335
549
|
buildCompositeFilter(eb, model, modelAlias, key, payload) {
|
|
336
|
-
return (0,
|
|
550
|
+
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();
|
|
337
551
|
}
|
|
338
552
|
buildRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
339
553
|
if (!fieldDef.array) {
|
|
@@ -342,19 +556,26 @@ var BaseCrudDialect = class {
|
|
|
342
556
|
return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
|
|
343
557
|
}
|
|
344
558
|
}
|
|
345
|
-
buildToOneRelationFilter(eb, model,
|
|
559
|
+
buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
346
560
|
if (payload === null) {
|
|
347
561
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
348
|
-
if (ownedByModel) {
|
|
349
|
-
return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely.sql.ref(`${
|
|
562
|
+
if (ownedByModel && !fieldDef.originModel) {
|
|
563
|
+
return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely.sql.ref(`${modelAlias}.${fk}`), "is", null)));
|
|
350
564
|
} else {
|
|
351
|
-
return this.buildToOneRelationFilter(eb, model,
|
|
565
|
+
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
|
|
352
566
|
is: null
|
|
353
567
|
});
|
|
354
568
|
}
|
|
355
569
|
}
|
|
356
|
-
const joinAlias = `${
|
|
357
|
-
const joinPairs = buildJoinPairs(
|
|
570
|
+
const joinAlias = `${modelAlias}$${field}`;
|
|
571
|
+
const joinPairs = buildJoinPairs(
|
|
572
|
+
this.schema,
|
|
573
|
+
model,
|
|
574
|
+
// if field is from a base, use the base model to join
|
|
575
|
+
fieldDef.originModel ?? modelAlias,
|
|
576
|
+
field,
|
|
577
|
+
joinAlias
|
|
578
|
+
);
|
|
358
579
|
const filterResultField = `${field}$filter`;
|
|
359
580
|
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));
|
|
360
581
|
const conditions = [];
|
|
@@ -384,25 +605,26 @@ var BaseCrudDialect = class {
|
|
|
384
605
|
}
|
|
385
606
|
return this.and(eb, ...conditions);
|
|
386
607
|
}
|
|
387
|
-
buildToManyRelationFilter(eb, model,
|
|
608
|
+
buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
388
609
|
if (payload === null) {
|
|
389
|
-
return eb(import_kysely.sql.ref(`${
|
|
610
|
+
return eb(import_kysely.sql.ref(`${modelAlias}.${field}`), "is", null);
|
|
390
611
|
}
|
|
391
612
|
const relationModel = fieldDef.type;
|
|
613
|
+
const relationFilterSelectAlias = `${modelAlias}$${field}$filter`;
|
|
392
614
|
const buildPkFkWhereRefs = /* @__PURE__ */ __name((eb2) => {
|
|
393
615
|
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
394
616
|
if (m2m) {
|
|
395
617
|
const modelIdField = getIdFields(this.schema, model)[0];
|
|
396
618
|
const relationIdField = getIdFields(this.schema, relationModel)[0];
|
|
397
|
-
return eb2(import_kysely.sql.ref(`${
|
|
619
|
+
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}`)));
|
|
398
620
|
} else {
|
|
399
621
|
const relationKeyPairs = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
400
622
|
let result2 = this.true(eb2);
|
|
401
623
|
for (const { fk, pk } of relationKeyPairs.keyPairs) {
|
|
402
624
|
if (relationKeyPairs.ownedByModel) {
|
|
403
|
-
result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${
|
|
625
|
+
result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${modelAlias}.${fk}`), "=", import_kysely.sql.ref(`${relationFilterSelectAlias}.${pk}`)));
|
|
404
626
|
} else {
|
|
405
|
-
result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${
|
|
627
|
+
result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${modelAlias}.${pk}`), "=", import_kysely.sql.ref(`${relationFilterSelectAlias}.${fk}`)));
|
|
406
628
|
}
|
|
407
629
|
}
|
|
408
630
|
return result2;
|
|
@@ -415,30 +637,29 @@ var BaseCrudDialect = class {
|
|
|
415
637
|
}
|
|
416
638
|
switch (key) {
|
|
417
639
|
case "some": {
|
|
418
|
-
result = this.and(eb, result, eb(
|
|
640
|
+
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));
|
|
419
641
|
break;
|
|
420
642
|
}
|
|
421
643
|
case "every": {
|
|
422
|
-
result = this.and(eb, result, eb(
|
|
644
|
+
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));
|
|
423
645
|
break;
|
|
424
646
|
}
|
|
425
647
|
case "none": {
|
|
426
|
-
result = this.and(eb, result, eb(
|
|
648
|
+
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));
|
|
427
649
|
break;
|
|
428
650
|
}
|
|
429
651
|
}
|
|
430
652
|
}
|
|
431
653
|
return result;
|
|
432
654
|
}
|
|
433
|
-
buildArrayFilter(eb,
|
|
655
|
+
buildArrayFilter(eb, fieldRef, fieldDef, payload) {
|
|
434
656
|
const clauses = [];
|
|
435
657
|
const fieldType = fieldDef.type;
|
|
436
|
-
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
|
|
437
658
|
for (const [key, _value] of Object.entries(payload)) {
|
|
438
659
|
if (_value === void 0) {
|
|
439
660
|
continue;
|
|
440
661
|
}
|
|
441
|
-
const value = this.transformPrimitive(_value, fieldType);
|
|
662
|
+
const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
|
|
442
663
|
switch (key) {
|
|
443
664
|
case "equals": {
|
|
444
665
|
clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
|
|
@@ -469,20 +690,24 @@ var BaseCrudDialect = class {
|
|
|
469
690
|
}
|
|
470
691
|
return this.and(eb, ...clauses);
|
|
471
692
|
}
|
|
472
|
-
buildPrimitiveFilter(eb,
|
|
693
|
+
buildPrimitiveFilter(eb, fieldRef, fieldDef, payload) {
|
|
473
694
|
if (payload === null) {
|
|
474
|
-
return eb(
|
|
695
|
+
return eb(fieldRef, "is", null);
|
|
475
696
|
}
|
|
476
697
|
if (isEnum(this.schema, fieldDef.type)) {
|
|
477
|
-
return this.buildEnumFilter(eb,
|
|
698
|
+
return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
|
|
478
699
|
}
|
|
479
|
-
return (0,
|
|
700
|
+
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", () => {
|
|
701
|
+
throw new InternalError("JSON filters are not supported yet");
|
|
702
|
+
}).with("Unsupported", () => {
|
|
703
|
+
throw new QueryError(`Unsupported field cannot be used in filters`);
|
|
704
|
+
}).exhaustive();
|
|
480
705
|
}
|
|
481
706
|
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
482
|
-
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
|
|
707
|
+
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
483
708
|
}
|
|
484
|
-
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
|
|
485
|
-
if (payload === null || !(0,
|
|
709
|
+
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
710
|
+
if (payload === null || !(0, import_common_helpers.isPlainObject)(payload)) {
|
|
486
711
|
return {
|
|
487
712
|
conditions: [
|
|
488
713
|
this.buildLiteralFilter(eb, lhs, type, payload)
|
|
@@ -496,22 +721,29 @@ var BaseCrudDialect = class {
|
|
|
496
721
|
if (onlyForKeys && !onlyForKeys.includes(op)) {
|
|
497
722
|
continue;
|
|
498
723
|
}
|
|
724
|
+
if (excludeKeys.includes(op)) {
|
|
725
|
+
continue;
|
|
726
|
+
}
|
|
499
727
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
500
|
-
const condition = (0,
|
|
501
|
-
(0,
|
|
728
|
+
const condition = (0, import_ts_pattern2.match)(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
729
|
+
(0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
502
730
|
if (rhs.length === 0) {
|
|
503
731
|
return this.false(eb);
|
|
504
732
|
} else {
|
|
505
733
|
return eb(lhs, "in", rhs);
|
|
506
734
|
}
|
|
507
735
|
}).with("notIn", () => {
|
|
508
|
-
(0,
|
|
736
|
+
(0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
509
737
|
if (rhs.length === 0) {
|
|
510
738
|
return this.true(eb);
|
|
511
739
|
} else {
|
|
512
740
|
return eb.not(eb(lhs, "in", rhs));
|
|
513
741
|
}
|
|
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))).
|
|
742
|
+
}).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) => {
|
|
743
|
+
const innerResult = this.buildStandardFilter(eb, type, value, aggregate(eb, lhs, op2), getRhs, recurse, throwIfInvalid);
|
|
744
|
+
consumedKeys.push(...innerResult.consumedKeys);
|
|
745
|
+
return this.and(eb, ...innerResult.conditions);
|
|
746
|
+
}).otherwise(() => {
|
|
515
747
|
if (throwIfInvalid) {
|
|
516
748
|
throw new QueryError(`Invalid filter key: ${op}`);
|
|
517
749
|
} else {
|
|
@@ -528,24 +760,21 @@ var BaseCrudDialect = class {
|
|
|
528
760
|
consumedKeys
|
|
529
761
|
};
|
|
530
762
|
}
|
|
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
|
-
]);
|
|
763
|
+
buildStringFilter(eb, fieldRef, payload) {
|
|
764
|
+
let mode;
|
|
765
|
+
if (payload && typeof payload === "object" && "mode" in payload) {
|
|
766
|
+
mode = payload.mode;
|
|
540
767
|
}
|
|
541
|
-
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload,
|
|
768
|
+
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, mode === "insensitive" ? eb.fn("lower", [
|
|
769
|
+
fieldRef
|
|
770
|
+
]) : fieldRef, (value) => this.prepStringCasing(eb, value, mode), (value) => this.buildStringFilter(eb, fieldRef, value));
|
|
542
771
|
if (payload && typeof payload === "object") {
|
|
543
772
|
for (const [key, value] of Object.entries(payload)) {
|
|
544
773
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
545
774
|
continue;
|
|
546
775
|
}
|
|
547
|
-
const condition = (0,
|
|
548
|
-
throw new
|
|
776
|
+
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(() => {
|
|
777
|
+
throw new QueryError(`Invalid string filter key: ${key}`);
|
|
549
778
|
});
|
|
550
779
|
if (condition) {
|
|
551
780
|
conditions.push(condition);
|
|
@@ -554,34 +783,37 @@ var BaseCrudDialect = class {
|
|
|
554
783
|
}
|
|
555
784
|
return this.and(eb, ...conditions);
|
|
556
785
|
}
|
|
557
|
-
prepStringCasing(eb, value,
|
|
786
|
+
prepStringCasing(eb, value, mode) {
|
|
787
|
+
if (!mode || mode === "default") {
|
|
788
|
+
return value === null ? value : import_kysely.sql.val(value);
|
|
789
|
+
}
|
|
558
790
|
if (typeof value === "string") {
|
|
559
|
-
return
|
|
560
|
-
import_kysely.sql.
|
|
561
|
-
])
|
|
791
|
+
return eb.fn("lower", [
|
|
792
|
+
import_kysely.sql.val(value)
|
|
793
|
+
]);
|
|
562
794
|
} else if (Array.isArray(value)) {
|
|
563
|
-
return value.map((v) => this.prepStringCasing(eb, v,
|
|
795
|
+
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
564
796
|
} else {
|
|
565
|
-
return value === null ? null : import_kysely.sql.
|
|
797
|
+
return value === null ? null : import_kysely.sql.val(value);
|
|
566
798
|
}
|
|
567
799
|
}
|
|
568
|
-
buildNumberFilter(eb,
|
|
569
|
-
const { conditions } = this.buildStandardFilter(eb, type, payload,
|
|
800
|
+
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
801
|
+
const { conditions } = this.buildStandardFilter(eb, type, payload, fieldRef, (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, fieldRef, type, value));
|
|
570
802
|
return this.and(eb, ...conditions);
|
|
571
803
|
}
|
|
572
|
-
buildBooleanFilter(eb,
|
|
573
|
-
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload,
|
|
804
|
+
buildBooleanFilter(eb, fieldRef, payload) {
|
|
805
|
+
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, fieldRef, (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, fieldRef, value), true, [
|
|
574
806
|
"equals",
|
|
575
807
|
"not"
|
|
576
808
|
]);
|
|
577
809
|
return this.and(eb, ...conditions);
|
|
578
810
|
}
|
|
579
|
-
buildDateTimeFilter(eb,
|
|
580
|
-
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload,
|
|
811
|
+
buildDateTimeFilter(eb, fieldRef, payload) {
|
|
812
|
+
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, fieldRef, (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, fieldRef, value), true);
|
|
581
813
|
return this.and(eb, ...conditions);
|
|
582
814
|
}
|
|
583
|
-
buildBytesFilter(eb,
|
|
584
|
-
const conditions = this.buildStandardFilter(eb, "Bytes", payload,
|
|
815
|
+
buildBytesFilter(eb, fieldRef, payload) {
|
|
816
|
+
const conditions = this.buildStandardFilter(eb, "Bytes", payload, fieldRef, (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, fieldRef, value), true, [
|
|
585
817
|
"equals",
|
|
586
818
|
"in",
|
|
587
819
|
"notIn",
|
|
@@ -589,8 +821,8 @@ var BaseCrudDialect = class {
|
|
|
589
821
|
]);
|
|
590
822
|
return this.and(eb, ...conditions.conditions);
|
|
591
823
|
}
|
|
592
|
-
buildEnumFilter(eb,
|
|
593
|
-
const conditions = this.buildStandardFilter(eb, "String", payload,
|
|
824
|
+
buildEnumFilter(eb, fieldRef, fieldDef, payload) {
|
|
825
|
+
const conditions = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => value, (value) => this.buildEnumFilter(eb, fieldRef, fieldDef, value), true, [
|
|
594
826
|
"equals",
|
|
595
827
|
"in",
|
|
596
828
|
"notIn",
|
|
@@ -619,21 +851,19 @@ var BaseCrudDialect = class {
|
|
|
619
851
|
"_min",
|
|
620
852
|
"_max"
|
|
621
853
|
].includes(field)) {
|
|
622
|
-
(0,
|
|
854
|
+
(0, import_common_helpers.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
623
855
|
for (const [k, v] of Object.entries(value)) {
|
|
624
|
-
(0,
|
|
625
|
-
result = result.orderBy((eb) => eb.
|
|
626
|
-
import_kysely.sql.ref(k)
|
|
627
|
-
]), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
856
|
+
(0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
857
|
+
result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
628
858
|
}
|
|
629
859
|
continue;
|
|
630
860
|
}
|
|
631
861
|
switch (field) {
|
|
632
862
|
case "_count": {
|
|
633
|
-
(0,
|
|
863
|
+
(0, import_common_helpers.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
|
|
634
864
|
for (const [k, v] of Object.entries(value)) {
|
|
635
|
-
(0,
|
|
636
|
-
result = result.orderBy((eb) => eb.fn.count(
|
|
865
|
+
(0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
866
|
+
result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
637
867
|
}
|
|
638
868
|
continue;
|
|
639
869
|
}
|
|
@@ -642,10 +872,11 @@ var BaseCrudDialect = class {
|
|
|
642
872
|
}
|
|
643
873
|
const fieldDef = requireField(this.schema, model, field);
|
|
644
874
|
if (!fieldDef.relation) {
|
|
875
|
+
const fieldRef = this.fieldRef(model, field, (0, import_kysely.expressionBuilder)(), modelAlias);
|
|
645
876
|
if (value === "asc" || value === "desc") {
|
|
646
|
-
result = result.orderBy(
|
|
877
|
+
result = result.orderBy(fieldRef, this.negateSort(value, negated));
|
|
647
878
|
} 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(
|
|
879
|
+
result = result.orderBy(fieldRef, import_kysely.sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
|
|
649
880
|
}
|
|
650
881
|
} else {
|
|
651
882
|
const relationModel = fieldDef.type;
|
|
@@ -654,11 +885,12 @@ var BaseCrudDialect = class {
|
|
|
654
885
|
throw new QueryError(`invalid orderBy value for field "${field}"`);
|
|
655
886
|
}
|
|
656
887
|
if ("_count" in value) {
|
|
657
|
-
(0,
|
|
888
|
+
(0, import_common_helpers.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
658
889
|
const sort = this.negateSort(value._count, negated);
|
|
659
890
|
result = result.orderBy((eb) => {
|
|
660
|
-
|
|
661
|
-
|
|
891
|
+
const subQueryAlias = `${modelAlias}$orderBy$${field}$count`;
|
|
892
|
+
let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
|
|
893
|
+
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, subQueryAlias);
|
|
662
894
|
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right)))));
|
|
663
895
|
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
664
896
|
return subQuery;
|
|
@@ -676,14 +908,90 @@ var BaseCrudDialect = class {
|
|
|
676
908
|
});
|
|
677
909
|
return result;
|
|
678
910
|
}
|
|
911
|
+
buildSelectAllFields(model, query, omit, modelAlias) {
|
|
912
|
+
const modelDef = requireModel(this.schema, model);
|
|
913
|
+
let result = query;
|
|
914
|
+
for (const field of Object.keys(modelDef.fields)) {
|
|
915
|
+
if (isRelationField(this.schema, model, field)) {
|
|
916
|
+
continue;
|
|
917
|
+
}
|
|
918
|
+
if (omit?.[field] === true) {
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
921
|
+
result = this.buildSelectField(result, model, modelAlias, field);
|
|
922
|
+
}
|
|
923
|
+
const descendants = getDelegateDescendantModels(this.schema, model);
|
|
924
|
+
for (const subModel of descendants) {
|
|
925
|
+
result = this.buildDelegateJoin(model, modelAlias, subModel.name, result);
|
|
926
|
+
result = result.select((eb) => {
|
|
927
|
+
const jsonObject = {};
|
|
928
|
+
for (const field of Object.keys(subModel.fields)) {
|
|
929
|
+
if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
|
|
930
|
+
continue;
|
|
931
|
+
}
|
|
932
|
+
jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
|
|
933
|
+
}
|
|
934
|
+
return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
return result;
|
|
938
|
+
}
|
|
939
|
+
buildSelectField(query, model, modelAlias, field) {
|
|
940
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
941
|
+
if (fieldDef.computed) {
|
|
942
|
+
return query.select((eb) => this.fieldRef(model, field, eb, modelAlias).as(field));
|
|
943
|
+
} else if (!fieldDef.originModel) {
|
|
944
|
+
return query.select(import_kysely.sql.ref(`${modelAlias}.${field}`).as(field));
|
|
945
|
+
} else {
|
|
946
|
+
return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
buildDelegateJoin(thisModel, thisModelAlias, otherModelAlias, query) {
|
|
950
|
+
const idFields = getIdFields(this.schema, thisModel);
|
|
951
|
+
query = query.leftJoin(otherModelAlias, (qb) => {
|
|
952
|
+
for (const idField of idFields) {
|
|
953
|
+
qb = qb.onRef(`${thisModelAlias}.${idField}`, "=", `${otherModelAlias}.${idField}`);
|
|
954
|
+
}
|
|
955
|
+
return qb;
|
|
956
|
+
});
|
|
957
|
+
return query;
|
|
958
|
+
}
|
|
959
|
+
buildCountJson(model, eb, parentAlias, payload) {
|
|
960
|
+
const modelDef = requireModel(this.schema, model);
|
|
961
|
+
const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
|
|
962
|
+
const selections = payload === true ? {
|
|
963
|
+
select: toManyRelations.reduce((acc, [field]) => {
|
|
964
|
+
acc[field] = true;
|
|
965
|
+
return acc;
|
|
966
|
+
}, {})
|
|
967
|
+
} : payload;
|
|
968
|
+
const jsonObject = {};
|
|
969
|
+
for (const [field, value] of Object.entries(selections.select)) {
|
|
970
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
971
|
+
const fieldModel = fieldDef.type;
|
|
972
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
973
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
974
|
+
for (const [left, right] of joinPairs) {
|
|
975
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
976
|
+
}
|
|
977
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
978
|
+
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
979
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
980
|
+
}
|
|
981
|
+
jsonObject[field] = fieldCountQuery;
|
|
982
|
+
}
|
|
983
|
+
return this.buildJsonObject(eb, jsonObject);
|
|
984
|
+
}
|
|
985
|
+
// #endregion
|
|
986
|
+
// #region utils
|
|
679
987
|
negateSort(sort, negated) {
|
|
680
988
|
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
681
989
|
}
|
|
682
990
|
true(eb) {
|
|
683
|
-
return eb.lit(this.transformPrimitive(true, "Boolean"));
|
|
991
|
+
return eb.lit(this.transformPrimitive(true, "Boolean", false));
|
|
684
992
|
}
|
|
685
993
|
false(eb) {
|
|
686
|
-
return eb.lit(this.transformPrimitive(false, "Boolean"));
|
|
994
|
+
return eb.lit(this.transformPrimitive(false, "Boolean", false));
|
|
687
995
|
}
|
|
688
996
|
isTrue(expression) {
|
|
689
997
|
const node = expression.toOperationNode();
|
|
@@ -722,6 +1030,9 @@ var BaseCrudDialect = class {
|
|
|
722
1030
|
not(eb, ...args) {
|
|
723
1031
|
return eb.not(this.and(eb, ...args));
|
|
724
1032
|
}
|
|
1033
|
+
fieldRef(model, field, eb, modelAlias, inlineComputedField = true) {
|
|
1034
|
+
return buildFieldRef(this.schema, model, field, this.options, eb, modelAlias, inlineComputedField);
|
|
1035
|
+
}
|
|
725
1036
|
};
|
|
726
1037
|
|
|
727
1038
|
// src/client/crud/dialects/postgresql.ts
|
|
@@ -732,14 +1043,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
732
1043
|
get provider() {
|
|
733
1044
|
return "postgresql";
|
|
734
1045
|
}
|
|
735
|
-
transformPrimitive(value, type) {
|
|
1046
|
+
transformPrimitive(value, type, forArrayField) {
|
|
736
1047
|
if (value === void 0) {
|
|
737
1048
|
return value;
|
|
738
1049
|
}
|
|
739
1050
|
if (Array.isArray(value)) {
|
|
740
|
-
|
|
1051
|
+
if (type === "Json" && !forArrayField) {
|
|
1052
|
+
return JSON.stringify(value);
|
|
1053
|
+
} else {
|
|
1054
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
1055
|
+
}
|
|
741
1056
|
} else {
|
|
742
|
-
return (0,
|
|
1057
|
+
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);
|
|
743
1058
|
}
|
|
744
1059
|
}
|
|
745
1060
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -752,43 +1067,34 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
752
1067
|
return qb.leftJoinLateral((eb) => {
|
|
753
1068
|
const joinTableName = `${parentName}$${relationField}`;
|
|
754
1069
|
let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
|
|
1070
|
+
const subQueryAlias = `${relationModel}$${relationField}$sub`;
|
|
755
1071
|
result = eb.selectFrom(() => {
|
|
756
|
-
let subQuery =
|
|
1072
|
+
let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
|
|
1073
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0, subQueryAlias);
|
|
757
1074
|
if (payload && typeof payload === "object") {
|
|
758
|
-
|
|
759
|
-
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
760
|
-
}
|
|
761
|
-
const skip = payload.skip;
|
|
762
|
-
let take = payload.take;
|
|
763
|
-
let negateOrderBy = false;
|
|
764
|
-
if (take !== void 0 && take < 0) {
|
|
765
|
-
negateOrderBy = true;
|
|
766
|
-
take = -take;
|
|
767
|
-
}
|
|
768
|
-
subQuery = this.buildSkipTake(subQuery, skip, take);
|
|
769
|
-
subQuery = this.buildOrderBy(subQuery, relationModel, relationModel, payload.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
1075
|
+
subQuery = this.buildFilterSortTake(relationModel, payload, subQuery, subQueryAlias);
|
|
770
1076
|
}
|
|
771
1077
|
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
772
1078
|
if (m2m) {
|
|
773
1079
|
const parentIds = getIdFields(this.schema, model);
|
|
774
1080
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
775
|
-
(0,
|
|
776
|
-
(0,
|
|
777
|
-
subQuery = subQuery.where(eb(eb.ref(`${
|
|
1081
|
+
(0, import_common_helpers2.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1082
|
+
(0, import_common_helpers2.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1083
|
+
subQuery = subQuery.where(eb(eb.ref(`${subQueryAlias}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentName}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
778
1084
|
} else {
|
|
779
|
-
const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField,
|
|
1085
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField, subQueryAlias);
|
|
780
1086
|
subQuery = subQuery.where((eb2) => this.and(eb2, ...joinPairs.map(([left, right]) => eb2(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right)))));
|
|
781
1087
|
}
|
|
782
1088
|
return subQuery.as(joinTableName);
|
|
783
1089
|
});
|
|
784
|
-
result = this.buildRelationObjectSelect(relationModel, relationField, relationFieldDef, result, payload, parentName);
|
|
1090
|
+
result = this.buildRelationObjectSelect(relationModel, joinTableName, relationField, relationFieldDef, result, payload, parentName);
|
|
785
1091
|
result = this.buildRelationJoins(relationModel, relationField, result, payload, parentName);
|
|
786
1092
|
return result.as(joinTableName);
|
|
787
1093
|
}, (join) => join.onTrue());
|
|
788
1094
|
}
|
|
789
|
-
buildRelationObjectSelect(relationModel, relationField, relationFieldDef, qb, payload, parentName) {
|
|
1095
|
+
buildRelationObjectSelect(relationModel, relationModelAlias, relationField, relationFieldDef, qb, payload, parentName) {
|
|
790
1096
|
qb = qb.select((eb) => {
|
|
791
|
-
const objArgs = this.buildRelationObjectArgs(relationModel, relationField, eb, payload, parentName);
|
|
1097
|
+
const objArgs = this.buildRelationObjectArgs(relationModel, relationModelAlias, relationField, eb, payload, parentName);
|
|
792
1098
|
if (relationFieldDef.array) {
|
|
793
1099
|
return eb.fn.coalesce(import_kysely2.sql`jsonb_agg(jsonb_build_object(${import_kysely2.sql.join(objArgs)}))`, import_kysely2.sql`'[]'::jsonb`).as("$j");
|
|
794
1100
|
} else {
|
|
@@ -797,34 +1103,57 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
797
1103
|
});
|
|
798
1104
|
return qb;
|
|
799
1105
|
}
|
|
800
|
-
buildRelationObjectArgs(relationModel, relationField, eb, payload,
|
|
1106
|
+
buildRelationObjectArgs(relationModel, relationModelAlias, relationField, eb, payload, parentAlias) {
|
|
801
1107
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
802
1108
|
const objArgs = [];
|
|
1109
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1110
|
+
if (descendantModels.length > 0) {
|
|
1111
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1112
|
+
import_kysely2.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1113
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1114
|
+
]).flatMap((v) => v));
|
|
1115
|
+
}
|
|
803
1116
|
if (payload === true || !payload.select) {
|
|
804
1117
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
805
1118
|
import_kysely2.sql.lit(field),
|
|
806
|
-
|
|
1119
|
+
this.fieldRef(relationModel, field, eb, relationModelAlias, false)
|
|
807
1120
|
]).flatMap((v) => v));
|
|
808
1121
|
} else if (payload.select) {
|
|
809
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) =>
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
1122
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1123
|
+
if (field === "_count") {
|
|
1124
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1125
|
+
return [
|
|
1126
|
+
import_kysely2.sql.lit(field),
|
|
1127
|
+
subJson
|
|
1128
|
+
];
|
|
1129
|
+
} else {
|
|
1130
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1131
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : this.fieldRef(relationModel, field, eb, void 0, false);
|
|
1132
|
+
return [
|
|
1133
|
+
import_kysely2.sql.lit(field),
|
|
1134
|
+
fieldValue
|
|
1135
|
+
];
|
|
1136
|
+
}
|
|
1137
|
+
}).flatMap((v) => v));
|
|
813
1138
|
}
|
|
814
1139
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
815
1140
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
816
1141
|
import_kysely2.sql.lit(field),
|
|
817
|
-
|
|
1142
|
+
// reference the synthesized JSON field
|
|
1143
|
+
eb.ref(`${parentAlias}$${relationField}$${field}.$j`)
|
|
818
1144
|
]).flatMap((v) => v));
|
|
819
1145
|
}
|
|
820
1146
|
return objArgs;
|
|
821
1147
|
}
|
|
822
|
-
buildRelationJoins(
|
|
1148
|
+
buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
|
|
823
1149
|
let result = qb;
|
|
824
|
-
if (typeof payload === "object"
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
1150
|
+
if (typeof payload === "object") {
|
|
1151
|
+
const selectInclude = payload.include ?? payload.select;
|
|
1152
|
+
if (selectInclude && typeof selectInclude === "object") {
|
|
1153
|
+
Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
|
|
1154
|
+
result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
|
|
1155
|
+
});
|
|
1156
|
+
}
|
|
828
1157
|
}
|
|
829
1158
|
return result;
|
|
830
1159
|
}
|
|
@@ -864,12 +1193,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
864
1193
|
return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
|
|
865
1194
|
}
|
|
866
1195
|
}
|
|
1196
|
+
get supportInsertWithDefault() {
|
|
1197
|
+
return true;
|
|
1198
|
+
}
|
|
867
1199
|
};
|
|
868
1200
|
|
|
869
1201
|
// src/client/crud/dialects/sqlite.ts
|
|
1202
|
+
var import_common_helpers3 = require("@zenstackhq/common-helpers");
|
|
870
1203
|
var import_kysely3 = require("kysely");
|
|
871
|
-
var
|
|
872
|
-
var import_ts_pattern3 = require("ts-pattern");
|
|
1204
|
+
var import_ts_pattern4 = require("ts-pattern");
|
|
873
1205
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
874
1206
|
static {
|
|
875
1207
|
__name(this, "SqliteCrudDialect");
|
|
@@ -877,54 +1209,49 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
877
1209
|
get provider() {
|
|
878
1210
|
return "sqlite";
|
|
879
1211
|
}
|
|
880
|
-
transformPrimitive(value, type) {
|
|
1212
|
+
transformPrimitive(value, type, _forArrayField) {
|
|
881
1213
|
if (value === void 0) {
|
|
882
1214
|
return value;
|
|
883
1215
|
}
|
|
884
1216
|
if (Array.isArray(value)) {
|
|
885
|
-
return value.map((v) => this.transformPrimitive(v, type));
|
|
1217
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
886
1218
|
} else {
|
|
887
|
-
|
|
1219
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1220
|
+
return JSON.stringify(value);
|
|
1221
|
+
} else {
|
|
1222
|
+
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);
|
|
1223
|
+
}
|
|
888
1224
|
}
|
|
889
1225
|
}
|
|
890
1226
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
891
1227
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
892
1228
|
}
|
|
893
|
-
buildRelationJSON(model, eb, relationField,
|
|
1229
|
+
buildRelationJSON(model, eb, relationField, parentAlias, payload) {
|
|
894
1230
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
895
1231
|
const relationModel = relationFieldDef.type;
|
|
896
1232
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
897
|
-
const subQueryName = `${
|
|
1233
|
+
const subQueryName = `${parentAlias}$${relationField}`;
|
|
898
1234
|
let tbl = eb.selectFrom(() => {
|
|
899
|
-
|
|
1235
|
+
const subQueryAlias = `${parentAlias}$${relationField}$sub`;
|
|
1236
|
+
let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
|
|
1237
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0, subQueryAlias);
|
|
900
1238
|
if (payload && typeof payload === "object") {
|
|
901
|
-
|
|
902
|
-
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
903
|
-
}
|
|
904
|
-
const skip = payload.skip;
|
|
905
|
-
let take = payload.take;
|
|
906
|
-
let negateOrderBy = false;
|
|
907
|
-
if (take !== void 0 && take < 0) {
|
|
908
|
-
negateOrderBy = true;
|
|
909
|
-
take = -take;
|
|
910
|
-
}
|
|
911
|
-
subQuery = this.buildSkipTake(subQuery, skip, take);
|
|
912
|
-
subQuery = this.buildOrderBy(subQuery, relationModel, relationModel, payload.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
1239
|
+
subQuery = this.buildFilterSortTake(relationModel, payload, subQuery, subQueryAlias);
|
|
913
1240
|
}
|
|
914
1241
|
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
915
1242
|
if (m2m) {
|
|
916
1243
|
const parentIds = getIdFields(this.schema, model);
|
|
917
1244
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
918
|
-
(0,
|
|
919
|
-
(0,
|
|
920
|
-
subQuery = subQuery.where(eb(eb.ref(`${
|
|
1245
|
+
(0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1246
|
+
(0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1247
|
+
subQuery = subQuery.where(eb(eb.ref(`${subQueryAlias}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
921
1248
|
} else {
|
|
922
1249
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
923
1250
|
keyPairs.forEach(({ fk, pk }) => {
|
|
924
1251
|
if (ownedByModel) {
|
|
925
|
-
subQuery = subQuery.whereRef(`${
|
|
1252
|
+
subQuery = subQuery.whereRef(`${subQueryAlias}.${pk}`, "=", `${parentAlias}.${fk}`);
|
|
926
1253
|
} else {
|
|
927
|
-
subQuery = subQuery.whereRef(`${
|
|
1254
|
+
subQuery = subQuery.whereRef(`${subQueryAlias}.${fk}`, "=", `${parentAlias}.${pk}`);
|
|
928
1255
|
}
|
|
929
1256
|
});
|
|
930
1257
|
}
|
|
@@ -932,31 +1259,46 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
932
1259
|
});
|
|
933
1260
|
tbl = tbl.select(() => {
|
|
934
1261
|
const objArgs = [];
|
|
1262
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1263
|
+
if (descendantModels.length > 0) {
|
|
1264
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1265
|
+
import_kysely3.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1266
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1267
|
+
]).flatMap((v) => v));
|
|
1268
|
+
}
|
|
935
1269
|
if (payload === true || !payload.select) {
|
|
936
1270
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
937
1271
|
import_kysely3.sql.lit(field),
|
|
938
|
-
|
|
1272
|
+
this.fieldRef(relationModel, field, eb, void 0, false)
|
|
939
1273
|
]).flatMap((v) => v));
|
|
940
1274
|
} else if (payload.select) {
|
|
941
1275
|
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
|
|
1276
|
+
if (field === "_count") {
|
|
1277
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
945
1278
|
return [
|
|
946
1279
|
import_kysely3.sql.lit(field),
|
|
947
1280
|
subJson
|
|
948
1281
|
];
|
|
949
1282
|
} else {
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
1283
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1284
|
+
if (fieldDef.relation) {
|
|
1285
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1286
|
+
return [
|
|
1287
|
+
import_kysely3.sql.lit(field),
|
|
1288
|
+
subJson
|
|
1289
|
+
];
|
|
1290
|
+
} else {
|
|
1291
|
+
return [
|
|
1292
|
+
import_kysely3.sql.lit(field),
|
|
1293
|
+
this.fieldRef(relationModel, field, eb, void 0, false)
|
|
1294
|
+
];
|
|
1295
|
+
}
|
|
954
1296
|
}
|
|
955
1297
|
}).flatMap((v) => v));
|
|
956
1298
|
}
|
|
957
1299
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
958
1300
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
959
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${
|
|
1301
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
960
1302
|
return [
|
|
961
1303
|
import_kysely3.sql.lit(field),
|
|
962
1304
|
subJson
|
|
@@ -1006,93 +1348,17 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1006
1348
|
buildArrayLiteralSQL(_values) {
|
|
1007
1349
|
throw new Error("SQLite does not support array literals");
|
|
1008
1350
|
}
|
|
1351
|
+
get supportInsertWithDefault() {
|
|
1352
|
+
return false;
|
|
1353
|
+
}
|
|
1009
1354
|
};
|
|
1010
1355
|
|
|
1011
1356
|
// src/client/crud/dialects/index.ts
|
|
1012
1357
|
function getCrudDialect(schema, options) {
|
|
1013
|
-
return (0,
|
|
1358
|
+
return (0, import_ts_pattern5.match)(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
|
|
1014
1359
|
}
|
|
1015
1360
|
__name(getCrudDialect, "getCrudDialect");
|
|
1016
1361
|
|
|
1017
|
-
// src/schema/expression.ts
|
|
1018
|
-
var ExpressionUtils = {
|
|
1019
|
-
literal: /* @__PURE__ */ __name((value) => {
|
|
1020
|
-
return {
|
|
1021
|
-
kind: "literal",
|
|
1022
|
-
value
|
|
1023
|
-
};
|
|
1024
|
-
}, "literal"),
|
|
1025
|
-
array: /* @__PURE__ */ __name((items) => {
|
|
1026
|
-
return {
|
|
1027
|
-
kind: "array",
|
|
1028
|
-
items
|
|
1029
|
-
};
|
|
1030
|
-
}, "array"),
|
|
1031
|
-
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
1032
|
-
return {
|
|
1033
|
-
kind: "call",
|
|
1034
|
-
function: functionName,
|
|
1035
|
-
args
|
|
1036
|
-
};
|
|
1037
|
-
}, "call"),
|
|
1038
|
-
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
1039
|
-
return {
|
|
1040
|
-
kind: "binary",
|
|
1041
|
-
op,
|
|
1042
|
-
left,
|
|
1043
|
-
right
|
|
1044
|
-
};
|
|
1045
|
-
}, "binary"),
|
|
1046
|
-
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
1047
|
-
return {
|
|
1048
|
-
kind: "unary",
|
|
1049
|
-
op,
|
|
1050
|
-
operand
|
|
1051
|
-
};
|
|
1052
|
-
}, "unary"),
|
|
1053
|
-
field: /* @__PURE__ */ __name((field) => {
|
|
1054
|
-
return {
|
|
1055
|
-
kind: "field",
|
|
1056
|
-
field
|
|
1057
|
-
};
|
|
1058
|
-
}, "field"),
|
|
1059
|
-
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
1060
|
-
return {
|
|
1061
|
-
kind: "member",
|
|
1062
|
-
receiver,
|
|
1063
|
-
members
|
|
1064
|
-
};
|
|
1065
|
-
}, "member"),
|
|
1066
|
-
_this: /* @__PURE__ */ __name(() => {
|
|
1067
|
-
return {
|
|
1068
|
-
kind: "this"
|
|
1069
|
-
};
|
|
1070
|
-
}, "_this"),
|
|
1071
|
-
_null: /* @__PURE__ */ __name(() => {
|
|
1072
|
-
return {
|
|
1073
|
-
kind: "null"
|
|
1074
|
-
};
|
|
1075
|
-
}, "_null"),
|
|
1076
|
-
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1077
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
1078
|
-
}, "and"),
|
|
1079
|
-
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1080
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
1081
|
-
}, "or"),
|
|
1082
|
-
is: /* @__PURE__ */ __name((value, kind) => {
|
|
1083
|
-
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
1084
|
-
}, "is"),
|
|
1085
|
-
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
1086
|
-
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
1087
|
-
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
1088
|
-
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
1089
|
-
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
1090
|
-
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
1091
|
-
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
1092
|
-
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
1093
|
-
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
|
|
1094
|
-
};
|
|
1095
|
-
|
|
1096
1362
|
// src/utils/default-operation-node-visitor.ts
|
|
1097
1363
|
var import_kysely4 = require("kysely");
|
|
1098
1364
|
var DefaultOperationNodeVisitor = class extends import_kysely4.OperationNodeVisitor {
|
|
@@ -1412,19 +1678,19 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1412
1678
|
};
|
|
1413
1679
|
|
|
1414
1680
|
// src/plugins/policy/expression-transformer.ts
|
|
1681
|
+
var import_common_helpers5 = require("@zenstackhq/common-helpers");
|
|
1415
1682
|
var import_kysely6 = require("kysely");
|
|
1416
|
-
var
|
|
1417
|
-
var import_ts_pattern6 = require("ts-pattern");
|
|
1683
|
+
var import_ts_pattern7 = require("ts-pattern");
|
|
1418
1684
|
|
|
1419
1685
|
// src/plugins/policy/expression-evaluator.ts
|
|
1420
|
-
var
|
|
1421
|
-
var
|
|
1686
|
+
var import_common_helpers4 = require("@zenstackhq/common-helpers");
|
|
1687
|
+
var import_ts_pattern6 = require("ts-pattern");
|
|
1422
1688
|
var ExpressionEvaluator = class {
|
|
1423
1689
|
static {
|
|
1424
1690
|
__name(this, "ExpressionEvaluator");
|
|
1425
1691
|
}
|
|
1426
1692
|
evaluate(expression, context) {
|
|
1427
|
-
const result = (0,
|
|
1693
|
+
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();
|
|
1428
1694
|
return result ?? null;
|
|
1429
1695
|
}
|
|
1430
1696
|
evaluateCall(expr2, context) {
|
|
@@ -1435,7 +1701,7 @@ var ExpressionEvaluator = class {
|
|
|
1435
1701
|
}
|
|
1436
1702
|
}
|
|
1437
1703
|
evaluateUnary(expr2, context) {
|
|
1438
|
-
return (0,
|
|
1704
|
+
return (0, import_ts_pattern6.match)(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
|
|
1439
1705
|
}
|
|
1440
1706
|
evaluateMember(expr2, context) {
|
|
1441
1707
|
let val = this.evaluate(expr2.receiver, context);
|
|
@@ -1459,21 +1725,21 @@ var ExpressionEvaluator = class {
|
|
|
1459
1725
|
}
|
|
1460
1726
|
const left = this.evaluate(expr2.left, context);
|
|
1461
1727
|
const right = this.evaluate(expr2.right, context);
|
|
1462
|
-
return (0,
|
|
1728
|
+
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", () => {
|
|
1463
1729
|
const _right = right ?? [];
|
|
1464
|
-
(0,
|
|
1730
|
+
(0, import_common_helpers4.invariant)(Array.isArray(_right), 'expected array for "in" operator');
|
|
1465
1731
|
return _right.includes(left);
|
|
1466
1732
|
}).exhaustive();
|
|
1467
1733
|
}
|
|
1468
1734
|
evaluateCollectionPredicate(expr2, context) {
|
|
1469
1735
|
const op = expr2.op;
|
|
1470
|
-
(0,
|
|
1736
|
+
(0, import_common_helpers4.invariant)(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
|
|
1471
1737
|
const left = this.evaluate(expr2.left, context);
|
|
1472
1738
|
if (!left) {
|
|
1473
1739
|
return false;
|
|
1474
1740
|
}
|
|
1475
|
-
(0,
|
|
1476
|
-
return (0,
|
|
1741
|
+
(0, import_common_helpers4.invariant)(Array.isArray(left), "expected array");
|
|
1742
|
+
return (0, import_ts_pattern6.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1477
1743
|
...context,
|
|
1478
1744
|
thisValue: item
|
|
1479
1745
|
}))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
|
|
@@ -1489,11 +1755,11 @@ var ExpressionEvaluator = class {
|
|
|
1489
1755
|
// src/plugins/policy/utils.ts
|
|
1490
1756
|
var import_kysely5 = require("kysely");
|
|
1491
1757
|
function trueNode(dialect) {
|
|
1492
|
-
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
|
|
1758
|
+
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1493
1759
|
}
|
|
1494
1760
|
__name(trueNode, "trueNode");
|
|
1495
1761
|
function falseNode(dialect) {
|
|
1496
|
-
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
|
|
1762
|
+
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1497
1763
|
}
|
|
1498
1764
|
__name(falseNode, "falseNode");
|
|
1499
1765
|
function isTrueNode(node) {
|
|
@@ -1694,20 +1960,20 @@ var ExpressionTransformer = class {
|
|
|
1694
1960
|
return import_kysely6.BinaryOperationNode.create(left, this.transformOperator(op), right);
|
|
1695
1961
|
}
|
|
1696
1962
|
transformCollectionPredicate(expr2, context) {
|
|
1697
|
-
(0,
|
|
1963
|
+
(0, import_common_helpers5.invariant)(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
|
|
1698
1964
|
if (this.isAuthCall(expr2.left) || this.isAuthMember(expr2.left)) {
|
|
1699
1965
|
const value = new ExpressionEvaluator().evaluate(expr2, {
|
|
1700
1966
|
auth: this.auth
|
|
1701
1967
|
});
|
|
1702
1968
|
return this.transformValue(value, "Boolean");
|
|
1703
1969
|
}
|
|
1704
|
-
(0,
|
|
1970
|
+
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
|
|
1705
1971
|
let newContextModel;
|
|
1706
1972
|
if (ExpressionUtils.isField(expr2.left)) {
|
|
1707
1973
|
const fieldDef = requireField(this.schema, context.model, expr2.left.field);
|
|
1708
1974
|
newContextModel = fieldDef.type;
|
|
1709
1975
|
} else {
|
|
1710
|
-
(0,
|
|
1976
|
+
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left.receiver));
|
|
1711
1977
|
const fieldDef = requireField(this.schema, context.model, expr2.left.receiver.field);
|
|
1712
1978
|
newContextModel = fieldDef.type;
|
|
1713
1979
|
for (const member of expr2.left.members) {
|
|
@@ -1727,7 +1993,7 @@ var ExpressionTransformer = class {
|
|
|
1727
1993
|
const count = import_kysely6.FunctionNode.create("count", [
|
|
1728
1994
|
import_kysely6.ValueNode.createImmediate(1)
|
|
1729
1995
|
]);
|
|
1730
|
-
const predicateResult = (0,
|
|
1996
|
+
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();
|
|
1731
1997
|
return this.transform(expr2.left, {
|
|
1732
1998
|
...context,
|
|
1733
1999
|
memberSelect: import_kysely6.SelectionNode.create(import_kysely6.AliasNode.create(predicateResult, import_kysely6.IdentifierNode.create("$t"))),
|
|
@@ -1751,14 +2017,14 @@ var ExpressionTransformer = class {
|
|
|
1751
2017
|
}
|
|
1752
2018
|
}
|
|
1753
2019
|
transformValue(value, type) {
|
|
1754
|
-
return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type) ?? null);
|
|
2020
|
+
return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
1755
2021
|
}
|
|
1756
2022
|
_unary(expr2, context) {
|
|
1757
|
-
(0,
|
|
2023
|
+
(0, import_common_helpers5.invariant)(expr2.op === "!", 'only "!" operator is supported');
|
|
1758
2024
|
return import_kysely6.BinaryOperationNode.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
|
|
1759
2025
|
}
|
|
1760
2026
|
transformOperator(op) {
|
|
1761
|
-
const mappedOp = (0,
|
|
2027
|
+
const mappedOp = (0, import_ts_pattern7.match)(op).with("==", () => "=").otherwise(() => op);
|
|
1762
2028
|
return import_kysely6.OperatorNode.create(mappedOp);
|
|
1763
2029
|
}
|
|
1764
2030
|
_call(expr2, context) {
|
|
@@ -1797,10 +2063,10 @@ var ExpressionTransformer = class {
|
|
|
1797
2063
|
if (this.isAuthCall(expr2.receiver)) {
|
|
1798
2064
|
return this.valueMemberAccess(this.auth, expr2, this.authType);
|
|
1799
2065
|
}
|
|
1800
|
-
(0,
|
|
2066
|
+
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.receiver), "expect receiver to be field expression");
|
|
1801
2067
|
const { memberFilter, memberSelect, ...restContext } = context;
|
|
1802
2068
|
const receiver = this.transform(expr2.receiver, restContext);
|
|
1803
|
-
(0,
|
|
2069
|
+
(0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(receiver), "expected receiver to be select query");
|
|
1804
2070
|
const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
|
|
1805
2071
|
const memberFields = [];
|
|
1806
2072
|
let currType = receiverField.type;
|
|
@@ -1824,7 +2090,7 @@ var ExpressionTransformer = class {
|
|
|
1824
2090
|
thisEntity: void 0
|
|
1825
2091
|
});
|
|
1826
2092
|
if (currNode) {
|
|
1827
|
-
(0,
|
|
2093
|
+
(0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(currNode), "expected select query node");
|
|
1828
2094
|
currNode = {
|
|
1829
2095
|
...relation,
|
|
1830
2096
|
selections: [
|
|
@@ -1841,8 +2107,8 @@ var ExpressionTransformer = class {
|
|
|
1841
2107
|
};
|
|
1842
2108
|
}
|
|
1843
2109
|
} else {
|
|
1844
|
-
(0,
|
|
1845
|
-
(0,
|
|
2110
|
+
(0, import_common_helpers5.invariant)(i === expr2.members.length - 1, "plain field access must be the last segment");
|
|
2111
|
+
(0, import_common_helpers5.invariant)(!currNode, "plain field access must be the last segment");
|
|
1846
2112
|
currNode = import_kysely6.ColumnNode.create(member);
|
|
1847
2113
|
}
|
|
1848
2114
|
}
|
|
@@ -1994,7 +2260,7 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
1994
2260
|
get kysely() {
|
|
1995
2261
|
return this.client.$qb;
|
|
1996
2262
|
}
|
|
1997
|
-
async handle(node, proceed
|
|
2263
|
+
async handle(node, proceed) {
|
|
1998
2264
|
if (!this.isCrudQueryNode(node)) {
|
|
1999
2265
|
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
2000
2266
|
}
|
|
@@ -2014,27 +2280,20 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2014
2280
|
if (!mutationRequiresTransaction && !node.returning) {
|
|
2015
2281
|
return proceed(this.transformNode(node));
|
|
2016
2282
|
}
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
const
|
|
2024
|
-
if (
|
|
2025
|
-
|
|
2026
|
-
if (readBackResult.rows.length !== result2.rows.length) {
|
|
2027
|
-
readBackError = true;
|
|
2028
|
-
}
|
|
2029
|
-
return readBackResult;
|
|
2030
|
-
} else {
|
|
2031
|
-
return result2;
|
|
2283
|
+
if (import_kysely7.InsertQueryNode.is(node)) {
|
|
2284
|
+
await this.enforcePreCreatePolicy(node, proceed);
|
|
2285
|
+
}
|
|
2286
|
+
const transformedNode = this.transformNode(node);
|
|
2287
|
+
const result = await proceed(transformedNode);
|
|
2288
|
+
if (!this.onlyReturningId(node)) {
|
|
2289
|
+
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2290
|
+
if (readBackResult.rows.length !== result.rows.length) {
|
|
2291
|
+
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
2032
2292
|
}
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2293
|
+
return readBackResult;
|
|
2294
|
+
} else {
|
|
2295
|
+
return result;
|
|
2036
2296
|
}
|
|
2037
|
-
return result;
|
|
2038
2297
|
}
|
|
2039
2298
|
onlyReturningId(node) {
|
|
2040
2299
|
if (!node.returning) {
|
|
@@ -2087,19 +2346,19 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2087
2346
|
}
|
|
2088
2347
|
}
|
|
2089
2348
|
unwrapCreateValueRow(data, model, fields) {
|
|
2090
|
-
(0,
|
|
2349
|
+
(0, import_common_helpers6.invariant)(data.length === fields.length, "data length must match fields length");
|
|
2091
2350
|
const result = [];
|
|
2092
2351
|
for (let i = 0; i < data.length; i++) {
|
|
2093
2352
|
const item = data[i];
|
|
2094
2353
|
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
2095
2354
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2096
|
-
(0,
|
|
2355
|
+
(0, import_common_helpers6.invariant)(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2097
2356
|
result.push({
|
|
2098
|
-
node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
|
|
2357
|
+
node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2099
2358
|
raw: item.value
|
|
2100
2359
|
});
|
|
2101
2360
|
} else {
|
|
2102
|
-
const value = this.dialect.transformPrimitive(item, fieldDef.type);
|
|
2361
|
+
const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
2103
2362
|
if (Array.isArray(value)) {
|
|
2104
2363
|
result.push({
|
|
2105
2364
|
node: import_kysely7.RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
@@ -2168,7 +2427,7 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2168
2427
|
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]))))));
|
|
2169
2428
|
}
|
|
2170
2429
|
getMutationModel(node) {
|
|
2171
|
-
const r = (0,
|
|
2430
|
+
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) => {
|
|
2172
2431
|
if (node2.from.froms.length !== 1) {
|
|
2173
2432
|
throw new InternalError("Only one from table is supported for delete");
|
|
2174
2433
|
}
|
|
@@ -2301,8 +2560,8 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2301
2560
|
const modelDef = requireModel(this.client.$schema, modelName);
|
|
2302
2561
|
const result = [];
|
|
2303
2562
|
const extractOperations = /* @__PURE__ */ __name((expr2) => {
|
|
2304
|
-
(0,
|
|
2305
|
-
(0,
|
|
2563
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isLiteral(expr2), "expecting a literal");
|
|
2564
|
+
(0, import_common_helpers6.invariant)(typeof expr2.value === "string", "expecting a string literal");
|
|
2306
2565
|
return expr2.value.split(",").filter((v) => !!v).map((v) => v.trim());
|
|
2307
2566
|
}, "extractOperations");
|
|
2308
2567
|
if (modelDef.attributes) {
|
|
@@ -2330,9 +2589,18 @@ var PolicyPlugin = class {
|
|
|
2330
2589
|
get description() {
|
|
2331
2590
|
return "Enforces access policies defined in the schema.";
|
|
2332
2591
|
}
|
|
2333
|
-
onKyselyQuery({
|
|
2592
|
+
onKyselyQuery({
|
|
2593
|
+
query,
|
|
2594
|
+
client,
|
|
2595
|
+
proceed
|
|
2596
|
+
/*, transaction*/
|
|
2597
|
+
}) {
|
|
2334
2598
|
const handler = new PolicyHandler(client);
|
|
2335
|
-
return handler.handle(
|
|
2599
|
+
return handler.handle(
|
|
2600
|
+
query,
|
|
2601
|
+
proceed
|
|
2602
|
+
/*, transaction*/
|
|
2603
|
+
);
|
|
2336
2604
|
}
|
|
2337
2605
|
};
|
|
2338
2606
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -2340,4 +2608,4 @@ var PolicyPlugin = class {
|
|
|
2340
2608
|
PolicyPlugin,
|
|
2341
2609
|
RejectedByPolicyError
|
|
2342
2610
|
});
|
|
2343
|
-
//# sourceMappingURL=
|
|
2611
|
+
//# sourceMappingURL=index.cjs.map
|