@zenstackhq/runtime 3.0.0-alpha.2 → 3.0.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{contract-DguafRNB.d.cts → contract-XFKcwhq7.d.cts} +970 -785
- package/dist/{contract-DguafRNB.d.ts → contract-XFKcwhq7.d.ts} +970 -785
- package/dist/{utils/pg-utils.cjs → helpers.cjs} +8 -16
- package/dist/helpers.cjs.map +1 -0
- package/dist/helpers.d.cts +1 -0
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +6 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.cjs +1774 -892
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -6
- package/dist/index.d.ts +28 -6
- package/dist/index.js +1724 -847
- package/dist/index.js.map +1 -1
- package/dist/plugins/{policy.cjs → policy/index.cjs} +463 -266
- package/dist/plugins/policy/index.cjs.map +1 -0
- package/dist/plugins/{policy.d.ts → policy/index.d.cts} +2 -4
- package/dist/plugins/{policy.d.cts → policy/index.d.ts} +2 -4
- package/dist/plugins/{policy.js → policy/index.js} +435 -228
- package/dist/plugins/policy/index.js.map +1 -0
- package/dist/plugins/policy/plugin.zmodel +33 -0
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js.map +1 -1
- package/package.json +27 -49
- package/dist/client.cjs +0 -6094
- package/dist/client.cjs.map +0 -1
- package/dist/client.d.cts +0 -19
- package/dist/client.d.ts +0 -19
- package/dist/client.js +0 -6060
- package/dist/client.js.map +0 -1
- package/dist/plugins/policy.cjs.map +0 -1
- package/dist/plugins/policy.js.map +0 -1
- package/dist/utils/pg-utils.cjs.map +0 -1
- package/dist/utils/pg-utils.d.cts +0 -8
- package/dist/utils/pg-utils.d.ts +0 -8
- package/dist/utils/pg-utils.js +0 -16
- package/dist/utils/pg-utils.js.map +0 -1
- package/dist/utils/sqlite-utils.cjs +0 -55
- package/dist/utils/sqlite-utils.cjs.map +0 -1
- package/dist/utils/sqlite-utils.d.cts +0 -8
- package/dist/utils/sqlite-utils.d.ts +0 -8
- package/dist/utils/sqlite-utils.js +0 -22
- package/dist/utils/sqlite-utils.js.map +0 -1
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
7
|
var __export = (target, all) => {
|
|
@@ -18,14 +16,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
16
|
}
|
|
19
17
|
return to;
|
|
20
18
|
};
|
|
21
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
-
mod
|
|
28
|
-
));
|
|
29
19
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
20
|
|
|
31
21
|
// src/plugins/policy/index.ts
|
|
@@ -49,34 +39,130 @@ var RejectedByPolicyError = class extends Error {
|
|
|
49
39
|
};
|
|
50
40
|
|
|
51
41
|
// src/plugins/policy/policy-handler.ts
|
|
42
|
+
var import_common_helpers6 = require("@zenstackhq/common-helpers");
|
|
52
43
|
var import_kysely7 = require("kysely");
|
|
53
|
-
var
|
|
54
|
-
var import_ts_pattern7 = require("ts-pattern");
|
|
44
|
+
var import_ts_pattern8 = require("ts-pattern");
|
|
55
45
|
|
|
56
46
|
// src/client/crud/dialects/index.ts
|
|
57
|
-
var
|
|
47
|
+
var import_ts_pattern5 = require("ts-pattern");
|
|
58
48
|
|
|
59
49
|
// src/client/crud/dialects/postgresql.ts
|
|
50
|
+
var import_common_helpers2 = require("@zenstackhq/common-helpers");
|
|
60
51
|
var import_kysely2 = require("kysely");
|
|
61
|
-
var
|
|
62
|
-
|
|
52
|
+
var import_ts_pattern3 = require("ts-pattern");
|
|
53
|
+
|
|
54
|
+
// src/client/constants.ts
|
|
55
|
+
var DELEGATE_JOINED_FIELD_PREFIX = "$delegate$";
|
|
56
|
+
var LOGICAL_COMBINATORS = [
|
|
57
|
+
"AND",
|
|
58
|
+
"OR",
|
|
59
|
+
"NOT"
|
|
60
|
+
];
|
|
61
|
+
var AGGREGATE_OPERATORS = [
|
|
62
|
+
"_count",
|
|
63
|
+
"_sum",
|
|
64
|
+
"_avg",
|
|
65
|
+
"_min",
|
|
66
|
+
"_max"
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
// src/client/query-utils.ts
|
|
70
|
+
var import_ts_pattern = require("ts-pattern");
|
|
71
|
+
|
|
72
|
+
// src/schema/expression.ts
|
|
73
|
+
var ExpressionUtils = {
|
|
74
|
+
literal: /* @__PURE__ */ __name((value) => {
|
|
75
|
+
return {
|
|
76
|
+
kind: "literal",
|
|
77
|
+
value
|
|
78
|
+
};
|
|
79
|
+
}, "literal"),
|
|
80
|
+
array: /* @__PURE__ */ __name((items) => {
|
|
81
|
+
return {
|
|
82
|
+
kind: "array",
|
|
83
|
+
items
|
|
84
|
+
};
|
|
85
|
+
}, "array"),
|
|
86
|
+
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
87
|
+
return {
|
|
88
|
+
kind: "call",
|
|
89
|
+
function: functionName,
|
|
90
|
+
args
|
|
91
|
+
};
|
|
92
|
+
}, "call"),
|
|
93
|
+
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
94
|
+
return {
|
|
95
|
+
kind: "binary",
|
|
96
|
+
op,
|
|
97
|
+
left,
|
|
98
|
+
right
|
|
99
|
+
};
|
|
100
|
+
}, "binary"),
|
|
101
|
+
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
102
|
+
return {
|
|
103
|
+
kind: "unary",
|
|
104
|
+
op,
|
|
105
|
+
operand
|
|
106
|
+
};
|
|
107
|
+
}, "unary"),
|
|
108
|
+
field: /* @__PURE__ */ __name((field) => {
|
|
109
|
+
return {
|
|
110
|
+
kind: "field",
|
|
111
|
+
field
|
|
112
|
+
};
|
|
113
|
+
}, "field"),
|
|
114
|
+
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
115
|
+
return {
|
|
116
|
+
kind: "member",
|
|
117
|
+
receiver,
|
|
118
|
+
members
|
|
119
|
+
};
|
|
120
|
+
}, "member"),
|
|
121
|
+
_this: /* @__PURE__ */ __name(() => {
|
|
122
|
+
return {
|
|
123
|
+
kind: "this"
|
|
124
|
+
};
|
|
125
|
+
}, "_this"),
|
|
126
|
+
_null: /* @__PURE__ */ __name(() => {
|
|
127
|
+
return {
|
|
128
|
+
kind: "null"
|
|
129
|
+
};
|
|
130
|
+
}, "_null"),
|
|
131
|
+
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
132
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
133
|
+
}, "and"),
|
|
134
|
+
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
135
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
136
|
+
}, "or"),
|
|
137
|
+
is: /* @__PURE__ */ __name((value, kind) => {
|
|
138
|
+
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
139
|
+
}, "is"),
|
|
140
|
+
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
141
|
+
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
142
|
+
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
143
|
+
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
144
|
+
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
145
|
+
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
146
|
+
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
147
|
+
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
148
|
+
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
|
|
149
|
+
};
|
|
63
150
|
|
|
64
151
|
// src/client/errors.ts
|
|
65
152
|
var QueryError = class extends Error {
|
|
66
153
|
static {
|
|
67
154
|
__name(this, "QueryError");
|
|
68
155
|
}
|
|
69
|
-
constructor(message) {
|
|
70
|
-
super(message
|
|
156
|
+
constructor(message, cause) {
|
|
157
|
+
super(message, {
|
|
158
|
+
cause
|
|
159
|
+
});
|
|
71
160
|
}
|
|
72
161
|
};
|
|
73
162
|
var InternalError = class extends Error {
|
|
74
163
|
static {
|
|
75
164
|
__name(this, "InternalError");
|
|
76
165
|
}
|
|
77
|
-
constructor(message) {
|
|
78
|
-
super(message);
|
|
79
|
-
}
|
|
80
166
|
};
|
|
81
167
|
|
|
82
168
|
// src/client/query-utils.ts
|
|
@@ -87,7 +173,7 @@ __name(getModel, "getModel");
|
|
|
87
173
|
function requireModel(schema, model) {
|
|
88
174
|
const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
|
|
89
175
|
if (!matchedName) {
|
|
90
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
176
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
91
177
|
}
|
|
92
178
|
return schema.models[matchedName];
|
|
93
179
|
}
|
|
@@ -150,6 +236,16 @@ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
|
150
236
|
}
|
|
151
237
|
}
|
|
152
238
|
__name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
|
|
239
|
+
function isRelationField(schema, model, field) {
|
|
240
|
+
const fieldDef = getField(schema, model, field);
|
|
241
|
+
return !!fieldDef?.relation;
|
|
242
|
+
}
|
|
243
|
+
__name(isRelationField, "isRelationField");
|
|
244
|
+
function isInheritedField(schema, model, field) {
|
|
245
|
+
const fieldDef = getField(schema, model, field);
|
|
246
|
+
return !!fieldDef?.originModel;
|
|
247
|
+
}
|
|
248
|
+
__name(isInheritedField, "isInheritedField");
|
|
153
249
|
function getUniqueFields(schema, model) {
|
|
154
250
|
const modelDef = requireModel(schema, model);
|
|
155
251
|
const result = [];
|
|
@@ -186,7 +282,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias) {
|
|
|
186
282
|
computer = computedFields?.[model]?.[field];
|
|
187
283
|
}
|
|
188
284
|
if (!computer) {
|
|
189
|
-
throw new QueryError(`Computed field "${field}" implementation not provided`);
|
|
285
|
+
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
190
286
|
}
|
|
191
287
|
return computer(eb);
|
|
192
288
|
}
|
|
@@ -263,11 +359,28 @@ function flattenCompoundUniqueFilters(schema, model, filter) {
|
|
|
263
359
|
return result;
|
|
264
360
|
}
|
|
265
361
|
__name(flattenCompoundUniqueFilters, "flattenCompoundUniqueFilters");
|
|
362
|
+
function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */ new Set()) {
|
|
363
|
+
const subModels = Object.values(schema.models).filter((m) => m.baseModel === model);
|
|
364
|
+
subModels.forEach((def) => {
|
|
365
|
+
if (!collected.has(def)) {
|
|
366
|
+
collected.add(def);
|
|
367
|
+
getDelegateDescendantModels(schema, def.name, collected);
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
return [
|
|
371
|
+
...collected
|
|
372
|
+
];
|
|
373
|
+
}
|
|
374
|
+
__name(getDelegateDescendantModels, "getDelegateDescendantModels");
|
|
375
|
+
function aggregate(eb, expr2, op) {
|
|
376
|
+
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();
|
|
377
|
+
}
|
|
378
|
+
__name(aggregate, "aggregate");
|
|
266
379
|
|
|
267
380
|
// src/client/crud/dialects/base.ts
|
|
381
|
+
var import_common_helpers = require("@zenstackhq/common-helpers");
|
|
268
382
|
var import_kysely = require("kysely");
|
|
269
|
-
var
|
|
270
|
-
var import_ts_pattern = require("ts-pattern");
|
|
383
|
+
var import_ts_pattern2 = require("ts-pattern");
|
|
271
384
|
|
|
272
385
|
// src/utils/enumerate.ts
|
|
273
386
|
function enumerate(x) {
|
|
@@ -284,7 +397,6 @@ function enumerate(x) {
|
|
|
284
397
|
__name(enumerate, "enumerate");
|
|
285
398
|
|
|
286
399
|
// src/client/crud/dialects/base.ts
|
|
287
|
-
var import_is_plain_object = require("is-plain-object");
|
|
288
400
|
var BaseCrudDialect = class {
|
|
289
401
|
static {
|
|
290
402
|
__name(this, "BaseCrudDialect");
|
|
@@ -295,9 +407,20 @@ var BaseCrudDialect = class {
|
|
|
295
407
|
this.schema = schema;
|
|
296
408
|
this.options = options;
|
|
297
409
|
}
|
|
298
|
-
transformPrimitive(value, _type) {
|
|
410
|
+
transformPrimitive(value, _type, _forArrayField) {
|
|
299
411
|
return value;
|
|
300
412
|
}
|
|
413
|
+
// #region common query builders
|
|
414
|
+
buildSelectModel(eb, model) {
|
|
415
|
+
const modelDef = requireModel(this.schema, model);
|
|
416
|
+
let result = eb.selectFrom(model);
|
|
417
|
+
let joinBase = modelDef.baseModel;
|
|
418
|
+
while (joinBase) {
|
|
419
|
+
result = this.buildDelegateJoin(model, joinBase, result);
|
|
420
|
+
joinBase = requireModel(this.schema, joinBase).baseModel;
|
|
421
|
+
}
|
|
422
|
+
return result;
|
|
423
|
+
}
|
|
301
424
|
buildFilter(eb, model, modelAlias, where) {
|
|
302
425
|
if (where === true || where === void 0) {
|
|
303
426
|
return this.true(eb);
|
|
@@ -314,17 +437,20 @@ var BaseCrudDialect = class {
|
|
|
314
437
|
if (key.startsWith("$")) {
|
|
315
438
|
continue;
|
|
316
439
|
}
|
|
317
|
-
if (key
|
|
440
|
+
if (this.isLogicalCombinator(key)) {
|
|
318
441
|
result = this.and(eb, result, this.buildCompositeFilter(eb, model, modelAlias, key, payload));
|
|
319
442
|
continue;
|
|
320
443
|
}
|
|
321
444
|
const fieldDef = requireField(this.schema, model, key);
|
|
322
445
|
if (fieldDef.relation) {
|
|
323
446
|
result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
324
|
-
} else if (fieldDef.array) {
|
|
325
|
-
result = this.and(eb, result, this.buildArrayFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
326
447
|
} else {
|
|
327
|
-
|
|
448
|
+
const fieldRef = buildFieldRef(this.schema, fieldDef.originModel ?? model, key, this.options, eb, fieldDef.originModel ?? modelAlias);
|
|
449
|
+
if (fieldDef.array) {
|
|
450
|
+
result = this.and(eb, result, this.buildArrayFilter(eb, fieldRef, fieldDef, payload));
|
|
451
|
+
} else {
|
|
452
|
+
result = this.and(eb, result, this.buildPrimitiveFilter(eb, fieldRef, fieldDef, payload));
|
|
453
|
+
}
|
|
328
454
|
}
|
|
329
455
|
}
|
|
330
456
|
if ("$expr" in _where && typeof _where["$expr"] === "function") {
|
|
@@ -332,8 +458,11 @@ var BaseCrudDialect = class {
|
|
|
332
458
|
}
|
|
333
459
|
return result;
|
|
334
460
|
}
|
|
461
|
+
isLogicalCombinator(key) {
|
|
462
|
+
return LOGICAL_COMBINATORS.includes(key);
|
|
463
|
+
}
|
|
335
464
|
buildCompositeFilter(eb, model, modelAlias, key, payload) {
|
|
336
|
-
return (0,
|
|
465
|
+
return (0, import_ts_pattern2.match)(key).with("AND", () => this.and(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("OR", () => this.or(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("NOT", () => eb.not(this.buildCompositeFilter(eb, model, modelAlias, "AND", payload))).exhaustive();
|
|
337
466
|
}
|
|
338
467
|
buildRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
339
468
|
if (!fieldDef.array) {
|
|
@@ -342,19 +471,26 @@ var BaseCrudDialect = class {
|
|
|
342
471
|
return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
|
|
343
472
|
}
|
|
344
473
|
}
|
|
345
|
-
buildToOneRelationFilter(eb, model,
|
|
474
|
+
buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
346
475
|
if (payload === null) {
|
|
347
476
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
348
|
-
if (ownedByModel) {
|
|
349
|
-
return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely.sql.ref(`${
|
|
477
|
+
if (ownedByModel && !fieldDef.originModel) {
|
|
478
|
+
return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely.sql.ref(`${modelAlias}.${fk}`), "is", null)));
|
|
350
479
|
} else {
|
|
351
|
-
return this.buildToOneRelationFilter(eb, model,
|
|
480
|
+
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
|
|
352
481
|
is: null
|
|
353
482
|
});
|
|
354
483
|
}
|
|
355
484
|
}
|
|
356
|
-
const joinAlias = `${
|
|
357
|
-
const joinPairs = buildJoinPairs(
|
|
485
|
+
const joinAlias = `${modelAlias}$${field}`;
|
|
486
|
+
const joinPairs = buildJoinPairs(
|
|
487
|
+
this.schema,
|
|
488
|
+
model,
|
|
489
|
+
// if field is from a base, use the base model to join
|
|
490
|
+
fieldDef.originModel ?? modelAlias,
|
|
491
|
+
field,
|
|
492
|
+
joinAlias
|
|
493
|
+
);
|
|
358
494
|
const filterResultField = `${field}$filter`;
|
|
359
495
|
const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
|
|
360
496
|
const conditions = [];
|
|
@@ -415,30 +551,29 @@ var BaseCrudDialect = class {
|
|
|
415
551
|
}
|
|
416
552
|
switch (key) {
|
|
417
553
|
case "some": {
|
|
418
|
-
result = this.and(eb, result, eb(
|
|
554
|
+
result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), ">", 0));
|
|
419
555
|
break;
|
|
420
556
|
}
|
|
421
557
|
case "every": {
|
|
422
|
-
result = this.and(eb, result, eb(
|
|
558
|
+
result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => eb1.not(this.buildFilter(eb1, relationModel, relationModel, subPayload))), "=", 0));
|
|
423
559
|
break;
|
|
424
560
|
}
|
|
425
561
|
case "none": {
|
|
426
|
-
result = this.and(eb, result, eb(
|
|
562
|
+
result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), "=", 0));
|
|
427
563
|
break;
|
|
428
564
|
}
|
|
429
565
|
}
|
|
430
566
|
}
|
|
431
567
|
return result;
|
|
432
568
|
}
|
|
433
|
-
buildArrayFilter(eb,
|
|
569
|
+
buildArrayFilter(eb, fieldRef, fieldDef, payload) {
|
|
434
570
|
const clauses = [];
|
|
435
571
|
const fieldType = fieldDef.type;
|
|
436
|
-
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
|
|
437
572
|
for (const [key, _value] of Object.entries(payload)) {
|
|
438
573
|
if (_value === void 0) {
|
|
439
574
|
continue;
|
|
440
575
|
}
|
|
441
|
-
const value = this.transformPrimitive(_value, fieldType);
|
|
576
|
+
const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
|
|
442
577
|
switch (key) {
|
|
443
578
|
case "equals": {
|
|
444
579
|
clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
|
|
@@ -469,20 +604,24 @@ var BaseCrudDialect = class {
|
|
|
469
604
|
}
|
|
470
605
|
return this.and(eb, ...clauses);
|
|
471
606
|
}
|
|
472
|
-
buildPrimitiveFilter(eb,
|
|
607
|
+
buildPrimitiveFilter(eb, fieldRef, fieldDef, payload) {
|
|
473
608
|
if (payload === null) {
|
|
474
|
-
return eb(
|
|
609
|
+
return eb(fieldRef, "is", null);
|
|
475
610
|
}
|
|
476
611
|
if (isEnum(this.schema, fieldDef.type)) {
|
|
477
|
-
return this.buildEnumFilter(eb,
|
|
612
|
+
return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
|
|
478
613
|
}
|
|
479
|
-
return (0,
|
|
614
|
+
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", () => {
|
|
615
|
+
throw new InternalError("JSON filters are not supported yet");
|
|
616
|
+
}).with("Unsupported", () => {
|
|
617
|
+
throw new QueryError(`Unsupported field cannot be used in filters`);
|
|
618
|
+
}).exhaustive();
|
|
480
619
|
}
|
|
481
620
|
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
482
|
-
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
|
|
621
|
+
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
483
622
|
}
|
|
484
|
-
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
|
|
485
|
-
if (payload === null || !(0,
|
|
623
|
+
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
624
|
+
if (payload === null || !(0, import_common_helpers.isPlainObject)(payload)) {
|
|
486
625
|
return {
|
|
487
626
|
conditions: [
|
|
488
627
|
this.buildLiteralFilter(eb, lhs, type, payload)
|
|
@@ -496,22 +635,29 @@ var BaseCrudDialect = class {
|
|
|
496
635
|
if (onlyForKeys && !onlyForKeys.includes(op)) {
|
|
497
636
|
continue;
|
|
498
637
|
}
|
|
638
|
+
if (excludeKeys.includes(op)) {
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
499
641
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
500
|
-
const condition = (0,
|
|
501
|
-
(0,
|
|
642
|
+
const condition = (0, import_ts_pattern2.match)(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
643
|
+
(0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
502
644
|
if (rhs.length === 0) {
|
|
503
645
|
return this.false(eb);
|
|
504
646
|
} else {
|
|
505
647
|
return eb(lhs, "in", rhs);
|
|
506
648
|
}
|
|
507
649
|
}).with("notIn", () => {
|
|
508
|
-
(0,
|
|
650
|
+
(0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
509
651
|
if (rhs.length === 0) {
|
|
510
652
|
return this.true(eb);
|
|
511
653
|
} else {
|
|
512
654
|
return eb.not(eb(lhs, "in", rhs));
|
|
513
655
|
}
|
|
514
|
-
}).with("lt", () => eb(lhs, "<", rhs)).with("lte", () => eb(lhs, "<=", rhs)).with("gt", () => eb(lhs, ">", rhs)).with("gte", () => eb(lhs, ">=", rhs)).with("not", () => eb.not(recurse(value))).
|
|
656
|
+
}).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) => {
|
|
657
|
+
const innerResult = this.buildStandardFilter(eb, type, value, aggregate(eb, lhs, op2), getRhs, recurse, throwIfInvalid);
|
|
658
|
+
consumedKeys.push(...innerResult.consumedKeys);
|
|
659
|
+
return this.and(eb, ...innerResult.conditions);
|
|
660
|
+
}).otherwise(() => {
|
|
515
661
|
if (throwIfInvalid) {
|
|
516
662
|
throw new QueryError(`Invalid filter key: ${op}`);
|
|
517
663
|
} else {
|
|
@@ -528,24 +674,21 @@ var BaseCrudDialect = class {
|
|
|
528
674
|
consumedKeys
|
|
529
675
|
};
|
|
530
676
|
}
|
|
531
|
-
buildStringFilter(eb,
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
if (payload && typeof payload === "object" && "mode" in payload && payload.mode === "insensitive") {
|
|
536
|
-
insensitive = true;
|
|
537
|
-
fieldRef = eb.fn("lower", [
|
|
538
|
-
fieldRef
|
|
539
|
-
]);
|
|
677
|
+
buildStringFilter(eb, fieldRef, payload) {
|
|
678
|
+
let mode;
|
|
679
|
+
if (payload && typeof payload === "object" && "mode" in payload) {
|
|
680
|
+
mode = payload.mode;
|
|
540
681
|
}
|
|
541
|
-
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload,
|
|
682
|
+
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, mode === "insensitive" ? eb.fn("lower", [
|
|
683
|
+
fieldRef
|
|
684
|
+
]) : fieldRef, (value) => this.prepStringCasing(eb, value, mode), (value) => this.buildStringFilter(eb, fieldRef, value));
|
|
542
685
|
if (payload && typeof payload === "object") {
|
|
543
686
|
for (const [key, value] of Object.entries(payload)) {
|
|
544
687
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
545
688
|
continue;
|
|
546
689
|
}
|
|
547
|
-
const condition = (0,
|
|
548
|
-
throw new
|
|
690
|
+
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(() => {
|
|
691
|
+
throw new QueryError(`Invalid string filter key: ${key}`);
|
|
549
692
|
});
|
|
550
693
|
if (condition) {
|
|
551
694
|
conditions.push(condition);
|
|
@@ -554,34 +697,37 @@ var BaseCrudDialect = class {
|
|
|
554
697
|
}
|
|
555
698
|
return this.and(eb, ...conditions);
|
|
556
699
|
}
|
|
557
|
-
prepStringCasing(eb, value,
|
|
700
|
+
prepStringCasing(eb, value, mode) {
|
|
701
|
+
if (!mode || mode === "default") {
|
|
702
|
+
return value === null ? value : import_kysely.sql.val(value);
|
|
703
|
+
}
|
|
558
704
|
if (typeof value === "string") {
|
|
559
|
-
return
|
|
560
|
-
import_kysely.sql.
|
|
561
|
-
])
|
|
705
|
+
return eb.fn("lower", [
|
|
706
|
+
import_kysely.sql.val(value)
|
|
707
|
+
]);
|
|
562
708
|
} else if (Array.isArray(value)) {
|
|
563
|
-
return value.map((v) => this.prepStringCasing(eb, v,
|
|
709
|
+
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
564
710
|
} else {
|
|
565
|
-
return value === null ? null : import_kysely.sql.
|
|
711
|
+
return value === null ? null : import_kysely.sql.val(value);
|
|
566
712
|
}
|
|
567
713
|
}
|
|
568
|
-
buildNumberFilter(eb,
|
|
569
|
-
const { conditions } = this.buildStandardFilter(eb, type, payload,
|
|
714
|
+
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
715
|
+
const { conditions } = this.buildStandardFilter(eb, type, payload, fieldRef, (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, fieldRef, type, value));
|
|
570
716
|
return this.and(eb, ...conditions);
|
|
571
717
|
}
|
|
572
|
-
buildBooleanFilter(eb,
|
|
573
|
-
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload,
|
|
718
|
+
buildBooleanFilter(eb, fieldRef, payload) {
|
|
719
|
+
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, fieldRef, (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, fieldRef, value), true, [
|
|
574
720
|
"equals",
|
|
575
721
|
"not"
|
|
576
722
|
]);
|
|
577
723
|
return this.and(eb, ...conditions);
|
|
578
724
|
}
|
|
579
|
-
buildDateTimeFilter(eb,
|
|
580
|
-
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload,
|
|
725
|
+
buildDateTimeFilter(eb, fieldRef, payload) {
|
|
726
|
+
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, fieldRef, (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, fieldRef, value), true);
|
|
581
727
|
return this.and(eb, ...conditions);
|
|
582
728
|
}
|
|
583
|
-
buildBytesFilter(eb,
|
|
584
|
-
const conditions = this.buildStandardFilter(eb, "Bytes", payload,
|
|
729
|
+
buildBytesFilter(eb, fieldRef, payload) {
|
|
730
|
+
const conditions = this.buildStandardFilter(eb, "Bytes", payload, fieldRef, (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, fieldRef, value), true, [
|
|
585
731
|
"equals",
|
|
586
732
|
"in",
|
|
587
733
|
"notIn",
|
|
@@ -589,8 +735,8 @@ var BaseCrudDialect = class {
|
|
|
589
735
|
]);
|
|
590
736
|
return this.and(eb, ...conditions.conditions);
|
|
591
737
|
}
|
|
592
|
-
buildEnumFilter(eb,
|
|
593
|
-
const conditions = this.buildStandardFilter(eb, "String", payload,
|
|
738
|
+
buildEnumFilter(eb, fieldRef, fieldDef, payload) {
|
|
739
|
+
const conditions = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => value, (value) => this.buildEnumFilter(eb, fieldRef, fieldDef, value), true, [
|
|
594
740
|
"equals",
|
|
595
741
|
"in",
|
|
596
742
|
"notIn",
|
|
@@ -619,20 +765,18 @@ var BaseCrudDialect = class {
|
|
|
619
765
|
"_min",
|
|
620
766
|
"_max"
|
|
621
767
|
].includes(field)) {
|
|
622
|
-
(0,
|
|
768
|
+
(0, import_common_helpers.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
623
769
|
for (const [k, v] of Object.entries(value)) {
|
|
624
|
-
(0,
|
|
625
|
-
result = result.orderBy((eb) => eb.
|
|
626
|
-
import_kysely.sql.ref(k)
|
|
627
|
-
]), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
770
|
+
(0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
771
|
+
result = result.orderBy((eb) => aggregate(eb, import_kysely.sql.ref(`${modelAlias}.${k}`), field), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
628
772
|
}
|
|
629
773
|
continue;
|
|
630
774
|
}
|
|
631
775
|
switch (field) {
|
|
632
776
|
case "_count": {
|
|
633
|
-
(0,
|
|
777
|
+
(0, import_common_helpers.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
|
|
634
778
|
for (const [k, v] of Object.entries(value)) {
|
|
635
|
-
(0,
|
|
779
|
+
(0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
636
780
|
result = result.orderBy((eb) => eb.fn.count(import_kysely.sql.ref(k)), import_kysely.sql.raw(this.negateSort(v, negated)));
|
|
637
781
|
}
|
|
638
782
|
continue;
|
|
@@ -654,10 +798,10 @@ var BaseCrudDialect = class {
|
|
|
654
798
|
throw new QueryError(`invalid orderBy value for field "${field}"`);
|
|
655
799
|
}
|
|
656
800
|
if ("_count" in value) {
|
|
657
|
-
(0,
|
|
801
|
+
(0, import_common_helpers.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
658
802
|
const sort = this.negateSort(value._count, negated);
|
|
659
803
|
result = result.orderBy((eb) => {
|
|
660
|
-
let subQuery =
|
|
804
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
661
805
|
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
|
|
662
806
|
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely.sql.ref(left), "=", import_kysely.sql.ref(right)))));
|
|
663
807
|
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
@@ -676,14 +820,90 @@ var BaseCrudDialect = class {
|
|
|
676
820
|
});
|
|
677
821
|
return result;
|
|
678
822
|
}
|
|
823
|
+
buildSelectAllFields(model, query, omit) {
|
|
824
|
+
const modelDef = requireModel(this.schema, model);
|
|
825
|
+
let result = query;
|
|
826
|
+
for (const field of Object.keys(modelDef.fields)) {
|
|
827
|
+
if (isRelationField(this.schema, model, field)) {
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
if (omit?.[field] === true) {
|
|
831
|
+
continue;
|
|
832
|
+
}
|
|
833
|
+
result = this.buildSelectField(result, model, model, field);
|
|
834
|
+
}
|
|
835
|
+
const descendants = getDelegateDescendantModels(this.schema, model);
|
|
836
|
+
for (const subModel of descendants) {
|
|
837
|
+
result = this.buildDelegateJoin(model, subModel.name, result);
|
|
838
|
+
result = result.select((eb) => {
|
|
839
|
+
const jsonObject = {};
|
|
840
|
+
for (const field of Object.keys(subModel.fields)) {
|
|
841
|
+
if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
|
|
842
|
+
continue;
|
|
843
|
+
}
|
|
844
|
+
jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
|
|
845
|
+
}
|
|
846
|
+
return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
return result;
|
|
850
|
+
}
|
|
851
|
+
buildSelectField(query, model, modelAlias, field) {
|
|
852
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
853
|
+
if (fieldDef.computed) {
|
|
854
|
+
return query.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(field));
|
|
855
|
+
} else if (!fieldDef.originModel) {
|
|
856
|
+
return query.select(import_kysely.sql.ref(`${modelAlias}.${field}`).as(field));
|
|
857
|
+
} else {
|
|
858
|
+
return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
buildDelegateJoin(thisModel, otherModel, query) {
|
|
862
|
+
const idFields = getIdFields(this.schema, thisModel);
|
|
863
|
+
query = query.leftJoin(otherModel, (qb) => {
|
|
864
|
+
for (const idField of idFields) {
|
|
865
|
+
qb = qb.onRef(`${thisModel}.${idField}`, "=", `${otherModel}.${idField}`);
|
|
866
|
+
}
|
|
867
|
+
return qb;
|
|
868
|
+
});
|
|
869
|
+
return query;
|
|
870
|
+
}
|
|
871
|
+
buildCountJson(model, eb, parentAlias, payload) {
|
|
872
|
+
const modelDef = requireModel(this.schema, model);
|
|
873
|
+
const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
|
|
874
|
+
const selections = payload === true ? {
|
|
875
|
+
select: toManyRelations.reduce((acc, [field]) => {
|
|
876
|
+
acc[field] = true;
|
|
877
|
+
return acc;
|
|
878
|
+
}, {})
|
|
879
|
+
} : payload;
|
|
880
|
+
const jsonObject = {};
|
|
881
|
+
for (const [field, value] of Object.entries(selections.select)) {
|
|
882
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
883
|
+
const fieldModel = fieldDef.type;
|
|
884
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
885
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
886
|
+
for (const [left, right] of joinPairs) {
|
|
887
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
888
|
+
}
|
|
889
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
890
|
+
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
891
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
892
|
+
}
|
|
893
|
+
jsonObject[field] = fieldCountQuery;
|
|
894
|
+
}
|
|
895
|
+
return this.buildJsonObject(eb, jsonObject);
|
|
896
|
+
}
|
|
897
|
+
// #endregion
|
|
898
|
+
// #region utils
|
|
679
899
|
negateSort(sort, negated) {
|
|
680
900
|
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
681
901
|
}
|
|
682
902
|
true(eb) {
|
|
683
|
-
return eb.lit(this.transformPrimitive(true, "Boolean"));
|
|
903
|
+
return eb.lit(this.transformPrimitive(true, "Boolean", false));
|
|
684
904
|
}
|
|
685
905
|
false(eb) {
|
|
686
|
-
return eb.lit(this.transformPrimitive(false, "Boolean"));
|
|
906
|
+
return eb.lit(this.transformPrimitive(false, "Boolean", false));
|
|
687
907
|
}
|
|
688
908
|
isTrue(expression) {
|
|
689
909
|
const node = expression.toOperationNode();
|
|
@@ -732,14 +952,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
732
952
|
get provider() {
|
|
733
953
|
return "postgresql";
|
|
734
954
|
}
|
|
735
|
-
transformPrimitive(value, type) {
|
|
955
|
+
transformPrimitive(value, type, forArrayField) {
|
|
736
956
|
if (value === void 0) {
|
|
737
957
|
return value;
|
|
738
958
|
}
|
|
739
959
|
if (Array.isArray(value)) {
|
|
740
|
-
|
|
960
|
+
if (type === "Json" && !forArrayField) {
|
|
961
|
+
return JSON.stringify(value);
|
|
962
|
+
} else {
|
|
963
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
964
|
+
}
|
|
741
965
|
} else {
|
|
742
|
-
return (0,
|
|
966
|
+
return (0, import_ts_pattern3.match)(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
|
|
743
967
|
}
|
|
744
968
|
}
|
|
745
969
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -753,7 +977,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
753
977
|
const joinTableName = `${parentName}$${relationField}`;
|
|
754
978
|
let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
|
|
755
979
|
result = eb.selectFrom(() => {
|
|
756
|
-
let subQuery =
|
|
980
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
981
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
757
982
|
if (payload && typeof payload === "object") {
|
|
758
983
|
if (payload.where) {
|
|
759
984
|
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
@@ -772,8 +997,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
772
997
|
if (m2m) {
|
|
773
998
|
const parentIds = getIdFields(this.schema, model);
|
|
774
999
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
775
|
-
(0,
|
|
776
|
-
(0,
|
|
1000
|
+
(0, import_common_helpers2.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1001
|
+
(0, import_common_helpers2.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
777
1002
|
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentName}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
778
1003
|
} else {
|
|
779
1004
|
const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField, relationModel);
|
|
@@ -797,34 +1022,57 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
797
1022
|
});
|
|
798
1023
|
return qb;
|
|
799
1024
|
}
|
|
800
|
-
buildRelationObjectArgs(relationModel, relationField, eb, payload,
|
|
1025
|
+
buildRelationObjectArgs(relationModel, relationField, eb, payload, parentAlias) {
|
|
801
1026
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
802
1027
|
const objArgs = [];
|
|
1028
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1029
|
+
if (descendantModels.length > 0) {
|
|
1030
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1031
|
+
import_kysely2.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1032
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1033
|
+
]).flatMap((v) => v));
|
|
1034
|
+
}
|
|
803
1035
|
if (payload === true || !payload.select) {
|
|
804
1036
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
805
1037
|
import_kysely2.sql.lit(field),
|
|
806
1038
|
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
807
1039
|
]).flatMap((v) => v));
|
|
808
1040
|
} else if (payload.select) {
|
|
809
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) =>
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
1041
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1042
|
+
if (field === "_count") {
|
|
1043
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1044
|
+
return [
|
|
1045
|
+
import_kysely2.sql.lit(field),
|
|
1046
|
+
subJson
|
|
1047
|
+
];
|
|
1048
|
+
} else {
|
|
1049
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1050
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
|
|
1051
|
+
return [
|
|
1052
|
+
import_kysely2.sql.lit(field),
|
|
1053
|
+
fieldValue
|
|
1054
|
+
];
|
|
1055
|
+
}
|
|
1056
|
+
}).flatMap((v) => v));
|
|
813
1057
|
}
|
|
814
1058
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
815
1059
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
816
1060
|
import_kysely2.sql.lit(field),
|
|
817
|
-
|
|
1061
|
+
// reference the synthesized JSON field
|
|
1062
|
+
eb.ref(`${parentAlias}$${relationField}$${field}.$j`)
|
|
818
1063
|
]).flatMap((v) => v));
|
|
819
1064
|
}
|
|
820
1065
|
return objArgs;
|
|
821
1066
|
}
|
|
822
|
-
buildRelationJoins(
|
|
1067
|
+
buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
|
|
823
1068
|
let result = qb;
|
|
824
|
-
if (typeof payload === "object"
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
1069
|
+
if (typeof payload === "object") {
|
|
1070
|
+
const selectInclude = payload.include ?? payload.select;
|
|
1071
|
+
if (selectInclude && typeof selectInclude === "object") {
|
|
1072
|
+
Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
|
|
1073
|
+
result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
828
1076
|
}
|
|
829
1077
|
return result;
|
|
830
1078
|
}
|
|
@@ -864,12 +1112,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
864
1112
|
return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
|
|
865
1113
|
}
|
|
866
1114
|
}
|
|
1115
|
+
get supportInsertWithDefault() {
|
|
1116
|
+
return true;
|
|
1117
|
+
}
|
|
867
1118
|
};
|
|
868
1119
|
|
|
869
1120
|
// src/client/crud/dialects/sqlite.ts
|
|
1121
|
+
var import_common_helpers3 = require("@zenstackhq/common-helpers");
|
|
870
1122
|
var import_kysely3 = require("kysely");
|
|
871
|
-
var
|
|
872
|
-
var import_ts_pattern3 = require("ts-pattern");
|
|
1123
|
+
var import_ts_pattern4 = require("ts-pattern");
|
|
873
1124
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
874
1125
|
static {
|
|
875
1126
|
__name(this, "SqliteCrudDialect");
|
|
@@ -877,26 +1128,31 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
877
1128
|
get provider() {
|
|
878
1129
|
return "sqlite";
|
|
879
1130
|
}
|
|
880
|
-
transformPrimitive(value, type) {
|
|
1131
|
+
transformPrimitive(value, type, _forArrayField) {
|
|
881
1132
|
if (value === void 0) {
|
|
882
1133
|
return value;
|
|
883
1134
|
}
|
|
884
1135
|
if (Array.isArray(value)) {
|
|
885
|
-
return value.map((v) => this.transformPrimitive(v, type));
|
|
1136
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
886
1137
|
} else {
|
|
887
|
-
|
|
1138
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1139
|
+
return JSON.stringify(value);
|
|
1140
|
+
} else {
|
|
1141
|
+
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);
|
|
1142
|
+
}
|
|
888
1143
|
}
|
|
889
1144
|
}
|
|
890
1145
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
891
1146
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
892
1147
|
}
|
|
893
|
-
buildRelationJSON(model, eb, relationField,
|
|
1148
|
+
buildRelationJSON(model, eb, relationField, parentAlias, payload) {
|
|
894
1149
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
895
1150
|
const relationModel = relationFieldDef.type;
|
|
896
1151
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
897
|
-
const subQueryName = `${
|
|
1152
|
+
const subQueryName = `${parentAlias}$${relationField}`;
|
|
898
1153
|
let tbl = eb.selectFrom(() => {
|
|
899
|
-
let subQuery =
|
|
1154
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
1155
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
900
1156
|
if (payload && typeof payload === "object") {
|
|
901
1157
|
if (payload.where) {
|
|
902
1158
|
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
@@ -915,16 +1171,16 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
915
1171
|
if (m2m) {
|
|
916
1172
|
const parentIds = getIdFields(this.schema, model);
|
|
917
1173
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
918
|
-
(0,
|
|
919
|
-
(0,
|
|
920
|
-
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${
|
|
1174
|
+
(0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1175
|
+
(0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1176
|
+
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
921
1177
|
} else {
|
|
922
1178
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
923
1179
|
keyPairs.forEach(({ fk, pk }) => {
|
|
924
1180
|
if (ownedByModel) {
|
|
925
|
-
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${
|
|
1181
|
+
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentAlias}.${fk}`);
|
|
926
1182
|
} else {
|
|
927
|
-
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${
|
|
1183
|
+
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentAlias}.${pk}`);
|
|
928
1184
|
}
|
|
929
1185
|
});
|
|
930
1186
|
}
|
|
@@ -932,6 +1188,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
932
1188
|
});
|
|
933
1189
|
tbl = tbl.select(() => {
|
|
934
1190
|
const objArgs = [];
|
|
1191
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1192
|
+
if (descendantModels.length > 0) {
|
|
1193
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1194
|
+
import_kysely3.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1195
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1196
|
+
]).flatMap((v) => v));
|
|
1197
|
+
}
|
|
935
1198
|
if (payload === true || !payload.select) {
|
|
936
1199
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
937
1200
|
import_kysely3.sql.lit(field),
|
|
@@ -939,24 +1202,32 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
939
1202
|
]).flatMap((v) => v));
|
|
940
1203
|
} else if (payload.select) {
|
|
941
1204
|
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
|
|
1205
|
+
if (field === "_count") {
|
|
1206
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
945
1207
|
return [
|
|
946
1208
|
import_kysely3.sql.lit(field),
|
|
947
1209
|
subJson
|
|
948
1210
|
];
|
|
949
1211
|
} else {
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
1212
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1213
|
+
if (fieldDef.relation) {
|
|
1214
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1215
|
+
return [
|
|
1216
|
+
import_kysely3.sql.lit(field),
|
|
1217
|
+
subJson
|
|
1218
|
+
];
|
|
1219
|
+
} else {
|
|
1220
|
+
return [
|
|
1221
|
+
import_kysely3.sql.lit(field),
|
|
1222
|
+
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
1223
|
+
];
|
|
1224
|
+
}
|
|
954
1225
|
}
|
|
955
1226
|
}).flatMap((v) => v));
|
|
956
1227
|
}
|
|
957
1228
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
958
1229
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
959
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${
|
|
1230
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
960
1231
|
return [
|
|
961
1232
|
import_kysely3.sql.lit(field),
|
|
962
1233
|
subJson
|
|
@@ -1006,93 +1277,17 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1006
1277
|
buildArrayLiteralSQL(_values) {
|
|
1007
1278
|
throw new Error("SQLite does not support array literals");
|
|
1008
1279
|
}
|
|
1280
|
+
get supportInsertWithDefault() {
|
|
1281
|
+
return false;
|
|
1282
|
+
}
|
|
1009
1283
|
};
|
|
1010
1284
|
|
|
1011
1285
|
// src/client/crud/dialects/index.ts
|
|
1012
1286
|
function getCrudDialect(schema, options) {
|
|
1013
|
-
return (0,
|
|
1287
|
+
return (0, import_ts_pattern5.match)(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
|
|
1014
1288
|
}
|
|
1015
1289
|
__name(getCrudDialect, "getCrudDialect");
|
|
1016
1290
|
|
|
1017
|
-
// src/schema/expression.ts
|
|
1018
|
-
var ExpressionUtils = {
|
|
1019
|
-
literal: /* @__PURE__ */ __name((value) => {
|
|
1020
|
-
return {
|
|
1021
|
-
kind: "literal",
|
|
1022
|
-
value
|
|
1023
|
-
};
|
|
1024
|
-
}, "literal"),
|
|
1025
|
-
array: /* @__PURE__ */ __name((items) => {
|
|
1026
|
-
return {
|
|
1027
|
-
kind: "array",
|
|
1028
|
-
items
|
|
1029
|
-
};
|
|
1030
|
-
}, "array"),
|
|
1031
|
-
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
1032
|
-
return {
|
|
1033
|
-
kind: "call",
|
|
1034
|
-
function: functionName,
|
|
1035
|
-
args
|
|
1036
|
-
};
|
|
1037
|
-
}, "call"),
|
|
1038
|
-
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
1039
|
-
return {
|
|
1040
|
-
kind: "binary",
|
|
1041
|
-
op,
|
|
1042
|
-
left,
|
|
1043
|
-
right
|
|
1044
|
-
};
|
|
1045
|
-
}, "binary"),
|
|
1046
|
-
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
1047
|
-
return {
|
|
1048
|
-
kind: "unary",
|
|
1049
|
-
op,
|
|
1050
|
-
operand
|
|
1051
|
-
};
|
|
1052
|
-
}, "unary"),
|
|
1053
|
-
field: /* @__PURE__ */ __name((field) => {
|
|
1054
|
-
return {
|
|
1055
|
-
kind: "field",
|
|
1056
|
-
field
|
|
1057
|
-
};
|
|
1058
|
-
}, "field"),
|
|
1059
|
-
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
1060
|
-
return {
|
|
1061
|
-
kind: "member",
|
|
1062
|
-
receiver,
|
|
1063
|
-
members
|
|
1064
|
-
};
|
|
1065
|
-
}, "member"),
|
|
1066
|
-
_this: /* @__PURE__ */ __name(() => {
|
|
1067
|
-
return {
|
|
1068
|
-
kind: "this"
|
|
1069
|
-
};
|
|
1070
|
-
}, "_this"),
|
|
1071
|
-
_null: /* @__PURE__ */ __name(() => {
|
|
1072
|
-
return {
|
|
1073
|
-
kind: "null"
|
|
1074
|
-
};
|
|
1075
|
-
}, "_null"),
|
|
1076
|
-
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1077
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
1078
|
-
}, "and"),
|
|
1079
|
-
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1080
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
1081
|
-
}, "or"),
|
|
1082
|
-
is: /* @__PURE__ */ __name((value, kind) => {
|
|
1083
|
-
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
1084
|
-
}, "is"),
|
|
1085
|
-
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
1086
|
-
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
1087
|
-
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
1088
|
-
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
1089
|
-
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
1090
|
-
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
1091
|
-
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
1092
|
-
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
1093
|
-
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
|
|
1094
|
-
};
|
|
1095
|
-
|
|
1096
1291
|
// src/utils/default-operation-node-visitor.ts
|
|
1097
1292
|
var import_kysely4 = require("kysely");
|
|
1098
1293
|
var DefaultOperationNodeVisitor = class extends import_kysely4.OperationNodeVisitor {
|
|
@@ -1412,19 +1607,19 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1412
1607
|
};
|
|
1413
1608
|
|
|
1414
1609
|
// src/plugins/policy/expression-transformer.ts
|
|
1610
|
+
var import_common_helpers5 = require("@zenstackhq/common-helpers");
|
|
1415
1611
|
var import_kysely6 = require("kysely");
|
|
1416
|
-
var
|
|
1417
|
-
var import_ts_pattern6 = require("ts-pattern");
|
|
1612
|
+
var import_ts_pattern7 = require("ts-pattern");
|
|
1418
1613
|
|
|
1419
1614
|
// src/plugins/policy/expression-evaluator.ts
|
|
1420
|
-
var
|
|
1421
|
-
var
|
|
1615
|
+
var import_common_helpers4 = require("@zenstackhq/common-helpers");
|
|
1616
|
+
var import_ts_pattern6 = require("ts-pattern");
|
|
1422
1617
|
var ExpressionEvaluator = class {
|
|
1423
1618
|
static {
|
|
1424
1619
|
__name(this, "ExpressionEvaluator");
|
|
1425
1620
|
}
|
|
1426
1621
|
evaluate(expression, context) {
|
|
1427
|
-
const result = (0,
|
|
1622
|
+
const result = (0, import_ts_pattern6.match)(expression).when(ExpressionUtils.isArray, (expr2) => this.evaluateArray(expr2, context)).when(ExpressionUtils.isBinary, (expr2) => this.evaluateBinary(expr2, context)).when(ExpressionUtils.isField, (expr2) => this.evaluateField(expr2, context)).when(ExpressionUtils.isLiteral, (expr2) => this.evaluateLiteral(expr2)).when(ExpressionUtils.isMember, (expr2) => this.evaluateMember(expr2, context)).when(ExpressionUtils.isUnary, (expr2) => this.evaluateUnary(expr2, context)).when(ExpressionUtils.isCall, (expr2) => this.evaluateCall(expr2, context)).when(ExpressionUtils.isThis, () => context.thisValue).when(ExpressionUtils.isNull, () => null).exhaustive();
|
|
1428
1623
|
return result ?? null;
|
|
1429
1624
|
}
|
|
1430
1625
|
evaluateCall(expr2, context) {
|
|
@@ -1435,7 +1630,7 @@ var ExpressionEvaluator = class {
|
|
|
1435
1630
|
}
|
|
1436
1631
|
}
|
|
1437
1632
|
evaluateUnary(expr2, context) {
|
|
1438
|
-
return (0,
|
|
1633
|
+
return (0, import_ts_pattern6.match)(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
|
|
1439
1634
|
}
|
|
1440
1635
|
evaluateMember(expr2, context) {
|
|
1441
1636
|
let val = this.evaluate(expr2.receiver, context);
|
|
@@ -1459,21 +1654,21 @@ var ExpressionEvaluator = class {
|
|
|
1459
1654
|
}
|
|
1460
1655
|
const left = this.evaluate(expr2.left, context);
|
|
1461
1656
|
const right = this.evaluate(expr2.right, context);
|
|
1462
|
-
return (0,
|
|
1657
|
+
return (0, import_ts_pattern6.match)(expr2.op).with("==", () => left === right).with("!=", () => left !== right).with(">", () => left > right).with(">=", () => left >= right).with("<", () => left < right).with("<=", () => left <= right).with("&&", () => left && right).with("||", () => left || right).with("in", () => {
|
|
1463
1658
|
const _right = right ?? [];
|
|
1464
|
-
(0,
|
|
1659
|
+
(0, import_common_helpers4.invariant)(Array.isArray(_right), 'expected array for "in" operator');
|
|
1465
1660
|
return _right.includes(left);
|
|
1466
1661
|
}).exhaustive();
|
|
1467
1662
|
}
|
|
1468
1663
|
evaluateCollectionPredicate(expr2, context) {
|
|
1469
1664
|
const op = expr2.op;
|
|
1470
|
-
(0,
|
|
1665
|
+
(0, import_common_helpers4.invariant)(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
|
|
1471
1666
|
const left = this.evaluate(expr2.left, context);
|
|
1472
1667
|
if (!left) {
|
|
1473
1668
|
return false;
|
|
1474
1669
|
}
|
|
1475
|
-
(0,
|
|
1476
|
-
return (0,
|
|
1670
|
+
(0, import_common_helpers4.invariant)(Array.isArray(left), "expected array");
|
|
1671
|
+
return (0, import_ts_pattern6.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1477
1672
|
...context,
|
|
1478
1673
|
thisValue: item
|
|
1479
1674
|
}))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
|
|
@@ -1489,11 +1684,11 @@ var ExpressionEvaluator = class {
|
|
|
1489
1684
|
// src/plugins/policy/utils.ts
|
|
1490
1685
|
var import_kysely5 = require("kysely");
|
|
1491
1686
|
function trueNode(dialect) {
|
|
1492
|
-
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
|
|
1687
|
+
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1493
1688
|
}
|
|
1494
1689
|
__name(trueNode, "trueNode");
|
|
1495
1690
|
function falseNode(dialect) {
|
|
1496
|
-
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
|
|
1691
|
+
return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1497
1692
|
}
|
|
1498
1693
|
__name(falseNode, "falseNode");
|
|
1499
1694
|
function isTrueNode(node) {
|
|
@@ -1694,20 +1889,20 @@ var ExpressionTransformer = class {
|
|
|
1694
1889
|
return import_kysely6.BinaryOperationNode.create(left, this.transformOperator(op), right);
|
|
1695
1890
|
}
|
|
1696
1891
|
transformCollectionPredicate(expr2, context) {
|
|
1697
|
-
(0,
|
|
1892
|
+
(0, import_common_helpers5.invariant)(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
|
|
1698
1893
|
if (this.isAuthCall(expr2.left) || this.isAuthMember(expr2.left)) {
|
|
1699
1894
|
const value = new ExpressionEvaluator().evaluate(expr2, {
|
|
1700
1895
|
auth: this.auth
|
|
1701
1896
|
});
|
|
1702
1897
|
return this.transformValue(value, "Boolean");
|
|
1703
1898
|
}
|
|
1704
|
-
(0,
|
|
1899
|
+
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
|
|
1705
1900
|
let newContextModel;
|
|
1706
1901
|
if (ExpressionUtils.isField(expr2.left)) {
|
|
1707
1902
|
const fieldDef = requireField(this.schema, context.model, expr2.left.field);
|
|
1708
1903
|
newContextModel = fieldDef.type;
|
|
1709
1904
|
} else {
|
|
1710
|
-
(0,
|
|
1905
|
+
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left.receiver));
|
|
1711
1906
|
const fieldDef = requireField(this.schema, context.model, expr2.left.receiver.field);
|
|
1712
1907
|
newContextModel = fieldDef.type;
|
|
1713
1908
|
for (const member of expr2.left.members) {
|
|
@@ -1727,7 +1922,7 @@ var ExpressionTransformer = class {
|
|
|
1727
1922
|
const count = import_kysely6.FunctionNode.create("count", [
|
|
1728
1923
|
import_kysely6.ValueNode.createImmediate(1)
|
|
1729
1924
|
]);
|
|
1730
|
-
const predicateResult = (0,
|
|
1925
|
+
const predicateResult = (0, import_ts_pattern7.match)(expr2.op).with("?", () => import_kysely6.BinaryOperationNode.create(count, import_kysely6.OperatorNode.create(">"), import_kysely6.ValueNode.createImmediate(0))).with("!", () => import_kysely6.BinaryOperationNode.create(count, import_kysely6.OperatorNode.create("="), import_kysely6.ValueNode.createImmediate(0))).with("^", () => import_kysely6.BinaryOperationNode.create(count, import_kysely6.OperatorNode.create("="), import_kysely6.ValueNode.createImmediate(0))).exhaustive();
|
|
1731
1926
|
return this.transform(expr2.left, {
|
|
1732
1927
|
...context,
|
|
1733
1928
|
memberSelect: import_kysely6.SelectionNode.create(import_kysely6.AliasNode.create(predicateResult, import_kysely6.IdentifierNode.create("$t"))),
|
|
@@ -1751,14 +1946,14 @@ var ExpressionTransformer = class {
|
|
|
1751
1946
|
}
|
|
1752
1947
|
}
|
|
1753
1948
|
transformValue(value, type) {
|
|
1754
|
-
return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type) ?? null);
|
|
1949
|
+
return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
1755
1950
|
}
|
|
1756
1951
|
_unary(expr2, context) {
|
|
1757
|
-
(0,
|
|
1952
|
+
(0, import_common_helpers5.invariant)(expr2.op === "!", 'only "!" operator is supported');
|
|
1758
1953
|
return import_kysely6.BinaryOperationNode.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
|
|
1759
1954
|
}
|
|
1760
1955
|
transformOperator(op) {
|
|
1761
|
-
const mappedOp = (0,
|
|
1956
|
+
const mappedOp = (0, import_ts_pattern7.match)(op).with("==", () => "=").otherwise(() => op);
|
|
1762
1957
|
return import_kysely6.OperatorNode.create(mappedOp);
|
|
1763
1958
|
}
|
|
1764
1959
|
_call(expr2, context) {
|
|
@@ -1797,10 +1992,10 @@ var ExpressionTransformer = class {
|
|
|
1797
1992
|
if (this.isAuthCall(expr2.receiver)) {
|
|
1798
1993
|
return this.valueMemberAccess(this.auth, expr2, this.authType);
|
|
1799
1994
|
}
|
|
1800
|
-
(0,
|
|
1995
|
+
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.receiver), "expect receiver to be field expression");
|
|
1801
1996
|
const { memberFilter, memberSelect, ...restContext } = context;
|
|
1802
1997
|
const receiver = this.transform(expr2.receiver, restContext);
|
|
1803
|
-
(0,
|
|
1998
|
+
(0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(receiver), "expected receiver to be select query");
|
|
1804
1999
|
const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
|
|
1805
2000
|
const memberFields = [];
|
|
1806
2001
|
let currType = receiverField.type;
|
|
@@ -1824,7 +2019,7 @@ var ExpressionTransformer = class {
|
|
|
1824
2019
|
thisEntity: void 0
|
|
1825
2020
|
});
|
|
1826
2021
|
if (currNode) {
|
|
1827
|
-
(0,
|
|
2022
|
+
(0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(currNode), "expected select query node");
|
|
1828
2023
|
currNode = {
|
|
1829
2024
|
...relation,
|
|
1830
2025
|
selections: [
|
|
@@ -1841,8 +2036,8 @@ var ExpressionTransformer = class {
|
|
|
1841
2036
|
};
|
|
1842
2037
|
}
|
|
1843
2038
|
} else {
|
|
1844
|
-
(0,
|
|
1845
|
-
(0,
|
|
2039
|
+
(0, import_common_helpers5.invariant)(i === expr2.members.length - 1, "plain field access must be the last segment");
|
|
2040
|
+
(0, import_common_helpers5.invariant)(!currNode, "plain field access must be the last segment");
|
|
1846
2041
|
currNode = import_kysely6.ColumnNode.create(member);
|
|
1847
2042
|
}
|
|
1848
2043
|
}
|
|
@@ -1994,7 +2189,7 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
1994
2189
|
get kysely() {
|
|
1995
2190
|
return this.client.$qb;
|
|
1996
2191
|
}
|
|
1997
|
-
async handle(node, proceed
|
|
2192
|
+
async handle(node, proceed) {
|
|
1998
2193
|
if (!this.isCrudQueryNode(node)) {
|
|
1999
2194
|
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
2000
2195
|
}
|
|
@@ -2014,27 +2209,20 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2014
2209
|
if (!mutationRequiresTransaction && !node.returning) {
|
|
2015
2210
|
return proceed(this.transformNode(node));
|
|
2016
2211
|
}
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
const
|
|
2024
|
-
if (
|
|
2025
|
-
|
|
2026
|
-
if (readBackResult.rows.length !== result2.rows.length) {
|
|
2027
|
-
readBackError = true;
|
|
2028
|
-
}
|
|
2029
|
-
return readBackResult;
|
|
2030
|
-
} else {
|
|
2031
|
-
return result2;
|
|
2212
|
+
if (import_kysely7.InsertQueryNode.is(node)) {
|
|
2213
|
+
await this.enforcePreCreatePolicy(node, proceed);
|
|
2214
|
+
}
|
|
2215
|
+
const transformedNode = this.transformNode(node);
|
|
2216
|
+
const result = await proceed(transformedNode);
|
|
2217
|
+
if (!this.onlyReturningId(node)) {
|
|
2218
|
+
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2219
|
+
if (readBackResult.rows.length !== result.rows.length) {
|
|
2220
|
+
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
2032
2221
|
}
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2222
|
+
return readBackResult;
|
|
2223
|
+
} else {
|
|
2224
|
+
return result;
|
|
2036
2225
|
}
|
|
2037
|
-
return result;
|
|
2038
2226
|
}
|
|
2039
2227
|
onlyReturningId(node) {
|
|
2040
2228
|
if (!node.returning) {
|
|
@@ -2087,19 +2275,19 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2087
2275
|
}
|
|
2088
2276
|
}
|
|
2089
2277
|
unwrapCreateValueRow(data, model, fields) {
|
|
2090
|
-
(0,
|
|
2278
|
+
(0, import_common_helpers6.invariant)(data.length === fields.length, "data length must match fields length");
|
|
2091
2279
|
const result = [];
|
|
2092
2280
|
for (let i = 0; i < data.length; i++) {
|
|
2093
2281
|
const item = data[i];
|
|
2094
2282
|
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
2095
2283
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2096
|
-
(0,
|
|
2284
|
+
(0, import_common_helpers6.invariant)(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2097
2285
|
result.push({
|
|
2098
|
-
node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
|
|
2286
|
+
node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2099
2287
|
raw: item.value
|
|
2100
2288
|
});
|
|
2101
2289
|
} else {
|
|
2102
|
-
const value = this.dialect.transformPrimitive(item, fieldDef.type);
|
|
2290
|
+
const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
2103
2291
|
if (Array.isArray(value)) {
|
|
2104
2292
|
result.push({
|
|
2105
2293
|
node: import_kysely7.RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
@@ -2168,7 +2356,7 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2168
2356
|
return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => import_kysely7.BinaryOperationNode.create(import_kysely7.ColumnNode.create(field), import_kysely7.OperatorNode.create("="), import_kysely7.ValueNode.create(row[field]))))));
|
|
2169
2357
|
}
|
|
2170
2358
|
getMutationModel(node) {
|
|
2171
|
-
const r = (0,
|
|
2359
|
+
const r = (0, import_ts_pattern8.match)(node).when(import_kysely7.InsertQueryNode.is, (node2) => getTableName(node2.into)).when(import_kysely7.UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(import_kysely7.DeleteQueryNode.is, (node2) => {
|
|
2172
2360
|
if (node2.from.froms.length !== 1) {
|
|
2173
2361
|
throw new InternalError("Only one from table is supported for delete");
|
|
2174
2362
|
}
|
|
@@ -2301,8 +2489,8 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2301
2489
|
const modelDef = requireModel(this.client.$schema, modelName);
|
|
2302
2490
|
const result = [];
|
|
2303
2491
|
const extractOperations = /* @__PURE__ */ __name((expr2) => {
|
|
2304
|
-
(0,
|
|
2305
|
-
(0,
|
|
2492
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isLiteral(expr2), "expecting a literal");
|
|
2493
|
+
(0, import_common_helpers6.invariant)(typeof expr2.value === "string", "expecting a string literal");
|
|
2306
2494
|
return expr2.value.split(",").filter((v) => !!v).map((v) => v.trim());
|
|
2307
2495
|
}, "extractOperations");
|
|
2308
2496
|
if (modelDef.attributes) {
|
|
@@ -2330,9 +2518,18 @@ var PolicyPlugin = class {
|
|
|
2330
2518
|
get description() {
|
|
2331
2519
|
return "Enforces access policies defined in the schema.";
|
|
2332
2520
|
}
|
|
2333
|
-
onKyselyQuery({
|
|
2521
|
+
onKyselyQuery({
|
|
2522
|
+
query,
|
|
2523
|
+
client,
|
|
2524
|
+
proceed
|
|
2525
|
+
/*, transaction*/
|
|
2526
|
+
}) {
|
|
2334
2527
|
const handler = new PolicyHandler(client);
|
|
2335
|
-
return handler.handle(
|
|
2528
|
+
return handler.handle(
|
|
2529
|
+
query,
|
|
2530
|
+
proceed
|
|
2531
|
+
/*, transaction*/
|
|
2532
|
+
);
|
|
2336
2533
|
}
|
|
2337
2534
|
};
|
|
2338
2535
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -2340,4 +2537,4 @@ var PolicyPlugin = class {
|
|
|
2340
2537
|
PolicyPlugin,
|
|
2341
2538
|
RejectedByPolicyError
|
|
2342
2539
|
});
|
|
2343
|
-
//# sourceMappingURL=
|
|
2540
|
+
//# sourceMappingURL=index.cjs.map
|