@zenstackhq/runtime 3.0.0-beta.3 → 3.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{contract-CusA0mQO.d.cts → contract-BJce14-p.d.cts} +58 -17
- package/dist/{contract-CusA0mQO.d.ts → contract-BJce14-p.d.ts} +58 -17
- package/dist/index.cjs +1401 -786
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1286 -671
- package/dist/index.js.map +1 -1
- package/dist/plugins/policy/index.cjs +965 -375
- package/dist/plugins/policy/index.cjs.map +1 -1
- package/dist/plugins/policy/index.d.cts +24 -4
- package/dist/plugins/policy/index.d.ts +24 -4
- package/dist/plugins/policy/index.js +880 -301
- package/dist/plugins/policy/index.js.map +1 -1
- package/dist/plugins/policy/plugin.zmodel +10 -0
- package/dist/schema.cjs +3 -0
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +1 -0
- package/dist/schema.d.ts +1 -0
- package/dist/schema.js +3 -0
- package/dist/schema.js.map +1 -1
- package/package.json +11 -8
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
9
|
var __export = (target, all) => {
|
|
@@ -16,57 +18,70 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
18
|
}
|
|
17
19
|
return to;
|
|
18
20
|
};
|
|
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
|
+
));
|
|
19
29
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
30
|
|
|
21
31
|
// src/plugins/policy/index.ts
|
|
22
32
|
var policy_exports = {};
|
|
23
33
|
__export(policy_exports, {
|
|
24
34
|
PolicyPlugin: () => PolicyPlugin,
|
|
25
|
-
RejectedByPolicyError: () => RejectedByPolicyError
|
|
35
|
+
RejectedByPolicyError: () => RejectedByPolicyError,
|
|
36
|
+
RejectedByPolicyReason: () => RejectedByPolicyReason
|
|
26
37
|
});
|
|
27
38
|
module.exports = __toCommonJS(policy_exports);
|
|
28
39
|
|
|
29
40
|
// src/plugins/policy/errors.ts
|
|
41
|
+
var RejectedByPolicyReason = /* @__PURE__ */ function(RejectedByPolicyReason2) {
|
|
42
|
+
RejectedByPolicyReason2["NO_ACCESS"] = "no-access";
|
|
43
|
+
RejectedByPolicyReason2["CANNOT_READ_BACK"] = "cannot-read-back";
|
|
44
|
+
RejectedByPolicyReason2["OTHER"] = "other";
|
|
45
|
+
return RejectedByPolicyReason2;
|
|
46
|
+
}({});
|
|
30
47
|
var RejectedByPolicyError = class extends Error {
|
|
31
48
|
static {
|
|
32
49
|
__name(this, "RejectedByPolicyError");
|
|
33
50
|
}
|
|
34
51
|
model;
|
|
35
52
|
reason;
|
|
36
|
-
constructor(model, reason) {
|
|
37
|
-
super(
|
|
53
|
+
constructor(model, reason = "no-access", message) {
|
|
54
|
+
super(message ?? `Operation rejected by policy${model ? ": " + model : ""}`), this.model = model, this.reason = reason;
|
|
38
55
|
}
|
|
39
56
|
};
|
|
40
57
|
|
|
41
|
-
// src/plugins/policy/
|
|
42
|
-
var
|
|
43
|
-
var
|
|
44
|
-
var import_ts_pattern8 = require("ts-pattern");
|
|
45
|
-
|
|
46
|
-
// src/client/crud/dialects/index.ts
|
|
47
|
-
var import_ts_pattern5 = require("ts-pattern");
|
|
58
|
+
// src/plugins/policy/functions.ts
|
|
59
|
+
var import_common_helpers8 = require("@zenstackhq/common-helpers");
|
|
60
|
+
var import_kysely9 = require("kysely");
|
|
48
61
|
|
|
49
|
-
// src/client/
|
|
50
|
-
var
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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"
|
|
62
|
+
// src/client/contract.ts
|
|
63
|
+
var CRUD = [
|
|
64
|
+
"create",
|
|
65
|
+
"read",
|
|
66
|
+
"update",
|
|
67
|
+
"delete"
|
|
67
68
|
];
|
|
68
69
|
|
|
70
|
+
// src/client/kysely-utils.ts
|
|
71
|
+
var import_kysely = require("kysely");
|
|
72
|
+
function extractFieldName(node) {
|
|
73
|
+
if (import_kysely.ReferenceNode.is(node) && import_kysely.ColumnNode.is(node.column)) {
|
|
74
|
+
return node.column.column.name;
|
|
75
|
+
} else if (import_kysely.ColumnNode.is(node)) {
|
|
76
|
+
return node.column.name;
|
|
77
|
+
} else {
|
|
78
|
+
return void 0;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
__name(extractFieldName, "extractFieldName");
|
|
82
|
+
|
|
69
83
|
// src/client/query-utils.ts
|
|
84
|
+
var import_common_helpers = require("@zenstackhq/common-helpers");
|
|
70
85
|
var import_ts_pattern = require("ts-pattern");
|
|
71
86
|
|
|
72
87
|
// src/schema/expression.ts
|
|
@@ -134,6 +149,9 @@ var ExpressionUtils = {
|
|
|
134
149
|
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
135
150
|
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
136
151
|
}, "or"),
|
|
152
|
+
not: /* @__PURE__ */ __name((expr2) => {
|
|
153
|
+
return ExpressionUtils.unary("!", expr2);
|
|
154
|
+
}, "not"),
|
|
137
155
|
is: /* @__PURE__ */ __name((value, kind) => {
|
|
138
156
|
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
139
157
|
}, "is"),
|
|
@@ -170,15 +188,19 @@ var InternalError = class extends Error {
|
|
|
170
188
|
|
|
171
189
|
// src/client/query-utils.ts
|
|
172
190
|
function getModel(schema, model) {
|
|
173
|
-
return schema.models
|
|
191
|
+
return Object.values(schema.models).find((m) => m.name.toLowerCase() === model.toLowerCase());
|
|
174
192
|
}
|
|
175
193
|
__name(getModel, "getModel");
|
|
194
|
+
function getTypeDef(schema, type) {
|
|
195
|
+
return schema.typeDefs?.[type];
|
|
196
|
+
}
|
|
197
|
+
__name(getTypeDef, "getTypeDef");
|
|
176
198
|
function requireModel(schema, model) {
|
|
177
|
-
const
|
|
178
|
-
if (!
|
|
199
|
+
const modelDef = getModel(schema, model);
|
|
200
|
+
if (!modelDef) {
|
|
179
201
|
throw new QueryError(`Model "${model}" not found in schema`);
|
|
180
202
|
}
|
|
181
|
-
return
|
|
203
|
+
return modelDef;
|
|
182
204
|
}
|
|
183
205
|
__name(requireModel, "requireModel");
|
|
184
206
|
function getField(schema, model, field) {
|
|
@@ -186,19 +208,35 @@ function getField(schema, model, field) {
|
|
|
186
208
|
return modelDef?.fields[field];
|
|
187
209
|
}
|
|
188
210
|
__name(getField, "getField");
|
|
189
|
-
function requireField(schema,
|
|
190
|
-
const modelDef =
|
|
191
|
-
if (
|
|
192
|
-
|
|
211
|
+
function requireField(schema, modelOrType, field) {
|
|
212
|
+
const modelDef = getModel(schema, modelOrType);
|
|
213
|
+
if (modelDef) {
|
|
214
|
+
if (!modelDef.fields[field]) {
|
|
215
|
+
throw new QueryError(`Field "${field}" not found in model "${modelOrType}"`);
|
|
216
|
+
} else {
|
|
217
|
+
return modelDef.fields[field];
|
|
218
|
+
}
|
|
193
219
|
}
|
|
194
|
-
|
|
220
|
+
const typeDef = getTypeDef(schema, modelOrType);
|
|
221
|
+
if (typeDef) {
|
|
222
|
+
if (!typeDef.fields[field]) {
|
|
223
|
+
throw new QueryError(`Field "${field}" not found in type "${modelOrType}"`);
|
|
224
|
+
} else {
|
|
225
|
+
return typeDef.fields[field];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
throw new QueryError(`Model or type "${modelOrType}" not found in schema`);
|
|
195
229
|
}
|
|
196
230
|
__name(requireField, "requireField");
|
|
197
|
-
function
|
|
231
|
+
function requireIdFields(schema, model) {
|
|
198
232
|
const modelDef = requireModel(schema, model);
|
|
199
|
-
|
|
233
|
+
const result = modelDef?.idFields;
|
|
234
|
+
if (!result) {
|
|
235
|
+
throw new InternalError(`Model "${model}" does not have ID field(s)`);
|
|
236
|
+
}
|
|
237
|
+
return result;
|
|
200
238
|
}
|
|
201
|
-
__name(
|
|
239
|
+
__name(requireIdFields, "requireIdFields");
|
|
202
240
|
function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
203
241
|
const fieldDef = requireField(schema, model, relationField);
|
|
204
242
|
if (!fieldDef?.relation) {
|
|
@@ -291,7 +329,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias, inlineComp
|
|
|
291
329
|
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
292
330
|
}
|
|
293
331
|
return computer(eb, {
|
|
294
|
-
|
|
332
|
+
modelAlias
|
|
295
333
|
});
|
|
296
334
|
}
|
|
297
335
|
}
|
|
@@ -318,7 +356,7 @@ function buildJoinPairs(schema, model, modelAlias, relationField, relationModelA
|
|
|
318
356
|
}
|
|
319
357
|
__name(buildJoinPairs, "buildJoinPairs");
|
|
320
358
|
function makeDefaultOrderBy(schema, model) {
|
|
321
|
-
const idFields =
|
|
359
|
+
const idFields = requireIdFields(schema, model);
|
|
322
360
|
return idFields.map((f) => ({
|
|
323
361
|
[f]: "asc"
|
|
324
362
|
}));
|
|
@@ -357,11 +395,17 @@ function getManyToManyRelation(schema, model, field) {
|
|
|
357
395
|
"A"
|
|
358
396
|
];
|
|
359
397
|
}
|
|
398
|
+
const modelIdFields = requireIdFields(schema, model);
|
|
399
|
+
(0, import_common_helpers.invariant)(modelIdFields.length === 1, "Only single-field ID is supported for many-to-many relation");
|
|
400
|
+
const otherIdFields = requireIdFields(schema, fieldDef.type);
|
|
401
|
+
(0, import_common_helpers.invariant)(otherIdFields.length === 1, "Only single-field ID is supported for many-to-many relation");
|
|
360
402
|
return {
|
|
361
403
|
parentFkName: orderedFK[0],
|
|
404
|
+
parentPKName: modelIdFields[0],
|
|
362
405
|
otherModel: fieldDef.type,
|
|
363
406
|
otherField: fieldDef.relation.opposite,
|
|
364
407
|
otherFkName: orderedFK[1],
|
|
408
|
+
otherPKName: otherIdFields[0],
|
|
365
409
|
joinTable: fieldDef.relation.name ? `_${fieldDef.relation.name}` : `_${sortedModelNames[0]}To${sortedModelNames[1]}`
|
|
366
410
|
};
|
|
367
411
|
} else {
|
|
@@ -417,9 +461,38 @@ function aggregate(eb, expr2, op) {
|
|
|
417
461
|
}
|
|
418
462
|
__name(aggregate, "aggregate");
|
|
419
463
|
|
|
420
|
-
// src/
|
|
421
|
-
var
|
|
422
|
-
var
|
|
464
|
+
// src/plugins/policy/policy-handler.ts
|
|
465
|
+
var import_common_helpers7 = require("@zenstackhq/common-helpers");
|
|
466
|
+
var import_kysely8 = require("kysely");
|
|
467
|
+
var import_ts_pattern8 = require("ts-pattern");
|
|
468
|
+
|
|
469
|
+
// src/client/crud/dialects/index.ts
|
|
470
|
+
var import_ts_pattern5 = require("ts-pattern");
|
|
471
|
+
|
|
472
|
+
// src/client/crud/dialects/postgresql.ts
|
|
473
|
+
var import_common_helpers3 = require("@zenstackhq/common-helpers");
|
|
474
|
+
var import_decimal = __toESM(require("decimal.js"), 1);
|
|
475
|
+
var import_kysely3 = require("kysely");
|
|
476
|
+
var import_ts_pattern3 = require("ts-pattern");
|
|
477
|
+
|
|
478
|
+
// src/client/constants.ts
|
|
479
|
+
var DELEGATE_JOINED_FIELD_PREFIX = "$delegate$";
|
|
480
|
+
var LOGICAL_COMBINATORS = [
|
|
481
|
+
"AND",
|
|
482
|
+
"OR",
|
|
483
|
+
"NOT"
|
|
484
|
+
];
|
|
485
|
+
var AGGREGATE_OPERATORS = [
|
|
486
|
+
"_count",
|
|
487
|
+
"_sum",
|
|
488
|
+
"_avg",
|
|
489
|
+
"_min",
|
|
490
|
+
"_max"
|
|
491
|
+
];
|
|
492
|
+
|
|
493
|
+
// src/client/crud/dialects/base-dialect.ts
|
|
494
|
+
var import_common_helpers2 = require("@zenstackhq/common-helpers");
|
|
495
|
+
var import_kysely2 = require("kysely");
|
|
423
496
|
var import_ts_pattern2 = require("ts-pattern");
|
|
424
497
|
|
|
425
498
|
// src/utils/enumerate.ts
|
|
@@ -436,7 +509,7 @@ function enumerate(x) {
|
|
|
436
509
|
}
|
|
437
510
|
__name(enumerate, "enumerate");
|
|
438
511
|
|
|
439
|
-
// src/client/crud/dialects/base.ts
|
|
512
|
+
// src/client/crud/dialects/base-dialect.ts
|
|
440
513
|
var BaseCrudDialect = class {
|
|
441
514
|
static {
|
|
442
515
|
__name(this, "BaseCrudDialect");
|
|
@@ -450,6 +523,9 @@ var BaseCrudDialect = class {
|
|
|
450
523
|
transformPrimitive(value, _type, _forArrayField) {
|
|
451
524
|
return value;
|
|
452
525
|
}
|
|
526
|
+
transformOutput(value, _type) {
|
|
527
|
+
return value;
|
|
528
|
+
}
|
|
453
529
|
// #region common query builders
|
|
454
530
|
buildSelectModel(eb, model, modelAlias) {
|
|
455
531
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -478,7 +554,7 @@ var BaseCrudDialect = class {
|
|
|
478
554
|
if ("distinct" in args && args.distinct) {
|
|
479
555
|
const distinct = ensureArray(args.distinct);
|
|
480
556
|
if (this.supportsDistinctOn) {
|
|
481
|
-
result = result.distinctOn(distinct.map((f) =>
|
|
557
|
+
result = result.distinctOn(distinct.map((f) => import_kysely2.sql.ref(`${modelAlias}.${f}`)));
|
|
482
558
|
} else {
|
|
483
559
|
throw new QueryError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
|
|
484
560
|
}
|
|
@@ -528,7 +604,7 @@ var BaseCrudDialect = class {
|
|
|
528
604
|
buildCursorFilter(model, query, cursor, orderBy, negateOrderBy, modelAlias) {
|
|
529
605
|
const _orderBy = orderBy ?? makeDefaultOrderBy(this.schema, model);
|
|
530
606
|
const orderByItems = ensureArray(_orderBy).flatMap((obj) => Object.entries(obj));
|
|
531
|
-
const eb = (0,
|
|
607
|
+
const eb = (0, import_kysely2.expressionBuilder)();
|
|
532
608
|
const subQueryAlias = `${model}$cursor$sub`;
|
|
533
609
|
const cursorFilter = this.buildFilter(eb, model, subQueryAlias, cursor);
|
|
534
610
|
let result = query;
|
|
@@ -563,7 +639,7 @@ var BaseCrudDialect = class {
|
|
|
563
639
|
if (payload === null) {
|
|
564
640
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
565
641
|
if (ownedByModel && !fieldDef.originModel) {
|
|
566
|
-
return this.and(eb, ...keyPairs.map(({ fk }) => eb(
|
|
642
|
+
return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely2.sql.ref(`${modelAlias}.${fk}`), "is", null)));
|
|
567
643
|
} else {
|
|
568
644
|
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
|
|
569
645
|
is: null
|
|
@@ -580,7 +656,7 @@ var BaseCrudDialect = class {
|
|
|
580
656
|
joinAlias
|
|
581
657
|
);
|
|
582
658
|
const filterResultField = `${field}$filter`;
|
|
583
|
-
const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(
|
|
659
|
+
const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
|
|
584
660
|
const conditions = [];
|
|
585
661
|
if ("is" in payload || "isNot" in payload) {
|
|
586
662
|
if ("is" in payload) {
|
|
@@ -610,24 +686,26 @@ var BaseCrudDialect = class {
|
|
|
610
686
|
}
|
|
611
687
|
buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
612
688
|
if (payload === null) {
|
|
613
|
-
return eb(
|
|
689
|
+
return eb(import_kysely2.sql.ref(`${modelAlias}.${field}`), "is", null);
|
|
614
690
|
}
|
|
615
691
|
const relationModel = fieldDef.type;
|
|
616
692
|
const relationFilterSelectAlias = `${modelAlias}$${field}$filter`;
|
|
617
693
|
const buildPkFkWhereRefs = /* @__PURE__ */ __name((eb2) => {
|
|
618
694
|
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
619
695
|
if (m2m) {
|
|
620
|
-
const
|
|
621
|
-
|
|
622
|
-
|
|
696
|
+
const modelIdFields = requireIdFields(this.schema, model);
|
|
697
|
+
(0, import_common_helpers2.invariant)(modelIdFields.length === 1, "many-to-many relation must have exactly one id field");
|
|
698
|
+
const relationIdFields = requireIdFields(this.schema, relationModel);
|
|
699
|
+
(0, import_common_helpers2.invariant)(relationIdFields.length === 1, "many-to-many relation must have exactly one id field");
|
|
700
|
+
return eb2(import_kysely2.sql.ref(`${relationFilterSelectAlias}.${relationIdFields[0]}`), "in", eb2.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(import_kysely2.sql.ref(`${m2m.joinTable}.${m2m.parentFkName}`), "=", import_kysely2.sql.ref(`${modelAlias}.${modelIdFields[0]}`)));
|
|
623
701
|
} else {
|
|
624
702
|
const relationKeyPairs = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
625
703
|
let result2 = this.true(eb2);
|
|
626
704
|
for (const { fk, pk } of relationKeyPairs.keyPairs) {
|
|
627
705
|
if (relationKeyPairs.ownedByModel) {
|
|
628
|
-
result2 = this.and(eb2, result2, eb2(
|
|
706
|
+
result2 = this.and(eb2, result2, eb2(import_kysely2.sql.ref(`${modelAlias}.${fk}`), "=", import_kysely2.sql.ref(`${relationFilterSelectAlias}.${pk}`)));
|
|
629
707
|
} else {
|
|
630
|
-
result2 = this.and(eb2, result2, eb2(
|
|
708
|
+
result2 = this.and(eb2, result2, eb2(import_kysely2.sql.ref(`${modelAlias}.${pk}`), "=", import_kysely2.sql.ref(`${relationFilterSelectAlias}.${fk}`)));
|
|
631
709
|
}
|
|
632
710
|
}
|
|
633
711
|
return result2;
|
|
@@ -710,7 +788,7 @@ var BaseCrudDialect = class {
|
|
|
710
788
|
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
711
789
|
}
|
|
712
790
|
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
713
|
-
if (payload === null || !(0,
|
|
791
|
+
if (payload === null || !(0, import_common_helpers2.isPlainObject)(payload)) {
|
|
714
792
|
return {
|
|
715
793
|
conditions: [
|
|
716
794
|
this.buildLiteralFilter(eb, lhs, type, payload)
|
|
@@ -729,14 +807,14 @@ var BaseCrudDialect = class {
|
|
|
729
807
|
}
|
|
730
808
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
731
809
|
const condition = (0, import_ts_pattern2.match)(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
732
|
-
(0,
|
|
810
|
+
(0, import_common_helpers2.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
733
811
|
if (rhs.length === 0) {
|
|
734
812
|
return this.false(eb);
|
|
735
813
|
} else {
|
|
736
814
|
return eb(lhs, "in", rhs);
|
|
737
815
|
}
|
|
738
816
|
}).with("notIn", () => {
|
|
739
|
-
(0,
|
|
817
|
+
(0, import_common_helpers2.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
740
818
|
if (rhs.length === 0) {
|
|
741
819
|
return this.true(eb);
|
|
742
820
|
} else {
|
|
@@ -776,7 +854,7 @@ var BaseCrudDialect = class {
|
|
|
776
854
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
777
855
|
continue;
|
|
778
856
|
}
|
|
779
|
-
const condition = (0, import_ts_pattern2.match)(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike",
|
|
857
|
+
const condition = (0, import_ts_pattern2.match)(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely2.sql.val(`%${value}%`)) : eb(fieldRef, "like", import_kysely2.sql.val(`%${value}%`))).with("startsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely2.sql.val(`${value}%`)) : eb(fieldRef, "like", import_kysely2.sql.val(`${value}%`))).with("endsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely2.sql.val(`%${value}`)) : eb(fieldRef, "like", import_kysely2.sql.val(`%${value}`))).otherwise(() => {
|
|
780
858
|
throw new QueryError(`Invalid string filter key: ${key}`);
|
|
781
859
|
});
|
|
782
860
|
if (condition) {
|
|
@@ -788,16 +866,16 @@ var BaseCrudDialect = class {
|
|
|
788
866
|
}
|
|
789
867
|
prepStringCasing(eb, value, mode) {
|
|
790
868
|
if (!mode || mode === "default") {
|
|
791
|
-
return value === null ? value :
|
|
869
|
+
return value === null ? value : import_kysely2.sql.val(value);
|
|
792
870
|
}
|
|
793
871
|
if (typeof value === "string") {
|
|
794
872
|
return eb.fn("lower", [
|
|
795
|
-
|
|
873
|
+
import_kysely2.sql.val(value)
|
|
796
874
|
]);
|
|
797
875
|
} else if (Array.isArray(value)) {
|
|
798
876
|
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
799
877
|
} else {
|
|
800
|
-
return value === null ? null :
|
|
878
|
+
return value === null ? null : import_kysely2.sql.val(value);
|
|
801
879
|
}
|
|
802
880
|
}
|
|
803
881
|
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
@@ -854,19 +932,19 @@ var BaseCrudDialect = class {
|
|
|
854
932
|
"_min",
|
|
855
933
|
"_max"
|
|
856
934
|
].includes(field)) {
|
|
857
|
-
(0,
|
|
935
|
+
(0, import_common_helpers2.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
858
936
|
for (const [k, v] of Object.entries(value)) {
|
|
859
|
-
(0,
|
|
860
|
-
result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field),
|
|
937
|
+
(0, import_common_helpers2.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
938
|
+
result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field), import_kysely2.sql.raw(this.negateSort(v, negated)));
|
|
861
939
|
}
|
|
862
940
|
continue;
|
|
863
941
|
}
|
|
864
942
|
switch (field) {
|
|
865
943
|
case "_count": {
|
|
866
|
-
(0,
|
|
944
|
+
(0, import_common_helpers2.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
|
|
867
945
|
for (const [k, v] of Object.entries(value)) {
|
|
868
|
-
(0,
|
|
869
|
-
result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)),
|
|
946
|
+
(0, import_common_helpers2.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
947
|
+
result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), import_kysely2.sql.raw(this.negateSort(v, negated)));
|
|
870
948
|
}
|
|
871
949
|
continue;
|
|
872
950
|
}
|
|
@@ -875,11 +953,11 @@ var BaseCrudDialect = class {
|
|
|
875
953
|
}
|
|
876
954
|
const fieldDef = requireField(this.schema, model, field);
|
|
877
955
|
if (!fieldDef.relation) {
|
|
878
|
-
const fieldRef = this.fieldRef(model, field, (0,
|
|
956
|
+
const fieldRef = this.fieldRef(model, field, (0, import_kysely2.expressionBuilder)(), modelAlias);
|
|
879
957
|
if (value === "asc" || value === "desc") {
|
|
880
958
|
result = result.orderBy(fieldRef, this.negateSort(value, negated));
|
|
881
959
|
} else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
|
|
882
|
-
result = result.orderBy(fieldRef,
|
|
960
|
+
result = result.orderBy(fieldRef, import_kysely2.sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
|
|
883
961
|
}
|
|
884
962
|
} else {
|
|
885
963
|
const relationModel = fieldDef.type;
|
|
@@ -888,13 +966,13 @@ var BaseCrudDialect = class {
|
|
|
888
966
|
throw new QueryError(`invalid orderBy value for field "${field}"`);
|
|
889
967
|
}
|
|
890
968
|
if ("_count" in value) {
|
|
891
|
-
(0,
|
|
969
|
+
(0, import_common_helpers2.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
892
970
|
const sort = this.negateSort(value._count, negated);
|
|
893
971
|
result = result.orderBy((eb) => {
|
|
894
972
|
const subQueryAlias = `${modelAlias}$orderBy$${field}$count`;
|
|
895
973
|
let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
|
|
896
974
|
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, subQueryAlias);
|
|
897
|
-
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(
|
|
975
|
+
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right)))));
|
|
898
976
|
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
899
977
|
return subQuery;
|
|
900
978
|
}, sort);
|
|
@@ -902,7 +980,7 @@ var BaseCrudDialect = class {
|
|
|
902
980
|
} else {
|
|
903
981
|
result = result.leftJoin(relationModel, (join) => {
|
|
904
982
|
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
|
|
905
|
-
return join.on((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(
|
|
983
|
+
return join.on((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right)))));
|
|
906
984
|
});
|
|
907
985
|
result = this.buildOrderBy(result, fieldDef.type, relationModel, value, false, negated);
|
|
908
986
|
}
|
|
@@ -954,13 +1032,13 @@ var BaseCrudDialect = class {
|
|
|
954
1032
|
if (fieldDef.computed) {
|
|
955
1033
|
return query.select((eb) => this.fieldRef(model, field, eb, modelAlias).as(field));
|
|
956
1034
|
} else if (!fieldDef.originModel) {
|
|
957
|
-
return query.select(
|
|
1035
|
+
return query.select(import_kysely2.sql.ref(`${modelAlias}.${field}`).as(field));
|
|
958
1036
|
} else {
|
|
959
1037
|
return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
|
|
960
1038
|
}
|
|
961
1039
|
}
|
|
962
1040
|
buildDelegateJoin(thisModel, thisModelAlias, otherModelAlias, query) {
|
|
963
|
-
const idFields =
|
|
1041
|
+
const idFields = requireIdFields(this.schema, thisModel);
|
|
964
1042
|
query = query.leftJoin(otherModelAlias, (qb) => {
|
|
965
1043
|
for (const idField of idFields) {
|
|
966
1044
|
qb = qb.onRef(`${thisModelAlias}.${idField}`, "=", `${otherModelAlias}.${idField}`);
|
|
@@ -982,10 +1060,16 @@ var BaseCrudDialect = class {
|
|
|
982
1060
|
for (const [field, value] of Object.entries(selections.select)) {
|
|
983
1061
|
const fieldDef = requireField(this.schema, model, field);
|
|
984
1062
|
const fieldModel = fieldDef.type;
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
fieldCountQuery =
|
|
1063
|
+
let fieldCountQuery;
|
|
1064
|
+
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
1065
|
+
if (m2m) {
|
|
1066
|
+
fieldCountQuery = eb.selectFrom(fieldModel).innerJoin(m2m.joinTable, (join) => join.onRef(`${m2m.joinTable}.${m2m.otherFkName}`, "=", `${fieldModel}.${m2m.otherPKName}`).onRef(`${m2m.joinTable}.${m2m.parentFkName}`, "=", `${parentAlias}.${m2m.parentPKName}`)).select(eb.fn.countAll().as(`_count$${field}`));
|
|
1067
|
+
} else {
|
|
1068
|
+
fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
1069
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
1070
|
+
for (const [left, right] of joinPairs) {
|
|
1071
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
1072
|
+
}
|
|
989
1073
|
}
|
|
990
1074
|
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
991
1075
|
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
@@ -1065,6 +1149,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1065
1149
|
static {
|
|
1066
1150
|
__name(this, "PostgresCrudDialect");
|
|
1067
1151
|
}
|
|
1152
|
+
constructor(schema, options) {
|
|
1153
|
+
super(schema, options);
|
|
1154
|
+
}
|
|
1068
1155
|
get provider() {
|
|
1069
1156
|
return "postgresql";
|
|
1070
1157
|
}
|
|
@@ -1079,8 +1166,40 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1079
1166
|
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
1080
1167
|
}
|
|
1081
1168
|
} else {
|
|
1082
|
-
return (0, import_ts_pattern3.match)(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
|
|
1169
|
+
return (0, import_ts_pattern3.match)(type).with("DateTime", () => value instanceof Date ? value.toISOString() : typeof value === "string" ? new Date(value).toISOString() : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
transformOutput(value, type) {
|
|
1173
|
+
if (value === null || value === void 0) {
|
|
1174
|
+
return value;
|
|
1175
|
+
}
|
|
1176
|
+
return (0, import_ts_pattern3.match)(type).with("DateTime", () => this.transformOutputDate(value)).with("Bytes", () => this.transformOutputBytes(value)).with("BigInt", () => this.transformOutputBigInt(value)).with("Decimal", () => this.transformDecimal(value)).otherwise(() => super.transformOutput(value, type));
|
|
1177
|
+
}
|
|
1178
|
+
transformOutputBigInt(value) {
|
|
1179
|
+
if (typeof value === "bigint") {
|
|
1180
|
+
return value;
|
|
1181
|
+
}
|
|
1182
|
+
(0, import_common_helpers3.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
1183
|
+
return BigInt(value);
|
|
1184
|
+
}
|
|
1185
|
+
transformDecimal(value) {
|
|
1186
|
+
if (value instanceof import_decimal.default) {
|
|
1187
|
+
return value;
|
|
1083
1188
|
}
|
|
1189
|
+
(0, import_common_helpers3.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal.default, `Expected string, number or Decimal, got ${typeof value}`);
|
|
1190
|
+
return new import_decimal.default(value);
|
|
1191
|
+
}
|
|
1192
|
+
transformOutputDate(value) {
|
|
1193
|
+
if (typeof value === "string") {
|
|
1194
|
+
return new Date(value);
|
|
1195
|
+
} else if (value instanceof Date && this.options.fixPostgresTimezone !== false) {
|
|
1196
|
+
return new Date(value.getTime() - value.getTimezoneOffset() * 60 * 1e3);
|
|
1197
|
+
} else {
|
|
1198
|
+
return value;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
transformOutputBytes(value) {
|
|
1202
|
+
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
1084
1203
|
}
|
|
1085
1204
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
1086
1205
|
const relationResultName = `${parentAlias}$${relationField}`;
|
|
@@ -1112,14 +1231,14 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1112
1231
|
buildRelationJoinFilter(query, model, relationField, relationModel, relationModelAlias, parentAlias) {
|
|
1113
1232
|
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
1114
1233
|
if (m2m) {
|
|
1115
|
-
const parentIds =
|
|
1116
|
-
const relationIds =
|
|
1117
|
-
(0,
|
|
1118
|
-
(0,
|
|
1234
|
+
const parentIds = requireIdFields(this.schema, model);
|
|
1235
|
+
const relationIds = requireIdFields(this.schema, relationModel);
|
|
1236
|
+
(0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1237
|
+
(0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1119
1238
|
query = query.where((eb) => eb(eb.ref(`${relationModelAlias}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
1120
1239
|
} else {
|
|
1121
1240
|
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, relationField, relationModelAlias);
|
|
1122
|
-
query = query.where((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(
|
|
1241
|
+
query = query.where((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely3.sql.ref(left), "=", import_kysely3.sql.ref(right)))));
|
|
1123
1242
|
}
|
|
1124
1243
|
return query;
|
|
1125
1244
|
}
|
|
@@ -1127,9 +1246,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1127
1246
|
qb = qb.select((eb) => {
|
|
1128
1247
|
const objArgs = this.buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName);
|
|
1129
1248
|
if (relationFieldDef.array) {
|
|
1130
|
-
return eb.fn.coalesce(
|
|
1249
|
+
return eb.fn.coalesce(import_kysely3.sql`jsonb_agg(jsonb_build_object(${import_kysely3.sql.join(objArgs)}))`, import_kysely3.sql`'[]'::jsonb`).as("$data");
|
|
1131
1250
|
} else {
|
|
1132
|
-
return
|
|
1251
|
+
return import_kysely3.sql`jsonb_build_object(${import_kysely3.sql.join(objArgs)})`.as("$data");
|
|
1133
1252
|
}
|
|
1134
1253
|
});
|
|
1135
1254
|
return qb;
|
|
@@ -1140,13 +1259,13 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1140
1259
|
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1141
1260
|
if (descendantModels.length > 0) {
|
|
1142
1261
|
objArgs.push(...descendantModels.map((subModel) => [
|
|
1143
|
-
|
|
1262
|
+
import_kysely3.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1144
1263
|
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1145
1264
|
]).flatMap((v) => v));
|
|
1146
1265
|
}
|
|
1147
1266
|
if (payload === true || !payload.select) {
|
|
1148
1267
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
1149
|
-
|
|
1268
|
+
import_kysely3.sql.lit(field),
|
|
1150
1269
|
this.fieldRef(relationModel, field, eb, relationModelAlias, false)
|
|
1151
1270
|
]).flatMap((v) => v));
|
|
1152
1271
|
} else if (payload.select) {
|
|
@@ -1154,14 +1273,14 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1154
1273
|
if (field === "_count") {
|
|
1155
1274
|
const subJson = this.buildCountJson(relationModel, eb, relationModelAlias, value);
|
|
1156
1275
|
return [
|
|
1157
|
-
|
|
1276
|
+
import_kysely3.sql.lit(field),
|
|
1158
1277
|
subJson
|
|
1159
1278
|
];
|
|
1160
1279
|
} else {
|
|
1161
1280
|
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1162
1281
|
const fieldValue = fieldDef.relation ? eb.ref(`${parentResultName}$${field}.$data`) : this.fieldRef(relationModel, field, eb, relationModelAlias, false);
|
|
1163
1282
|
return [
|
|
1164
|
-
|
|
1283
|
+
import_kysely3.sql.lit(field),
|
|
1165
1284
|
fieldValue
|
|
1166
1285
|
];
|
|
1167
1286
|
}
|
|
@@ -1169,7 +1288,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1169
1288
|
}
|
|
1170
1289
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
1171
1290
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
1172
|
-
|
|
1291
|
+
import_kysely3.sql.lit(field),
|
|
1173
1292
|
// reference the synthesized JSON field
|
|
1174
1293
|
eb.ref(`${parentResultName}$${field}.$data`)
|
|
1175
1294
|
]).flatMap((v) => v));
|
|
@@ -1199,7 +1318,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1199
1318
|
}
|
|
1200
1319
|
buildJsonObject(eb, value) {
|
|
1201
1320
|
return eb.fn("jsonb_build_object", Object.entries(value).flatMap(([key, value2]) => [
|
|
1202
|
-
|
|
1321
|
+
import_kysely3.sql.lit(key),
|
|
1203
1322
|
value2
|
|
1204
1323
|
]));
|
|
1205
1324
|
}
|
|
@@ -1227,11 +1346,33 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1227
1346
|
get supportInsertWithDefault() {
|
|
1228
1347
|
return true;
|
|
1229
1348
|
}
|
|
1349
|
+
getFieldSqlType(fieldDef) {
|
|
1350
|
+
if (fieldDef.relation) {
|
|
1351
|
+
throw new QueryError("Cannot get SQL type of a relation field");
|
|
1352
|
+
}
|
|
1353
|
+
let result;
|
|
1354
|
+
if (this.schema.enums?.[fieldDef.type]) {
|
|
1355
|
+
result = "text";
|
|
1356
|
+
} else {
|
|
1357
|
+
result = (0, import_ts_pattern3.match)(fieldDef.type).with("String", () => "text").with("Boolean", () => "boolean").with("Int", () => "integer").with("BigInt", () => "bigint").with("Float", () => "double precision").with("Decimal", () => "decimal").with("DateTime", () => "timestamp").with("Bytes", () => "bytea").with("Json", () => "jsonb").otherwise(() => "text");
|
|
1358
|
+
}
|
|
1359
|
+
if (fieldDef.array) {
|
|
1360
|
+
result += "[]";
|
|
1361
|
+
}
|
|
1362
|
+
return result;
|
|
1363
|
+
}
|
|
1364
|
+
getStringCasingBehavior() {
|
|
1365
|
+
return {
|
|
1366
|
+
supportsILike: true,
|
|
1367
|
+
likeCaseSensitive: true
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1230
1370
|
};
|
|
1231
1371
|
|
|
1232
1372
|
// src/client/crud/dialects/sqlite.ts
|
|
1233
|
-
var
|
|
1234
|
-
var
|
|
1373
|
+
var import_common_helpers4 = require("@zenstackhq/common-helpers");
|
|
1374
|
+
var import_decimal2 = __toESM(require("decimal.js"), 1);
|
|
1375
|
+
var import_kysely4 = require("kysely");
|
|
1235
1376
|
var import_ts_pattern4 = require("ts-pattern");
|
|
1236
1377
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
1237
1378
|
static {
|
|
@@ -1250,9 +1391,57 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1250
1391
|
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1251
1392
|
return JSON.stringify(value);
|
|
1252
1393
|
} else {
|
|
1253
|
-
return (0, import_ts_pattern4.match)(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).with("Json", () => JSON.stringify(value)).otherwise(() => value);
|
|
1394
|
+
return (0, import_ts_pattern4.match)(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : typeof value === "string" ? new Date(value).toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).with("Json", () => JSON.stringify(value)).otherwise(() => value);
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
transformOutput(value, type) {
|
|
1399
|
+
if (value === null || value === void 0) {
|
|
1400
|
+
return value;
|
|
1401
|
+
} else if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1402
|
+
return this.transformOutputJson(value);
|
|
1403
|
+
} else {
|
|
1404
|
+
return (0, import_ts_pattern4.match)(type).with("Boolean", () => this.transformOutputBoolean(value)).with("DateTime", () => this.transformOutputDate(value)).with("Bytes", () => this.transformOutputBytes(value)).with("Decimal", () => this.transformOutputDecimal(value)).with("BigInt", () => this.transformOutputBigInt(value)).with("Json", () => this.transformOutputJson(value)).otherwise(() => super.transformOutput(value, type));
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
transformOutputDecimal(value) {
|
|
1408
|
+
if (value instanceof import_decimal2.default) {
|
|
1409
|
+
return value;
|
|
1410
|
+
}
|
|
1411
|
+
(0, import_common_helpers4.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal2.default, `Expected string, number or Decimal, got ${typeof value}`);
|
|
1412
|
+
return new import_decimal2.default(value);
|
|
1413
|
+
}
|
|
1414
|
+
transformOutputBigInt(value) {
|
|
1415
|
+
if (typeof value === "bigint") {
|
|
1416
|
+
return value;
|
|
1417
|
+
}
|
|
1418
|
+
(0, import_common_helpers4.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
1419
|
+
return BigInt(value);
|
|
1420
|
+
}
|
|
1421
|
+
transformOutputBoolean(value) {
|
|
1422
|
+
return !!value;
|
|
1423
|
+
}
|
|
1424
|
+
transformOutputDate(value) {
|
|
1425
|
+
if (typeof value === "number") {
|
|
1426
|
+
return new Date(value);
|
|
1427
|
+
} else if (typeof value === "string") {
|
|
1428
|
+
return new Date(value);
|
|
1429
|
+
} else {
|
|
1430
|
+
return value;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
transformOutputBytes(value) {
|
|
1434
|
+
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
1435
|
+
}
|
|
1436
|
+
transformOutputJson(value) {
|
|
1437
|
+
if (typeof value === "string") {
|
|
1438
|
+
try {
|
|
1439
|
+
return JSON.parse(value);
|
|
1440
|
+
} catch (e) {
|
|
1441
|
+
throw new QueryError("Invalid JSON returned", e);
|
|
1254
1442
|
}
|
|
1255
1443
|
}
|
|
1444
|
+
return value;
|
|
1256
1445
|
}
|
|
1257
1446
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
1258
1447
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
@@ -1279,13 +1468,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1279
1468
|
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1280
1469
|
if (descendantModels.length > 0) {
|
|
1281
1470
|
objArgs.push(...descendantModels.map((subModel) => [
|
|
1282
|
-
|
|
1471
|
+
import_kysely4.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1283
1472
|
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1284
1473
|
]).flatMap((v) => v));
|
|
1285
1474
|
}
|
|
1286
1475
|
if (payload === true || !payload.select) {
|
|
1287
1476
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
1288
|
-
|
|
1477
|
+
import_kysely4.sql.lit(field),
|
|
1289
1478
|
this.fieldRef(relationModel, field, eb, subQueryName, false)
|
|
1290
1479
|
]).flatMap((v) => v));
|
|
1291
1480
|
} else if (payload.select) {
|
|
@@ -1293,7 +1482,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1293
1482
|
if (field === "_count") {
|
|
1294
1483
|
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1295
1484
|
return [
|
|
1296
|
-
|
|
1485
|
+
import_kysely4.sql.lit(field),
|
|
1297
1486
|
subJson
|
|
1298
1487
|
];
|
|
1299
1488
|
} else {
|
|
@@ -1301,12 +1490,12 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1301
1490
|
if (fieldDef.relation) {
|
|
1302
1491
|
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1303
1492
|
return [
|
|
1304
|
-
|
|
1493
|
+
import_kysely4.sql.lit(field),
|
|
1305
1494
|
subJson
|
|
1306
1495
|
];
|
|
1307
1496
|
} else {
|
|
1308
1497
|
return [
|
|
1309
|
-
|
|
1498
|
+
import_kysely4.sql.lit(field),
|
|
1310
1499
|
this.fieldRef(relationModel, field, eb, subQueryName, false)
|
|
1311
1500
|
];
|
|
1312
1501
|
}
|
|
@@ -1317,15 +1506,15 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1317
1506
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
1318
1507
|
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1319
1508
|
return [
|
|
1320
|
-
|
|
1509
|
+
import_kysely4.sql.lit(field),
|
|
1321
1510
|
subJson
|
|
1322
1511
|
];
|
|
1323
1512
|
}).flatMap((v) => v));
|
|
1324
1513
|
}
|
|
1325
1514
|
if (relationFieldDef.array) {
|
|
1326
|
-
return eb.fn.coalesce(
|
|
1515
|
+
return eb.fn.coalesce(import_kysely4.sql`json_group_array(json_object(${import_kysely4.sql.join(objArgs)}))`, import_kysely4.sql`json_array()`).as("$data");
|
|
1327
1516
|
} else {
|
|
1328
|
-
return
|
|
1517
|
+
return import_kysely4.sql`json_object(${import_kysely4.sql.join(objArgs)})`.as("$data");
|
|
1329
1518
|
}
|
|
1330
1519
|
});
|
|
1331
1520
|
return tbl;
|
|
@@ -1335,10 +1524,10 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1335
1524
|
const relationModel = fieldDef.type;
|
|
1336
1525
|
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
1337
1526
|
if (m2m) {
|
|
1338
|
-
const parentIds =
|
|
1339
|
-
const relationIds =
|
|
1340
|
-
(0,
|
|
1341
|
-
(0,
|
|
1527
|
+
const parentIds = requireIdFields(this.schema, model);
|
|
1528
|
+
const relationIds = requireIdFields(this.schema, relationModel);
|
|
1529
|
+
(0, import_common_helpers4.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1530
|
+
(0, import_common_helpers4.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1342
1531
|
selectModelQuery = selectModelQuery.where((eb) => eb(eb.ref(`${relationModelAlias}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
1343
1532
|
} else {
|
|
1344
1533
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
@@ -1366,7 +1555,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1366
1555
|
}
|
|
1367
1556
|
buildJsonObject(eb, value) {
|
|
1368
1557
|
return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
|
|
1369
|
-
|
|
1558
|
+
import_kysely4.sql.lit(key),
|
|
1370
1559
|
value2
|
|
1371
1560
|
]));
|
|
1372
1561
|
}
|
|
@@ -1390,6 +1579,24 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1390
1579
|
get supportInsertWithDefault() {
|
|
1391
1580
|
return false;
|
|
1392
1581
|
}
|
|
1582
|
+
getFieldSqlType(fieldDef) {
|
|
1583
|
+
if (fieldDef.relation) {
|
|
1584
|
+
throw new QueryError("Cannot get SQL type of a relation field");
|
|
1585
|
+
}
|
|
1586
|
+
if (fieldDef.array) {
|
|
1587
|
+
throw new QueryError("SQLite does not support scalar list type");
|
|
1588
|
+
}
|
|
1589
|
+
if (this.schema.enums?.[fieldDef.type]) {
|
|
1590
|
+
return "text";
|
|
1591
|
+
}
|
|
1592
|
+
return (0, import_ts_pattern4.match)(fieldDef.type).with("String", () => "text").with("Boolean", () => "integer").with("Int", () => "integer").with("BigInt", () => "integer").with("Float", () => "real").with("Decimal", () => "decimal").with("DateTime", () => "numeric").with("Bytes", () => "blob").with("Json", () => "jsonb").otherwise(() => "text");
|
|
1593
|
+
}
|
|
1594
|
+
getStringCasingBehavior() {
|
|
1595
|
+
return {
|
|
1596
|
+
supportsILike: false,
|
|
1597
|
+
likeCaseSensitive: false
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1393
1600
|
};
|
|
1394
1601
|
|
|
1395
1602
|
// src/client/crud/dialects/index.ts
|
|
@@ -1399,8 +1606,8 @@ function getCrudDialect(schema, options) {
|
|
|
1399
1606
|
__name(getCrudDialect, "getCrudDialect");
|
|
1400
1607
|
|
|
1401
1608
|
// src/utils/default-operation-node-visitor.ts
|
|
1402
|
-
var
|
|
1403
|
-
var DefaultOperationNodeVisitor = class extends
|
|
1609
|
+
var import_kysely5 = require("kysely");
|
|
1610
|
+
var DefaultOperationNodeVisitor = class extends import_kysely5.OperationNodeVisitor {
|
|
1404
1611
|
static {
|
|
1405
1612
|
__name(this, "DefaultOperationNodeVisitor");
|
|
1406
1613
|
}
|
|
@@ -1717,12 +1924,12 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1717
1924
|
};
|
|
1718
1925
|
|
|
1719
1926
|
// src/plugins/policy/expression-transformer.ts
|
|
1720
|
-
var
|
|
1721
|
-
var
|
|
1927
|
+
var import_common_helpers6 = require("@zenstackhq/common-helpers");
|
|
1928
|
+
var import_kysely7 = require("kysely");
|
|
1722
1929
|
var import_ts_pattern7 = require("ts-pattern");
|
|
1723
1930
|
|
|
1724
1931
|
// src/plugins/policy/expression-evaluator.ts
|
|
1725
|
-
var
|
|
1932
|
+
var import_common_helpers5 = require("@zenstackhq/common-helpers");
|
|
1726
1933
|
var import_ts_pattern6 = require("ts-pattern");
|
|
1727
1934
|
var ExpressionEvaluator = class {
|
|
1728
1935
|
static {
|
|
@@ -1766,18 +1973,18 @@ var ExpressionEvaluator = class {
|
|
|
1766
1973
|
const right = this.evaluate(expr2.right, context);
|
|
1767
1974
|
return (0, import_ts_pattern6.match)(expr2.op).with("==", () => left === right).with("!=", () => left !== right).with(">", () => left > right).with(">=", () => left >= right).with("<", () => left < right).with("<=", () => left <= right).with("&&", () => left && right).with("||", () => left || right).with("in", () => {
|
|
1768
1975
|
const _right = right ?? [];
|
|
1769
|
-
(0,
|
|
1976
|
+
(0, import_common_helpers5.invariant)(Array.isArray(_right), 'expected array for "in" operator');
|
|
1770
1977
|
return _right.includes(left);
|
|
1771
1978
|
}).exhaustive();
|
|
1772
1979
|
}
|
|
1773
1980
|
evaluateCollectionPredicate(expr2, context) {
|
|
1774
1981
|
const op = expr2.op;
|
|
1775
|
-
(0,
|
|
1982
|
+
(0, import_common_helpers5.invariant)(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
|
|
1776
1983
|
const left = this.evaluate(expr2.left, context);
|
|
1777
1984
|
if (!left) {
|
|
1778
1985
|
return false;
|
|
1779
1986
|
}
|
|
1780
|
-
(0,
|
|
1987
|
+
(0, import_common_helpers5.invariant)(Array.isArray(left), "expected array");
|
|
1781
1988
|
return (0, import_ts_pattern6.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1782
1989
|
...context,
|
|
1783
1990
|
thisValue: item
|
|
@@ -1792,24 +1999,30 @@ var ExpressionEvaluator = class {
|
|
|
1792
1999
|
};
|
|
1793
2000
|
|
|
1794
2001
|
// src/plugins/policy/utils.ts
|
|
1795
|
-
var
|
|
2002
|
+
var import_kysely6 = require("kysely");
|
|
1796
2003
|
function trueNode(dialect) {
|
|
1797
|
-
return
|
|
2004
|
+
return import_kysely6.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1798
2005
|
}
|
|
1799
2006
|
__name(trueNode, "trueNode");
|
|
1800
2007
|
function falseNode(dialect) {
|
|
1801
|
-
return
|
|
2008
|
+
return import_kysely6.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1802
2009
|
}
|
|
1803
2010
|
__name(falseNode, "falseNode");
|
|
1804
2011
|
function isTrueNode(node) {
|
|
1805
|
-
return
|
|
2012
|
+
return import_kysely6.ValueNode.is(node) && (node.value === true || node.value === 1);
|
|
1806
2013
|
}
|
|
1807
2014
|
__name(isTrueNode, "isTrueNode");
|
|
1808
2015
|
function isFalseNode(node) {
|
|
1809
|
-
return
|
|
2016
|
+
return import_kysely6.ValueNode.is(node) && (node.value === false || node.value === 0);
|
|
1810
2017
|
}
|
|
1811
2018
|
__name(isFalseNode, "isFalseNode");
|
|
1812
2019
|
function conjunction(dialect, nodes) {
|
|
2020
|
+
if (nodes.length === 0) {
|
|
2021
|
+
return trueNode(dialect);
|
|
2022
|
+
}
|
|
2023
|
+
if (nodes.length === 1) {
|
|
2024
|
+
return nodes[0];
|
|
2025
|
+
}
|
|
1813
2026
|
if (nodes.some(isFalseNode)) {
|
|
1814
2027
|
return falseNode(dialect);
|
|
1815
2028
|
}
|
|
@@ -1817,10 +2030,16 @@ function conjunction(dialect, nodes) {
|
|
|
1817
2030
|
if (items.length === 0) {
|
|
1818
2031
|
return trueNode(dialect);
|
|
1819
2032
|
}
|
|
1820
|
-
return items.reduce((acc, node) =>
|
|
2033
|
+
return items.reduce((acc, node) => import_kysely6.AndNode.create(wrapParensIf(acc, import_kysely6.OrNode.is), wrapParensIf(node, import_kysely6.OrNode.is)));
|
|
1821
2034
|
}
|
|
1822
2035
|
__name(conjunction, "conjunction");
|
|
1823
2036
|
function disjunction(dialect, nodes) {
|
|
2037
|
+
if (nodes.length === 0) {
|
|
2038
|
+
return falseNode(dialect);
|
|
2039
|
+
}
|
|
2040
|
+
if (nodes.length === 1) {
|
|
2041
|
+
return nodes[0];
|
|
2042
|
+
}
|
|
1824
2043
|
if (nodes.some(isTrueNode)) {
|
|
1825
2044
|
return trueNode(dialect);
|
|
1826
2045
|
}
|
|
@@ -1828,26 +2047,36 @@ function disjunction(dialect, nodes) {
|
|
|
1828
2047
|
if (items.length === 0) {
|
|
1829
2048
|
return falseNode(dialect);
|
|
1830
2049
|
}
|
|
1831
|
-
return items.reduce((acc, node) =>
|
|
2050
|
+
return items.reduce((acc, node) => import_kysely6.OrNode.create(wrapParensIf(acc, import_kysely6.AndNode.is), wrapParensIf(node, import_kysely6.AndNode.is)));
|
|
1832
2051
|
}
|
|
1833
2052
|
__name(disjunction, "disjunction");
|
|
1834
|
-
function logicalNot(node) {
|
|
1835
|
-
|
|
2053
|
+
function logicalNot(dialect, node) {
|
|
2054
|
+
if (isTrueNode(node)) {
|
|
2055
|
+
return falseNode(dialect);
|
|
2056
|
+
}
|
|
2057
|
+
if (isFalseNode(node)) {
|
|
2058
|
+
return trueNode(dialect);
|
|
2059
|
+
}
|
|
2060
|
+
return import_kysely6.UnaryOperationNode.create(import_kysely6.OperatorNode.create("not"), wrapParensIf(node, (n) => import_kysely6.AndNode.is(n) || import_kysely6.OrNode.is(n)));
|
|
1836
2061
|
}
|
|
1837
2062
|
__name(logicalNot, "logicalNot");
|
|
2063
|
+
function wrapParensIf(node, predicate) {
|
|
2064
|
+
return predicate(node) ? import_kysely6.ParensNode.create(node) : node;
|
|
2065
|
+
}
|
|
2066
|
+
__name(wrapParensIf, "wrapParensIf");
|
|
1838
2067
|
function buildIsFalse(node, dialect) {
|
|
1839
2068
|
if (isFalseNode(node)) {
|
|
1840
2069
|
return trueNode(dialect);
|
|
1841
2070
|
} else if (isTrueNode(node)) {
|
|
1842
2071
|
return falseNode(dialect);
|
|
1843
2072
|
}
|
|
1844
|
-
return
|
|
2073
|
+
return import_kysely6.BinaryOperationNode.create(
|
|
1845
2074
|
// coalesce so null is treated as false
|
|
1846
|
-
|
|
2075
|
+
import_kysely6.FunctionNode.create("coalesce", [
|
|
1847
2076
|
node,
|
|
1848
2077
|
falseNode(dialect)
|
|
1849
2078
|
]),
|
|
1850
|
-
|
|
2079
|
+
import_kysely6.OperatorNode.create("="),
|
|
1851
2080
|
falseNode(dialect)
|
|
1852
2081
|
);
|
|
1853
2082
|
}
|
|
@@ -1856,11 +2085,11 @@ function getTableName(node) {
|
|
|
1856
2085
|
if (!node) {
|
|
1857
2086
|
return node;
|
|
1858
2087
|
}
|
|
1859
|
-
if (
|
|
2088
|
+
if (import_kysely6.TableNode.is(node)) {
|
|
1860
2089
|
return node.table.identifier.name;
|
|
1861
|
-
} else if (
|
|
2090
|
+
} else if (import_kysely6.AliasNode.is(node)) {
|
|
1862
2091
|
return getTableName(node.node);
|
|
1863
|
-
} else if (
|
|
2092
|
+
} else if (import_kysely6.ReferenceNode.is(node) && node.table) {
|
|
1864
2093
|
return getTableName(node.table);
|
|
1865
2094
|
}
|
|
1866
2095
|
return void 0;
|
|
@@ -1893,16 +2122,21 @@ var ExpressionTransformer = class {
|
|
|
1893
2122
|
static {
|
|
1894
2123
|
__name(this, "ExpressionTransformer");
|
|
1895
2124
|
}
|
|
1896
|
-
|
|
1897
|
-
clientOptions;
|
|
1898
|
-
auth;
|
|
2125
|
+
client;
|
|
1899
2126
|
dialect;
|
|
1900
|
-
constructor(
|
|
1901
|
-
this.
|
|
1902
|
-
this.clientOptions = clientOptions;
|
|
1903
|
-
this.auth = auth;
|
|
2127
|
+
constructor(client) {
|
|
2128
|
+
this.client = client;
|
|
1904
2129
|
this.dialect = getCrudDialect(this.schema, this.clientOptions);
|
|
1905
2130
|
}
|
|
2131
|
+
get schema() {
|
|
2132
|
+
return this.client.$schema;
|
|
2133
|
+
}
|
|
2134
|
+
get clientOptions() {
|
|
2135
|
+
return this.client.$options;
|
|
2136
|
+
}
|
|
2137
|
+
get auth() {
|
|
2138
|
+
return this.client.$auth;
|
|
2139
|
+
}
|
|
1906
2140
|
get authType() {
|
|
1907
2141
|
if (!this.schema.authType) {
|
|
1908
2142
|
throw new InternalError('Schema does not have an "authType" specified');
|
|
@@ -1920,16 +2154,12 @@ var ExpressionTransformer = class {
|
|
|
1920
2154
|
return this.transformValue(expr2.value, typeof expr2.value === "string" ? "String" : typeof expr2.value === "boolean" ? "Boolean" : "Int");
|
|
1921
2155
|
}
|
|
1922
2156
|
_array(expr2, context) {
|
|
1923
|
-
return
|
|
2157
|
+
return import_kysely7.ValueListNode.create(expr2.items.map((item) => this.transform(item, context)));
|
|
1924
2158
|
}
|
|
1925
2159
|
_field(expr2, context) {
|
|
1926
2160
|
const fieldDef = requireField(this.schema, context.model, expr2.field);
|
|
1927
2161
|
if (!fieldDef.relation) {
|
|
1928
|
-
|
|
1929
|
-
return context.thisEntity[expr2.field];
|
|
1930
|
-
} else {
|
|
1931
|
-
return this.createColumnRef(expr2.field, context);
|
|
1932
|
-
}
|
|
2162
|
+
return this.createColumnRef(expr2.field, context);
|
|
1933
2163
|
} else {
|
|
1934
2164
|
const { memberFilter, memberSelect, ...restContext } = context;
|
|
1935
2165
|
const relation = this.transformRelationAccess(expr2.field, fieldDef.type, restContext);
|
|
@@ -1944,18 +2174,18 @@ var ExpressionTransformer = class {
|
|
|
1944
2174
|
}
|
|
1945
2175
|
mergeWhere(where, memberFilter) {
|
|
1946
2176
|
if (!where) {
|
|
1947
|
-
return
|
|
2177
|
+
return import_kysely7.WhereNode.create(memberFilter ?? trueNode(this.dialect));
|
|
1948
2178
|
}
|
|
1949
2179
|
if (!memberFilter) {
|
|
1950
2180
|
return where;
|
|
1951
2181
|
}
|
|
1952
|
-
return
|
|
2182
|
+
return import_kysely7.WhereNode.create(conjunction(this.dialect, [
|
|
1953
2183
|
where.where,
|
|
1954
2184
|
memberFilter
|
|
1955
2185
|
]));
|
|
1956
2186
|
}
|
|
1957
2187
|
_null() {
|
|
1958
|
-
return
|
|
2188
|
+
return import_kysely7.ValueNode.createImmediate(null);
|
|
1959
2189
|
}
|
|
1960
2190
|
_binary(expr2, context) {
|
|
1961
2191
|
if (expr2.op === "&&") {
|
|
@@ -1970,51 +2200,88 @@ var ExpressionTransformer = class {
|
|
|
1970
2200
|
]);
|
|
1971
2201
|
}
|
|
1972
2202
|
if (this.isAuthCall(expr2.left) || this.isAuthCall(expr2.right)) {
|
|
1973
|
-
return this.transformAuthBinary(expr2);
|
|
2203
|
+
return this.transformAuthBinary(expr2, context);
|
|
1974
2204
|
}
|
|
1975
2205
|
const op = expr2.op;
|
|
1976
2206
|
if (op === "?" || op === "!" || op === "^") {
|
|
1977
2207
|
return this.transformCollectionPredicate(expr2, context);
|
|
1978
2208
|
}
|
|
1979
|
-
const
|
|
1980
|
-
const
|
|
2209
|
+
const { normalizedLeft, normalizedRight } = this.normalizeBinaryOperationOperands(expr2, context);
|
|
2210
|
+
const left = this.transform(normalizedLeft, context);
|
|
2211
|
+
const right = this.transform(normalizedRight, context);
|
|
1981
2212
|
if (op === "in") {
|
|
1982
2213
|
if (this.isNullNode(left)) {
|
|
1983
2214
|
return this.transformValue(false, "Boolean");
|
|
1984
2215
|
} else {
|
|
1985
|
-
if (
|
|
1986
|
-
return
|
|
2216
|
+
if (import_kysely7.ValueListNode.is(right)) {
|
|
2217
|
+
return import_kysely7.BinaryOperationNode.create(left, import_kysely7.OperatorNode.create("in"), right);
|
|
1987
2218
|
} else {
|
|
1988
|
-
return
|
|
2219
|
+
return import_kysely7.BinaryOperationNode.create(left, import_kysely7.OperatorNode.create("="), import_kysely7.FunctionNode.create("any", [
|
|
1989
2220
|
right
|
|
1990
2221
|
]));
|
|
1991
2222
|
}
|
|
1992
2223
|
}
|
|
1993
2224
|
}
|
|
1994
2225
|
if (this.isNullNode(right)) {
|
|
1995
|
-
return
|
|
2226
|
+
return this.transformNullCheck(left, expr2.op);
|
|
1996
2227
|
} else if (this.isNullNode(left)) {
|
|
1997
|
-
return
|
|
2228
|
+
return this.transformNullCheck(right, expr2.op);
|
|
2229
|
+
} else {
|
|
2230
|
+
return import_kysely7.BinaryOperationNode.create(left, this.transformOperator(op), right);
|
|
1998
2231
|
}
|
|
1999
|
-
|
|
2232
|
+
}
|
|
2233
|
+
transformNullCheck(expr2, operator) {
|
|
2234
|
+
(0, import_common_helpers6.invariant)(operator === "==" || operator === "!=", 'operator must be "==" or "!=" for null comparison');
|
|
2235
|
+
if (import_kysely7.ValueNode.is(expr2)) {
|
|
2236
|
+
if (expr2.value === null) {
|
|
2237
|
+
return operator === "==" ? trueNode(this.dialect) : falseNode(this.dialect);
|
|
2238
|
+
} else {
|
|
2239
|
+
return operator === "==" ? falseNode(this.dialect) : trueNode(this.dialect);
|
|
2240
|
+
}
|
|
2241
|
+
} else {
|
|
2242
|
+
return operator === "==" ? import_kysely7.BinaryOperationNode.create(expr2, import_kysely7.OperatorNode.create("is"), import_kysely7.ValueNode.createImmediate(null)) : import_kysely7.BinaryOperationNode.create(expr2, import_kysely7.OperatorNode.create("is not"), import_kysely7.ValueNode.createImmediate(null));
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
normalizeBinaryOperationOperands(expr2, context) {
|
|
2246
|
+
let normalizedLeft = expr2.left;
|
|
2247
|
+
if (this.isRelationField(expr2.left, context.model)) {
|
|
2248
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isNull(expr2.right), "only null comparison is supported for relation field");
|
|
2249
|
+
const leftRelDef = this.getFieldDefFromFieldRef(expr2.left, context.model);
|
|
2250
|
+
(0, import_common_helpers6.invariant)(leftRelDef, "failed to get relation field definition");
|
|
2251
|
+
const idFields = requireIdFields(this.schema, leftRelDef.type);
|
|
2252
|
+
normalizedLeft = this.makeOrAppendMember(normalizedLeft, idFields[0]);
|
|
2253
|
+
}
|
|
2254
|
+
let normalizedRight = expr2.right;
|
|
2255
|
+
if (this.isRelationField(expr2.right, context.model)) {
|
|
2256
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isNull(expr2.left), "only null comparison is supported for relation field");
|
|
2257
|
+
const rightRelDef = this.getFieldDefFromFieldRef(expr2.right, context.model);
|
|
2258
|
+
(0, import_common_helpers6.invariant)(rightRelDef, "failed to get relation field definition");
|
|
2259
|
+
const idFields = requireIdFields(this.schema, rightRelDef.type);
|
|
2260
|
+
normalizedRight = this.makeOrAppendMember(normalizedRight, idFields[0]);
|
|
2261
|
+
}
|
|
2262
|
+
return {
|
|
2263
|
+
normalizedLeft,
|
|
2264
|
+
normalizedRight
|
|
2265
|
+
};
|
|
2000
2266
|
}
|
|
2001
2267
|
transformCollectionPredicate(expr2, context) {
|
|
2002
|
-
(0,
|
|
2268
|
+
(0, import_common_helpers6.invariant)(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
|
|
2003
2269
|
if (this.isAuthCall(expr2.left) || this.isAuthMember(expr2.left)) {
|
|
2004
2270
|
const value = new ExpressionEvaluator().evaluate(expr2, {
|
|
2005
2271
|
auth: this.auth
|
|
2006
2272
|
});
|
|
2007
2273
|
return this.transformValue(value, "Boolean");
|
|
2008
2274
|
}
|
|
2009
|
-
(0,
|
|
2275
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
|
|
2010
2276
|
let newContextModel;
|
|
2011
|
-
|
|
2012
|
-
|
|
2277
|
+
const fieldDef = this.getFieldDefFromFieldRef(expr2.left, context.model);
|
|
2278
|
+
if (fieldDef) {
|
|
2279
|
+
(0, import_common_helpers6.invariant)(fieldDef.relation, `field is not a relation: ${JSON.stringify(expr2.left)}`);
|
|
2013
2280
|
newContextModel = fieldDef.type;
|
|
2014
2281
|
} else {
|
|
2015
|
-
(0,
|
|
2016
|
-
const
|
|
2017
|
-
newContextModel =
|
|
2282
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isMember(expr2.left) && ExpressionUtils.isField(expr2.left.receiver), "left operand must be member access with field receiver");
|
|
2283
|
+
const fieldDef2 = requireField(this.schema, context.model, expr2.left.receiver.field);
|
|
2284
|
+
newContextModel = fieldDef2.type;
|
|
2018
2285
|
for (const member of expr2.left.members) {
|
|
2019
2286
|
const memberDef = requireField(this.schema, newContextModel, member);
|
|
2020
2287
|
newContextModel = memberDef.type;
|
|
@@ -2023,71 +2290,118 @@ var ExpressionTransformer = class {
|
|
|
2023
2290
|
let predicateFilter = this.transform(expr2.right, {
|
|
2024
2291
|
...context,
|
|
2025
2292
|
model: newContextModel,
|
|
2026
|
-
alias: void 0
|
|
2027
|
-
thisEntity: void 0
|
|
2293
|
+
alias: void 0
|
|
2028
2294
|
});
|
|
2029
2295
|
if (expr2.op === "!") {
|
|
2030
|
-
predicateFilter = logicalNot(predicateFilter);
|
|
2296
|
+
predicateFilter = logicalNot(this.dialect, predicateFilter);
|
|
2031
2297
|
}
|
|
2032
|
-
const count =
|
|
2033
|
-
|
|
2298
|
+
const count = import_kysely7.FunctionNode.create("count", [
|
|
2299
|
+
import_kysely7.ValueNode.createImmediate(1)
|
|
2034
2300
|
]);
|
|
2035
|
-
const predicateResult = (0, import_ts_pattern7.match)(expr2.op).with("?", () =>
|
|
2301
|
+
const predicateResult = (0, import_ts_pattern7.match)(expr2.op).with("?", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create(">"), import_kysely7.ValueNode.createImmediate(0))).with("!", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create("="), import_kysely7.ValueNode.createImmediate(0))).with("^", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create("="), import_kysely7.ValueNode.createImmediate(0))).exhaustive();
|
|
2036
2302
|
return this.transform(expr2.left, {
|
|
2037
2303
|
...context,
|
|
2038
|
-
memberSelect:
|
|
2304
|
+
memberSelect: import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(predicateResult, import_kysely7.IdentifierNode.create("$t"))),
|
|
2039
2305
|
memberFilter: predicateFilter
|
|
2040
2306
|
});
|
|
2041
2307
|
}
|
|
2042
|
-
transformAuthBinary(expr2) {
|
|
2308
|
+
transformAuthBinary(expr2, context) {
|
|
2043
2309
|
if (expr2.op !== "==" && expr2.op !== "!=") {
|
|
2044
|
-
throw new
|
|
2310
|
+
throw new QueryError(`Unsupported operator for \`auth()\` in policy of model "${context.model}": ${expr2.op}`);
|
|
2045
2311
|
}
|
|
2312
|
+
let authExpr;
|
|
2046
2313
|
let other;
|
|
2047
2314
|
if (this.isAuthCall(expr2.left)) {
|
|
2315
|
+
authExpr = expr2.left;
|
|
2048
2316
|
other = expr2.right;
|
|
2049
2317
|
} else {
|
|
2318
|
+
authExpr = expr2.right;
|
|
2050
2319
|
other = expr2.left;
|
|
2051
2320
|
}
|
|
2052
2321
|
if (ExpressionUtils.isNull(other)) {
|
|
2053
2322
|
return this.transformValue(expr2.op === "==" ? !this.auth : !!this.auth, "Boolean");
|
|
2054
2323
|
} else {
|
|
2055
|
-
|
|
2324
|
+
const authModel = getModel(this.schema, this.authType);
|
|
2325
|
+
if (!authModel) {
|
|
2326
|
+
throw new QueryError(`Unsupported use of \`auth()\` in policy of model "${context.model}", comparing with \`auth()\` is only possible when auth type is a model`);
|
|
2327
|
+
}
|
|
2328
|
+
const idFields = Object.values(authModel.fields).filter((f) => f.id).map((f) => f.name);
|
|
2329
|
+
(0, import_common_helpers6.invariant)(idFields.length > 0, "auth type model must have at least one id field");
|
|
2330
|
+
const conditions = idFields.map((fieldName) => ExpressionUtils.binary(ExpressionUtils.member(authExpr, [
|
|
2331
|
+
fieldName
|
|
2332
|
+
]), "==", this.makeOrAppendMember(other, fieldName)));
|
|
2333
|
+
let result = this.buildAnd(conditions);
|
|
2334
|
+
if (expr2.op === "!=") {
|
|
2335
|
+
result = this.buildLogicalNot(result);
|
|
2336
|
+
}
|
|
2337
|
+
return this.transform(result, context);
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
makeOrAppendMember(other, fieldName) {
|
|
2341
|
+
if (ExpressionUtils.isMember(other)) {
|
|
2342
|
+
return ExpressionUtils.member(other.receiver, [
|
|
2343
|
+
...other.members,
|
|
2344
|
+
fieldName
|
|
2345
|
+
]);
|
|
2346
|
+
} else {
|
|
2347
|
+
return ExpressionUtils.member(other, [
|
|
2348
|
+
fieldName
|
|
2349
|
+
]);
|
|
2056
2350
|
}
|
|
2057
2351
|
}
|
|
2058
2352
|
transformValue(value, type) {
|
|
2059
|
-
|
|
2353
|
+
if (value === true) {
|
|
2354
|
+
return trueNode(this.dialect);
|
|
2355
|
+
} else if (value === false) {
|
|
2356
|
+
return falseNode(this.dialect);
|
|
2357
|
+
} else {
|
|
2358
|
+
return import_kysely7.ValueNode.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
2359
|
+
}
|
|
2060
2360
|
}
|
|
2061
2361
|
_unary(expr2, context) {
|
|
2062
|
-
(0,
|
|
2063
|
-
return
|
|
2362
|
+
(0, import_common_helpers6.invariant)(expr2.op === "!", 'only "!" operator is supported');
|
|
2363
|
+
return logicalNot(this.dialect, this.transform(expr2.operand, context));
|
|
2064
2364
|
}
|
|
2065
2365
|
transformOperator(op) {
|
|
2066
2366
|
const mappedOp = (0, import_ts_pattern7.match)(op).with("==", () => "=").otherwise(() => op);
|
|
2067
|
-
return
|
|
2367
|
+
return import_kysely7.OperatorNode.create(mappedOp);
|
|
2068
2368
|
}
|
|
2069
2369
|
_call(expr2, context) {
|
|
2070
2370
|
const result = this.transformCall(expr2, context);
|
|
2071
2371
|
return result.toOperationNode();
|
|
2072
2372
|
}
|
|
2073
2373
|
transformCall(expr2, context) {
|
|
2074
|
-
const func = this.
|
|
2374
|
+
const func = this.getFunctionImpl(expr2.function);
|
|
2075
2375
|
if (!func) {
|
|
2076
2376
|
throw new QueryError(`Function not implemented: ${expr2.function}`);
|
|
2077
2377
|
}
|
|
2078
|
-
const eb = (0,
|
|
2378
|
+
const eb = (0, import_kysely7.expressionBuilder)();
|
|
2079
2379
|
return func(eb, (expr2.args ?? []).map((arg) => this.transformCallArg(eb, arg, context)), {
|
|
2380
|
+
client: this.client,
|
|
2080
2381
|
dialect: this.dialect,
|
|
2081
2382
|
model: context.model,
|
|
2383
|
+
modelAlias: context.alias ?? context.model,
|
|
2082
2384
|
operation: context.operation
|
|
2083
2385
|
});
|
|
2084
2386
|
}
|
|
2387
|
+
getFunctionImpl(functionName) {
|
|
2388
|
+
let func = this.clientOptions.functions?.[functionName];
|
|
2389
|
+
if (!func) {
|
|
2390
|
+
for (const plugin of this.clientOptions.plugins ?? []) {
|
|
2391
|
+
if (plugin.functions?.[functionName]) {
|
|
2392
|
+
func = plugin.functions[functionName];
|
|
2393
|
+
break;
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
return func;
|
|
2398
|
+
}
|
|
2085
2399
|
transformCallArg(eb, arg, context) {
|
|
2086
2400
|
if (ExpressionUtils.isLiteral(arg)) {
|
|
2087
2401
|
return eb.val(arg.value);
|
|
2088
2402
|
}
|
|
2089
2403
|
if (ExpressionUtils.isField(arg)) {
|
|
2090
|
-
return
|
|
2404
|
+
return eb.ref(arg.field);
|
|
2091
2405
|
}
|
|
2092
2406
|
if (ExpressionUtils.isCall(arg)) {
|
|
2093
2407
|
return this.transformCall(arg, context);
|
|
@@ -2102,14 +2416,32 @@ var ExpressionTransformer = class {
|
|
|
2102
2416
|
if (this.isAuthCall(expr2.receiver)) {
|
|
2103
2417
|
return this.valueMemberAccess(this.auth, expr2, this.authType);
|
|
2104
2418
|
}
|
|
2105
|
-
(0,
|
|
2419
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isField(expr2.receiver) || ExpressionUtils.isThis(expr2.receiver), 'expect receiver to be field expression or "this"');
|
|
2420
|
+
let members = expr2.members;
|
|
2421
|
+
let receiver;
|
|
2106
2422
|
const { memberFilter, memberSelect, ...restContext } = context;
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2423
|
+
if (ExpressionUtils.isThis(expr2.receiver)) {
|
|
2424
|
+
if (expr2.members.length === 1) {
|
|
2425
|
+
return this._field(ExpressionUtils.field(expr2.members[0]), context);
|
|
2426
|
+
} else {
|
|
2427
|
+
const firstMemberFieldDef = requireField(this.schema, context.model, expr2.members[0]);
|
|
2428
|
+
receiver = this.transformRelationAccess(expr2.members[0], firstMemberFieldDef.type, restContext);
|
|
2429
|
+
members = expr2.members.slice(1);
|
|
2430
|
+
}
|
|
2431
|
+
} else {
|
|
2432
|
+
receiver = this.transform(expr2.receiver, restContext);
|
|
2433
|
+
}
|
|
2434
|
+
(0, import_common_helpers6.invariant)(import_kysely7.SelectQueryNode.is(receiver), "expected receiver to be select query");
|
|
2435
|
+
let startType;
|
|
2436
|
+
if (ExpressionUtils.isField(expr2.receiver)) {
|
|
2437
|
+
const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
|
|
2438
|
+
startType = receiverField.type;
|
|
2439
|
+
} else {
|
|
2440
|
+
startType = context.model;
|
|
2441
|
+
}
|
|
2110
2442
|
const memberFields = [];
|
|
2111
|
-
let currType =
|
|
2112
|
-
for (const member of
|
|
2443
|
+
let currType = startType;
|
|
2444
|
+
for (const member of members) {
|
|
2113
2445
|
const fieldDef = requireField(this.schema, currType, member);
|
|
2114
2446
|
memberFields.push({
|
|
2115
2447
|
fieldDef,
|
|
@@ -2118,22 +2450,21 @@ var ExpressionTransformer = class {
|
|
|
2118
2450
|
currType = fieldDef.type;
|
|
2119
2451
|
}
|
|
2120
2452
|
let currNode = void 0;
|
|
2121
|
-
for (let i =
|
|
2122
|
-
const member =
|
|
2453
|
+
for (let i = members.length - 1; i >= 0; i--) {
|
|
2454
|
+
const member = members[i];
|
|
2123
2455
|
const { fieldDef, fromModel } = memberFields[i];
|
|
2124
2456
|
if (fieldDef.relation) {
|
|
2125
2457
|
const relation = this.transformRelationAccess(member, fieldDef.type, {
|
|
2126
2458
|
...restContext,
|
|
2127
2459
|
model: fromModel,
|
|
2128
|
-
alias: void 0
|
|
2129
|
-
thisEntity: void 0
|
|
2460
|
+
alias: void 0
|
|
2130
2461
|
});
|
|
2131
2462
|
if (currNode) {
|
|
2132
|
-
(0,
|
|
2463
|
+
(0, import_common_helpers6.invariant)(import_kysely7.SelectQueryNode.is(currNode), "expected select query node");
|
|
2133
2464
|
currNode = {
|
|
2134
2465
|
...relation,
|
|
2135
2466
|
selections: [
|
|
2136
|
-
|
|
2467
|
+
import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(currNode, import_kysely7.IdentifierNode.create(members[i + 1])))
|
|
2137
2468
|
]
|
|
2138
2469
|
};
|
|
2139
2470
|
} else {
|
|
@@ -2146,21 +2477,21 @@ var ExpressionTransformer = class {
|
|
|
2146
2477
|
};
|
|
2147
2478
|
}
|
|
2148
2479
|
} else {
|
|
2149
|
-
(0,
|
|
2150
|
-
(0,
|
|
2151
|
-
currNode =
|
|
2480
|
+
(0, import_common_helpers6.invariant)(i === members.length - 1, "plain field access must be the last segment");
|
|
2481
|
+
(0, import_common_helpers6.invariant)(!currNode, "plain field access must be the last segment");
|
|
2482
|
+
currNode = import_kysely7.ColumnNode.create(member);
|
|
2152
2483
|
}
|
|
2153
2484
|
}
|
|
2154
2485
|
return {
|
|
2155
2486
|
...receiver,
|
|
2156
2487
|
selections: [
|
|
2157
|
-
|
|
2488
|
+
import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(currNode, import_kysely7.IdentifierNode.create("$t")))
|
|
2158
2489
|
]
|
|
2159
2490
|
};
|
|
2160
2491
|
}
|
|
2161
2492
|
valueMemberAccess(receiver, expr2, receiverType) {
|
|
2162
2493
|
if (!receiver) {
|
|
2163
|
-
return
|
|
2494
|
+
return import_kysely7.ValueNode.createImmediate(null);
|
|
2164
2495
|
}
|
|
2165
2496
|
if (expr2.members.length !== 1) {
|
|
2166
2497
|
throw new Error(`Only single member access is supported`);
|
|
@@ -2171,40 +2502,33 @@ var ExpressionTransformer = class {
|
|
|
2171
2502
|
return this.transformValue(fieldValue, fieldDef.type);
|
|
2172
2503
|
}
|
|
2173
2504
|
transformRelationAccess(field, relationModel, context) {
|
|
2505
|
+
const m2m = getManyToManyRelation(this.schema, context.model, field);
|
|
2506
|
+
if (m2m) {
|
|
2507
|
+
return this.transformManyToManyRelationAccess(m2m, context);
|
|
2508
|
+
}
|
|
2174
2509
|
const fromModel = context.model;
|
|
2175
2510
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, fromModel, field);
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(relationModel)), import_kysely6.OperatorNode.create("="), context.thisEntity[fk])));
|
|
2180
|
-
} else {
|
|
2181
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(relationModel)), import_kysely6.OperatorNode.create("="), context.thisEntity[pk])));
|
|
2182
|
-
}
|
|
2183
|
-
return {
|
|
2184
|
-
kind: "SelectQueryNode",
|
|
2185
|
-
from: import_kysely6.FromNode.create([
|
|
2186
|
-
import_kysely6.TableNode.create(relationModel)
|
|
2187
|
-
]),
|
|
2188
|
-
where: import_kysely6.WhereNode.create(condition)
|
|
2189
|
-
};
|
|
2511
|
+
let condition;
|
|
2512
|
+
if (ownedByModel) {
|
|
2513
|
+
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely7.BinaryOperationNode.create(import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(fk), import_kysely7.TableNode.create(context.alias ?? fromModel)), import_kysely7.OperatorNode.create("="), import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(pk), import_kysely7.TableNode.create(relationModel)))));
|
|
2190
2514
|
} else {
|
|
2191
|
-
|
|
2192
|
-
if (ownedByModel) {
|
|
2193
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(context.alias ?? fromModel)), import_kysely6.OperatorNode.create("="), import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(relationModel)))));
|
|
2194
|
-
} else {
|
|
2195
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(context.alias ?? fromModel)), import_kysely6.OperatorNode.create("="), import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(relationModel)))));
|
|
2196
|
-
}
|
|
2197
|
-
return {
|
|
2198
|
-
kind: "SelectQueryNode",
|
|
2199
|
-
from: import_kysely6.FromNode.create([
|
|
2200
|
-
import_kysely6.TableNode.create(relationModel)
|
|
2201
|
-
]),
|
|
2202
|
-
where: import_kysely6.WhereNode.create(condition)
|
|
2203
|
-
};
|
|
2515
|
+
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely7.BinaryOperationNode.create(import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(pk), import_kysely7.TableNode.create(context.alias ?? fromModel)), import_kysely7.OperatorNode.create("="), import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(fk), import_kysely7.TableNode.create(relationModel)))));
|
|
2204
2516
|
}
|
|
2517
|
+
return {
|
|
2518
|
+
kind: "SelectQueryNode",
|
|
2519
|
+
from: import_kysely7.FromNode.create([
|
|
2520
|
+
import_kysely7.TableNode.create(relationModel)
|
|
2521
|
+
]),
|
|
2522
|
+
where: import_kysely7.WhereNode.create(condition)
|
|
2523
|
+
};
|
|
2524
|
+
}
|
|
2525
|
+
transformManyToManyRelationAccess(m2m, context) {
|
|
2526
|
+
const eb = (0, import_kysely7.expressionBuilder)();
|
|
2527
|
+
const relationQuery = eb.selectFrom(m2m.otherModel).innerJoin(m2m.joinTable, (join) => join.onRef(`${m2m.otherModel}.${m2m.otherPKName}`, "=", `${m2m.joinTable}.${m2m.otherFkName}`).onRef(`${m2m.joinTable}.${m2m.parentFkName}`, "=", `${context.alias ?? context.model}.${m2m.parentPKName}`));
|
|
2528
|
+
return relationQuery.toOperationNode();
|
|
2205
2529
|
}
|
|
2206
2530
|
createColumnRef(column, context) {
|
|
2207
|
-
return
|
|
2531
|
+
return import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(column), import_kysely7.TableNode.create(context.alias ?? context.model));
|
|
2208
2532
|
}
|
|
2209
2533
|
isAuthCall(value) {
|
|
2210
2534
|
return ExpressionUtils.isCall(value) && value.function === "auth";
|
|
@@ -2213,7 +2537,32 @@ var ExpressionTransformer = class {
|
|
|
2213
2537
|
return ExpressionUtils.isMember(expr2) && this.isAuthCall(expr2.receiver);
|
|
2214
2538
|
}
|
|
2215
2539
|
isNullNode(node) {
|
|
2216
|
-
return
|
|
2540
|
+
return import_kysely7.ValueNode.is(node) && node.value === null;
|
|
2541
|
+
}
|
|
2542
|
+
buildLogicalNot(result) {
|
|
2543
|
+
return ExpressionUtils.unary("!", result);
|
|
2544
|
+
}
|
|
2545
|
+
buildAnd(conditions) {
|
|
2546
|
+
if (conditions.length === 0) {
|
|
2547
|
+
return ExpressionUtils.literal(true);
|
|
2548
|
+
} else if (conditions.length === 1) {
|
|
2549
|
+
return conditions[0];
|
|
2550
|
+
} else {
|
|
2551
|
+
return conditions.reduce((acc, condition) => ExpressionUtils.binary(acc, "&&", condition));
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
isRelationField(expr2, model) {
|
|
2555
|
+
const fieldDef = this.getFieldDefFromFieldRef(expr2, model);
|
|
2556
|
+
return !!fieldDef?.relation;
|
|
2557
|
+
}
|
|
2558
|
+
getFieldDefFromFieldRef(expr2, model) {
|
|
2559
|
+
if (ExpressionUtils.isField(expr2)) {
|
|
2560
|
+
return requireField(this.schema, model, expr2.field);
|
|
2561
|
+
} else if (ExpressionUtils.isMember(expr2) && expr2.members.length === 1 && ExpressionUtils.isThis(expr2.receiver)) {
|
|
2562
|
+
return requireField(this.schema, model, expr2.members[0]);
|
|
2563
|
+
} else {
|
|
2564
|
+
return void 0;
|
|
2565
|
+
}
|
|
2217
2566
|
}
|
|
2218
2567
|
};
|
|
2219
2568
|
_ts_decorate([
|
|
@@ -2286,7 +2635,7 @@ _ts_decorate([
|
|
|
2286
2635
|
], ExpressionTransformer.prototype, "_member", null);
|
|
2287
2636
|
|
|
2288
2637
|
// src/plugins/policy/policy-handler.ts
|
|
2289
|
-
var PolicyHandler = class extends
|
|
2638
|
+
var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
|
|
2290
2639
|
static {
|
|
2291
2640
|
__name(this, "PolicyHandler");
|
|
2292
2641
|
}
|
|
@@ -2301,111 +2650,296 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2301
2650
|
}
|
|
2302
2651
|
async handle(node, proceed) {
|
|
2303
2652
|
if (!this.isCrudQueryNode(node)) {
|
|
2304
|
-
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
2653
|
+
throw new RejectedByPolicyError(void 0, RejectedByPolicyReason.OTHER, "non-CRUD queries are not allowed");
|
|
2305
2654
|
}
|
|
2306
2655
|
if (!this.isMutationQueryNode(node)) {
|
|
2307
2656
|
return proceed(this.transformNode(node));
|
|
2308
2657
|
}
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
if (
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2658
|
+
const { mutationModel } = this.getMutationModel(node);
|
|
2659
|
+
if (import_kysely8.InsertQueryNode.is(node)) {
|
|
2660
|
+
const isManyToManyJoinTable = this.isManyToManyJoinTable(mutationModel);
|
|
2661
|
+
let needCheckPreCreate = true;
|
|
2662
|
+
if (!isManyToManyJoinTable) {
|
|
2663
|
+
const constCondition = this.tryGetConstantPolicy(mutationModel, "create");
|
|
2664
|
+
if (constCondition === true) {
|
|
2665
|
+
needCheckPreCreate = false;
|
|
2666
|
+
} else if (constCondition === false) {
|
|
2667
|
+
throw new RejectedByPolicyError(mutationModel);
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
if (needCheckPreCreate) {
|
|
2671
|
+
await this.enforcePreCreatePolicy(node, mutationModel, isManyToManyJoinTable, proceed);
|
|
2317
2672
|
}
|
|
2318
2673
|
}
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
await this.enforcePreCreatePolicy(node, proceed);
|
|
2324
|
-
}
|
|
2325
|
-
const transformedNode = this.transformNode(node);
|
|
2326
|
-
const result = await proceed(transformedNode);
|
|
2327
|
-
if (!this.onlyReturningId(node)) {
|
|
2674
|
+
const result = await proceed(this.transformNode(node));
|
|
2675
|
+
if (!node.returning || this.onlyReturningId(node)) {
|
|
2676
|
+
return result;
|
|
2677
|
+
} else {
|
|
2328
2678
|
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2329
2679
|
if (readBackResult.rows.length !== result.rows.length) {
|
|
2330
|
-
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
2680
|
+
throw new RejectedByPolicyError(mutationModel, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
|
|
2331
2681
|
}
|
|
2332
2682
|
return readBackResult;
|
|
2333
|
-
}
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
// #region overrides
|
|
2686
|
+
transformSelectQuery(node) {
|
|
2687
|
+
let whereNode = this.transformNode(node.where);
|
|
2688
|
+
const policyFilter = this.createPolicyFilterForFrom(node.from);
|
|
2689
|
+
if (policyFilter) {
|
|
2690
|
+
whereNode = import_kysely8.WhereNode.create(whereNode?.where ? conjunction(this.dialect, [
|
|
2691
|
+
whereNode.where,
|
|
2692
|
+
policyFilter
|
|
2693
|
+
]) : policyFilter);
|
|
2694
|
+
}
|
|
2695
|
+
const baseResult = super.transformSelectQuery({
|
|
2696
|
+
...node,
|
|
2697
|
+
where: void 0
|
|
2698
|
+
});
|
|
2699
|
+
return {
|
|
2700
|
+
...baseResult,
|
|
2701
|
+
where: whereNode
|
|
2702
|
+
};
|
|
2703
|
+
}
|
|
2704
|
+
transformJoin(node) {
|
|
2705
|
+
const table = this.extractTableName(node.table);
|
|
2706
|
+
if (!table) {
|
|
2707
|
+
return super.transformJoin(node);
|
|
2708
|
+
}
|
|
2709
|
+
const filter = this.buildPolicyFilter(table.model, table.alias, "read");
|
|
2710
|
+
const nestedSelect = {
|
|
2711
|
+
kind: "SelectQueryNode",
|
|
2712
|
+
from: import_kysely8.FromNode.create([
|
|
2713
|
+
node.table
|
|
2714
|
+
]),
|
|
2715
|
+
selections: [
|
|
2716
|
+
import_kysely8.SelectionNode.createSelectAll()
|
|
2717
|
+
],
|
|
2718
|
+
where: import_kysely8.WhereNode.create(filter)
|
|
2719
|
+
};
|
|
2720
|
+
return {
|
|
2721
|
+
...node,
|
|
2722
|
+
table: import_kysely8.AliasNode.create(import_kysely8.ParensNode.create(nestedSelect), import_kysely8.IdentifierNode.create(table.alias ?? table.model))
|
|
2723
|
+
};
|
|
2724
|
+
}
|
|
2725
|
+
transformInsertQuery(node) {
|
|
2726
|
+
let onConflict = node.onConflict;
|
|
2727
|
+
if (onConflict?.updates) {
|
|
2728
|
+
const { mutationModel, alias } = this.getMutationModel(node);
|
|
2729
|
+
const filter = this.buildPolicyFilter(mutationModel, alias, "update");
|
|
2730
|
+
if (onConflict.updateWhere) {
|
|
2731
|
+
onConflict = {
|
|
2732
|
+
...onConflict,
|
|
2733
|
+
updateWhere: import_kysely8.WhereNode.create(conjunction(this.dialect, [
|
|
2734
|
+
onConflict.updateWhere.where,
|
|
2735
|
+
filter
|
|
2736
|
+
]))
|
|
2737
|
+
};
|
|
2738
|
+
} else {
|
|
2739
|
+
onConflict = {
|
|
2740
|
+
...onConflict,
|
|
2741
|
+
updateWhere: import_kysely8.WhereNode.create(filter)
|
|
2742
|
+
};
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
const processedNode = onConflict ? {
|
|
2746
|
+
...node,
|
|
2747
|
+
onConflict
|
|
2748
|
+
} : node;
|
|
2749
|
+
const result = super.transformInsertQuery(processedNode);
|
|
2750
|
+
if (!node.returning) {
|
|
2751
|
+
return result;
|
|
2752
|
+
}
|
|
2753
|
+
if (this.onlyReturningId(node)) {
|
|
2334
2754
|
return result;
|
|
2755
|
+
} else {
|
|
2756
|
+
const { mutationModel } = this.getMutationModel(node);
|
|
2757
|
+
const idFields = requireIdFields(this.client.$schema, mutationModel);
|
|
2758
|
+
return {
|
|
2759
|
+
...result,
|
|
2760
|
+
returning: import_kysely8.ReturningNode.create(idFields.map((field) => import_kysely8.SelectionNode.create(import_kysely8.ColumnNode.create(field))))
|
|
2761
|
+
};
|
|
2335
2762
|
}
|
|
2336
2763
|
}
|
|
2764
|
+
transformUpdateQuery(node) {
|
|
2765
|
+
const result = super.transformUpdateQuery(node);
|
|
2766
|
+
const { mutationModel, alias } = this.getMutationModel(node);
|
|
2767
|
+
let filter = this.buildPolicyFilter(mutationModel, alias, "update");
|
|
2768
|
+
if (node.from) {
|
|
2769
|
+
const joinFilter = this.createPolicyFilterForFrom(node.from);
|
|
2770
|
+
if (joinFilter) {
|
|
2771
|
+
filter = conjunction(this.dialect, [
|
|
2772
|
+
filter,
|
|
2773
|
+
joinFilter
|
|
2774
|
+
]);
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
return {
|
|
2778
|
+
...result,
|
|
2779
|
+
where: import_kysely8.WhereNode.create(result.where ? conjunction(this.dialect, [
|
|
2780
|
+
result.where.where,
|
|
2781
|
+
filter
|
|
2782
|
+
]) : filter)
|
|
2783
|
+
};
|
|
2784
|
+
}
|
|
2785
|
+
transformDeleteQuery(node) {
|
|
2786
|
+
const result = super.transformDeleteQuery(node);
|
|
2787
|
+
const { mutationModel, alias } = this.getMutationModel(node);
|
|
2788
|
+
let filter = this.buildPolicyFilter(mutationModel, alias, "delete");
|
|
2789
|
+
if (node.using) {
|
|
2790
|
+
const joinFilter = this.createPolicyFilterForTables(node.using.tables);
|
|
2791
|
+
if (joinFilter) {
|
|
2792
|
+
filter = conjunction(this.dialect, [
|
|
2793
|
+
filter,
|
|
2794
|
+
joinFilter
|
|
2795
|
+
]);
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
return {
|
|
2799
|
+
...result,
|
|
2800
|
+
where: import_kysely8.WhereNode.create(result.where ? conjunction(this.dialect, [
|
|
2801
|
+
result.where.where,
|
|
2802
|
+
filter
|
|
2803
|
+
]) : filter)
|
|
2804
|
+
};
|
|
2805
|
+
}
|
|
2806
|
+
// #endregion
|
|
2807
|
+
// #region helpers
|
|
2337
2808
|
onlyReturningId(node) {
|
|
2338
2809
|
if (!node.returning) {
|
|
2339
2810
|
return true;
|
|
2340
2811
|
}
|
|
2341
|
-
const
|
|
2812
|
+
const { mutationModel } = this.getMutationModel(node);
|
|
2813
|
+
const idFields = requireIdFields(this.client.$schema, mutationModel);
|
|
2342
2814
|
const collector = new ColumnCollector();
|
|
2343
2815
|
const selectedColumns = collector.collect(node.returning);
|
|
2344
2816
|
return selectedColumns.every((c) => idFields.includes(c));
|
|
2345
2817
|
}
|
|
2346
|
-
async enforcePreCreatePolicy(node, proceed) {
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
const fields = node.columns.map((c) => c.column.name);
|
|
2352
|
-
const valueRows = this.unwrapCreateValueRows(node.values, model, fields);
|
|
2818
|
+
async enforcePreCreatePolicy(node, mutationModel, isManyToManyJoinTable, proceed) {
|
|
2819
|
+
const fields = node.columns?.map((c) => c.column.name) ?? [];
|
|
2820
|
+
const valueRows = node.values ? this.unwrapCreateValueRows(node.values, mutationModel, fields, isManyToManyJoinTable) : [
|
|
2821
|
+
[]
|
|
2822
|
+
];
|
|
2353
2823
|
for (const values of valueRows) {
|
|
2354
|
-
|
|
2824
|
+
if (isManyToManyJoinTable) {
|
|
2825
|
+
await this.enforcePreCreatePolicyForManyToManyJoinTable(mutationModel, fields, values.map((v) => v.node), proceed);
|
|
2826
|
+
} else {
|
|
2827
|
+
await this.enforcePreCreatePolicyForOne(mutationModel, fields, values.map((v) => v.node), proceed);
|
|
2828
|
+
}
|
|
2355
2829
|
}
|
|
2356
2830
|
}
|
|
2357
|
-
async
|
|
2358
|
-
const
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2831
|
+
async enforcePreCreatePolicyForManyToManyJoinTable(tableName, fields, values, proceed) {
|
|
2832
|
+
const m2m = this.resolveManyToManyJoinTable(tableName);
|
|
2833
|
+
(0, import_common_helpers7.invariant)(m2m);
|
|
2834
|
+
(0, import_common_helpers7.invariant)(fields.includes("A") && fields.includes("B"), "many-to-many join table must have A and B fk fields");
|
|
2835
|
+
const aIndex = fields.indexOf("A");
|
|
2836
|
+
const aNode = values[aIndex];
|
|
2837
|
+
const bIndex = fields.indexOf("B");
|
|
2838
|
+
const bNode = values[bIndex];
|
|
2839
|
+
(0, import_common_helpers7.invariant)(import_kysely8.ValueNode.is(aNode) && import_kysely8.ValueNode.is(bNode), "A and B values must be ValueNode");
|
|
2840
|
+
const aValue = aNode.value;
|
|
2841
|
+
const bValue = bNode.value;
|
|
2842
|
+
(0, import_common_helpers7.invariant)(aValue !== null && aValue !== void 0, "A value cannot be null or undefined");
|
|
2843
|
+
(0, import_common_helpers7.invariant)(bValue !== null && bValue !== void 0, "B value cannot be null or undefined");
|
|
2844
|
+
const eb = (0, import_kysely8.expressionBuilder)();
|
|
2845
|
+
const filterA = this.buildPolicyFilter(m2m.firstModel, void 0, "update");
|
|
2846
|
+
const queryA = eb.selectFrom(m2m.firstModel).where(eb(eb.ref(`${m2m.firstModel}.${m2m.firstIdField}`), "=", aValue)).select(() => new import_kysely8.ExpressionWrapper(filterA).as("$t"));
|
|
2847
|
+
const filterB = this.buildPolicyFilter(m2m.secondModel, void 0, "update");
|
|
2848
|
+
const queryB = eb.selectFrom(m2m.secondModel).where(eb(eb.ref(`${m2m.secondModel}.${m2m.secondIdField}`), "=", bValue)).select(() => new import_kysely8.ExpressionWrapper(filterB).as("$t"));
|
|
2849
|
+
const queryNode = {
|
|
2850
|
+
kind: "SelectQueryNode",
|
|
2851
|
+
selections: [
|
|
2852
|
+
import_kysely8.SelectionNode.create(import_kysely8.AliasNode.create(queryA.toOperationNode(), import_kysely8.IdentifierNode.create("$conditionA"))),
|
|
2853
|
+
import_kysely8.SelectionNode.create(import_kysely8.AliasNode.create(queryB.toOperationNode(), import_kysely8.IdentifierNode.create("$conditionB")))
|
|
2854
|
+
]
|
|
2855
|
+
};
|
|
2856
|
+
const result = await proceed(queryNode);
|
|
2857
|
+
if (!result.rows[0]?.$conditionA) {
|
|
2858
|
+
throw new RejectedByPolicyError(m2m.firstModel, RejectedByPolicyReason.CANNOT_READ_BACK, `many-to-many relation participant model "${m2m.firstModel}" not updatable`);
|
|
2859
|
+
}
|
|
2860
|
+
if (!result.rows[0]?.$conditionB) {
|
|
2861
|
+
throw new RejectedByPolicyError(m2m.secondModel, RejectedByPolicyReason.NO_ACCESS, `many-to-many relation participant model "${m2m.secondModel}" not updatable`);
|
|
2363
2862
|
}
|
|
2364
|
-
|
|
2863
|
+
}
|
|
2864
|
+
async enforcePreCreatePolicyForOne(model, fields, values, proceed) {
|
|
2865
|
+
const allFields = Object.entries(requireModel(this.client.$schema, model).fields).filter(([, def]) => !def.relation);
|
|
2866
|
+
const allValues = [];
|
|
2867
|
+
for (const [name, _def] of allFields) {
|
|
2868
|
+
const index = fields.indexOf(name);
|
|
2869
|
+
if (index >= 0) {
|
|
2870
|
+
allValues.push(values[index]);
|
|
2871
|
+
} else {
|
|
2872
|
+
allValues.push(import_kysely8.ValueNode.createImmediate(null));
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
const eb = (0, import_kysely8.expressionBuilder)();
|
|
2876
|
+
const constTable = {
|
|
2877
|
+
kind: "SelectQueryNode",
|
|
2878
|
+
from: import_kysely8.FromNode.create([
|
|
2879
|
+
import_kysely8.AliasNode.create(import_kysely8.ParensNode.create(import_kysely8.ValuesNode.create([
|
|
2880
|
+
import_kysely8.ValueListNode.create(allValues)
|
|
2881
|
+
])), import_kysely8.IdentifierNode.create("$t"))
|
|
2882
|
+
]),
|
|
2883
|
+
selections: allFields.map(([name, def], index) => {
|
|
2884
|
+
const castedColumnRef = import_kysely8.sql`CAST(${eb.ref(`column${index + 1}`)} as ${import_kysely8.sql.raw(this.dialect.getFieldSqlType(def))})`.as(name);
|
|
2885
|
+
return import_kysely8.SelectionNode.create(castedColumnRef.toOperationNode());
|
|
2886
|
+
})
|
|
2887
|
+
};
|
|
2888
|
+
const filter = this.buildPolicyFilter(model, void 0, "create");
|
|
2365
2889
|
const preCreateCheck = {
|
|
2366
2890
|
kind: "SelectQueryNode",
|
|
2891
|
+
from: import_kysely8.FromNode.create([
|
|
2892
|
+
import_kysely8.AliasNode.create(constTable, import_kysely8.IdentifierNode.create(model))
|
|
2893
|
+
]),
|
|
2367
2894
|
selections: [
|
|
2368
|
-
|
|
2369
|
-
|
|
2895
|
+
import_kysely8.SelectionNode.create(import_kysely8.AliasNode.create(import_kysely8.BinaryOperationNode.create(import_kysely8.FunctionNode.create("COUNT", [
|
|
2896
|
+
import_kysely8.ValueNode.createImmediate(1)
|
|
2897
|
+
]), import_kysely8.OperatorNode.create(">"), import_kysely8.ValueNode.createImmediate(0)), import_kysely8.IdentifierNode.create("$condition")))
|
|
2898
|
+
],
|
|
2899
|
+
where: import_kysely8.WhereNode.create(filter)
|
|
2370
2900
|
};
|
|
2371
2901
|
const result = await proceed(preCreateCheck);
|
|
2372
2902
|
if (!result.rows[0]?.$condition) {
|
|
2373
2903
|
throw new RejectedByPolicyError(model);
|
|
2374
2904
|
}
|
|
2375
2905
|
}
|
|
2376
|
-
unwrapCreateValueRows(node, model, fields) {
|
|
2377
|
-
if (
|
|
2378
|
-
return node.values.map((v) => this.unwrapCreateValueRow(v.values, model, fields));
|
|
2379
|
-
} else if (
|
|
2906
|
+
unwrapCreateValueRows(node, model, fields, isManyToManyJoinTable) {
|
|
2907
|
+
if (import_kysely8.ValuesNode.is(node)) {
|
|
2908
|
+
return node.values.map((v) => this.unwrapCreateValueRow(v.values, model, fields, isManyToManyJoinTable));
|
|
2909
|
+
} else if (import_kysely8.PrimitiveValueListNode.is(node)) {
|
|
2380
2910
|
return [
|
|
2381
|
-
this.unwrapCreateValueRow(node.values, model, fields)
|
|
2911
|
+
this.unwrapCreateValueRow(node.values, model, fields, isManyToManyJoinTable)
|
|
2382
2912
|
];
|
|
2383
2913
|
} else {
|
|
2384
2914
|
throw new InternalError(`Unexpected node kind: ${node.kind} for unwrapping create values`);
|
|
2385
2915
|
}
|
|
2386
2916
|
}
|
|
2387
|
-
unwrapCreateValueRow(data, model, fields) {
|
|
2388
|
-
(0,
|
|
2917
|
+
unwrapCreateValueRow(data, model, fields, isImplicitManyToManyJoinTable) {
|
|
2918
|
+
(0, import_common_helpers7.invariant)(data.length === fields.length, "data length must match fields length");
|
|
2389
2919
|
const result = [];
|
|
2390
2920
|
for (let i = 0; i < data.length; i++) {
|
|
2391
2921
|
const item = data[i];
|
|
2392
|
-
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
2393
2922
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2394
|
-
|
|
2923
|
+
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
2924
|
+
(0, import_common_helpers7.invariant)(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2395
2925
|
result.push({
|
|
2396
|
-
node:
|
|
2926
|
+
node: import_kysely8.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2397
2927
|
raw: item.value
|
|
2398
2928
|
});
|
|
2399
2929
|
} else {
|
|
2400
|
-
|
|
2930
|
+
let value = item;
|
|
2931
|
+
if (!isImplicitManyToManyJoinTable) {
|
|
2932
|
+
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
2933
|
+
value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
2934
|
+
}
|
|
2401
2935
|
if (Array.isArray(value)) {
|
|
2402
2936
|
result.push({
|
|
2403
|
-
node:
|
|
2937
|
+
node: import_kysely8.RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
2404
2938
|
raw: value
|
|
2405
2939
|
});
|
|
2406
2940
|
} else {
|
|
2407
2941
|
result.push({
|
|
2408
|
-
node:
|
|
2942
|
+
node: import_kysely8.ValueNode.create(value),
|
|
2409
2943
|
raw: value
|
|
2410
2944
|
});
|
|
2411
2945
|
}
|
|
@@ -2441,18 +2975,15 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2441
2975
|
if (!this.isMutationQueryNode(node) || !node.returning) {
|
|
2442
2976
|
return result;
|
|
2443
2977
|
}
|
|
2444
|
-
const
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
}
|
|
2448
|
-
const idConditions = this.buildIdConditions(table, result.rows);
|
|
2449
|
-
const policyFilter = this.buildPolicyFilter(table, void 0, "read");
|
|
2978
|
+
const { mutationModel } = this.getMutationModel(node);
|
|
2979
|
+
const idConditions = this.buildIdConditions(mutationModel, result.rows);
|
|
2980
|
+
const policyFilter = this.buildPolicyFilter(mutationModel, void 0, "read");
|
|
2450
2981
|
const select = {
|
|
2451
2982
|
kind: "SelectQueryNode",
|
|
2452
|
-
from:
|
|
2453
|
-
|
|
2983
|
+
from: import_kysely8.FromNode.create([
|
|
2984
|
+
import_kysely8.TableNode.create(mutationModel)
|
|
2454
2985
|
]),
|
|
2455
|
-
where:
|
|
2986
|
+
where: import_kysely8.WhereNode.create(conjunction(this.dialect, [
|
|
2456
2987
|
idConditions,
|
|
2457
2988
|
policyFilter
|
|
2458
2989
|
])),
|
|
@@ -2462,15 +2993,31 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2462
2993
|
return selectResult;
|
|
2463
2994
|
}
|
|
2464
2995
|
buildIdConditions(table, rows) {
|
|
2465
|
-
const idFields =
|
|
2466
|
-
return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) =>
|
|
2996
|
+
const idFields = requireIdFields(this.client.$schema, table);
|
|
2997
|
+
return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => import_kysely8.BinaryOperationNode.create(import_kysely8.ColumnNode.create(field), import_kysely8.OperatorNode.create("="), import_kysely8.ValueNode.create(row[field]))))));
|
|
2467
2998
|
}
|
|
2468
2999
|
getMutationModel(node) {
|
|
2469
|
-
const r = (0, import_ts_pattern8.match)(node).when(
|
|
3000
|
+
const r = (0, import_ts_pattern8.match)(node).when(import_kysely8.InsertQueryNode.is, (node2) => ({
|
|
3001
|
+
mutationModel: getTableName(node2.into),
|
|
3002
|
+
alias: void 0
|
|
3003
|
+
})).when(import_kysely8.UpdateQueryNode.is, (node2) => {
|
|
3004
|
+
if (!node2.table) {
|
|
3005
|
+
throw new QueryError("Update query must have a table");
|
|
3006
|
+
}
|
|
3007
|
+
const r2 = this.extractTableName(node2.table);
|
|
3008
|
+
return r2 ? {
|
|
3009
|
+
mutationModel: r2.model,
|
|
3010
|
+
alias: r2.alias
|
|
3011
|
+
} : void 0;
|
|
3012
|
+
}).when(import_kysely8.DeleteQueryNode.is, (node2) => {
|
|
2470
3013
|
if (node2.from.froms.length !== 1) {
|
|
2471
|
-
throw new
|
|
3014
|
+
throw new QueryError("Only one from table is supported for delete");
|
|
2472
3015
|
}
|
|
2473
|
-
|
|
3016
|
+
const r2 = this.extractTableName(node2.from.froms[0]);
|
|
3017
|
+
return r2 ? {
|
|
3018
|
+
mutationModel: r2.model,
|
|
3019
|
+
alias: r2.alias
|
|
3020
|
+
} : void 0;
|
|
2474
3021
|
}).exhaustive();
|
|
2475
3022
|
if (!r) {
|
|
2476
3023
|
throw new InternalError(`Unable to get table name for query node: ${node}`);
|
|
@@ -2478,18 +3025,22 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2478
3025
|
return r;
|
|
2479
3026
|
}
|
|
2480
3027
|
isCrudQueryNode(node) {
|
|
2481
|
-
return
|
|
3028
|
+
return import_kysely8.SelectQueryNode.is(node) || import_kysely8.InsertQueryNode.is(node) || import_kysely8.UpdateQueryNode.is(node) || import_kysely8.DeleteQueryNode.is(node);
|
|
2482
3029
|
}
|
|
2483
3030
|
isMutationQueryNode(node) {
|
|
2484
|
-
return
|
|
3031
|
+
return import_kysely8.InsertQueryNode.is(node) || import_kysely8.UpdateQueryNode.is(node) || import_kysely8.DeleteQueryNode.is(node);
|
|
2485
3032
|
}
|
|
2486
|
-
buildPolicyFilter(model, alias, operation
|
|
3033
|
+
buildPolicyFilter(model, alias, operation) {
|
|
3034
|
+
const m2mFilter = this.getModelPolicyFilterForManyToManyJoinTable(model, alias, operation);
|
|
3035
|
+
if (m2mFilter) {
|
|
3036
|
+
return m2mFilter;
|
|
3037
|
+
}
|
|
2487
3038
|
const policies = this.getModelPolicies(model, operation);
|
|
2488
3039
|
if (policies.length === 0) {
|
|
2489
3040
|
return falseNode(this.dialect);
|
|
2490
3041
|
}
|
|
2491
|
-
const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.
|
|
2492
|
-
const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.
|
|
3042
|
+
const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.compilePolicyCondition(model, alias, operation, policy));
|
|
3043
|
+
const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.compilePolicyCondition(model, alias, operation, policy));
|
|
2493
3044
|
let combinedPolicy;
|
|
2494
3045
|
if (allows.length === 0) {
|
|
2495
3046
|
combinedPolicy = falseNode(this.dialect);
|
|
@@ -2505,102 +3056,59 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2505
3056
|
}
|
|
2506
3057
|
return combinedPolicy;
|
|
2507
3058
|
}
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
node.from?.froms.forEach((from) => {
|
|
2511
|
-
const extractResult = this.extractTableName(from);
|
|
2512
|
-
if (extractResult) {
|
|
2513
|
-
const { model, alias } = extractResult;
|
|
2514
|
-
const filter = this.buildPolicyFilter(model, alias, "read");
|
|
2515
|
-
whereNode = import_kysely7.WhereNode.create(whereNode?.where ? conjunction(this.dialect, [
|
|
2516
|
-
whereNode.where,
|
|
2517
|
-
filter
|
|
2518
|
-
]) : filter);
|
|
2519
|
-
}
|
|
2520
|
-
});
|
|
2521
|
-
const baseResult = super.transformSelectQuery({
|
|
2522
|
-
...node,
|
|
2523
|
-
where: void 0
|
|
2524
|
-
});
|
|
2525
|
-
return {
|
|
2526
|
-
...baseResult,
|
|
2527
|
-
where: whereNode
|
|
2528
|
-
};
|
|
2529
|
-
}
|
|
2530
|
-
transformInsertQuery(node) {
|
|
2531
|
-
const result = super.transformInsertQuery(node);
|
|
2532
|
-
if (!node.returning) {
|
|
2533
|
-
return result;
|
|
2534
|
-
}
|
|
2535
|
-
if (this.onlyReturningId(node)) {
|
|
2536
|
-
return result;
|
|
2537
|
-
} else {
|
|
2538
|
-
const idFields = getIdFields(this.client.$schema, this.getMutationModel(node));
|
|
2539
|
-
return {
|
|
2540
|
-
...result,
|
|
2541
|
-
returning: import_kysely7.ReturningNode.create(idFields.map((field) => import_kysely7.SelectionNode.create(import_kysely7.ColumnNode.create(field))))
|
|
2542
|
-
};
|
|
2543
|
-
}
|
|
2544
|
-
}
|
|
2545
|
-
transformUpdateQuery(node) {
|
|
2546
|
-
const result = super.transformUpdateQuery(node);
|
|
2547
|
-
const mutationModel = this.getMutationModel(node);
|
|
2548
|
-
const filter = this.buildPolicyFilter(mutationModel, void 0, "update");
|
|
2549
|
-
return {
|
|
2550
|
-
...result,
|
|
2551
|
-
where: import_kysely7.WhereNode.create(result.where ? conjunction(this.dialect, [
|
|
2552
|
-
result.where.where,
|
|
2553
|
-
filter
|
|
2554
|
-
]) : filter)
|
|
2555
|
-
};
|
|
2556
|
-
}
|
|
2557
|
-
transformDeleteQuery(node) {
|
|
2558
|
-
const result = super.transformDeleteQuery(node);
|
|
2559
|
-
const mutationModel = this.getMutationModel(node);
|
|
2560
|
-
const filter = this.buildPolicyFilter(mutationModel, void 0, "delete");
|
|
2561
|
-
return {
|
|
2562
|
-
...result,
|
|
2563
|
-
where: import_kysely7.WhereNode.create(result.where ? conjunction(this.dialect, [
|
|
2564
|
-
result.where.where,
|
|
2565
|
-
filter
|
|
2566
|
-
]) : filter)
|
|
2567
|
-
};
|
|
2568
|
-
}
|
|
2569
|
-
extractTableName(from) {
|
|
2570
|
-
if (import_kysely7.TableNode.is(from)) {
|
|
3059
|
+
extractTableName(node) {
|
|
3060
|
+
if (import_kysely8.TableNode.is(node)) {
|
|
2571
3061
|
return {
|
|
2572
|
-
model:
|
|
3062
|
+
model: node.table.identifier.name
|
|
2573
3063
|
};
|
|
2574
3064
|
}
|
|
2575
|
-
if (
|
|
2576
|
-
const inner = this.extractTableName(
|
|
3065
|
+
if (import_kysely8.AliasNode.is(node)) {
|
|
3066
|
+
const inner = this.extractTableName(node.node);
|
|
2577
3067
|
if (!inner) {
|
|
2578
3068
|
return void 0;
|
|
2579
3069
|
}
|
|
2580
3070
|
return {
|
|
2581
3071
|
model: inner.model,
|
|
2582
|
-
alias:
|
|
3072
|
+
alias: import_kysely8.IdentifierNode.is(node.alias) ? node.alias.name : void 0
|
|
2583
3073
|
};
|
|
2584
3074
|
} else {
|
|
2585
3075
|
return void 0;
|
|
2586
3076
|
}
|
|
2587
3077
|
}
|
|
2588
|
-
|
|
2589
|
-
|
|
3078
|
+
createPolicyFilterForFrom(node) {
|
|
3079
|
+
if (!node) {
|
|
3080
|
+
return void 0;
|
|
3081
|
+
}
|
|
3082
|
+
return this.createPolicyFilterForTables(node.froms);
|
|
3083
|
+
}
|
|
3084
|
+
createPolicyFilterForTables(tables) {
|
|
3085
|
+
return tables.reduce((acc, table) => {
|
|
3086
|
+
const extractResult = this.extractTableName(table);
|
|
3087
|
+
if (extractResult) {
|
|
3088
|
+
const { model, alias } = extractResult;
|
|
3089
|
+
const filter = this.buildPolicyFilter(model, alias, "read");
|
|
3090
|
+
return acc ? conjunction(this.dialect, [
|
|
3091
|
+
acc,
|
|
3092
|
+
filter
|
|
3093
|
+
]) : filter;
|
|
3094
|
+
}
|
|
3095
|
+
return acc;
|
|
3096
|
+
}, void 0);
|
|
3097
|
+
}
|
|
3098
|
+
compilePolicyCondition(model, alias, operation, policy) {
|
|
3099
|
+
return new ExpressionTransformer(this.client).transform(policy.condition, {
|
|
2590
3100
|
model,
|
|
2591
3101
|
alias,
|
|
2592
3102
|
operation,
|
|
2593
|
-
thisEntity,
|
|
2594
|
-
thisEntityRaw,
|
|
2595
3103
|
auth: this.client.$auth
|
|
2596
3104
|
});
|
|
2597
3105
|
}
|
|
2598
|
-
getModelPolicies(
|
|
2599
|
-
const modelDef = requireModel(this.client.$schema,
|
|
3106
|
+
getModelPolicies(model, operation) {
|
|
3107
|
+
const modelDef = requireModel(this.client.$schema, model);
|
|
2600
3108
|
const result = [];
|
|
2601
3109
|
const extractOperations = /* @__PURE__ */ __name((expr2) => {
|
|
2602
|
-
(0,
|
|
2603
|
-
(0,
|
|
3110
|
+
(0, import_common_helpers7.invariant)(ExpressionUtils.isLiteral(expr2), "expecting a literal");
|
|
3111
|
+
(0, import_common_helpers7.invariant)(typeof expr2.value === "string", "expecting a string literal");
|
|
2604
3112
|
return expr2.value.split(",").filter((v) => !!v).map((v) => v.trim());
|
|
2605
3113
|
}, "extractOperations");
|
|
2606
3114
|
if (modelDef.attributes) {
|
|
@@ -2612,8 +3120,84 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2612
3120
|
}
|
|
2613
3121
|
return result;
|
|
2614
3122
|
}
|
|
3123
|
+
resolveManyToManyJoinTable(tableName) {
|
|
3124
|
+
for (const model of Object.values(this.client.$schema.models)) {
|
|
3125
|
+
for (const field of Object.values(model.fields)) {
|
|
3126
|
+
const m2m = getManyToManyRelation(this.client.$schema, model.name, field.name);
|
|
3127
|
+
if (m2m?.joinTable === tableName) {
|
|
3128
|
+
const sortedRecord = [
|
|
3129
|
+
{
|
|
3130
|
+
model: model.name,
|
|
3131
|
+
field: field.name
|
|
3132
|
+
},
|
|
3133
|
+
{
|
|
3134
|
+
model: m2m.otherModel,
|
|
3135
|
+
field: m2m.otherField
|
|
3136
|
+
}
|
|
3137
|
+
].sort(this.manyToManySorter);
|
|
3138
|
+
const firstIdFields = requireIdFields(this.client.$schema, sortedRecord[0].model);
|
|
3139
|
+
const secondIdFields = requireIdFields(this.client.$schema, sortedRecord[1].model);
|
|
3140
|
+
(0, import_common_helpers7.invariant)(firstIdFields.length === 1 && secondIdFields.length === 1, "only single-field id is supported for implicit many-to-many join table");
|
|
3141
|
+
return {
|
|
3142
|
+
firstModel: sortedRecord[0].model,
|
|
3143
|
+
firstField: sortedRecord[0].field,
|
|
3144
|
+
firstIdField: firstIdFields[0],
|
|
3145
|
+
secondModel: sortedRecord[1].model,
|
|
3146
|
+
secondField: sortedRecord[1].field,
|
|
3147
|
+
secondIdField: secondIdFields[0]
|
|
3148
|
+
};
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
return void 0;
|
|
3153
|
+
}
|
|
3154
|
+
manyToManySorter(a, b) {
|
|
3155
|
+
return a.model !== b.model ? a.model.localeCompare(b.model) : a.field.localeCompare(b.field);
|
|
3156
|
+
}
|
|
3157
|
+
isManyToManyJoinTable(tableName) {
|
|
3158
|
+
return !!this.resolveManyToManyJoinTable(tableName);
|
|
3159
|
+
}
|
|
3160
|
+
getModelPolicyFilterForManyToManyJoinTable(tableName, alias, operation) {
|
|
3161
|
+
const m2m = this.resolveManyToManyJoinTable(tableName);
|
|
3162
|
+
if (!m2m) {
|
|
3163
|
+
return void 0;
|
|
3164
|
+
}
|
|
3165
|
+
const checkForOperation = operation === "read" ? "read" : "update";
|
|
3166
|
+
const eb = (0, import_kysely8.expressionBuilder)();
|
|
3167
|
+
const joinTable = alias ?? tableName;
|
|
3168
|
+
const aQuery = eb.selectFrom(m2m.firstModel).whereRef(`${m2m.firstModel}.${m2m.firstIdField}`, "=", `${joinTable}.A`).select(() => new import_kysely8.ExpressionWrapper(this.buildPolicyFilter(m2m.firstModel, void 0, checkForOperation)).as("$conditionA"));
|
|
3169
|
+
const bQuery = eb.selectFrom(m2m.secondModel).whereRef(`${m2m.secondModel}.${m2m.secondIdField}`, "=", `${joinTable}.B`).select(() => new import_kysely8.ExpressionWrapper(this.buildPolicyFilter(m2m.secondModel, void 0, checkForOperation)).as("$conditionB"));
|
|
3170
|
+
return eb.and([
|
|
3171
|
+
aQuery,
|
|
3172
|
+
bQuery
|
|
3173
|
+
]).toOperationNode();
|
|
3174
|
+
}
|
|
2615
3175
|
};
|
|
2616
3176
|
|
|
3177
|
+
// src/plugins/policy/functions.ts
|
|
3178
|
+
var check = /* @__PURE__ */ __name((eb, args, { client, model, modelAlias, operation }) => {
|
|
3179
|
+
(0, import_common_helpers8.invariant)(args.length === 1 || args.length === 2, '"check" function requires 1 or 2 arguments');
|
|
3180
|
+
const arg1Node = args[0].toOperationNode();
|
|
3181
|
+
const arg2Node = args.length === 2 ? args[1].toOperationNode() : void 0;
|
|
3182
|
+
if (arg2Node) {
|
|
3183
|
+
(0, import_common_helpers8.invariant)(import_kysely9.ValueNode.is(arg2Node) && typeof arg2Node.value === "string", '"operation" parameter must be a string literal when provided');
|
|
3184
|
+
(0, import_common_helpers8.invariant)(CRUD.includes(arg2Node.value), '"operation" parameter must be one of "create", "read", "update", "delete"');
|
|
3185
|
+
}
|
|
3186
|
+
const fieldName = extractFieldName(arg1Node);
|
|
3187
|
+
(0, import_common_helpers8.invariant)(fieldName, 'Failed to extract field name from the first argument of "check" function');
|
|
3188
|
+
const fieldDef = requireField(client.$schema, model, fieldName);
|
|
3189
|
+
(0, import_common_helpers8.invariant)(fieldDef.relation, `Field "${fieldName}" is not a relation field in model "${model}"`);
|
|
3190
|
+
(0, import_common_helpers8.invariant)(!fieldDef.array, `Field "${fieldName}" is a to-many relation, which is not supported by "check"`);
|
|
3191
|
+
const relationModel = fieldDef.type;
|
|
3192
|
+
const op = arg2Node ? arg2Node.value : operation;
|
|
3193
|
+
const policyHandler = new PolicyHandler(client);
|
|
3194
|
+
const joinPairs = buildJoinPairs(client.$schema, model, modelAlias, fieldName, relationModel);
|
|
3195
|
+
const joinCondition = joinPairs.length === 1 ? eb(eb.ref(joinPairs[0][0]), "=", eb.ref(joinPairs[0][1])) : eb.and(joinPairs.map(([left, right]) => eb(eb.ref(left), "=", eb.ref(right))));
|
|
3196
|
+
const policyCondition = policyHandler.buildPolicyFilter(relationModel, void 0, op);
|
|
3197
|
+
const result = eb.selectFrom(relationModel).where(joinCondition).select(new import_kysely9.ExpressionWrapper(policyCondition).as("$condition"));
|
|
3198
|
+
return result;
|
|
3199
|
+
}, "check");
|
|
3200
|
+
|
|
2617
3201
|
// src/plugins/policy/plugin.ts
|
|
2618
3202
|
var PolicyPlugin = class {
|
|
2619
3203
|
static {
|
|
@@ -2628,6 +3212,11 @@ var PolicyPlugin = class {
|
|
|
2628
3212
|
get description() {
|
|
2629
3213
|
return "Enforces access policies defined in the schema.";
|
|
2630
3214
|
}
|
|
3215
|
+
get functions() {
|
|
3216
|
+
return {
|
|
3217
|
+
check
|
|
3218
|
+
};
|
|
3219
|
+
}
|
|
2631
3220
|
onKyselyQuery({
|
|
2632
3221
|
query,
|
|
2633
3222
|
client,
|
|
@@ -2645,6 +3234,7 @@ var PolicyPlugin = class {
|
|
|
2645
3234
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2646
3235
|
0 && (module.exports = {
|
|
2647
3236
|
PolicyPlugin,
|
|
2648
|
-
RejectedByPolicyError
|
|
3237
|
+
RejectedByPolicyError,
|
|
3238
|
+
RejectedByPolicyReason
|
|
2649
3239
|
});
|
|
2650
3240
|
//# sourceMappingURL=index.cjs.map
|