@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
|
@@ -14,34 +14,130 @@ var RejectedByPolicyError = class extends Error {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
// src/plugins/policy/policy-handler.ts
|
|
17
|
+
import { invariant as invariant6 } from "@zenstackhq/common-helpers";
|
|
17
18
|
import { AliasNode as AliasNode3, BinaryOperationNode as BinaryOperationNode3, ColumnNode as ColumnNode2, DeleteQueryNode, FromNode as FromNode2, IdentifierNode as IdentifierNode2, InsertQueryNode, OperationNodeTransformer, OperatorNode as OperatorNode3, PrimitiveValueListNode, RawNode, ReturningNode, SelectionNode as SelectionNode2, SelectQueryNode as SelectQueryNode2, TableNode as TableNode3, UpdateQueryNode, ValueNode as ValueNode3, ValuesNode, WhereNode as WhereNode2 } from "kysely";
|
|
18
|
-
import
|
|
19
|
-
import { match as match7 } from "ts-pattern";
|
|
19
|
+
import { match as match8 } from "ts-pattern";
|
|
20
20
|
|
|
21
21
|
// src/client/crud/dialects/index.ts
|
|
22
|
-
import { match as
|
|
22
|
+
import { match as match5 } from "ts-pattern";
|
|
23
23
|
|
|
24
24
|
// src/client/crud/dialects/postgresql.ts
|
|
25
|
+
import { invariant as invariant2 } from "@zenstackhq/common-helpers";
|
|
25
26
|
import { sql as sql2 } from "kysely";
|
|
26
|
-
import
|
|
27
|
-
|
|
27
|
+
import { match as match3 } from "ts-pattern";
|
|
28
|
+
|
|
29
|
+
// src/client/constants.ts
|
|
30
|
+
var DELEGATE_JOINED_FIELD_PREFIX = "$delegate$";
|
|
31
|
+
var LOGICAL_COMBINATORS = [
|
|
32
|
+
"AND",
|
|
33
|
+
"OR",
|
|
34
|
+
"NOT"
|
|
35
|
+
];
|
|
36
|
+
var AGGREGATE_OPERATORS = [
|
|
37
|
+
"_count",
|
|
38
|
+
"_sum",
|
|
39
|
+
"_avg",
|
|
40
|
+
"_min",
|
|
41
|
+
"_max"
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
// src/client/query-utils.ts
|
|
45
|
+
import { match } from "ts-pattern";
|
|
46
|
+
|
|
47
|
+
// src/schema/expression.ts
|
|
48
|
+
var ExpressionUtils = {
|
|
49
|
+
literal: /* @__PURE__ */ __name((value) => {
|
|
50
|
+
return {
|
|
51
|
+
kind: "literal",
|
|
52
|
+
value
|
|
53
|
+
};
|
|
54
|
+
}, "literal"),
|
|
55
|
+
array: /* @__PURE__ */ __name((items) => {
|
|
56
|
+
return {
|
|
57
|
+
kind: "array",
|
|
58
|
+
items
|
|
59
|
+
};
|
|
60
|
+
}, "array"),
|
|
61
|
+
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
62
|
+
return {
|
|
63
|
+
kind: "call",
|
|
64
|
+
function: functionName,
|
|
65
|
+
args
|
|
66
|
+
};
|
|
67
|
+
}, "call"),
|
|
68
|
+
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
69
|
+
return {
|
|
70
|
+
kind: "binary",
|
|
71
|
+
op,
|
|
72
|
+
left,
|
|
73
|
+
right
|
|
74
|
+
};
|
|
75
|
+
}, "binary"),
|
|
76
|
+
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
77
|
+
return {
|
|
78
|
+
kind: "unary",
|
|
79
|
+
op,
|
|
80
|
+
operand
|
|
81
|
+
};
|
|
82
|
+
}, "unary"),
|
|
83
|
+
field: /* @__PURE__ */ __name((field) => {
|
|
84
|
+
return {
|
|
85
|
+
kind: "field",
|
|
86
|
+
field
|
|
87
|
+
};
|
|
88
|
+
}, "field"),
|
|
89
|
+
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
90
|
+
return {
|
|
91
|
+
kind: "member",
|
|
92
|
+
receiver,
|
|
93
|
+
members
|
|
94
|
+
};
|
|
95
|
+
}, "member"),
|
|
96
|
+
_this: /* @__PURE__ */ __name(() => {
|
|
97
|
+
return {
|
|
98
|
+
kind: "this"
|
|
99
|
+
};
|
|
100
|
+
}, "_this"),
|
|
101
|
+
_null: /* @__PURE__ */ __name(() => {
|
|
102
|
+
return {
|
|
103
|
+
kind: "null"
|
|
104
|
+
};
|
|
105
|
+
}, "_null"),
|
|
106
|
+
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
107
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
108
|
+
}, "and"),
|
|
109
|
+
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
110
|
+
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
111
|
+
}, "or"),
|
|
112
|
+
is: /* @__PURE__ */ __name((value, kind) => {
|
|
113
|
+
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
114
|
+
}, "is"),
|
|
115
|
+
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
116
|
+
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
117
|
+
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
118
|
+
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
119
|
+
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
120
|
+
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
121
|
+
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
122
|
+
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
123
|
+
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
|
|
124
|
+
};
|
|
28
125
|
|
|
29
126
|
// src/client/errors.ts
|
|
30
127
|
var QueryError = class extends Error {
|
|
31
128
|
static {
|
|
32
129
|
__name(this, "QueryError");
|
|
33
130
|
}
|
|
34
|
-
constructor(message) {
|
|
35
|
-
super(message
|
|
131
|
+
constructor(message, cause) {
|
|
132
|
+
super(message, {
|
|
133
|
+
cause
|
|
134
|
+
});
|
|
36
135
|
}
|
|
37
136
|
};
|
|
38
137
|
var InternalError = class extends Error {
|
|
39
138
|
static {
|
|
40
139
|
__name(this, "InternalError");
|
|
41
140
|
}
|
|
42
|
-
constructor(message) {
|
|
43
|
-
super(message);
|
|
44
|
-
}
|
|
45
141
|
};
|
|
46
142
|
|
|
47
143
|
// src/client/query-utils.ts
|
|
@@ -52,7 +148,7 @@ __name(getModel, "getModel");
|
|
|
52
148
|
function requireModel(schema, model) {
|
|
53
149
|
const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
|
|
54
150
|
if (!matchedName) {
|
|
55
|
-
throw new QueryError(`Model "${model}" not found`);
|
|
151
|
+
throw new QueryError(`Model "${model}" not found in schema`);
|
|
56
152
|
}
|
|
57
153
|
return schema.models[matchedName];
|
|
58
154
|
}
|
|
@@ -115,6 +211,16 @@ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
|
115
211
|
}
|
|
116
212
|
}
|
|
117
213
|
__name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
|
|
214
|
+
function isRelationField(schema, model, field) {
|
|
215
|
+
const fieldDef = getField(schema, model, field);
|
|
216
|
+
return !!fieldDef?.relation;
|
|
217
|
+
}
|
|
218
|
+
__name(isRelationField, "isRelationField");
|
|
219
|
+
function isInheritedField(schema, model, field) {
|
|
220
|
+
const fieldDef = getField(schema, model, field);
|
|
221
|
+
return !!fieldDef?.originModel;
|
|
222
|
+
}
|
|
223
|
+
__name(isInheritedField, "isInheritedField");
|
|
118
224
|
function getUniqueFields(schema, model) {
|
|
119
225
|
const modelDef = requireModel(schema, model);
|
|
120
226
|
const result = [];
|
|
@@ -151,7 +257,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias) {
|
|
|
151
257
|
computer = computedFields?.[model]?.[field];
|
|
152
258
|
}
|
|
153
259
|
if (!computer) {
|
|
154
|
-
throw new QueryError(`Computed field "${field}" implementation not provided`);
|
|
260
|
+
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
155
261
|
}
|
|
156
262
|
return computer(eb);
|
|
157
263
|
}
|
|
@@ -228,11 +334,28 @@ function flattenCompoundUniqueFilters(schema, model, filter) {
|
|
|
228
334
|
return result;
|
|
229
335
|
}
|
|
230
336
|
__name(flattenCompoundUniqueFilters, "flattenCompoundUniqueFilters");
|
|
337
|
+
function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */ new Set()) {
|
|
338
|
+
const subModels = Object.values(schema.models).filter((m) => m.baseModel === model);
|
|
339
|
+
subModels.forEach((def) => {
|
|
340
|
+
if (!collected.has(def)) {
|
|
341
|
+
collected.add(def);
|
|
342
|
+
getDelegateDescendantModels(schema, def.name, collected);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
return [
|
|
346
|
+
...collected
|
|
347
|
+
];
|
|
348
|
+
}
|
|
349
|
+
__name(getDelegateDescendantModels, "getDelegateDescendantModels");
|
|
350
|
+
function aggregate(eb, expr2, op) {
|
|
351
|
+
return match(op).with("_count", () => eb.fn.count(expr2)).with("_sum", () => eb.fn.sum(expr2)).with("_avg", () => eb.fn.avg(expr2)).with("_min", () => eb.fn.min(expr2)).with("_max", () => eb.fn.max(expr2)).exhaustive();
|
|
352
|
+
}
|
|
353
|
+
__name(aggregate, "aggregate");
|
|
231
354
|
|
|
232
355
|
// src/client/crud/dialects/base.ts
|
|
356
|
+
import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
|
|
233
357
|
import { sql } from "kysely";
|
|
234
|
-
import
|
|
235
|
-
import { match, P } from "ts-pattern";
|
|
358
|
+
import { match as match2, P } from "ts-pattern";
|
|
236
359
|
|
|
237
360
|
// src/utils/enumerate.ts
|
|
238
361
|
function enumerate(x) {
|
|
@@ -249,7 +372,6 @@ function enumerate(x) {
|
|
|
249
372
|
__name(enumerate, "enumerate");
|
|
250
373
|
|
|
251
374
|
// src/client/crud/dialects/base.ts
|
|
252
|
-
import { isPlainObject } from "is-plain-object";
|
|
253
375
|
var BaseCrudDialect = class {
|
|
254
376
|
static {
|
|
255
377
|
__name(this, "BaseCrudDialect");
|
|
@@ -260,9 +382,20 @@ var BaseCrudDialect = class {
|
|
|
260
382
|
this.schema = schema;
|
|
261
383
|
this.options = options;
|
|
262
384
|
}
|
|
263
|
-
transformPrimitive(value, _type) {
|
|
385
|
+
transformPrimitive(value, _type, _forArrayField) {
|
|
264
386
|
return value;
|
|
265
387
|
}
|
|
388
|
+
// #region common query builders
|
|
389
|
+
buildSelectModel(eb, model) {
|
|
390
|
+
const modelDef = requireModel(this.schema, model);
|
|
391
|
+
let result = eb.selectFrom(model);
|
|
392
|
+
let joinBase = modelDef.baseModel;
|
|
393
|
+
while (joinBase) {
|
|
394
|
+
result = this.buildDelegateJoin(model, joinBase, result);
|
|
395
|
+
joinBase = requireModel(this.schema, joinBase).baseModel;
|
|
396
|
+
}
|
|
397
|
+
return result;
|
|
398
|
+
}
|
|
266
399
|
buildFilter(eb, model, modelAlias, where) {
|
|
267
400
|
if (where === true || where === void 0) {
|
|
268
401
|
return this.true(eb);
|
|
@@ -279,17 +412,20 @@ var BaseCrudDialect = class {
|
|
|
279
412
|
if (key.startsWith("$")) {
|
|
280
413
|
continue;
|
|
281
414
|
}
|
|
282
|
-
if (key
|
|
415
|
+
if (this.isLogicalCombinator(key)) {
|
|
283
416
|
result = this.and(eb, result, this.buildCompositeFilter(eb, model, modelAlias, key, payload));
|
|
284
417
|
continue;
|
|
285
418
|
}
|
|
286
419
|
const fieldDef = requireField(this.schema, model, key);
|
|
287
420
|
if (fieldDef.relation) {
|
|
288
421
|
result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
289
|
-
} else if (fieldDef.array) {
|
|
290
|
-
result = this.and(eb, result, this.buildArrayFilter(eb, model, modelAlias, key, fieldDef, payload));
|
|
291
422
|
} else {
|
|
292
|
-
|
|
423
|
+
const fieldRef = buildFieldRef(this.schema, fieldDef.originModel ?? model, key, this.options, eb, fieldDef.originModel ?? modelAlias);
|
|
424
|
+
if (fieldDef.array) {
|
|
425
|
+
result = this.and(eb, result, this.buildArrayFilter(eb, fieldRef, fieldDef, payload));
|
|
426
|
+
} else {
|
|
427
|
+
result = this.and(eb, result, this.buildPrimitiveFilter(eb, fieldRef, fieldDef, payload));
|
|
428
|
+
}
|
|
293
429
|
}
|
|
294
430
|
}
|
|
295
431
|
if ("$expr" in _where && typeof _where["$expr"] === "function") {
|
|
@@ -297,8 +433,11 @@ var BaseCrudDialect = class {
|
|
|
297
433
|
}
|
|
298
434
|
return result;
|
|
299
435
|
}
|
|
436
|
+
isLogicalCombinator(key) {
|
|
437
|
+
return LOGICAL_COMBINATORS.includes(key);
|
|
438
|
+
}
|
|
300
439
|
buildCompositeFilter(eb, model, modelAlias, key, payload) {
|
|
301
|
-
return
|
|
440
|
+
return match2(key).with("AND", () => this.and(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("OR", () => this.or(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("NOT", () => eb.not(this.buildCompositeFilter(eb, model, modelAlias, "AND", payload))).exhaustive();
|
|
302
441
|
}
|
|
303
442
|
buildRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
304
443
|
if (!fieldDef.array) {
|
|
@@ -307,19 +446,26 @@ var BaseCrudDialect = class {
|
|
|
307
446
|
return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
|
|
308
447
|
}
|
|
309
448
|
}
|
|
310
|
-
buildToOneRelationFilter(eb, model,
|
|
449
|
+
buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
311
450
|
if (payload === null) {
|
|
312
451
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
313
|
-
if (ownedByModel) {
|
|
314
|
-
return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${
|
|
452
|
+
if (ownedByModel && !fieldDef.originModel) {
|
|
453
|
+
return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${modelAlias}.${fk}`), "is", null)));
|
|
315
454
|
} else {
|
|
316
|
-
return this.buildToOneRelationFilter(eb, model,
|
|
455
|
+
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
|
|
317
456
|
is: null
|
|
318
457
|
});
|
|
319
458
|
}
|
|
320
459
|
}
|
|
321
|
-
const joinAlias = `${
|
|
322
|
-
const joinPairs = buildJoinPairs(
|
|
460
|
+
const joinAlias = `${modelAlias}$${field}`;
|
|
461
|
+
const joinPairs = buildJoinPairs(
|
|
462
|
+
this.schema,
|
|
463
|
+
model,
|
|
464
|
+
// if field is from a base, use the base model to join
|
|
465
|
+
fieldDef.originModel ?? modelAlias,
|
|
466
|
+
field,
|
|
467
|
+
joinAlias
|
|
468
|
+
);
|
|
323
469
|
const filterResultField = `${field}$filter`;
|
|
324
470
|
const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
|
|
325
471
|
const conditions = [];
|
|
@@ -380,30 +526,29 @@ var BaseCrudDialect = class {
|
|
|
380
526
|
}
|
|
381
527
|
switch (key) {
|
|
382
528
|
case "some": {
|
|
383
|
-
result = this.and(eb, result, eb(
|
|
529
|
+
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));
|
|
384
530
|
break;
|
|
385
531
|
}
|
|
386
532
|
case "every": {
|
|
387
|
-
result = this.and(eb, result, eb(
|
|
533
|
+
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));
|
|
388
534
|
break;
|
|
389
535
|
}
|
|
390
536
|
case "none": {
|
|
391
|
-
result = this.and(eb, result, eb(
|
|
537
|
+
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));
|
|
392
538
|
break;
|
|
393
539
|
}
|
|
394
540
|
}
|
|
395
541
|
}
|
|
396
542
|
return result;
|
|
397
543
|
}
|
|
398
|
-
buildArrayFilter(eb,
|
|
544
|
+
buildArrayFilter(eb, fieldRef, fieldDef, payload) {
|
|
399
545
|
const clauses = [];
|
|
400
546
|
const fieldType = fieldDef.type;
|
|
401
|
-
const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
|
|
402
547
|
for (const [key, _value] of Object.entries(payload)) {
|
|
403
548
|
if (_value === void 0) {
|
|
404
549
|
continue;
|
|
405
550
|
}
|
|
406
|
-
const value = this.transformPrimitive(_value, fieldType);
|
|
551
|
+
const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
|
|
407
552
|
switch (key) {
|
|
408
553
|
case "equals": {
|
|
409
554
|
clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
|
|
@@ -434,19 +579,23 @@ var BaseCrudDialect = class {
|
|
|
434
579
|
}
|
|
435
580
|
return this.and(eb, ...clauses);
|
|
436
581
|
}
|
|
437
|
-
buildPrimitiveFilter(eb,
|
|
582
|
+
buildPrimitiveFilter(eb, fieldRef, fieldDef, payload) {
|
|
438
583
|
if (payload === null) {
|
|
439
|
-
return eb(
|
|
584
|
+
return eb(fieldRef, "is", null);
|
|
440
585
|
}
|
|
441
586
|
if (isEnum(this.schema, fieldDef.type)) {
|
|
442
|
-
return this.buildEnumFilter(eb,
|
|
587
|
+
return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
|
|
443
588
|
}
|
|
444
|
-
return
|
|
589
|
+
return match2(fieldDef.type).with("String", () => this.buildStringFilter(eb, fieldRef, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, fieldRef, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, fieldRef, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, fieldRef, payload)).with("Bytes", () => this.buildBytesFilter(eb, fieldRef, payload)).with("Json", () => {
|
|
590
|
+
throw new InternalError("JSON filters are not supported yet");
|
|
591
|
+
}).with("Unsupported", () => {
|
|
592
|
+
throw new QueryError(`Unsupported field cannot be used in filters`);
|
|
593
|
+
}).exhaustive();
|
|
445
594
|
}
|
|
446
595
|
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
447
|
-
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
|
|
596
|
+
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
448
597
|
}
|
|
449
|
-
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
|
|
598
|
+
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
450
599
|
if (payload === null || !isPlainObject(payload)) {
|
|
451
600
|
return {
|
|
452
601
|
conditions: [
|
|
@@ -461,8 +610,11 @@ var BaseCrudDialect = class {
|
|
|
461
610
|
if (onlyForKeys && !onlyForKeys.includes(op)) {
|
|
462
611
|
continue;
|
|
463
612
|
}
|
|
613
|
+
if (excludeKeys.includes(op)) {
|
|
614
|
+
continue;
|
|
615
|
+
}
|
|
464
616
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
465
|
-
const condition =
|
|
617
|
+
const condition = match2(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
466
618
|
invariant(Array.isArray(rhs), "right hand side must be an array");
|
|
467
619
|
if (rhs.length === 0) {
|
|
468
620
|
return this.false(eb);
|
|
@@ -476,7 +628,11 @@ var BaseCrudDialect = class {
|
|
|
476
628
|
} else {
|
|
477
629
|
return eb.not(eb(lhs, "in", rhs));
|
|
478
630
|
}
|
|
479
|
-
}).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))).
|
|
631
|
+
}).with("lt", () => eb(lhs, "<", rhs)).with("lte", () => eb(lhs, "<=", rhs)).with("gt", () => eb(lhs, ">", rhs)).with("gte", () => eb(lhs, ">=", rhs)).with("not", () => eb.not(recurse(value))).with(P.union(...AGGREGATE_OPERATORS), (op2) => {
|
|
632
|
+
const innerResult = this.buildStandardFilter(eb, type, value, aggregate(eb, lhs, op2), getRhs, recurse, throwIfInvalid);
|
|
633
|
+
consumedKeys.push(...innerResult.consumedKeys);
|
|
634
|
+
return this.and(eb, ...innerResult.conditions);
|
|
635
|
+
}).otherwise(() => {
|
|
480
636
|
if (throwIfInvalid) {
|
|
481
637
|
throw new QueryError(`Invalid filter key: ${op}`);
|
|
482
638
|
} else {
|
|
@@ -493,24 +649,21 @@ var BaseCrudDialect = class {
|
|
|
493
649
|
consumedKeys
|
|
494
650
|
};
|
|
495
651
|
}
|
|
496
|
-
buildStringFilter(eb,
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
if (payload && typeof payload === "object" && "mode" in payload && payload.mode === "insensitive") {
|
|
501
|
-
insensitive = true;
|
|
502
|
-
fieldRef = eb.fn("lower", [
|
|
503
|
-
fieldRef
|
|
504
|
-
]);
|
|
652
|
+
buildStringFilter(eb, fieldRef, payload) {
|
|
653
|
+
let mode;
|
|
654
|
+
if (payload && typeof payload === "object" && "mode" in payload) {
|
|
655
|
+
mode = payload.mode;
|
|
505
656
|
}
|
|
506
|
-
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload,
|
|
657
|
+
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, mode === "insensitive" ? eb.fn("lower", [
|
|
658
|
+
fieldRef
|
|
659
|
+
]) : fieldRef, (value) => this.prepStringCasing(eb, value, mode), (value) => this.buildStringFilter(eb, fieldRef, value));
|
|
507
660
|
if (payload && typeof payload === "object") {
|
|
508
661
|
for (const [key, value] of Object.entries(payload)) {
|
|
509
662
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
510
663
|
continue;
|
|
511
664
|
}
|
|
512
|
-
const condition =
|
|
513
|
-
throw new
|
|
665
|
+
const condition = match2(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`%${value}%`)) : eb(fieldRef, "like", sql.val(`%${value}%`))).with("startsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`${value}%`)) : eb(fieldRef, "like", sql.val(`${value}%`))).with("endsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`%${value}`)) : eb(fieldRef, "like", sql.val(`%${value}`))).otherwise(() => {
|
|
666
|
+
throw new QueryError(`Invalid string filter key: ${key}`);
|
|
514
667
|
});
|
|
515
668
|
if (condition) {
|
|
516
669
|
conditions.push(condition);
|
|
@@ -519,34 +672,37 @@ var BaseCrudDialect = class {
|
|
|
519
672
|
}
|
|
520
673
|
return this.and(eb, ...conditions);
|
|
521
674
|
}
|
|
522
|
-
prepStringCasing(eb, value,
|
|
675
|
+
prepStringCasing(eb, value, mode) {
|
|
676
|
+
if (!mode || mode === "default") {
|
|
677
|
+
return value === null ? value : sql.val(value);
|
|
678
|
+
}
|
|
523
679
|
if (typeof value === "string") {
|
|
524
|
-
return
|
|
525
|
-
sql.
|
|
526
|
-
])
|
|
680
|
+
return eb.fn("lower", [
|
|
681
|
+
sql.val(value)
|
|
682
|
+
]);
|
|
527
683
|
} else if (Array.isArray(value)) {
|
|
528
|
-
return value.map((v) => this.prepStringCasing(eb, v,
|
|
684
|
+
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
529
685
|
} else {
|
|
530
|
-
return value === null ? null : sql.
|
|
686
|
+
return value === null ? null : sql.val(value);
|
|
531
687
|
}
|
|
532
688
|
}
|
|
533
|
-
buildNumberFilter(eb,
|
|
534
|
-
const { conditions } = this.buildStandardFilter(eb, type, payload,
|
|
689
|
+
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
690
|
+
const { conditions } = this.buildStandardFilter(eb, type, payload, fieldRef, (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, fieldRef, type, value));
|
|
535
691
|
return this.and(eb, ...conditions);
|
|
536
692
|
}
|
|
537
|
-
buildBooleanFilter(eb,
|
|
538
|
-
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload,
|
|
693
|
+
buildBooleanFilter(eb, fieldRef, payload) {
|
|
694
|
+
const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, fieldRef, (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, fieldRef, value), true, [
|
|
539
695
|
"equals",
|
|
540
696
|
"not"
|
|
541
697
|
]);
|
|
542
698
|
return this.and(eb, ...conditions);
|
|
543
699
|
}
|
|
544
|
-
buildDateTimeFilter(eb,
|
|
545
|
-
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload,
|
|
700
|
+
buildDateTimeFilter(eb, fieldRef, payload) {
|
|
701
|
+
const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, fieldRef, (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, fieldRef, value), true);
|
|
546
702
|
return this.and(eb, ...conditions);
|
|
547
703
|
}
|
|
548
|
-
buildBytesFilter(eb,
|
|
549
|
-
const conditions = this.buildStandardFilter(eb, "Bytes", payload,
|
|
704
|
+
buildBytesFilter(eb, fieldRef, payload) {
|
|
705
|
+
const conditions = this.buildStandardFilter(eb, "Bytes", payload, fieldRef, (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, fieldRef, value), true, [
|
|
550
706
|
"equals",
|
|
551
707
|
"in",
|
|
552
708
|
"notIn",
|
|
@@ -554,8 +710,8 @@ var BaseCrudDialect = class {
|
|
|
554
710
|
]);
|
|
555
711
|
return this.and(eb, ...conditions.conditions);
|
|
556
712
|
}
|
|
557
|
-
buildEnumFilter(eb,
|
|
558
|
-
const conditions = this.buildStandardFilter(eb, "String", payload,
|
|
713
|
+
buildEnumFilter(eb, fieldRef, fieldDef, payload) {
|
|
714
|
+
const conditions = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => value, (value) => this.buildEnumFilter(eb, fieldRef, fieldDef, value), true, [
|
|
559
715
|
"equals",
|
|
560
716
|
"in",
|
|
561
717
|
"notIn",
|
|
@@ -587,9 +743,7 @@ var BaseCrudDialect = class {
|
|
|
587
743
|
invariant(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
588
744
|
for (const [k, v] of Object.entries(value)) {
|
|
589
745
|
invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
590
|
-
result = result.orderBy((eb) => eb.
|
|
591
|
-
sql.ref(k)
|
|
592
|
-
]), sql.raw(this.negateSort(v, negated)));
|
|
746
|
+
result = result.orderBy((eb) => aggregate(eb, sql.ref(`${modelAlias}.${k}`), field), sql.raw(this.negateSort(v, negated)));
|
|
593
747
|
}
|
|
594
748
|
continue;
|
|
595
749
|
}
|
|
@@ -622,7 +776,7 @@ var BaseCrudDialect = class {
|
|
|
622
776
|
invariant(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
623
777
|
const sort = this.negateSort(value._count, negated);
|
|
624
778
|
result = result.orderBy((eb) => {
|
|
625
|
-
let subQuery =
|
|
779
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
626
780
|
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
|
|
627
781
|
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right)))));
|
|
628
782
|
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
@@ -641,14 +795,90 @@ var BaseCrudDialect = class {
|
|
|
641
795
|
});
|
|
642
796
|
return result;
|
|
643
797
|
}
|
|
798
|
+
buildSelectAllFields(model, query, omit) {
|
|
799
|
+
const modelDef = requireModel(this.schema, model);
|
|
800
|
+
let result = query;
|
|
801
|
+
for (const field of Object.keys(modelDef.fields)) {
|
|
802
|
+
if (isRelationField(this.schema, model, field)) {
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
if (omit?.[field] === true) {
|
|
806
|
+
continue;
|
|
807
|
+
}
|
|
808
|
+
result = this.buildSelectField(result, model, model, field);
|
|
809
|
+
}
|
|
810
|
+
const descendants = getDelegateDescendantModels(this.schema, model);
|
|
811
|
+
for (const subModel of descendants) {
|
|
812
|
+
result = this.buildDelegateJoin(model, subModel.name, result);
|
|
813
|
+
result = result.select((eb) => {
|
|
814
|
+
const jsonObject = {};
|
|
815
|
+
for (const field of Object.keys(subModel.fields)) {
|
|
816
|
+
if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
819
|
+
jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
|
|
820
|
+
}
|
|
821
|
+
return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
return result;
|
|
825
|
+
}
|
|
826
|
+
buildSelectField(query, model, modelAlias, field) {
|
|
827
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
828
|
+
if (fieldDef.computed) {
|
|
829
|
+
return query.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(field));
|
|
830
|
+
} else if (!fieldDef.originModel) {
|
|
831
|
+
return query.select(sql.ref(`${modelAlias}.${field}`).as(field));
|
|
832
|
+
} else {
|
|
833
|
+
return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
buildDelegateJoin(thisModel, otherModel, query) {
|
|
837
|
+
const idFields = getIdFields(this.schema, thisModel);
|
|
838
|
+
query = query.leftJoin(otherModel, (qb) => {
|
|
839
|
+
for (const idField of idFields) {
|
|
840
|
+
qb = qb.onRef(`${thisModel}.${idField}`, "=", `${otherModel}.${idField}`);
|
|
841
|
+
}
|
|
842
|
+
return qb;
|
|
843
|
+
});
|
|
844
|
+
return query;
|
|
845
|
+
}
|
|
846
|
+
buildCountJson(model, eb, parentAlias, payload) {
|
|
847
|
+
const modelDef = requireModel(this.schema, model);
|
|
848
|
+
const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
|
|
849
|
+
const selections = payload === true ? {
|
|
850
|
+
select: toManyRelations.reduce((acc, [field]) => {
|
|
851
|
+
acc[field] = true;
|
|
852
|
+
return acc;
|
|
853
|
+
}, {})
|
|
854
|
+
} : payload;
|
|
855
|
+
const jsonObject = {};
|
|
856
|
+
for (const [field, value] of Object.entries(selections.select)) {
|
|
857
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
858
|
+
const fieldModel = fieldDef.type;
|
|
859
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
860
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
861
|
+
for (const [left, right] of joinPairs) {
|
|
862
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
863
|
+
}
|
|
864
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
865
|
+
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
866
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
867
|
+
}
|
|
868
|
+
jsonObject[field] = fieldCountQuery;
|
|
869
|
+
}
|
|
870
|
+
return this.buildJsonObject(eb, jsonObject);
|
|
871
|
+
}
|
|
872
|
+
// #endregion
|
|
873
|
+
// #region utils
|
|
644
874
|
negateSort(sort, negated) {
|
|
645
875
|
return negated ? sort === "asc" ? "desc" : "asc" : sort;
|
|
646
876
|
}
|
|
647
877
|
true(eb) {
|
|
648
|
-
return eb.lit(this.transformPrimitive(true, "Boolean"));
|
|
878
|
+
return eb.lit(this.transformPrimitive(true, "Boolean", false));
|
|
649
879
|
}
|
|
650
880
|
false(eb) {
|
|
651
|
-
return eb.lit(this.transformPrimitive(false, "Boolean"));
|
|
881
|
+
return eb.lit(this.transformPrimitive(false, "Boolean", false));
|
|
652
882
|
}
|
|
653
883
|
isTrue(expression) {
|
|
654
884
|
const node = expression.toOperationNode();
|
|
@@ -697,14 +927,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
697
927
|
get provider() {
|
|
698
928
|
return "postgresql";
|
|
699
929
|
}
|
|
700
|
-
transformPrimitive(value, type) {
|
|
930
|
+
transformPrimitive(value, type, forArrayField) {
|
|
701
931
|
if (value === void 0) {
|
|
702
932
|
return value;
|
|
703
933
|
}
|
|
704
934
|
if (Array.isArray(value)) {
|
|
705
|
-
|
|
935
|
+
if (type === "Json" && !forArrayField) {
|
|
936
|
+
return JSON.stringify(value);
|
|
937
|
+
} else {
|
|
938
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
939
|
+
}
|
|
706
940
|
} else {
|
|
707
|
-
return
|
|
941
|
+
return match3(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
|
|
708
942
|
}
|
|
709
943
|
}
|
|
710
944
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
@@ -718,7 +952,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
718
952
|
const joinTableName = `${parentName}$${relationField}`;
|
|
719
953
|
let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
|
|
720
954
|
result = eb.selectFrom(() => {
|
|
721
|
-
let subQuery =
|
|
955
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
956
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
722
957
|
if (payload && typeof payload === "object") {
|
|
723
958
|
if (payload.where) {
|
|
724
959
|
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
@@ -762,34 +997,57 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
762
997
|
});
|
|
763
998
|
return qb;
|
|
764
999
|
}
|
|
765
|
-
buildRelationObjectArgs(relationModel, relationField, eb, payload,
|
|
1000
|
+
buildRelationObjectArgs(relationModel, relationField, eb, payload, parentAlias) {
|
|
766
1001
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
767
1002
|
const objArgs = [];
|
|
1003
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1004
|
+
if (descendantModels.length > 0) {
|
|
1005
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1006
|
+
sql2.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1007
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1008
|
+
]).flatMap((v) => v));
|
|
1009
|
+
}
|
|
768
1010
|
if (payload === true || !payload.select) {
|
|
769
1011
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
770
1012
|
sql2.lit(field),
|
|
771
1013
|
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
772
1014
|
]).flatMap((v) => v));
|
|
773
1015
|
} else if (payload.select) {
|
|
774
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) =>
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
1016
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1017
|
+
if (field === "_count") {
|
|
1018
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1019
|
+
return [
|
|
1020
|
+
sql2.lit(field),
|
|
1021
|
+
subJson
|
|
1022
|
+
];
|
|
1023
|
+
} else {
|
|
1024
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1025
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
|
|
1026
|
+
return [
|
|
1027
|
+
sql2.lit(field),
|
|
1028
|
+
fieldValue
|
|
1029
|
+
];
|
|
1030
|
+
}
|
|
1031
|
+
}).flatMap((v) => v));
|
|
778
1032
|
}
|
|
779
1033
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
780
1034
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
781
1035
|
sql2.lit(field),
|
|
782
|
-
|
|
1036
|
+
// reference the synthesized JSON field
|
|
1037
|
+
eb.ref(`${parentAlias}$${relationField}$${field}.$j`)
|
|
783
1038
|
]).flatMap((v) => v));
|
|
784
1039
|
}
|
|
785
1040
|
return objArgs;
|
|
786
1041
|
}
|
|
787
|
-
buildRelationJoins(
|
|
1042
|
+
buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
|
|
788
1043
|
let result = qb;
|
|
789
|
-
if (typeof payload === "object"
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
1044
|
+
if (typeof payload === "object") {
|
|
1045
|
+
const selectInclude = payload.include ?? payload.select;
|
|
1046
|
+
if (selectInclude && typeof selectInclude === "object") {
|
|
1047
|
+
Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
|
|
1048
|
+
result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
793
1051
|
}
|
|
794
1052
|
return result;
|
|
795
1053
|
}
|
|
@@ -829,12 +1087,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
829
1087
|
return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
|
|
830
1088
|
}
|
|
831
1089
|
}
|
|
1090
|
+
get supportInsertWithDefault() {
|
|
1091
|
+
return true;
|
|
1092
|
+
}
|
|
832
1093
|
};
|
|
833
1094
|
|
|
834
1095
|
// src/client/crud/dialects/sqlite.ts
|
|
1096
|
+
import { invariant as invariant3 } from "@zenstackhq/common-helpers";
|
|
835
1097
|
import { sql as sql3 } from "kysely";
|
|
836
|
-
import
|
|
837
|
-
import { match as match3 } from "ts-pattern";
|
|
1098
|
+
import { match as match4 } from "ts-pattern";
|
|
838
1099
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
839
1100
|
static {
|
|
840
1101
|
__name(this, "SqliteCrudDialect");
|
|
@@ -842,26 +1103,31 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
842
1103
|
get provider() {
|
|
843
1104
|
return "sqlite";
|
|
844
1105
|
}
|
|
845
|
-
transformPrimitive(value, type) {
|
|
1106
|
+
transformPrimitive(value, type, _forArrayField) {
|
|
846
1107
|
if (value === void 0) {
|
|
847
1108
|
return value;
|
|
848
1109
|
}
|
|
849
1110
|
if (Array.isArray(value)) {
|
|
850
|
-
return value.map((v) => this.transformPrimitive(v, type));
|
|
1111
|
+
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
851
1112
|
} else {
|
|
852
|
-
|
|
1113
|
+
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1114
|
+
return JSON.stringify(value);
|
|
1115
|
+
} else {
|
|
1116
|
+
return match4(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).with("Json", () => JSON.stringify(value)).otherwise(() => value);
|
|
1117
|
+
}
|
|
853
1118
|
}
|
|
854
1119
|
}
|
|
855
1120
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
856
1121
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
857
1122
|
}
|
|
858
|
-
buildRelationJSON(model, eb, relationField,
|
|
1123
|
+
buildRelationJSON(model, eb, relationField, parentAlias, payload) {
|
|
859
1124
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
860
1125
|
const relationModel = relationFieldDef.type;
|
|
861
1126
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
862
|
-
const subQueryName = `${
|
|
1127
|
+
const subQueryName = `${parentAlias}$${relationField}`;
|
|
863
1128
|
let tbl = eb.selectFrom(() => {
|
|
864
|
-
let subQuery =
|
|
1129
|
+
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
1130
|
+
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
865
1131
|
if (payload && typeof payload === "object") {
|
|
866
1132
|
if (payload.where) {
|
|
867
1133
|
subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
|
|
@@ -882,14 +1148,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
882
1148
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
883
1149
|
invariant3(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
884
1150
|
invariant3(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
885
|
-
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${
|
|
1151
|
+
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}`)));
|
|
886
1152
|
} else {
|
|
887
1153
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
888
1154
|
keyPairs.forEach(({ fk, pk }) => {
|
|
889
1155
|
if (ownedByModel) {
|
|
890
|
-
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${
|
|
1156
|
+
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentAlias}.${fk}`);
|
|
891
1157
|
} else {
|
|
892
|
-
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${
|
|
1158
|
+
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentAlias}.${pk}`);
|
|
893
1159
|
}
|
|
894
1160
|
});
|
|
895
1161
|
}
|
|
@@ -897,6 +1163,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
897
1163
|
});
|
|
898
1164
|
tbl = tbl.select(() => {
|
|
899
1165
|
const objArgs = [];
|
|
1166
|
+
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1167
|
+
if (descendantModels.length > 0) {
|
|
1168
|
+
objArgs.push(...descendantModels.map((subModel) => [
|
|
1169
|
+
sql3.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1170
|
+
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1171
|
+
]).flatMap((v) => v));
|
|
1172
|
+
}
|
|
900
1173
|
if (payload === true || !payload.select) {
|
|
901
1174
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
902
1175
|
sql3.lit(field),
|
|
@@ -904,24 +1177,32 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
904
1177
|
]).flatMap((v) => v));
|
|
905
1178
|
} else if (payload.select) {
|
|
906
1179
|
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
|
|
1180
|
+
if (field === "_count") {
|
|
1181
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
910
1182
|
return [
|
|
911
1183
|
sql3.lit(field),
|
|
912
1184
|
subJson
|
|
913
1185
|
];
|
|
914
1186
|
} else {
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
1187
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1188
|
+
if (fieldDef.relation) {
|
|
1189
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1190
|
+
return [
|
|
1191
|
+
sql3.lit(field),
|
|
1192
|
+
subJson
|
|
1193
|
+
];
|
|
1194
|
+
} else {
|
|
1195
|
+
return [
|
|
1196
|
+
sql3.lit(field),
|
|
1197
|
+
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
1198
|
+
];
|
|
1199
|
+
}
|
|
919
1200
|
}
|
|
920
1201
|
}).flatMap((v) => v));
|
|
921
1202
|
}
|
|
922
1203
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
923
1204
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
924
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${
|
|
1205
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
925
1206
|
return [
|
|
926
1207
|
sql3.lit(field),
|
|
927
1208
|
subJson
|
|
@@ -971,93 +1252,17 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
971
1252
|
buildArrayLiteralSQL(_values) {
|
|
972
1253
|
throw new Error("SQLite does not support array literals");
|
|
973
1254
|
}
|
|
1255
|
+
get supportInsertWithDefault() {
|
|
1256
|
+
return false;
|
|
1257
|
+
}
|
|
974
1258
|
};
|
|
975
1259
|
|
|
976
1260
|
// src/client/crud/dialects/index.ts
|
|
977
1261
|
function getCrudDialect(schema, options) {
|
|
978
|
-
return
|
|
1262
|
+
return match5(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
|
|
979
1263
|
}
|
|
980
1264
|
__name(getCrudDialect, "getCrudDialect");
|
|
981
1265
|
|
|
982
|
-
// src/schema/expression.ts
|
|
983
|
-
var ExpressionUtils = {
|
|
984
|
-
literal: /* @__PURE__ */ __name((value) => {
|
|
985
|
-
return {
|
|
986
|
-
kind: "literal",
|
|
987
|
-
value
|
|
988
|
-
};
|
|
989
|
-
}, "literal"),
|
|
990
|
-
array: /* @__PURE__ */ __name((items) => {
|
|
991
|
-
return {
|
|
992
|
-
kind: "array",
|
|
993
|
-
items
|
|
994
|
-
};
|
|
995
|
-
}, "array"),
|
|
996
|
-
call: /* @__PURE__ */ __name((functionName, args) => {
|
|
997
|
-
return {
|
|
998
|
-
kind: "call",
|
|
999
|
-
function: functionName,
|
|
1000
|
-
args
|
|
1001
|
-
};
|
|
1002
|
-
}, "call"),
|
|
1003
|
-
binary: /* @__PURE__ */ __name((left, op, right) => {
|
|
1004
|
-
return {
|
|
1005
|
-
kind: "binary",
|
|
1006
|
-
op,
|
|
1007
|
-
left,
|
|
1008
|
-
right
|
|
1009
|
-
};
|
|
1010
|
-
}, "binary"),
|
|
1011
|
-
unary: /* @__PURE__ */ __name((op, operand) => {
|
|
1012
|
-
return {
|
|
1013
|
-
kind: "unary",
|
|
1014
|
-
op,
|
|
1015
|
-
operand
|
|
1016
|
-
};
|
|
1017
|
-
}, "unary"),
|
|
1018
|
-
field: /* @__PURE__ */ __name((field) => {
|
|
1019
|
-
return {
|
|
1020
|
-
kind: "field",
|
|
1021
|
-
field
|
|
1022
|
-
};
|
|
1023
|
-
}, "field"),
|
|
1024
|
-
member: /* @__PURE__ */ __name((receiver, members) => {
|
|
1025
|
-
return {
|
|
1026
|
-
kind: "member",
|
|
1027
|
-
receiver,
|
|
1028
|
-
members
|
|
1029
|
-
};
|
|
1030
|
-
}, "member"),
|
|
1031
|
-
_this: /* @__PURE__ */ __name(() => {
|
|
1032
|
-
return {
|
|
1033
|
-
kind: "this"
|
|
1034
|
-
};
|
|
1035
|
-
}, "_this"),
|
|
1036
|
-
_null: /* @__PURE__ */ __name(() => {
|
|
1037
|
-
return {
|
|
1038
|
-
kind: "null"
|
|
1039
|
-
};
|
|
1040
|
-
}, "_null"),
|
|
1041
|
-
and: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1042
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
|
|
1043
|
-
}, "and"),
|
|
1044
|
-
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
1045
|
-
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
1046
|
-
}, "or"),
|
|
1047
|
-
is: /* @__PURE__ */ __name((value, kind) => {
|
|
1048
|
-
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
1049
|
-
}, "is"),
|
|
1050
|
-
isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
|
|
1051
|
-
isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
|
|
1052
|
-
isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
|
|
1053
|
-
isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
|
|
1054
|
-
isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
|
|
1055
|
-
isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
|
|
1056
|
-
isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
|
|
1057
|
-
isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
|
|
1058
|
-
isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
|
|
1059
|
-
};
|
|
1060
|
-
|
|
1061
1266
|
// src/utils/default-operation-node-visitor.ts
|
|
1062
1267
|
import { OperationNodeVisitor } from "kysely";
|
|
1063
1268
|
var DefaultOperationNodeVisitor = class extends OperationNodeVisitor {
|
|
@@ -1377,19 +1582,19 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1377
1582
|
};
|
|
1378
1583
|
|
|
1379
1584
|
// src/plugins/policy/expression-transformer.ts
|
|
1585
|
+
import { invariant as invariant5 } from "@zenstackhq/common-helpers";
|
|
1380
1586
|
import { AliasNode as AliasNode2, BinaryOperationNode as BinaryOperationNode2, ColumnNode, expressionBuilder, FromNode, FunctionNode as FunctionNode2, IdentifierNode, OperatorNode as OperatorNode2, ReferenceNode as ReferenceNode2, SelectionNode, SelectQueryNode, TableNode as TableNode2, ValueListNode, ValueNode as ValueNode2, WhereNode } from "kysely";
|
|
1381
|
-
import
|
|
1382
|
-
import { match as match6 } from "ts-pattern";
|
|
1587
|
+
import { match as match7 } from "ts-pattern";
|
|
1383
1588
|
|
|
1384
1589
|
// src/plugins/policy/expression-evaluator.ts
|
|
1385
|
-
import invariant4 from "
|
|
1386
|
-
import { match as
|
|
1590
|
+
import { invariant as invariant4 } from "@zenstackhq/common-helpers";
|
|
1591
|
+
import { match as match6 } from "ts-pattern";
|
|
1387
1592
|
var ExpressionEvaluator = class {
|
|
1388
1593
|
static {
|
|
1389
1594
|
__name(this, "ExpressionEvaluator");
|
|
1390
1595
|
}
|
|
1391
1596
|
evaluate(expression, context) {
|
|
1392
|
-
const result =
|
|
1597
|
+
const result = match6(expression).when(ExpressionUtils.isArray, (expr2) => this.evaluateArray(expr2, context)).when(ExpressionUtils.isBinary, (expr2) => this.evaluateBinary(expr2, context)).when(ExpressionUtils.isField, (expr2) => this.evaluateField(expr2, context)).when(ExpressionUtils.isLiteral, (expr2) => this.evaluateLiteral(expr2)).when(ExpressionUtils.isMember, (expr2) => this.evaluateMember(expr2, context)).when(ExpressionUtils.isUnary, (expr2) => this.evaluateUnary(expr2, context)).when(ExpressionUtils.isCall, (expr2) => this.evaluateCall(expr2, context)).when(ExpressionUtils.isThis, () => context.thisValue).when(ExpressionUtils.isNull, () => null).exhaustive();
|
|
1393
1598
|
return result ?? null;
|
|
1394
1599
|
}
|
|
1395
1600
|
evaluateCall(expr2, context) {
|
|
@@ -1400,7 +1605,7 @@ var ExpressionEvaluator = class {
|
|
|
1400
1605
|
}
|
|
1401
1606
|
}
|
|
1402
1607
|
evaluateUnary(expr2, context) {
|
|
1403
|
-
return
|
|
1608
|
+
return match6(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
|
|
1404
1609
|
}
|
|
1405
1610
|
evaluateMember(expr2, context) {
|
|
1406
1611
|
let val = this.evaluate(expr2.receiver, context);
|
|
@@ -1424,7 +1629,7 @@ var ExpressionEvaluator = class {
|
|
|
1424
1629
|
}
|
|
1425
1630
|
const left = this.evaluate(expr2.left, context);
|
|
1426
1631
|
const right = this.evaluate(expr2.right, context);
|
|
1427
|
-
return
|
|
1632
|
+
return match6(expr2.op).with("==", () => left === right).with("!=", () => left !== right).with(">", () => left > right).with(">=", () => left >= right).with("<", () => left < right).with("<=", () => left <= right).with("&&", () => left && right).with("||", () => left || right).with("in", () => {
|
|
1428
1633
|
const _right = right ?? [];
|
|
1429
1634
|
invariant4(Array.isArray(_right), 'expected array for "in" operator');
|
|
1430
1635
|
return _right.includes(left);
|
|
@@ -1438,7 +1643,7 @@ var ExpressionEvaluator = class {
|
|
|
1438
1643
|
return false;
|
|
1439
1644
|
}
|
|
1440
1645
|
invariant4(Array.isArray(left), "expected array");
|
|
1441
|
-
return
|
|
1646
|
+
return match6(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1442
1647
|
...context,
|
|
1443
1648
|
thisValue: item
|
|
1444
1649
|
}))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
|
|
@@ -1454,11 +1659,11 @@ var ExpressionEvaluator = class {
|
|
|
1454
1659
|
// src/plugins/policy/utils.ts
|
|
1455
1660
|
import { AliasNode, AndNode, BinaryOperationNode, FunctionNode, OperatorNode, OrNode, ParensNode, ReferenceNode, TableNode, UnaryOperationNode, ValueNode } from "kysely";
|
|
1456
1661
|
function trueNode(dialect) {
|
|
1457
|
-
return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
|
|
1662
|
+
return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1458
1663
|
}
|
|
1459
1664
|
__name(trueNode, "trueNode");
|
|
1460
1665
|
function falseNode(dialect) {
|
|
1461
|
-
return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
|
|
1666
|
+
return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1462
1667
|
}
|
|
1463
1668
|
__name(falseNode, "falseNode");
|
|
1464
1669
|
function isTrueNode(node) {
|
|
@@ -1692,7 +1897,7 @@ var ExpressionTransformer = class {
|
|
|
1692
1897
|
const count = FunctionNode2.create("count", [
|
|
1693
1898
|
ValueNode2.createImmediate(1)
|
|
1694
1899
|
]);
|
|
1695
|
-
const predicateResult =
|
|
1900
|
+
const predicateResult = match7(expr2.op).with("?", () => BinaryOperationNode2.create(count, OperatorNode2.create(">"), ValueNode2.createImmediate(0))).with("!", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).with("^", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).exhaustive();
|
|
1696
1901
|
return this.transform(expr2.left, {
|
|
1697
1902
|
...context,
|
|
1698
1903
|
memberSelect: SelectionNode.create(AliasNode2.create(predicateResult, IdentifierNode.create("$t"))),
|
|
@@ -1716,14 +1921,14 @@ var ExpressionTransformer = class {
|
|
|
1716
1921
|
}
|
|
1717
1922
|
}
|
|
1718
1923
|
transformValue(value, type) {
|
|
1719
|
-
return ValueNode2.create(this.dialect.transformPrimitive(value, type) ?? null);
|
|
1924
|
+
return ValueNode2.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
1720
1925
|
}
|
|
1721
1926
|
_unary(expr2, context) {
|
|
1722
1927
|
invariant5(expr2.op === "!", 'only "!" operator is supported');
|
|
1723
1928
|
return BinaryOperationNode2.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
|
|
1724
1929
|
}
|
|
1725
1930
|
transformOperator(op) {
|
|
1726
|
-
const mappedOp =
|
|
1931
|
+
const mappedOp = match7(op).with("==", () => "=").otherwise(() => op);
|
|
1727
1932
|
return OperatorNode2.create(mappedOp);
|
|
1728
1933
|
}
|
|
1729
1934
|
_call(expr2, context) {
|
|
@@ -1959,7 +2164,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
1959
2164
|
get kysely() {
|
|
1960
2165
|
return this.client.$qb;
|
|
1961
2166
|
}
|
|
1962
|
-
async handle(node, proceed
|
|
2167
|
+
async handle(node, proceed) {
|
|
1963
2168
|
if (!this.isCrudQueryNode(node)) {
|
|
1964
2169
|
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
1965
2170
|
}
|
|
@@ -1979,27 +2184,20 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
1979
2184
|
if (!mutationRequiresTransaction && !node.returning) {
|
|
1980
2185
|
return proceed(this.transformNode(node));
|
|
1981
2186
|
}
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
const
|
|
1989
|
-
if (
|
|
1990
|
-
|
|
1991
|
-
if (readBackResult.rows.length !== result2.rows.length) {
|
|
1992
|
-
readBackError = true;
|
|
1993
|
-
}
|
|
1994
|
-
return readBackResult;
|
|
1995
|
-
} else {
|
|
1996
|
-
return result2;
|
|
2187
|
+
if (InsertQueryNode.is(node)) {
|
|
2188
|
+
await this.enforcePreCreatePolicy(node, proceed);
|
|
2189
|
+
}
|
|
2190
|
+
const transformedNode = this.transformNode(node);
|
|
2191
|
+
const result = await proceed(transformedNode);
|
|
2192
|
+
if (!this.onlyReturningId(node)) {
|
|
2193
|
+
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2194
|
+
if (readBackResult.rows.length !== result.rows.length) {
|
|
2195
|
+
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
1997
2196
|
}
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2197
|
+
return readBackResult;
|
|
2198
|
+
} else {
|
|
2199
|
+
return result;
|
|
2001
2200
|
}
|
|
2002
|
-
return result;
|
|
2003
2201
|
}
|
|
2004
2202
|
onlyReturningId(node) {
|
|
2005
2203
|
if (!node.returning) {
|
|
@@ -2060,11 +2258,11 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2060
2258
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2061
2259
|
invariant6(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2062
2260
|
result.push({
|
|
2063
|
-
node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
|
|
2261
|
+
node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2064
2262
|
raw: item.value
|
|
2065
2263
|
});
|
|
2066
2264
|
} else {
|
|
2067
|
-
const value = this.dialect.transformPrimitive(item, fieldDef.type);
|
|
2265
|
+
const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
2068
2266
|
if (Array.isArray(value)) {
|
|
2069
2267
|
result.push({
|
|
2070
2268
|
node: RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
@@ -2133,7 +2331,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
|
|
|
2133
2331
|
return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => BinaryOperationNode3.create(ColumnNode2.create(field), OperatorNode3.create("="), ValueNode3.create(row[field]))))));
|
|
2134
2332
|
}
|
|
2135
2333
|
getMutationModel(node) {
|
|
2136
|
-
const r =
|
|
2334
|
+
const r = match8(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
|
|
2137
2335
|
if (node2.from.froms.length !== 1) {
|
|
2138
2336
|
throw new InternalError("Only one from table is supported for delete");
|
|
2139
2337
|
}
|
|
@@ -2295,13 +2493,22 @@ var PolicyPlugin = class {
|
|
|
2295
2493
|
get description() {
|
|
2296
2494
|
return "Enforces access policies defined in the schema.";
|
|
2297
2495
|
}
|
|
2298
|
-
onKyselyQuery({
|
|
2496
|
+
onKyselyQuery({
|
|
2497
|
+
query,
|
|
2498
|
+
client,
|
|
2499
|
+
proceed
|
|
2500
|
+
/*, transaction*/
|
|
2501
|
+
}) {
|
|
2299
2502
|
const handler = new PolicyHandler(client);
|
|
2300
|
-
return handler.handle(
|
|
2503
|
+
return handler.handle(
|
|
2504
|
+
query,
|
|
2505
|
+
proceed
|
|
2506
|
+
/*, transaction*/
|
|
2507
|
+
);
|
|
2301
2508
|
}
|
|
2302
2509
|
};
|
|
2303
2510
|
export {
|
|
2304
2511
|
PolicyPlugin,
|
|
2305
2512
|
RejectedByPolicyError
|
|
2306
2513
|
};
|
|
2307
|
-
//# sourceMappingURL=
|
|
2514
|
+
//# sourceMappingURL=index.js.map
|