@zenstackhq/runtime 3.0.0-beta.1 → 3.0.0-beta.10
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-CusA0mQO.d.cts → auth-CzM6GLw6.d.cts} +17 -960
- package/dist/{contract-CusA0mQO.d.ts → auth-CzM6GLw6.d.ts} +17 -960
- package/dist/index.cjs +5204 -5406
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1288 -11
- package/dist/index.d.ts +1288 -11
- package/dist/index.js +5194 -5406
- package/dist/index.js.map +1 -1
- package/dist/schema.cjs +3 -0
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +3 -0
- package/dist/schema.d.ts +3 -0
- package/dist/schema.js +3 -0
- package/dist/schema.js.map +1 -1
- package/package.json +13 -16
- package/dist/plugins/policy/index.cjs +0 -2650
- package/dist/plugins/policy/index.cjs.map +0 -1
- package/dist/plugins/policy/index.d.cts +0 -22
- package/dist/plugins/policy/index.d.ts +0 -22
- package/dist/plugins/policy/index.js +0 -2624
- package/dist/plugins/policy/index.js.map +0 -1
- package/dist/plugins/policy/plugin.zmodel +0 -33
|
@@ -1,2650 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
-
|
|
21
|
-
// src/plugins/policy/index.ts
|
|
22
|
-
var policy_exports = {};
|
|
23
|
-
__export(policy_exports, {
|
|
24
|
-
PolicyPlugin: () => PolicyPlugin,
|
|
25
|
-
RejectedByPolicyError: () => RejectedByPolicyError
|
|
26
|
-
});
|
|
27
|
-
module.exports = __toCommonJS(policy_exports);
|
|
28
|
-
|
|
29
|
-
// src/plugins/policy/errors.ts
|
|
30
|
-
var RejectedByPolicyError = class extends Error {
|
|
31
|
-
static {
|
|
32
|
-
__name(this, "RejectedByPolicyError");
|
|
33
|
-
}
|
|
34
|
-
model;
|
|
35
|
-
reason;
|
|
36
|
-
constructor(model, reason) {
|
|
37
|
-
super(reason ?? `Operation rejected by policy${model ? ": " + model : ""}`), this.model = model, this.reason = reason;
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
// src/plugins/policy/policy-handler.ts
|
|
42
|
-
var import_common_helpers6 = require("@zenstackhq/common-helpers");
|
|
43
|
-
var import_kysely7 = require("kysely");
|
|
44
|
-
var import_ts_pattern8 = require("ts-pattern");
|
|
45
|
-
|
|
46
|
-
// src/client/crud/dialects/index.ts
|
|
47
|
-
var import_ts_pattern5 = require("ts-pattern");
|
|
48
|
-
|
|
49
|
-
// src/client/crud/dialects/postgresql.ts
|
|
50
|
-
var import_common_helpers2 = require("@zenstackhq/common-helpers");
|
|
51
|
-
var import_kysely2 = require("kysely");
|
|
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
|
-
};
|
|
153
|
-
|
|
154
|
-
// src/client/errors.ts
|
|
155
|
-
var QueryError = class extends Error {
|
|
156
|
-
static {
|
|
157
|
-
__name(this, "QueryError");
|
|
158
|
-
}
|
|
159
|
-
constructor(message, cause) {
|
|
160
|
-
super(message, {
|
|
161
|
-
cause
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
var InternalError = class extends Error {
|
|
166
|
-
static {
|
|
167
|
-
__name(this, "InternalError");
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
// src/client/query-utils.ts
|
|
172
|
-
function getModel(schema, model) {
|
|
173
|
-
return schema.models[model];
|
|
174
|
-
}
|
|
175
|
-
__name(getModel, "getModel");
|
|
176
|
-
function requireModel(schema, model) {
|
|
177
|
-
const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
|
|
178
|
-
if (!matchedName) {
|
|
179
|
-
throw new QueryError(`Model "${model}" not found in schema`);
|
|
180
|
-
}
|
|
181
|
-
return schema.models[matchedName];
|
|
182
|
-
}
|
|
183
|
-
__name(requireModel, "requireModel");
|
|
184
|
-
function getField(schema, model, field) {
|
|
185
|
-
const modelDef = getModel(schema, model);
|
|
186
|
-
return modelDef?.fields[field];
|
|
187
|
-
}
|
|
188
|
-
__name(getField, "getField");
|
|
189
|
-
function requireField(schema, model, field) {
|
|
190
|
-
const modelDef = requireModel(schema, model);
|
|
191
|
-
if (!modelDef.fields[field]) {
|
|
192
|
-
throw new QueryError(`Field "${field}" not found in model "${model}"`);
|
|
193
|
-
}
|
|
194
|
-
return modelDef.fields[field];
|
|
195
|
-
}
|
|
196
|
-
__name(requireField, "requireField");
|
|
197
|
-
function getIdFields(schema, model) {
|
|
198
|
-
const modelDef = requireModel(schema, model);
|
|
199
|
-
return modelDef?.idFields;
|
|
200
|
-
}
|
|
201
|
-
__name(getIdFields, "getIdFields");
|
|
202
|
-
function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
203
|
-
const fieldDef = requireField(schema, model, relationField);
|
|
204
|
-
if (!fieldDef?.relation) {
|
|
205
|
-
throw new InternalError(`Field "${relationField}" is not a relation`);
|
|
206
|
-
}
|
|
207
|
-
if (fieldDef.relation.fields) {
|
|
208
|
-
if (!fieldDef.relation.references) {
|
|
209
|
-
throw new InternalError(`Relation references not defined for field "${relationField}"`);
|
|
210
|
-
}
|
|
211
|
-
return {
|
|
212
|
-
keyPairs: fieldDef.relation.fields.map((f, i) => ({
|
|
213
|
-
fk: f,
|
|
214
|
-
pk: fieldDef.relation.references[i]
|
|
215
|
-
})),
|
|
216
|
-
ownedByModel: true
|
|
217
|
-
};
|
|
218
|
-
} else {
|
|
219
|
-
if (!fieldDef.relation.opposite) {
|
|
220
|
-
throw new InternalError(`Opposite relation not defined for field "${relationField}"`);
|
|
221
|
-
}
|
|
222
|
-
const oppositeField = requireField(schema, fieldDef.type, fieldDef.relation.opposite);
|
|
223
|
-
if (!oppositeField.relation) {
|
|
224
|
-
throw new InternalError(`Field "${fieldDef.relation.opposite}" is not a relation`);
|
|
225
|
-
}
|
|
226
|
-
if (!oppositeField.relation.fields) {
|
|
227
|
-
throw new InternalError(`Relation fields not defined for field "${relationField}"`);
|
|
228
|
-
}
|
|
229
|
-
if (!oppositeField.relation.references) {
|
|
230
|
-
throw new InternalError(`Relation references not defined for field "${relationField}"`);
|
|
231
|
-
}
|
|
232
|
-
return {
|
|
233
|
-
keyPairs: oppositeField.relation.fields.map((f, i) => ({
|
|
234
|
-
fk: f,
|
|
235
|
-
pk: oppositeField.relation.references[i]
|
|
236
|
-
})),
|
|
237
|
-
ownedByModel: false
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
__name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
|
|
242
|
-
function isRelationField(schema, model, field) {
|
|
243
|
-
const fieldDef = getField(schema, model, field);
|
|
244
|
-
return !!fieldDef?.relation;
|
|
245
|
-
}
|
|
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");
|
|
252
|
-
function getUniqueFields(schema, model) {
|
|
253
|
-
const modelDef = requireModel(schema, model);
|
|
254
|
-
const result = [];
|
|
255
|
-
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
256
|
-
if (typeof value !== "object") {
|
|
257
|
-
throw new InternalError(`Invalid unique field definition for "${key}"`);
|
|
258
|
-
}
|
|
259
|
-
if (typeof value.type === "string") {
|
|
260
|
-
result.push({
|
|
261
|
-
name: key,
|
|
262
|
-
def: requireField(schema, model, key)
|
|
263
|
-
});
|
|
264
|
-
} else {
|
|
265
|
-
result.push({
|
|
266
|
-
name: key,
|
|
267
|
-
defs: Object.fromEntries(Object.keys(value).map((k) => [
|
|
268
|
-
k,
|
|
269
|
-
requireField(schema, model, k)
|
|
270
|
-
]))
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
return result;
|
|
275
|
-
}
|
|
276
|
-
__name(getUniqueFields, "getUniqueFields");
|
|
277
|
-
function buildFieldRef(schema, model, field, options, eb, modelAlias, inlineComputedField = true) {
|
|
278
|
-
const fieldDef = requireField(schema, model, field);
|
|
279
|
-
if (!fieldDef.computed) {
|
|
280
|
-
return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
|
|
281
|
-
} else {
|
|
282
|
-
if (!inlineComputedField) {
|
|
283
|
-
return eb.ref(modelAlias ? `${modelAlias}.${field}` : field);
|
|
284
|
-
}
|
|
285
|
-
let computer;
|
|
286
|
-
if ("computedFields" in options) {
|
|
287
|
-
const computedFields = options.computedFields;
|
|
288
|
-
computer = computedFields?.[model]?.[field];
|
|
289
|
-
}
|
|
290
|
-
if (!computer) {
|
|
291
|
-
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
292
|
-
}
|
|
293
|
-
return computer(eb, {
|
|
294
|
-
currentModel: modelAlias
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
__name(buildFieldRef, "buildFieldRef");
|
|
299
|
-
function isEnum(schema, type) {
|
|
300
|
-
return !!schema.enums?.[type];
|
|
301
|
-
}
|
|
302
|
-
__name(isEnum, "isEnum");
|
|
303
|
-
function buildJoinPairs(schema, model, modelAlias, relationField, relationModelAlias) {
|
|
304
|
-
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(schema, model, relationField);
|
|
305
|
-
return keyPairs.map(({ fk, pk }) => {
|
|
306
|
-
if (ownedByModel) {
|
|
307
|
-
return [
|
|
308
|
-
`${relationModelAlias}.${pk}`,
|
|
309
|
-
`${modelAlias}.${fk}`
|
|
310
|
-
];
|
|
311
|
-
} else {
|
|
312
|
-
return [
|
|
313
|
-
`${relationModelAlias}.${fk}`,
|
|
314
|
-
`${modelAlias}.${pk}`
|
|
315
|
-
];
|
|
316
|
-
}
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
__name(buildJoinPairs, "buildJoinPairs");
|
|
320
|
-
function makeDefaultOrderBy(schema, model) {
|
|
321
|
-
const idFields = getIdFields(schema, model);
|
|
322
|
-
return idFields.map((f) => ({
|
|
323
|
-
[f]: "asc"
|
|
324
|
-
}));
|
|
325
|
-
}
|
|
326
|
-
__name(makeDefaultOrderBy, "makeDefaultOrderBy");
|
|
327
|
-
function getManyToManyRelation(schema, model, field) {
|
|
328
|
-
const fieldDef = requireField(schema, model, field);
|
|
329
|
-
if (!fieldDef.array || !fieldDef.relation?.opposite) {
|
|
330
|
-
return void 0;
|
|
331
|
-
}
|
|
332
|
-
const oppositeFieldDef = requireField(schema, fieldDef.type, fieldDef.relation.opposite);
|
|
333
|
-
if (oppositeFieldDef.array) {
|
|
334
|
-
const sortedModelNames = [
|
|
335
|
-
model,
|
|
336
|
-
fieldDef.type
|
|
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
|
-
}
|
|
360
|
-
return {
|
|
361
|
-
parentFkName: orderedFK[0],
|
|
362
|
-
otherModel: fieldDef.type,
|
|
363
|
-
otherField: fieldDef.relation.opposite,
|
|
364
|
-
otherFkName: orderedFK[1],
|
|
365
|
-
joinTable: fieldDef.relation.name ? `_${fieldDef.relation.name}` : `_${sortedModelNames[0]}To${sortedModelNames[1]}`
|
|
366
|
-
};
|
|
367
|
-
} else {
|
|
368
|
-
return void 0;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
__name(getManyToManyRelation, "getManyToManyRelation");
|
|
372
|
-
function flattenCompoundUniqueFilters(schema, model, filter) {
|
|
373
|
-
if (typeof filter !== "object" || !filter) {
|
|
374
|
-
return filter;
|
|
375
|
-
}
|
|
376
|
-
const uniqueFields = getUniqueFields(schema, model);
|
|
377
|
-
const compoundUniques = uniqueFields.filter((u) => "defs" in u);
|
|
378
|
-
if (compoundUniques.length === 0) {
|
|
379
|
-
return filter;
|
|
380
|
-
}
|
|
381
|
-
const result = {};
|
|
382
|
-
for (const [key, value] of Object.entries(filter)) {
|
|
383
|
-
if (compoundUniques.some(({ name }) => name === key)) {
|
|
384
|
-
Object.assign(result, value);
|
|
385
|
-
} else {
|
|
386
|
-
result[key] = value;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
return result;
|
|
390
|
-
}
|
|
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");
|
|
419
|
-
|
|
420
|
-
// src/client/crud/dialects/base.ts
|
|
421
|
-
var import_common_helpers = require("@zenstackhq/common-helpers");
|
|
422
|
-
var import_kysely = require("kysely");
|
|
423
|
-
var import_ts_pattern2 = require("ts-pattern");
|
|
424
|
-
|
|
425
|
-
// src/utils/enumerate.ts
|
|
426
|
-
function enumerate(x) {
|
|
427
|
-
if (x === null || x === void 0) {
|
|
428
|
-
return [];
|
|
429
|
-
} else if (Array.isArray(x)) {
|
|
430
|
-
return x;
|
|
431
|
-
} else {
|
|
432
|
-
return [
|
|
433
|
-
x
|
|
434
|
-
];
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
__name(enumerate, "enumerate");
|
|
438
|
-
|
|
439
|
-
// src/client/crud/dialects/base.ts
|
|
440
|
-
var BaseCrudDialect = class {
|
|
441
|
-
static {
|
|
442
|
-
__name(this, "BaseCrudDialect");
|
|
443
|
-
}
|
|
444
|
-
schema;
|
|
445
|
-
options;
|
|
446
|
-
constructor(schema, options) {
|
|
447
|
-
this.schema = schema;
|
|
448
|
-
this.options = options;
|
|
449
|
-
}
|
|
450
|
-
transformPrimitive(value, _type, _forArrayField) {
|
|
451
|
-
return value;
|
|
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
|
-
}
|
|
491
|
-
buildFilter(eb, model, modelAlias, where) {
|
|
492
|
-
if (where === true || where === void 0) {
|
|
493
|
-
return this.true(eb);
|
|
494
|
-
}
|
|
495
|
-
if (where === false) {
|
|
496
|
-
return this.false(eb);
|
|
497
|
-
}
|
|
498
|
-
let result = this.true(eb);
|
|
499
|
-
const _where = flattenCompoundUniqueFilters(this.schema, model, where);
|
|
500
|
-
for (const [key, payload] of Object.entries(_where)) {
|
|
501
|
-
if (payload === void 0) {
|
|
502
|
-
continue;
|
|
503
|
-
}
|
|
504
|
-
if (key.startsWith("$")) {
|
|
505
|
-
continue;
|
|
506
|
-
}
|
|
507
|
-
if (this.isLogicalCombinator(key)) {
|
|
508
|
-
result = this.and(eb, result, this.buildCompositeFilter(eb, model, modelAlias, key, payload));
|
|
509
|
-
continue;
|
|
510
|
-
}
|
|
511
|
-
const fieldDef = requireField(this.schema, model, key);
|
|
512
|
-
if (fieldDef.relation) {
|
|
513
|
-
result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
514
|
-
} else {
|
|
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
|
-
}
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
if ("$expr" in _where && typeof _where["$expr"] === "function") {
|
|
524
|
-
result = this.and(eb, result, _where["$expr"](eb));
|
|
525
|
-
}
|
|
526
|
-
return result;
|
|
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
|
-
}
|
|
552
|
-
buildCompositeFilter(eb, model, modelAlias, key, payload) {
|
|
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();
|
|
554
|
-
}
|
|
555
|
-
buildRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
556
|
-
if (!fieldDef.array) {
|
|
557
|
-
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
|
|
558
|
-
} else {
|
|
559
|
-
return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
563
|
-
if (payload === null) {
|
|
564
|
-
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
565
|
-
if (ownedByModel && !fieldDef.originModel) {
|
|
566
|
-
return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely.sql.ref(`${modelAlias}.${fk}`), "is", null)));
|
|
567
|
-
} else {
|
|
568
|
-
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
|
|
569
|
-
is: null
|
|
570
|
-
});
|
|
571
|
-
}
|
|
572
|
-
}
|
|
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
|
-
);
|
|
582
|
-
const filterResultField = `${field}$filter`;
|
|
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));
|
|
584
|
-
const conditions = [];
|
|
585
|
-
if ("is" in payload || "isNot" in payload) {
|
|
586
|
-
if ("is" in payload) {
|
|
587
|
-
if (payload.is === null) {
|
|
588
|
-
conditions.push(eb(joinSelect, "=", 0));
|
|
589
|
-
} else {
|
|
590
|
-
conditions.push(eb(joinSelect.where(() => this.buildFilter(eb, fieldDef.type, joinAlias, payload.is)), ">", 0));
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
if ("isNot" in payload) {
|
|
594
|
-
if (payload.isNot === null) {
|
|
595
|
-
conditions.push(eb(joinSelect, ">", 0));
|
|
596
|
-
} else {
|
|
597
|
-
conditions.push(this.or(
|
|
598
|
-
eb,
|
|
599
|
-
// is null
|
|
600
|
-
eb(joinSelect, "=", 0),
|
|
601
|
-
// found one that matches the filter
|
|
602
|
-
eb(joinSelect.where(() => this.buildFilter(eb, fieldDef.type, joinAlias, payload.isNot)), "=", 0)
|
|
603
|
-
));
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
} else {
|
|
607
|
-
conditions.push(eb(joinSelect.where(() => this.buildFilter(eb, fieldDef.type, joinAlias, payload)), ">", 0));
|
|
608
|
-
}
|
|
609
|
-
return this.and(eb, ...conditions);
|
|
610
|
-
}
|
|
611
|
-
buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
612
|
-
if (payload === null) {
|
|
613
|
-
return eb(import_kysely.sql.ref(`${modelAlias}.${field}`), "is", null);
|
|
614
|
-
}
|
|
615
|
-
const relationModel = fieldDef.type;
|
|
616
|
-
const relationFilterSelectAlias = `${modelAlias}$${field}$filter`;
|
|
617
|
-
const buildPkFkWhereRefs = /* @__PURE__ */ __name((eb2) => {
|
|
618
|
-
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
619
|
-
if (m2m) {
|
|
620
|
-
const modelIdField = getIdFields(this.schema, model)[0];
|
|
621
|
-
const relationIdField = getIdFields(this.schema, relationModel)[0];
|
|
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}`)));
|
|
623
|
-
} else {
|
|
624
|
-
const relationKeyPairs = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
625
|
-
let result2 = this.true(eb2);
|
|
626
|
-
for (const { fk, pk } of relationKeyPairs.keyPairs) {
|
|
627
|
-
if (relationKeyPairs.ownedByModel) {
|
|
628
|
-
result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${modelAlias}.${fk}`), "=", import_kysely.sql.ref(`${relationFilterSelectAlias}.${pk}`)));
|
|
629
|
-
} else {
|
|
630
|
-
result2 = this.and(eb2, result2, eb2(import_kysely.sql.ref(`${modelAlias}.${pk}`), "=", import_kysely.sql.ref(`${relationFilterSelectAlias}.${fk}`)));
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
return result2;
|
|
634
|
-
}
|
|
635
|
-
}, "buildPkFkWhereRefs");
|
|
636
|
-
let result = this.true(eb);
|
|
637
|
-
for (const [key, subPayload] of Object.entries(payload)) {
|
|
638
|
-
if (!subPayload) {
|
|
639
|
-
continue;
|
|
640
|
-
}
|
|
641
|
-
switch (key) {
|
|
642
|
-
case "some": {
|
|
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));
|
|
644
|
-
break;
|
|
645
|
-
}
|
|
646
|
-
case "every": {
|
|
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));
|
|
648
|
-
break;
|
|
649
|
-
}
|
|
650
|
-
case "none": {
|
|
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));
|
|
652
|
-
break;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
return result;
|
|
657
|
-
}
|
|
658
|
-
buildArrayFilter(eb, fieldRef, fieldDef, payload) {
|
|
659
|
-
const clauses = [];
|
|
660
|
-
const fieldType = fieldDef.type;
|
|
661
|
-
for (const [key, _value] of Object.entries(payload)) {
|
|
662
|
-
if (_value === void 0) {
|
|
663
|
-
continue;
|
|
664
|
-
}
|
|
665
|
-
const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
|
|
666
|
-
switch (key) {
|
|
667
|
-
case "equals": {
|
|
668
|
-
clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
|
|
669
|
-
break;
|
|
670
|
-
}
|
|
671
|
-
case "has": {
|
|
672
|
-
clauses.push(eb(fieldRef, "@>", eb.val([
|
|
673
|
-
value
|
|
674
|
-
])));
|
|
675
|
-
break;
|
|
676
|
-
}
|
|
677
|
-
case "hasEvery": {
|
|
678
|
-
clauses.push(eb(fieldRef, "@>", eb.val(value)));
|
|
679
|
-
break;
|
|
680
|
-
}
|
|
681
|
-
case "hasSome": {
|
|
682
|
-
clauses.push(eb(fieldRef, "&&", eb.val(value)));
|
|
683
|
-
break;
|
|
684
|
-
}
|
|
685
|
-
case "isEmpty": {
|
|
686
|
-
clauses.push(eb(fieldRef, value === true ? "=" : "!=", eb.val([])));
|
|
687
|
-
break;
|
|
688
|
-
}
|
|
689
|
-
default: {
|
|
690
|
-
throw new InternalError(`Invalid array filter key: ${key}`);
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
return this.and(eb, ...clauses);
|
|
695
|
-
}
|
|
696
|
-
buildPrimitiveFilter(eb, fieldRef, fieldDef, payload) {
|
|
697
|
-
if (payload === null) {
|
|
698
|
-
return eb(fieldRef, "is", null);
|
|
699
|
-
}
|
|
700
|
-
if (isEnum(this.schema, fieldDef.type)) {
|
|
701
|
-
return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
|
|
702
|
-
}
|
|
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", () => {
|
|
704
|
-
throw new InternalError("JSON filters are not supported yet");
|
|
705
|
-
}).with("Unsupported", () => {
|
|
706
|
-
throw new QueryError(`Unsupported field cannot be used in filters`);
|
|
707
|
-
}).exhaustive();
|
|
708
|
-
}
|
|
709
|
-
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
710
|
-
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
711
|
-
}
|
|
712
|
-
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
713
|
-
if (payload === null || !(0, import_common_helpers.isPlainObject)(payload)) {
|
|
714
|
-
return {
|
|
715
|
-
conditions: [
|
|
716
|
-
this.buildLiteralFilter(eb, lhs, type, payload)
|
|
717
|
-
],
|
|
718
|
-
consumedKeys: []
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
const conditions = [];
|
|
722
|
-
const consumedKeys = [];
|
|
723
|
-
for (const [op, value] of Object.entries(payload)) {
|
|
724
|
-
if (onlyForKeys && !onlyForKeys.includes(op)) {
|
|
725
|
-
continue;
|
|
726
|
-
}
|
|
727
|
-
if (excludeKeys.includes(op)) {
|
|
728
|
-
continue;
|
|
729
|
-
}
|
|
730
|
-
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
731
|
-
const condition = (0, import_ts_pattern2.match)(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
732
|
-
(0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
733
|
-
if (rhs.length === 0) {
|
|
734
|
-
return this.false(eb);
|
|
735
|
-
} else {
|
|
736
|
-
return eb(lhs, "in", rhs);
|
|
737
|
-
}
|
|
738
|
-
}).with("notIn", () => {
|
|
739
|
-
(0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
740
|
-
if (rhs.length === 0) {
|
|
741
|
-
return this.true(eb);
|
|
742
|
-
} else {
|
|
743
|
-
return eb.not(eb(lhs, "in", rhs));
|
|
744
|
-
}
|
|
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(() => {
|
|
750
|
-
if (throwIfInvalid) {
|
|
751
|
-
throw new QueryError(`Invalid filter key: ${op}`);
|
|
752
|
-
} else {
|
|
753
|
-
return void 0;
|
|
754
|
-
}
|
|
755
|
-
});
|
|
756
|
-
if (condition) {
|
|
757
|
-
conditions.push(condition);
|
|
758
|
-
consumedKeys.push(op);
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
return {
|
|
762
|
-
conditions,
|
|
763
|
-
consumedKeys
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
buildStringFilter(eb, fieldRef, payload) {
|
|
767
|
-
let mode;
|
|
768
|
-
if (payload && typeof payload === "object" && "mode" in payload) {
|
|
769
|
-
mode = payload.mode;
|
|
770
|
-
}
|
|
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));
|
|
774
|
-
if (payload && typeof payload === "object") {
|
|
775
|
-
for (const [key, value] of Object.entries(payload)) {
|
|
776
|
-
if (key === "mode" || consumedKeys.includes(key)) {
|
|
777
|
-
continue;
|
|
778
|
-
}
|
|
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}`);
|
|
781
|
-
});
|
|
782
|
-
if (condition) {
|
|
783
|
-
conditions.push(condition);
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
return this.and(eb, ...conditions);
|
|
788
|
-
}
|
|
789
|
-
prepStringCasing(eb, value, mode) {
|
|
790
|
-
if (!mode || mode === "default") {
|
|
791
|
-
return value === null ? value : import_kysely.sql.val(value);
|
|
792
|
-
}
|
|
793
|
-
if (typeof value === "string") {
|
|
794
|
-
return eb.fn("lower", [
|
|
795
|
-
import_kysely.sql.val(value)
|
|
796
|
-
]);
|
|
797
|
-
} else if (Array.isArray(value)) {
|
|
798
|
-
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
799
|
-
} else {
|
|
800
|
-
return value === null ? null : import_kysely.sql.val(value);
|
|
801
|
-
}
|
|
802
|
-
}
|
|
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));
|
|
805
|
-
return this.and(eb, ...conditions);
|
|
806
|
-
}
|
|
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, [
|
|
809
|
-
"equals",
|
|
810
|
-
"not"
|
|
811
|
-
]);
|
|
812
|
-
return this.and(eb, ...conditions);
|
|
813
|
-
}
|
|
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);
|
|
816
|
-
return this.and(eb, ...conditions);
|
|
817
|
-
}
|
|
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, [
|
|
820
|
-
"equals",
|
|
821
|
-
"in",
|
|
822
|
-
"notIn",
|
|
823
|
-
"not"
|
|
824
|
-
]);
|
|
825
|
-
return this.and(eb, ...conditions.conditions);
|
|
826
|
-
}
|
|
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, [
|
|
829
|
-
"equals",
|
|
830
|
-
"in",
|
|
831
|
-
"notIn",
|
|
832
|
-
"not"
|
|
833
|
-
]);
|
|
834
|
-
return this.and(eb, ...conditions.conditions);
|
|
835
|
-
}
|
|
836
|
-
buildOrderBy(query, model, modelAlias, orderBy, useDefaultIfEmpty, negated) {
|
|
837
|
-
if (!orderBy) {
|
|
838
|
-
if (useDefaultIfEmpty) {
|
|
839
|
-
orderBy = makeDefaultOrderBy(this.schema, model);
|
|
840
|
-
} else {
|
|
841
|
-
return query;
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
let result = query;
|
|
845
|
-
enumerate(orderBy).forEach((orderBy2) => {
|
|
846
|
-
for (const [field, value] of Object.entries(orderBy2)) {
|
|
847
|
-
if (!value) {
|
|
848
|
-
continue;
|
|
849
|
-
}
|
|
850
|
-
if ([
|
|
851
|
-
"_count",
|
|
852
|
-
"_avg",
|
|
853
|
-
"_sum",
|
|
854
|
-
"_min",
|
|
855
|
-
"_max"
|
|
856
|
-
].includes(field)) {
|
|
857
|
-
(0, import_common_helpers.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
858
|
-
for (const [k, v] of Object.entries(value)) {
|
|
859
|
-
(0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
860
|
-
result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
861
|
-
}
|
|
862
|
-
continue;
|
|
863
|
-
}
|
|
864
|
-
switch (field) {
|
|
865
|
-
case "_count": {
|
|
866
|
-
(0, import_common_helpers.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
|
|
867
|
-
for (const [k, v] of Object.entries(value)) {
|
|
868
|
-
(0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
869
|
-
result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
870
|
-
}
|
|
871
|
-
continue;
|
|
872
|
-
}
|
|
873
|
-
default:
|
|
874
|
-
break;
|
|
875
|
-
}
|
|
876
|
-
const fieldDef = requireField(this.schema, model, field);
|
|
877
|
-
if (!fieldDef.relation) {
|
|
878
|
-
const fieldRef = this.fieldRef(model, field, (0, import_kysely.expressionBuilder)(), modelAlias);
|
|
879
|
-
if (value === "asc" || value === "desc") {
|
|
880
|
-
result = result.orderBy(fieldRef, this.negateSort(value, negated));
|
|
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")) {
|
|
882
|
-
result = result.orderBy(fieldRef, import_kysely.sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
|
|
883
|
-
}
|
|
884
|
-
} else {
|
|
885
|
-
const relationModel = fieldDef.type;
|
|
886
|
-
if (fieldDef.array) {
|
|
887
|
-
if (typeof value !== "object") {
|
|
888
|
-
throw new QueryError(`invalid orderBy value for field "${field}"`);
|
|
889
|
-
}
|
|
890
|
-
if ("_count" in value) {
|
|
891
|
-
(0, import_common_helpers.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
892
|
-
const sort = this.negateSort(value._count, negated);
|
|
893
|
-
result = result.orderBy((eb) => {
|
|
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);
|
|
897
|
-
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right)))));
|
|
898
|
-
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
899
|
-
return subQuery;
|
|
900
|
-
}, sort);
|
|
901
|
-
}
|
|
902
|
-
} else {
|
|
903
|
-
result = result.leftJoin(relationModel, (join) => {
|
|
904
|
-
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
|
|
905
|
-
return join.on((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right)))));
|
|
906
|
-
});
|
|
907
|
-
result = this.buildOrderBy(result, fieldDef.type, relationModel, value, false, negated);
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
});
|
|
912
|
-
return result;
|
|
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
|
|
1000
|
-
negateSort(sort, negated) {
|
|
1001
|
-
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
1002
|
-
}
|
|
1003
|
-
true(eb) {
|
|
1004
|
-
return eb.lit(this.transformPrimitive(true, "Boolean", false));
|
|
1005
|
-
}
|
|
1006
|
-
false(eb) {
|
|
1007
|
-
return eb.lit(this.transformPrimitive(false, "Boolean", false));
|
|
1008
|
-
}
|
|
1009
|
-
isTrue(expression) {
|
|
1010
|
-
const node = expression.toOperationNode();
|
|
1011
|
-
if (node.kind !== "ValueNode") {
|
|
1012
|
-
return false;
|
|
1013
|
-
}
|
|
1014
|
-
return node.value === true || node.value === 1;
|
|
1015
|
-
}
|
|
1016
|
-
isFalse(expression) {
|
|
1017
|
-
const node = expression.toOperationNode();
|
|
1018
|
-
if (node.kind !== "ValueNode") {
|
|
1019
|
-
return false;
|
|
1020
|
-
}
|
|
1021
|
-
return node.value === false || node.value === 0;
|
|
1022
|
-
}
|
|
1023
|
-
and(eb, ...args) {
|
|
1024
|
-
const nonTrueArgs = args.filter((arg) => !this.isTrue(arg));
|
|
1025
|
-
if (nonTrueArgs.length === 0) {
|
|
1026
|
-
return this.true(eb);
|
|
1027
|
-
} else if (nonTrueArgs.length === 1) {
|
|
1028
|
-
return nonTrueArgs[0];
|
|
1029
|
-
} else {
|
|
1030
|
-
return eb.and(nonTrueArgs);
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
or(eb, ...args) {
|
|
1034
|
-
const nonFalseArgs = args.filter((arg) => !this.isFalse(arg));
|
|
1035
|
-
if (nonFalseArgs.length === 0) {
|
|
1036
|
-
return this.false(eb);
|
|
1037
|
-
} else if (nonFalseArgs.length === 1) {
|
|
1038
|
-
return nonFalseArgs[0];
|
|
1039
|
-
} else {
|
|
1040
|
-
return eb.or(nonFalseArgs);
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
not(eb, ...args) {
|
|
1044
|
-
return eb.not(this.and(eb, ...args));
|
|
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
|
-
}
|
|
1061
|
-
};
|
|
1062
|
-
|
|
1063
|
-
// src/client/crud/dialects/postgresql.ts
|
|
1064
|
-
var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
1065
|
-
static {
|
|
1066
|
-
__name(this, "PostgresCrudDialect");
|
|
1067
|
-
}
|
|
1068
|
-
get provider() {
|
|
1069
|
-
return "postgresql";
|
|
1070
|
-
}
|
|
1071
|
-
transformPrimitive(value, type, forArrayField) {
|
|
1072
|
-
if (value === void 0) {
|
|
1073
|
-
return value;
|
|
1074
|
-
}
|
|
1075
|
-
if (Array.isArray(value)) {
|
|
1076
|
-
if (type === "Json" && !forArrayField) {
|
|
1077
|
-
return JSON.stringify(value);
|
|
1078
|
-
} else {
|
|
1079
|
-
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
1080
|
-
}
|
|
1081
|
-
} else {
|
|
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);
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
1086
|
-
const relationResultName = `${parentAlias}$${relationField}`;
|
|
1087
|
-
const joinedQuery = this.buildRelationJSON(model, query, relationField, parentAlias, payload, relationResultName);
|
|
1088
|
-
return joinedQuery.select(`${relationResultName}.$data as ${relationField}`);
|
|
1089
|
-
}
|
|
1090
|
-
buildRelationJSON(model, qb, relationField, parentAlias, payload, resultName) {
|
|
1091
|
-
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
1092
|
-
const relationModel = relationFieldDef.type;
|
|
1093
|
-
return qb.leftJoinLateral((eb) => {
|
|
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);
|
|
1110
|
-
}, (join) => join.onTrue());
|
|
1111
|
-
}
|
|
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) {
|
|
1127
|
-
qb = qb.select((eb) => {
|
|
1128
|
-
const objArgs = this.buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName);
|
|
1129
|
-
if (relationFieldDef.array) {
|
|
1130
|
-
return eb.fn.coalesce(import_kysely2.sql`jsonb_agg(jsonb_build_object(${import_kysely2.sql.join(objArgs)}))`, import_kysely2.sql`'[]'::jsonb`).as("$data");
|
|
1131
|
-
} else {
|
|
1132
|
-
return import_kysely2.sql`jsonb_build_object(${import_kysely2.sql.join(objArgs)})`.as("$data");
|
|
1133
|
-
}
|
|
1134
|
-
});
|
|
1135
|
-
return qb;
|
|
1136
|
-
}
|
|
1137
|
-
buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName) {
|
|
1138
|
-
const relationModelDef = requireModel(this.schema, relationModel);
|
|
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
|
-
}
|
|
1147
|
-
if (payload === true || !payload.select) {
|
|
1148
|
-
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
1149
|
-
import_kysely2.sql.lit(field),
|
|
1150
|
-
this.fieldRef(relationModel, field, eb, relationModelAlias, false)
|
|
1151
|
-
]).flatMap((v) => v));
|
|
1152
|
-
} else if (payload.select) {
|
|
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
|
-
}
|
|
1168
|
-
}).flatMap((v) => v));
|
|
1169
|
-
}
|
|
1170
|
-
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
1171
|
-
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
1172
|
-
import_kysely2.sql.lit(field),
|
|
1173
|
-
// reference the synthesized JSON field
|
|
1174
|
-
eb.ref(`${parentResultName}$${field}.$data`)
|
|
1175
|
-
]).flatMap((v) => v));
|
|
1176
|
-
}
|
|
1177
|
-
return objArgs;
|
|
1178
|
-
}
|
|
1179
|
-
buildRelationJoins(query, relationModel, relationModelAlias, payload, parentResultName) {
|
|
1180
|
-
let result = query;
|
|
1181
|
-
if (typeof payload === "object") {
|
|
1182
|
-
const selectInclude = payload.include ?? payload.select;
|
|
1183
|
-
if (selectInclude && typeof selectInclude === "object") {
|
|
1184
|
-
Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
|
|
1185
|
-
result = this.buildRelationJSON(relationModel, result, field, relationModelAlias, value, `${parentResultName}$${field}`);
|
|
1186
|
-
});
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
return result;
|
|
1190
|
-
}
|
|
1191
|
-
buildSkipTake(query, skip, take) {
|
|
1192
|
-
if (take !== void 0) {
|
|
1193
|
-
query = query.limit(take);
|
|
1194
|
-
}
|
|
1195
|
-
if (skip !== void 0) {
|
|
1196
|
-
query = query.offset(skip);
|
|
1197
|
-
}
|
|
1198
|
-
return query;
|
|
1199
|
-
}
|
|
1200
|
-
buildJsonObject(eb, value) {
|
|
1201
|
-
return eb.fn("jsonb_build_object", Object.entries(value).flatMap(([key, value2]) => [
|
|
1202
|
-
import_kysely2.sql.lit(key),
|
|
1203
|
-
value2
|
|
1204
|
-
]));
|
|
1205
|
-
}
|
|
1206
|
-
get supportsUpdateWithLimit() {
|
|
1207
|
-
return false;
|
|
1208
|
-
}
|
|
1209
|
-
get supportsDeleteWithLimit() {
|
|
1210
|
-
return false;
|
|
1211
|
-
}
|
|
1212
|
-
get supportsDistinctOn() {
|
|
1213
|
-
return true;
|
|
1214
|
-
}
|
|
1215
|
-
buildArrayLength(eb, array) {
|
|
1216
|
-
return eb.fn("array_length", [
|
|
1217
|
-
array
|
|
1218
|
-
]);
|
|
1219
|
-
}
|
|
1220
|
-
buildArrayLiteralSQL(values) {
|
|
1221
|
-
if (values.length === 0) {
|
|
1222
|
-
return "{}";
|
|
1223
|
-
} else {
|
|
1224
|
-
return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
get supportInsertWithDefault() {
|
|
1228
|
-
return true;
|
|
1229
|
-
}
|
|
1230
|
-
};
|
|
1231
|
-
|
|
1232
|
-
// src/client/crud/dialects/sqlite.ts
|
|
1233
|
-
var import_common_helpers3 = require("@zenstackhq/common-helpers");
|
|
1234
|
-
var import_kysely3 = require("kysely");
|
|
1235
|
-
var import_ts_pattern4 = require("ts-pattern");
|
|
1236
|
-
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
1237
|
-
static {
|
|
1238
|
-
__name(this, "SqliteCrudDialect");
|
|
1239
|
-
}
|
|
1240
|
-
get provider() {
|
|
1241
|
-
return "sqlite";
|
|
1242
|
-
}
|
|
1243
|
-
transformPrimitive(value, type, _forArrayField) {
|
|
1244
|
-
if (value === void 0) {
|
|
1245
|
-
return value;
|
|
1246
|
-
}
|
|
1247
|
-
if (Array.isArray(value)) {
|
|
1248
|
-
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
1249
|
-
} else {
|
|
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
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
1258
|
-
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
1259
|
-
}
|
|
1260
|
-
buildRelationJSON(model, eb, relationField, parentAlias, payload) {
|
|
1261
|
-
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
1262
|
-
const relationModel = relationFieldDef.type;
|
|
1263
|
-
const relationModelDef = requireModel(this.schema, relationModel);
|
|
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
|
-
}
|
|
1277
|
-
tbl = tbl.select(() => {
|
|
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
|
-
}
|
|
1286
|
-
if (payload === true || !payload.select) {
|
|
1287
|
-
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
1288
|
-
import_kysely3.sql.lit(field),
|
|
1289
|
-
this.fieldRef(relationModel, field, eb, subQueryName, false)
|
|
1290
|
-
]).flatMap((v) => v));
|
|
1291
|
-
} else if (payload.select) {
|
|
1292
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1293
|
-
if (field === "_count") {
|
|
1294
|
-
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1295
|
-
return [
|
|
1296
|
-
import_kysely3.sql.lit(field),
|
|
1297
|
-
subJson
|
|
1298
|
-
];
|
|
1299
|
-
} else {
|
|
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
|
-
}
|
|
1313
|
-
}
|
|
1314
|
-
}).flatMap((v) => v));
|
|
1315
|
-
}
|
|
1316
|
-
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
1317
|
-
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
1318
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1319
|
-
return [
|
|
1320
|
-
import_kysely3.sql.lit(field),
|
|
1321
|
-
subJson
|
|
1322
|
-
];
|
|
1323
|
-
}).flatMap((v) => v));
|
|
1324
|
-
}
|
|
1325
|
-
if (relationFieldDef.array) {
|
|
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");
|
|
1327
|
-
} else {
|
|
1328
|
-
return import_kysely3.sql`json_object(${import_kysely3.sql.join(objArgs)})`.as("$data");
|
|
1329
|
-
}
|
|
1330
|
-
});
|
|
1331
|
-
return tbl;
|
|
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
|
-
}
|
|
1355
|
-
buildSkipTake(query, skip, take) {
|
|
1356
|
-
if (take !== void 0) {
|
|
1357
|
-
query = query.limit(take);
|
|
1358
|
-
}
|
|
1359
|
-
if (skip !== void 0) {
|
|
1360
|
-
query = query.offset(skip);
|
|
1361
|
-
if (take === void 0) {
|
|
1362
|
-
query = query.limit(-1);
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
return query;
|
|
1366
|
-
}
|
|
1367
|
-
buildJsonObject(eb, value) {
|
|
1368
|
-
return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
|
|
1369
|
-
import_kysely3.sql.lit(key),
|
|
1370
|
-
value2
|
|
1371
|
-
]));
|
|
1372
|
-
}
|
|
1373
|
-
get supportsUpdateWithLimit() {
|
|
1374
|
-
return false;
|
|
1375
|
-
}
|
|
1376
|
-
get supportsDeleteWithLimit() {
|
|
1377
|
-
return false;
|
|
1378
|
-
}
|
|
1379
|
-
get supportsDistinctOn() {
|
|
1380
|
-
return false;
|
|
1381
|
-
}
|
|
1382
|
-
buildArrayLength(eb, array) {
|
|
1383
|
-
return eb.fn("json_array_length", [
|
|
1384
|
-
array
|
|
1385
|
-
]);
|
|
1386
|
-
}
|
|
1387
|
-
buildArrayLiteralSQL(_values) {
|
|
1388
|
-
throw new Error("SQLite does not support array literals");
|
|
1389
|
-
}
|
|
1390
|
-
get supportInsertWithDefault() {
|
|
1391
|
-
return false;
|
|
1392
|
-
}
|
|
1393
|
-
};
|
|
1394
|
-
|
|
1395
|
-
// src/client/crud/dialects/index.ts
|
|
1396
|
-
function getCrudDialect(schema, options) {
|
|
1397
|
-
return (0, import_ts_pattern5.match)(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
|
|
1398
|
-
}
|
|
1399
|
-
__name(getCrudDialect, "getCrudDialect");
|
|
1400
|
-
|
|
1401
|
-
// src/utils/default-operation-node-visitor.ts
|
|
1402
|
-
var import_kysely4 = require("kysely");
|
|
1403
|
-
var DefaultOperationNodeVisitor = class extends import_kysely4.OperationNodeVisitor {
|
|
1404
|
-
static {
|
|
1405
|
-
__name(this, "DefaultOperationNodeVisitor");
|
|
1406
|
-
}
|
|
1407
|
-
defaultVisit(node) {
|
|
1408
|
-
Object.values(node).forEach((value) => {
|
|
1409
|
-
if (!value) {
|
|
1410
|
-
return;
|
|
1411
|
-
}
|
|
1412
|
-
if (Array.isArray(value)) {
|
|
1413
|
-
value.forEach((el) => this.defaultVisit(el));
|
|
1414
|
-
}
|
|
1415
|
-
if (typeof value === "object" && "kind" in value && typeof value.kind === "string") {
|
|
1416
|
-
this.visitNode(value);
|
|
1417
|
-
}
|
|
1418
|
-
});
|
|
1419
|
-
}
|
|
1420
|
-
visitSelectQuery(node) {
|
|
1421
|
-
this.defaultVisit(node);
|
|
1422
|
-
}
|
|
1423
|
-
visitSelection(node) {
|
|
1424
|
-
this.defaultVisit(node);
|
|
1425
|
-
}
|
|
1426
|
-
visitColumn(node) {
|
|
1427
|
-
this.defaultVisit(node);
|
|
1428
|
-
}
|
|
1429
|
-
visitAlias(node) {
|
|
1430
|
-
this.defaultVisit(node);
|
|
1431
|
-
}
|
|
1432
|
-
visitTable(node) {
|
|
1433
|
-
this.defaultVisit(node);
|
|
1434
|
-
}
|
|
1435
|
-
visitFrom(node) {
|
|
1436
|
-
this.defaultVisit(node);
|
|
1437
|
-
}
|
|
1438
|
-
visitReference(node) {
|
|
1439
|
-
this.defaultVisit(node);
|
|
1440
|
-
}
|
|
1441
|
-
visitAnd(node) {
|
|
1442
|
-
this.defaultVisit(node);
|
|
1443
|
-
}
|
|
1444
|
-
visitOr(node) {
|
|
1445
|
-
this.defaultVisit(node);
|
|
1446
|
-
}
|
|
1447
|
-
visitValueList(node) {
|
|
1448
|
-
this.defaultVisit(node);
|
|
1449
|
-
}
|
|
1450
|
-
visitParens(node) {
|
|
1451
|
-
this.defaultVisit(node);
|
|
1452
|
-
}
|
|
1453
|
-
visitJoin(node) {
|
|
1454
|
-
this.defaultVisit(node);
|
|
1455
|
-
}
|
|
1456
|
-
visitRaw(node) {
|
|
1457
|
-
this.defaultVisit(node);
|
|
1458
|
-
}
|
|
1459
|
-
visitWhere(node) {
|
|
1460
|
-
this.defaultVisit(node);
|
|
1461
|
-
}
|
|
1462
|
-
visitInsertQuery(node) {
|
|
1463
|
-
this.defaultVisit(node);
|
|
1464
|
-
}
|
|
1465
|
-
visitDeleteQuery(node) {
|
|
1466
|
-
this.defaultVisit(node);
|
|
1467
|
-
}
|
|
1468
|
-
visitReturning(node) {
|
|
1469
|
-
this.defaultVisit(node);
|
|
1470
|
-
}
|
|
1471
|
-
visitCreateTable(node) {
|
|
1472
|
-
this.defaultVisit(node);
|
|
1473
|
-
}
|
|
1474
|
-
visitAddColumn(node) {
|
|
1475
|
-
this.defaultVisit(node);
|
|
1476
|
-
}
|
|
1477
|
-
visitColumnDefinition(node) {
|
|
1478
|
-
this.defaultVisit(node);
|
|
1479
|
-
}
|
|
1480
|
-
visitDropTable(node) {
|
|
1481
|
-
this.defaultVisit(node);
|
|
1482
|
-
}
|
|
1483
|
-
visitOrderBy(node) {
|
|
1484
|
-
this.defaultVisit(node);
|
|
1485
|
-
}
|
|
1486
|
-
visitOrderByItem(node) {
|
|
1487
|
-
this.defaultVisit(node);
|
|
1488
|
-
}
|
|
1489
|
-
visitGroupBy(node) {
|
|
1490
|
-
this.defaultVisit(node);
|
|
1491
|
-
}
|
|
1492
|
-
visitGroupByItem(node) {
|
|
1493
|
-
this.defaultVisit(node);
|
|
1494
|
-
}
|
|
1495
|
-
visitUpdateQuery(node) {
|
|
1496
|
-
this.defaultVisit(node);
|
|
1497
|
-
}
|
|
1498
|
-
visitColumnUpdate(node) {
|
|
1499
|
-
this.defaultVisit(node);
|
|
1500
|
-
}
|
|
1501
|
-
visitLimit(node) {
|
|
1502
|
-
this.defaultVisit(node);
|
|
1503
|
-
}
|
|
1504
|
-
visitOffset(node) {
|
|
1505
|
-
this.defaultVisit(node);
|
|
1506
|
-
}
|
|
1507
|
-
visitOnConflict(node) {
|
|
1508
|
-
this.defaultVisit(node);
|
|
1509
|
-
}
|
|
1510
|
-
visitOnDuplicateKey(node) {
|
|
1511
|
-
this.defaultVisit(node);
|
|
1512
|
-
}
|
|
1513
|
-
visitCheckConstraint(node) {
|
|
1514
|
-
this.defaultVisit(node);
|
|
1515
|
-
}
|
|
1516
|
-
visitDataType(node) {
|
|
1517
|
-
this.defaultVisit(node);
|
|
1518
|
-
}
|
|
1519
|
-
visitSelectAll(node) {
|
|
1520
|
-
this.defaultVisit(node);
|
|
1521
|
-
}
|
|
1522
|
-
visitIdentifier(node) {
|
|
1523
|
-
this.defaultVisit(node);
|
|
1524
|
-
}
|
|
1525
|
-
visitSchemableIdentifier(node) {
|
|
1526
|
-
this.defaultVisit(node);
|
|
1527
|
-
}
|
|
1528
|
-
visitValue(node) {
|
|
1529
|
-
this.defaultVisit(node);
|
|
1530
|
-
}
|
|
1531
|
-
visitPrimitiveValueList(node) {
|
|
1532
|
-
this.defaultVisit(node);
|
|
1533
|
-
}
|
|
1534
|
-
visitOperator(node) {
|
|
1535
|
-
this.defaultVisit(node);
|
|
1536
|
-
}
|
|
1537
|
-
visitCreateIndex(node) {
|
|
1538
|
-
this.defaultVisit(node);
|
|
1539
|
-
}
|
|
1540
|
-
visitDropIndex(node) {
|
|
1541
|
-
this.defaultVisit(node);
|
|
1542
|
-
}
|
|
1543
|
-
visitList(node) {
|
|
1544
|
-
this.defaultVisit(node);
|
|
1545
|
-
}
|
|
1546
|
-
visitPrimaryKeyConstraint(node) {
|
|
1547
|
-
this.defaultVisit(node);
|
|
1548
|
-
}
|
|
1549
|
-
visitUniqueConstraint(node) {
|
|
1550
|
-
this.defaultVisit(node);
|
|
1551
|
-
}
|
|
1552
|
-
visitReferences(node) {
|
|
1553
|
-
this.defaultVisit(node);
|
|
1554
|
-
}
|
|
1555
|
-
visitWith(node) {
|
|
1556
|
-
this.defaultVisit(node);
|
|
1557
|
-
}
|
|
1558
|
-
visitCommonTableExpression(node) {
|
|
1559
|
-
this.defaultVisit(node);
|
|
1560
|
-
}
|
|
1561
|
-
visitCommonTableExpressionName(node) {
|
|
1562
|
-
this.defaultVisit(node);
|
|
1563
|
-
}
|
|
1564
|
-
visitHaving(node) {
|
|
1565
|
-
this.defaultVisit(node);
|
|
1566
|
-
}
|
|
1567
|
-
visitCreateSchema(node) {
|
|
1568
|
-
this.defaultVisit(node);
|
|
1569
|
-
}
|
|
1570
|
-
visitDropSchema(node) {
|
|
1571
|
-
this.defaultVisit(node);
|
|
1572
|
-
}
|
|
1573
|
-
visitAlterTable(node) {
|
|
1574
|
-
this.defaultVisit(node);
|
|
1575
|
-
}
|
|
1576
|
-
visitDropColumn(node) {
|
|
1577
|
-
this.defaultVisit(node);
|
|
1578
|
-
}
|
|
1579
|
-
visitRenameColumn(node) {
|
|
1580
|
-
this.defaultVisit(node);
|
|
1581
|
-
}
|
|
1582
|
-
visitAlterColumn(node) {
|
|
1583
|
-
this.defaultVisit(node);
|
|
1584
|
-
}
|
|
1585
|
-
visitModifyColumn(node) {
|
|
1586
|
-
this.defaultVisit(node);
|
|
1587
|
-
}
|
|
1588
|
-
visitAddConstraint(node) {
|
|
1589
|
-
this.defaultVisit(node);
|
|
1590
|
-
}
|
|
1591
|
-
visitDropConstraint(node) {
|
|
1592
|
-
this.defaultVisit(node);
|
|
1593
|
-
}
|
|
1594
|
-
visitForeignKeyConstraint(node) {
|
|
1595
|
-
this.defaultVisit(node);
|
|
1596
|
-
}
|
|
1597
|
-
visitCreateView(node) {
|
|
1598
|
-
this.defaultVisit(node);
|
|
1599
|
-
}
|
|
1600
|
-
visitDropView(node) {
|
|
1601
|
-
this.defaultVisit(node);
|
|
1602
|
-
}
|
|
1603
|
-
visitGenerated(node) {
|
|
1604
|
-
this.defaultVisit(node);
|
|
1605
|
-
}
|
|
1606
|
-
visitDefaultValue(node) {
|
|
1607
|
-
this.defaultVisit(node);
|
|
1608
|
-
}
|
|
1609
|
-
visitOn(node) {
|
|
1610
|
-
this.defaultVisit(node);
|
|
1611
|
-
}
|
|
1612
|
-
visitValues(node) {
|
|
1613
|
-
this.defaultVisit(node);
|
|
1614
|
-
}
|
|
1615
|
-
visitSelectModifier(node) {
|
|
1616
|
-
this.defaultVisit(node);
|
|
1617
|
-
}
|
|
1618
|
-
visitCreateType(node) {
|
|
1619
|
-
this.defaultVisit(node);
|
|
1620
|
-
}
|
|
1621
|
-
visitDropType(node) {
|
|
1622
|
-
this.defaultVisit(node);
|
|
1623
|
-
}
|
|
1624
|
-
visitExplain(node) {
|
|
1625
|
-
this.defaultVisit(node);
|
|
1626
|
-
}
|
|
1627
|
-
visitDefaultInsertValue(node) {
|
|
1628
|
-
this.defaultVisit(node);
|
|
1629
|
-
}
|
|
1630
|
-
visitAggregateFunction(node) {
|
|
1631
|
-
this.defaultVisit(node);
|
|
1632
|
-
}
|
|
1633
|
-
visitOver(node) {
|
|
1634
|
-
this.defaultVisit(node);
|
|
1635
|
-
}
|
|
1636
|
-
visitPartitionBy(node) {
|
|
1637
|
-
this.defaultVisit(node);
|
|
1638
|
-
}
|
|
1639
|
-
visitPartitionByItem(node) {
|
|
1640
|
-
this.defaultVisit(node);
|
|
1641
|
-
}
|
|
1642
|
-
visitSetOperation(node) {
|
|
1643
|
-
this.defaultVisit(node);
|
|
1644
|
-
}
|
|
1645
|
-
visitBinaryOperation(node) {
|
|
1646
|
-
this.defaultVisit(node);
|
|
1647
|
-
}
|
|
1648
|
-
visitUnaryOperation(node) {
|
|
1649
|
-
this.defaultVisit(node);
|
|
1650
|
-
}
|
|
1651
|
-
visitUsing(node) {
|
|
1652
|
-
this.defaultVisit(node);
|
|
1653
|
-
}
|
|
1654
|
-
visitFunction(node) {
|
|
1655
|
-
this.defaultVisit(node);
|
|
1656
|
-
}
|
|
1657
|
-
visitCase(node) {
|
|
1658
|
-
this.defaultVisit(node);
|
|
1659
|
-
}
|
|
1660
|
-
visitWhen(node) {
|
|
1661
|
-
this.defaultVisit(node);
|
|
1662
|
-
}
|
|
1663
|
-
visitJSONReference(node) {
|
|
1664
|
-
this.defaultVisit(node);
|
|
1665
|
-
}
|
|
1666
|
-
visitJSONPath(node) {
|
|
1667
|
-
this.defaultVisit(node);
|
|
1668
|
-
}
|
|
1669
|
-
visitJSONPathLeg(node) {
|
|
1670
|
-
this.defaultVisit(node);
|
|
1671
|
-
}
|
|
1672
|
-
visitJSONOperatorChain(node) {
|
|
1673
|
-
this.defaultVisit(node);
|
|
1674
|
-
}
|
|
1675
|
-
visitTuple(node) {
|
|
1676
|
-
this.defaultVisit(node);
|
|
1677
|
-
}
|
|
1678
|
-
visitMergeQuery(node) {
|
|
1679
|
-
this.defaultVisit(node);
|
|
1680
|
-
}
|
|
1681
|
-
visitMatched(node) {
|
|
1682
|
-
this.defaultVisit(node);
|
|
1683
|
-
}
|
|
1684
|
-
visitAddIndex(node) {
|
|
1685
|
-
this.defaultVisit(node);
|
|
1686
|
-
}
|
|
1687
|
-
visitCast(node) {
|
|
1688
|
-
this.defaultVisit(node);
|
|
1689
|
-
}
|
|
1690
|
-
visitFetch(node) {
|
|
1691
|
-
this.defaultVisit(node);
|
|
1692
|
-
}
|
|
1693
|
-
visitTop(node) {
|
|
1694
|
-
this.defaultVisit(node);
|
|
1695
|
-
}
|
|
1696
|
-
visitOutput(node) {
|
|
1697
|
-
this.defaultVisit(node);
|
|
1698
|
-
}
|
|
1699
|
-
};
|
|
1700
|
-
|
|
1701
|
-
// src/plugins/policy/column-collector.ts
|
|
1702
|
-
var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
1703
|
-
static {
|
|
1704
|
-
__name(this, "ColumnCollector");
|
|
1705
|
-
}
|
|
1706
|
-
columns = [];
|
|
1707
|
-
collect(node) {
|
|
1708
|
-
this.columns = [];
|
|
1709
|
-
this.visitNode(node);
|
|
1710
|
-
return this.columns;
|
|
1711
|
-
}
|
|
1712
|
-
visitColumn(node) {
|
|
1713
|
-
if (!this.columns.includes(node.column.name)) {
|
|
1714
|
-
this.columns.push(node.column.name);
|
|
1715
|
-
}
|
|
1716
|
-
}
|
|
1717
|
-
};
|
|
1718
|
-
|
|
1719
|
-
// src/plugins/policy/expression-transformer.ts
|
|
1720
|
-
var import_common_helpers5 = require("@zenstackhq/common-helpers");
|
|
1721
|
-
var import_kysely6 = require("kysely");
|
|
1722
|
-
var import_ts_pattern7 = require("ts-pattern");
|
|
1723
|
-
|
|
1724
|
-
// src/plugins/policy/expression-evaluator.ts
|
|
1725
|
-
var import_common_helpers4 = require("@zenstackhq/common-helpers");
|
|
1726
|
-
var import_ts_pattern6 = require("ts-pattern");
|
|
1727
|
-
var ExpressionEvaluator = class {
|
|
1728
|
-
static {
|
|
1729
|
-
__name(this, "ExpressionEvaluator");
|
|
1730
|
-
}
|
|
1731
|
-
evaluate(expression, context) {
|
|
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();
|
|
1733
|
-
return result ?? null;
|
|
1734
|
-
}
|
|
1735
|
-
evaluateCall(expr2, context) {
|
|
1736
|
-
if (expr2.function === "auth") {
|
|
1737
|
-
return context.auth;
|
|
1738
|
-
} else {
|
|
1739
|
-
throw new Error(`Unsupported call expression function: ${expr2.function}`);
|
|
1740
|
-
}
|
|
1741
|
-
}
|
|
1742
|
-
evaluateUnary(expr2, context) {
|
|
1743
|
-
return (0, import_ts_pattern6.match)(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
|
|
1744
|
-
}
|
|
1745
|
-
evaluateMember(expr2, context) {
|
|
1746
|
-
let val = this.evaluate(expr2.receiver, context);
|
|
1747
|
-
for (const member of expr2.members) {
|
|
1748
|
-
val = val?.[member];
|
|
1749
|
-
}
|
|
1750
|
-
return val;
|
|
1751
|
-
}
|
|
1752
|
-
evaluateLiteral(expr2) {
|
|
1753
|
-
return expr2.value;
|
|
1754
|
-
}
|
|
1755
|
-
evaluateField(expr2, context) {
|
|
1756
|
-
return context.thisValue?.[expr2.field];
|
|
1757
|
-
}
|
|
1758
|
-
evaluateArray(expr2, context) {
|
|
1759
|
-
return expr2.items.map((item) => this.evaluate(item, context));
|
|
1760
|
-
}
|
|
1761
|
-
evaluateBinary(expr2, context) {
|
|
1762
|
-
if (expr2.op === "?" || expr2.op === "!" || expr2.op === "^") {
|
|
1763
|
-
return this.evaluateCollectionPredicate(expr2, context);
|
|
1764
|
-
}
|
|
1765
|
-
const left = this.evaluate(expr2.left, context);
|
|
1766
|
-
const right = this.evaluate(expr2.right, context);
|
|
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", () => {
|
|
1768
|
-
const _right = right ?? [];
|
|
1769
|
-
(0, import_common_helpers4.invariant)(Array.isArray(_right), 'expected array for "in" operator');
|
|
1770
|
-
return _right.includes(left);
|
|
1771
|
-
}).exhaustive();
|
|
1772
|
-
}
|
|
1773
|
-
evaluateCollectionPredicate(expr2, context) {
|
|
1774
|
-
const op = expr2.op;
|
|
1775
|
-
(0, import_common_helpers4.invariant)(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
|
|
1776
|
-
const left = this.evaluate(expr2.left, context);
|
|
1777
|
-
if (!left) {
|
|
1778
|
-
return false;
|
|
1779
|
-
}
|
|
1780
|
-
(0, import_common_helpers4.invariant)(Array.isArray(left), "expected array");
|
|
1781
|
-
return (0, import_ts_pattern6.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1782
|
-
...context,
|
|
1783
|
-
thisValue: item
|
|
1784
|
-
}))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
|
|
1785
|
-
...context,
|
|
1786
|
-
thisValue: item
|
|
1787
|
-
}))).with("^", () => !left.some((item) => this.evaluate(expr2.right, {
|
|
1788
|
-
...context,
|
|
1789
|
-
thisValue: item
|
|
1790
|
-
}))).exhaustive();
|
|
1791
|
-
}
|
|
1792
|
-
};
|
|
1793
|
-
|
|
1794
|
-
// src/plugins/policy/utils.ts
|
|
1795
|
-
var import_kysely5 = require("kysely");
|
|
1796
|
-
function trueNode(dialect) {
|
|
1797
|
-
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1798
|
-
}
|
|
1799
|
-
__name(trueNode, "trueNode");
|
|
1800
|
-
function falseNode(dialect) {
|
|
1801
|
-
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1802
|
-
}
|
|
1803
|
-
__name(falseNode, "falseNode");
|
|
1804
|
-
function isTrueNode(node) {
|
|
1805
|
-
return import_kysely5.ValueNode.is(node) && (node.value === true || node.value === 1);
|
|
1806
|
-
}
|
|
1807
|
-
__name(isTrueNode, "isTrueNode");
|
|
1808
|
-
function isFalseNode(node) {
|
|
1809
|
-
return import_kysely5.ValueNode.is(node) && (node.value === false || node.value === 0);
|
|
1810
|
-
}
|
|
1811
|
-
__name(isFalseNode, "isFalseNode");
|
|
1812
|
-
function conjunction(dialect, nodes) {
|
|
1813
|
-
if (nodes.some(isFalseNode)) {
|
|
1814
|
-
return falseNode(dialect);
|
|
1815
|
-
}
|
|
1816
|
-
const items = nodes.filter((n) => !isTrueNode(n));
|
|
1817
|
-
if (items.length === 0) {
|
|
1818
|
-
return trueNode(dialect);
|
|
1819
|
-
}
|
|
1820
|
-
return items.reduce((acc, node) => import_kysely5.OrNode.is(node) ? import_kysely5.AndNode.create(acc, import_kysely5.ParensNode.create(node)) : import_kysely5.AndNode.create(acc, node));
|
|
1821
|
-
}
|
|
1822
|
-
__name(conjunction, "conjunction");
|
|
1823
|
-
function disjunction(dialect, nodes) {
|
|
1824
|
-
if (nodes.some(isTrueNode)) {
|
|
1825
|
-
return trueNode(dialect);
|
|
1826
|
-
}
|
|
1827
|
-
const items = nodes.filter((n) => !isFalseNode(n));
|
|
1828
|
-
if (items.length === 0) {
|
|
1829
|
-
return falseNode(dialect);
|
|
1830
|
-
}
|
|
1831
|
-
return items.reduce((acc, node) => import_kysely5.AndNode.is(node) ? import_kysely5.OrNode.create(acc, import_kysely5.ParensNode.create(node)) : import_kysely5.OrNode.create(acc, node));
|
|
1832
|
-
}
|
|
1833
|
-
__name(disjunction, "disjunction");
|
|
1834
|
-
function logicalNot(node) {
|
|
1835
|
-
return import_kysely5.UnaryOperationNode.create(import_kysely5.OperatorNode.create("not"), import_kysely5.AndNode.is(node) || import_kysely5.OrNode.is(node) ? import_kysely5.ParensNode.create(node) : node);
|
|
1836
|
-
}
|
|
1837
|
-
__name(logicalNot, "logicalNot");
|
|
1838
|
-
function buildIsFalse(node, dialect) {
|
|
1839
|
-
if (isFalseNode(node)) {
|
|
1840
|
-
return trueNode(dialect);
|
|
1841
|
-
} else if (isTrueNode(node)) {
|
|
1842
|
-
return falseNode(dialect);
|
|
1843
|
-
}
|
|
1844
|
-
return import_kysely5.BinaryOperationNode.create(
|
|
1845
|
-
// coalesce so null is treated as false
|
|
1846
|
-
import_kysely5.FunctionNode.create("coalesce", [
|
|
1847
|
-
node,
|
|
1848
|
-
falseNode(dialect)
|
|
1849
|
-
]),
|
|
1850
|
-
import_kysely5.OperatorNode.create("="),
|
|
1851
|
-
falseNode(dialect)
|
|
1852
|
-
);
|
|
1853
|
-
}
|
|
1854
|
-
__name(buildIsFalse, "buildIsFalse");
|
|
1855
|
-
function getTableName(node) {
|
|
1856
|
-
if (!node) {
|
|
1857
|
-
return node;
|
|
1858
|
-
}
|
|
1859
|
-
if (import_kysely5.TableNode.is(node)) {
|
|
1860
|
-
return node.table.identifier.name;
|
|
1861
|
-
} else if (import_kysely5.AliasNode.is(node)) {
|
|
1862
|
-
return getTableName(node.node);
|
|
1863
|
-
} else if (import_kysely5.ReferenceNode.is(node) && node.table) {
|
|
1864
|
-
return getTableName(node.table);
|
|
1865
|
-
}
|
|
1866
|
-
return void 0;
|
|
1867
|
-
}
|
|
1868
|
-
__name(getTableName, "getTableName");
|
|
1869
|
-
|
|
1870
|
-
// src/plugins/policy/expression-transformer.ts
|
|
1871
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
1872
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1873
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1874
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1875
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1876
|
-
}
|
|
1877
|
-
__name(_ts_decorate, "_ts_decorate");
|
|
1878
|
-
function _ts_metadata(k, v) {
|
|
1879
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1880
|
-
}
|
|
1881
|
-
__name(_ts_metadata, "_ts_metadata");
|
|
1882
|
-
var expressionHandlers = /* @__PURE__ */ new Map();
|
|
1883
|
-
function expr(kind) {
|
|
1884
|
-
return function(_target, _propertyKey, descriptor) {
|
|
1885
|
-
if (!expressionHandlers.get(kind)) {
|
|
1886
|
-
expressionHandlers.set(kind, descriptor);
|
|
1887
|
-
}
|
|
1888
|
-
return descriptor;
|
|
1889
|
-
};
|
|
1890
|
-
}
|
|
1891
|
-
__name(expr, "expr");
|
|
1892
|
-
var ExpressionTransformer = class {
|
|
1893
|
-
static {
|
|
1894
|
-
__name(this, "ExpressionTransformer");
|
|
1895
|
-
}
|
|
1896
|
-
schema;
|
|
1897
|
-
clientOptions;
|
|
1898
|
-
auth;
|
|
1899
|
-
dialect;
|
|
1900
|
-
constructor(schema, clientOptions, auth) {
|
|
1901
|
-
this.schema = schema;
|
|
1902
|
-
this.clientOptions = clientOptions;
|
|
1903
|
-
this.auth = auth;
|
|
1904
|
-
this.dialect = getCrudDialect(this.schema, this.clientOptions);
|
|
1905
|
-
}
|
|
1906
|
-
get authType() {
|
|
1907
|
-
if (!this.schema.authType) {
|
|
1908
|
-
throw new InternalError('Schema does not have an "authType" specified');
|
|
1909
|
-
}
|
|
1910
|
-
return this.schema.authType;
|
|
1911
|
-
}
|
|
1912
|
-
transform(expression, context) {
|
|
1913
|
-
const handler = expressionHandlers.get(expression.kind);
|
|
1914
|
-
if (!handler) {
|
|
1915
|
-
throw new Error(`Unsupported expression kind: ${expression.kind}`);
|
|
1916
|
-
}
|
|
1917
|
-
return handler.value.call(this, expression, context);
|
|
1918
|
-
}
|
|
1919
|
-
_literal(expr2) {
|
|
1920
|
-
return this.transformValue(expr2.value, typeof expr2.value === "string" ? "String" : typeof expr2.value === "boolean" ? "Boolean" : "Int");
|
|
1921
|
-
}
|
|
1922
|
-
_array(expr2, context) {
|
|
1923
|
-
return import_kysely6.ValueListNode.create(expr2.items.map((item) => this.transform(item, context)));
|
|
1924
|
-
}
|
|
1925
|
-
_field(expr2, context) {
|
|
1926
|
-
const fieldDef = requireField(this.schema, context.model, expr2.field);
|
|
1927
|
-
if (!fieldDef.relation) {
|
|
1928
|
-
if (context.thisEntity) {
|
|
1929
|
-
return context.thisEntity[expr2.field];
|
|
1930
|
-
} else {
|
|
1931
|
-
return this.createColumnRef(expr2.field, context);
|
|
1932
|
-
}
|
|
1933
|
-
} else {
|
|
1934
|
-
const { memberFilter, memberSelect, ...restContext } = context;
|
|
1935
|
-
const relation = this.transformRelationAccess(expr2.field, fieldDef.type, restContext);
|
|
1936
|
-
return {
|
|
1937
|
-
...relation,
|
|
1938
|
-
where: this.mergeWhere(relation.where, memberFilter),
|
|
1939
|
-
selections: memberSelect ? [
|
|
1940
|
-
memberSelect
|
|
1941
|
-
] : relation.selections
|
|
1942
|
-
};
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
mergeWhere(where, memberFilter) {
|
|
1946
|
-
if (!where) {
|
|
1947
|
-
return import_kysely6.WhereNode.create(memberFilter ?? trueNode(this.dialect));
|
|
1948
|
-
}
|
|
1949
|
-
if (!memberFilter) {
|
|
1950
|
-
return where;
|
|
1951
|
-
}
|
|
1952
|
-
return import_kysely6.WhereNode.create(conjunction(this.dialect, [
|
|
1953
|
-
where.where,
|
|
1954
|
-
memberFilter
|
|
1955
|
-
]));
|
|
1956
|
-
}
|
|
1957
|
-
_null() {
|
|
1958
|
-
return import_kysely6.ValueNode.createImmediate(null);
|
|
1959
|
-
}
|
|
1960
|
-
_binary(expr2, context) {
|
|
1961
|
-
if (expr2.op === "&&") {
|
|
1962
|
-
return conjunction(this.dialect, [
|
|
1963
|
-
this.transform(expr2.left, context),
|
|
1964
|
-
this.transform(expr2.right, context)
|
|
1965
|
-
]);
|
|
1966
|
-
} else if (expr2.op === "||") {
|
|
1967
|
-
return disjunction(this.dialect, [
|
|
1968
|
-
this.transform(expr2.left, context),
|
|
1969
|
-
this.transform(expr2.right, context)
|
|
1970
|
-
]);
|
|
1971
|
-
}
|
|
1972
|
-
if (this.isAuthCall(expr2.left) || this.isAuthCall(expr2.right)) {
|
|
1973
|
-
return this.transformAuthBinary(expr2);
|
|
1974
|
-
}
|
|
1975
|
-
const op = expr2.op;
|
|
1976
|
-
if (op === "?" || op === "!" || op === "^") {
|
|
1977
|
-
return this.transformCollectionPredicate(expr2, context);
|
|
1978
|
-
}
|
|
1979
|
-
const left = this.transform(expr2.left, context);
|
|
1980
|
-
const right = this.transform(expr2.right, context);
|
|
1981
|
-
if (op === "in") {
|
|
1982
|
-
if (this.isNullNode(left)) {
|
|
1983
|
-
return this.transformValue(false, "Boolean");
|
|
1984
|
-
} else {
|
|
1985
|
-
if (import_kysely6.ValueListNode.is(right)) {
|
|
1986
|
-
return import_kysely6.BinaryOperationNode.create(left, import_kysely6.OperatorNode.create("in"), right);
|
|
1987
|
-
} else {
|
|
1988
|
-
return import_kysely6.BinaryOperationNode.create(left, import_kysely6.OperatorNode.create("="), import_kysely6.FunctionNode.create("any", [
|
|
1989
|
-
right
|
|
1990
|
-
]));
|
|
1991
|
-
}
|
|
1992
|
-
}
|
|
1993
|
-
}
|
|
1994
|
-
if (this.isNullNode(right)) {
|
|
1995
|
-
return expr2.op === "==" ? import_kysely6.BinaryOperationNode.create(left, import_kysely6.OperatorNode.create("is"), right) : import_kysely6.BinaryOperationNode.create(left, import_kysely6.OperatorNode.create("is not"), right);
|
|
1996
|
-
} else if (this.isNullNode(left)) {
|
|
1997
|
-
return expr2.op === "==" ? import_kysely6.BinaryOperationNode.create(right, import_kysely6.OperatorNode.create("is"), import_kysely6.ValueNode.createImmediate(null)) : import_kysely6.BinaryOperationNode.create(right, import_kysely6.OperatorNode.create("is not"), import_kysely6.ValueNode.createImmediate(null));
|
|
1998
|
-
}
|
|
1999
|
-
return import_kysely6.BinaryOperationNode.create(left, this.transformOperator(op), right);
|
|
2000
|
-
}
|
|
2001
|
-
transformCollectionPredicate(expr2, context) {
|
|
2002
|
-
(0, import_common_helpers5.invariant)(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
|
|
2003
|
-
if (this.isAuthCall(expr2.left) || this.isAuthMember(expr2.left)) {
|
|
2004
|
-
const value = new ExpressionEvaluator().evaluate(expr2, {
|
|
2005
|
-
auth: this.auth
|
|
2006
|
-
});
|
|
2007
|
-
return this.transformValue(value, "Boolean");
|
|
2008
|
-
}
|
|
2009
|
-
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
|
|
2010
|
-
let newContextModel;
|
|
2011
|
-
if (ExpressionUtils.isField(expr2.left)) {
|
|
2012
|
-
const fieldDef = requireField(this.schema, context.model, expr2.left.field);
|
|
2013
|
-
newContextModel = fieldDef.type;
|
|
2014
|
-
} else {
|
|
2015
|
-
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left.receiver));
|
|
2016
|
-
const fieldDef = requireField(this.schema, context.model, expr2.left.receiver.field);
|
|
2017
|
-
newContextModel = fieldDef.type;
|
|
2018
|
-
for (const member of expr2.left.members) {
|
|
2019
|
-
const memberDef = requireField(this.schema, newContextModel, member);
|
|
2020
|
-
newContextModel = memberDef.type;
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
let predicateFilter = this.transform(expr2.right, {
|
|
2024
|
-
...context,
|
|
2025
|
-
model: newContextModel,
|
|
2026
|
-
alias: void 0,
|
|
2027
|
-
thisEntity: void 0
|
|
2028
|
-
});
|
|
2029
|
-
if (expr2.op === "!") {
|
|
2030
|
-
predicateFilter = logicalNot(predicateFilter);
|
|
2031
|
-
}
|
|
2032
|
-
const count = import_kysely6.FunctionNode.create("count", [
|
|
2033
|
-
import_kysely6.ValueNode.createImmediate(1)
|
|
2034
|
-
]);
|
|
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();
|
|
2036
|
-
return this.transform(expr2.left, {
|
|
2037
|
-
...context,
|
|
2038
|
-
memberSelect: import_kysely6.SelectionNode.create(import_kysely6.AliasNode.create(predicateResult, import_kysely6.IdentifierNode.create("$t"))),
|
|
2039
|
-
memberFilter: predicateFilter
|
|
2040
|
-
});
|
|
2041
|
-
}
|
|
2042
|
-
transformAuthBinary(expr2) {
|
|
2043
|
-
if (expr2.op !== "==" && expr2.op !== "!=") {
|
|
2044
|
-
throw new Error(`Unsupported operator for auth call: ${expr2.op}`);
|
|
2045
|
-
}
|
|
2046
|
-
let other;
|
|
2047
|
-
if (this.isAuthCall(expr2.left)) {
|
|
2048
|
-
other = expr2.right;
|
|
2049
|
-
} else {
|
|
2050
|
-
other = expr2.left;
|
|
2051
|
-
}
|
|
2052
|
-
if (ExpressionUtils.isNull(other)) {
|
|
2053
|
-
return this.transformValue(expr2.op === "==" ? !this.auth : !!this.auth, "Boolean");
|
|
2054
|
-
} else {
|
|
2055
|
-
throw new Error("Unsupported binary expression with `auth()`");
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
transformValue(value, type) {
|
|
2059
|
-
return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
2060
|
-
}
|
|
2061
|
-
_unary(expr2, context) {
|
|
2062
|
-
(0, import_common_helpers5.invariant)(expr2.op === "!", 'only "!" operator is supported');
|
|
2063
|
-
return import_kysely6.BinaryOperationNode.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
|
|
2064
|
-
}
|
|
2065
|
-
transformOperator(op) {
|
|
2066
|
-
const mappedOp = (0, import_ts_pattern7.match)(op).with("==", () => "=").otherwise(() => op);
|
|
2067
|
-
return import_kysely6.OperatorNode.create(mappedOp);
|
|
2068
|
-
}
|
|
2069
|
-
_call(expr2, context) {
|
|
2070
|
-
const result = this.transformCall(expr2, context);
|
|
2071
|
-
return result.toOperationNode();
|
|
2072
|
-
}
|
|
2073
|
-
transformCall(expr2, context) {
|
|
2074
|
-
const func = this.clientOptions.functions?.[expr2.function];
|
|
2075
|
-
if (!func) {
|
|
2076
|
-
throw new QueryError(`Function not implemented: ${expr2.function}`);
|
|
2077
|
-
}
|
|
2078
|
-
const eb = (0, import_kysely6.expressionBuilder)();
|
|
2079
|
-
return func(eb, (expr2.args ?? []).map((arg) => this.transformCallArg(eb, arg, context)), {
|
|
2080
|
-
dialect: this.dialect,
|
|
2081
|
-
model: context.model,
|
|
2082
|
-
operation: context.operation
|
|
2083
|
-
});
|
|
2084
|
-
}
|
|
2085
|
-
transformCallArg(eb, arg, context) {
|
|
2086
|
-
if (ExpressionUtils.isLiteral(arg)) {
|
|
2087
|
-
return eb.val(arg.value);
|
|
2088
|
-
}
|
|
2089
|
-
if (ExpressionUtils.isField(arg)) {
|
|
2090
|
-
return context.thisEntityRaw ? eb.val(context.thisEntityRaw[arg.field]) : eb.ref(arg.field);
|
|
2091
|
-
}
|
|
2092
|
-
if (ExpressionUtils.isCall(arg)) {
|
|
2093
|
-
return this.transformCall(arg, context);
|
|
2094
|
-
}
|
|
2095
|
-
if (this.isAuthMember(arg)) {
|
|
2096
|
-
const valNode = this.valueMemberAccess(context.auth, arg, this.authType);
|
|
2097
|
-
return valNode ? eb.val(valNode.value) : eb.val(null);
|
|
2098
|
-
}
|
|
2099
|
-
throw new InternalError(`Unsupported argument expression: ${arg.kind}`);
|
|
2100
|
-
}
|
|
2101
|
-
_member(expr2, context) {
|
|
2102
|
-
if (this.isAuthCall(expr2.receiver)) {
|
|
2103
|
-
return this.valueMemberAccess(this.auth, expr2, this.authType);
|
|
2104
|
-
}
|
|
2105
|
-
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.receiver), "expect receiver to be field expression");
|
|
2106
|
-
const { memberFilter, memberSelect, ...restContext } = context;
|
|
2107
|
-
const receiver = this.transform(expr2.receiver, restContext);
|
|
2108
|
-
(0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(receiver), "expected receiver to be select query");
|
|
2109
|
-
const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
|
|
2110
|
-
const memberFields = [];
|
|
2111
|
-
let currType = receiverField.type;
|
|
2112
|
-
for (const member of expr2.members) {
|
|
2113
|
-
const fieldDef = requireField(this.schema, currType, member);
|
|
2114
|
-
memberFields.push({
|
|
2115
|
-
fieldDef,
|
|
2116
|
-
fromModel: currType
|
|
2117
|
-
});
|
|
2118
|
-
currType = fieldDef.type;
|
|
2119
|
-
}
|
|
2120
|
-
let currNode = void 0;
|
|
2121
|
-
for (let i = expr2.members.length - 1; i >= 0; i--) {
|
|
2122
|
-
const member = expr2.members[i];
|
|
2123
|
-
const { fieldDef, fromModel } = memberFields[i];
|
|
2124
|
-
if (fieldDef.relation) {
|
|
2125
|
-
const relation = this.transformRelationAccess(member, fieldDef.type, {
|
|
2126
|
-
...restContext,
|
|
2127
|
-
model: fromModel,
|
|
2128
|
-
alias: void 0,
|
|
2129
|
-
thisEntity: void 0
|
|
2130
|
-
});
|
|
2131
|
-
if (currNode) {
|
|
2132
|
-
(0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(currNode), "expected select query node");
|
|
2133
|
-
currNode = {
|
|
2134
|
-
...relation,
|
|
2135
|
-
selections: [
|
|
2136
|
-
import_kysely6.SelectionNode.create(import_kysely6.AliasNode.create(currNode, import_kysely6.IdentifierNode.create(expr2.members[i + 1])))
|
|
2137
|
-
]
|
|
2138
|
-
};
|
|
2139
|
-
} else {
|
|
2140
|
-
currNode = {
|
|
2141
|
-
...relation,
|
|
2142
|
-
where: this.mergeWhere(relation.where, memberFilter),
|
|
2143
|
-
selections: memberSelect ? [
|
|
2144
|
-
memberSelect
|
|
2145
|
-
] : relation.selections
|
|
2146
|
-
};
|
|
2147
|
-
}
|
|
2148
|
-
} else {
|
|
2149
|
-
(0, import_common_helpers5.invariant)(i === expr2.members.length - 1, "plain field access must be the last segment");
|
|
2150
|
-
(0, import_common_helpers5.invariant)(!currNode, "plain field access must be the last segment");
|
|
2151
|
-
currNode = import_kysely6.ColumnNode.create(member);
|
|
2152
|
-
}
|
|
2153
|
-
}
|
|
2154
|
-
return {
|
|
2155
|
-
...receiver,
|
|
2156
|
-
selections: [
|
|
2157
|
-
import_kysely6.SelectionNode.create(import_kysely6.AliasNode.create(currNode, import_kysely6.IdentifierNode.create("$t")))
|
|
2158
|
-
]
|
|
2159
|
-
};
|
|
2160
|
-
}
|
|
2161
|
-
valueMemberAccess(receiver, expr2, receiverType) {
|
|
2162
|
-
if (!receiver) {
|
|
2163
|
-
return import_kysely6.ValueNode.createImmediate(null);
|
|
2164
|
-
}
|
|
2165
|
-
if (expr2.members.length !== 1) {
|
|
2166
|
-
throw new Error(`Only single member access is supported`);
|
|
2167
|
-
}
|
|
2168
|
-
const field = expr2.members[0];
|
|
2169
|
-
const fieldDef = requireField(this.schema, receiverType, field);
|
|
2170
|
-
const fieldValue = receiver[field] ?? null;
|
|
2171
|
-
return this.transformValue(fieldValue, fieldDef.type);
|
|
2172
|
-
}
|
|
2173
|
-
transformRelationAccess(field, relationModel, context) {
|
|
2174
|
-
const fromModel = context.model;
|
|
2175
|
-
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, fromModel, field);
|
|
2176
|
-
if (context.thisEntity) {
|
|
2177
|
-
let condition;
|
|
2178
|
-
if (ownedByModel) {
|
|
2179
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(relationModel)), import_kysely6.OperatorNode.create("="), context.thisEntity[fk])));
|
|
2180
|
-
} else {
|
|
2181
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(relationModel)), import_kysely6.OperatorNode.create("="), context.thisEntity[pk])));
|
|
2182
|
-
}
|
|
2183
|
-
return {
|
|
2184
|
-
kind: "SelectQueryNode",
|
|
2185
|
-
from: import_kysely6.FromNode.create([
|
|
2186
|
-
import_kysely6.TableNode.create(relationModel)
|
|
2187
|
-
]),
|
|
2188
|
-
where: import_kysely6.WhereNode.create(condition)
|
|
2189
|
-
};
|
|
2190
|
-
} else {
|
|
2191
|
-
let condition;
|
|
2192
|
-
if (ownedByModel) {
|
|
2193
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(context.alias ?? fromModel)), import_kysely6.OperatorNode.create("="), import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(relationModel)))));
|
|
2194
|
-
} else {
|
|
2195
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(context.alias ?? fromModel)), import_kysely6.OperatorNode.create("="), import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(relationModel)))));
|
|
2196
|
-
}
|
|
2197
|
-
return {
|
|
2198
|
-
kind: "SelectQueryNode",
|
|
2199
|
-
from: import_kysely6.FromNode.create([
|
|
2200
|
-
import_kysely6.TableNode.create(relationModel)
|
|
2201
|
-
]),
|
|
2202
|
-
where: import_kysely6.WhereNode.create(condition)
|
|
2203
|
-
};
|
|
2204
|
-
}
|
|
2205
|
-
}
|
|
2206
|
-
createColumnRef(column, context) {
|
|
2207
|
-
return import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(column), import_kysely6.TableNode.create(context.alias ?? context.model));
|
|
2208
|
-
}
|
|
2209
|
-
isAuthCall(value) {
|
|
2210
|
-
return ExpressionUtils.isCall(value) && value.function === "auth";
|
|
2211
|
-
}
|
|
2212
|
-
isAuthMember(expr2) {
|
|
2213
|
-
return ExpressionUtils.isMember(expr2) && this.isAuthCall(expr2.receiver);
|
|
2214
|
-
}
|
|
2215
|
-
isNullNode(node) {
|
|
2216
|
-
return import_kysely6.ValueNode.is(node) && node.value === null;
|
|
2217
|
-
}
|
|
2218
|
-
};
|
|
2219
|
-
_ts_decorate([
|
|
2220
|
-
expr("literal"),
|
|
2221
|
-
_ts_metadata("design:type", Function),
|
|
2222
|
-
_ts_metadata("design:paramtypes", [
|
|
2223
|
-
typeof LiteralExpression === "undefined" ? Object : LiteralExpression
|
|
2224
|
-
]),
|
|
2225
|
-
_ts_metadata("design:returntype", void 0)
|
|
2226
|
-
], ExpressionTransformer.prototype, "_literal", null);
|
|
2227
|
-
_ts_decorate([
|
|
2228
|
-
expr("array"),
|
|
2229
|
-
_ts_metadata("design:type", Function),
|
|
2230
|
-
_ts_metadata("design:paramtypes", [
|
|
2231
|
-
typeof ArrayExpression === "undefined" ? Object : ArrayExpression,
|
|
2232
|
-
typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
|
|
2233
|
-
]),
|
|
2234
|
-
_ts_metadata("design:returntype", void 0)
|
|
2235
|
-
], ExpressionTransformer.prototype, "_array", null);
|
|
2236
|
-
_ts_decorate([
|
|
2237
|
-
expr("field"),
|
|
2238
|
-
_ts_metadata("design:type", Function),
|
|
2239
|
-
_ts_metadata("design:paramtypes", [
|
|
2240
|
-
typeof FieldExpression === "undefined" ? Object : FieldExpression,
|
|
2241
|
-
typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
|
|
2242
|
-
]),
|
|
2243
|
-
_ts_metadata("design:returntype", void 0)
|
|
2244
|
-
], ExpressionTransformer.prototype, "_field", null);
|
|
2245
|
-
_ts_decorate([
|
|
2246
|
-
expr("null"),
|
|
2247
|
-
_ts_metadata("design:type", Function),
|
|
2248
|
-
_ts_metadata("design:paramtypes", []),
|
|
2249
|
-
_ts_metadata("design:returntype", void 0)
|
|
2250
|
-
], ExpressionTransformer.prototype, "_null", null);
|
|
2251
|
-
_ts_decorate([
|
|
2252
|
-
expr("binary"),
|
|
2253
|
-
_ts_metadata("design:type", Function),
|
|
2254
|
-
_ts_metadata("design:paramtypes", [
|
|
2255
|
-
typeof BinaryExpression === "undefined" ? Object : BinaryExpression,
|
|
2256
|
-
typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
|
|
2257
|
-
]),
|
|
2258
|
-
_ts_metadata("design:returntype", void 0)
|
|
2259
|
-
], ExpressionTransformer.prototype, "_binary", null);
|
|
2260
|
-
_ts_decorate([
|
|
2261
|
-
expr("unary"),
|
|
2262
|
-
_ts_metadata("design:type", Function),
|
|
2263
|
-
_ts_metadata("design:paramtypes", [
|
|
2264
|
-
typeof UnaryExpression === "undefined" ? Object : UnaryExpression,
|
|
2265
|
-
typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
|
|
2266
|
-
]),
|
|
2267
|
-
_ts_metadata("design:returntype", void 0)
|
|
2268
|
-
], ExpressionTransformer.prototype, "_unary", null);
|
|
2269
|
-
_ts_decorate([
|
|
2270
|
-
expr("call"),
|
|
2271
|
-
_ts_metadata("design:type", Function),
|
|
2272
|
-
_ts_metadata("design:paramtypes", [
|
|
2273
|
-
typeof CallExpression === "undefined" ? Object : CallExpression,
|
|
2274
|
-
typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
|
|
2275
|
-
]),
|
|
2276
|
-
_ts_metadata("design:returntype", void 0)
|
|
2277
|
-
], ExpressionTransformer.prototype, "_call", null);
|
|
2278
|
-
_ts_decorate([
|
|
2279
|
-
expr("member"),
|
|
2280
|
-
_ts_metadata("design:type", Function),
|
|
2281
|
-
_ts_metadata("design:paramtypes", [
|
|
2282
|
-
typeof MemberExpression === "undefined" ? Object : MemberExpression,
|
|
2283
|
-
typeof ExpressionTransformerContext === "undefined" ? Object : ExpressionTransformerContext
|
|
2284
|
-
]),
|
|
2285
|
-
_ts_metadata("design:returntype", void 0)
|
|
2286
|
-
], ExpressionTransformer.prototype, "_member", null);
|
|
2287
|
-
|
|
2288
|
-
// src/plugins/policy/policy-handler.ts
|
|
2289
|
-
var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
2290
|
-
static {
|
|
2291
|
-
__name(this, "PolicyHandler");
|
|
2292
|
-
}
|
|
2293
|
-
client;
|
|
2294
|
-
dialect;
|
|
2295
|
-
constructor(client) {
|
|
2296
|
-
super(), this.client = client;
|
|
2297
|
-
this.dialect = getCrudDialect(this.client.$schema, this.client.$options);
|
|
2298
|
-
}
|
|
2299
|
-
get kysely() {
|
|
2300
|
-
return this.client.$qb;
|
|
2301
|
-
}
|
|
2302
|
-
async handle(node, proceed) {
|
|
2303
|
-
if (!this.isCrudQueryNode(node)) {
|
|
2304
|
-
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
2305
|
-
}
|
|
2306
|
-
if (!this.isMutationQueryNode(node)) {
|
|
2307
|
-
return proceed(this.transformNode(node));
|
|
2308
|
-
}
|
|
2309
|
-
let mutationRequiresTransaction = false;
|
|
2310
|
-
const mutationModel = this.getMutationModel(node);
|
|
2311
|
-
if (import_kysely7.InsertQueryNode.is(node)) {
|
|
2312
|
-
const constCondition = this.tryGetConstantPolicy(mutationModel, "create");
|
|
2313
|
-
if (constCondition === false) {
|
|
2314
|
-
throw new RejectedByPolicyError(mutationModel);
|
|
2315
|
-
} else if (constCondition === void 0) {
|
|
2316
|
-
mutationRequiresTransaction = true;
|
|
2317
|
-
}
|
|
2318
|
-
}
|
|
2319
|
-
if (!mutationRequiresTransaction && !node.returning) {
|
|
2320
|
-
return proceed(this.transformNode(node));
|
|
2321
|
-
}
|
|
2322
|
-
if (import_kysely7.InsertQueryNode.is(node)) {
|
|
2323
|
-
await this.enforcePreCreatePolicy(node, proceed);
|
|
2324
|
-
}
|
|
2325
|
-
const transformedNode = this.transformNode(node);
|
|
2326
|
-
const result = await proceed(transformedNode);
|
|
2327
|
-
if (!this.onlyReturningId(node)) {
|
|
2328
|
-
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2329
|
-
if (readBackResult.rows.length !== result.rows.length) {
|
|
2330
|
-
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
2331
|
-
}
|
|
2332
|
-
return readBackResult;
|
|
2333
|
-
} else {
|
|
2334
|
-
return result;
|
|
2335
|
-
}
|
|
2336
|
-
}
|
|
2337
|
-
onlyReturningId(node) {
|
|
2338
|
-
if (!node.returning) {
|
|
2339
|
-
return true;
|
|
2340
|
-
}
|
|
2341
|
-
const idFields = getIdFields(this.client.$schema, this.getMutationModel(node));
|
|
2342
|
-
const collector = new ColumnCollector();
|
|
2343
|
-
const selectedColumns = collector.collect(node.returning);
|
|
2344
|
-
return selectedColumns.every((c) => idFields.includes(c));
|
|
2345
|
-
}
|
|
2346
|
-
async enforcePreCreatePolicy(node, proceed) {
|
|
2347
|
-
if (!node.columns || !node.values) {
|
|
2348
|
-
return;
|
|
2349
|
-
}
|
|
2350
|
-
const model = this.getMutationModel(node);
|
|
2351
|
-
const fields = node.columns.map((c) => c.column.name);
|
|
2352
|
-
const valueRows = this.unwrapCreateValueRows(node.values, model, fields);
|
|
2353
|
-
for (const values of valueRows) {
|
|
2354
|
-
await this.enforcePreCreatePolicyForOne(model, fields, values.map((v) => v.node), values.map((v) => v.raw), proceed);
|
|
2355
|
-
}
|
|
2356
|
-
}
|
|
2357
|
-
async enforcePreCreatePolicyForOne(model, fields, values, valuesRaw, proceed) {
|
|
2358
|
-
const thisEntity = {};
|
|
2359
|
-
const thisEntityRaw = {};
|
|
2360
|
-
for (let i = 0; i < fields.length; i++) {
|
|
2361
|
-
thisEntity[fields[i]] = values[i];
|
|
2362
|
-
thisEntityRaw[fields[i]] = valuesRaw[i];
|
|
2363
|
-
}
|
|
2364
|
-
const filter = this.buildPolicyFilter(model, void 0, "create", thisEntity, thisEntityRaw);
|
|
2365
|
-
const preCreateCheck = {
|
|
2366
|
-
kind: "SelectQueryNode",
|
|
2367
|
-
selections: [
|
|
2368
|
-
import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(filter, import_kysely7.IdentifierNode.create("$condition")))
|
|
2369
|
-
]
|
|
2370
|
-
};
|
|
2371
|
-
const result = await proceed(preCreateCheck);
|
|
2372
|
-
if (!result.rows[0]?.$condition) {
|
|
2373
|
-
throw new RejectedByPolicyError(model);
|
|
2374
|
-
}
|
|
2375
|
-
}
|
|
2376
|
-
unwrapCreateValueRows(node, model, fields) {
|
|
2377
|
-
if (import_kysely7.ValuesNode.is(node)) {
|
|
2378
|
-
return node.values.map((v) => this.unwrapCreateValueRow(v.values, model, fields));
|
|
2379
|
-
} else if (import_kysely7.PrimitiveValueListNode.is(node)) {
|
|
2380
|
-
return [
|
|
2381
|
-
this.unwrapCreateValueRow(node.values, model, fields)
|
|
2382
|
-
];
|
|
2383
|
-
} else {
|
|
2384
|
-
throw new InternalError(`Unexpected node kind: ${node.kind} for unwrapping create values`);
|
|
2385
|
-
}
|
|
2386
|
-
}
|
|
2387
|
-
unwrapCreateValueRow(data, model, fields) {
|
|
2388
|
-
(0, import_common_helpers6.invariant)(data.length === fields.length, "data length must match fields length");
|
|
2389
|
-
const result = [];
|
|
2390
|
-
for (let i = 0; i < data.length; i++) {
|
|
2391
|
-
const item = data[i];
|
|
2392
|
-
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
2393
|
-
if (typeof item === "object" && item && "kind" in item) {
|
|
2394
|
-
(0, import_common_helpers6.invariant)(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2395
|
-
result.push({
|
|
2396
|
-
node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2397
|
-
raw: item.value
|
|
2398
|
-
});
|
|
2399
|
-
} else {
|
|
2400
|
-
const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
2401
|
-
if (Array.isArray(value)) {
|
|
2402
|
-
result.push({
|
|
2403
|
-
node: import_kysely7.RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
2404
|
-
raw: value
|
|
2405
|
-
});
|
|
2406
|
-
} else {
|
|
2407
|
-
result.push({
|
|
2408
|
-
node: import_kysely7.ValueNode.create(value),
|
|
2409
|
-
raw: value
|
|
2410
|
-
});
|
|
2411
|
-
}
|
|
2412
|
-
}
|
|
2413
|
-
}
|
|
2414
|
-
return result;
|
|
2415
|
-
}
|
|
2416
|
-
tryGetConstantPolicy(model, operation) {
|
|
2417
|
-
const policies = this.getModelPolicies(model, operation);
|
|
2418
|
-
if (!policies.some((p) => p.kind === "allow")) {
|
|
2419
|
-
return false;
|
|
2420
|
-
} else if (
|
|
2421
|
-
// unconditional deny
|
|
2422
|
-
policies.some((p) => p.kind === "deny" && this.isTrueExpr(p.condition))
|
|
2423
|
-
) {
|
|
2424
|
-
return false;
|
|
2425
|
-
} else if (
|
|
2426
|
-
// unconditional allow
|
|
2427
|
-
!policies.some((p) => p.kind === "deny") && policies.some((p) => p.kind === "allow" && this.isTrueExpr(p.condition))
|
|
2428
|
-
) {
|
|
2429
|
-
return true;
|
|
2430
|
-
} else {
|
|
2431
|
-
return void 0;
|
|
2432
|
-
}
|
|
2433
|
-
}
|
|
2434
|
-
isTrueExpr(expr2) {
|
|
2435
|
-
return ExpressionUtils.isLiteral(expr2) && expr2.value === true;
|
|
2436
|
-
}
|
|
2437
|
-
async processReadBack(node, result, proceed) {
|
|
2438
|
-
if (result.rows.length === 0) {
|
|
2439
|
-
return result;
|
|
2440
|
-
}
|
|
2441
|
-
if (!this.isMutationQueryNode(node) || !node.returning) {
|
|
2442
|
-
return result;
|
|
2443
|
-
}
|
|
2444
|
-
const table = this.getMutationModel(node);
|
|
2445
|
-
if (!table) {
|
|
2446
|
-
throw new InternalError(`Unable to get table name for query node: ${node}`);
|
|
2447
|
-
}
|
|
2448
|
-
const idConditions = this.buildIdConditions(table, result.rows);
|
|
2449
|
-
const policyFilter = this.buildPolicyFilter(table, void 0, "read");
|
|
2450
|
-
const select = {
|
|
2451
|
-
kind: "SelectQueryNode",
|
|
2452
|
-
from: import_kysely7.FromNode.create([
|
|
2453
|
-
import_kysely7.TableNode.create(table)
|
|
2454
|
-
]),
|
|
2455
|
-
where: import_kysely7.WhereNode.create(conjunction(this.dialect, [
|
|
2456
|
-
idConditions,
|
|
2457
|
-
policyFilter
|
|
2458
|
-
])),
|
|
2459
|
-
selections: node.returning.selections
|
|
2460
|
-
};
|
|
2461
|
-
const selectResult = await proceed(select);
|
|
2462
|
-
return selectResult;
|
|
2463
|
-
}
|
|
2464
|
-
buildIdConditions(table, rows) {
|
|
2465
|
-
const idFields = getIdFields(this.client.$schema, table);
|
|
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]))))));
|
|
2467
|
-
}
|
|
2468
|
-
getMutationModel(node) {
|
|
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) => {
|
|
2470
|
-
if (node2.from.froms.length !== 1) {
|
|
2471
|
-
throw new InternalError("Only one from table is supported for delete");
|
|
2472
|
-
}
|
|
2473
|
-
return getTableName(node2.from.froms[0]);
|
|
2474
|
-
}).exhaustive();
|
|
2475
|
-
if (!r) {
|
|
2476
|
-
throw new InternalError(`Unable to get table name for query node: ${node}`);
|
|
2477
|
-
}
|
|
2478
|
-
return r;
|
|
2479
|
-
}
|
|
2480
|
-
isCrudQueryNode(node) {
|
|
2481
|
-
return import_kysely7.SelectQueryNode.is(node) || import_kysely7.InsertQueryNode.is(node) || import_kysely7.UpdateQueryNode.is(node) || import_kysely7.DeleteQueryNode.is(node);
|
|
2482
|
-
}
|
|
2483
|
-
isMutationQueryNode(node) {
|
|
2484
|
-
return import_kysely7.InsertQueryNode.is(node) || import_kysely7.UpdateQueryNode.is(node) || import_kysely7.DeleteQueryNode.is(node);
|
|
2485
|
-
}
|
|
2486
|
-
buildPolicyFilter(model, alias, operation, thisEntity, thisEntityRaw) {
|
|
2487
|
-
const policies = this.getModelPolicies(model, operation);
|
|
2488
|
-
if (policies.length === 0) {
|
|
2489
|
-
return falseNode(this.dialect);
|
|
2490
|
-
}
|
|
2491
|
-
const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.transformPolicyCondition(model, alias, operation, policy, thisEntity, thisEntityRaw));
|
|
2492
|
-
const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.transformPolicyCondition(model, alias, operation, policy, thisEntity, thisEntityRaw));
|
|
2493
|
-
let combinedPolicy;
|
|
2494
|
-
if (allows.length === 0) {
|
|
2495
|
-
combinedPolicy = falseNode(this.dialect);
|
|
2496
|
-
} else {
|
|
2497
|
-
combinedPolicy = disjunction(this.dialect, allows);
|
|
2498
|
-
if (denies.length !== 0) {
|
|
2499
|
-
const combinedDenies = conjunction(this.dialect, denies.map((d) => buildIsFalse(d, this.dialect)));
|
|
2500
|
-
combinedPolicy = conjunction(this.dialect, [
|
|
2501
|
-
combinedPolicy,
|
|
2502
|
-
combinedDenies
|
|
2503
|
-
]);
|
|
2504
|
-
}
|
|
2505
|
-
}
|
|
2506
|
-
return combinedPolicy;
|
|
2507
|
-
}
|
|
2508
|
-
transformSelectQuery(node) {
|
|
2509
|
-
let whereNode = node.where;
|
|
2510
|
-
node.from?.froms.forEach((from) => {
|
|
2511
|
-
const extractResult = this.extractTableName(from);
|
|
2512
|
-
if (extractResult) {
|
|
2513
|
-
const { model, alias } = extractResult;
|
|
2514
|
-
const filter = this.buildPolicyFilter(model, alias, "read");
|
|
2515
|
-
whereNode = import_kysely7.WhereNode.create(whereNode?.where ? conjunction(this.dialect, [
|
|
2516
|
-
whereNode.where,
|
|
2517
|
-
filter
|
|
2518
|
-
]) : filter);
|
|
2519
|
-
}
|
|
2520
|
-
});
|
|
2521
|
-
const baseResult = super.transformSelectQuery({
|
|
2522
|
-
...node,
|
|
2523
|
-
where: void 0
|
|
2524
|
-
});
|
|
2525
|
-
return {
|
|
2526
|
-
...baseResult,
|
|
2527
|
-
where: whereNode
|
|
2528
|
-
};
|
|
2529
|
-
}
|
|
2530
|
-
transformInsertQuery(node) {
|
|
2531
|
-
const result = super.transformInsertQuery(node);
|
|
2532
|
-
if (!node.returning) {
|
|
2533
|
-
return result;
|
|
2534
|
-
}
|
|
2535
|
-
if (this.onlyReturningId(node)) {
|
|
2536
|
-
return result;
|
|
2537
|
-
} else {
|
|
2538
|
-
const idFields = getIdFields(this.client.$schema, this.getMutationModel(node));
|
|
2539
|
-
return {
|
|
2540
|
-
...result,
|
|
2541
|
-
returning: import_kysely7.ReturningNode.create(idFields.map((field) => import_kysely7.SelectionNode.create(import_kysely7.ColumnNode.create(field))))
|
|
2542
|
-
};
|
|
2543
|
-
}
|
|
2544
|
-
}
|
|
2545
|
-
transformUpdateQuery(node) {
|
|
2546
|
-
const result = super.transformUpdateQuery(node);
|
|
2547
|
-
const mutationModel = this.getMutationModel(node);
|
|
2548
|
-
const filter = this.buildPolicyFilter(mutationModel, void 0, "update");
|
|
2549
|
-
return {
|
|
2550
|
-
...result,
|
|
2551
|
-
where: import_kysely7.WhereNode.create(result.where ? conjunction(this.dialect, [
|
|
2552
|
-
result.where.where,
|
|
2553
|
-
filter
|
|
2554
|
-
]) : filter)
|
|
2555
|
-
};
|
|
2556
|
-
}
|
|
2557
|
-
transformDeleteQuery(node) {
|
|
2558
|
-
const result = super.transformDeleteQuery(node);
|
|
2559
|
-
const mutationModel = this.getMutationModel(node);
|
|
2560
|
-
const filter = this.buildPolicyFilter(mutationModel, void 0, "delete");
|
|
2561
|
-
return {
|
|
2562
|
-
...result,
|
|
2563
|
-
where: import_kysely7.WhereNode.create(result.where ? conjunction(this.dialect, [
|
|
2564
|
-
result.where.where,
|
|
2565
|
-
filter
|
|
2566
|
-
]) : filter)
|
|
2567
|
-
};
|
|
2568
|
-
}
|
|
2569
|
-
extractTableName(from) {
|
|
2570
|
-
if (import_kysely7.TableNode.is(from)) {
|
|
2571
|
-
return {
|
|
2572
|
-
model: from.table.identifier.name
|
|
2573
|
-
};
|
|
2574
|
-
}
|
|
2575
|
-
if (import_kysely7.AliasNode.is(from)) {
|
|
2576
|
-
const inner = this.extractTableName(from.node);
|
|
2577
|
-
if (!inner) {
|
|
2578
|
-
return void 0;
|
|
2579
|
-
}
|
|
2580
|
-
return {
|
|
2581
|
-
model: inner.model,
|
|
2582
|
-
alias: import_kysely7.IdentifierNode.is(from.alias) ? from.alias.name : void 0
|
|
2583
|
-
};
|
|
2584
|
-
} else {
|
|
2585
|
-
return void 0;
|
|
2586
|
-
}
|
|
2587
|
-
}
|
|
2588
|
-
transformPolicyCondition(model, alias, operation, policy, thisEntity, thisEntityRaw) {
|
|
2589
|
-
return new ExpressionTransformer(this.client.$schema, this.client.$options, this.client.$auth).transform(policy.condition, {
|
|
2590
|
-
model,
|
|
2591
|
-
alias,
|
|
2592
|
-
operation,
|
|
2593
|
-
thisEntity,
|
|
2594
|
-
thisEntityRaw,
|
|
2595
|
-
auth: this.client.$auth
|
|
2596
|
-
});
|
|
2597
|
-
}
|
|
2598
|
-
getModelPolicies(modelName, operation) {
|
|
2599
|
-
const modelDef = requireModel(this.client.$schema, modelName);
|
|
2600
|
-
const result = [];
|
|
2601
|
-
const extractOperations = /* @__PURE__ */ __name((expr2) => {
|
|
2602
|
-
(0, import_common_helpers6.invariant)(ExpressionUtils.isLiteral(expr2), "expecting a literal");
|
|
2603
|
-
(0, import_common_helpers6.invariant)(typeof expr2.value === "string", "expecting a string literal");
|
|
2604
|
-
return expr2.value.split(",").filter((v) => !!v).map((v) => v.trim());
|
|
2605
|
-
}, "extractOperations");
|
|
2606
|
-
if (modelDef.attributes) {
|
|
2607
|
-
result.push(...modelDef.attributes.filter((attr) => attr.name === "@@allow" || attr.name === "@@deny").map((attr) => ({
|
|
2608
|
-
kind: attr.name === "@@allow" ? "allow" : "deny",
|
|
2609
|
-
operations: extractOperations(attr.args[0].value),
|
|
2610
|
-
condition: attr.args[1].value
|
|
2611
|
-
})).filter((policy) => policy.operations.includes("all") || policy.operations.includes(operation)));
|
|
2612
|
-
}
|
|
2613
|
-
return result;
|
|
2614
|
-
}
|
|
2615
|
-
};
|
|
2616
|
-
|
|
2617
|
-
// src/plugins/policy/plugin.ts
|
|
2618
|
-
var PolicyPlugin = class {
|
|
2619
|
-
static {
|
|
2620
|
-
__name(this, "PolicyPlugin");
|
|
2621
|
-
}
|
|
2622
|
-
get id() {
|
|
2623
|
-
return "policy";
|
|
2624
|
-
}
|
|
2625
|
-
get name() {
|
|
2626
|
-
return "Access Policy";
|
|
2627
|
-
}
|
|
2628
|
-
get description() {
|
|
2629
|
-
return "Enforces access policies defined in the schema.";
|
|
2630
|
-
}
|
|
2631
|
-
onKyselyQuery({
|
|
2632
|
-
query,
|
|
2633
|
-
client,
|
|
2634
|
-
proceed
|
|
2635
|
-
/*, transaction*/
|
|
2636
|
-
}) {
|
|
2637
|
-
const handler = new PolicyHandler(client);
|
|
2638
|
-
return handler.handle(
|
|
2639
|
-
query,
|
|
2640
|
-
proceed
|
|
2641
|
-
/*, transaction*/
|
|
2642
|
-
);
|
|
2643
|
-
}
|
|
2644
|
-
};
|
|
2645
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
2646
|
-
0 && (module.exports = {
|
|
2647
|
-
PolicyPlugin,
|
|
2648
|
-
RejectedByPolicyError
|
|
2649
|
-
});
|
|
2650
|
-
//# sourceMappingURL=index.cjs.map
|