@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
package/dist/index.cjs
CHANGED
|
@@ -37,19 +37,20 @@ __export(src_exports, {
|
|
|
37
37
|
QueryError: () => QueryError,
|
|
38
38
|
ZenStackClient: () => ZenStackClient,
|
|
39
39
|
definePlugin: () => definePlugin,
|
|
40
|
-
sql: () =>
|
|
40
|
+
sql: () => import_kysely19.sql
|
|
41
41
|
});
|
|
42
42
|
module.exports = __toCommonJS(src_exports);
|
|
43
43
|
|
|
44
44
|
// src/client/client-impl.ts
|
|
45
45
|
var import_common_helpers16 = require("@zenstackhq/common-helpers");
|
|
46
|
-
var
|
|
46
|
+
var import_kysely18 = require("kysely");
|
|
47
47
|
|
|
48
48
|
// src/client/crud/operations/aggregate.ts
|
|
49
|
-
var
|
|
49
|
+
var import_kysely11 = require("kysely");
|
|
50
50
|
var import_ts_pattern10 = require("ts-pattern");
|
|
51
51
|
|
|
52
52
|
// src/client/query-utils.ts
|
|
53
|
+
var import_common_helpers = require("@zenstackhq/common-helpers");
|
|
53
54
|
var import_ts_pattern = require("ts-pattern");
|
|
54
55
|
|
|
55
56
|
// src/schema/expression.ts
|
|
@@ -117,6 +118,9 @@ var ExpressionUtils = {
|
|
|
117
118
|
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
118
119
|
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
119
120
|
}, "or"),
|
|
121
|
+
not: /* @__PURE__ */ __name((expr2) => {
|
|
122
|
+
return ExpressionUtils.unary("!", expr2);
|
|
123
|
+
}, "not"),
|
|
120
124
|
is: /* @__PURE__ */ __name((value, kind) => {
|
|
121
125
|
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
122
126
|
}, "is"),
|
|
@@ -177,22 +181,26 @@ var NotFoundError = class extends Error {
|
|
|
177
181
|
static {
|
|
178
182
|
__name(this, "NotFoundError");
|
|
179
183
|
}
|
|
180
|
-
constructor(model) {
|
|
181
|
-
super(`Entity not found for model "${model}"`);
|
|
184
|
+
constructor(model, details) {
|
|
185
|
+
super(`Entity not found for model "${model}"${details ? `: ${details}` : ""}`);
|
|
182
186
|
}
|
|
183
187
|
};
|
|
184
188
|
|
|
185
189
|
// src/client/query-utils.ts
|
|
186
190
|
function getModel(schema, model) {
|
|
187
|
-
return schema.models
|
|
191
|
+
return Object.values(schema.models).find((m) => m.name.toLowerCase() === model.toLowerCase());
|
|
188
192
|
}
|
|
189
193
|
__name(getModel, "getModel");
|
|
194
|
+
function getTypeDef(schema, type) {
|
|
195
|
+
return schema.typeDefs?.[type];
|
|
196
|
+
}
|
|
197
|
+
__name(getTypeDef, "getTypeDef");
|
|
190
198
|
function requireModel(schema, model) {
|
|
191
|
-
const
|
|
192
|
-
if (!
|
|
199
|
+
const modelDef = getModel(schema, model);
|
|
200
|
+
if (!modelDef) {
|
|
193
201
|
throw new QueryError(`Model "${model}" not found in schema`);
|
|
194
202
|
}
|
|
195
|
-
return
|
|
203
|
+
return modelDef;
|
|
196
204
|
}
|
|
197
205
|
__name(requireModel, "requireModel");
|
|
198
206
|
function getField(schema, model, field) {
|
|
@@ -200,19 +208,40 @@ function getField(schema, model, field) {
|
|
|
200
208
|
return modelDef?.fields[field];
|
|
201
209
|
}
|
|
202
210
|
__name(getField, "getField");
|
|
203
|
-
function requireField(schema,
|
|
204
|
-
const modelDef =
|
|
205
|
-
if (
|
|
206
|
-
|
|
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
|
+
}
|
|
219
|
+
}
|
|
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
|
+
}
|
|
207
227
|
}
|
|
208
|
-
|
|
228
|
+
throw new QueryError(`Model or type "${modelOrType}" not found in schema`);
|
|
209
229
|
}
|
|
210
230
|
__name(requireField, "requireField");
|
|
211
231
|
function getIdFields(schema, model) {
|
|
212
|
-
const modelDef =
|
|
232
|
+
const modelDef = getModel(schema, model);
|
|
213
233
|
return modelDef?.idFields;
|
|
214
234
|
}
|
|
215
235
|
__name(getIdFields, "getIdFields");
|
|
236
|
+
function requireIdFields(schema, model) {
|
|
237
|
+
const modelDef = requireModel(schema, model);
|
|
238
|
+
const result = modelDef?.idFields;
|
|
239
|
+
if (!result) {
|
|
240
|
+
throw new InternalError(`Model "${model}" does not have ID field(s)`);
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
244
|
+
__name(requireIdFields, "requireIdFields");
|
|
216
245
|
function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
217
246
|
const fieldDef = requireField(schema, model, relationField);
|
|
218
247
|
if (!fieldDef?.relation) {
|
|
@@ -326,7 +355,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias, inlineComp
|
|
|
326
355
|
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
327
356
|
}
|
|
328
357
|
return computer(eb, {
|
|
329
|
-
|
|
358
|
+
modelAlias
|
|
330
359
|
});
|
|
331
360
|
}
|
|
332
361
|
}
|
|
@@ -361,7 +390,7 @@ function buildJoinPairs(schema, model, modelAlias, relationField, relationModelA
|
|
|
361
390
|
}
|
|
362
391
|
__name(buildJoinPairs, "buildJoinPairs");
|
|
363
392
|
function makeDefaultOrderBy(schema, model) {
|
|
364
|
-
const idFields =
|
|
393
|
+
const idFields = requireIdFields(schema, model);
|
|
365
394
|
return idFields.map((f) => ({
|
|
366
395
|
[f]: "asc"
|
|
367
396
|
}));
|
|
@@ -400,11 +429,17 @@ function getManyToManyRelation(schema, model, field) {
|
|
|
400
429
|
"A"
|
|
401
430
|
];
|
|
402
431
|
}
|
|
432
|
+
const modelIdFields = requireIdFields(schema, model);
|
|
433
|
+
(0, import_common_helpers.invariant)(modelIdFields.length === 1, "Only single-field ID is supported for many-to-many relation");
|
|
434
|
+
const otherIdFields = requireIdFields(schema, fieldDef.type);
|
|
435
|
+
(0, import_common_helpers.invariant)(otherIdFields.length === 1, "Only single-field ID is supported for many-to-many relation");
|
|
403
436
|
return {
|
|
404
437
|
parentFkName: orderedFK[0],
|
|
438
|
+
parentPKName: modelIdFields[0],
|
|
405
439
|
otherModel: fieldDef.type,
|
|
406
440
|
otherField: fieldDef.relation.opposite,
|
|
407
441
|
otherFkName: orderedFK[1],
|
|
442
|
+
otherPKName: otherIdFields[0],
|
|
408
443
|
joinTable: fieldDef.relation.name ? `_${fieldDef.relation.name}` : `_${sortedModelNames[0]}To${sortedModelNames[1]}`
|
|
409
444
|
};
|
|
410
445
|
} else {
|
|
@@ -443,7 +478,7 @@ function ensureArray(value) {
|
|
|
443
478
|
}
|
|
444
479
|
__name(ensureArray, "ensureArray");
|
|
445
480
|
function extractIdFields(entity, schema, model) {
|
|
446
|
-
const idFields =
|
|
481
|
+
const idFields = requireIdFields(schema, model);
|
|
447
482
|
return extractFields(entity, idFields);
|
|
448
483
|
}
|
|
449
484
|
__name(extractIdFields, "extractIdFields");
|
|
@@ -480,36 +515,95 @@ __name(aggregate, "aggregate");
|
|
|
480
515
|
|
|
481
516
|
// src/client/crud/operations/base.ts
|
|
482
517
|
var import_cuid2 = require("@paralleldrive/cuid2");
|
|
483
|
-
var
|
|
484
|
-
var
|
|
518
|
+
var import_common_helpers10 = require("@zenstackhq/common-helpers");
|
|
519
|
+
var import_kysely10 = require("kysely");
|
|
485
520
|
var import_nanoid = require("nanoid");
|
|
486
521
|
var import_ts_pattern9 = require("ts-pattern");
|
|
487
522
|
var import_ulid = require("ulid");
|
|
488
523
|
var uuid = __toESM(require("uuid"), 1);
|
|
489
524
|
|
|
490
525
|
// src/plugins/policy/errors.ts
|
|
526
|
+
var RejectedByPolicyReason = /* @__PURE__ */ function(RejectedByPolicyReason2) {
|
|
527
|
+
RejectedByPolicyReason2["NO_ACCESS"] = "no-access";
|
|
528
|
+
RejectedByPolicyReason2["CANNOT_READ_BACK"] = "cannot-read-back";
|
|
529
|
+
RejectedByPolicyReason2["OTHER"] = "other";
|
|
530
|
+
return RejectedByPolicyReason2;
|
|
531
|
+
}({});
|
|
491
532
|
var RejectedByPolicyError = class extends Error {
|
|
492
533
|
static {
|
|
493
534
|
__name(this, "RejectedByPolicyError");
|
|
494
535
|
}
|
|
495
536
|
model;
|
|
496
537
|
reason;
|
|
497
|
-
constructor(model, reason) {
|
|
498
|
-
super(
|
|
538
|
+
constructor(model, reason = "no-access", message) {
|
|
539
|
+
super(message ?? `Operation rejected by policy${model ? ": " + model : ""}`), this.model = model, this.reason = reason;
|
|
499
540
|
}
|
|
500
541
|
};
|
|
501
542
|
|
|
543
|
+
// src/plugins/policy/functions.ts
|
|
544
|
+
var import_common_helpers8 = require("@zenstackhq/common-helpers");
|
|
545
|
+
var import_kysely9 = require("kysely");
|
|
546
|
+
|
|
547
|
+
// src/client/contract.ts
|
|
548
|
+
var TransactionIsolationLevel = /* @__PURE__ */ function(TransactionIsolationLevel2) {
|
|
549
|
+
TransactionIsolationLevel2["ReadUncommitted"] = "read uncommitted";
|
|
550
|
+
TransactionIsolationLevel2["ReadCommitted"] = "read committed";
|
|
551
|
+
TransactionIsolationLevel2["RepeatableRead"] = "repeatable read";
|
|
552
|
+
TransactionIsolationLevel2["Serializable"] = "serializable";
|
|
553
|
+
TransactionIsolationLevel2["Snapshot"] = "snapshot";
|
|
554
|
+
return TransactionIsolationLevel2;
|
|
555
|
+
}({});
|
|
556
|
+
var CRUD = [
|
|
557
|
+
"create",
|
|
558
|
+
"read",
|
|
559
|
+
"update",
|
|
560
|
+
"delete"
|
|
561
|
+
];
|
|
562
|
+
|
|
563
|
+
// src/client/kysely-utils.ts
|
|
564
|
+
var import_kysely = require("kysely");
|
|
565
|
+
function stripAlias(node) {
|
|
566
|
+
if (import_kysely.AliasNode.is(node)) {
|
|
567
|
+
return {
|
|
568
|
+
alias: node.alias,
|
|
569
|
+
node: node.node
|
|
570
|
+
};
|
|
571
|
+
} else {
|
|
572
|
+
return {
|
|
573
|
+
alias: void 0,
|
|
574
|
+
node
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
__name(stripAlias, "stripAlias");
|
|
579
|
+
function extractModelName(node) {
|
|
580
|
+
const { node: innerNode } = stripAlias(node);
|
|
581
|
+
return import_kysely.TableNode.is(innerNode) ? innerNode.table.identifier.name : void 0;
|
|
582
|
+
}
|
|
583
|
+
__name(extractModelName, "extractModelName");
|
|
584
|
+
function extractFieldName(node) {
|
|
585
|
+
if (import_kysely.ReferenceNode.is(node) && import_kysely.ColumnNode.is(node.column)) {
|
|
586
|
+
return node.column.column.name;
|
|
587
|
+
} else if (import_kysely.ColumnNode.is(node)) {
|
|
588
|
+
return node.column.name;
|
|
589
|
+
} else {
|
|
590
|
+
return void 0;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
__name(extractFieldName, "extractFieldName");
|
|
594
|
+
|
|
502
595
|
// src/plugins/policy/policy-handler.ts
|
|
503
|
-
var
|
|
504
|
-
var
|
|
596
|
+
var import_common_helpers7 = require("@zenstackhq/common-helpers");
|
|
597
|
+
var import_kysely8 = require("kysely");
|
|
505
598
|
var import_ts_pattern8 = require("ts-pattern");
|
|
506
599
|
|
|
507
600
|
// src/client/crud/dialects/index.ts
|
|
508
601
|
var import_ts_pattern5 = require("ts-pattern");
|
|
509
602
|
|
|
510
603
|
// src/client/crud/dialects/postgresql.ts
|
|
511
|
-
var
|
|
512
|
-
var
|
|
604
|
+
var import_common_helpers3 = require("@zenstackhq/common-helpers");
|
|
605
|
+
var import_decimal = __toESM(require("decimal.js"), 1);
|
|
606
|
+
var import_kysely3 = require("kysely");
|
|
513
607
|
var import_ts_pattern3 = require("ts-pattern");
|
|
514
608
|
|
|
515
609
|
// src/client/constants.ts
|
|
@@ -533,9 +627,9 @@ var AGGREGATE_OPERATORS = [
|
|
|
533
627
|
"_max"
|
|
534
628
|
];
|
|
535
629
|
|
|
536
|
-
// src/client/crud/dialects/base.ts
|
|
537
|
-
var
|
|
538
|
-
var
|
|
630
|
+
// src/client/crud/dialects/base-dialect.ts
|
|
631
|
+
var import_common_helpers2 = require("@zenstackhq/common-helpers");
|
|
632
|
+
var import_kysely2 = require("kysely");
|
|
539
633
|
var import_ts_pattern2 = require("ts-pattern");
|
|
540
634
|
|
|
541
635
|
// src/utils/enumerate.ts
|
|
@@ -552,7 +646,7 @@ function enumerate(x) {
|
|
|
552
646
|
}
|
|
553
647
|
__name(enumerate, "enumerate");
|
|
554
648
|
|
|
555
|
-
// src/client/crud/dialects/base.ts
|
|
649
|
+
// src/client/crud/dialects/base-dialect.ts
|
|
556
650
|
var BaseCrudDialect = class {
|
|
557
651
|
static {
|
|
558
652
|
__name(this, "BaseCrudDialect");
|
|
@@ -566,6 +660,9 @@ var BaseCrudDialect = class {
|
|
|
566
660
|
transformPrimitive(value, _type, _forArrayField) {
|
|
567
661
|
return value;
|
|
568
662
|
}
|
|
663
|
+
transformOutput(value, _type) {
|
|
664
|
+
return value;
|
|
665
|
+
}
|
|
569
666
|
// #region common query builders
|
|
570
667
|
buildSelectModel(eb, model, modelAlias) {
|
|
571
668
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -594,7 +691,7 @@ var BaseCrudDialect = class {
|
|
|
594
691
|
if ("distinct" in args && args.distinct) {
|
|
595
692
|
const distinct = ensureArray(args.distinct);
|
|
596
693
|
if (this.supportsDistinctOn) {
|
|
597
|
-
result = result.distinctOn(distinct.map((f) =>
|
|
694
|
+
result = result.distinctOn(distinct.map((f) => import_kysely2.sql.ref(`${modelAlias}.${f}`)));
|
|
598
695
|
} else {
|
|
599
696
|
throw new QueryError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
|
|
600
697
|
}
|
|
@@ -644,7 +741,7 @@ var BaseCrudDialect = class {
|
|
|
644
741
|
buildCursorFilter(model, query, cursor, orderBy, negateOrderBy, modelAlias) {
|
|
645
742
|
const _orderBy = orderBy ?? makeDefaultOrderBy(this.schema, model);
|
|
646
743
|
const orderByItems = ensureArray(_orderBy).flatMap((obj) => Object.entries(obj));
|
|
647
|
-
const eb = (0,
|
|
744
|
+
const eb = (0, import_kysely2.expressionBuilder)();
|
|
648
745
|
const subQueryAlias = `${model}$cursor$sub`;
|
|
649
746
|
const cursorFilter = this.buildFilter(eb, model, subQueryAlias, cursor);
|
|
650
747
|
let result = query;
|
|
@@ -679,7 +776,7 @@ var BaseCrudDialect = class {
|
|
|
679
776
|
if (payload === null) {
|
|
680
777
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
681
778
|
if (ownedByModel && !fieldDef.originModel) {
|
|
682
|
-
return this.and(eb, ...keyPairs.map(({ fk }) => eb(
|
|
779
|
+
return this.and(eb, ...keyPairs.map(({ fk }) => eb(import_kysely2.sql.ref(`${modelAlias}.${fk}`), "is", null)));
|
|
683
780
|
} else {
|
|
684
781
|
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
|
|
685
782
|
is: null
|
|
@@ -696,7 +793,7 @@ var BaseCrudDialect = class {
|
|
|
696
793
|
joinAlias
|
|
697
794
|
);
|
|
698
795
|
const filterResultField = `${field}$filter`;
|
|
699
|
-
const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(
|
|
796
|
+
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));
|
|
700
797
|
const conditions = [];
|
|
701
798
|
if ("is" in payload || "isNot" in payload) {
|
|
702
799
|
if ("is" in payload) {
|
|
@@ -726,24 +823,26 @@ var BaseCrudDialect = class {
|
|
|
726
823
|
}
|
|
727
824
|
buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
728
825
|
if (payload === null) {
|
|
729
|
-
return eb(
|
|
826
|
+
return eb(import_kysely2.sql.ref(`${modelAlias}.${field}`), "is", null);
|
|
730
827
|
}
|
|
731
828
|
const relationModel = fieldDef.type;
|
|
732
829
|
const relationFilterSelectAlias = `${modelAlias}$${field}$filter`;
|
|
733
830
|
const buildPkFkWhereRefs = /* @__PURE__ */ __name((eb2) => {
|
|
734
831
|
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
735
832
|
if (m2m) {
|
|
736
|
-
const
|
|
737
|
-
|
|
738
|
-
|
|
833
|
+
const modelIdFields = requireIdFields(this.schema, model);
|
|
834
|
+
(0, import_common_helpers2.invariant)(modelIdFields.length === 1, "many-to-many relation must have exactly one id field");
|
|
835
|
+
const relationIdFields = requireIdFields(this.schema, relationModel);
|
|
836
|
+
(0, import_common_helpers2.invariant)(relationIdFields.length === 1, "many-to-many relation must have exactly one id field");
|
|
837
|
+
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]}`)));
|
|
739
838
|
} else {
|
|
740
839
|
const relationKeyPairs = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
741
840
|
let result2 = this.true(eb2);
|
|
742
841
|
for (const { fk, pk } of relationKeyPairs.keyPairs) {
|
|
743
842
|
if (relationKeyPairs.ownedByModel) {
|
|
744
|
-
result2 = this.and(eb2, result2, eb2(
|
|
843
|
+
result2 = this.and(eb2, result2, eb2(import_kysely2.sql.ref(`${modelAlias}.${fk}`), "=", import_kysely2.sql.ref(`${relationFilterSelectAlias}.${pk}`)));
|
|
745
844
|
} else {
|
|
746
|
-
result2 = this.and(eb2, result2, eb2(
|
|
845
|
+
result2 = this.and(eb2, result2, eb2(import_kysely2.sql.ref(`${modelAlias}.${pk}`), "=", import_kysely2.sql.ref(`${relationFilterSelectAlias}.${fk}`)));
|
|
747
846
|
}
|
|
748
847
|
}
|
|
749
848
|
return result2;
|
|
@@ -826,7 +925,7 @@ var BaseCrudDialect = class {
|
|
|
826
925
|
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
827
926
|
}
|
|
828
927
|
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
829
|
-
if (payload === null || !(0,
|
|
928
|
+
if (payload === null || !(0, import_common_helpers2.isPlainObject)(payload)) {
|
|
830
929
|
return {
|
|
831
930
|
conditions: [
|
|
832
931
|
this.buildLiteralFilter(eb, lhs, type, payload)
|
|
@@ -845,14 +944,14 @@ var BaseCrudDialect = class {
|
|
|
845
944
|
}
|
|
846
945
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
847
946
|
const condition = (0, import_ts_pattern2.match)(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
848
|
-
(0,
|
|
947
|
+
(0, import_common_helpers2.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
849
948
|
if (rhs.length === 0) {
|
|
850
949
|
return this.false(eb);
|
|
851
950
|
} else {
|
|
852
951
|
return eb(lhs, "in", rhs);
|
|
853
952
|
}
|
|
854
953
|
}).with("notIn", () => {
|
|
855
|
-
(0,
|
|
954
|
+
(0, import_common_helpers2.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
856
955
|
if (rhs.length === 0) {
|
|
857
956
|
return this.true(eb);
|
|
858
957
|
} else {
|
|
@@ -892,7 +991,7 @@ var BaseCrudDialect = class {
|
|
|
892
991
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
893
992
|
continue;
|
|
894
993
|
}
|
|
895
|
-
const condition = (0, import_ts_pattern2.match)(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike",
|
|
994
|
+
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(() => {
|
|
896
995
|
throw new QueryError(`Invalid string filter key: ${key}`);
|
|
897
996
|
});
|
|
898
997
|
if (condition) {
|
|
@@ -904,16 +1003,16 @@ var BaseCrudDialect = class {
|
|
|
904
1003
|
}
|
|
905
1004
|
prepStringCasing(eb, value, mode) {
|
|
906
1005
|
if (!mode || mode === "default") {
|
|
907
|
-
return value === null ? value :
|
|
1006
|
+
return value === null ? value : import_kysely2.sql.val(value);
|
|
908
1007
|
}
|
|
909
1008
|
if (typeof value === "string") {
|
|
910
1009
|
return eb.fn("lower", [
|
|
911
|
-
|
|
1010
|
+
import_kysely2.sql.val(value)
|
|
912
1011
|
]);
|
|
913
1012
|
} else if (Array.isArray(value)) {
|
|
914
1013
|
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
915
1014
|
} else {
|
|
916
|
-
return value === null ? null :
|
|
1015
|
+
return value === null ? null : import_kysely2.sql.val(value);
|
|
917
1016
|
}
|
|
918
1017
|
}
|
|
919
1018
|
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
@@ -970,19 +1069,19 @@ var BaseCrudDialect = class {
|
|
|
970
1069
|
"_min",
|
|
971
1070
|
"_max"
|
|
972
1071
|
].includes(field)) {
|
|
973
|
-
(0,
|
|
1072
|
+
(0, import_common_helpers2.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
974
1073
|
for (const [k, v] of Object.entries(value)) {
|
|
975
|
-
(0,
|
|
976
|
-
result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field),
|
|
1074
|
+
(0, import_common_helpers2.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
1075
|
+
result = result.orderBy((eb) => aggregate(eb, this.fieldRef(model, k, eb, modelAlias), field), import_kysely2.sql.raw(this.negateSort(v, negated)));
|
|
977
1076
|
}
|
|
978
1077
|
continue;
|
|
979
1078
|
}
|
|
980
1079
|
switch (field) {
|
|
981
1080
|
case "_count": {
|
|
982
|
-
(0,
|
|
1081
|
+
(0, import_common_helpers2.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
|
|
983
1082
|
for (const [k, v] of Object.entries(value)) {
|
|
984
|
-
(0,
|
|
985
|
-
result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)),
|
|
1083
|
+
(0, import_common_helpers2.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
1084
|
+
result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), import_kysely2.sql.raw(this.negateSort(v, negated)));
|
|
986
1085
|
}
|
|
987
1086
|
continue;
|
|
988
1087
|
}
|
|
@@ -991,11 +1090,11 @@ var BaseCrudDialect = class {
|
|
|
991
1090
|
}
|
|
992
1091
|
const fieldDef = requireField(this.schema, model, field);
|
|
993
1092
|
if (!fieldDef.relation) {
|
|
994
|
-
const fieldRef = this.fieldRef(model, field, (0,
|
|
1093
|
+
const fieldRef = this.fieldRef(model, field, (0, import_kysely2.expressionBuilder)(), modelAlias);
|
|
995
1094
|
if (value === "asc" || value === "desc") {
|
|
996
1095
|
result = result.orderBy(fieldRef, this.negateSort(value, negated));
|
|
997
1096
|
} else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
|
|
998
|
-
result = result.orderBy(fieldRef,
|
|
1097
|
+
result = result.orderBy(fieldRef, import_kysely2.sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
|
|
999
1098
|
}
|
|
1000
1099
|
} else {
|
|
1001
1100
|
const relationModel = fieldDef.type;
|
|
@@ -1004,13 +1103,13 @@ var BaseCrudDialect = class {
|
|
|
1004
1103
|
throw new QueryError(`invalid orderBy value for field "${field}"`);
|
|
1005
1104
|
}
|
|
1006
1105
|
if ("_count" in value) {
|
|
1007
|
-
(0,
|
|
1106
|
+
(0, import_common_helpers2.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
1008
1107
|
const sort = this.negateSort(value._count, negated);
|
|
1009
1108
|
result = result.orderBy((eb) => {
|
|
1010
1109
|
const subQueryAlias = `${modelAlias}$orderBy$${field}$count`;
|
|
1011
1110
|
let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
|
|
1012
1111
|
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, subQueryAlias);
|
|
1013
|
-
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(
|
|
1112
|
+
subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right)))));
|
|
1014
1113
|
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
1015
1114
|
return subQuery;
|
|
1016
1115
|
}, sort);
|
|
@@ -1018,7 +1117,7 @@ var BaseCrudDialect = class {
|
|
|
1018
1117
|
} else {
|
|
1019
1118
|
result = result.leftJoin(relationModel, (join) => {
|
|
1020
1119
|
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
|
|
1021
|
-
return join.on((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(
|
|
1120
|
+
return join.on((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely2.sql.ref(left), "=", import_kysely2.sql.ref(right)))));
|
|
1022
1121
|
});
|
|
1023
1122
|
result = this.buildOrderBy(result, fieldDef.type, relationModel, value, false, negated);
|
|
1024
1123
|
}
|
|
@@ -1070,13 +1169,13 @@ var BaseCrudDialect = class {
|
|
|
1070
1169
|
if (fieldDef.computed) {
|
|
1071
1170
|
return query.select((eb) => this.fieldRef(model, field, eb, modelAlias).as(field));
|
|
1072
1171
|
} else if (!fieldDef.originModel) {
|
|
1073
|
-
return query.select(
|
|
1172
|
+
return query.select(import_kysely2.sql.ref(`${modelAlias}.${field}`).as(field));
|
|
1074
1173
|
} else {
|
|
1075
1174
|
return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
|
|
1076
1175
|
}
|
|
1077
1176
|
}
|
|
1078
1177
|
buildDelegateJoin(thisModel, thisModelAlias, otherModelAlias, query) {
|
|
1079
|
-
const idFields =
|
|
1178
|
+
const idFields = requireIdFields(this.schema, thisModel);
|
|
1080
1179
|
query = query.leftJoin(otherModelAlias, (qb) => {
|
|
1081
1180
|
for (const idField of idFields) {
|
|
1082
1181
|
qb = qb.onRef(`${thisModelAlias}.${idField}`, "=", `${otherModelAlias}.${idField}`);
|
|
@@ -1098,10 +1197,16 @@ var BaseCrudDialect = class {
|
|
|
1098
1197
|
for (const [field, value] of Object.entries(selections.select)) {
|
|
1099
1198
|
const fieldDef = requireField(this.schema, model, field);
|
|
1100
1199
|
const fieldModel = fieldDef.type;
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
fieldCountQuery =
|
|
1200
|
+
let fieldCountQuery;
|
|
1201
|
+
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
1202
|
+
if (m2m) {
|
|
1203
|
+
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}`));
|
|
1204
|
+
} else {
|
|
1205
|
+
fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
1206
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
1207
|
+
for (const [left, right] of joinPairs) {
|
|
1208
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
1209
|
+
}
|
|
1105
1210
|
}
|
|
1106
1211
|
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
1107
1212
|
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
@@ -1181,6 +1286,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1181
1286
|
static {
|
|
1182
1287
|
__name(this, "PostgresCrudDialect");
|
|
1183
1288
|
}
|
|
1289
|
+
constructor(schema, options) {
|
|
1290
|
+
super(schema, options);
|
|
1291
|
+
}
|
|
1184
1292
|
get provider() {
|
|
1185
1293
|
return "postgresql";
|
|
1186
1294
|
}
|
|
@@ -1195,9 +1303,41 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1195
1303
|
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
1196
1304
|
}
|
|
1197
1305
|
} else {
|
|
1198
|
-
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);
|
|
1306
|
+
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);
|
|
1199
1307
|
}
|
|
1200
1308
|
}
|
|
1309
|
+
transformOutput(value, type) {
|
|
1310
|
+
if (value === null || value === void 0) {
|
|
1311
|
+
return value;
|
|
1312
|
+
}
|
|
1313
|
+
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));
|
|
1314
|
+
}
|
|
1315
|
+
transformOutputBigInt(value) {
|
|
1316
|
+
if (typeof value === "bigint") {
|
|
1317
|
+
return value;
|
|
1318
|
+
}
|
|
1319
|
+
(0, import_common_helpers3.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
1320
|
+
return BigInt(value);
|
|
1321
|
+
}
|
|
1322
|
+
transformDecimal(value) {
|
|
1323
|
+
if (value instanceof import_decimal.default) {
|
|
1324
|
+
return value;
|
|
1325
|
+
}
|
|
1326
|
+
(0, import_common_helpers3.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal.default, `Expected string, number or Decimal, got ${typeof value}`);
|
|
1327
|
+
return new import_decimal.default(value);
|
|
1328
|
+
}
|
|
1329
|
+
transformOutputDate(value) {
|
|
1330
|
+
if (typeof value === "string") {
|
|
1331
|
+
return new Date(value);
|
|
1332
|
+
} else if (value instanceof Date && this.options.fixPostgresTimezone !== false) {
|
|
1333
|
+
return new Date(value.getTime() - value.getTimezoneOffset() * 60 * 1e3);
|
|
1334
|
+
} else {
|
|
1335
|
+
return value;
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
transformOutputBytes(value) {
|
|
1339
|
+
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
1340
|
+
}
|
|
1201
1341
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
1202
1342
|
const relationResultName = `${parentAlias}$${relationField}`;
|
|
1203
1343
|
const joinedQuery = this.buildRelationJSON(model, query, relationField, parentAlias, payload, relationResultName);
|
|
@@ -1228,14 +1368,14 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1228
1368
|
buildRelationJoinFilter(query, model, relationField, relationModel, relationModelAlias, parentAlias) {
|
|
1229
1369
|
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
1230
1370
|
if (m2m) {
|
|
1231
|
-
const parentIds =
|
|
1232
|
-
const relationIds =
|
|
1233
|
-
(0,
|
|
1234
|
-
(0,
|
|
1371
|
+
const parentIds = requireIdFields(this.schema, model);
|
|
1372
|
+
const relationIds = requireIdFields(this.schema, relationModel);
|
|
1373
|
+
(0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1374
|
+
(0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1235
1375
|
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}`)));
|
|
1236
1376
|
} else {
|
|
1237
1377
|
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, relationField, relationModelAlias);
|
|
1238
|
-
query = query.where((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(
|
|
1378
|
+
query = query.where((eb) => this.and(eb, ...joinPairs.map(([left, right]) => eb(import_kysely3.sql.ref(left), "=", import_kysely3.sql.ref(right)))));
|
|
1239
1379
|
}
|
|
1240
1380
|
return query;
|
|
1241
1381
|
}
|
|
@@ -1243,9 +1383,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1243
1383
|
qb = qb.select((eb) => {
|
|
1244
1384
|
const objArgs = this.buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName);
|
|
1245
1385
|
if (relationFieldDef.array) {
|
|
1246
|
-
return eb.fn.coalesce(
|
|
1386
|
+
return eb.fn.coalesce(import_kysely3.sql`jsonb_agg(jsonb_build_object(${import_kysely3.sql.join(objArgs)}))`, import_kysely3.sql`'[]'::jsonb`).as("$data");
|
|
1247
1387
|
} else {
|
|
1248
|
-
return
|
|
1388
|
+
return import_kysely3.sql`jsonb_build_object(${import_kysely3.sql.join(objArgs)})`.as("$data");
|
|
1249
1389
|
}
|
|
1250
1390
|
});
|
|
1251
1391
|
return qb;
|
|
@@ -1256,13 +1396,13 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1256
1396
|
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1257
1397
|
if (descendantModels.length > 0) {
|
|
1258
1398
|
objArgs.push(...descendantModels.map((subModel) => [
|
|
1259
|
-
|
|
1399
|
+
import_kysely3.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1260
1400
|
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1261
1401
|
]).flatMap((v) => v));
|
|
1262
1402
|
}
|
|
1263
1403
|
if (payload === true || !payload.select) {
|
|
1264
1404
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
1265
|
-
|
|
1405
|
+
import_kysely3.sql.lit(field),
|
|
1266
1406
|
this.fieldRef(relationModel, field, eb, relationModelAlias, false)
|
|
1267
1407
|
]).flatMap((v) => v));
|
|
1268
1408
|
} else if (payload.select) {
|
|
@@ -1270,14 +1410,14 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1270
1410
|
if (field === "_count") {
|
|
1271
1411
|
const subJson = this.buildCountJson(relationModel, eb, relationModelAlias, value);
|
|
1272
1412
|
return [
|
|
1273
|
-
|
|
1413
|
+
import_kysely3.sql.lit(field),
|
|
1274
1414
|
subJson
|
|
1275
1415
|
];
|
|
1276
1416
|
} else {
|
|
1277
1417
|
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1278
1418
|
const fieldValue = fieldDef.relation ? eb.ref(`${parentResultName}$${field}.$data`) : this.fieldRef(relationModel, field, eb, relationModelAlias, false);
|
|
1279
1419
|
return [
|
|
1280
|
-
|
|
1420
|
+
import_kysely3.sql.lit(field),
|
|
1281
1421
|
fieldValue
|
|
1282
1422
|
];
|
|
1283
1423
|
}
|
|
@@ -1285,7 +1425,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1285
1425
|
}
|
|
1286
1426
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
1287
1427
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
1288
|
-
|
|
1428
|
+
import_kysely3.sql.lit(field),
|
|
1289
1429
|
// reference the synthesized JSON field
|
|
1290
1430
|
eb.ref(`${parentResultName}$${field}.$data`)
|
|
1291
1431
|
]).flatMap((v) => v));
|
|
@@ -1315,7 +1455,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1315
1455
|
}
|
|
1316
1456
|
buildJsonObject(eb, value) {
|
|
1317
1457
|
return eb.fn("jsonb_build_object", Object.entries(value).flatMap(([key, value2]) => [
|
|
1318
|
-
|
|
1458
|
+
import_kysely3.sql.lit(key),
|
|
1319
1459
|
value2
|
|
1320
1460
|
]));
|
|
1321
1461
|
}
|
|
@@ -1343,11 +1483,33 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1343
1483
|
get supportInsertWithDefault() {
|
|
1344
1484
|
return true;
|
|
1345
1485
|
}
|
|
1486
|
+
getFieldSqlType(fieldDef) {
|
|
1487
|
+
if (fieldDef.relation) {
|
|
1488
|
+
throw new QueryError("Cannot get SQL type of a relation field");
|
|
1489
|
+
}
|
|
1490
|
+
let result;
|
|
1491
|
+
if (this.schema.enums?.[fieldDef.type]) {
|
|
1492
|
+
result = "text";
|
|
1493
|
+
} else {
|
|
1494
|
+
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");
|
|
1495
|
+
}
|
|
1496
|
+
if (fieldDef.array) {
|
|
1497
|
+
result += "[]";
|
|
1498
|
+
}
|
|
1499
|
+
return result;
|
|
1500
|
+
}
|
|
1501
|
+
getStringCasingBehavior() {
|
|
1502
|
+
return {
|
|
1503
|
+
supportsILike: true,
|
|
1504
|
+
likeCaseSensitive: true
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1346
1507
|
};
|
|
1347
1508
|
|
|
1348
1509
|
// src/client/crud/dialects/sqlite.ts
|
|
1349
|
-
var
|
|
1350
|
-
var
|
|
1510
|
+
var import_common_helpers4 = require("@zenstackhq/common-helpers");
|
|
1511
|
+
var import_decimal2 = __toESM(require("decimal.js"), 1);
|
|
1512
|
+
var import_kysely4 = require("kysely");
|
|
1351
1513
|
var import_ts_pattern4 = require("ts-pattern");
|
|
1352
1514
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
1353
1515
|
static {
|
|
@@ -1366,9 +1528,57 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1366
1528
|
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1367
1529
|
return JSON.stringify(value);
|
|
1368
1530
|
} else {
|
|
1369
|
-
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);
|
|
1531
|
+
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);
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
transformOutput(value, type) {
|
|
1536
|
+
if (value === null || value === void 0) {
|
|
1537
|
+
return value;
|
|
1538
|
+
} else if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1539
|
+
return this.transformOutputJson(value);
|
|
1540
|
+
} else {
|
|
1541
|
+
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));
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
transformOutputDecimal(value) {
|
|
1545
|
+
if (value instanceof import_decimal2.default) {
|
|
1546
|
+
return value;
|
|
1547
|
+
}
|
|
1548
|
+
(0, import_common_helpers4.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal2.default, `Expected string, number or Decimal, got ${typeof value}`);
|
|
1549
|
+
return new import_decimal2.default(value);
|
|
1550
|
+
}
|
|
1551
|
+
transformOutputBigInt(value) {
|
|
1552
|
+
if (typeof value === "bigint") {
|
|
1553
|
+
return value;
|
|
1554
|
+
}
|
|
1555
|
+
(0, import_common_helpers4.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
1556
|
+
return BigInt(value);
|
|
1557
|
+
}
|
|
1558
|
+
transformOutputBoolean(value) {
|
|
1559
|
+
return !!value;
|
|
1560
|
+
}
|
|
1561
|
+
transformOutputDate(value) {
|
|
1562
|
+
if (typeof value === "number") {
|
|
1563
|
+
return new Date(value);
|
|
1564
|
+
} else if (typeof value === "string") {
|
|
1565
|
+
return new Date(value);
|
|
1566
|
+
} else {
|
|
1567
|
+
return value;
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
transformOutputBytes(value) {
|
|
1571
|
+
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
1572
|
+
}
|
|
1573
|
+
transformOutputJson(value) {
|
|
1574
|
+
if (typeof value === "string") {
|
|
1575
|
+
try {
|
|
1576
|
+
return JSON.parse(value);
|
|
1577
|
+
} catch (e) {
|
|
1578
|
+
throw new QueryError("Invalid JSON returned", e);
|
|
1370
1579
|
}
|
|
1371
1580
|
}
|
|
1581
|
+
return value;
|
|
1372
1582
|
}
|
|
1373
1583
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
1374
1584
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
@@ -1395,13 +1605,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1395
1605
|
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1396
1606
|
if (descendantModels.length > 0) {
|
|
1397
1607
|
objArgs.push(...descendantModels.map((subModel) => [
|
|
1398
|
-
|
|
1608
|
+
import_kysely4.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1399
1609
|
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1400
1610
|
]).flatMap((v) => v));
|
|
1401
1611
|
}
|
|
1402
1612
|
if (payload === true || !payload.select) {
|
|
1403
1613
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
1404
|
-
|
|
1614
|
+
import_kysely4.sql.lit(field),
|
|
1405
1615
|
this.fieldRef(relationModel, field, eb, subQueryName, false)
|
|
1406
1616
|
]).flatMap((v) => v));
|
|
1407
1617
|
} else if (payload.select) {
|
|
@@ -1409,7 +1619,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1409
1619
|
if (field === "_count") {
|
|
1410
1620
|
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1411
1621
|
return [
|
|
1412
|
-
|
|
1622
|
+
import_kysely4.sql.lit(field),
|
|
1413
1623
|
subJson
|
|
1414
1624
|
];
|
|
1415
1625
|
} else {
|
|
@@ -1417,12 +1627,12 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1417
1627
|
if (fieldDef.relation) {
|
|
1418
1628
|
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1419
1629
|
return [
|
|
1420
|
-
|
|
1630
|
+
import_kysely4.sql.lit(field),
|
|
1421
1631
|
subJson
|
|
1422
1632
|
];
|
|
1423
1633
|
} else {
|
|
1424
1634
|
return [
|
|
1425
|
-
|
|
1635
|
+
import_kysely4.sql.lit(field),
|
|
1426
1636
|
this.fieldRef(relationModel, field, eb, subQueryName, false)
|
|
1427
1637
|
];
|
|
1428
1638
|
}
|
|
@@ -1433,15 +1643,15 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1433
1643
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
1434
1644
|
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1435
1645
|
return [
|
|
1436
|
-
|
|
1646
|
+
import_kysely4.sql.lit(field),
|
|
1437
1647
|
subJson
|
|
1438
1648
|
];
|
|
1439
1649
|
}).flatMap((v) => v));
|
|
1440
1650
|
}
|
|
1441
1651
|
if (relationFieldDef.array) {
|
|
1442
|
-
return eb.fn.coalesce(
|
|
1652
|
+
return eb.fn.coalesce(import_kysely4.sql`json_group_array(json_object(${import_kysely4.sql.join(objArgs)}))`, import_kysely4.sql`json_array()`).as("$data");
|
|
1443
1653
|
} else {
|
|
1444
|
-
return
|
|
1654
|
+
return import_kysely4.sql`json_object(${import_kysely4.sql.join(objArgs)})`.as("$data");
|
|
1445
1655
|
}
|
|
1446
1656
|
});
|
|
1447
1657
|
return tbl;
|
|
@@ -1451,10 +1661,10 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1451
1661
|
const relationModel = fieldDef.type;
|
|
1452
1662
|
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
1453
1663
|
if (m2m) {
|
|
1454
|
-
const parentIds =
|
|
1455
|
-
const relationIds =
|
|
1456
|
-
(0,
|
|
1457
|
-
(0,
|
|
1664
|
+
const parentIds = requireIdFields(this.schema, model);
|
|
1665
|
+
const relationIds = requireIdFields(this.schema, relationModel);
|
|
1666
|
+
(0, import_common_helpers4.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1667
|
+
(0, import_common_helpers4.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1458
1668
|
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}`)));
|
|
1459
1669
|
} else {
|
|
1460
1670
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
@@ -1482,7 +1692,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1482
1692
|
}
|
|
1483
1693
|
buildJsonObject(eb, value) {
|
|
1484
1694
|
return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
|
|
1485
|
-
|
|
1695
|
+
import_kysely4.sql.lit(key),
|
|
1486
1696
|
value2
|
|
1487
1697
|
]));
|
|
1488
1698
|
}
|
|
@@ -1506,6 +1716,24 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1506
1716
|
get supportInsertWithDefault() {
|
|
1507
1717
|
return false;
|
|
1508
1718
|
}
|
|
1719
|
+
getFieldSqlType(fieldDef) {
|
|
1720
|
+
if (fieldDef.relation) {
|
|
1721
|
+
throw new QueryError("Cannot get SQL type of a relation field");
|
|
1722
|
+
}
|
|
1723
|
+
if (fieldDef.array) {
|
|
1724
|
+
throw new QueryError("SQLite does not support scalar list type");
|
|
1725
|
+
}
|
|
1726
|
+
if (this.schema.enums?.[fieldDef.type]) {
|
|
1727
|
+
return "text";
|
|
1728
|
+
}
|
|
1729
|
+
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");
|
|
1730
|
+
}
|
|
1731
|
+
getStringCasingBehavior() {
|
|
1732
|
+
return {
|
|
1733
|
+
supportsILike: false,
|
|
1734
|
+
likeCaseSensitive: false
|
|
1735
|
+
};
|
|
1736
|
+
}
|
|
1509
1737
|
};
|
|
1510
1738
|
|
|
1511
1739
|
// src/client/crud/dialects/index.ts
|
|
@@ -1515,8 +1743,8 @@ function getCrudDialect(schema, options) {
|
|
|
1515
1743
|
__name(getCrudDialect, "getCrudDialect");
|
|
1516
1744
|
|
|
1517
1745
|
// src/utils/default-operation-node-visitor.ts
|
|
1518
|
-
var
|
|
1519
|
-
var DefaultOperationNodeVisitor = class extends
|
|
1746
|
+
var import_kysely5 = require("kysely");
|
|
1747
|
+
var DefaultOperationNodeVisitor = class extends import_kysely5.OperationNodeVisitor {
|
|
1520
1748
|
static {
|
|
1521
1749
|
__name(this, "DefaultOperationNodeVisitor");
|
|
1522
1750
|
}
|
|
@@ -1833,12 +2061,12 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1833
2061
|
};
|
|
1834
2062
|
|
|
1835
2063
|
// src/plugins/policy/expression-transformer.ts
|
|
1836
|
-
var
|
|
1837
|
-
var
|
|
2064
|
+
var import_common_helpers6 = require("@zenstackhq/common-helpers");
|
|
2065
|
+
var import_kysely7 = require("kysely");
|
|
1838
2066
|
var import_ts_pattern7 = require("ts-pattern");
|
|
1839
2067
|
|
|
1840
2068
|
// src/plugins/policy/expression-evaluator.ts
|
|
1841
|
-
var
|
|
2069
|
+
var import_common_helpers5 = require("@zenstackhq/common-helpers");
|
|
1842
2070
|
var import_ts_pattern6 = require("ts-pattern");
|
|
1843
2071
|
var ExpressionEvaluator = class {
|
|
1844
2072
|
static {
|
|
@@ -1882,18 +2110,18 @@ var ExpressionEvaluator = class {
|
|
|
1882
2110
|
const right = this.evaluate(expr2.right, context);
|
|
1883
2111
|
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", () => {
|
|
1884
2112
|
const _right = right ?? [];
|
|
1885
|
-
(0,
|
|
2113
|
+
(0, import_common_helpers5.invariant)(Array.isArray(_right), 'expected array for "in" operator');
|
|
1886
2114
|
return _right.includes(left);
|
|
1887
2115
|
}).exhaustive();
|
|
1888
2116
|
}
|
|
1889
2117
|
evaluateCollectionPredicate(expr2, context) {
|
|
1890
2118
|
const op = expr2.op;
|
|
1891
|
-
(0,
|
|
2119
|
+
(0, import_common_helpers5.invariant)(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
|
|
1892
2120
|
const left = this.evaluate(expr2.left, context);
|
|
1893
2121
|
if (!left) {
|
|
1894
2122
|
return false;
|
|
1895
2123
|
}
|
|
1896
|
-
(0,
|
|
2124
|
+
(0, import_common_helpers5.invariant)(Array.isArray(left), "expected array");
|
|
1897
2125
|
return (0, import_ts_pattern6.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1898
2126
|
...context,
|
|
1899
2127
|
thisValue: item
|
|
@@ -1908,24 +2136,30 @@ var ExpressionEvaluator = class {
|
|
|
1908
2136
|
};
|
|
1909
2137
|
|
|
1910
2138
|
// src/plugins/policy/utils.ts
|
|
1911
|
-
var
|
|
2139
|
+
var import_kysely6 = require("kysely");
|
|
1912
2140
|
function trueNode(dialect) {
|
|
1913
|
-
return
|
|
2141
|
+
return import_kysely6.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1914
2142
|
}
|
|
1915
2143
|
__name(trueNode, "trueNode");
|
|
1916
2144
|
function falseNode(dialect) {
|
|
1917
|
-
return
|
|
2145
|
+
return import_kysely6.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1918
2146
|
}
|
|
1919
2147
|
__name(falseNode, "falseNode");
|
|
1920
2148
|
function isTrueNode(node) {
|
|
1921
|
-
return
|
|
2149
|
+
return import_kysely6.ValueNode.is(node) && (node.value === true || node.value === 1);
|
|
1922
2150
|
}
|
|
1923
2151
|
__name(isTrueNode, "isTrueNode");
|
|
1924
2152
|
function isFalseNode(node) {
|
|
1925
|
-
return
|
|
2153
|
+
return import_kysely6.ValueNode.is(node) && (node.value === false || node.value === 0);
|
|
1926
2154
|
}
|
|
1927
2155
|
__name(isFalseNode, "isFalseNode");
|
|
1928
2156
|
function conjunction(dialect, nodes) {
|
|
2157
|
+
if (nodes.length === 0) {
|
|
2158
|
+
return trueNode(dialect);
|
|
2159
|
+
}
|
|
2160
|
+
if (nodes.length === 1) {
|
|
2161
|
+
return nodes[0];
|
|
2162
|
+
}
|
|
1929
2163
|
if (nodes.some(isFalseNode)) {
|
|
1930
2164
|
return falseNode(dialect);
|
|
1931
2165
|
}
|
|
@@ -1933,10 +2167,16 @@ function conjunction(dialect, nodes) {
|
|
|
1933
2167
|
if (items.length === 0) {
|
|
1934
2168
|
return trueNode(dialect);
|
|
1935
2169
|
}
|
|
1936
|
-
return items.reduce((acc, node) =>
|
|
2170
|
+
return items.reduce((acc, node) => import_kysely6.AndNode.create(wrapParensIf(acc, import_kysely6.OrNode.is), wrapParensIf(node, import_kysely6.OrNode.is)));
|
|
1937
2171
|
}
|
|
1938
2172
|
__name(conjunction, "conjunction");
|
|
1939
2173
|
function disjunction(dialect, nodes) {
|
|
2174
|
+
if (nodes.length === 0) {
|
|
2175
|
+
return falseNode(dialect);
|
|
2176
|
+
}
|
|
2177
|
+
if (nodes.length === 1) {
|
|
2178
|
+
return nodes[0];
|
|
2179
|
+
}
|
|
1940
2180
|
if (nodes.some(isTrueNode)) {
|
|
1941
2181
|
return trueNode(dialect);
|
|
1942
2182
|
}
|
|
@@ -1944,26 +2184,36 @@ function disjunction(dialect, nodes) {
|
|
|
1944
2184
|
if (items.length === 0) {
|
|
1945
2185
|
return falseNode(dialect);
|
|
1946
2186
|
}
|
|
1947
|
-
return items.reduce((acc, node) =>
|
|
2187
|
+
return items.reduce((acc, node) => import_kysely6.OrNode.create(wrapParensIf(acc, import_kysely6.AndNode.is), wrapParensIf(node, import_kysely6.AndNode.is)));
|
|
1948
2188
|
}
|
|
1949
2189
|
__name(disjunction, "disjunction");
|
|
1950
|
-
function logicalNot(node) {
|
|
1951
|
-
|
|
2190
|
+
function logicalNot(dialect, node) {
|
|
2191
|
+
if (isTrueNode(node)) {
|
|
2192
|
+
return falseNode(dialect);
|
|
2193
|
+
}
|
|
2194
|
+
if (isFalseNode(node)) {
|
|
2195
|
+
return trueNode(dialect);
|
|
2196
|
+
}
|
|
2197
|
+
return import_kysely6.UnaryOperationNode.create(import_kysely6.OperatorNode.create("not"), wrapParensIf(node, (n) => import_kysely6.AndNode.is(n) || import_kysely6.OrNode.is(n)));
|
|
1952
2198
|
}
|
|
1953
2199
|
__name(logicalNot, "logicalNot");
|
|
2200
|
+
function wrapParensIf(node, predicate) {
|
|
2201
|
+
return predicate(node) ? import_kysely6.ParensNode.create(node) : node;
|
|
2202
|
+
}
|
|
2203
|
+
__name(wrapParensIf, "wrapParensIf");
|
|
1954
2204
|
function buildIsFalse(node, dialect) {
|
|
1955
2205
|
if (isFalseNode(node)) {
|
|
1956
2206
|
return trueNode(dialect);
|
|
1957
2207
|
} else if (isTrueNode(node)) {
|
|
1958
2208
|
return falseNode(dialect);
|
|
1959
2209
|
}
|
|
1960
|
-
return
|
|
2210
|
+
return import_kysely6.BinaryOperationNode.create(
|
|
1961
2211
|
// coalesce so null is treated as false
|
|
1962
|
-
|
|
2212
|
+
import_kysely6.FunctionNode.create("coalesce", [
|
|
1963
2213
|
node,
|
|
1964
2214
|
falseNode(dialect)
|
|
1965
2215
|
]),
|
|
1966
|
-
|
|
2216
|
+
import_kysely6.OperatorNode.create("="),
|
|
1967
2217
|
falseNode(dialect)
|
|
1968
2218
|
);
|
|
1969
2219
|
}
|
|
@@ -1972,11 +2222,11 @@ function getTableName(node) {
|
|
|
1972
2222
|
if (!node) {
|
|
1973
2223
|
return node;
|
|
1974
2224
|
}
|
|
1975
|
-
if (
|
|
2225
|
+
if (import_kysely6.TableNode.is(node)) {
|
|
1976
2226
|
return node.table.identifier.name;
|
|
1977
|
-
} else if (
|
|
2227
|
+
} else if (import_kysely6.AliasNode.is(node)) {
|
|
1978
2228
|
return getTableName(node.node);
|
|
1979
|
-
} else if (
|
|
2229
|
+
} else if (import_kysely6.ReferenceNode.is(node) && node.table) {
|
|
1980
2230
|
return getTableName(node.table);
|
|
1981
2231
|
}
|
|
1982
2232
|
return void 0;
|
|
@@ -2009,16 +2259,21 @@ var ExpressionTransformer = class {
|
|
|
2009
2259
|
static {
|
|
2010
2260
|
__name(this, "ExpressionTransformer");
|
|
2011
2261
|
}
|
|
2012
|
-
|
|
2013
|
-
clientOptions;
|
|
2014
|
-
auth;
|
|
2262
|
+
client;
|
|
2015
2263
|
dialect;
|
|
2016
|
-
constructor(
|
|
2017
|
-
this.
|
|
2018
|
-
this.clientOptions = clientOptions;
|
|
2019
|
-
this.auth = auth;
|
|
2264
|
+
constructor(client) {
|
|
2265
|
+
this.client = client;
|
|
2020
2266
|
this.dialect = getCrudDialect(this.schema, this.clientOptions);
|
|
2021
2267
|
}
|
|
2268
|
+
get schema() {
|
|
2269
|
+
return this.client.$schema;
|
|
2270
|
+
}
|
|
2271
|
+
get clientOptions() {
|
|
2272
|
+
return this.client.$options;
|
|
2273
|
+
}
|
|
2274
|
+
get auth() {
|
|
2275
|
+
return this.client.$auth;
|
|
2276
|
+
}
|
|
2022
2277
|
get authType() {
|
|
2023
2278
|
if (!this.schema.authType) {
|
|
2024
2279
|
throw new InternalError('Schema does not have an "authType" specified');
|
|
@@ -2036,16 +2291,12 @@ var ExpressionTransformer = class {
|
|
|
2036
2291
|
return this.transformValue(expr2.value, typeof expr2.value === "string" ? "String" : typeof expr2.value === "boolean" ? "Boolean" : "Int");
|
|
2037
2292
|
}
|
|
2038
2293
|
_array(expr2, context) {
|
|
2039
|
-
return
|
|
2294
|
+
return import_kysely7.ValueListNode.create(expr2.items.map((item) => this.transform(item, context)));
|
|
2040
2295
|
}
|
|
2041
2296
|
_field(expr2, context) {
|
|
2042
2297
|
const fieldDef = requireField(this.schema, context.model, expr2.field);
|
|
2043
2298
|
if (!fieldDef.relation) {
|
|
2044
|
-
|
|
2045
|
-
return context.thisEntity[expr2.field];
|
|
2046
|
-
} else {
|
|
2047
|
-
return this.createColumnRef(expr2.field, context);
|
|
2048
|
-
}
|
|
2299
|
+
return this.createColumnRef(expr2.field, context);
|
|
2049
2300
|
} else {
|
|
2050
2301
|
const { memberFilter, memberSelect, ...restContext } = context;
|
|
2051
2302
|
const relation = this.transformRelationAccess(expr2.field, fieldDef.type, restContext);
|
|
@@ -2060,18 +2311,18 @@ var ExpressionTransformer = class {
|
|
|
2060
2311
|
}
|
|
2061
2312
|
mergeWhere(where, memberFilter) {
|
|
2062
2313
|
if (!where) {
|
|
2063
|
-
return
|
|
2314
|
+
return import_kysely7.WhereNode.create(memberFilter ?? trueNode(this.dialect));
|
|
2064
2315
|
}
|
|
2065
2316
|
if (!memberFilter) {
|
|
2066
2317
|
return where;
|
|
2067
2318
|
}
|
|
2068
|
-
return
|
|
2319
|
+
return import_kysely7.WhereNode.create(conjunction(this.dialect, [
|
|
2069
2320
|
where.where,
|
|
2070
2321
|
memberFilter
|
|
2071
2322
|
]));
|
|
2072
2323
|
}
|
|
2073
2324
|
_null() {
|
|
2074
|
-
return
|
|
2325
|
+
return import_kysely7.ValueNode.createImmediate(null);
|
|
2075
2326
|
}
|
|
2076
2327
|
_binary(expr2, context) {
|
|
2077
2328
|
if (expr2.op === "&&") {
|
|
@@ -2086,51 +2337,88 @@ var ExpressionTransformer = class {
|
|
|
2086
2337
|
]);
|
|
2087
2338
|
}
|
|
2088
2339
|
if (this.isAuthCall(expr2.left) || this.isAuthCall(expr2.right)) {
|
|
2089
|
-
return this.transformAuthBinary(expr2);
|
|
2340
|
+
return this.transformAuthBinary(expr2, context);
|
|
2090
2341
|
}
|
|
2091
2342
|
const op = expr2.op;
|
|
2092
2343
|
if (op === "?" || op === "!" || op === "^") {
|
|
2093
2344
|
return this.transformCollectionPredicate(expr2, context);
|
|
2094
2345
|
}
|
|
2095
|
-
const
|
|
2096
|
-
const
|
|
2346
|
+
const { normalizedLeft, normalizedRight } = this.normalizeBinaryOperationOperands(expr2, context);
|
|
2347
|
+
const left = this.transform(normalizedLeft, context);
|
|
2348
|
+
const right = this.transform(normalizedRight, context);
|
|
2097
2349
|
if (op === "in") {
|
|
2098
2350
|
if (this.isNullNode(left)) {
|
|
2099
2351
|
return this.transformValue(false, "Boolean");
|
|
2100
2352
|
} else {
|
|
2101
|
-
if (
|
|
2102
|
-
return
|
|
2353
|
+
if (import_kysely7.ValueListNode.is(right)) {
|
|
2354
|
+
return import_kysely7.BinaryOperationNode.create(left, import_kysely7.OperatorNode.create("in"), right);
|
|
2103
2355
|
} else {
|
|
2104
|
-
return
|
|
2356
|
+
return import_kysely7.BinaryOperationNode.create(left, import_kysely7.OperatorNode.create("="), import_kysely7.FunctionNode.create("any", [
|
|
2105
2357
|
right
|
|
2106
2358
|
]));
|
|
2107
2359
|
}
|
|
2108
2360
|
}
|
|
2109
2361
|
}
|
|
2110
2362
|
if (this.isNullNode(right)) {
|
|
2111
|
-
return
|
|
2363
|
+
return this.transformNullCheck(left, expr2.op);
|
|
2112
2364
|
} else if (this.isNullNode(left)) {
|
|
2113
|
-
return
|
|
2365
|
+
return this.transformNullCheck(right, expr2.op);
|
|
2366
|
+
} else {
|
|
2367
|
+
return import_kysely7.BinaryOperationNode.create(left, this.transformOperator(op), right);
|
|
2114
2368
|
}
|
|
2115
|
-
|
|
2369
|
+
}
|
|
2370
|
+
transformNullCheck(expr2, operator) {
|
|
2371
|
+
(0, import_common_helpers6.invariant)(operator === "==" || operator === "!=", 'operator must be "==" or "!=" for null comparison');
|
|
2372
|
+
if (import_kysely7.ValueNode.is(expr2)) {
|
|
2373
|
+
if (expr2.value === null) {
|
|
2374
|
+
return operator === "==" ? trueNode(this.dialect) : falseNode(this.dialect);
|
|
2375
|
+
} else {
|
|
2376
|
+
return operator === "==" ? falseNode(this.dialect) : trueNode(this.dialect);
|
|
2377
|
+
}
|
|
2378
|
+
} else {
|
|
2379
|
+
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));
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
normalizeBinaryOperationOperands(expr2, context) {
|
|
2383
|
+
let normalizedLeft = expr2.left;
|
|
2384
|
+
if (this.isRelationField(expr2.left, context.model)) {
|
|
2385
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isNull(expr2.right), "only null comparison is supported for relation field");
|
|
2386
|
+
const leftRelDef = this.getFieldDefFromFieldRef(expr2.left, context.model);
|
|
2387
|
+
(0, import_common_helpers6.invariant)(leftRelDef, "failed to get relation field definition");
|
|
2388
|
+
const idFields = requireIdFields(this.schema, leftRelDef.type);
|
|
2389
|
+
normalizedLeft = this.makeOrAppendMember(normalizedLeft, idFields[0]);
|
|
2390
|
+
}
|
|
2391
|
+
let normalizedRight = expr2.right;
|
|
2392
|
+
if (this.isRelationField(expr2.right, context.model)) {
|
|
2393
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isNull(expr2.left), "only null comparison is supported for relation field");
|
|
2394
|
+
const rightRelDef = this.getFieldDefFromFieldRef(expr2.right, context.model);
|
|
2395
|
+
(0, import_common_helpers6.invariant)(rightRelDef, "failed to get relation field definition");
|
|
2396
|
+
const idFields = requireIdFields(this.schema, rightRelDef.type);
|
|
2397
|
+
normalizedRight = this.makeOrAppendMember(normalizedRight, idFields[0]);
|
|
2398
|
+
}
|
|
2399
|
+
return {
|
|
2400
|
+
normalizedLeft,
|
|
2401
|
+
normalizedRight
|
|
2402
|
+
};
|
|
2116
2403
|
}
|
|
2117
2404
|
transformCollectionPredicate(expr2, context) {
|
|
2118
|
-
(0,
|
|
2405
|
+
(0, import_common_helpers6.invariant)(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
|
|
2119
2406
|
if (this.isAuthCall(expr2.left) || this.isAuthMember(expr2.left)) {
|
|
2120
2407
|
const value = new ExpressionEvaluator().evaluate(expr2, {
|
|
2121
2408
|
auth: this.auth
|
|
2122
2409
|
});
|
|
2123
2410
|
return this.transformValue(value, "Boolean");
|
|
2124
2411
|
}
|
|
2125
|
-
(0,
|
|
2412
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
|
|
2126
2413
|
let newContextModel;
|
|
2127
|
-
|
|
2128
|
-
|
|
2414
|
+
const fieldDef = this.getFieldDefFromFieldRef(expr2.left, context.model);
|
|
2415
|
+
if (fieldDef) {
|
|
2416
|
+
(0, import_common_helpers6.invariant)(fieldDef.relation, `field is not a relation: ${JSON.stringify(expr2.left)}`);
|
|
2129
2417
|
newContextModel = fieldDef.type;
|
|
2130
2418
|
} else {
|
|
2131
|
-
(0,
|
|
2132
|
-
const
|
|
2133
|
-
newContextModel =
|
|
2419
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isMember(expr2.left) && ExpressionUtils.isField(expr2.left.receiver), "left operand must be member access with field receiver");
|
|
2420
|
+
const fieldDef2 = requireField(this.schema, context.model, expr2.left.receiver.field);
|
|
2421
|
+
newContextModel = fieldDef2.type;
|
|
2134
2422
|
for (const member of expr2.left.members) {
|
|
2135
2423
|
const memberDef = requireField(this.schema, newContextModel, member);
|
|
2136
2424
|
newContextModel = memberDef.type;
|
|
@@ -2139,71 +2427,118 @@ var ExpressionTransformer = class {
|
|
|
2139
2427
|
let predicateFilter = this.transform(expr2.right, {
|
|
2140
2428
|
...context,
|
|
2141
2429
|
model: newContextModel,
|
|
2142
|
-
alias: void 0
|
|
2143
|
-
thisEntity: void 0
|
|
2430
|
+
alias: void 0
|
|
2144
2431
|
});
|
|
2145
2432
|
if (expr2.op === "!") {
|
|
2146
|
-
predicateFilter = logicalNot(predicateFilter);
|
|
2433
|
+
predicateFilter = logicalNot(this.dialect, predicateFilter);
|
|
2147
2434
|
}
|
|
2148
|
-
const count =
|
|
2149
|
-
|
|
2435
|
+
const count = import_kysely7.FunctionNode.create("count", [
|
|
2436
|
+
import_kysely7.ValueNode.createImmediate(1)
|
|
2150
2437
|
]);
|
|
2151
|
-
const predicateResult = (0, import_ts_pattern7.match)(expr2.op).with("?", () =>
|
|
2438
|
+
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();
|
|
2152
2439
|
return this.transform(expr2.left, {
|
|
2153
2440
|
...context,
|
|
2154
|
-
memberSelect:
|
|
2441
|
+
memberSelect: import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(predicateResult, import_kysely7.IdentifierNode.create("$t"))),
|
|
2155
2442
|
memberFilter: predicateFilter
|
|
2156
2443
|
});
|
|
2157
2444
|
}
|
|
2158
|
-
transformAuthBinary(expr2) {
|
|
2445
|
+
transformAuthBinary(expr2, context) {
|
|
2159
2446
|
if (expr2.op !== "==" && expr2.op !== "!=") {
|
|
2160
|
-
throw new
|
|
2447
|
+
throw new QueryError(`Unsupported operator for \`auth()\` in policy of model "${context.model}": ${expr2.op}`);
|
|
2161
2448
|
}
|
|
2449
|
+
let authExpr;
|
|
2162
2450
|
let other;
|
|
2163
2451
|
if (this.isAuthCall(expr2.left)) {
|
|
2452
|
+
authExpr = expr2.left;
|
|
2164
2453
|
other = expr2.right;
|
|
2165
2454
|
} else {
|
|
2455
|
+
authExpr = expr2.right;
|
|
2166
2456
|
other = expr2.left;
|
|
2167
2457
|
}
|
|
2168
2458
|
if (ExpressionUtils.isNull(other)) {
|
|
2169
2459
|
return this.transformValue(expr2.op === "==" ? !this.auth : !!this.auth, "Boolean");
|
|
2170
2460
|
} else {
|
|
2171
|
-
|
|
2461
|
+
const authModel = getModel(this.schema, this.authType);
|
|
2462
|
+
if (!authModel) {
|
|
2463
|
+
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`);
|
|
2464
|
+
}
|
|
2465
|
+
const idFields = Object.values(authModel.fields).filter((f) => f.id).map((f) => f.name);
|
|
2466
|
+
(0, import_common_helpers6.invariant)(idFields.length > 0, "auth type model must have at least one id field");
|
|
2467
|
+
const conditions = idFields.map((fieldName) => ExpressionUtils.binary(ExpressionUtils.member(authExpr, [
|
|
2468
|
+
fieldName
|
|
2469
|
+
]), "==", this.makeOrAppendMember(other, fieldName)));
|
|
2470
|
+
let result = this.buildAnd(conditions);
|
|
2471
|
+
if (expr2.op === "!=") {
|
|
2472
|
+
result = this.buildLogicalNot(result);
|
|
2473
|
+
}
|
|
2474
|
+
return this.transform(result, context);
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
makeOrAppendMember(other, fieldName) {
|
|
2478
|
+
if (ExpressionUtils.isMember(other)) {
|
|
2479
|
+
return ExpressionUtils.member(other.receiver, [
|
|
2480
|
+
...other.members,
|
|
2481
|
+
fieldName
|
|
2482
|
+
]);
|
|
2483
|
+
} else {
|
|
2484
|
+
return ExpressionUtils.member(other, [
|
|
2485
|
+
fieldName
|
|
2486
|
+
]);
|
|
2172
2487
|
}
|
|
2173
2488
|
}
|
|
2174
2489
|
transformValue(value, type) {
|
|
2175
|
-
|
|
2490
|
+
if (value === true) {
|
|
2491
|
+
return trueNode(this.dialect);
|
|
2492
|
+
} else if (value === false) {
|
|
2493
|
+
return falseNode(this.dialect);
|
|
2494
|
+
} else {
|
|
2495
|
+
return import_kysely7.ValueNode.create(this.dialect.transformPrimitive(value, type, false) ?? null);
|
|
2496
|
+
}
|
|
2176
2497
|
}
|
|
2177
2498
|
_unary(expr2, context) {
|
|
2178
|
-
(0,
|
|
2179
|
-
return
|
|
2499
|
+
(0, import_common_helpers6.invariant)(expr2.op === "!", 'only "!" operator is supported');
|
|
2500
|
+
return logicalNot(this.dialect, this.transform(expr2.operand, context));
|
|
2180
2501
|
}
|
|
2181
2502
|
transformOperator(op) {
|
|
2182
2503
|
const mappedOp = (0, import_ts_pattern7.match)(op).with("==", () => "=").otherwise(() => op);
|
|
2183
|
-
return
|
|
2504
|
+
return import_kysely7.OperatorNode.create(mappedOp);
|
|
2184
2505
|
}
|
|
2185
2506
|
_call(expr2, context) {
|
|
2186
2507
|
const result = this.transformCall(expr2, context);
|
|
2187
2508
|
return result.toOperationNode();
|
|
2188
2509
|
}
|
|
2189
2510
|
transformCall(expr2, context) {
|
|
2190
|
-
const func = this.
|
|
2511
|
+
const func = this.getFunctionImpl(expr2.function);
|
|
2191
2512
|
if (!func) {
|
|
2192
2513
|
throw new QueryError(`Function not implemented: ${expr2.function}`);
|
|
2193
2514
|
}
|
|
2194
|
-
const eb = (0,
|
|
2515
|
+
const eb = (0, import_kysely7.expressionBuilder)();
|
|
2195
2516
|
return func(eb, (expr2.args ?? []).map((arg) => this.transformCallArg(eb, arg, context)), {
|
|
2517
|
+
client: this.client,
|
|
2196
2518
|
dialect: this.dialect,
|
|
2197
2519
|
model: context.model,
|
|
2520
|
+
modelAlias: context.alias ?? context.model,
|
|
2198
2521
|
operation: context.operation
|
|
2199
2522
|
});
|
|
2200
2523
|
}
|
|
2524
|
+
getFunctionImpl(functionName) {
|
|
2525
|
+
let func = this.clientOptions.functions?.[functionName];
|
|
2526
|
+
if (!func) {
|
|
2527
|
+
for (const plugin of this.clientOptions.plugins ?? []) {
|
|
2528
|
+
if (plugin.functions?.[functionName]) {
|
|
2529
|
+
func = plugin.functions[functionName];
|
|
2530
|
+
break;
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
return func;
|
|
2535
|
+
}
|
|
2201
2536
|
transformCallArg(eb, arg, context) {
|
|
2202
2537
|
if (ExpressionUtils.isLiteral(arg)) {
|
|
2203
2538
|
return eb.val(arg.value);
|
|
2204
2539
|
}
|
|
2205
2540
|
if (ExpressionUtils.isField(arg)) {
|
|
2206
|
-
return
|
|
2541
|
+
return eb.ref(arg.field);
|
|
2207
2542
|
}
|
|
2208
2543
|
if (ExpressionUtils.isCall(arg)) {
|
|
2209
2544
|
return this.transformCall(arg, context);
|
|
@@ -2218,14 +2553,32 @@ var ExpressionTransformer = class {
|
|
|
2218
2553
|
if (this.isAuthCall(expr2.receiver)) {
|
|
2219
2554
|
return this.valueMemberAccess(this.auth, expr2, this.authType);
|
|
2220
2555
|
}
|
|
2221
|
-
(0,
|
|
2556
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isField(expr2.receiver) || ExpressionUtils.isThis(expr2.receiver), 'expect receiver to be field expression or "this"');
|
|
2557
|
+
let members = expr2.members;
|
|
2558
|
+
let receiver;
|
|
2222
2559
|
const { memberFilter, memberSelect, ...restContext } = context;
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2560
|
+
if (ExpressionUtils.isThis(expr2.receiver)) {
|
|
2561
|
+
if (expr2.members.length === 1) {
|
|
2562
|
+
return this._field(ExpressionUtils.field(expr2.members[0]), context);
|
|
2563
|
+
} else {
|
|
2564
|
+
const firstMemberFieldDef = requireField(this.schema, context.model, expr2.members[0]);
|
|
2565
|
+
receiver = this.transformRelationAccess(expr2.members[0], firstMemberFieldDef.type, restContext);
|
|
2566
|
+
members = expr2.members.slice(1);
|
|
2567
|
+
}
|
|
2568
|
+
} else {
|
|
2569
|
+
receiver = this.transform(expr2.receiver, restContext);
|
|
2570
|
+
}
|
|
2571
|
+
(0, import_common_helpers6.invariant)(import_kysely7.SelectQueryNode.is(receiver), "expected receiver to be select query");
|
|
2572
|
+
let startType;
|
|
2573
|
+
if (ExpressionUtils.isField(expr2.receiver)) {
|
|
2574
|
+
const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
|
|
2575
|
+
startType = receiverField.type;
|
|
2576
|
+
} else {
|
|
2577
|
+
startType = context.model;
|
|
2578
|
+
}
|
|
2226
2579
|
const memberFields = [];
|
|
2227
|
-
let currType =
|
|
2228
|
-
for (const member of
|
|
2580
|
+
let currType = startType;
|
|
2581
|
+
for (const member of members) {
|
|
2229
2582
|
const fieldDef = requireField(this.schema, currType, member);
|
|
2230
2583
|
memberFields.push({
|
|
2231
2584
|
fieldDef,
|
|
@@ -2234,22 +2587,21 @@ var ExpressionTransformer = class {
|
|
|
2234
2587
|
currType = fieldDef.type;
|
|
2235
2588
|
}
|
|
2236
2589
|
let currNode = void 0;
|
|
2237
|
-
for (let i =
|
|
2238
|
-
const member =
|
|
2590
|
+
for (let i = members.length - 1; i >= 0; i--) {
|
|
2591
|
+
const member = members[i];
|
|
2239
2592
|
const { fieldDef, fromModel } = memberFields[i];
|
|
2240
2593
|
if (fieldDef.relation) {
|
|
2241
2594
|
const relation = this.transformRelationAccess(member, fieldDef.type, {
|
|
2242
2595
|
...restContext,
|
|
2243
2596
|
model: fromModel,
|
|
2244
|
-
alias: void 0
|
|
2245
|
-
thisEntity: void 0
|
|
2597
|
+
alias: void 0
|
|
2246
2598
|
});
|
|
2247
2599
|
if (currNode) {
|
|
2248
|
-
(0,
|
|
2600
|
+
(0, import_common_helpers6.invariant)(import_kysely7.SelectQueryNode.is(currNode), "expected select query node");
|
|
2249
2601
|
currNode = {
|
|
2250
2602
|
...relation,
|
|
2251
2603
|
selections: [
|
|
2252
|
-
|
|
2604
|
+
import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(currNode, import_kysely7.IdentifierNode.create(members[i + 1])))
|
|
2253
2605
|
]
|
|
2254
2606
|
};
|
|
2255
2607
|
} else {
|
|
@@ -2262,21 +2614,21 @@ var ExpressionTransformer = class {
|
|
|
2262
2614
|
};
|
|
2263
2615
|
}
|
|
2264
2616
|
} else {
|
|
2265
|
-
(0,
|
|
2266
|
-
(0,
|
|
2267
|
-
currNode =
|
|
2617
|
+
(0, import_common_helpers6.invariant)(i === members.length - 1, "plain field access must be the last segment");
|
|
2618
|
+
(0, import_common_helpers6.invariant)(!currNode, "plain field access must be the last segment");
|
|
2619
|
+
currNode = import_kysely7.ColumnNode.create(member);
|
|
2268
2620
|
}
|
|
2269
2621
|
}
|
|
2270
2622
|
return {
|
|
2271
2623
|
...receiver,
|
|
2272
2624
|
selections: [
|
|
2273
|
-
|
|
2625
|
+
import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(currNode, import_kysely7.IdentifierNode.create("$t")))
|
|
2274
2626
|
]
|
|
2275
2627
|
};
|
|
2276
2628
|
}
|
|
2277
2629
|
valueMemberAccess(receiver, expr2, receiverType) {
|
|
2278
2630
|
if (!receiver) {
|
|
2279
|
-
return
|
|
2631
|
+
return import_kysely7.ValueNode.createImmediate(null);
|
|
2280
2632
|
}
|
|
2281
2633
|
if (expr2.members.length !== 1) {
|
|
2282
2634
|
throw new Error(`Only single member access is supported`);
|
|
@@ -2287,40 +2639,33 @@ var ExpressionTransformer = class {
|
|
|
2287
2639
|
return this.transformValue(fieldValue, fieldDef.type);
|
|
2288
2640
|
}
|
|
2289
2641
|
transformRelationAccess(field, relationModel, context) {
|
|
2642
|
+
const m2m = getManyToManyRelation(this.schema, context.model, field);
|
|
2643
|
+
if (m2m) {
|
|
2644
|
+
return this.transformManyToManyRelationAccess(m2m, context);
|
|
2645
|
+
}
|
|
2290
2646
|
const fromModel = context.model;
|
|
2291
2647
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, fromModel, field);
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
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])));
|
|
2296
|
-
} else {
|
|
2297
|
-
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])));
|
|
2298
|
-
}
|
|
2299
|
-
return {
|
|
2300
|
-
kind: "SelectQueryNode",
|
|
2301
|
-
from: import_kysely6.FromNode.create([
|
|
2302
|
-
import_kysely6.TableNode.create(relationModel)
|
|
2303
|
-
]),
|
|
2304
|
-
where: import_kysely6.WhereNode.create(condition)
|
|
2305
|
-
};
|
|
2648
|
+
let condition;
|
|
2649
|
+
if (ownedByModel) {
|
|
2650
|
+
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)))));
|
|
2306
2651
|
} else {
|
|
2307
|
-
|
|
2308
|
-
if (ownedByModel) {
|
|
2309
|
-
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)))));
|
|
2310
|
-
} else {
|
|
2311
|
-
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)))));
|
|
2312
|
-
}
|
|
2313
|
-
return {
|
|
2314
|
-
kind: "SelectQueryNode",
|
|
2315
|
-
from: import_kysely6.FromNode.create([
|
|
2316
|
-
import_kysely6.TableNode.create(relationModel)
|
|
2317
|
-
]),
|
|
2318
|
-
where: import_kysely6.WhereNode.create(condition)
|
|
2319
|
-
};
|
|
2652
|
+
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)))));
|
|
2320
2653
|
}
|
|
2654
|
+
return {
|
|
2655
|
+
kind: "SelectQueryNode",
|
|
2656
|
+
from: import_kysely7.FromNode.create([
|
|
2657
|
+
import_kysely7.TableNode.create(relationModel)
|
|
2658
|
+
]),
|
|
2659
|
+
where: import_kysely7.WhereNode.create(condition)
|
|
2660
|
+
};
|
|
2661
|
+
}
|
|
2662
|
+
transformManyToManyRelationAccess(m2m, context) {
|
|
2663
|
+
const eb = (0, import_kysely7.expressionBuilder)();
|
|
2664
|
+
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}`));
|
|
2665
|
+
return relationQuery.toOperationNode();
|
|
2321
2666
|
}
|
|
2322
2667
|
createColumnRef(column, context) {
|
|
2323
|
-
return
|
|
2668
|
+
return import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(column), import_kysely7.TableNode.create(context.alias ?? context.model));
|
|
2324
2669
|
}
|
|
2325
2670
|
isAuthCall(value) {
|
|
2326
2671
|
return ExpressionUtils.isCall(value) && value.function === "auth";
|
|
@@ -2329,7 +2674,32 @@ var ExpressionTransformer = class {
|
|
|
2329
2674
|
return ExpressionUtils.isMember(expr2) && this.isAuthCall(expr2.receiver);
|
|
2330
2675
|
}
|
|
2331
2676
|
isNullNode(node) {
|
|
2332
|
-
return
|
|
2677
|
+
return import_kysely7.ValueNode.is(node) && node.value === null;
|
|
2678
|
+
}
|
|
2679
|
+
buildLogicalNot(result) {
|
|
2680
|
+
return ExpressionUtils.unary("!", result);
|
|
2681
|
+
}
|
|
2682
|
+
buildAnd(conditions) {
|
|
2683
|
+
if (conditions.length === 0) {
|
|
2684
|
+
return ExpressionUtils.literal(true);
|
|
2685
|
+
} else if (conditions.length === 1) {
|
|
2686
|
+
return conditions[0];
|
|
2687
|
+
} else {
|
|
2688
|
+
return conditions.reduce((acc, condition) => ExpressionUtils.binary(acc, "&&", condition));
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
isRelationField(expr2, model) {
|
|
2692
|
+
const fieldDef = this.getFieldDefFromFieldRef(expr2, model);
|
|
2693
|
+
return !!fieldDef?.relation;
|
|
2694
|
+
}
|
|
2695
|
+
getFieldDefFromFieldRef(expr2, model) {
|
|
2696
|
+
if (ExpressionUtils.isField(expr2)) {
|
|
2697
|
+
return requireField(this.schema, model, expr2.field);
|
|
2698
|
+
} else if (ExpressionUtils.isMember(expr2) && expr2.members.length === 1 && ExpressionUtils.isThis(expr2.receiver)) {
|
|
2699
|
+
return requireField(this.schema, model, expr2.members[0]);
|
|
2700
|
+
} else {
|
|
2701
|
+
return void 0;
|
|
2702
|
+
}
|
|
2333
2703
|
}
|
|
2334
2704
|
};
|
|
2335
2705
|
_ts_decorate([
|
|
@@ -2402,7 +2772,7 @@ _ts_decorate([
|
|
|
2402
2772
|
], ExpressionTransformer.prototype, "_member", null);
|
|
2403
2773
|
|
|
2404
2774
|
// src/plugins/policy/policy-handler.ts
|
|
2405
|
-
var PolicyHandler = class extends
|
|
2775
|
+
var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
|
|
2406
2776
|
static {
|
|
2407
2777
|
__name(this, "PolicyHandler");
|
|
2408
2778
|
}
|
|
@@ -2417,111 +2787,296 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2417
2787
|
}
|
|
2418
2788
|
async handle(node, proceed) {
|
|
2419
2789
|
if (!this.isCrudQueryNode(node)) {
|
|
2420
|
-
throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
|
|
2790
|
+
throw new RejectedByPolicyError(void 0, RejectedByPolicyReason.OTHER, "non-CRUD queries are not allowed");
|
|
2421
2791
|
}
|
|
2422
2792
|
if (!this.isMutationQueryNode(node)) {
|
|
2423
2793
|
return proceed(this.transformNode(node));
|
|
2424
2794
|
}
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
if (
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2795
|
+
const { mutationModel } = this.getMutationModel(node);
|
|
2796
|
+
if (import_kysely8.InsertQueryNode.is(node)) {
|
|
2797
|
+
const isManyToManyJoinTable = this.isManyToManyJoinTable(mutationModel);
|
|
2798
|
+
let needCheckPreCreate = true;
|
|
2799
|
+
if (!isManyToManyJoinTable) {
|
|
2800
|
+
const constCondition = this.tryGetConstantPolicy(mutationModel, "create");
|
|
2801
|
+
if (constCondition === true) {
|
|
2802
|
+
needCheckPreCreate = false;
|
|
2803
|
+
} else if (constCondition === false) {
|
|
2804
|
+
throw new RejectedByPolicyError(mutationModel);
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
if (needCheckPreCreate) {
|
|
2808
|
+
await this.enforcePreCreatePolicy(node, mutationModel, isManyToManyJoinTable, proceed);
|
|
2433
2809
|
}
|
|
2434
2810
|
}
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
await this.enforcePreCreatePolicy(node, proceed);
|
|
2440
|
-
}
|
|
2441
|
-
const transformedNode = this.transformNode(node);
|
|
2442
|
-
const result = await proceed(transformedNode);
|
|
2443
|
-
if (!this.onlyReturningId(node)) {
|
|
2811
|
+
const result = await proceed(this.transformNode(node));
|
|
2812
|
+
if (!node.returning || this.onlyReturningId(node)) {
|
|
2813
|
+
return result;
|
|
2814
|
+
} else {
|
|
2444
2815
|
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2445
2816
|
if (readBackResult.rows.length !== result.rows.length) {
|
|
2446
|
-
throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
|
|
2817
|
+
throw new RejectedByPolicyError(mutationModel, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
|
|
2447
2818
|
}
|
|
2448
2819
|
return readBackResult;
|
|
2449
|
-
}
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
// #region overrides
|
|
2823
|
+
transformSelectQuery(node) {
|
|
2824
|
+
let whereNode = this.transformNode(node.where);
|
|
2825
|
+
const policyFilter = this.createPolicyFilterForFrom(node.from);
|
|
2826
|
+
if (policyFilter) {
|
|
2827
|
+
whereNode = import_kysely8.WhereNode.create(whereNode?.where ? conjunction(this.dialect, [
|
|
2828
|
+
whereNode.where,
|
|
2829
|
+
policyFilter
|
|
2830
|
+
]) : policyFilter);
|
|
2831
|
+
}
|
|
2832
|
+
const baseResult = super.transformSelectQuery({
|
|
2833
|
+
...node,
|
|
2834
|
+
where: void 0
|
|
2835
|
+
});
|
|
2836
|
+
return {
|
|
2837
|
+
...baseResult,
|
|
2838
|
+
where: whereNode
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2841
|
+
transformJoin(node) {
|
|
2842
|
+
const table = this.extractTableName(node.table);
|
|
2843
|
+
if (!table) {
|
|
2844
|
+
return super.transformJoin(node);
|
|
2845
|
+
}
|
|
2846
|
+
const filter = this.buildPolicyFilter(table.model, table.alias, "read");
|
|
2847
|
+
const nestedSelect = {
|
|
2848
|
+
kind: "SelectQueryNode",
|
|
2849
|
+
from: import_kysely8.FromNode.create([
|
|
2850
|
+
node.table
|
|
2851
|
+
]),
|
|
2852
|
+
selections: [
|
|
2853
|
+
import_kysely8.SelectionNode.createSelectAll()
|
|
2854
|
+
],
|
|
2855
|
+
where: import_kysely8.WhereNode.create(filter)
|
|
2856
|
+
};
|
|
2857
|
+
return {
|
|
2858
|
+
...node,
|
|
2859
|
+
table: import_kysely8.AliasNode.create(import_kysely8.ParensNode.create(nestedSelect), import_kysely8.IdentifierNode.create(table.alias ?? table.model))
|
|
2860
|
+
};
|
|
2861
|
+
}
|
|
2862
|
+
transformInsertQuery(node) {
|
|
2863
|
+
let onConflict = node.onConflict;
|
|
2864
|
+
if (onConflict?.updates) {
|
|
2865
|
+
const { mutationModel, alias } = this.getMutationModel(node);
|
|
2866
|
+
const filter = this.buildPolicyFilter(mutationModel, alias, "update");
|
|
2867
|
+
if (onConflict.updateWhere) {
|
|
2868
|
+
onConflict = {
|
|
2869
|
+
...onConflict,
|
|
2870
|
+
updateWhere: import_kysely8.WhereNode.create(conjunction(this.dialect, [
|
|
2871
|
+
onConflict.updateWhere.where,
|
|
2872
|
+
filter
|
|
2873
|
+
]))
|
|
2874
|
+
};
|
|
2875
|
+
} else {
|
|
2876
|
+
onConflict = {
|
|
2877
|
+
...onConflict,
|
|
2878
|
+
updateWhere: import_kysely8.WhereNode.create(filter)
|
|
2879
|
+
};
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
const processedNode = onConflict ? {
|
|
2883
|
+
...node,
|
|
2884
|
+
onConflict
|
|
2885
|
+
} : node;
|
|
2886
|
+
const result = super.transformInsertQuery(processedNode);
|
|
2887
|
+
if (!node.returning) {
|
|
2888
|
+
return result;
|
|
2889
|
+
}
|
|
2890
|
+
if (this.onlyReturningId(node)) {
|
|
2450
2891
|
return result;
|
|
2892
|
+
} else {
|
|
2893
|
+
const { mutationModel } = this.getMutationModel(node);
|
|
2894
|
+
const idFields = requireIdFields(this.client.$schema, mutationModel);
|
|
2895
|
+
return {
|
|
2896
|
+
...result,
|
|
2897
|
+
returning: import_kysely8.ReturningNode.create(idFields.map((field) => import_kysely8.SelectionNode.create(import_kysely8.ColumnNode.create(field))))
|
|
2898
|
+
};
|
|
2451
2899
|
}
|
|
2452
2900
|
}
|
|
2901
|
+
transformUpdateQuery(node) {
|
|
2902
|
+
const result = super.transformUpdateQuery(node);
|
|
2903
|
+
const { mutationModel, alias } = this.getMutationModel(node);
|
|
2904
|
+
let filter = this.buildPolicyFilter(mutationModel, alias, "update");
|
|
2905
|
+
if (node.from) {
|
|
2906
|
+
const joinFilter = this.createPolicyFilterForFrom(node.from);
|
|
2907
|
+
if (joinFilter) {
|
|
2908
|
+
filter = conjunction(this.dialect, [
|
|
2909
|
+
filter,
|
|
2910
|
+
joinFilter
|
|
2911
|
+
]);
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
return {
|
|
2915
|
+
...result,
|
|
2916
|
+
where: import_kysely8.WhereNode.create(result.where ? conjunction(this.dialect, [
|
|
2917
|
+
result.where.where,
|
|
2918
|
+
filter
|
|
2919
|
+
]) : filter)
|
|
2920
|
+
};
|
|
2921
|
+
}
|
|
2922
|
+
transformDeleteQuery(node) {
|
|
2923
|
+
const result = super.transformDeleteQuery(node);
|
|
2924
|
+
const { mutationModel, alias } = this.getMutationModel(node);
|
|
2925
|
+
let filter = this.buildPolicyFilter(mutationModel, alias, "delete");
|
|
2926
|
+
if (node.using) {
|
|
2927
|
+
const joinFilter = this.createPolicyFilterForTables(node.using.tables);
|
|
2928
|
+
if (joinFilter) {
|
|
2929
|
+
filter = conjunction(this.dialect, [
|
|
2930
|
+
filter,
|
|
2931
|
+
joinFilter
|
|
2932
|
+
]);
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
return {
|
|
2936
|
+
...result,
|
|
2937
|
+
where: import_kysely8.WhereNode.create(result.where ? conjunction(this.dialect, [
|
|
2938
|
+
result.where.where,
|
|
2939
|
+
filter
|
|
2940
|
+
]) : filter)
|
|
2941
|
+
};
|
|
2942
|
+
}
|
|
2943
|
+
// #endregion
|
|
2944
|
+
// #region helpers
|
|
2453
2945
|
onlyReturningId(node) {
|
|
2454
2946
|
if (!node.returning) {
|
|
2455
2947
|
return true;
|
|
2456
2948
|
}
|
|
2457
|
-
const
|
|
2949
|
+
const { mutationModel } = this.getMutationModel(node);
|
|
2950
|
+
const idFields = requireIdFields(this.client.$schema, mutationModel);
|
|
2458
2951
|
const collector = new ColumnCollector();
|
|
2459
2952
|
const selectedColumns = collector.collect(node.returning);
|
|
2460
2953
|
return selectedColumns.every((c) => idFields.includes(c));
|
|
2461
2954
|
}
|
|
2462
|
-
async enforcePreCreatePolicy(node, proceed) {
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
const fields = node.columns.map((c) => c.column.name);
|
|
2468
|
-
const valueRows = this.unwrapCreateValueRows(node.values, model, fields);
|
|
2955
|
+
async enforcePreCreatePolicy(node, mutationModel, isManyToManyJoinTable, proceed) {
|
|
2956
|
+
const fields = node.columns?.map((c) => c.column.name) ?? [];
|
|
2957
|
+
const valueRows = node.values ? this.unwrapCreateValueRows(node.values, mutationModel, fields, isManyToManyJoinTable) : [
|
|
2958
|
+
[]
|
|
2959
|
+
];
|
|
2469
2960
|
for (const values of valueRows) {
|
|
2470
|
-
|
|
2961
|
+
if (isManyToManyJoinTable) {
|
|
2962
|
+
await this.enforcePreCreatePolicyForManyToManyJoinTable(mutationModel, fields, values.map((v) => v.node), proceed);
|
|
2963
|
+
} else {
|
|
2964
|
+
await this.enforcePreCreatePolicyForOne(mutationModel, fields, values.map((v) => v.node), proceed);
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
async enforcePreCreatePolicyForManyToManyJoinTable(tableName, fields, values, proceed) {
|
|
2969
|
+
const m2m = this.resolveManyToManyJoinTable(tableName);
|
|
2970
|
+
(0, import_common_helpers7.invariant)(m2m);
|
|
2971
|
+
(0, import_common_helpers7.invariant)(fields.includes("A") && fields.includes("B"), "many-to-many join table must have A and B fk fields");
|
|
2972
|
+
const aIndex = fields.indexOf("A");
|
|
2973
|
+
const aNode = values[aIndex];
|
|
2974
|
+
const bIndex = fields.indexOf("B");
|
|
2975
|
+
const bNode = values[bIndex];
|
|
2976
|
+
(0, import_common_helpers7.invariant)(import_kysely8.ValueNode.is(aNode) && import_kysely8.ValueNode.is(bNode), "A and B values must be ValueNode");
|
|
2977
|
+
const aValue = aNode.value;
|
|
2978
|
+
const bValue = bNode.value;
|
|
2979
|
+
(0, import_common_helpers7.invariant)(aValue !== null && aValue !== void 0, "A value cannot be null or undefined");
|
|
2980
|
+
(0, import_common_helpers7.invariant)(bValue !== null && bValue !== void 0, "B value cannot be null or undefined");
|
|
2981
|
+
const eb = (0, import_kysely8.expressionBuilder)();
|
|
2982
|
+
const filterA = this.buildPolicyFilter(m2m.firstModel, void 0, "update");
|
|
2983
|
+
const queryA = eb.selectFrom(m2m.firstModel).where(eb(eb.ref(`${m2m.firstModel}.${m2m.firstIdField}`), "=", aValue)).select(() => new import_kysely8.ExpressionWrapper(filterA).as("$t"));
|
|
2984
|
+
const filterB = this.buildPolicyFilter(m2m.secondModel, void 0, "update");
|
|
2985
|
+
const queryB = eb.selectFrom(m2m.secondModel).where(eb(eb.ref(`${m2m.secondModel}.${m2m.secondIdField}`), "=", bValue)).select(() => new import_kysely8.ExpressionWrapper(filterB).as("$t"));
|
|
2986
|
+
const queryNode = {
|
|
2987
|
+
kind: "SelectQueryNode",
|
|
2988
|
+
selections: [
|
|
2989
|
+
import_kysely8.SelectionNode.create(import_kysely8.AliasNode.create(queryA.toOperationNode(), import_kysely8.IdentifierNode.create("$conditionA"))),
|
|
2990
|
+
import_kysely8.SelectionNode.create(import_kysely8.AliasNode.create(queryB.toOperationNode(), import_kysely8.IdentifierNode.create("$conditionB")))
|
|
2991
|
+
]
|
|
2992
|
+
};
|
|
2993
|
+
const result = await proceed(queryNode);
|
|
2994
|
+
if (!result.rows[0]?.$conditionA) {
|
|
2995
|
+
throw new RejectedByPolicyError(m2m.firstModel, RejectedByPolicyReason.CANNOT_READ_BACK, `many-to-many relation participant model "${m2m.firstModel}" not updatable`);
|
|
2996
|
+
}
|
|
2997
|
+
if (!result.rows[0]?.$conditionB) {
|
|
2998
|
+
throw new RejectedByPolicyError(m2m.secondModel, RejectedByPolicyReason.NO_ACCESS, `many-to-many relation participant model "${m2m.secondModel}" not updatable`);
|
|
2471
2999
|
}
|
|
2472
3000
|
}
|
|
2473
|
-
async enforcePreCreatePolicyForOne(model, fields, values,
|
|
2474
|
-
const
|
|
2475
|
-
const
|
|
2476
|
-
for (
|
|
2477
|
-
|
|
2478
|
-
|
|
3001
|
+
async enforcePreCreatePolicyForOne(model, fields, values, proceed) {
|
|
3002
|
+
const allFields = Object.entries(requireModel(this.client.$schema, model).fields).filter(([, def]) => !def.relation);
|
|
3003
|
+
const allValues = [];
|
|
3004
|
+
for (const [name, _def] of allFields) {
|
|
3005
|
+
const index = fields.indexOf(name);
|
|
3006
|
+
if (index >= 0) {
|
|
3007
|
+
allValues.push(values[index]);
|
|
3008
|
+
} else {
|
|
3009
|
+
allValues.push(import_kysely8.ValueNode.createImmediate(null));
|
|
3010
|
+
}
|
|
2479
3011
|
}
|
|
2480
|
-
const
|
|
3012
|
+
const eb = (0, import_kysely8.expressionBuilder)();
|
|
3013
|
+
const constTable = {
|
|
3014
|
+
kind: "SelectQueryNode",
|
|
3015
|
+
from: import_kysely8.FromNode.create([
|
|
3016
|
+
import_kysely8.AliasNode.create(import_kysely8.ParensNode.create(import_kysely8.ValuesNode.create([
|
|
3017
|
+
import_kysely8.ValueListNode.create(allValues)
|
|
3018
|
+
])), import_kysely8.IdentifierNode.create("$t"))
|
|
3019
|
+
]),
|
|
3020
|
+
selections: allFields.map(([name, def], index) => {
|
|
3021
|
+
const castedColumnRef = import_kysely8.sql`CAST(${eb.ref(`column${index + 1}`)} as ${import_kysely8.sql.raw(this.dialect.getFieldSqlType(def))})`.as(name);
|
|
3022
|
+
return import_kysely8.SelectionNode.create(castedColumnRef.toOperationNode());
|
|
3023
|
+
})
|
|
3024
|
+
};
|
|
3025
|
+
const filter = this.buildPolicyFilter(model, void 0, "create");
|
|
2481
3026
|
const preCreateCheck = {
|
|
2482
3027
|
kind: "SelectQueryNode",
|
|
3028
|
+
from: import_kysely8.FromNode.create([
|
|
3029
|
+
import_kysely8.AliasNode.create(constTable, import_kysely8.IdentifierNode.create(model))
|
|
3030
|
+
]),
|
|
2483
3031
|
selections: [
|
|
2484
|
-
|
|
2485
|
-
|
|
3032
|
+
import_kysely8.SelectionNode.create(import_kysely8.AliasNode.create(import_kysely8.BinaryOperationNode.create(import_kysely8.FunctionNode.create("COUNT", [
|
|
3033
|
+
import_kysely8.ValueNode.createImmediate(1)
|
|
3034
|
+
]), import_kysely8.OperatorNode.create(">"), import_kysely8.ValueNode.createImmediate(0)), import_kysely8.IdentifierNode.create("$condition")))
|
|
3035
|
+
],
|
|
3036
|
+
where: import_kysely8.WhereNode.create(filter)
|
|
2486
3037
|
};
|
|
2487
3038
|
const result = await proceed(preCreateCheck);
|
|
2488
3039
|
if (!result.rows[0]?.$condition) {
|
|
2489
3040
|
throw new RejectedByPolicyError(model);
|
|
2490
3041
|
}
|
|
2491
3042
|
}
|
|
2492
|
-
unwrapCreateValueRows(node, model, fields) {
|
|
2493
|
-
if (
|
|
2494
|
-
return node.values.map((v) => this.unwrapCreateValueRow(v.values, model, fields));
|
|
2495
|
-
} else if (
|
|
3043
|
+
unwrapCreateValueRows(node, model, fields, isManyToManyJoinTable) {
|
|
3044
|
+
if (import_kysely8.ValuesNode.is(node)) {
|
|
3045
|
+
return node.values.map((v) => this.unwrapCreateValueRow(v.values, model, fields, isManyToManyJoinTable));
|
|
3046
|
+
} else if (import_kysely8.PrimitiveValueListNode.is(node)) {
|
|
2496
3047
|
return [
|
|
2497
|
-
this.unwrapCreateValueRow(node.values, model, fields)
|
|
3048
|
+
this.unwrapCreateValueRow(node.values, model, fields, isManyToManyJoinTable)
|
|
2498
3049
|
];
|
|
2499
3050
|
} else {
|
|
2500
3051
|
throw new InternalError(`Unexpected node kind: ${node.kind} for unwrapping create values`);
|
|
2501
3052
|
}
|
|
2502
3053
|
}
|
|
2503
|
-
unwrapCreateValueRow(data, model, fields) {
|
|
2504
|
-
(0,
|
|
3054
|
+
unwrapCreateValueRow(data, model, fields, isImplicitManyToManyJoinTable) {
|
|
3055
|
+
(0, import_common_helpers7.invariant)(data.length === fields.length, "data length must match fields length");
|
|
2505
3056
|
const result = [];
|
|
2506
3057
|
for (let i = 0; i < data.length; i++) {
|
|
2507
3058
|
const item = data[i];
|
|
2508
|
-
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
2509
3059
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2510
|
-
|
|
3060
|
+
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
3061
|
+
(0, import_common_helpers7.invariant)(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2511
3062
|
result.push({
|
|
2512
|
-
node:
|
|
3063
|
+
node: import_kysely8.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2513
3064
|
raw: item.value
|
|
2514
3065
|
});
|
|
2515
3066
|
} else {
|
|
2516
|
-
|
|
3067
|
+
let value = item;
|
|
3068
|
+
if (!isImplicitManyToManyJoinTable) {
|
|
3069
|
+
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
3070
|
+
value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
|
|
3071
|
+
}
|
|
2517
3072
|
if (Array.isArray(value)) {
|
|
2518
3073
|
result.push({
|
|
2519
|
-
node:
|
|
3074
|
+
node: import_kysely8.RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
2520
3075
|
raw: value
|
|
2521
3076
|
});
|
|
2522
3077
|
} else {
|
|
2523
3078
|
result.push({
|
|
2524
|
-
node:
|
|
3079
|
+
node: import_kysely8.ValueNode.create(value),
|
|
2525
3080
|
raw: value
|
|
2526
3081
|
});
|
|
2527
3082
|
}
|
|
@@ -2557,18 +3112,15 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2557
3112
|
if (!this.isMutationQueryNode(node) || !node.returning) {
|
|
2558
3113
|
return result;
|
|
2559
3114
|
}
|
|
2560
|
-
const
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
}
|
|
2564
|
-
const idConditions = this.buildIdConditions(table, result.rows);
|
|
2565
|
-
const policyFilter = this.buildPolicyFilter(table, void 0, "read");
|
|
3115
|
+
const { mutationModel } = this.getMutationModel(node);
|
|
3116
|
+
const idConditions = this.buildIdConditions(mutationModel, result.rows);
|
|
3117
|
+
const policyFilter = this.buildPolicyFilter(mutationModel, void 0, "read");
|
|
2566
3118
|
const select = {
|
|
2567
3119
|
kind: "SelectQueryNode",
|
|
2568
|
-
from:
|
|
2569
|
-
|
|
3120
|
+
from: import_kysely8.FromNode.create([
|
|
3121
|
+
import_kysely8.TableNode.create(mutationModel)
|
|
2570
3122
|
]),
|
|
2571
|
-
where:
|
|
3123
|
+
where: import_kysely8.WhereNode.create(conjunction(this.dialect, [
|
|
2572
3124
|
idConditions,
|
|
2573
3125
|
policyFilter
|
|
2574
3126
|
])),
|
|
@@ -2578,15 +3130,31 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2578
3130
|
return selectResult;
|
|
2579
3131
|
}
|
|
2580
3132
|
buildIdConditions(table, rows) {
|
|
2581
|
-
const idFields =
|
|
2582
|
-
return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) =>
|
|
3133
|
+
const idFields = requireIdFields(this.client.$schema, table);
|
|
3134
|
+
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]))))));
|
|
2583
3135
|
}
|
|
2584
3136
|
getMutationModel(node) {
|
|
2585
|
-
const r = (0, import_ts_pattern8.match)(node).when(
|
|
3137
|
+
const r = (0, import_ts_pattern8.match)(node).when(import_kysely8.InsertQueryNode.is, (node2) => ({
|
|
3138
|
+
mutationModel: getTableName(node2.into),
|
|
3139
|
+
alias: void 0
|
|
3140
|
+
})).when(import_kysely8.UpdateQueryNode.is, (node2) => {
|
|
3141
|
+
if (!node2.table) {
|
|
3142
|
+
throw new QueryError("Update query must have a table");
|
|
3143
|
+
}
|
|
3144
|
+
const r2 = this.extractTableName(node2.table);
|
|
3145
|
+
return r2 ? {
|
|
3146
|
+
mutationModel: r2.model,
|
|
3147
|
+
alias: r2.alias
|
|
3148
|
+
} : void 0;
|
|
3149
|
+
}).when(import_kysely8.DeleteQueryNode.is, (node2) => {
|
|
2586
3150
|
if (node2.from.froms.length !== 1) {
|
|
2587
|
-
throw new
|
|
3151
|
+
throw new QueryError("Only one from table is supported for delete");
|
|
2588
3152
|
}
|
|
2589
|
-
|
|
3153
|
+
const r2 = this.extractTableName(node2.from.froms[0]);
|
|
3154
|
+
return r2 ? {
|
|
3155
|
+
mutationModel: r2.model,
|
|
3156
|
+
alias: r2.alias
|
|
3157
|
+
} : void 0;
|
|
2590
3158
|
}).exhaustive();
|
|
2591
3159
|
if (!r) {
|
|
2592
3160
|
throw new InternalError(`Unable to get table name for query node: ${node}`);
|
|
@@ -2594,18 +3162,22 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2594
3162
|
return r;
|
|
2595
3163
|
}
|
|
2596
3164
|
isCrudQueryNode(node) {
|
|
2597
|
-
return
|
|
3165
|
+
return import_kysely8.SelectQueryNode.is(node) || import_kysely8.InsertQueryNode.is(node) || import_kysely8.UpdateQueryNode.is(node) || import_kysely8.DeleteQueryNode.is(node);
|
|
2598
3166
|
}
|
|
2599
3167
|
isMutationQueryNode(node) {
|
|
2600
|
-
return
|
|
3168
|
+
return import_kysely8.InsertQueryNode.is(node) || import_kysely8.UpdateQueryNode.is(node) || import_kysely8.DeleteQueryNode.is(node);
|
|
2601
3169
|
}
|
|
2602
|
-
buildPolicyFilter(model, alias, operation
|
|
3170
|
+
buildPolicyFilter(model, alias, operation) {
|
|
3171
|
+
const m2mFilter = this.getModelPolicyFilterForManyToManyJoinTable(model, alias, operation);
|
|
3172
|
+
if (m2mFilter) {
|
|
3173
|
+
return m2mFilter;
|
|
3174
|
+
}
|
|
2603
3175
|
const policies = this.getModelPolicies(model, operation);
|
|
2604
3176
|
if (policies.length === 0) {
|
|
2605
3177
|
return falseNode(this.dialect);
|
|
2606
3178
|
}
|
|
2607
|
-
const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.
|
|
2608
|
-
const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.
|
|
3179
|
+
const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.compilePolicyCondition(model, alias, operation, policy));
|
|
3180
|
+
const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.compilePolicyCondition(model, alias, operation, policy));
|
|
2609
3181
|
let combinedPolicy;
|
|
2610
3182
|
if (allows.length === 0) {
|
|
2611
3183
|
combinedPolicy = falseNode(this.dialect);
|
|
@@ -2614,109 +3186,66 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2614
3186
|
if (denies.length !== 0) {
|
|
2615
3187
|
const combinedDenies = conjunction(this.dialect, denies.map((d) => buildIsFalse(d, this.dialect)));
|
|
2616
3188
|
combinedPolicy = conjunction(this.dialect, [
|
|
2617
|
-
combinedPolicy,
|
|
2618
|
-
combinedDenies
|
|
2619
|
-
]);
|
|
2620
|
-
}
|
|
2621
|
-
}
|
|
2622
|
-
return combinedPolicy;
|
|
2623
|
-
}
|
|
2624
|
-
transformSelectQuery(node) {
|
|
2625
|
-
let whereNode = node.where;
|
|
2626
|
-
node.from?.froms.forEach((from) => {
|
|
2627
|
-
const extractResult = this.extractTableName(from);
|
|
2628
|
-
if (extractResult) {
|
|
2629
|
-
const { model, alias } = extractResult;
|
|
2630
|
-
const filter = this.buildPolicyFilter(model, alias, "read");
|
|
2631
|
-
whereNode = import_kysely7.WhereNode.create(whereNode?.where ? conjunction(this.dialect, [
|
|
2632
|
-
whereNode.where,
|
|
2633
|
-
filter
|
|
2634
|
-
]) : filter);
|
|
2635
|
-
}
|
|
2636
|
-
});
|
|
2637
|
-
const baseResult = super.transformSelectQuery({
|
|
2638
|
-
...node,
|
|
2639
|
-
where: void 0
|
|
2640
|
-
});
|
|
2641
|
-
return {
|
|
2642
|
-
...baseResult,
|
|
2643
|
-
where: whereNode
|
|
2644
|
-
};
|
|
2645
|
-
}
|
|
2646
|
-
transformInsertQuery(node) {
|
|
2647
|
-
const result = super.transformInsertQuery(node);
|
|
2648
|
-
if (!node.returning) {
|
|
2649
|
-
return result;
|
|
2650
|
-
}
|
|
2651
|
-
if (this.onlyReturningId(node)) {
|
|
2652
|
-
return result;
|
|
2653
|
-
} else {
|
|
2654
|
-
const idFields = getIdFields(this.client.$schema, this.getMutationModel(node));
|
|
2655
|
-
return {
|
|
2656
|
-
...result,
|
|
2657
|
-
returning: import_kysely7.ReturningNode.create(idFields.map((field) => import_kysely7.SelectionNode.create(import_kysely7.ColumnNode.create(field))))
|
|
2658
|
-
};
|
|
2659
|
-
}
|
|
2660
|
-
}
|
|
2661
|
-
transformUpdateQuery(node) {
|
|
2662
|
-
const result = super.transformUpdateQuery(node);
|
|
2663
|
-
const mutationModel = this.getMutationModel(node);
|
|
2664
|
-
const filter = this.buildPolicyFilter(mutationModel, void 0, "update");
|
|
2665
|
-
return {
|
|
2666
|
-
...result,
|
|
2667
|
-
where: import_kysely7.WhereNode.create(result.where ? conjunction(this.dialect, [
|
|
2668
|
-
result.where.where,
|
|
2669
|
-
filter
|
|
2670
|
-
]) : filter)
|
|
2671
|
-
};
|
|
2672
|
-
}
|
|
2673
|
-
transformDeleteQuery(node) {
|
|
2674
|
-
const result = super.transformDeleteQuery(node);
|
|
2675
|
-
const mutationModel = this.getMutationModel(node);
|
|
2676
|
-
const filter = this.buildPolicyFilter(mutationModel, void 0, "delete");
|
|
2677
|
-
return {
|
|
2678
|
-
...result,
|
|
2679
|
-
where: import_kysely7.WhereNode.create(result.where ? conjunction(this.dialect, [
|
|
2680
|
-
result.where.where,
|
|
2681
|
-
filter
|
|
2682
|
-
]) : filter)
|
|
2683
|
-
};
|
|
3189
|
+
combinedPolicy,
|
|
3190
|
+
combinedDenies
|
|
3191
|
+
]);
|
|
3192
|
+
}
|
|
3193
|
+
}
|
|
3194
|
+
return combinedPolicy;
|
|
2684
3195
|
}
|
|
2685
|
-
extractTableName(
|
|
2686
|
-
if (
|
|
3196
|
+
extractTableName(node) {
|
|
3197
|
+
if (import_kysely8.TableNode.is(node)) {
|
|
2687
3198
|
return {
|
|
2688
|
-
model:
|
|
3199
|
+
model: node.table.identifier.name
|
|
2689
3200
|
};
|
|
2690
3201
|
}
|
|
2691
|
-
if (
|
|
2692
|
-
const inner = this.extractTableName(
|
|
3202
|
+
if (import_kysely8.AliasNode.is(node)) {
|
|
3203
|
+
const inner = this.extractTableName(node.node);
|
|
2693
3204
|
if (!inner) {
|
|
2694
3205
|
return void 0;
|
|
2695
3206
|
}
|
|
2696
3207
|
return {
|
|
2697
3208
|
model: inner.model,
|
|
2698
|
-
alias:
|
|
3209
|
+
alias: import_kysely8.IdentifierNode.is(node.alias) ? node.alias.name : void 0
|
|
2699
3210
|
};
|
|
2700
3211
|
} else {
|
|
2701
3212
|
return void 0;
|
|
2702
3213
|
}
|
|
2703
3214
|
}
|
|
2704
|
-
|
|
2705
|
-
|
|
3215
|
+
createPolicyFilterForFrom(node) {
|
|
3216
|
+
if (!node) {
|
|
3217
|
+
return void 0;
|
|
3218
|
+
}
|
|
3219
|
+
return this.createPolicyFilterForTables(node.froms);
|
|
3220
|
+
}
|
|
3221
|
+
createPolicyFilterForTables(tables) {
|
|
3222
|
+
return tables.reduce((acc, table) => {
|
|
3223
|
+
const extractResult = this.extractTableName(table);
|
|
3224
|
+
if (extractResult) {
|
|
3225
|
+
const { model, alias } = extractResult;
|
|
3226
|
+
const filter = this.buildPolicyFilter(model, alias, "read");
|
|
3227
|
+
return acc ? conjunction(this.dialect, [
|
|
3228
|
+
acc,
|
|
3229
|
+
filter
|
|
3230
|
+
]) : filter;
|
|
3231
|
+
}
|
|
3232
|
+
return acc;
|
|
3233
|
+
}, void 0);
|
|
3234
|
+
}
|
|
3235
|
+
compilePolicyCondition(model, alias, operation, policy) {
|
|
3236
|
+
return new ExpressionTransformer(this.client).transform(policy.condition, {
|
|
2706
3237
|
model,
|
|
2707
3238
|
alias,
|
|
2708
3239
|
operation,
|
|
2709
|
-
thisEntity,
|
|
2710
|
-
thisEntityRaw,
|
|
2711
3240
|
auth: this.client.$auth
|
|
2712
3241
|
});
|
|
2713
3242
|
}
|
|
2714
|
-
getModelPolicies(
|
|
2715
|
-
const modelDef = requireModel(this.client.$schema,
|
|
3243
|
+
getModelPolicies(model, operation) {
|
|
3244
|
+
const modelDef = requireModel(this.client.$schema, model);
|
|
2716
3245
|
const result = [];
|
|
2717
3246
|
const extractOperations = /* @__PURE__ */ __name((expr2) => {
|
|
2718
|
-
(0,
|
|
2719
|
-
(0,
|
|
3247
|
+
(0, import_common_helpers7.invariant)(ExpressionUtils.isLiteral(expr2), "expecting a literal");
|
|
3248
|
+
(0, import_common_helpers7.invariant)(typeof expr2.value === "string", "expecting a string literal");
|
|
2720
3249
|
return expr2.value.split(",").filter((v) => !!v).map((v) => v.trim());
|
|
2721
3250
|
}, "extractOperations");
|
|
2722
3251
|
if (modelDef.attributes) {
|
|
@@ -2728,8 +3257,84 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2728
3257
|
}
|
|
2729
3258
|
return result;
|
|
2730
3259
|
}
|
|
3260
|
+
resolveManyToManyJoinTable(tableName) {
|
|
3261
|
+
for (const model of Object.values(this.client.$schema.models)) {
|
|
3262
|
+
for (const field of Object.values(model.fields)) {
|
|
3263
|
+
const m2m = getManyToManyRelation(this.client.$schema, model.name, field.name);
|
|
3264
|
+
if (m2m?.joinTable === tableName) {
|
|
3265
|
+
const sortedRecord = [
|
|
3266
|
+
{
|
|
3267
|
+
model: model.name,
|
|
3268
|
+
field: field.name
|
|
3269
|
+
},
|
|
3270
|
+
{
|
|
3271
|
+
model: m2m.otherModel,
|
|
3272
|
+
field: m2m.otherField
|
|
3273
|
+
}
|
|
3274
|
+
].sort(this.manyToManySorter);
|
|
3275
|
+
const firstIdFields = requireIdFields(this.client.$schema, sortedRecord[0].model);
|
|
3276
|
+
const secondIdFields = requireIdFields(this.client.$schema, sortedRecord[1].model);
|
|
3277
|
+
(0, import_common_helpers7.invariant)(firstIdFields.length === 1 && secondIdFields.length === 1, "only single-field id is supported for implicit many-to-many join table");
|
|
3278
|
+
return {
|
|
3279
|
+
firstModel: sortedRecord[0].model,
|
|
3280
|
+
firstField: sortedRecord[0].field,
|
|
3281
|
+
firstIdField: firstIdFields[0],
|
|
3282
|
+
secondModel: sortedRecord[1].model,
|
|
3283
|
+
secondField: sortedRecord[1].field,
|
|
3284
|
+
secondIdField: secondIdFields[0]
|
|
3285
|
+
};
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
return void 0;
|
|
3290
|
+
}
|
|
3291
|
+
manyToManySorter(a, b) {
|
|
3292
|
+
return a.model !== b.model ? a.model.localeCompare(b.model) : a.field.localeCompare(b.field);
|
|
3293
|
+
}
|
|
3294
|
+
isManyToManyJoinTable(tableName) {
|
|
3295
|
+
return !!this.resolveManyToManyJoinTable(tableName);
|
|
3296
|
+
}
|
|
3297
|
+
getModelPolicyFilterForManyToManyJoinTable(tableName, alias, operation) {
|
|
3298
|
+
const m2m = this.resolveManyToManyJoinTable(tableName);
|
|
3299
|
+
if (!m2m) {
|
|
3300
|
+
return void 0;
|
|
3301
|
+
}
|
|
3302
|
+
const checkForOperation = operation === "read" ? "read" : "update";
|
|
3303
|
+
const eb = (0, import_kysely8.expressionBuilder)();
|
|
3304
|
+
const joinTable = alias ?? tableName;
|
|
3305
|
+
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"));
|
|
3306
|
+
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"));
|
|
3307
|
+
return eb.and([
|
|
3308
|
+
aQuery,
|
|
3309
|
+
bQuery
|
|
3310
|
+
]).toOperationNode();
|
|
3311
|
+
}
|
|
2731
3312
|
};
|
|
2732
3313
|
|
|
3314
|
+
// src/plugins/policy/functions.ts
|
|
3315
|
+
var check = /* @__PURE__ */ __name((eb, args, { client, model, modelAlias, operation }) => {
|
|
3316
|
+
(0, import_common_helpers8.invariant)(args.length === 1 || args.length === 2, '"check" function requires 1 or 2 arguments');
|
|
3317
|
+
const arg1Node = args[0].toOperationNode();
|
|
3318
|
+
const arg2Node = args.length === 2 ? args[1].toOperationNode() : void 0;
|
|
3319
|
+
if (arg2Node) {
|
|
3320
|
+
(0, import_common_helpers8.invariant)(import_kysely9.ValueNode.is(arg2Node) && typeof arg2Node.value === "string", '"operation" parameter must be a string literal when provided');
|
|
3321
|
+
(0, import_common_helpers8.invariant)(CRUD.includes(arg2Node.value), '"operation" parameter must be one of "create", "read", "update", "delete"');
|
|
3322
|
+
}
|
|
3323
|
+
const fieldName = extractFieldName(arg1Node);
|
|
3324
|
+
(0, import_common_helpers8.invariant)(fieldName, 'Failed to extract field name from the first argument of "check" function');
|
|
3325
|
+
const fieldDef = requireField(client.$schema, model, fieldName);
|
|
3326
|
+
(0, import_common_helpers8.invariant)(fieldDef.relation, `Field "${fieldName}" is not a relation field in model "${model}"`);
|
|
3327
|
+
(0, import_common_helpers8.invariant)(!fieldDef.array, `Field "${fieldName}" is a to-many relation, which is not supported by "check"`);
|
|
3328
|
+
const relationModel = fieldDef.type;
|
|
3329
|
+
const op = arg2Node ? arg2Node.value : operation;
|
|
3330
|
+
const policyHandler = new PolicyHandler(client);
|
|
3331
|
+
const joinPairs = buildJoinPairs(client.$schema, model, modelAlias, fieldName, relationModel);
|
|
3332
|
+
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))));
|
|
3333
|
+
const policyCondition = policyHandler.buildPolicyFilter(relationModel, void 0, op);
|
|
3334
|
+
const result = eb.selectFrom(relationModel).where(joinCondition).select(new import_kysely9.ExpressionWrapper(policyCondition).as("$condition"));
|
|
3335
|
+
return result;
|
|
3336
|
+
}, "check");
|
|
3337
|
+
|
|
2733
3338
|
// src/plugins/policy/plugin.ts
|
|
2734
3339
|
var PolicyPlugin = class {
|
|
2735
3340
|
static {
|
|
@@ -2744,6 +3349,11 @@ var PolicyPlugin = class {
|
|
|
2744
3349
|
get description() {
|
|
2745
3350
|
return "Enforces access policies defined in the schema.";
|
|
2746
3351
|
}
|
|
3352
|
+
get functions() {
|
|
3353
|
+
return {
|
|
3354
|
+
check
|
|
3355
|
+
};
|
|
3356
|
+
}
|
|
2747
3357
|
onKyselyQuery({
|
|
2748
3358
|
query,
|
|
2749
3359
|
client,
|
|
@@ -2760,13 +3370,13 @@ var PolicyPlugin = class {
|
|
|
2760
3370
|
};
|
|
2761
3371
|
|
|
2762
3372
|
// src/utils/clone.ts
|
|
2763
|
-
var
|
|
3373
|
+
var import_common_helpers9 = require("@zenstackhq/common-helpers");
|
|
2764
3374
|
function clone(value) {
|
|
2765
3375
|
if (Array.isArray(value)) {
|
|
2766
3376
|
return value.map((v) => clone(v));
|
|
2767
3377
|
}
|
|
2768
3378
|
if (typeof value === "object") {
|
|
2769
|
-
if (!value || !(0,
|
|
3379
|
+
if (!value || !(0, import_common_helpers9.isPlainObject)(value)) {
|
|
2770
3380
|
return value;
|
|
2771
3381
|
}
|
|
2772
3382
|
const result = {};
|
|
@@ -2779,16 +3389,6 @@ function clone(value) {
|
|
|
2779
3389
|
}
|
|
2780
3390
|
__name(clone, "clone");
|
|
2781
3391
|
|
|
2782
|
-
// src/client/contract.ts
|
|
2783
|
-
var TransactionIsolationLevel = /* @__PURE__ */ function(TransactionIsolationLevel2) {
|
|
2784
|
-
TransactionIsolationLevel2["ReadUncommitted"] = "read uncommitted";
|
|
2785
|
-
TransactionIsolationLevel2["ReadCommitted"] = "read committed";
|
|
2786
|
-
TransactionIsolationLevel2["RepeatableRead"] = "repeatable read";
|
|
2787
|
-
TransactionIsolationLevel2["Serializable"] = "serializable";
|
|
2788
|
-
TransactionIsolationLevel2["Snapshot"] = "snapshot";
|
|
2789
|
-
return TransactionIsolationLevel2;
|
|
2790
|
-
}({});
|
|
2791
|
-
|
|
2792
3392
|
// src/client/crud/operations/base.ts
|
|
2793
3393
|
var BaseOperationHandler = class {
|
|
2794
3394
|
static {
|
|
@@ -2833,7 +3433,7 @@ var BaseOperationHandler = class {
|
|
|
2833
3433
|
return getField(this.schema, model, field);
|
|
2834
3434
|
}
|
|
2835
3435
|
async exists(kysely, model, filter) {
|
|
2836
|
-
const idFields =
|
|
3436
|
+
const idFields = requireIdFields(this.schema, model);
|
|
2837
3437
|
const _filter = flattenCompoundUniqueFilters(this.schema, model, filter);
|
|
2838
3438
|
const query = kysely.selectFrom(model).where((eb) => eb.and(_filter)).select(idFields.map((f) => kysely.dynamic.ref(f))).limit(1).modifyEnd(this.makeContextComment({
|
|
2839
3439
|
model,
|
|
@@ -2842,7 +3442,7 @@ var BaseOperationHandler = class {
|
|
|
2842
3442
|
return this.executeQueryTakeFirst(kysely, query, "exists");
|
|
2843
3443
|
}
|
|
2844
3444
|
async read(kysely, model, args) {
|
|
2845
|
-
let query = this.dialect.buildSelectModel((0,
|
|
3445
|
+
let query = this.dialect.buildSelectModel((0, import_kysely10.expressionBuilder)(), model, model);
|
|
2846
3446
|
if (args) {
|
|
2847
3447
|
query = this.dialect.buildFilterSortTake(model, args, query, model);
|
|
2848
3448
|
}
|
|
@@ -2914,26 +3514,21 @@ var BaseOperationHandler = class {
|
|
|
2914
3514
|
throw new QueryError(`Model "${this.model}" is a delegate and cannot be created directly.`);
|
|
2915
3515
|
}
|
|
2916
3516
|
let createFields = {};
|
|
2917
|
-
let
|
|
3517
|
+
let updateParent = void 0;
|
|
2918
3518
|
let m2m = void 0;
|
|
2919
3519
|
if (fromRelation) {
|
|
2920
3520
|
m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
|
|
2921
3521
|
if (!m2m) {
|
|
2922
3522
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation?.model ?? "", fromRelation?.field ?? "");
|
|
2923
3523
|
if (!ownedByModel) {
|
|
2924
|
-
const parentFkFields = this.buildFkAssignments(fromRelation.model, fromRelation.field, fromRelation.ids);
|
|
3524
|
+
const parentFkFields = await this.buildFkAssignments(kysely, fromRelation.model, fromRelation.field, fromRelation.ids);
|
|
2925
3525
|
Object.assign(createFields, parentFkFields);
|
|
2926
3526
|
} else {
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
model: fromRelation.model,
|
|
2933
|
-
operation: "update"
|
|
2934
|
-
}));
|
|
2935
|
-
return this.executeQuery(kysely, query2, "update");
|
|
2936
|
-
}, "parentUpdateTask");
|
|
3527
|
+
updateParent = /* @__PURE__ */ __name((entity) => {
|
|
3528
|
+
for (const { fk, pk } of keyPairs) {
|
|
3529
|
+
fromRelation.parentUpdates[fk] = entity[pk];
|
|
3530
|
+
}
|
|
3531
|
+
}, "updateParent");
|
|
2937
3532
|
}
|
|
2938
3533
|
}
|
|
2939
3534
|
}
|
|
@@ -2965,24 +3560,23 @@ var BaseOperationHandler = class {
|
|
|
2965
3560
|
const baseCreateResult = await this.processBaseModelCreate(kysely, modelDef.baseModel, createFields, model);
|
|
2966
3561
|
createFields = baseCreateResult.remainingFields;
|
|
2967
3562
|
}
|
|
2968
|
-
const updatedData = this.
|
|
2969
|
-
const idFields =
|
|
3563
|
+
const updatedData = this.fillGeneratedAndDefaultValues(modelDef, createFields);
|
|
3564
|
+
const idFields = requireIdFields(this.schema, model);
|
|
2970
3565
|
const query = kysely.insertInto(model).$if(Object.keys(updatedData).length === 0, (qb) => qb.defaultValues()).$if(Object.keys(updatedData).length > 0, (qb) => qb.values(updatedData)).returning(idFields).modifyEnd(this.makeContextComment({
|
|
2971
3566
|
model,
|
|
2972
3567
|
operation: "create"
|
|
2973
3568
|
}));
|
|
2974
3569
|
const createdEntity = await this.executeQueryTakeFirst(kysely, query, "create");
|
|
2975
3570
|
if (Object.keys(postCreateRelations).length > 0) {
|
|
2976
|
-
const
|
|
2977
|
-
|
|
2978
|
-
}
|
|
2979
|
-
await Promise.all(relationPromises);
|
|
3571
|
+
for (const [field, subPayload] of Object.entries(postCreateRelations)) {
|
|
3572
|
+
await this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
|
|
3573
|
+
}
|
|
2980
3574
|
}
|
|
2981
3575
|
if (fromRelation && m2m) {
|
|
2982
3576
|
await this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, createdEntity, m2m.joinTable);
|
|
2983
3577
|
}
|
|
2984
|
-
if (
|
|
2985
|
-
|
|
3578
|
+
if (updateParent) {
|
|
3579
|
+
updateParent(createdEntity);
|
|
2986
3580
|
}
|
|
2987
3581
|
return createdEntity;
|
|
2988
3582
|
}
|
|
@@ -2998,7 +3592,7 @@ var BaseOperationHandler = class {
|
|
|
2998
3592
|
}
|
|
2999
3593
|
});
|
|
3000
3594
|
const discriminatorField = getDiscriminatorField(this.schema, model);
|
|
3001
|
-
(0,
|
|
3595
|
+
(0, import_common_helpers10.invariant)(discriminatorField, `Base model "${model}" must have a discriminator field`);
|
|
3002
3596
|
thisCreateFields[discriminatorField] = forModel;
|
|
3003
3597
|
const baseEntity = await this.create(kysely, model, thisCreateFields, void 0, true);
|
|
3004
3598
|
const idValues = extractIdFields(baseEntity, this.schema, model);
|
|
@@ -3008,14 +3602,24 @@ var BaseOperationHandler = class {
|
|
|
3008
3602
|
remainingFields
|
|
3009
3603
|
};
|
|
3010
3604
|
}
|
|
3011
|
-
buildFkAssignments(model, relationField, entity) {
|
|
3605
|
+
async buildFkAssignments(kysely, model, relationField, entity) {
|
|
3012
3606
|
const parentFkFields = {};
|
|
3013
|
-
(0,
|
|
3014
|
-
(0,
|
|
3607
|
+
(0, import_common_helpers10.invariant)(relationField, "parentField must be defined if parentModel is defined");
|
|
3608
|
+
(0, import_common_helpers10.invariant)(entity, "parentEntity must be defined if parentModel is defined");
|
|
3015
3609
|
const { keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
3016
3610
|
for (const pair of keyPairs) {
|
|
3017
3611
|
if (!(pair.pk in entity)) {
|
|
3018
|
-
|
|
3612
|
+
const extraRead = await this.readUnique(kysely, model, {
|
|
3613
|
+
where: entity,
|
|
3614
|
+
select: {
|
|
3615
|
+
[pair.pk]: true
|
|
3616
|
+
}
|
|
3617
|
+
});
|
|
3618
|
+
if (!extraRead) {
|
|
3619
|
+
throw new QueryError(`Field "${pair.pk}" not found in parent created data`);
|
|
3620
|
+
} else {
|
|
3621
|
+
Object.assign(entity, extraRead);
|
|
3622
|
+
}
|
|
3019
3623
|
}
|
|
3020
3624
|
Object.assign(parentFkFields, {
|
|
3021
3625
|
[pair.fk]: entity[pair.pk]
|
|
@@ -3036,15 +3640,15 @@ var BaseOperationHandler = class {
|
|
|
3036
3640
|
entity: rightEntity
|
|
3037
3641
|
}
|
|
3038
3642
|
].sort((a, b) => (
|
|
3039
|
-
// the
|
|
3643
|
+
// the implicit m2m join table's "A", "B" fk fields' order is determined
|
|
3040
3644
|
// by model name's sort order, and when identical (for self-relations),
|
|
3041
3645
|
// field name's sort order
|
|
3042
3646
|
a.model !== b.model ? a.model.localeCompare(b.model) : a.field.localeCompare(b.field)
|
|
3043
3647
|
));
|
|
3044
|
-
const firstIds =
|
|
3045
|
-
const secondIds =
|
|
3046
|
-
(0,
|
|
3047
|
-
(0,
|
|
3648
|
+
const firstIds = requireIdFields(this.schema, sortedRecords[0].model);
|
|
3649
|
+
const secondIds = requireIdFields(this.schema, sortedRecords[1].model);
|
|
3650
|
+
(0, import_common_helpers10.invariant)(firstIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
3651
|
+
(0, import_common_helpers10.invariant)(secondIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
3048
3652
|
if (action === "connect") {
|
|
3049
3653
|
const result = await kysely.insertInto(joinTable).values({
|
|
3050
3654
|
A: sortedRecords[0].entity[firstIds[0]],
|
|
@@ -3055,17 +3659,17 @@ var BaseOperationHandler = class {
|
|
|
3055
3659
|
]).doNothing()).execute();
|
|
3056
3660
|
return result[0];
|
|
3057
3661
|
} else {
|
|
3058
|
-
const eb = (0,
|
|
3662
|
+
const eb = (0, import_kysely10.expressionBuilder)();
|
|
3059
3663
|
const result = await kysely.deleteFrom(joinTable).where(eb(`${joinTable}.A`, "=", sortedRecords[0].entity[firstIds[0]])).where(eb(`${joinTable}.B`, "=", sortedRecords[1].entity[secondIds[0]])).execute();
|
|
3060
3664
|
return result[0];
|
|
3061
3665
|
}
|
|
3062
3666
|
}
|
|
3063
3667
|
resetManyToManyRelation(kysely, model, field, parentIds) {
|
|
3064
|
-
(0,
|
|
3668
|
+
(0, import_common_helpers10.invariant)(Object.keys(parentIds).length === 1, "parentIds must have exactly one field");
|
|
3065
3669
|
const parentId = Object.values(parentIds)[0];
|
|
3066
3670
|
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
3067
|
-
(0,
|
|
3068
|
-
const eb = (0,
|
|
3671
|
+
(0, import_common_helpers10.invariant)(m2m, "not a many-to-many relation");
|
|
3672
|
+
const eb = (0, import_kysely10.expressionBuilder)();
|
|
3069
3673
|
return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
|
|
3070
3674
|
}
|
|
3071
3675
|
async processOwnedRelationForCreate(kysely, relationField, payload) {
|
|
@@ -3086,7 +3690,7 @@ var BaseOperationHandler = class {
|
|
|
3086
3690
|
}
|
|
3087
3691
|
case "connect": {
|
|
3088
3692
|
const referencedPkFields = relationField.relation.references;
|
|
3089
|
-
(0,
|
|
3693
|
+
(0, import_common_helpers10.invariant)(referencedPkFields, "relation must have fields info");
|
|
3090
3694
|
const extractedFks = extractFields(subPayload, referencedPkFields);
|
|
3091
3695
|
if (Object.keys(extractedFks).length === referencedPkFields.length) {
|
|
3092
3696
|
result = extractedFks;
|
|
@@ -3096,7 +3700,7 @@ var BaseOperationHandler = class {
|
|
|
3096
3700
|
select: fieldsToSelectObject(referencedPkFields)
|
|
3097
3701
|
});
|
|
3098
3702
|
if (!relationEntity) {
|
|
3099
|
-
throw new NotFoundError(`Could not find the entity
|
|
3703
|
+
throw new NotFoundError(relationModel, `Could not find the entity to connect for the relation "${relationField.name}"`);
|
|
3100
3704
|
}
|
|
3101
3705
|
result = relationEntity;
|
|
3102
3706
|
}
|
|
@@ -3118,14 +3722,14 @@ var BaseOperationHandler = class {
|
|
|
3118
3722
|
}
|
|
3119
3723
|
return result;
|
|
3120
3724
|
}
|
|
3121
|
-
processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
|
|
3725
|
+
async processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
|
|
3122
3726
|
const relationFieldDef = this.requireField(contextModel, relationFieldName);
|
|
3123
3727
|
const relationModel = relationFieldDef.type;
|
|
3124
|
-
const tasks = [];
|
|
3125
3728
|
const fromRelationContext = {
|
|
3126
3729
|
model: contextModel,
|
|
3127
3730
|
field: relationFieldName,
|
|
3128
|
-
ids: parentEntity
|
|
3731
|
+
ids: parentEntity,
|
|
3732
|
+
parentUpdates: {}
|
|
3129
3733
|
};
|
|
3130
3734
|
for (const [action, subPayload] of Object.entries(payload)) {
|
|
3131
3735
|
if (!subPayload) {
|
|
@@ -3133,39 +3737,35 @@ var BaseOperationHandler = class {
|
|
|
3133
3737
|
}
|
|
3134
3738
|
switch (action) {
|
|
3135
3739
|
case "create": {
|
|
3136
|
-
|
|
3740
|
+
for (const item of enumerate(subPayload)) {
|
|
3741
|
+
await this.create(kysely, relationModel, item, fromRelationContext);
|
|
3742
|
+
}
|
|
3137
3743
|
break;
|
|
3138
3744
|
}
|
|
3139
3745
|
case "createMany": {
|
|
3140
|
-
(0,
|
|
3141
|
-
|
|
3746
|
+
(0, import_common_helpers10.invariant)(relationFieldDef.array, "relation must be an array for createMany");
|
|
3747
|
+
await this.createMany(kysely, relationModel, subPayload, false, fromRelationContext);
|
|
3142
3748
|
break;
|
|
3143
3749
|
}
|
|
3144
3750
|
case "connect": {
|
|
3145
|
-
|
|
3146
|
-
model: contextModel,
|
|
3147
|
-
field: relationFieldName,
|
|
3148
|
-
ids: parentEntity
|
|
3149
|
-
}));
|
|
3751
|
+
await this.connectRelation(kysely, relationModel, subPayload, fromRelationContext);
|
|
3150
3752
|
break;
|
|
3151
3753
|
}
|
|
3152
3754
|
case "connectOrCreate": {
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
}))));
|
|
3755
|
+
for (const item of enumerate(subPayload)) {
|
|
3756
|
+
const found = await this.exists(kysely, relationModel, item.where);
|
|
3757
|
+
if (!found) {
|
|
3758
|
+
await this.create(kysely, relationModel, item.create, fromRelationContext);
|
|
3759
|
+
} else {
|
|
3760
|
+
await this.connectRelation(kysely, relationModel, found, fromRelationContext);
|
|
3761
|
+
}
|
|
3762
|
+
}
|
|
3162
3763
|
break;
|
|
3163
3764
|
}
|
|
3164
3765
|
default:
|
|
3165
3766
|
throw new QueryError(`Invalid relation action: ${action}`);
|
|
3166
3767
|
}
|
|
3167
3768
|
}
|
|
3168
|
-
return Promise.all(tasks);
|
|
3169
3769
|
}
|
|
3170
3770
|
async createMany(kysely, model, input, returnData, fromRelation) {
|
|
3171
3771
|
if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
|
|
@@ -3186,7 +3786,7 @@ var BaseOperationHandler = class {
|
|
|
3186
3786
|
const newItem = {};
|
|
3187
3787
|
for (const [name, value] of Object.entries(item)) {
|
|
3188
3788
|
const fieldDef = this.requireField(model, name);
|
|
3189
|
-
(0,
|
|
3789
|
+
(0, import_common_helpers10.invariant)(!fieldDef.relation, "createMany does not support relations");
|
|
3190
3790
|
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
3191
3791
|
}
|
|
3192
3792
|
if (fromRelation) {
|
|
@@ -3194,7 +3794,7 @@ var BaseOperationHandler = class {
|
|
|
3194
3794
|
newItem[fk] = fromRelation.ids[pk];
|
|
3195
3795
|
}
|
|
3196
3796
|
}
|
|
3197
|
-
return this.
|
|
3797
|
+
return this.fillGeneratedAndDefaultValues(modelDef, newItem);
|
|
3198
3798
|
});
|
|
3199
3799
|
if (!this.dialect.supportInsertWithDefault) {
|
|
3200
3800
|
const allPassedFields = createData.reduce((acc, item) => {
|
|
@@ -3236,7 +3836,7 @@ var BaseOperationHandler = class {
|
|
|
3236
3836
|
count: Number(result.numAffectedRows)
|
|
3237
3837
|
};
|
|
3238
3838
|
} else {
|
|
3239
|
-
const idFields =
|
|
3839
|
+
const idFields = requireIdFields(this.schema, model);
|
|
3240
3840
|
const result = await query.returning(idFields).execute();
|
|
3241
3841
|
return result;
|
|
3242
3842
|
}
|
|
@@ -3245,7 +3845,7 @@ var BaseOperationHandler = class {
|
|
|
3245
3845
|
const thisCreateRows = [];
|
|
3246
3846
|
const remainingFieldRows = [];
|
|
3247
3847
|
const discriminatorField = getDiscriminatorField(this.schema, model);
|
|
3248
|
-
(0,
|
|
3848
|
+
(0, import_common_helpers10.invariant)(discriminatorField, `Base model "${model}" must have a discriminator field`);
|
|
3249
3849
|
for (const createFields of createRows) {
|
|
3250
3850
|
const thisCreateFields = {};
|
|
3251
3851
|
const remainingFields = {};
|
|
@@ -3274,7 +3874,7 @@ var BaseOperationHandler = class {
|
|
|
3274
3874
|
remainingFieldRows
|
|
3275
3875
|
};
|
|
3276
3876
|
}
|
|
3277
|
-
|
|
3877
|
+
fillGeneratedAndDefaultValues(modelDef, data) {
|
|
3278
3878
|
const fields = modelDef.fields;
|
|
3279
3879
|
const values = clone(data);
|
|
3280
3880
|
for (const [field, fieldDef] of Object.entries(fields)) {
|
|
@@ -3289,6 +3889,16 @@ var BaseOperationHandler = class {
|
|
|
3289
3889
|
}
|
|
3290
3890
|
} else if (fields[field]?.updatedAt) {
|
|
3291
3891
|
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
3892
|
+
} else if (fields[field]?.default !== void 0) {
|
|
3893
|
+
let value = fields[field].default;
|
|
3894
|
+
if (fieldDef.type === "Json") {
|
|
3895
|
+
if (fieldDef.array && Array.isArray(value)) {
|
|
3896
|
+
value = value.map((v) => typeof v === "string" ? JSON.parse(v) : v);
|
|
3897
|
+
} else if (typeof value === "string") {
|
|
3898
|
+
value = JSON.parse(value);
|
|
3899
|
+
}
|
|
3900
|
+
}
|
|
3901
|
+
values[field] = this.dialect.transformPrimitive(value, fields[field].type, !!fields[field].array);
|
|
3292
3902
|
}
|
|
3293
3903
|
}
|
|
3294
3904
|
}
|
|
@@ -3331,7 +3941,7 @@ var BaseOperationHandler = class {
|
|
|
3331
3941
|
}
|
|
3332
3942
|
} else {
|
|
3333
3943
|
const fromRelationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3334
|
-
(0,
|
|
3944
|
+
(0, import_common_helpers10.invariant)(fromRelationFieldDef.relation?.opposite);
|
|
3335
3945
|
parentWhere[fromRelationFieldDef.relation.opposite] = {
|
|
3336
3946
|
some: fromRelation.ids
|
|
3337
3947
|
};
|
|
@@ -3389,10 +3999,7 @@ var BaseOperationHandler = class {
|
|
|
3389
3999
|
throw new QueryError(`Relation update not allowed for field "${field}"`);
|
|
3390
4000
|
}
|
|
3391
4001
|
if (!thisEntity) {
|
|
3392
|
-
thisEntity = await this.
|
|
3393
|
-
where: combinedWhere,
|
|
3394
|
-
select: this.makeIdSelect(model)
|
|
3395
|
-
});
|
|
4002
|
+
thisEntity = await this.getEntityIds(kysely, model, combinedWhere);
|
|
3396
4003
|
if (!thisEntity) {
|
|
3397
4004
|
if (throwIfNotFound) {
|
|
3398
4005
|
throw new NotFoundError(model);
|
|
@@ -3401,13 +4008,16 @@ var BaseOperationHandler = class {
|
|
|
3401
4008
|
}
|
|
3402
4009
|
}
|
|
3403
4010
|
}
|
|
3404
|
-
await this.processRelationUpdates(kysely, model, field, fieldDef, thisEntity, finalData[field], throwIfNotFound);
|
|
4011
|
+
const parentUpdates = await this.processRelationUpdates(kysely, model, field, fieldDef, thisEntity, finalData[field], throwIfNotFound);
|
|
4012
|
+
if (Object.keys(parentUpdates).length > 0) {
|
|
4013
|
+
Object.assign(updateFields, parentUpdates);
|
|
4014
|
+
}
|
|
3405
4015
|
}
|
|
3406
4016
|
}
|
|
3407
4017
|
if (Object.keys(updateFields).length === 0) {
|
|
3408
4018
|
return combinedWhere;
|
|
3409
4019
|
} else {
|
|
3410
|
-
const idFields =
|
|
4020
|
+
const idFields = requireIdFields(this.schema, model);
|
|
3411
4021
|
const query = kysely.updateTable(model).where((eb) => this.dialect.buildFilter(eb, model, model, combinedWhere)).set(updateFields).returning(idFields).modifyEnd(this.makeContextComment({
|
|
3412
4022
|
model,
|
|
3413
4023
|
operation: "update"
|
|
@@ -3452,7 +4062,7 @@ var BaseOperationHandler = class {
|
|
|
3452
4062
|
if (!filter || typeof filter !== "object") {
|
|
3453
4063
|
return false;
|
|
3454
4064
|
}
|
|
3455
|
-
const idFields =
|
|
4065
|
+
const idFields = requireIdFields(this.schema, model);
|
|
3456
4066
|
return idFields.length === Object.keys(filter).length && idFields.every((field) => field in filter);
|
|
3457
4067
|
}
|
|
3458
4068
|
async processBaseModelUpdate(kysely, model, where, updateFields, throwIfNotFound) {
|
|
@@ -3473,20 +4083,20 @@ var BaseOperationHandler = class {
|
|
|
3473
4083
|
};
|
|
3474
4084
|
}
|
|
3475
4085
|
transformIncrementalUpdate(model, field, fieldDef, payload) {
|
|
3476
|
-
(0,
|
|
4086
|
+
(0, import_common_helpers10.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
|
|
3477
4087
|
const key = Object.keys(payload)[0];
|
|
3478
4088
|
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
|
|
3479
|
-
const eb = (0,
|
|
4089
|
+
const eb = (0, import_kysely10.expressionBuilder)();
|
|
3480
4090
|
const fieldRef = this.dialect.fieldRef(model, field, eb);
|
|
3481
4091
|
return (0, import_ts_pattern9.match)(key).with("set", () => value).with("increment", () => eb(fieldRef, "+", value)).with("decrement", () => eb(fieldRef, "-", value)).with("multiply", () => eb(fieldRef, "*", value)).with("divide", () => eb(fieldRef, "/", value)).otherwise(() => {
|
|
3482
4092
|
throw new InternalError(`Invalid incremental update operation: ${key}`);
|
|
3483
4093
|
});
|
|
3484
4094
|
}
|
|
3485
4095
|
transformScalarListUpdate(model, field, fieldDef, payload) {
|
|
3486
|
-
(0,
|
|
4096
|
+
(0, import_common_helpers10.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
|
|
3487
4097
|
const key = Object.keys(payload)[0];
|
|
3488
4098
|
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
|
|
3489
|
-
const eb = (0,
|
|
4099
|
+
const eb = (0, import_kysely10.expressionBuilder)();
|
|
3490
4100
|
const fieldRef = this.dialect.fieldRef(model, field, eb);
|
|
3491
4101
|
return (0, import_ts_pattern9.match)(key).with("set", () => value).with("push", () => {
|
|
3492
4102
|
return eb(fieldRef, "||", eb.val(ensureArray(value)));
|
|
@@ -3498,7 +4108,7 @@ var BaseOperationHandler = class {
|
|
|
3498
4108
|
return NUMERIC_FIELD_TYPES.includes(fieldDef.type) && !fieldDef.array;
|
|
3499
4109
|
}
|
|
3500
4110
|
makeContextComment(_context) {
|
|
3501
|
-
return
|
|
4111
|
+
return import_kysely10.sql``;
|
|
3502
4112
|
}
|
|
3503
4113
|
async updateMany(kysely, model, where, data, limit, returnData, filterModel) {
|
|
3504
4114
|
if (typeof data !== "object") {
|
|
@@ -3557,7 +4167,7 @@ var BaseOperationHandler = class {
|
|
|
3557
4167
|
count: Number(result.numAffectedRows)
|
|
3558
4168
|
};
|
|
3559
4169
|
} else {
|
|
3560
|
-
const idFields =
|
|
4170
|
+
const idFields = requireIdFields(this.schema, model);
|
|
3561
4171
|
const result = await query.returning(idFields).execute();
|
|
3562
4172
|
return result;
|
|
3563
4173
|
}
|
|
@@ -3580,82 +4190,87 @@ var BaseOperationHandler = class {
|
|
|
3580
4190
|
};
|
|
3581
4191
|
}
|
|
3582
4192
|
buildIdFieldRefs(kysely, model) {
|
|
3583
|
-
const idFields =
|
|
4193
|
+
const idFields = requireIdFields(this.schema, model);
|
|
3584
4194
|
return idFields.map((f) => kysely.dynamic.ref(`${model}.${f}`));
|
|
3585
4195
|
}
|
|
3586
4196
|
async processRelationUpdates(kysely, model, field, fieldDef, parentIds, args, throwIfNotFound) {
|
|
3587
|
-
const tasks = [];
|
|
3588
4197
|
const fieldModel = fieldDef.type;
|
|
3589
4198
|
const fromRelationContext = {
|
|
3590
4199
|
model,
|
|
3591
4200
|
field,
|
|
3592
|
-
ids: parentIds
|
|
4201
|
+
ids: parentIds,
|
|
4202
|
+
parentUpdates: {}
|
|
3593
4203
|
};
|
|
3594
4204
|
for (const [key, value] of Object.entries(args)) {
|
|
3595
4205
|
switch (key) {
|
|
3596
4206
|
case "create": {
|
|
3597
|
-
(0,
|
|
3598
|
-
|
|
4207
|
+
(0, import_common_helpers10.invariant)(!Array.isArray(value) || fieldDef.array, "relation must be an array if create is an array");
|
|
4208
|
+
for (const item of enumerate(value)) {
|
|
4209
|
+
await this.create(kysely, fieldModel, item, fromRelationContext);
|
|
4210
|
+
}
|
|
3599
4211
|
break;
|
|
3600
4212
|
}
|
|
3601
4213
|
case "createMany": {
|
|
3602
|
-
(0,
|
|
3603
|
-
|
|
4214
|
+
(0, import_common_helpers10.invariant)(fieldDef.array, "relation must be an array for createMany");
|
|
4215
|
+
await this.createMany(kysely, fieldModel, value, false, fromRelationContext);
|
|
3604
4216
|
break;
|
|
3605
4217
|
}
|
|
3606
4218
|
case "connect": {
|
|
3607
|
-
|
|
4219
|
+
await this.connectRelation(kysely, fieldModel, value, fromRelationContext);
|
|
3608
4220
|
break;
|
|
3609
4221
|
}
|
|
3610
4222
|
case "connectOrCreate": {
|
|
3611
|
-
|
|
4223
|
+
await this.connectOrCreateRelation(kysely, fieldModel, value, fromRelationContext);
|
|
3612
4224
|
break;
|
|
3613
4225
|
}
|
|
3614
4226
|
case "disconnect": {
|
|
3615
|
-
|
|
4227
|
+
await this.disconnectRelation(kysely, fieldModel, value, fromRelationContext);
|
|
3616
4228
|
break;
|
|
3617
4229
|
}
|
|
3618
4230
|
case "set": {
|
|
3619
|
-
(0,
|
|
3620
|
-
|
|
4231
|
+
(0, import_common_helpers10.invariant)(fieldDef.array, "relation must be an array");
|
|
4232
|
+
await this.setRelation(kysely, fieldModel, value, fromRelationContext);
|
|
3621
4233
|
break;
|
|
3622
4234
|
}
|
|
3623
4235
|
case "update": {
|
|
3624
|
-
|
|
4236
|
+
for (const _item of enumerate(value)) {
|
|
4237
|
+
const item = _item;
|
|
3625
4238
|
let where;
|
|
3626
4239
|
let data;
|
|
3627
|
-
if ("
|
|
4240
|
+
if ("data" in item && typeof item.data === "object") {
|
|
3628
4241
|
where = item.where;
|
|
3629
4242
|
data = item.data;
|
|
3630
4243
|
} else {
|
|
3631
4244
|
where = void 0;
|
|
3632
4245
|
data = item;
|
|
3633
4246
|
}
|
|
3634
|
-
|
|
3635
|
-
}
|
|
4247
|
+
await this.update(kysely, fieldModel, where, data, fromRelationContext, true, throwIfNotFound);
|
|
4248
|
+
}
|
|
3636
4249
|
break;
|
|
3637
4250
|
}
|
|
3638
4251
|
case "upsert": {
|
|
3639
|
-
|
|
4252
|
+
for (const _item of enumerate(value)) {
|
|
4253
|
+
const item = _item;
|
|
3640
4254
|
const updated = await this.update(kysely, fieldModel, item.where, item.update, fromRelationContext, true, false);
|
|
3641
|
-
if (updated) {
|
|
3642
|
-
|
|
3643
|
-
} else {
|
|
3644
|
-
return this.create(kysely, fieldModel, item.create, fromRelationContext);
|
|
4255
|
+
if (!updated) {
|
|
4256
|
+
await this.create(kysely, fieldModel, item.create, fromRelationContext);
|
|
3645
4257
|
}
|
|
3646
|
-
}
|
|
4258
|
+
}
|
|
3647
4259
|
break;
|
|
3648
4260
|
}
|
|
3649
4261
|
case "updateMany": {
|
|
3650
|
-
|
|
4262
|
+
for (const _item of enumerate(value)) {
|
|
4263
|
+
const item = _item;
|
|
4264
|
+
await this.update(kysely, fieldModel, item.where, item.data, fromRelationContext, false, false);
|
|
4265
|
+
}
|
|
3651
4266
|
break;
|
|
3652
4267
|
}
|
|
3653
4268
|
case "delete": {
|
|
3654
|
-
|
|
4269
|
+
await this.deleteRelation(kysely, fieldModel, value, fromRelationContext, true);
|
|
3655
4270
|
break;
|
|
3656
4271
|
}
|
|
3657
4272
|
case "deleteMany": {
|
|
3658
|
-
|
|
4273
|
+
await this.deleteRelation(kysely, fieldModel, value, fromRelationContext, false);
|
|
3659
4274
|
break;
|
|
3660
4275
|
}
|
|
3661
4276
|
default: {
|
|
@@ -3663,7 +4278,7 @@ var BaseOperationHandler = class {
|
|
|
3663
4278
|
}
|
|
3664
4279
|
}
|
|
3665
4280
|
}
|
|
3666
|
-
|
|
4281
|
+
return fromRelationContext.parentUpdates;
|
|
3667
4282
|
}
|
|
3668
4283
|
// #region relation manipulation
|
|
3669
4284
|
async connectRelation(kysely, model, data, fromRelation) {
|
|
@@ -3673,37 +4288,35 @@ var BaseOperationHandler = class {
|
|
|
3673
4288
|
}
|
|
3674
4289
|
const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
|
|
3675
4290
|
if (m2m) {
|
|
3676
|
-
const
|
|
4291
|
+
const results = [];
|
|
4292
|
+
for (const d of _data) {
|
|
3677
4293
|
const ids = await this.getEntityIds(kysely, model, d);
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
4294
|
+
if (!ids) {
|
|
4295
|
+
throw new NotFoundError(model);
|
|
4296
|
+
}
|
|
4297
|
+
const r = await this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable);
|
|
4298
|
+
results.push(r);
|
|
4299
|
+
}
|
|
3681
4300
|
if (_data.length > results.filter((r) => !!r).length) {
|
|
3682
4301
|
throw new NotFoundError(model);
|
|
3683
4302
|
}
|
|
3684
4303
|
} else {
|
|
3685
4304
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3686
|
-
let updateResult;
|
|
3687
4305
|
if (ownedByModel) {
|
|
3688
|
-
(0,
|
|
4306
|
+
(0, import_common_helpers10.invariant)(_data.length === 1, "only one entity can be connected");
|
|
3689
4307
|
const target = await this.readUnique(kysely, model, {
|
|
3690
4308
|
where: _data[0]
|
|
3691
4309
|
});
|
|
3692
4310
|
if (!target) {
|
|
3693
4311
|
throw new NotFoundError(model);
|
|
3694
4312
|
}
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
}), {})).modifyEnd(this.makeContextComment({
|
|
3699
|
-
model: fromRelation.model,
|
|
3700
|
-
operation: "update"
|
|
3701
|
-
}));
|
|
3702
|
-
updateResult = await this.executeQuery(kysely, query, "connect");
|
|
4313
|
+
for (const { fk, pk } of keyPairs) {
|
|
4314
|
+
fromRelation.parentUpdates[fk] = target[pk];
|
|
4315
|
+
}
|
|
3703
4316
|
} else {
|
|
3704
4317
|
const relationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3705
4318
|
if (!relationFieldDef.array) {
|
|
3706
|
-
const query2 = kysely.updateTable(model).where((eb) => eb.and(keyPairs.map(({ fk, pk }) => eb(
|
|
4319
|
+
const query2 = kysely.updateTable(model).where((eb) => eb.and(keyPairs.map(({ fk, pk }) => eb(import_kysely10.sql.ref(fk), "=", fromRelation.ids[pk])))).set(keyPairs.reduce((acc, { fk }) => ({
|
|
3707
4320
|
...acc,
|
|
3708
4321
|
[fk]: null
|
|
3709
4322
|
}), {})).modifyEnd(this.makeContextComment({
|
|
@@ -3719,10 +4332,10 @@ var BaseOperationHandler = class {
|
|
|
3719
4332
|
model,
|
|
3720
4333
|
operation: "update"
|
|
3721
4334
|
}));
|
|
3722
|
-
updateResult = await this.executeQuery(kysely, query, "connect");
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
4335
|
+
const updateResult = await this.executeQuery(kysely, query, "connect");
|
|
4336
|
+
if (!updateResult.numAffectedRows || _data.length > updateResult.numAffectedRows) {
|
|
4337
|
+
throw new NotFoundError(model);
|
|
4338
|
+
}
|
|
3726
4339
|
}
|
|
3727
4340
|
}
|
|
3728
4341
|
}
|
|
@@ -3731,16 +4344,16 @@ var BaseOperationHandler = class {
|
|
|
3731
4344
|
if (_data.length === 0) {
|
|
3732
4345
|
return;
|
|
3733
4346
|
}
|
|
3734
|
-
|
|
4347
|
+
for (const { where, create } of _data) {
|
|
3735
4348
|
const existing = await this.exists(kysely, model, where);
|
|
3736
4349
|
if (existing) {
|
|
3737
|
-
|
|
4350
|
+
await this.connectRelation(kysely, model, [
|
|
3738
4351
|
where
|
|
3739
4352
|
], fromRelation);
|
|
3740
4353
|
} else {
|
|
3741
|
-
|
|
4354
|
+
await this.create(kysely, model, create, fromRelation);
|
|
3742
4355
|
}
|
|
3743
|
-
}
|
|
4356
|
+
}
|
|
3744
4357
|
}
|
|
3745
4358
|
async disconnectRelation(kysely, model, data, fromRelation) {
|
|
3746
4359
|
let disconnectConditions = [];
|
|
@@ -3763,33 +4376,51 @@ var BaseOperationHandler = class {
|
|
|
3763
4376
|
}
|
|
3764
4377
|
const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
|
|
3765
4378
|
if (m2m) {
|
|
3766
|
-
const
|
|
4379
|
+
for (const d of disconnectConditions) {
|
|
3767
4380
|
const ids = await this.getEntityIds(kysely, model, d);
|
|
3768
4381
|
if (!ids) {
|
|
3769
4382
|
return;
|
|
3770
4383
|
}
|
|
3771
|
-
|
|
3772
|
-
}
|
|
3773
|
-
await Promise.all(actions);
|
|
4384
|
+
await this.handleManyToManyRelation(kysely, "disconnect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable);
|
|
4385
|
+
}
|
|
3774
4386
|
} else {
|
|
3775
4387
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3776
|
-
const eb = (0,
|
|
4388
|
+
const eb = (0, import_kysely10.expressionBuilder)();
|
|
3777
4389
|
if (ownedByModel) {
|
|
3778
|
-
(0,
|
|
4390
|
+
(0, import_common_helpers10.invariant)(disconnectConditions.length === 1, "only one entity can be disconnected");
|
|
3779
4391
|
const condition = disconnectConditions[0];
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
4392
|
+
if (condition === true) {
|
|
4393
|
+
for (const { fk } of keyPairs) {
|
|
4394
|
+
fromRelation.parentUpdates[fk] = null;
|
|
4395
|
+
}
|
|
4396
|
+
} else {
|
|
4397
|
+
const fromEntity = await this.readUnique(kysely, fromRelation.model, {
|
|
4398
|
+
where: fromRelation.ids,
|
|
4399
|
+
select: fieldsToSelectObject(keyPairs.map(({ fk }) => fk))
|
|
4400
|
+
});
|
|
4401
|
+
if (!fromEntity || keyPairs.some(({ fk }) => fromEntity[fk] == null)) {
|
|
4402
|
+
return;
|
|
4403
|
+
}
|
|
4404
|
+
const relationFilter = {
|
|
4405
|
+
AND: [
|
|
4406
|
+
condition,
|
|
4407
|
+
Object.fromEntries(keyPairs.map(({ fk, pk }) => [
|
|
4408
|
+
pk,
|
|
4409
|
+
fromEntity[fk]
|
|
4410
|
+
]))
|
|
4411
|
+
]
|
|
4412
|
+
};
|
|
4413
|
+
const targetExists = await this.read(kysely, model, {
|
|
4414
|
+
where: relationFilter,
|
|
4415
|
+
take: 1,
|
|
4416
|
+
select: this.makeIdSelect(model)
|
|
4417
|
+
});
|
|
4418
|
+
if (targetExists.length > 0) {
|
|
4419
|
+
for (const { fk } of keyPairs) {
|
|
4420
|
+
fromRelation.parentUpdates[fk] = null;
|
|
4421
|
+
}
|
|
4422
|
+
}
|
|
4423
|
+
}
|
|
3793
4424
|
} else {
|
|
3794
4425
|
const query = kysely.updateTable(model).where(eb.and([
|
|
3795
4426
|
// fk filter
|
|
@@ -3815,11 +4446,14 @@ var BaseOperationHandler = class {
|
|
|
3815
4446
|
const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
|
|
3816
4447
|
if (m2m) {
|
|
3817
4448
|
await this.resetManyToManyRelation(kysely, fromRelation.model, fromRelation.field, fromRelation.ids);
|
|
3818
|
-
const
|
|
4449
|
+
const results = [];
|
|
4450
|
+
for (const d of _data) {
|
|
3819
4451
|
const ids = await this.getEntityIds(kysely, model, d);
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
4452
|
+
if (!ids) {
|
|
4453
|
+
throw new NotFoundError(model);
|
|
4454
|
+
}
|
|
4455
|
+
results.push(await this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable));
|
|
4456
|
+
}
|
|
3823
4457
|
if (_data.length > results.filter((r) => !!r).length) {
|
|
3824
4458
|
throw new NotFoundError(model);
|
|
3825
4459
|
}
|
|
@@ -3854,7 +4488,7 @@ var BaseOperationHandler = class {
|
|
|
3854
4488
|
operation: "update"
|
|
3855
4489
|
}));
|
|
3856
4490
|
const r = await this.executeQuery(kysely, query2, "connect");
|
|
3857
|
-
if (_data.length > r.numAffectedRows) {
|
|
4491
|
+
if (!r.numAffectedRows || _data.length > r.numAffectedRows) {
|
|
3858
4492
|
throw new NotFoundError(model);
|
|
3859
4493
|
}
|
|
3860
4494
|
}
|
|
@@ -3880,10 +4514,12 @@ var BaseOperationHandler = class {
|
|
|
3880
4514
|
expectedDeleteCount = deleteConditions.length;
|
|
3881
4515
|
}
|
|
3882
4516
|
let deleteResult;
|
|
4517
|
+
let deleteFromModel;
|
|
3883
4518
|
const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
|
|
3884
4519
|
if (m2m) {
|
|
4520
|
+
deleteFromModel = model;
|
|
3885
4521
|
const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3886
|
-
(0,
|
|
4522
|
+
(0, import_common_helpers10.invariant)(fieldDef.relation?.opposite);
|
|
3887
4523
|
deleteResult = await this.delete(kysely, model, {
|
|
3888
4524
|
AND: [
|
|
3889
4525
|
{
|
|
@@ -3899,14 +4535,15 @@ var BaseOperationHandler = class {
|
|
|
3899
4535
|
} else {
|
|
3900
4536
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3901
4537
|
if (ownedByModel) {
|
|
4538
|
+
deleteFromModel = fromRelation.model;
|
|
3902
4539
|
const fromEntity = await this.readUnique(kysely, fromRelation.model, {
|
|
3903
4540
|
where: fromRelation.ids
|
|
3904
4541
|
});
|
|
3905
4542
|
if (!fromEntity) {
|
|
3906
|
-
throw new NotFoundError(model);
|
|
4543
|
+
throw new NotFoundError(fromRelation.model);
|
|
3907
4544
|
}
|
|
3908
4545
|
const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3909
|
-
(0,
|
|
4546
|
+
(0, import_common_helpers10.invariant)(fieldDef.relation?.opposite);
|
|
3910
4547
|
deleteResult = await this.delete(kysely, model, {
|
|
3911
4548
|
AND: [
|
|
3912
4549
|
// filter for parent
|
|
@@ -3920,6 +4557,7 @@ var BaseOperationHandler = class {
|
|
|
3920
4557
|
]
|
|
3921
4558
|
});
|
|
3922
4559
|
} else {
|
|
4560
|
+
deleteFromModel = model;
|
|
3923
4561
|
deleteResult = await this.delete(kysely, model, {
|
|
3924
4562
|
AND: [
|
|
3925
4563
|
Object.fromEntries(keyPairs.map(({ fk, pk }) => [
|
|
@@ -3934,7 +4572,7 @@ var BaseOperationHandler = class {
|
|
|
3934
4572
|
}
|
|
3935
4573
|
}
|
|
3936
4574
|
if (throwForNotFound && expectedDeleteCount > deleteResult.count) {
|
|
3937
|
-
throw new NotFoundError(
|
|
4575
|
+
throw new NotFoundError(deleteFromModel);
|
|
3938
4576
|
}
|
|
3939
4577
|
}
|
|
3940
4578
|
normalizeRelationManipulationInput(model, data) {
|
|
@@ -4035,7 +4673,7 @@ var BaseOperationHandler = class {
|
|
|
4035
4673
|
// reused the filter if it's a complete id filter (without extra fields)
|
|
4036
4674
|
// otherwise, read the entity by the filter
|
|
4037
4675
|
getEntityIds(kysely, model, uniqueFilter) {
|
|
4038
|
-
const idFields =
|
|
4676
|
+
const idFields = requireIdFields(this.schema, model);
|
|
4039
4677
|
if (
|
|
4040
4678
|
// all id fields are provided
|
|
4041
4679
|
idFields.every((f) => f in uniqueFilter && uniqueFilter[f] !== void 0) && // no non-id filter exists
|
|
@@ -4063,7 +4701,7 @@ var BaseOperationHandler = class {
|
|
|
4063
4701
|
for (const [key, value] of Object.entries(args)) {
|
|
4064
4702
|
if (value === void 0) {
|
|
4065
4703
|
delete args[key];
|
|
4066
|
-
} else if (value && (0,
|
|
4704
|
+
} else if (value && (0, import_common_helpers10.isPlainObject)(value)) {
|
|
4067
4705
|
this.doNormalizeArgs(value);
|
|
4068
4706
|
}
|
|
4069
4707
|
}
|
|
@@ -4137,7 +4775,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
4137
4775
|
if (field === "_all") {
|
|
4138
4776
|
query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as(`_count._all`));
|
|
4139
4777
|
} else {
|
|
4140
|
-
query = query.select((eb) => eb.cast(eb.fn.count(
|
|
4778
|
+
query = query.select((eb) => eb.cast(eb.fn.count(import_kysely11.sql.ref(`$sub.${field}`)), "integer").as(`${key}.${field}`));
|
|
4141
4779
|
}
|
|
4142
4780
|
}
|
|
4143
4781
|
});
|
|
@@ -4152,7 +4790,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
4152
4790
|
if (val === true) {
|
|
4153
4791
|
query = query.select((eb) => {
|
|
4154
4792
|
const fn = (0, import_ts_pattern10.match)(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
|
|
4155
|
-
return fn(
|
|
4793
|
+
return fn(import_kysely11.sql.ref(`$sub.${field}`)).as(`${key}.${field}`);
|
|
4156
4794
|
});
|
|
4157
4795
|
}
|
|
4158
4796
|
});
|
|
@@ -4199,7 +4837,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
4199
4837
|
};
|
|
4200
4838
|
|
|
4201
4839
|
// src/client/crud/operations/count.ts
|
|
4202
|
-
var
|
|
4840
|
+
var import_kysely12 = require("kysely");
|
|
4203
4841
|
var CountOperationHandler = class extends BaseOperationHandler {
|
|
4204
4842
|
static {
|
|
4205
4843
|
__name(this, "CountOperationHandler");
|
|
@@ -4223,7 +4861,7 @@ var CountOperationHandler = class extends BaseOperationHandler {
|
|
|
4223
4861
|
return subQuery.as(subQueryName);
|
|
4224
4862
|
});
|
|
4225
4863
|
if (parsedArgs?.select && typeof parsedArgs.select === "object") {
|
|
4226
|
-
query = query.select((eb) => Object.keys(parsedArgs.select).map((key) => key === "_all" ? eb.cast(eb.fn.countAll(), "integer").as("_all") : eb.cast(eb.fn.count(
|
|
4864
|
+
query = query.select((eb) => Object.keys(parsedArgs.select).map((key) => key === "_all" ? eb.cast(eb.fn.countAll(), "integer").as("_all") : eb.cast(eb.fn.count(import_kysely12.sql.ref(`${subQueryName}.${key}`)), "integer").as(key)));
|
|
4227
4865
|
const result = await this.executeQuery(this.kysely, query, "count");
|
|
4228
4866
|
return result.rows[0];
|
|
4229
4867
|
} else {
|
|
@@ -4259,7 +4897,7 @@ var CreateOperationHandler = class extends BaseOperationHandler {
|
|
|
4259
4897
|
});
|
|
4260
4898
|
});
|
|
4261
4899
|
if (!result && this.hasPolicyEnabled) {
|
|
4262
|
-
throw new RejectedByPolicyError(this.model, `result is not allowed to be read back`);
|
|
4900
|
+
throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, `result is not allowed to be read back`);
|
|
4263
4901
|
}
|
|
4264
4902
|
return result;
|
|
4265
4903
|
}
|
|
@@ -4305,15 +4943,15 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
|
4305
4943
|
omit: args.omit,
|
|
4306
4944
|
where: args.where
|
|
4307
4945
|
});
|
|
4308
|
-
if (!existing) {
|
|
4309
|
-
throw new NotFoundError(this.model);
|
|
4310
|
-
}
|
|
4311
4946
|
await this.safeTransaction(async (tx) => {
|
|
4312
4947
|
const result = await this.delete(tx, this.model, args.where);
|
|
4313
4948
|
if (result.count === 0) {
|
|
4314
4949
|
throw new NotFoundError(this.model);
|
|
4315
4950
|
}
|
|
4316
4951
|
});
|
|
4952
|
+
if (!existing && this.hasPolicyEnabled) {
|
|
4953
|
+
throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
|
|
4954
|
+
}
|
|
4317
4955
|
return existing;
|
|
4318
4956
|
}
|
|
4319
4957
|
async runDeleteMany(args) {
|
|
@@ -4347,7 +4985,7 @@ var FindOperationHandler = class extends BaseOperationHandler {
|
|
|
4347
4985
|
};
|
|
4348
4986
|
|
|
4349
4987
|
// src/client/crud/operations/group-by.ts
|
|
4350
|
-
var
|
|
4988
|
+
var import_kysely13 = require("kysely");
|
|
4351
4989
|
var import_ts_pattern13 = require("ts-pattern");
|
|
4352
4990
|
var GroupByOperationHandler = class extends BaseOperationHandler {
|
|
4353
4991
|
static {
|
|
@@ -4369,7 +5007,7 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
|
|
|
4369
5007
|
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
4370
5008
|
return subQuery.as("$sub");
|
|
4371
5009
|
});
|
|
4372
|
-
const fieldRef = /* @__PURE__ */ __name((field) => this.dialect.fieldRef(this.model, field, (0,
|
|
5010
|
+
const fieldRef = /* @__PURE__ */ __name((field) => this.dialect.fieldRef(this.model, field, (0, import_kysely13.expressionBuilder)(), "$sub"), "fieldRef");
|
|
4373
5011
|
const bys = typeof parsedArgs.by === "string" ? [
|
|
4374
5012
|
parsedArgs.by
|
|
4375
5013
|
] : parsedArgs.by;
|
|
@@ -4484,7 +5122,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
4484
5122
|
});
|
|
4485
5123
|
if (!readBackResult) {
|
|
4486
5124
|
if (this.hasPolicyEnabled) {
|
|
4487
|
-
throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
|
|
5125
|
+
throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
|
|
4488
5126
|
} else {
|
|
4489
5127
|
return null;
|
|
4490
5128
|
}
|
|
@@ -4501,16 +5139,24 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
4501
5139
|
if (!args) {
|
|
4502
5140
|
return [];
|
|
4503
5141
|
}
|
|
4504
|
-
|
|
4505
|
-
const
|
|
4506
|
-
|
|
5142
|
+
const { readBackResult, updateResult } = await this.safeTransaction(async (tx) => {
|
|
5143
|
+
const updateResult2 = await this.updateMany(tx, this.model, args.where, args.data, args.limit, true);
|
|
5144
|
+
const readBackResult2 = await this.read(tx, this.model, {
|
|
4507
5145
|
select: args.select,
|
|
4508
5146
|
omit: args.omit,
|
|
4509
5147
|
where: {
|
|
4510
|
-
OR:
|
|
5148
|
+
OR: updateResult2.map((item) => getIdValues(this.schema, this.model, item))
|
|
4511
5149
|
}
|
|
4512
5150
|
});
|
|
5151
|
+
return {
|
|
5152
|
+
readBackResult: readBackResult2,
|
|
5153
|
+
updateResult: updateResult2
|
|
5154
|
+
};
|
|
4513
5155
|
});
|
|
5156
|
+
if (readBackResult.length < updateResult.length && this.hasPolicyEnabled) {
|
|
5157
|
+
throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
|
|
5158
|
+
}
|
|
5159
|
+
return readBackResult;
|
|
4514
5160
|
}
|
|
4515
5161
|
async runUpsert(args) {
|
|
4516
5162
|
const result = await this.safeTransaction(async (tx) => {
|
|
@@ -4526,18 +5172,32 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
4526
5172
|
});
|
|
4527
5173
|
});
|
|
4528
5174
|
if (!result && this.hasPolicyEnabled) {
|
|
4529
|
-
throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
|
|
5175
|
+
throw new RejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
|
|
4530
5176
|
}
|
|
4531
5177
|
return result;
|
|
4532
5178
|
}
|
|
4533
5179
|
};
|
|
4534
5180
|
|
|
4535
5181
|
// src/client/crud/validator.ts
|
|
4536
|
-
var
|
|
4537
|
-
var
|
|
5182
|
+
var import_common_helpers11 = require("@zenstackhq/common-helpers");
|
|
5183
|
+
var import_decimal3 = __toESM(require("decimal.js"), 1);
|
|
4538
5184
|
var import_json_stable_stringify = __toESM(require("json-stable-stringify"), 1);
|
|
4539
5185
|
var import_ts_pattern15 = require("ts-pattern");
|
|
4540
5186
|
var import_zod = require("zod");
|
|
5187
|
+
|
|
5188
|
+
// src/utils/zod-utils.ts
|
|
5189
|
+
var import_v3 = require("zod-validation-error/v3");
|
|
5190
|
+
var import_v4 = require("zod-validation-error/v4");
|
|
5191
|
+
function formatError(error) {
|
|
5192
|
+
if ("_zod" in error) {
|
|
5193
|
+
return (0, import_v4.fromError)(error).toString();
|
|
5194
|
+
} else {
|
|
5195
|
+
return (0, import_v3.fromError)(error).toString();
|
|
5196
|
+
}
|
|
5197
|
+
}
|
|
5198
|
+
__name(formatError, "formatError");
|
|
5199
|
+
|
|
5200
|
+
// src/client/crud/validator.ts
|
|
4541
5201
|
var InputValidator = class {
|
|
4542
5202
|
static {
|
|
4543
5203
|
__name(this, "InputValidator");
|
|
@@ -4599,7 +5259,7 @@ var InputValidator = class {
|
|
|
4599
5259
|
}
|
|
4600
5260
|
const { error } = schema.safeParse(args);
|
|
4601
5261
|
if (error) {
|
|
4602
|
-
throw new InputValidationError(`Invalid ${operation} args: ${error
|
|
5262
|
+
throw new InputValidationError(`Invalid ${operation} args: ${formatError(error)}`, error);
|
|
4603
5263
|
}
|
|
4604
5264
|
return args;
|
|
4605
5265
|
}
|
|
@@ -4643,7 +5303,7 @@ var InputValidator = class {
|
|
|
4643
5303
|
import_zod.z.bigint()
|
|
4644
5304
|
])).with("Decimal", () => import_zod.z.union([
|
|
4645
5305
|
import_zod.z.number(),
|
|
4646
|
-
import_zod.z.instanceof(
|
|
5306
|
+
import_zod.z.instanceof(import_decimal3.default),
|
|
4647
5307
|
import_zod.z.string()
|
|
4648
5308
|
])).with("DateTime", () => import_zod.z.union([
|
|
4649
5309
|
import_zod.z.date(),
|
|
@@ -4658,7 +5318,7 @@ var InputValidator = class {
|
|
|
4658
5318
|
return schema;
|
|
4659
5319
|
}
|
|
4660
5320
|
const typeDef = this.schema.typeDefs?.[type];
|
|
4661
|
-
(0,
|
|
5321
|
+
(0, import_common_helpers11.invariant)(typeDef, `Type definition "${type}" not found in schema`);
|
|
4662
5322
|
schema = import_zod.z.object(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
|
|
4663
5323
|
let fieldSchema = this.makePrimitiveSchema(def.type);
|
|
4664
5324
|
if (def.array) {
|
|
@@ -4676,10 +5336,7 @@ var InputValidator = class {
|
|
|
4676
5336
|
return schema;
|
|
4677
5337
|
}
|
|
4678
5338
|
makeWhereSchema(model, unique, withoutRelationFields = false, withAggregations = false) {
|
|
4679
|
-
const modelDef =
|
|
4680
|
-
if (!modelDef) {
|
|
4681
|
-
throw new QueryError(`Model "${model}" not found in schema`);
|
|
4682
|
-
}
|
|
5339
|
+
const modelDef = requireModel(this.schema, model);
|
|
4683
5340
|
const fields = {};
|
|
4684
5341
|
for (const field of Object.keys(modelDef.fields)) {
|
|
4685
5342
|
const fieldDef = requireField(this.schema, model, field);
|
|
@@ -4729,7 +5386,7 @@ var InputValidator = class {
|
|
|
4729
5386
|
for (const uniqueField of uniqueFields) {
|
|
4730
5387
|
if ("defs" in uniqueField) {
|
|
4731
5388
|
fields[uniqueField.name] = import_zod.z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
|
|
4732
|
-
(0,
|
|
5389
|
+
(0, import_common_helpers11.invariant)(!def.relation, "unique field cannot be a relation");
|
|
4733
5390
|
let fieldSchema;
|
|
4734
5391
|
const enumDef = getEnum(this.schema, def.type);
|
|
4735
5392
|
if (enumDef) {
|
|
@@ -4935,9 +5592,16 @@ var InputValidator = class {
|
|
|
4935
5592
|
fields[field] = import_zod.z.boolean().optional();
|
|
4936
5593
|
}
|
|
4937
5594
|
}
|
|
5595
|
+
const _countSchema = this.makeCountSelectionSchema(modelDef);
|
|
5596
|
+
if (_countSchema) {
|
|
5597
|
+
fields["_count"] = _countSchema;
|
|
5598
|
+
}
|
|
5599
|
+
return import_zod.z.strictObject(fields);
|
|
5600
|
+
}
|
|
5601
|
+
makeCountSelectionSchema(modelDef) {
|
|
4938
5602
|
const toManyRelations = Object.values(modelDef.fields).filter((def) => def.relation && def.array);
|
|
4939
5603
|
if (toManyRelations.length > 0) {
|
|
4940
|
-
|
|
5604
|
+
return import_zod.z.union([
|
|
4941
5605
|
import_zod.z.literal(true),
|
|
4942
5606
|
import_zod.z.strictObject({
|
|
4943
5607
|
select: import_zod.z.strictObject(toManyRelations.reduce((acc, fieldDef) => ({
|
|
@@ -4951,8 +5615,9 @@ var InputValidator = class {
|
|
|
4951
5615
|
}), {}))
|
|
4952
5616
|
})
|
|
4953
5617
|
]).optional();
|
|
5618
|
+
} else {
|
|
5619
|
+
return void 0;
|
|
4954
5620
|
}
|
|
4955
|
-
return import_zod.z.strictObject(fields);
|
|
4956
5621
|
}
|
|
4957
5622
|
makeRelationSelectIncludeSchema(fieldDef) {
|
|
4958
5623
|
let objSchema = import_zod.z.strictObject({
|
|
@@ -4999,6 +5664,10 @@ var InputValidator = class {
|
|
|
4999
5664
|
fields[field] = this.makeRelationSelectIncludeSchema(fieldDef).optional();
|
|
5000
5665
|
}
|
|
5001
5666
|
}
|
|
5667
|
+
const _countSchema = this.makeCountSelectionSchema(modelDef);
|
|
5668
|
+
if (_countSchema) {
|
|
5669
|
+
fields["_count"] = _countSchema;
|
|
5670
|
+
}
|
|
5002
5671
|
return import_zod.z.strictObject(fields);
|
|
5003
5672
|
}
|
|
5004
5673
|
makeOrderBySchema(model, withRelation, WithAggregation) {
|
|
@@ -5065,13 +5734,15 @@ var InputValidator = class {
|
|
|
5065
5734
|
// #region Create
|
|
5066
5735
|
makeCreateSchema(model) {
|
|
5067
5736
|
const dataSchema = this.makeCreateDataSchema(model, false);
|
|
5068
|
-
|
|
5737
|
+
let schema = import_zod.z.strictObject({
|
|
5069
5738
|
data: dataSchema,
|
|
5070
5739
|
select: this.makeSelectSchema(model).optional(),
|
|
5071
5740
|
include: this.makeIncludeSchema(model).optional(),
|
|
5072
5741
|
omit: this.makeOmitSchema(model).optional()
|
|
5073
5742
|
});
|
|
5074
|
-
|
|
5743
|
+
schema = this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
5744
|
+
schema = this.refineForSelectOmitMutuallyExclusive(schema);
|
|
5745
|
+
return schema;
|
|
5075
5746
|
}
|
|
5076
5747
|
makeCreateManySchema(model) {
|
|
5077
5748
|
return this.makeCreateManyDataSchema(model, []).optional();
|
|
@@ -5196,11 +5867,11 @@ var InputValidator = class {
|
|
|
5196
5867
|
fields["delete"] = this.makeDeleteRelationDataSchema(fieldType, array, true).optional();
|
|
5197
5868
|
}
|
|
5198
5869
|
fields["update"] = array ? this.orArray(import_zod.z.strictObject({
|
|
5199
|
-
where: this.makeWhereSchema(fieldType, true),
|
|
5870
|
+
where: this.makeWhereSchema(fieldType, true).optional(),
|
|
5200
5871
|
data: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
5201
5872
|
}), true).optional() : import_zod.z.union([
|
|
5202
5873
|
import_zod.z.strictObject({
|
|
5203
|
-
where: this.makeWhereSchema(fieldType, true),
|
|
5874
|
+
where: this.makeWhereSchema(fieldType, true).optional(),
|
|
5204
5875
|
data: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
5205
5876
|
}),
|
|
5206
5877
|
this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
@@ -5260,14 +5931,16 @@ var InputValidator = class {
|
|
|
5260
5931
|
// #endregion
|
|
5261
5932
|
// #region Update
|
|
5262
5933
|
makeUpdateSchema(model) {
|
|
5263
|
-
|
|
5934
|
+
let schema = import_zod.z.strictObject({
|
|
5264
5935
|
where: this.makeWhereSchema(model, true),
|
|
5265
5936
|
data: this.makeUpdateDataSchema(model),
|
|
5266
5937
|
select: this.makeSelectSchema(model).optional(),
|
|
5267
5938
|
include: this.makeIncludeSchema(model).optional(),
|
|
5268
5939
|
omit: this.makeOmitSchema(model).optional()
|
|
5269
5940
|
});
|
|
5270
|
-
|
|
5941
|
+
schema = this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
5942
|
+
schema = this.refineForSelectOmitMutuallyExclusive(schema);
|
|
5943
|
+
return schema;
|
|
5271
5944
|
}
|
|
5272
5945
|
makeUpdateManySchema(model) {
|
|
5273
5946
|
return import_zod.z.strictObject({
|
|
@@ -5278,14 +5951,15 @@ var InputValidator = class {
|
|
|
5278
5951
|
}
|
|
5279
5952
|
makeUpdateManyAndReturnSchema(model) {
|
|
5280
5953
|
const base = this.makeUpdateManySchema(model);
|
|
5281
|
-
|
|
5954
|
+
let schema = base.extend({
|
|
5282
5955
|
select: this.makeSelectSchema(model).optional(),
|
|
5283
5956
|
omit: this.makeOmitSchema(model).optional()
|
|
5284
5957
|
});
|
|
5285
|
-
|
|
5958
|
+
schema = this.refineForSelectOmitMutuallyExclusive(schema);
|
|
5959
|
+
return schema;
|
|
5286
5960
|
}
|
|
5287
5961
|
makeUpsertSchema(model) {
|
|
5288
|
-
|
|
5962
|
+
let schema = import_zod.z.strictObject({
|
|
5289
5963
|
where: this.makeWhereSchema(model, true),
|
|
5290
5964
|
create: this.makeCreateDataSchema(model, false),
|
|
5291
5965
|
update: this.makeUpdateDataSchema(model),
|
|
@@ -5293,7 +5967,9 @@ var InputValidator = class {
|
|
|
5293
5967
|
include: this.makeIncludeSchema(model).optional(),
|
|
5294
5968
|
omit: this.makeOmitSchema(model).optional()
|
|
5295
5969
|
});
|
|
5296
|
-
|
|
5970
|
+
schema = this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
5971
|
+
schema = this.refineForSelectOmitMutuallyExclusive(schema);
|
|
5972
|
+
return schema;
|
|
5297
5973
|
}
|
|
5298
5974
|
makeUpdateDataSchema(model, withoutFields = [], withoutRelationFields = false) {
|
|
5299
5975
|
const uncheckedVariantFields = {};
|
|
@@ -5370,12 +6046,14 @@ var InputValidator = class {
|
|
|
5370
6046
|
// #endregion
|
|
5371
6047
|
// #region Delete
|
|
5372
6048
|
makeDeleteSchema(model) {
|
|
5373
|
-
|
|
6049
|
+
let schema = import_zod.z.strictObject({
|
|
5374
6050
|
where: this.makeWhereSchema(model, true),
|
|
5375
6051
|
select: this.makeSelectSchema(model).optional(),
|
|
5376
6052
|
include: this.makeIncludeSchema(model).optional()
|
|
5377
6053
|
});
|
|
5378
|
-
|
|
6054
|
+
schema = this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
6055
|
+
schema = this.refineForSelectOmitMutuallyExclusive(schema);
|
|
6056
|
+
return schema;
|
|
5379
6057
|
}
|
|
5380
6058
|
makeDeleteManySchema(model) {
|
|
5381
6059
|
return import_zod.z.object({
|
|
@@ -5725,33 +6403,14 @@ function performanceNow() {
|
|
|
5725
6403
|
__name(performanceNow, "performanceNow");
|
|
5726
6404
|
|
|
5727
6405
|
// src/client/executor/zenstack-query-executor.ts
|
|
5728
|
-
var
|
|
5729
|
-
var
|
|
6406
|
+
var import_common_helpers13 = require("@zenstackhq/common-helpers");
|
|
6407
|
+
var import_kysely15 = require("kysely");
|
|
5730
6408
|
var import_ts_pattern16 = require("ts-pattern");
|
|
5731
6409
|
|
|
5732
|
-
// src/client/executor/kysely-utils.ts
|
|
5733
|
-
var import_common_helpers10 = require("@zenstackhq/common-helpers");
|
|
5734
|
-
var import_kysely12 = require("kysely");
|
|
5735
|
-
function stripAlias(node) {
|
|
5736
|
-
if (import_kysely12.AliasNode.is(node)) {
|
|
5737
|
-
(0, import_common_helpers10.invariant)(import_kysely12.IdentifierNode.is(node.alias), "Expected identifier as alias");
|
|
5738
|
-
return {
|
|
5739
|
-
alias: node.alias.name,
|
|
5740
|
-
node: node.node
|
|
5741
|
-
};
|
|
5742
|
-
} else {
|
|
5743
|
-
return {
|
|
5744
|
-
alias: void 0,
|
|
5745
|
-
node
|
|
5746
|
-
};
|
|
5747
|
-
}
|
|
5748
|
-
}
|
|
5749
|
-
__name(stripAlias, "stripAlias");
|
|
5750
|
-
|
|
5751
6410
|
// src/client/executor/name-mapper.ts
|
|
5752
|
-
var
|
|
5753
|
-
var
|
|
5754
|
-
var QueryNameMapper = class extends
|
|
6411
|
+
var import_common_helpers12 = require("@zenstackhq/common-helpers");
|
|
6412
|
+
var import_kysely14 = require("kysely");
|
|
6413
|
+
var QueryNameMapper = class extends import_kysely14.OperationNodeTransformer {
|
|
5755
6414
|
static {
|
|
5756
6415
|
__name(this, "QueryNameMapper");
|
|
5757
6416
|
}
|
|
@@ -5793,7 +6452,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5793
6452
|
})) : void 0;
|
|
5794
6453
|
return {
|
|
5795
6454
|
...super.transformSelectQuery(node),
|
|
5796
|
-
from:
|
|
6455
|
+
from: import_kysely14.FromNode.create(processedFroms.map((f) => f.node)),
|
|
5797
6456
|
joins,
|
|
5798
6457
|
selections: this.processSelectQuerySelections(node)
|
|
5799
6458
|
};
|
|
@@ -5819,7 +6478,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5819
6478
|
};
|
|
5820
6479
|
}
|
|
5821
6480
|
transformReference(node) {
|
|
5822
|
-
if (!
|
|
6481
|
+
if (!import_kysely14.ColumnNode.is(node.column)) {
|
|
5823
6482
|
return super.transformReference(node);
|
|
5824
6483
|
}
|
|
5825
6484
|
const scope = this.resolveFieldFromScopes(node.column.column.name, node.table?.table.identifier.name);
|
|
@@ -5827,12 +6486,12 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5827
6486
|
const mappedFieldName = this.mapFieldName(scope.model, node.column.column.name);
|
|
5828
6487
|
let mappedTableName = node.table?.table.identifier.name;
|
|
5829
6488
|
if (mappedTableName) {
|
|
5830
|
-
if (scope.alias === mappedTableName) {
|
|
6489
|
+
if (scope.alias && import_kysely14.IdentifierNode.is(scope.alias) && scope.alias.name === mappedTableName) {
|
|
5831
6490
|
} else if (scope.model === mappedTableName) {
|
|
5832
6491
|
mappedTableName = this.mapTableName(scope.model);
|
|
5833
6492
|
}
|
|
5834
6493
|
}
|
|
5835
|
-
return
|
|
6494
|
+
return import_kysely14.ReferenceNode.create(import_kysely14.ColumnNode.create(mappedFieldName), mappedTableName ? import_kysely14.TableNode.create(mappedTableName) : void 0);
|
|
5836
6495
|
} else {
|
|
5837
6496
|
return super.transformReference(node);
|
|
5838
6497
|
}
|
|
@@ -5843,14 +6502,14 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5843
6502
|
return super.transformColumn(node);
|
|
5844
6503
|
}
|
|
5845
6504
|
const mappedName = this.mapFieldName(scope.model, node.column.name);
|
|
5846
|
-
return
|
|
6505
|
+
return import_kysely14.ColumnNode.create(mappedName);
|
|
5847
6506
|
}
|
|
5848
6507
|
transformUpdateQuery(node) {
|
|
5849
6508
|
if (!node.table) {
|
|
5850
6509
|
return super.transformUpdateQuery(node);
|
|
5851
6510
|
}
|
|
5852
6511
|
const { alias, node: innerTable } = stripAlias(node.table);
|
|
5853
|
-
if (!innerTable || !
|
|
6512
|
+
if (!innerTable || !import_kysely14.TableNode.is(innerTable)) {
|
|
5854
6513
|
return super.transformUpdateQuery(node);
|
|
5855
6514
|
}
|
|
5856
6515
|
return this.withScope({
|
|
@@ -5868,14 +6527,14 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5868
6527
|
const scopes = node.from.froms.map((node2) => {
|
|
5869
6528
|
const { alias, node: innerNode } = stripAlias(node2);
|
|
5870
6529
|
return {
|
|
5871
|
-
model:
|
|
6530
|
+
model: extractModelName(innerNode),
|
|
5872
6531
|
alias,
|
|
5873
6532
|
namesMapped: false
|
|
5874
6533
|
};
|
|
5875
6534
|
});
|
|
5876
6535
|
const froms = node.from.froms.map((from) => {
|
|
5877
6536
|
const { alias, node: innerNode } = stripAlias(from);
|
|
5878
|
-
if (
|
|
6537
|
+
if (import_kysely14.TableNode.is(innerNode)) {
|
|
5879
6538
|
return this.wrapAlias(this.processTableRef(innerNode), alias);
|
|
5880
6539
|
} else {
|
|
5881
6540
|
return super.transformNode(from);
|
|
@@ -5884,7 +6543,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5884
6543
|
return this.withScopes(scopes, () => {
|
|
5885
6544
|
return {
|
|
5886
6545
|
...super.transformDeleteQuery(node),
|
|
5887
|
-
from:
|
|
6546
|
+
from: import_kysely14.FromNode.create(froms)
|
|
5888
6547
|
};
|
|
5889
6548
|
});
|
|
5890
6549
|
}
|
|
@@ -5893,24 +6552,24 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5893
6552
|
processSelectQuerySelections(node) {
|
|
5894
6553
|
const selections = [];
|
|
5895
6554
|
for (const selection of node.selections ?? []) {
|
|
5896
|
-
if (
|
|
6555
|
+
if (import_kysely14.SelectAllNode.is(selection.selection)) {
|
|
5897
6556
|
const scope = this.scopes[this.scopes.length - 1];
|
|
5898
6557
|
if (scope?.model && !scope.namesMapped) {
|
|
5899
6558
|
selections.push(...this.createSelectAllFields(scope.model, scope.alias));
|
|
5900
6559
|
} else {
|
|
5901
6560
|
selections.push(super.transformSelection(selection));
|
|
5902
6561
|
}
|
|
5903
|
-
} else if (
|
|
6562
|
+
} else if (import_kysely14.ReferenceNode.is(selection.selection) || import_kysely14.ColumnNode.is(selection.selection)) {
|
|
5904
6563
|
const transformed = this.transformNode(selection.selection);
|
|
5905
|
-
if (
|
|
5906
|
-
selections.push(
|
|
6564
|
+
if (import_kysely14.AliasNode.is(transformed)) {
|
|
6565
|
+
selections.push(import_kysely14.SelectionNode.create(transformed));
|
|
5907
6566
|
} else {
|
|
5908
|
-
const origFieldName =
|
|
5909
|
-
const fieldName =
|
|
6567
|
+
const origFieldName = extractFieldName(selection.selection);
|
|
6568
|
+
const fieldName = extractFieldName(transformed);
|
|
5910
6569
|
if (fieldName !== origFieldName) {
|
|
5911
|
-
selections.push(
|
|
6570
|
+
selections.push(import_kysely14.SelectionNode.create(this.wrapAlias(transformed, origFieldName ? import_kysely14.IdentifierNode.create(origFieldName) : void 0)));
|
|
5912
6571
|
} else {
|
|
5913
|
-
selections.push(
|
|
6572
|
+
selections.push(import_kysely14.SelectionNode.create(transformed));
|
|
5914
6573
|
}
|
|
5915
6574
|
}
|
|
5916
6575
|
} else {
|
|
@@ -5924,7 +6583,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5924
6583
|
const scope = this.scopes[i];
|
|
5925
6584
|
if (qualifier) {
|
|
5926
6585
|
if (scope.alias) {
|
|
5927
|
-
if (scope.alias === qualifier) {
|
|
6586
|
+
if (scope.alias && import_kysely14.IdentifierNode.is(scope.alias) && scope.alias.name === qualifier) {
|
|
5928
6587
|
return scope;
|
|
5929
6588
|
} else {
|
|
5930
6589
|
continue;
|
|
@@ -5970,16 +6629,16 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5970
6629
|
}
|
|
5971
6630
|
}
|
|
5972
6631
|
wrapAlias(node, alias) {
|
|
5973
|
-
return alias ?
|
|
6632
|
+
return alias ? import_kysely14.AliasNode.create(node, alias) : node;
|
|
5974
6633
|
}
|
|
5975
6634
|
processTableRef(node) {
|
|
5976
6635
|
if (!node) {
|
|
5977
6636
|
return node;
|
|
5978
6637
|
}
|
|
5979
|
-
if (!
|
|
6638
|
+
if (!import_kysely14.TableNode.is(node)) {
|
|
5980
6639
|
return super.transformNode(node);
|
|
5981
6640
|
}
|
|
5982
|
-
return
|
|
6641
|
+
return import_kysely14.TableNode.create(this.mapTableName(node.table.identifier.name));
|
|
5983
6642
|
}
|
|
5984
6643
|
getMappedName(def) {
|
|
5985
6644
|
const mapAttr = def.attributes?.find((attr) => attr.name === "@@map" || attr.name === "@map");
|
|
@@ -6015,14 +6674,14 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6015
6674
|
// convert a "from" node to a nested query if there are columns with name mapping
|
|
6016
6675
|
processSelectTable(node) {
|
|
6017
6676
|
const { alias, node: innerNode } = stripAlias(node);
|
|
6018
|
-
if (innerNode &&
|
|
6677
|
+
if (innerNode && import_kysely14.TableNode.is(innerNode)) {
|
|
6019
6678
|
const modelName = innerNode.table.identifier.name;
|
|
6020
6679
|
const mappedName = this.mapTableName(modelName);
|
|
6021
|
-
const finalAlias = alias ?? (mappedName !== modelName ? modelName : void 0);
|
|
6680
|
+
const finalAlias = alias ?? (mappedName !== modelName ? import_kysely14.IdentifierNode.create(modelName) : void 0);
|
|
6022
6681
|
return {
|
|
6023
|
-
node: this.wrapAlias(
|
|
6682
|
+
node: this.wrapAlias(import_kysely14.TableNode.create(mappedName), finalAlias),
|
|
6024
6683
|
scope: {
|
|
6025
|
-
alias: alias ?? modelName,
|
|
6684
|
+
alias: alias ?? import_kysely14.IdentifierNode.create(modelName),
|
|
6026
6685
|
model: modelName,
|
|
6027
6686
|
namesMapped: !this.hasMappedColumns(modelName)
|
|
6028
6687
|
}
|
|
@@ -6042,12 +6701,12 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6042
6701
|
const modelDef = requireModel(this.schema, model);
|
|
6043
6702
|
return this.getModelFields(modelDef).map((fieldDef) => {
|
|
6044
6703
|
const columnName = this.mapFieldName(model, fieldDef.name);
|
|
6045
|
-
const columnRef =
|
|
6704
|
+
const columnRef = import_kysely14.ReferenceNode.create(import_kysely14.ColumnNode.create(columnName), alias && import_kysely14.IdentifierNode.is(alias) ? import_kysely14.TableNode.create(alias.name) : void 0);
|
|
6046
6705
|
if (columnName !== fieldDef.name) {
|
|
6047
|
-
const aliased =
|
|
6048
|
-
return
|
|
6706
|
+
const aliased = import_kysely14.AliasNode.create(columnRef, import_kysely14.IdentifierNode.create(fieldDef.name));
|
|
6707
|
+
return import_kysely14.SelectionNode.create(aliased);
|
|
6049
6708
|
} else {
|
|
6050
|
-
return
|
|
6709
|
+
return import_kysely14.SelectionNode.create(columnRef);
|
|
6051
6710
|
}
|
|
6052
6711
|
});
|
|
6053
6712
|
}
|
|
@@ -6057,57 +6716,44 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6057
6716
|
processSelections(selections) {
|
|
6058
6717
|
const result = [];
|
|
6059
6718
|
selections.forEach((selection) => {
|
|
6060
|
-
if (
|
|
6719
|
+
if (import_kysely14.SelectAllNode.is(selection.selection)) {
|
|
6061
6720
|
const processed = this.processSelectAll(selection.selection);
|
|
6062
6721
|
if (Array.isArray(processed)) {
|
|
6063
|
-
result.push(...processed.map((s) =>
|
|
6722
|
+
result.push(...processed.map((s) => import_kysely14.SelectionNode.create(s)));
|
|
6064
6723
|
} else {
|
|
6065
|
-
result.push(
|
|
6724
|
+
result.push(import_kysely14.SelectionNode.create(processed));
|
|
6066
6725
|
}
|
|
6067
6726
|
} else {
|
|
6068
|
-
result.push(
|
|
6727
|
+
result.push(import_kysely14.SelectionNode.create(this.processSelection(selection.selection)));
|
|
6069
6728
|
}
|
|
6070
6729
|
});
|
|
6071
6730
|
return result;
|
|
6072
6731
|
}
|
|
6073
6732
|
processSelection(node) {
|
|
6074
6733
|
let alias;
|
|
6075
|
-
if (!
|
|
6076
|
-
alias =
|
|
6734
|
+
if (!import_kysely14.AliasNode.is(node)) {
|
|
6735
|
+
alias = extractFieldName(node);
|
|
6077
6736
|
}
|
|
6078
6737
|
const result = super.transformNode(node);
|
|
6079
|
-
return this.wrapAlias(result, alias);
|
|
6738
|
+
return this.wrapAlias(result, alias ? import_kysely14.IdentifierNode.create(alias) : void 0);
|
|
6080
6739
|
}
|
|
6081
6740
|
processSelectAll(node) {
|
|
6082
6741
|
const scope = this.scopes[this.scopes.length - 1];
|
|
6083
|
-
(0,
|
|
6742
|
+
(0, import_common_helpers12.invariant)(scope);
|
|
6084
6743
|
if (!scope.model || !this.hasMappedColumns(scope.model)) {
|
|
6085
6744
|
return super.transformSelectAll(node);
|
|
6086
6745
|
}
|
|
6087
6746
|
const modelDef = requireModel(this.schema, scope.model);
|
|
6088
6747
|
return this.getModelFields(modelDef).map((fieldDef) => {
|
|
6089
6748
|
const columnName = this.mapFieldName(modelDef.name, fieldDef.name);
|
|
6090
|
-
const columnRef =
|
|
6091
|
-
return columnName !== fieldDef.name ? this.wrapAlias(columnRef, fieldDef.name) : columnRef;
|
|
6749
|
+
const columnRef = import_kysely14.ReferenceNode.create(import_kysely14.ColumnNode.create(columnName));
|
|
6750
|
+
return columnName !== fieldDef.name ? this.wrapAlias(columnRef, import_kysely14.IdentifierNode.create(fieldDef.name)) : columnRef;
|
|
6092
6751
|
});
|
|
6093
6752
|
}
|
|
6094
|
-
extractModelName(node) {
|
|
6095
|
-
const { node: innerNode } = stripAlias(node);
|
|
6096
|
-
return import_kysely13.TableNode.is(innerNode) ? innerNode.table.identifier.name : void 0;
|
|
6097
|
-
}
|
|
6098
|
-
extractFieldName(node) {
|
|
6099
|
-
if (import_kysely13.ReferenceNode.is(node) && import_kysely13.ColumnNode.is(node.column)) {
|
|
6100
|
-
return node.column.column.name;
|
|
6101
|
-
} else if (import_kysely13.ColumnNode.is(node)) {
|
|
6102
|
-
return node.column.name;
|
|
6103
|
-
} else {
|
|
6104
|
-
return void 0;
|
|
6105
|
-
}
|
|
6106
|
-
}
|
|
6107
6753
|
};
|
|
6108
6754
|
|
|
6109
6755
|
// src/client/executor/zenstack-query-executor.ts
|
|
6110
|
-
var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends
|
|
6756
|
+
var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely15.DefaultQueryExecutor {
|
|
6111
6757
|
static {
|
|
6112
6758
|
__name(this, "ZenStackQueryExecutor");
|
|
6113
6759
|
}
|
|
@@ -6150,7 +6796,6 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6150
6796
|
const hookResult = await hook({
|
|
6151
6797
|
client: this.client,
|
|
6152
6798
|
schema: this.client.$schema,
|
|
6153
|
-
kysely: this.kysely,
|
|
6154
6799
|
query,
|
|
6155
6800
|
proceed: _p
|
|
6156
6801
|
});
|
|
@@ -6164,13 +6809,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6164
6809
|
}
|
|
6165
6810
|
getMutationInfo(queryNode) {
|
|
6166
6811
|
const model = this.getMutationModel(queryNode);
|
|
6167
|
-
const { action, where } = (0, import_ts_pattern16.match)(queryNode).when(
|
|
6812
|
+
const { action, where } = (0, import_ts_pattern16.match)(queryNode).when(import_kysely15.InsertQueryNode.is, () => ({
|
|
6168
6813
|
action: "create",
|
|
6169
6814
|
where: void 0
|
|
6170
|
-
})).when(
|
|
6815
|
+
})).when(import_kysely15.UpdateQueryNode.is, (node) => ({
|
|
6171
6816
|
action: "update",
|
|
6172
6817
|
where: node.where
|
|
6173
|
-
})).when(
|
|
6818
|
+
})).when(import_kysely15.DeleteQueryNode.is, (node) => ({
|
|
6174
6819
|
action: "delete",
|
|
6175
6820
|
where: node.where
|
|
6176
6821
|
})).exhaustive();
|
|
@@ -6198,11 +6843,11 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6198
6843
|
result
|
|
6199
6844
|
};
|
|
6200
6845
|
}
|
|
6201
|
-
if ((
|
|
6846
|
+
if ((import_kysely15.InsertQueryNode.is(query) || import_kysely15.UpdateQueryNode.is(query)) && this.hasEntityMutationPluginsWithAfterMutationHooks) {
|
|
6202
6847
|
query = {
|
|
6203
6848
|
...query,
|
|
6204
|
-
returning:
|
|
6205
|
-
|
|
6849
|
+
returning: import_kysely15.ReturningNode.create([
|
|
6850
|
+
import_kysely15.SelectionNode.createSelectAll()
|
|
6206
6851
|
])
|
|
6207
6852
|
};
|
|
6208
6853
|
}
|
|
@@ -6219,7 +6864,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6219
6864
|
const mutationInfo = this.getMutationInfo(finalQuery);
|
|
6220
6865
|
let beforeMutationEntities;
|
|
6221
6866
|
const loadBeforeMutationEntities = /* @__PURE__ */ __name(async () => {
|
|
6222
|
-
if (beforeMutationEntities === void 0 && (
|
|
6867
|
+
if (beforeMutationEntities === void 0 && (import_kysely15.UpdateQueryNode.is(query) || import_kysely15.DeleteQueryNode.is(query))) {
|
|
6223
6868
|
beforeMutationEntities = await this.loadEntities(mutationInfo.model, mutationInfo.where, connection);
|
|
6224
6869
|
}
|
|
6225
6870
|
return beforeMutationEntities;
|
|
@@ -6261,7 +6906,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6261
6906
|
}
|
|
6262
6907
|
}
|
|
6263
6908
|
createClientForConnection(connection, inTx) {
|
|
6264
|
-
const innerExecutor = this.withConnectionProvider(new
|
|
6909
|
+
const innerExecutor = this.withConnectionProvider(new import_kysely15.SingleConnectionProvider(connection));
|
|
6265
6910
|
innerExecutor.suppressMutationHooks = true;
|
|
6266
6911
|
const innerClient = this.client.withExecutor(innerExecutor);
|
|
6267
6912
|
if (inTx) {
|
|
@@ -6279,7 +6924,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6279
6924
|
return (this.client.$options.plugins ?? []).some((plugin) => plugin.onEntityMutation?.runAfterMutationWithinTransaction);
|
|
6280
6925
|
}
|
|
6281
6926
|
isMutationNode(queryNode) {
|
|
6282
|
-
return
|
|
6927
|
+
return import_kysely15.InsertQueryNode.is(queryNode) || import_kysely15.UpdateQueryNode.is(queryNode) || import_kysely15.DeleteQueryNode.is(queryNode);
|
|
6283
6928
|
}
|
|
6284
6929
|
withPlugin(plugin) {
|
|
6285
6930
|
return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, [
|
|
@@ -6308,18 +6953,18 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6308
6953
|
return newExecutor;
|
|
6309
6954
|
}
|
|
6310
6955
|
getMutationModel(queryNode) {
|
|
6311
|
-
return (0, import_ts_pattern16.match)(queryNode).when(
|
|
6312
|
-
(0,
|
|
6956
|
+
return (0, import_ts_pattern16.match)(queryNode).when(import_kysely15.InsertQueryNode.is, (node) => {
|
|
6957
|
+
(0, import_common_helpers13.invariant)(node.into, "InsertQueryNode must have an into clause");
|
|
6313
6958
|
return node.into.table.identifier.name;
|
|
6314
|
-
}).when(
|
|
6315
|
-
(0,
|
|
6959
|
+
}).when(import_kysely15.UpdateQueryNode.is, (node) => {
|
|
6960
|
+
(0, import_common_helpers13.invariant)(node.table, "UpdateQueryNode must have a table");
|
|
6316
6961
|
const { node: tableNode } = stripAlias(node.table);
|
|
6317
|
-
(0,
|
|
6962
|
+
(0, import_common_helpers13.invariant)(import_kysely15.TableNode.is(tableNode), "UpdateQueryNode must use a TableNode");
|
|
6318
6963
|
return tableNode.table.identifier.name;
|
|
6319
|
-
}).when(
|
|
6320
|
-
(0,
|
|
6964
|
+
}).when(import_kysely15.DeleteQueryNode.is, (node) => {
|
|
6965
|
+
(0, import_common_helpers13.invariant)(node.from.froms.length === 1, "Delete query must have exactly one from table");
|
|
6321
6966
|
const { node: tableNode } = stripAlias(node.from.froms[0]);
|
|
6322
|
-
(0,
|
|
6967
|
+
(0, import_common_helpers13.invariant)(import_kysely15.TableNode.is(tableNode), "DeleteQueryNode must use a TableNode");
|
|
6323
6968
|
return tableNode.table.identifier.name;
|
|
6324
6969
|
}).otherwise((node) => {
|
|
6325
6970
|
throw new InternalError(`Invalid query node: ${node}`);
|
|
@@ -6393,9 +7038,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6393
7038
|
}
|
|
6394
7039
|
andNodes(condition1, condition2) {
|
|
6395
7040
|
if (condition1 && condition2) {
|
|
6396
|
-
return
|
|
7041
|
+
return import_kysely15.WhereNode.create(import_kysely15.AndNode.create(condition1, condition2));
|
|
6397
7042
|
} else if (condition1) {
|
|
6398
|
-
return
|
|
7043
|
+
return import_kysely15.WhereNode.create(condition1);
|
|
6399
7044
|
} else {
|
|
6400
7045
|
return condition2;
|
|
6401
7046
|
}
|
|
@@ -6417,53 +7062,58 @@ __export(functions_exports, {
|
|
|
6417
7062
|
search: () => search,
|
|
6418
7063
|
startsWith: () => startsWith
|
|
6419
7064
|
});
|
|
6420
|
-
var
|
|
6421
|
-
var
|
|
7065
|
+
var import_common_helpers14 = require("@zenstackhq/common-helpers");
|
|
7066
|
+
var import_kysely16 = require("kysely");
|
|
6422
7067
|
var import_ts_pattern17 = require("ts-pattern");
|
|
6423
|
-
var contains = /* @__PURE__ */ __name((eb, args) =>
|
|
6424
|
-
const [field, search2, caseInsensitive = false] = args;
|
|
6425
|
-
if (!field) {
|
|
6426
|
-
throw new Error('"field" parameter is required');
|
|
6427
|
-
}
|
|
6428
|
-
if (!search2) {
|
|
6429
|
-
throw new Error('"search" parameter is required');
|
|
6430
|
-
}
|
|
6431
|
-
const searchExpr = eb.fn("CONCAT", [
|
|
6432
|
-
import_kysely15.sql.lit("%"),
|
|
6433
|
-
search2,
|
|
6434
|
-
import_kysely15.sql.lit("%")
|
|
6435
|
-
]);
|
|
6436
|
-
return eb(field, caseInsensitive ? "ilike" : "like", searchExpr);
|
|
6437
|
-
}, "contains");
|
|
7068
|
+
var contains = /* @__PURE__ */ __name((eb, args, context) => textMatch(eb, args, context, "contains"), "contains");
|
|
6438
7069
|
var search = /* @__PURE__ */ __name((_eb, _args) => {
|
|
6439
7070
|
throw new Error(`"search" function is not implemented yet`);
|
|
6440
7071
|
}, "search");
|
|
6441
|
-
var startsWith = /* @__PURE__ */ __name((eb, args) =>
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
}
|
|
6446
|
-
if (!search2) {
|
|
6447
|
-
throw new Error('"search" parameter is required');
|
|
6448
|
-
}
|
|
6449
|
-
return eb(field, "like", eb.fn("CONCAT", [
|
|
6450
|
-
search2,
|
|
6451
|
-
import_kysely15.sql.lit("%")
|
|
6452
|
-
]));
|
|
6453
|
-
}, "startsWith");
|
|
6454
|
-
var endsWith = /* @__PURE__ */ __name((eb, args) => {
|
|
6455
|
-
const [field, search2] = args;
|
|
7072
|
+
var startsWith = /* @__PURE__ */ __name((eb, args, context) => textMatch(eb, args, context, "startsWith"), "startsWith");
|
|
7073
|
+
var endsWith = /* @__PURE__ */ __name((eb, args, context) => textMatch(eb, args, context, "endsWith"), "endsWith");
|
|
7074
|
+
var textMatch = /* @__PURE__ */ __name((eb, args, { dialect }, method) => {
|
|
7075
|
+
const [field, search2, caseInsensitive = void 0] = args;
|
|
6456
7076
|
if (!field) {
|
|
6457
7077
|
throw new Error('"field" parameter is required');
|
|
6458
7078
|
}
|
|
6459
7079
|
if (!search2) {
|
|
6460
7080
|
throw new Error('"search" parameter is required');
|
|
6461
7081
|
}
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
7082
|
+
const casingBehavior = dialect.getStringCasingBehavior();
|
|
7083
|
+
const caseInsensitiveValue = readBoolean(caseInsensitive, false);
|
|
7084
|
+
let op;
|
|
7085
|
+
let fieldExpr = field;
|
|
7086
|
+
let searchExpr = search2;
|
|
7087
|
+
if (caseInsensitiveValue) {
|
|
7088
|
+
if (casingBehavior.supportsILike) {
|
|
7089
|
+
op = "ilike";
|
|
7090
|
+
} else {
|
|
7091
|
+
op = "like";
|
|
7092
|
+
if (casingBehavior.likeCaseSensitive === true) {
|
|
7093
|
+
fieldExpr = eb.fn("LOWER", [
|
|
7094
|
+
fieldExpr
|
|
7095
|
+
]);
|
|
7096
|
+
searchExpr = eb.fn("LOWER", [
|
|
7097
|
+
searchExpr
|
|
7098
|
+
]);
|
|
7099
|
+
}
|
|
7100
|
+
}
|
|
7101
|
+
} else {
|
|
7102
|
+
op = "like";
|
|
7103
|
+
}
|
|
7104
|
+
searchExpr = (0, import_ts_pattern17.match)(method).with("contains", () => eb.fn("CONCAT", [
|
|
7105
|
+
import_kysely16.sql.lit("%"),
|
|
7106
|
+
import_kysely16.sql`CAST(${searchExpr} as text)`,
|
|
7107
|
+
import_kysely16.sql.lit("%")
|
|
7108
|
+
])).with("startsWith", () => eb.fn("CONCAT", [
|
|
7109
|
+
import_kysely16.sql`CAST(${searchExpr} as text)`,
|
|
7110
|
+
import_kysely16.sql.lit("%")
|
|
7111
|
+
])).with("endsWith", () => eb.fn("CONCAT", [
|
|
7112
|
+
import_kysely16.sql.lit("%"),
|
|
7113
|
+
import_kysely16.sql`CAST(${searchExpr} as text)`
|
|
7114
|
+
])).exhaustive();
|
|
7115
|
+
return eb(fieldExpr, op, searchExpr);
|
|
7116
|
+
}, "textMatch");
|
|
6467
7117
|
var has = /* @__PURE__ */ __name((eb, args) => {
|
|
6468
7118
|
const [field, search2] = args;
|
|
6469
7119
|
if (!field) {
|
|
@@ -6501,18 +7151,16 @@ var isEmpty = /* @__PURE__ */ __name((eb, args, { dialect }) => {
|
|
|
6501
7151
|
if (!field) {
|
|
6502
7152
|
throw new Error('"field" parameter is required');
|
|
6503
7153
|
}
|
|
6504
|
-
return eb(dialect.buildArrayLength(eb, field), "=",
|
|
7154
|
+
return eb(dialect.buildArrayLength(eb, field), "=", import_kysely16.sql.lit(0));
|
|
6505
7155
|
}, "isEmpty");
|
|
6506
|
-
var now = /* @__PURE__ */ __name((
|
|
6507
|
-
return (0, import_ts_pattern17.match)(dialect.provider).with("postgresql", () => eb.fn("now")).with("sqlite", () => import_kysely15.sql.raw("CURRENT_TIMESTAMP")).exhaustive();
|
|
6508
|
-
}, "now");
|
|
7156
|
+
var now = /* @__PURE__ */ __name(() => import_kysely16.sql.raw("CURRENT_TIMESTAMP"), "now");
|
|
6509
7157
|
var currentModel = /* @__PURE__ */ __name((_eb, args, { model }) => {
|
|
6510
7158
|
let result = model;
|
|
6511
7159
|
const [casing] = args;
|
|
6512
7160
|
if (casing) {
|
|
6513
7161
|
result = processCasing(casing, result, model);
|
|
6514
7162
|
}
|
|
6515
|
-
return
|
|
7163
|
+
return import_kysely16.sql.lit(result);
|
|
6516
7164
|
}, "currentModel");
|
|
6517
7165
|
var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
6518
7166
|
let result = operation;
|
|
@@ -6520,21 +7168,30 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
|
6520
7168
|
if (casing) {
|
|
6521
7169
|
result = processCasing(casing, result, operation);
|
|
6522
7170
|
}
|
|
6523
|
-
return
|
|
7171
|
+
return import_kysely16.sql.lit(result);
|
|
6524
7172
|
}, "currentOperation");
|
|
6525
7173
|
function processCasing(casing, result, model) {
|
|
6526
7174
|
const opNode = casing.toOperationNode();
|
|
6527
|
-
(0,
|
|
6528
|
-
result = (0, import_ts_pattern17.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => (0,
|
|
7175
|
+
(0, import_common_helpers14.invariant)(import_kysely16.ValueNode.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
|
|
7176
|
+
result = (0, import_ts_pattern17.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => (0, import_common_helpers14.upperCaseFirst)(result)).with("uncapitalize", () => (0, import_common_helpers14.lowerCaseFirst)(result)).otherwise(() => {
|
|
6529
7177
|
throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
|
|
6530
7178
|
});
|
|
6531
7179
|
return result;
|
|
6532
7180
|
}
|
|
6533
7181
|
__name(processCasing, "processCasing");
|
|
7182
|
+
function readBoolean(expr2, defaultValue) {
|
|
7183
|
+
if (expr2 === void 0) {
|
|
7184
|
+
return defaultValue;
|
|
7185
|
+
}
|
|
7186
|
+
const opNode = expr2.toOperationNode();
|
|
7187
|
+
(0, import_common_helpers14.invariant)(import_kysely16.ValueNode.is(opNode), "expression must be a literal value");
|
|
7188
|
+
return !!opNode.value;
|
|
7189
|
+
}
|
|
7190
|
+
__name(readBoolean, "readBoolean");
|
|
6534
7191
|
|
|
6535
7192
|
// src/client/helpers/schema-db-pusher.ts
|
|
6536
|
-
var
|
|
6537
|
-
var
|
|
7193
|
+
var import_common_helpers15 = require("@zenstackhq/common-helpers");
|
|
7194
|
+
var import_kysely17 = require("kysely");
|
|
6538
7195
|
var import_toposort = __toESM(require("toposort"), 1);
|
|
6539
7196
|
var import_ts_pattern18 = require("ts-pattern");
|
|
6540
7197
|
var SchemaDbPusher = class {
|
|
@@ -6555,7 +7212,8 @@ var SchemaDbPusher = class {
|
|
|
6555
7212
|
await createEnum.execute();
|
|
6556
7213
|
}
|
|
6557
7214
|
}
|
|
6558
|
-
const
|
|
7215
|
+
const models = Object.values(this.schema.models).filter((m) => !m.isView);
|
|
7216
|
+
const sortedModels = this.sortModels(models);
|
|
6559
7217
|
for (const modelDef of sortedModels) {
|
|
6560
7218
|
const createTable = this.createModelTable(tx, modelDef);
|
|
6561
7219
|
await createTable.execute();
|
|
@@ -6564,7 +7222,7 @@ var SchemaDbPusher = class {
|
|
|
6564
7222
|
}
|
|
6565
7223
|
sortModels(models) {
|
|
6566
7224
|
const graph = [];
|
|
6567
|
-
for (const model of
|
|
7225
|
+
for (const model of models) {
|
|
6568
7226
|
let added = false;
|
|
6569
7227
|
if (model.baseModel) {
|
|
6570
7228
|
const baseDef = requireModel(this.schema, model.baseModel);
|
|
@@ -6649,7 +7307,7 @@ var SchemaDbPusher = class {
|
|
|
6649
7307
|
}
|
|
6650
7308
|
addUniqueConstraint(table, modelDef) {
|
|
6651
7309
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
6652
|
-
(0,
|
|
7310
|
+
(0, import_common_helpers15.invariant)(typeof value === "object", "expecting an object");
|
|
6653
7311
|
if ("type" in value) {
|
|
6654
7312
|
const fieldDef = modelDef.fields[key];
|
|
6655
7313
|
if (fieldDef.unique) {
|
|
@@ -6672,7 +7330,7 @@ var SchemaDbPusher = class {
|
|
|
6672
7330
|
if (fieldDef.default !== void 0) {
|
|
6673
7331
|
if (typeof fieldDef.default === "object" && "kind" in fieldDef.default) {
|
|
6674
7332
|
if (ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "now") {
|
|
6675
|
-
col = col.defaultTo(
|
|
7333
|
+
col = col.defaultTo(import_kysely17.sql`CURRENT_TIMESTAMP`);
|
|
6676
7334
|
}
|
|
6677
7335
|
} else {
|
|
6678
7336
|
col = col.defaultTo(fieldDef.default);
|
|
@@ -6692,7 +7350,7 @@ var SchemaDbPusher = class {
|
|
|
6692
7350
|
}
|
|
6693
7351
|
mapFieldType(fieldDef) {
|
|
6694
7352
|
if (this.schema.enums?.[fieldDef.type]) {
|
|
6695
|
-
return this.schema.provider.type === "postgresql" ?
|
|
7353
|
+
return this.schema.provider.type === "postgresql" ? import_kysely17.sql.ref(fieldDef.type) : "text";
|
|
6696
7354
|
}
|
|
6697
7355
|
if (this.isAutoIncrement(fieldDef) && this.schema.provider.type === "postgresql") {
|
|
6698
7356
|
return "serial";
|
|
@@ -6705,7 +7363,7 @@ var SchemaDbPusher = class {
|
|
|
6705
7363
|
throw new Error(`Unsupported field type: ${type}`);
|
|
6706
7364
|
});
|
|
6707
7365
|
if (fieldDef.array) {
|
|
6708
|
-
return
|
|
7366
|
+
return import_kysely17.sql.raw(`${result}[]`);
|
|
6709
7367
|
} else {
|
|
6710
7368
|
return result;
|
|
6711
7369
|
}
|
|
@@ -6717,7 +7375,7 @@ var SchemaDbPusher = class {
|
|
|
6717
7375
|
return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
|
|
6718
7376
|
}
|
|
6719
7377
|
addForeignKeyConstraint(table, model, fieldName, fieldDef) {
|
|
6720
|
-
(0,
|
|
7378
|
+
(0, import_common_helpers15.invariant)(fieldDef.relation, "field must be a relation");
|
|
6721
7379
|
if (!fieldDef.relation.fields || !fieldDef.relation.references) {
|
|
6722
7380
|
return table;
|
|
6723
7381
|
}
|
|
@@ -6774,16 +7432,15 @@ function valueToPromise(thing) {
|
|
|
6774
7432
|
__name(valueToPromise, "valueToPromise");
|
|
6775
7433
|
|
|
6776
7434
|
// src/client/result-processor.ts
|
|
6777
|
-
var import_common_helpers15 = require("@zenstackhq/common-helpers");
|
|
6778
|
-
var import_decimal2 = __toESM(require("decimal.js"), 1);
|
|
6779
|
-
var import_ts_pattern19 = require("ts-pattern");
|
|
6780
7435
|
var ResultProcessor = class {
|
|
6781
7436
|
static {
|
|
6782
7437
|
__name(this, "ResultProcessor");
|
|
6783
7438
|
}
|
|
6784
7439
|
schema;
|
|
6785
|
-
|
|
7440
|
+
dialect;
|
|
7441
|
+
constructor(schema, options) {
|
|
6786
7442
|
this.schema = schema;
|
|
7443
|
+
this.dialect = getCrudDialect(schema, options);
|
|
6787
7444
|
}
|
|
6788
7445
|
processResult(data, model, args) {
|
|
6789
7446
|
const result = this.doProcessResult(data, model);
|
|
@@ -6812,7 +7469,7 @@ var ResultProcessor = class {
|
|
|
6812
7469
|
}
|
|
6813
7470
|
if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
|
|
6814
7471
|
if (value) {
|
|
6815
|
-
const subRow = this.
|
|
7472
|
+
const subRow = this.dialect.transformOutput(value, "Json");
|
|
6816
7473
|
const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
|
|
6817
7474
|
const idValues = getIdValues(this.schema, subModel, subRow);
|
|
6818
7475
|
if (Object.values(idValues).some((v) => v === null || v === void 0)) {
|
|
@@ -6846,10 +7503,10 @@ var ResultProcessor = class {
|
|
|
6846
7503
|
processFieldValue(value, fieldDef) {
|
|
6847
7504
|
const type = fieldDef.type;
|
|
6848
7505
|
if (Array.isArray(value)) {
|
|
6849
|
-
value.forEach((v, i) => value[i] = this.
|
|
7506
|
+
value.forEach((v, i) => value[i] = this.dialect.transformOutput(v, type));
|
|
6850
7507
|
return value;
|
|
6851
7508
|
} else {
|
|
6852
|
-
return this.
|
|
7509
|
+
return this.dialect.transformOutput(value, type);
|
|
6853
7510
|
}
|
|
6854
7511
|
}
|
|
6855
7512
|
processRelation(value, fieldDef) {
|
|
@@ -6863,42 +7520,6 @@ var ResultProcessor = class {
|
|
|
6863
7520
|
}
|
|
6864
7521
|
return this.doProcessResult(relationData, fieldDef.type);
|
|
6865
7522
|
}
|
|
6866
|
-
transformScalar(value, type) {
|
|
6867
|
-
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
6868
|
-
return this.transformJson(value);
|
|
6869
|
-
} else {
|
|
6870
|
-
return (0, import_ts_pattern19.match)(type).with("Boolean", () => this.transformBoolean(value)).with("DateTime", () => this.transformDate(value)).with("Bytes", () => this.transformBytes(value)).with("Decimal", () => this.transformDecimal(value)).with("BigInt", () => this.transformBigInt(value)).with("Json", () => this.transformJson(value)).otherwise(() => value);
|
|
6871
|
-
}
|
|
6872
|
-
}
|
|
6873
|
-
transformDecimal(value) {
|
|
6874
|
-
if (value instanceof import_decimal2.default) {
|
|
6875
|
-
return value;
|
|
6876
|
-
}
|
|
6877
|
-
(0, import_common_helpers15.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal2.default, `Expected string, number or Decimal, got ${typeof value}`);
|
|
6878
|
-
return new import_decimal2.default(value);
|
|
6879
|
-
}
|
|
6880
|
-
transformBigInt(value) {
|
|
6881
|
-
if (typeof value === "bigint") {
|
|
6882
|
-
return value;
|
|
6883
|
-
}
|
|
6884
|
-
(0, import_common_helpers15.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
6885
|
-
return BigInt(value);
|
|
6886
|
-
}
|
|
6887
|
-
transformBoolean(value) {
|
|
6888
|
-
return !!value;
|
|
6889
|
-
}
|
|
6890
|
-
transformDate(value) {
|
|
6891
|
-
if (typeof value === "number") {
|
|
6892
|
-
return new Date(value);
|
|
6893
|
-
} else if (typeof value === "string") {
|
|
6894
|
-
return new Date(Date.parse(value));
|
|
6895
|
-
} else {
|
|
6896
|
-
return value;
|
|
6897
|
-
}
|
|
6898
|
-
}
|
|
6899
|
-
transformBytes(value) {
|
|
6900
|
-
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
6901
|
-
}
|
|
6902
7523
|
fixReversedResult(data, model, args) {
|
|
6903
7524
|
if (!data) {
|
|
6904
7525
|
return;
|
|
@@ -6923,12 +7544,6 @@ var ResultProcessor = class {
|
|
|
6923
7544
|
}
|
|
6924
7545
|
}
|
|
6925
7546
|
}
|
|
6926
|
-
transformJson(value) {
|
|
6927
|
-
return (0, import_ts_pattern19.match)(this.schema.provider.type).with("sqlite", () => {
|
|
6928
|
-
(0, import_common_helpers15.invariant)(typeof value === "string", "Expected string, got " + typeof value);
|
|
6929
|
-
return JSON.parse(value);
|
|
6930
|
-
}).otherwise(() => value);
|
|
6931
|
-
}
|
|
6932
7547
|
};
|
|
6933
7548
|
|
|
6934
7549
|
// src/client/client-impl.ts
|
|
@@ -6951,7 +7566,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
6951
7566
|
this.schema = schema;
|
|
6952
7567
|
this.options = options;
|
|
6953
7568
|
this.$schema = schema;
|
|
6954
|
-
this.$options = options
|
|
7569
|
+
this.$options = options;
|
|
6955
7570
|
this.$options.functions = {
|
|
6956
7571
|
...functions_exports,
|
|
6957
7572
|
...this.$options.functions
|
|
@@ -6959,15 +7574,15 @@ var ClientImpl = class _ClientImpl {
|
|
|
6959
7574
|
if (baseClient) {
|
|
6960
7575
|
this.kyselyProps = {
|
|
6961
7576
|
...baseClient.kyselyProps,
|
|
6962
|
-
executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new
|
|
7577
|
+
executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new import_kysely18.DefaultConnectionProvider(baseClient.kyselyProps.driver))
|
|
6963
7578
|
};
|
|
6964
7579
|
this.kyselyRaw = baseClient.kyselyRaw;
|
|
6965
7580
|
this.auth = baseClient.auth;
|
|
6966
7581
|
} else {
|
|
6967
|
-
const driver = new ZenStackDriver(options.dialect.createDriver(), new
|
|
7582
|
+
const driver = new ZenStackDriver(options.dialect.createDriver(), new import_kysely18.Log(this.$options.log ?? []));
|
|
6968
7583
|
const compiler = options.dialect.createQueryCompiler();
|
|
6969
7584
|
const adapter = options.dialect.createAdapter();
|
|
6970
|
-
const connectionProvider = new
|
|
7585
|
+
const connectionProvider = new import_kysely18.DefaultConnectionProvider(driver);
|
|
6971
7586
|
this.kyselyProps = {
|
|
6972
7587
|
config: {
|
|
6973
7588
|
dialect: options.dialect,
|
|
@@ -6977,12 +7592,12 @@ var ClientImpl = class _ClientImpl {
|
|
|
6977
7592
|
driver,
|
|
6978
7593
|
executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
|
|
6979
7594
|
};
|
|
6980
|
-
this.kyselyRaw = new
|
|
7595
|
+
this.kyselyRaw = new import_kysely18.Kysely({
|
|
6981
7596
|
...this.kyselyProps,
|
|
6982
|
-
executor: new
|
|
7597
|
+
executor: new import_kysely18.DefaultQueryExecutor(compiler, adapter, connectionProvider, [])
|
|
6983
7598
|
});
|
|
6984
7599
|
}
|
|
6985
|
-
this.kysely = new
|
|
7600
|
+
this.kysely = new import_kysely18.Kysely(this.kyselyProps);
|
|
6986
7601
|
return createClientProxy(this);
|
|
6987
7602
|
}
|
|
6988
7603
|
get $qb() {
|
|
@@ -7011,7 +7626,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7011
7626
|
}
|
|
7012
7627
|
forceTransaction() {
|
|
7013
7628
|
if (!this.kysely.isTransaction) {
|
|
7014
|
-
this.kysely = new
|
|
7629
|
+
this.kysely = new import_kysely18.Transaction(this.kyselyProps);
|
|
7015
7630
|
}
|
|
7016
7631
|
}
|
|
7017
7632
|
async interactiveTransaction(callback, options) {
|
|
@@ -7118,7 +7733,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7118
7733
|
}
|
|
7119
7734
|
$executeRaw(query, ...values) {
|
|
7120
7735
|
return createZenStackPromise(async () => {
|
|
7121
|
-
const result = await (0,
|
|
7736
|
+
const result = await (0, import_kysely18.sql)(query, ...values).execute(this.kysely);
|
|
7122
7737
|
return Number(result.numAffectedRows ?? 0);
|
|
7123
7738
|
});
|
|
7124
7739
|
}
|
|
@@ -7131,7 +7746,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7131
7746
|
}
|
|
7132
7747
|
$queryRaw(query, ...values) {
|
|
7133
7748
|
return createZenStackPromise(async () => {
|
|
7134
|
-
const result = await (0,
|
|
7749
|
+
const result = await (0, import_kysely18.sql)(query, ...values).execute(this.kysely);
|
|
7135
7750
|
return result.rows;
|
|
7136
7751
|
});
|
|
7137
7752
|
}
|
|
@@ -7143,7 +7758,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7143
7758
|
});
|
|
7144
7759
|
}
|
|
7145
7760
|
createRawCompiledQuery(query, values) {
|
|
7146
|
-
const q =
|
|
7761
|
+
const q = import_kysely18.CompiledQuery.raw(query, values);
|
|
7147
7762
|
return {
|
|
7148
7763
|
...q,
|
|
7149
7764
|
$raw: true
|
|
@@ -7152,7 +7767,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7152
7767
|
};
|
|
7153
7768
|
function createClientProxy(client) {
|
|
7154
7769
|
const inputValidator = new InputValidator(client.$schema);
|
|
7155
|
-
const resultProcessor = new ResultProcessor(client.$schema);
|
|
7770
|
+
const resultProcessor = new ResultProcessor(client.$schema, client.$options);
|
|
7156
7771
|
return new Proxy(client, {
|
|
7157
7772
|
get: /* @__PURE__ */ __name((target, prop, receiver) => {
|
|
7158
7773
|
if (typeof prop === "string" && prop.startsWith("$")) {
|
|
@@ -7270,7 +7885,7 @@ function definePlugin(plugin) {
|
|
|
7270
7885
|
__name(definePlugin, "definePlugin");
|
|
7271
7886
|
|
|
7272
7887
|
// src/client/index.ts
|
|
7273
|
-
var
|
|
7888
|
+
var import_kysely19 = require("kysely");
|
|
7274
7889
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7275
7890
|
0 && (module.exports = {
|
|
7276
7891
|
InputValidationError,
|