@zenstackhq/runtime 3.0.0-beta.4 → 3.0.0-beta.6
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-hoS-Sd87.d.cts → contract-BJce14-p.d.cts} +54 -12
- package/dist/{contract-hoS-Sd87.d.ts → contract-BJce14-p.d.ts} +54 -12
- package/dist/index.cjs +1211 -690
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1049 -528
- package/dist/index.js.map +1 -1
- package/dist/plugins/policy/index.cjs +835 -329
- 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 +736 -241
- package/dist/plugins/policy/index.js.map +1 -1
- package/package.json +11 -8
- package/dist/plugins/policy/plugin.zmodel +0 -33
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
|
-
var
|
|
46
|
-
var
|
|
45
|
+
var import_common_helpers16 = require("@zenstackhq/common-helpers");
|
|
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
|
|
@@ -228,10 +229,19 @@ function requireField(schema, modelOrType, field) {
|
|
|
228
229
|
}
|
|
229
230
|
__name(requireField, "requireField");
|
|
230
231
|
function getIdFields(schema, model) {
|
|
231
|
-
const modelDef =
|
|
232
|
+
const modelDef = getModel(schema, model);
|
|
232
233
|
return modelDef?.idFields;
|
|
233
234
|
}
|
|
234
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");
|
|
235
245
|
function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
236
246
|
const fieldDef = requireField(schema, model, relationField);
|
|
237
247
|
if (!fieldDef?.relation) {
|
|
@@ -345,7 +355,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias, inlineComp
|
|
|
345
355
|
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
346
356
|
}
|
|
347
357
|
return computer(eb, {
|
|
348
|
-
|
|
358
|
+
modelAlias
|
|
349
359
|
});
|
|
350
360
|
}
|
|
351
361
|
}
|
|
@@ -380,7 +390,7 @@ function buildJoinPairs(schema, model, modelAlias, relationField, relationModelA
|
|
|
380
390
|
}
|
|
381
391
|
__name(buildJoinPairs, "buildJoinPairs");
|
|
382
392
|
function makeDefaultOrderBy(schema, model) {
|
|
383
|
-
const idFields =
|
|
393
|
+
const idFields = requireIdFields(schema, model);
|
|
384
394
|
return idFields.map((f) => ({
|
|
385
395
|
[f]: "asc"
|
|
386
396
|
}));
|
|
@@ -419,11 +429,17 @@ function getManyToManyRelation(schema, model, field) {
|
|
|
419
429
|
"A"
|
|
420
430
|
];
|
|
421
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");
|
|
422
436
|
return {
|
|
423
437
|
parentFkName: orderedFK[0],
|
|
438
|
+
parentPKName: modelIdFields[0],
|
|
424
439
|
otherModel: fieldDef.type,
|
|
425
440
|
otherField: fieldDef.relation.opposite,
|
|
426
441
|
otherFkName: orderedFK[1],
|
|
442
|
+
otherPKName: otherIdFields[0],
|
|
427
443
|
joinTable: fieldDef.relation.name ? `_${fieldDef.relation.name}` : `_${sortedModelNames[0]}To${sortedModelNames[1]}`
|
|
428
444
|
};
|
|
429
445
|
} else {
|
|
@@ -462,7 +478,7 @@ function ensureArray(value) {
|
|
|
462
478
|
}
|
|
463
479
|
__name(ensureArray, "ensureArray");
|
|
464
480
|
function extractIdFields(entity, schema, model) {
|
|
465
|
-
const idFields =
|
|
481
|
+
const idFields = requireIdFields(schema, model);
|
|
466
482
|
return extractFields(entity, idFields);
|
|
467
483
|
}
|
|
468
484
|
__name(extractIdFields, "extractIdFields");
|
|
@@ -499,36 +515,95 @@ __name(aggregate, "aggregate");
|
|
|
499
515
|
|
|
500
516
|
// src/client/crud/operations/base.ts
|
|
501
517
|
var import_cuid2 = require("@paralleldrive/cuid2");
|
|
502
|
-
var
|
|
503
|
-
var
|
|
518
|
+
var import_common_helpers10 = require("@zenstackhq/common-helpers");
|
|
519
|
+
var import_kysely10 = require("kysely");
|
|
504
520
|
var import_nanoid = require("nanoid");
|
|
505
521
|
var import_ts_pattern9 = require("ts-pattern");
|
|
506
522
|
var import_ulid = require("ulid");
|
|
507
523
|
var uuid = __toESM(require("uuid"), 1);
|
|
508
524
|
|
|
509
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
|
+
}({});
|
|
510
532
|
var RejectedByPolicyError = class extends Error {
|
|
511
533
|
static {
|
|
512
534
|
__name(this, "RejectedByPolicyError");
|
|
513
535
|
}
|
|
514
536
|
model;
|
|
515
537
|
reason;
|
|
516
|
-
constructor(model, reason) {
|
|
517
|
-
super(
|
|
538
|
+
constructor(model, reason = "no-access", message) {
|
|
539
|
+
super(message ?? `Operation rejected by policy${model ? ": " + model : ""}`), this.model = model, this.reason = reason;
|
|
518
540
|
}
|
|
519
541
|
};
|
|
520
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
|
+
|
|
521
595
|
// src/plugins/policy/policy-handler.ts
|
|
522
|
-
var
|
|
523
|
-
var
|
|
596
|
+
var import_common_helpers7 = require("@zenstackhq/common-helpers");
|
|
597
|
+
var import_kysely8 = require("kysely");
|
|
524
598
|
var import_ts_pattern8 = require("ts-pattern");
|
|
525
599
|
|
|
526
600
|
// src/client/crud/dialects/index.ts
|
|
527
601
|
var import_ts_pattern5 = require("ts-pattern");
|
|
528
602
|
|
|
529
603
|
// src/client/crud/dialects/postgresql.ts
|
|
530
|
-
var
|
|
531
|
-
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");
|
|
532
607
|
var import_ts_pattern3 = require("ts-pattern");
|
|
533
608
|
|
|
534
609
|
// src/client/constants.ts
|
|
@@ -553,8 +628,8 @@ var AGGREGATE_OPERATORS = [
|
|
|
553
628
|
];
|
|
554
629
|
|
|
555
630
|
// src/client/crud/dialects/base-dialect.ts
|
|
556
|
-
var
|
|
557
|
-
var
|
|
631
|
+
var import_common_helpers2 = require("@zenstackhq/common-helpers");
|
|
632
|
+
var import_kysely2 = require("kysely");
|
|
558
633
|
var import_ts_pattern2 = require("ts-pattern");
|
|
559
634
|
|
|
560
635
|
// src/utils/enumerate.ts
|
|
@@ -585,6 +660,9 @@ var BaseCrudDialect = class {
|
|
|
585
660
|
transformPrimitive(value, _type, _forArrayField) {
|
|
586
661
|
return value;
|
|
587
662
|
}
|
|
663
|
+
transformOutput(value, _type) {
|
|
664
|
+
return value;
|
|
665
|
+
}
|
|
588
666
|
// #region common query builders
|
|
589
667
|
buildSelectModel(eb, model, modelAlias) {
|
|
590
668
|
const modelDef = requireModel(this.schema, model);
|
|
@@ -613,7 +691,7 @@ var BaseCrudDialect = class {
|
|
|
613
691
|
if ("distinct" in args && args.distinct) {
|
|
614
692
|
const distinct = ensureArray(args.distinct);
|
|
615
693
|
if (this.supportsDistinctOn) {
|
|
616
|
-
result = result.distinctOn(distinct.map((f) =>
|
|
694
|
+
result = result.distinctOn(distinct.map((f) => import_kysely2.sql.ref(`${modelAlias}.${f}`)));
|
|
617
695
|
} else {
|
|
618
696
|
throw new QueryError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
|
|
619
697
|
}
|
|
@@ -663,7 +741,7 @@ var BaseCrudDialect = class {
|
|
|
663
741
|
buildCursorFilter(model, query, cursor, orderBy, negateOrderBy, modelAlias) {
|
|
664
742
|
const _orderBy = orderBy ?? makeDefaultOrderBy(this.schema, model);
|
|
665
743
|
const orderByItems = ensureArray(_orderBy).flatMap((obj) => Object.entries(obj));
|
|
666
|
-
const eb = (0,
|
|
744
|
+
const eb = (0, import_kysely2.expressionBuilder)();
|
|
667
745
|
const subQueryAlias = `${model}$cursor$sub`;
|
|
668
746
|
const cursorFilter = this.buildFilter(eb, model, subQueryAlias, cursor);
|
|
669
747
|
let result = query;
|
|
@@ -698,7 +776,7 @@ var BaseCrudDialect = class {
|
|
|
698
776
|
if (payload === null) {
|
|
699
777
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
700
778
|
if (ownedByModel && !fieldDef.originModel) {
|
|
701
|
-
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)));
|
|
702
780
|
} else {
|
|
703
781
|
return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
|
|
704
782
|
is: null
|
|
@@ -715,7 +793,7 @@ var BaseCrudDialect = class {
|
|
|
715
793
|
joinAlias
|
|
716
794
|
);
|
|
717
795
|
const filterResultField = `${field}$filter`;
|
|
718
|
-
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));
|
|
719
797
|
const conditions = [];
|
|
720
798
|
if ("is" in payload || "isNot" in payload) {
|
|
721
799
|
if ("is" in payload) {
|
|
@@ -745,24 +823,26 @@ var BaseCrudDialect = class {
|
|
|
745
823
|
}
|
|
746
824
|
buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
|
|
747
825
|
if (payload === null) {
|
|
748
|
-
return eb(
|
|
826
|
+
return eb(import_kysely2.sql.ref(`${modelAlias}.${field}`), "is", null);
|
|
749
827
|
}
|
|
750
828
|
const relationModel = fieldDef.type;
|
|
751
829
|
const relationFilterSelectAlias = `${modelAlias}$${field}$filter`;
|
|
752
830
|
const buildPkFkWhereRefs = /* @__PURE__ */ __name((eb2) => {
|
|
753
831
|
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
754
832
|
if (m2m) {
|
|
755
|
-
const
|
|
756
|
-
|
|
757
|
-
|
|
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]}`)));
|
|
758
838
|
} else {
|
|
759
839
|
const relationKeyPairs = getRelationForeignKeyFieldPairs(this.schema, model, field);
|
|
760
840
|
let result2 = this.true(eb2);
|
|
761
841
|
for (const { fk, pk } of relationKeyPairs.keyPairs) {
|
|
762
842
|
if (relationKeyPairs.ownedByModel) {
|
|
763
|
-
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}`)));
|
|
764
844
|
} else {
|
|
765
|
-
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}`)));
|
|
766
846
|
}
|
|
767
847
|
}
|
|
768
848
|
return result2;
|
|
@@ -845,7 +925,7 @@ var BaseCrudDialect = class {
|
|
|
845
925
|
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
846
926
|
}
|
|
847
927
|
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
848
|
-
if (payload === null || !(0,
|
|
928
|
+
if (payload === null || !(0, import_common_helpers2.isPlainObject)(payload)) {
|
|
849
929
|
return {
|
|
850
930
|
conditions: [
|
|
851
931
|
this.buildLiteralFilter(eb, lhs, type, payload)
|
|
@@ -864,14 +944,14 @@ var BaseCrudDialect = class {
|
|
|
864
944
|
}
|
|
865
945
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
866
946
|
const condition = (0, import_ts_pattern2.match)(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
867
|
-
(0,
|
|
947
|
+
(0, import_common_helpers2.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
868
948
|
if (rhs.length === 0) {
|
|
869
949
|
return this.false(eb);
|
|
870
950
|
} else {
|
|
871
951
|
return eb(lhs, "in", rhs);
|
|
872
952
|
}
|
|
873
953
|
}).with("notIn", () => {
|
|
874
|
-
(0,
|
|
954
|
+
(0, import_common_helpers2.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
875
955
|
if (rhs.length === 0) {
|
|
876
956
|
return this.true(eb);
|
|
877
957
|
} else {
|
|
@@ -911,7 +991,7 @@ var BaseCrudDialect = class {
|
|
|
911
991
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
912
992
|
continue;
|
|
913
993
|
}
|
|
914
|
-
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(() => {
|
|
915
995
|
throw new QueryError(`Invalid string filter key: ${key}`);
|
|
916
996
|
});
|
|
917
997
|
if (condition) {
|
|
@@ -923,16 +1003,16 @@ var BaseCrudDialect = class {
|
|
|
923
1003
|
}
|
|
924
1004
|
prepStringCasing(eb, value, mode) {
|
|
925
1005
|
if (!mode || mode === "default") {
|
|
926
|
-
return value === null ? value :
|
|
1006
|
+
return value === null ? value : import_kysely2.sql.val(value);
|
|
927
1007
|
}
|
|
928
1008
|
if (typeof value === "string") {
|
|
929
1009
|
return eb.fn("lower", [
|
|
930
|
-
|
|
1010
|
+
import_kysely2.sql.val(value)
|
|
931
1011
|
]);
|
|
932
1012
|
} else if (Array.isArray(value)) {
|
|
933
1013
|
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
934
1014
|
} else {
|
|
935
|
-
return value === null ? null :
|
|
1015
|
+
return value === null ? null : import_kysely2.sql.val(value);
|
|
936
1016
|
}
|
|
937
1017
|
}
|
|
938
1018
|
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
@@ -989,19 +1069,19 @@ var BaseCrudDialect = class {
|
|
|
989
1069
|
"_min",
|
|
990
1070
|
"_max"
|
|
991
1071
|
].includes(field)) {
|
|
992
|
-
(0,
|
|
1072
|
+
(0, import_common_helpers2.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
993
1073
|
for (const [k, v] of Object.entries(value)) {
|
|
994
|
-
(0,
|
|
995
|
-
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)));
|
|
996
1076
|
}
|
|
997
1077
|
continue;
|
|
998
1078
|
}
|
|
999
1079
|
switch (field) {
|
|
1000
1080
|
case "_count": {
|
|
1001
|
-
(0,
|
|
1081
|
+
(0, import_common_helpers2.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
|
|
1002
1082
|
for (const [k, v] of Object.entries(value)) {
|
|
1003
|
-
(0,
|
|
1004
|
-
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)));
|
|
1005
1085
|
}
|
|
1006
1086
|
continue;
|
|
1007
1087
|
}
|
|
@@ -1010,11 +1090,11 @@ var BaseCrudDialect = class {
|
|
|
1010
1090
|
}
|
|
1011
1091
|
const fieldDef = requireField(this.schema, model, field);
|
|
1012
1092
|
if (!fieldDef.relation) {
|
|
1013
|
-
const fieldRef = this.fieldRef(model, field, (0,
|
|
1093
|
+
const fieldRef = this.fieldRef(model, field, (0, import_kysely2.expressionBuilder)(), modelAlias);
|
|
1014
1094
|
if (value === "asc" || value === "desc") {
|
|
1015
1095
|
result = result.orderBy(fieldRef, this.negateSort(value, negated));
|
|
1016
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")) {
|
|
1017
|
-
result = result.orderBy(fieldRef,
|
|
1097
|
+
result = result.orderBy(fieldRef, import_kysely2.sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
|
|
1018
1098
|
}
|
|
1019
1099
|
} else {
|
|
1020
1100
|
const relationModel = fieldDef.type;
|
|
@@ -1023,13 +1103,13 @@ var BaseCrudDialect = class {
|
|
|
1023
1103
|
throw new QueryError(`invalid orderBy value for field "${field}"`);
|
|
1024
1104
|
}
|
|
1025
1105
|
if ("_count" in value) {
|
|
1026
|
-
(0,
|
|
1106
|
+
(0, import_common_helpers2.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
1027
1107
|
const sort = this.negateSort(value._count, negated);
|
|
1028
1108
|
result = result.orderBy((eb) => {
|
|
1029
1109
|
const subQueryAlias = `${modelAlias}$orderBy$${field}$count`;
|
|
1030
1110
|
let subQuery = this.buildSelectModel(eb, relationModel, subQueryAlias);
|
|
1031
1111
|
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, subQueryAlias);
|
|
1032
|
-
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)))));
|
|
1033
1113
|
subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
|
|
1034
1114
|
return subQuery;
|
|
1035
1115
|
}, sort);
|
|
@@ -1037,7 +1117,7 @@ var BaseCrudDialect = class {
|
|
|
1037
1117
|
} else {
|
|
1038
1118
|
result = result.leftJoin(relationModel, (join) => {
|
|
1039
1119
|
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
|
|
1040
|
-
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)))));
|
|
1041
1121
|
});
|
|
1042
1122
|
result = this.buildOrderBy(result, fieldDef.type, relationModel, value, false, negated);
|
|
1043
1123
|
}
|
|
@@ -1089,13 +1169,13 @@ var BaseCrudDialect = class {
|
|
|
1089
1169
|
if (fieldDef.computed) {
|
|
1090
1170
|
return query.select((eb) => this.fieldRef(model, field, eb, modelAlias).as(field));
|
|
1091
1171
|
} else if (!fieldDef.originModel) {
|
|
1092
|
-
return query.select(
|
|
1172
|
+
return query.select(import_kysely2.sql.ref(`${modelAlias}.${field}`).as(field));
|
|
1093
1173
|
} else {
|
|
1094
1174
|
return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
|
|
1095
1175
|
}
|
|
1096
1176
|
}
|
|
1097
1177
|
buildDelegateJoin(thisModel, thisModelAlias, otherModelAlias, query) {
|
|
1098
|
-
const idFields =
|
|
1178
|
+
const idFields = requireIdFields(this.schema, thisModel);
|
|
1099
1179
|
query = query.leftJoin(otherModelAlias, (qb) => {
|
|
1100
1180
|
for (const idField of idFields) {
|
|
1101
1181
|
qb = qb.onRef(`${thisModelAlias}.${idField}`, "=", `${otherModelAlias}.${idField}`);
|
|
@@ -1117,10 +1197,16 @@ var BaseCrudDialect = class {
|
|
|
1117
1197
|
for (const [field, value] of Object.entries(selections.select)) {
|
|
1118
1198
|
const fieldDef = requireField(this.schema, model, field);
|
|
1119
1199
|
const fieldModel = fieldDef.type;
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
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
|
+
}
|
|
1124
1210
|
}
|
|
1125
1211
|
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
1126
1212
|
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
@@ -1200,6 +1286,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1200
1286
|
static {
|
|
1201
1287
|
__name(this, "PostgresCrudDialect");
|
|
1202
1288
|
}
|
|
1289
|
+
constructor(schema, options) {
|
|
1290
|
+
super(schema, options);
|
|
1291
|
+
}
|
|
1203
1292
|
get provider() {
|
|
1204
1293
|
return "postgresql";
|
|
1205
1294
|
}
|
|
@@ -1214,9 +1303,41 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1214
1303
|
return value.map((v) => this.transformPrimitive(v, type, false));
|
|
1215
1304
|
}
|
|
1216
1305
|
} else {
|
|
1217
|
-
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);
|
|
1307
|
+
}
|
|
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;
|
|
1218
1336
|
}
|
|
1219
1337
|
}
|
|
1338
|
+
transformOutputBytes(value) {
|
|
1339
|
+
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
1340
|
+
}
|
|
1220
1341
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
1221
1342
|
const relationResultName = `${parentAlias}$${relationField}`;
|
|
1222
1343
|
const joinedQuery = this.buildRelationJSON(model, query, relationField, parentAlias, payload, relationResultName);
|
|
@@ -1247,14 +1368,14 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1247
1368
|
buildRelationJoinFilter(query, model, relationField, relationModel, relationModelAlias, parentAlias) {
|
|
1248
1369
|
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
1249
1370
|
if (m2m) {
|
|
1250
|
-
const parentIds =
|
|
1251
|
-
const relationIds =
|
|
1252
|
-
(0,
|
|
1253
|
-
(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");
|
|
1254
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}`)));
|
|
1255
1376
|
} else {
|
|
1256
1377
|
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, relationField, relationModelAlias);
|
|
1257
|
-
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)))));
|
|
1258
1379
|
}
|
|
1259
1380
|
return query;
|
|
1260
1381
|
}
|
|
@@ -1262,9 +1383,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1262
1383
|
qb = qb.select((eb) => {
|
|
1263
1384
|
const objArgs = this.buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName);
|
|
1264
1385
|
if (relationFieldDef.array) {
|
|
1265
|
-
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");
|
|
1266
1387
|
} else {
|
|
1267
|
-
return
|
|
1388
|
+
return import_kysely3.sql`jsonb_build_object(${import_kysely3.sql.join(objArgs)})`.as("$data");
|
|
1268
1389
|
}
|
|
1269
1390
|
});
|
|
1270
1391
|
return qb;
|
|
@@ -1275,13 +1396,13 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1275
1396
|
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1276
1397
|
if (descendantModels.length > 0) {
|
|
1277
1398
|
objArgs.push(...descendantModels.map((subModel) => [
|
|
1278
|
-
|
|
1399
|
+
import_kysely3.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1279
1400
|
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1280
1401
|
]).flatMap((v) => v));
|
|
1281
1402
|
}
|
|
1282
1403
|
if (payload === true || !payload.select) {
|
|
1283
1404
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
1284
|
-
|
|
1405
|
+
import_kysely3.sql.lit(field),
|
|
1285
1406
|
this.fieldRef(relationModel, field, eb, relationModelAlias, false)
|
|
1286
1407
|
]).flatMap((v) => v));
|
|
1287
1408
|
} else if (payload.select) {
|
|
@@ -1289,14 +1410,14 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1289
1410
|
if (field === "_count") {
|
|
1290
1411
|
const subJson = this.buildCountJson(relationModel, eb, relationModelAlias, value);
|
|
1291
1412
|
return [
|
|
1292
|
-
|
|
1413
|
+
import_kysely3.sql.lit(field),
|
|
1293
1414
|
subJson
|
|
1294
1415
|
];
|
|
1295
1416
|
} else {
|
|
1296
1417
|
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1297
1418
|
const fieldValue = fieldDef.relation ? eb.ref(`${parentResultName}$${field}.$data`) : this.fieldRef(relationModel, field, eb, relationModelAlias, false);
|
|
1298
1419
|
return [
|
|
1299
|
-
|
|
1420
|
+
import_kysely3.sql.lit(field),
|
|
1300
1421
|
fieldValue
|
|
1301
1422
|
];
|
|
1302
1423
|
}
|
|
@@ -1304,7 +1425,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1304
1425
|
}
|
|
1305
1426
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
1306
1427
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
1307
|
-
|
|
1428
|
+
import_kysely3.sql.lit(field),
|
|
1308
1429
|
// reference the synthesized JSON field
|
|
1309
1430
|
eb.ref(`${parentResultName}$${field}.$data`)
|
|
1310
1431
|
]).flatMap((v) => v));
|
|
@@ -1334,7 +1455,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1334
1455
|
}
|
|
1335
1456
|
buildJsonObject(eb, value) {
|
|
1336
1457
|
return eb.fn("jsonb_build_object", Object.entries(value).flatMap(([key, value2]) => [
|
|
1337
|
-
|
|
1458
|
+
import_kysely3.sql.lit(key),
|
|
1338
1459
|
value2
|
|
1339
1460
|
]));
|
|
1340
1461
|
}
|
|
@@ -1362,11 +1483,33 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1362
1483
|
get supportInsertWithDefault() {
|
|
1363
1484
|
return true;
|
|
1364
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
|
+
}
|
|
1365
1507
|
};
|
|
1366
1508
|
|
|
1367
1509
|
// src/client/crud/dialects/sqlite.ts
|
|
1368
|
-
var
|
|
1369
|
-
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");
|
|
1370
1513
|
var import_ts_pattern4 = require("ts-pattern");
|
|
1371
1514
|
var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
1372
1515
|
static {
|
|
@@ -1385,10 +1528,58 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1385
1528
|
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
1386
1529
|
return JSON.stringify(value);
|
|
1387
1530
|
} else {
|
|
1388
|
-
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);
|
|
1389
1532
|
}
|
|
1390
1533
|
}
|
|
1391
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);
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
return value;
|
|
1582
|
+
}
|
|
1392
1583
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
1393
1584
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
1394
1585
|
}
|
|
@@ -1414,13 +1605,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1414
1605
|
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
1415
1606
|
if (descendantModels.length > 0) {
|
|
1416
1607
|
objArgs.push(...descendantModels.map((subModel) => [
|
|
1417
|
-
|
|
1608
|
+
import_kysely4.sql.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
|
|
1418
1609
|
eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
|
|
1419
1610
|
]).flatMap((v) => v));
|
|
1420
1611
|
}
|
|
1421
1612
|
if (payload === true || !payload.select) {
|
|
1422
1613
|
objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
|
|
1423
|
-
|
|
1614
|
+
import_kysely4.sql.lit(field),
|
|
1424
1615
|
this.fieldRef(relationModel, field, eb, subQueryName, false)
|
|
1425
1616
|
]).flatMap((v) => v));
|
|
1426
1617
|
} else if (payload.select) {
|
|
@@ -1428,7 +1619,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1428
1619
|
if (field === "_count") {
|
|
1429
1620
|
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1430
1621
|
return [
|
|
1431
|
-
|
|
1622
|
+
import_kysely4.sql.lit(field),
|
|
1432
1623
|
subJson
|
|
1433
1624
|
];
|
|
1434
1625
|
} else {
|
|
@@ -1436,12 +1627,12 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1436
1627
|
if (fieldDef.relation) {
|
|
1437
1628
|
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1438
1629
|
return [
|
|
1439
|
-
|
|
1630
|
+
import_kysely4.sql.lit(field),
|
|
1440
1631
|
subJson
|
|
1441
1632
|
];
|
|
1442
1633
|
} else {
|
|
1443
1634
|
return [
|
|
1444
|
-
|
|
1635
|
+
import_kysely4.sql.lit(field),
|
|
1445
1636
|
this.fieldRef(relationModel, field, eb, subQueryName, false)
|
|
1446
1637
|
];
|
|
1447
1638
|
}
|
|
@@ -1452,15 +1643,15 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1452
1643
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
1453
1644
|
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1454
1645
|
return [
|
|
1455
|
-
|
|
1646
|
+
import_kysely4.sql.lit(field),
|
|
1456
1647
|
subJson
|
|
1457
1648
|
];
|
|
1458
1649
|
}).flatMap((v) => v));
|
|
1459
1650
|
}
|
|
1460
1651
|
if (relationFieldDef.array) {
|
|
1461
|
-
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");
|
|
1462
1653
|
} else {
|
|
1463
|
-
return
|
|
1654
|
+
return import_kysely4.sql`json_object(${import_kysely4.sql.join(objArgs)})`.as("$data");
|
|
1464
1655
|
}
|
|
1465
1656
|
});
|
|
1466
1657
|
return tbl;
|
|
@@ -1470,10 +1661,10 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1470
1661
|
const relationModel = fieldDef.type;
|
|
1471
1662
|
const m2m = getManyToManyRelation(this.schema, model, relationField);
|
|
1472
1663
|
if (m2m) {
|
|
1473
|
-
const parentIds =
|
|
1474
|
-
const relationIds =
|
|
1475
|
-
(0,
|
|
1476
|
-
(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");
|
|
1477
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}`)));
|
|
1478
1669
|
} else {
|
|
1479
1670
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
@@ -1501,7 +1692,7 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1501
1692
|
}
|
|
1502
1693
|
buildJsonObject(eb, value) {
|
|
1503
1694
|
return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
|
|
1504
|
-
|
|
1695
|
+
import_kysely4.sql.lit(key),
|
|
1505
1696
|
value2
|
|
1506
1697
|
]));
|
|
1507
1698
|
}
|
|
@@ -1525,6 +1716,24 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1525
1716
|
get supportInsertWithDefault() {
|
|
1526
1717
|
return false;
|
|
1527
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
|
+
}
|
|
1528
1737
|
};
|
|
1529
1738
|
|
|
1530
1739
|
// src/client/crud/dialects/index.ts
|
|
@@ -1534,8 +1743,8 @@ function getCrudDialect(schema, options) {
|
|
|
1534
1743
|
__name(getCrudDialect, "getCrudDialect");
|
|
1535
1744
|
|
|
1536
1745
|
// src/utils/default-operation-node-visitor.ts
|
|
1537
|
-
var
|
|
1538
|
-
var DefaultOperationNodeVisitor = class extends
|
|
1746
|
+
var import_kysely5 = require("kysely");
|
|
1747
|
+
var DefaultOperationNodeVisitor = class extends import_kysely5.OperationNodeVisitor {
|
|
1539
1748
|
static {
|
|
1540
1749
|
__name(this, "DefaultOperationNodeVisitor");
|
|
1541
1750
|
}
|
|
@@ -1852,12 +2061,12 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
|
|
|
1852
2061
|
};
|
|
1853
2062
|
|
|
1854
2063
|
// src/plugins/policy/expression-transformer.ts
|
|
1855
|
-
var
|
|
1856
|
-
var
|
|
2064
|
+
var import_common_helpers6 = require("@zenstackhq/common-helpers");
|
|
2065
|
+
var import_kysely7 = require("kysely");
|
|
1857
2066
|
var import_ts_pattern7 = require("ts-pattern");
|
|
1858
2067
|
|
|
1859
2068
|
// src/plugins/policy/expression-evaluator.ts
|
|
1860
|
-
var
|
|
2069
|
+
var import_common_helpers5 = require("@zenstackhq/common-helpers");
|
|
1861
2070
|
var import_ts_pattern6 = require("ts-pattern");
|
|
1862
2071
|
var ExpressionEvaluator = class {
|
|
1863
2072
|
static {
|
|
@@ -1901,18 +2110,18 @@ var ExpressionEvaluator = class {
|
|
|
1901
2110
|
const right = this.evaluate(expr2.right, context);
|
|
1902
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", () => {
|
|
1903
2112
|
const _right = right ?? [];
|
|
1904
|
-
(0,
|
|
2113
|
+
(0, import_common_helpers5.invariant)(Array.isArray(_right), 'expected array for "in" operator');
|
|
1905
2114
|
return _right.includes(left);
|
|
1906
2115
|
}).exhaustive();
|
|
1907
2116
|
}
|
|
1908
2117
|
evaluateCollectionPredicate(expr2, context) {
|
|
1909
2118
|
const op = expr2.op;
|
|
1910
|
-
(0,
|
|
2119
|
+
(0, import_common_helpers5.invariant)(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
|
|
1911
2120
|
const left = this.evaluate(expr2.left, context);
|
|
1912
2121
|
if (!left) {
|
|
1913
2122
|
return false;
|
|
1914
2123
|
}
|
|
1915
|
-
(0,
|
|
2124
|
+
(0, import_common_helpers5.invariant)(Array.isArray(left), "expected array");
|
|
1916
2125
|
return (0, import_ts_pattern6.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
|
|
1917
2126
|
...context,
|
|
1918
2127
|
thisValue: item
|
|
@@ -1927,21 +2136,21 @@ var ExpressionEvaluator = class {
|
|
|
1927
2136
|
};
|
|
1928
2137
|
|
|
1929
2138
|
// src/plugins/policy/utils.ts
|
|
1930
|
-
var
|
|
2139
|
+
var import_kysely6 = require("kysely");
|
|
1931
2140
|
function trueNode(dialect) {
|
|
1932
|
-
return
|
|
2141
|
+
return import_kysely6.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
|
|
1933
2142
|
}
|
|
1934
2143
|
__name(trueNode, "trueNode");
|
|
1935
2144
|
function falseNode(dialect) {
|
|
1936
|
-
return
|
|
2145
|
+
return import_kysely6.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
|
|
1937
2146
|
}
|
|
1938
2147
|
__name(falseNode, "falseNode");
|
|
1939
2148
|
function isTrueNode(node) {
|
|
1940
|
-
return
|
|
2149
|
+
return import_kysely6.ValueNode.is(node) && (node.value === true || node.value === 1);
|
|
1941
2150
|
}
|
|
1942
2151
|
__name(isTrueNode, "isTrueNode");
|
|
1943
2152
|
function isFalseNode(node) {
|
|
1944
|
-
return
|
|
2153
|
+
return import_kysely6.ValueNode.is(node) && (node.value === false || node.value === 0);
|
|
1945
2154
|
}
|
|
1946
2155
|
__name(isFalseNode, "isFalseNode");
|
|
1947
2156
|
function conjunction(dialect, nodes) {
|
|
@@ -1958,7 +2167,7 @@ function conjunction(dialect, nodes) {
|
|
|
1958
2167
|
if (items.length === 0) {
|
|
1959
2168
|
return trueNode(dialect);
|
|
1960
2169
|
}
|
|
1961
|
-
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)));
|
|
1962
2171
|
}
|
|
1963
2172
|
__name(conjunction, "conjunction");
|
|
1964
2173
|
function disjunction(dialect, nodes) {
|
|
@@ -1975,7 +2184,7 @@ function disjunction(dialect, nodes) {
|
|
|
1975
2184
|
if (items.length === 0) {
|
|
1976
2185
|
return falseNode(dialect);
|
|
1977
2186
|
}
|
|
1978
|
-
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)));
|
|
1979
2188
|
}
|
|
1980
2189
|
__name(disjunction, "disjunction");
|
|
1981
2190
|
function logicalNot(dialect, node) {
|
|
@@ -1985,11 +2194,11 @@ function logicalNot(dialect, node) {
|
|
|
1985
2194
|
if (isFalseNode(node)) {
|
|
1986
2195
|
return trueNode(dialect);
|
|
1987
2196
|
}
|
|
1988
|
-
return
|
|
2197
|
+
return import_kysely6.UnaryOperationNode.create(import_kysely6.OperatorNode.create("not"), wrapParensIf(node, (n) => import_kysely6.AndNode.is(n) || import_kysely6.OrNode.is(n)));
|
|
1989
2198
|
}
|
|
1990
2199
|
__name(logicalNot, "logicalNot");
|
|
1991
2200
|
function wrapParensIf(node, predicate) {
|
|
1992
|
-
return predicate(node) ?
|
|
2201
|
+
return predicate(node) ? import_kysely6.ParensNode.create(node) : node;
|
|
1993
2202
|
}
|
|
1994
2203
|
__name(wrapParensIf, "wrapParensIf");
|
|
1995
2204
|
function buildIsFalse(node, dialect) {
|
|
@@ -1998,13 +2207,13 @@ function buildIsFalse(node, dialect) {
|
|
|
1998
2207
|
} else if (isTrueNode(node)) {
|
|
1999
2208
|
return falseNode(dialect);
|
|
2000
2209
|
}
|
|
2001
|
-
return
|
|
2210
|
+
return import_kysely6.BinaryOperationNode.create(
|
|
2002
2211
|
// coalesce so null is treated as false
|
|
2003
|
-
|
|
2212
|
+
import_kysely6.FunctionNode.create("coalesce", [
|
|
2004
2213
|
node,
|
|
2005
2214
|
falseNode(dialect)
|
|
2006
2215
|
]),
|
|
2007
|
-
|
|
2216
|
+
import_kysely6.OperatorNode.create("="),
|
|
2008
2217
|
falseNode(dialect)
|
|
2009
2218
|
);
|
|
2010
2219
|
}
|
|
@@ -2013,11 +2222,11 @@ function getTableName(node) {
|
|
|
2013
2222
|
if (!node) {
|
|
2014
2223
|
return node;
|
|
2015
2224
|
}
|
|
2016
|
-
if (
|
|
2225
|
+
if (import_kysely6.TableNode.is(node)) {
|
|
2017
2226
|
return node.table.identifier.name;
|
|
2018
|
-
} else if (
|
|
2227
|
+
} else if (import_kysely6.AliasNode.is(node)) {
|
|
2019
2228
|
return getTableName(node.node);
|
|
2020
|
-
} else if (
|
|
2229
|
+
} else if (import_kysely6.ReferenceNode.is(node) && node.table) {
|
|
2021
2230
|
return getTableName(node.table);
|
|
2022
2231
|
}
|
|
2023
2232
|
return void 0;
|
|
@@ -2050,16 +2259,21 @@ var ExpressionTransformer = class {
|
|
|
2050
2259
|
static {
|
|
2051
2260
|
__name(this, "ExpressionTransformer");
|
|
2052
2261
|
}
|
|
2053
|
-
|
|
2054
|
-
clientOptions;
|
|
2055
|
-
auth;
|
|
2262
|
+
client;
|
|
2056
2263
|
dialect;
|
|
2057
|
-
constructor(
|
|
2058
|
-
this.
|
|
2059
|
-
this.clientOptions = clientOptions;
|
|
2060
|
-
this.auth = auth;
|
|
2264
|
+
constructor(client) {
|
|
2265
|
+
this.client = client;
|
|
2061
2266
|
this.dialect = getCrudDialect(this.schema, this.clientOptions);
|
|
2062
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
|
+
}
|
|
2063
2277
|
get authType() {
|
|
2064
2278
|
if (!this.schema.authType) {
|
|
2065
2279
|
throw new InternalError('Schema does not have an "authType" specified');
|
|
@@ -2077,7 +2291,7 @@ var ExpressionTransformer = class {
|
|
|
2077
2291
|
return this.transformValue(expr2.value, typeof expr2.value === "string" ? "String" : typeof expr2.value === "boolean" ? "Boolean" : "Int");
|
|
2078
2292
|
}
|
|
2079
2293
|
_array(expr2, context) {
|
|
2080
|
-
return
|
|
2294
|
+
return import_kysely7.ValueListNode.create(expr2.items.map((item) => this.transform(item, context)));
|
|
2081
2295
|
}
|
|
2082
2296
|
_field(expr2, context) {
|
|
2083
2297
|
const fieldDef = requireField(this.schema, context.model, expr2.field);
|
|
@@ -2097,18 +2311,18 @@ var ExpressionTransformer = class {
|
|
|
2097
2311
|
}
|
|
2098
2312
|
mergeWhere(where, memberFilter) {
|
|
2099
2313
|
if (!where) {
|
|
2100
|
-
return
|
|
2314
|
+
return import_kysely7.WhereNode.create(memberFilter ?? trueNode(this.dialect));
|
|
2101
2315
|
}
|
|
2102
2316
|
if (!memberFilter) {
|
|
2103
2317
|
return where;
|
|
2104
2318
|
}
|
|
2105
|
-
return
|
|
2319
|
+
return import_kysely7.WhereNode.create(conjunction(this.dialect, [
|
|
2106
2320
|
where.where,
|
|
2107
2321
|
memberFilter
|
|
2108
2322
|
]));
|
|
2109
2323
|
}
|
|
2110
2324
|
_null() {
|
|
2111
|
-
return
|
|
2325
|
+
return import_kysely7.ValueNode.createImmediate(null);
|
|
2112
2326
|
}
|
|
2113
2327
|
_binary(expr2, context) {
|
|
2114
2328
|
if (expr2.op === "&&") {
|
|
@@ -2129,45 +2343,82 @@ var ExpressionTransformer = class {
|
|
|
2129
2343
|
if (op === "?" || op === "!" || op === "^") {
|
|
2130
2344
|
return this.transformCollectionPredicate(expr2, context);
|
|
2131
2345
|
}
|
|
2132
|
-
const
|
|
2133
|
-
const
|
|
2346
|
+
const { normalizedLeft, normalizedRight } = this.normalizeBinaryOperationOperands(expr2, context);
|
|
2347
|
+
const left = this.transform(normalizedLeft, context);
|
|
2348
|
+
const right = this.transform(normalizedRight, context);
|
|
2134
2349
|
if (op === "in") {
|
|
2135
2350
|
if (this.isNullNode(left)) {
|
|
2136
2351
|
return this.transformValue(false, "Boolean");
|
|
2137
2352
|
} else {
|
|
2138
|
-
if (
|
|
2139
|
-
return
|
|
2353
|
+
if (import_kysely7.ValueListNode.is(right)) {
|
|
2354
|
+
return import_kysely7.BinaryOperationNode.create(left, import_kysely7.OperatorNode.create("in"), right);
|
|
2140
2355
|
} else {
|
|
2141
|
-
return
|
|
2356
|
+
return import_kysely7.BinaryOperationNode.create(left, import_kysely7.OperatorNode.create("="), import_kysely7.FunctionNode.create("any", [
|
|
2142
2357
|
right
|
|
2143
2358
|
]));
|
|
2144
2359
|
}
|
|
2145
2360
|
}
|
|
2146
2361
|
}
|
|
2147
2362
|
if (this.isNullNode(right)) {
|
|
2148
|
-
return
|
|
2363
|
+
return this.transformNullCheck(left, expr2.op);
|
|
2149
2364
|
} else if (this.isNullNode(left)) {
|
|
2150
|
-
return
|
|
2365
|
+
return this.transformNullCheck(right, expr2.op);
|
|
2366
|
+
} else {
|
|
2367
|
+
return import_kysely7.BinaryOperationNode.create(left, this.transformOperator(op), right);
|
|
2368
|
+
}
|
|
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]);
|
|
2151
2398
|
}
|
|
2152
|
-
return
|
|
2399
|
+
return {
|
|
2400
|
+
normalizedLeft,
|
|
2401
|
+
normalizedRight
|
|
2402
|
+
};
|
|
2153
2403
|
}
|
|
2154
2404
|
transformCollectionPredicate(expr2, context) {
|
|
2155
|
-
(0,
|
|
2405
|
+
(0, import_common_helpers6.invariant)(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
|
|
2156
2406
|
if (this.isAuthCall(expr2.left) || this.isAuthMember(expr2.left)) {
|
|
2157
2407
|
const value = new ExpressionEvaluator().evaluate(expr2, {
|
|
2158
2408
|
auth: this.auth
|
|
2159
2409
|
});
|
|
2160
2410
|
return this.transformValue(value, "Boolean");
|
|
2161
2411
|
}
|
|
2162
|
-
(0,
|
|
2412
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
|
|
2163
2413
|
let newContextModel;
|
|
2164
|
-
|
|
2165
|
-
|
|
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)}`);
|
|
2166
2417
|
newContextModel = fieldDef.type;
|
|
2167
2418
|
} else {
|
|
2168
|
-
(0,
|
|
2169
|
-
const
|
|
2170
|
-
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;
|
|
2171
2422
|
for (const member of expr2.left.members) {
|
|
2172
2423
|
const memberDef = requireField(this.schema, newContextModel, member);
|
|
2173
2424
|
newContextModel = memberDef.type;
|
|
@@ -2181,13 +2432,13 @@ var ExpressionTransformer = class {
|
|
|
2181
2432
|
if (expr2.op === "!") {
|
|
2182
2433
|
predicateFilter = logicalNot(this.dialect, predicateFilter);
|
|
2183
2434
|
}
|
|
2184
|
-
const count =
|
|
2185
|
-
|
|
2435
|
+
const count = import_kysely7.FunctionNode.create("count", [
|
|
2436
|
+
import_kysely7.ValueNode.createImmediate(1)
|
|
2186
2437
|
]);
|
|
2187
|
-
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();
|
|
2188
2439
|
return this.transform(expr2.left, {
|
|
2189
2440
|
...context,
|
|
2190
|
-
memberSelect:
|
|
2441
|
+
memberSelect: import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(predicateResult, import_kysely7.IdentifierNode.create("$t"))),
|
|
2191
2442
|
memberFilter: predicateFilter
|
|
2192
2443
|
});
|
|
2193
2444
|
}
|
|
@@ -2212,12 +2463,10 @@ var ExpressionTransformer = class {
|
|
|
2212
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`);
|
|
2213
2464
|
}
|
|
2214
2465
|
const idFields = Object.values(authModel.fields).filter((f) => f.id).map((f) => f.name);
|
|
2215
|
-
(0,
|
|
2466
|
+
(0, import_common_helpers6.invariant)(idFields.length > 0, "auth type model must have at least one id field");
|
|
2216
2467
|
const conditions = idFields.map((fieldName) => ExpressionUtils.binary(ExpressionUtils.member(authExpr, [
|
|
2217
2468
|
fieldName
|
|
2218
|
-
]), "==",
|
|
2219
|
-
fieldName
|
|
2220
|
-
])));
|
|
2469
|
+
]), "==", this.makeOrAppendMember(other, fieldName)));
|
|
2221
2470
|
let result = this.buildAnd(conditions);
|
|
2222
2471
|
if (expr2.op === "!=") {
|
|
2223
2472
|
result = this.buildLogicalNot(result);
|
|
@@ -2225,33 +2474,65 @@ var ExpressionTransformer = class {
|
|
|
2225
2474
|
return this.transform(result, context);
|
|
2226
2475
|
}
|
|
2227
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
|
+
]);
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2228
2489
|
transformValue(value, type) {
|
|
2229
|
-
|
|
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
|
+
}
|
|
2230
2497
|
}
|
|
2231
2498
|
_unary(expr2, context) {
|
|
2232
|
-
(0,
|
|
2499
|
+
(0, import_common_helpers6.invariant)(expr2.op === "!", 'only "!" operator is supported');
|
|
2233
2500
|
return logicalNot(this.dialect, this.transform(expr2.operand, context));
|
|
2234
2501
|
}
|
|
2235
2502
|
transformOperator(op) {
|
|
2236
2503
|
const mappedOp = (0, import_ts_pattern7.match)(op).with("==", () => "=").otherwise(() => op);
|
|
2237
|
-
return
|
|
2504
|
+
return import_kysely7.OperatorNode.create(mappedOp);
|
|
2238
2505
|
}
|
|
2239
2506
|
_call(expr2, context) {
|
|
2240
2507
|
const result = this.transformCall(expr2, context);
|
|
2241
2508
|
return result.toOperationNode();
|
|
2242
2509
|
}
|
|
2243
2510
|
transformCall(expr2, context) {
|
|
2244
|
-
const func = this.
|
|
2511
|
+
const func = this.getFunctionImpl(expr2.function);
|
|
2245
2512
|
if (!func) {
|
|
2246
2513
|
throw new QueryError(`Function not implemented: ${expr2.function}`);
|
|
2247
2514
|
}
|
|
2248
|
-
const eb = (0,
|
|
2515
|
+
const eb = (0, import_kysely7.expressionBuilder)();
|
|
2249
2516
|
return func(eb, (expr2.args ?? []).map((arg) => this.transformCallArg(eb, arg, context)), {
|
|
2517
|
+
client: this.client,
|
|
2250
2518
|
dialect: this.dialect,
|
|
2251
2519
|
model: context.model,
|
|
2520
|
+
modelAlias: context.alias ?? context.model,
|
|
2252
2521
|
operation: context.operation
|
|
2253
2522
|
});
|
|
2254
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
|
+
}
|
|
2255
2536
|
transformCallArg(eb, arg, context) {
|
|
2256
2537
|
if (ExpressionUtils.isLiteral(arg)) {
|
|
2257
2538
|
return eb.val(arg.value);
|
|
@@ -2272,23 +2553,22 @@ var ExpressionTransformer = class {
|
|
|
2272
2553
|
if (this.isAuthCall(expr2.receiver)) {
|
|
2273
2554
|
return this.valueMemberAccess(this.auth, expr2, this.authType);
|
|
2274
2555
|
}
|
|
2275
|
-
(0,
|
|
2556
|
+
(0, import_common_helpers6.invariant)(ExpressionUtils.isField(expr2.receiver) || ExpressionUtils.isThis(expr2.receiver), 'expect receiver to be field expression or "this"');
|
|
2276
2557
|
let members = expr2.members;
|
|
2277
2558
|
let receiver;
|
|
2278
2559
|
const { memberFilter, memberSelect, ...restContext } = context;
|
|
2279
2560
|
if (ExpressionUtils.isThis(expr2.receiver)) {
|
|
2280
2561
|
if (expr2.members.length === 1) {
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
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);
|
|
2284
2567
|
}
|
|
2285
|
-
const firstMemberFieldDef = requireField(this.schema, context.model, expr2.members[0]);
|
|
2286
|
-
receiver = this.transformRelationAccess(expr2.members[0], firstMemberFieldDef.type, restContext);
|
|
2287
|
-
members = expr2.members.slice(1);
|
|
2288
2568
|
} else {
|
|
2289
2569
|
receiver = this.transform(expr2.receiver, restContext);
|
|
2290
2570
|
}
|
|
2291
|
-
(0,
|
|
2571
|
+
(0, import_common_helpers6.invariant)(import_kysely7.SelectQueryNode.is(receiver), "expected receiver to be select query");
|
|
2292
2572
|
let startType;
|
|
2293
2573
|
if (ExpressionUtils.isField(expr2.receiver)) {
|
|
2294
2574
|
const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
|
|
@@ -2317,11 +2597,11 @@ var ExpressionTransformer = class {
|
|
|
2317
2597
|
alias: void 0
|
|
2318
2598
|
});
|
|
2319
2599
|
if (currNode) {
|
|
2320
|
-
(0,
|
|
2600
|
+
(0, import_common_helpers6.invariant)(import_kysely7.SelectQueryNode.is(currNode), "expected select query node");
|
|
2321
2601
|
currNode = {
|
|
2322
2602
|
...relation,
|
|
2323
2603
|
selections: [
|
|
2324
|
-
|
|
2604
|
+
import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(currNode, import_kysely7.IdentifierNode.create(members[i + 1])))
|
|
2325
2605
|
]
|
|
2326
2606
|
};
|
|
2327
2607
|
} else {
|
|
@@ -2334,21 +2614,21 @@ var ExpressionTransformer = class {
|
|
|
2334
2614
|
};
|
|
2335
2615
|
}
|
|
2336
2616
|
} else {
|
|
2337
|
-
(0,
|
|
2338
|
-
(0,
|
|
2339
|
-
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);
|
|
2340
2620
|
}
|
|
2341
2621
|
}
|
|
2342
2622
|
return {
|
|
2343
2623
|
...receiver,
|
|
2344
2624
|
selections: [
|
|
2345
|
-
|
|
2625
|
+
import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(currNode, import_kysely7.IdentifierNode.create("$t")))
|
|
2346
2626
|
]
|
|
2347
2627
|
};
|
|
2348
2628
|
}
|
|
2349
2629
|
valueMemberAccess(receiver, expr2, receiverType) {
|
|
2350
2630
|
if (!receiver) {
|
|
2351
|
-
return
|
|
2631
|
+
return import_kysely7.ValueNode.createImmediate(null);
|
|
2352
2632
|
}
|
|
2353
2633
|
if (expr2.members.length !== 1) {
|
|
2354
2634
|
throw new Error(`Only single member access is supported`);
|
|
@@ -2359,24 +2639,33 @@ var ExpressionTransformer = class {
|
|
|
2359
2639
|
return this.transformValue(fieldValue, fieldDef.type);
|
|
2360
2640
|
}
|
|
2361
2641
|
transformRelationAccess(field, relationModel, context) {
|
|
2642
|
+
const m2m = getManyToManyRelation(this.schema, context.model, field);
|
|
2643
|
+
if (m2m) {
|
|
2644
|
+
return this.transformManyToManyRelationAccess(m2m, context);
|
|
2645
|
+
}
|
|
2362
2646
|
const fromModel = context.model;
|
|
2363
2647
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, fromModel, field);
|
|
2364
2648
|
let condition;
|
|
2365
2649
|
if (ownedByModel) {
|
|
2366
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) =>
|
|
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)))));
|
|
2367
2651
|
} else {
|
|
2368
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) =>
|
|
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)))));
|
|
2369
2653
|
}
|
|
2370
2654
|
return {
|
|
2371
2655
|
kind: "SelectQueryNode",
|
|
2372
|
-
from:
|
|
2373
|
-
|
|
2656
|
+
from: import_kysely7.FromNode.create([
|
|
2657
|
+
import_kysely7.TableNode.create(relationModel)
|
|
2374
2658
|
]),
|
|
2375
|
-
where:
|
|
2659
|
+
where: import_kysely7.WhereNode.create(condition)
|
|
2376
2660
|
};
|
|
2377
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();
|
|
2666
|
+
}
|
|
2378
2667
|
createColumnRef(column, context) {
|
|
2379
|
-
return
|
|
2668
|
+
return import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(column), import_kysely7.TableNode.create(context.alias ?? context.model));
|
|
2380
2669
|
}
|
|
2381
2670
|
isAuthCall(value) {
|
|
2382
2671
|
return ExpressionUtils.isCall(value) && value.function === "auth";
|
|
@@ -2385,7 +2674,7 @@ var ExpressionTransformer = class {
|
|
|
2385
2674
|
return ExpressionUtils.isMember(expr2) && this.isAuthCall(expr2.receiver);
|
|
2386
2675
|
}
|
|
2387
2676
|
isNullNode(node) {
|
|
2388
|
-
return
|
|
2677
|
+
return import_kysely7.ValueNode.is(node) && node.value === null;
|
|
2389
2678
|
}
|
|
2390
2679
|
buildLogicalNot(result) {
|
|
2391
2680
|
return ExpressionUtils.unary("!", result);
|
|
@@ -2399,6 +2688,19 @@ var ExpressionTransformer = class {
|
|
|
2399
2688
|
return conditions.reduce((acc, condition) => ExpressionUtils.binary(acc, "&&", condition));
|
|
2400
2689
|
}
|
|
2401
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
|
+
}
|
|
2703
|
+
}
|
|
2402
2704
|
};
|
|
2403
2705
|
_ts_decorate([
|
|
2404
2706
|
expr("literal"),
|
|
@@ -2470,7 +2772,7 @@ _ts_decorate([
|
|
|
2470
2772
|
], ExpressionTransformer.prototype, "_member", null);
|
|
2471
2773
|
|
|
2472
2774
|
// src/plugins/policy/policy-handler.ts
|
|
2473
|
-
var PolicyHandler = class extends
|
|
2775
|
+
var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
|
|
2474
2776
|
static {
|
|
2475
2777
|
__name(this, "PolicyHandler");
|
|
2476
2778
|
}
|
|
@@ -2485,129 +2787,296 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2485
2787
|
}
|
|
2486
2788
|
async handle(node, proceed) {
|
|
2487
2789
|
if (!this.isCrudQueryNode(node)) {
|
|
2488
|
-
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");
|
|
2489
2791
|
}
|
|
2490
2792
|
if (!this.isMutationQueryNode(node)) {
|
|
2491
2793
|
return proceed(this.transformNode(node));
|
|
2492
2794
|
}
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
if (
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
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);
|
|
2501
2809
|
}
|
|
2502
2810
|
}
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
await this.enforcePreCreatePolicy(node, proceed);
|
|
2508
|
-
}
|
|
2509
|
-
const transformedNode = this.transformNode(node);
|
|
2510
|
-
const result = await proceed(transformedNode);
|
|
2511
|
-
if (!this.onlyReturningId(node)) {
|
|
2811
|
+
const result = await proceed(this.transformNode(node));
|
|
2812
|
+
if (!node.returning || this.onlyReturningId(node)) {
|
|
2813
|
+
return result;
|
|
2814
|
+
} else {
|
|
2512
2815
|
const readBackResult = await this.processReadBack(node, result, proceed);
|
|
2513
2816
|
if (readBackResult.rows.length !== result.rows.length) {
|
|
2514
|
-
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");
|
|
2515
2818
|
}
|
|
2516
2819
|
return readBackResult;
|
|
2517
|
-
}
|
|
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)) {
|
|
2518
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
|
+
};
|
|
2899
|
+
}
|
|
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
|
+
}
|
|
2519
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
|
+
};
|
|
2520
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
|
|
2521
2945
|
onlyReturningId(node) {
|
|
2522
2946
|
if (!node.returning) {
|
|
2523
2947
|
return true;
|
|
2524
2948
|
}
|
|
2525
|
-
const
|
|
2949
|
+
const { mutationModel } = this.getMutationModel(node);
|
|
2950
|
+
const idFields = requireIdFields(this.client.$schema, mutationModel);
|
|
2526
2951
|
const collector = new ColumnCollector();
|
|
2527
2952
|
const selectedColumns = collector.collect(node.returning);
|
|
2528
2953
|
return selectedColumns.every((c) => idFields.includes(c));
|
|
2529
2954
|
}
|
|
2530
|
-
async enforcePreCreatePolicy(node, proceed) {
|
|
2531
|
-
const model = this.getMutationModel(node);
|
|
2955
|
+
async enforcePreCreatePolicy(node, mutationModel, isManyToManyJoinTable, proceed) {
|
|
2532
2956
|
const fields = node.columns?.map((c) => c.column.name) ?? [];
|
|
2533
|
-
const valueRows = node.values ? this.unwrapCreateValueRows(node.values,
|
|
2957
|
+
const valueRows = node.values ? this.unwrapCreateValueRows(node.values, mutationModel, fields, isManyToManyJoinTable) : [
|
|
2534
2958
|
[]
|
|
2535
2959
|
];
|
|
2536
2960
|
for (const values of valueRows) {
|
|
2537
|
-
|
|
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`);
|
|
2538
2999
|
}
|
|
2539
3000
|
}
|
|
2540
3001
|
async enforcePreCreatePolicyForOne(model, fields, values, proceed) {
|
|
2541
|
-
const allFields = Object.
|
|
3002
|
+
const allFields = Object.entries(requireModel(this.client.$schema, model).fields).filter(([, def]) => !def.relation);
|
|
2542
3003
|
const allValues = [];
|
|
2543
|
-
for (const
|
|
2544
|
-
const index = fields.indexOf(
|
|
3004
|
+
for (const [name, _def] of allFields) {
|
|
3005
|
+
const index = fields.indexOf(name);
|
|
2545
3006
|
if (index >= 0) {
|
|
2546
3007
|
allValues.push(values[index]);
|
|
2547
3008
|
} else {
|
|
2548
|
-
allValues.push(
|
|
3009
|
+
allValues.push(import_kysely8.ValueNode.createImmediate(null));
|
|
2549
3010
|
}
|
|
2550
3011
|
}
|
|
3012
|
+
const eb = (0, import_kysely8.expressionBuilder)();
|
|
2551
3013
|
const constTable = {
|
|
2552
3014
|
kind: "SelectQueryNode",
|
|
2553
|
-
from:
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
])),
|
|
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"))
|
|
2557
3019
|
]),
|
|
2558
|
-
selections: allFields.map((
|
|
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
|
+
})
|
|
2559
3024
|
};
|
|
2560
3025
|
const filter = this.buildPolicyFilter(model, void 0, "create");
|
|
2561
3026
|
const preCreateCheck = {
|
|
2562
3027
|
kind: "SelectQueryNode",
|
|
2563
|
-
from:
|
|
2564
|
-
|
|
3028
|
+
from: import_kysely8.FromNode.create([
|
|
3029
|
+
import_kysely8.AliasNode.create(constTable, import_kysely8.IdentifierNode.create(model))
|
|
2565
3030
|
]),
|
|
2566
3031
|
selections: [
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
]),
|
|
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")))
|
|
2570
3035
|
],
|
|
2571
|
-
where:
|
|
3036
|
+
where: import_kysely8.WhereNode.create(filter)
|
|
2572
3037
|
};
|
|
2573
3038
|
const result = await proceed(preCreateCheck);
|
|
2574
3039
|
if (!result.rows[0]?.$condition) {
|
|
2575
3040
|
throw new RejectedByPolicyError(model);
|
|
2576
3041
|
}
|
|
2577
3042
|
}
|
|
2578
|
-
unwrapCreateValueRows(node, model, fields) {
|
|
2579
|
-
if (
|
|
2580
|
-
return node.values.map((v) => this.unwrapCreateValueRow(v.values, model, fields));
|
|
2581
|
-
} 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)) {
|
|
2582
3047
|
return [
|
|
2583
|
-
this.unwrapCreateValueRow(node.values, model, fields)
|
|
3048
|
+
this.unwrapCreateValueRow(node.values, model, fields, isManyToManyJoinTable)
|
|
2584
3049
|
];
|
|
2585
3050
|
} else {
|
|
2586
3051
|
throw new InternalError(`Unexpected node kind: ${node.kind} for unwrapping create values`);
|
|
2587
3052
|
}
|
|
2588
3053
|
}
|
|
2589
|
-
unwrapCreateValueRow(data, model, fields) {
|
|
2590
|
-
(0,
|
|
3054
|
+
unwrapCreateValueRow(data, model, fields, isImplicitManyToManyJoinTable) {
|
|
3055
|
+
(0, import_common_helpers7.invariant)(data.length === fields.length, "data length must match fields length");
|
|
2591
3056
|
const result = [];
|
|
2592
3057
|
for (let i = 0; i < data.length; i++) {
|
|
2593
3058
|
const item = data[i];
|
|
2594
|
-
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
2595
3059
|
if (typeof item === "object" && item && "kind" in item) {
|
|
2596
|
-
|
|
3060
|
+
const fieldDef = requireField(this.client.$schema, model, fields[i]);
|
|
3061
|
+
(0, import_common_helpers7.invariant)(item.kind === "ValueNode", "expecting a ValueNode");
|
|
2597
3062
|
result.push({
|
|
2598
|
-
node:
|
|
3063
|
+
node: import_kysely8.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
|
|
2599
3064
|
raw: item.value
|
|
2600
3065
|
});
|
|
2601
3066
|
} else {
|
|
2602
|
-
|
|
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
|
+
}
|
|
2603
3072
|
if (Array.isArray(value)) {
|
|
2604
3073
|
result.push({
|
|
2605
|
-
node:
|
|
3074
|
+
node: import_kysely8.RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
|
|
2606
3075
|
raw: value
|
|
2607
3076
|
});
|
|
2608
3077
|
} else {
|
|
2609
3078
|
result.push({
|
|
2610
|
-
node:
|
|
3079
|
+
node: import_kysely8.ValueNode.create(value),
|
|
2611
3080
|
raw: value
|
|
2612
3081
|
});
|
|
2613
3082
|
}
|
|
@@ -2643,18 +3112,15 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2643
3112
|
if (!this.isMutationQueryNode(node) || !node.returning) {
|
|
2644
3113
|
return result;
|
|
2645
3114
|
}
|
|
2646
|
-
const
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
}
|
|
2650
|
-
const idConditions = this.buildIdConditions(table, result.rows);
|
|
2651
|
-
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");
|
|
2652
3118
|
const select = {
|
|
2653
3119
|
kind: "SelectQueryNode",
|
|
2654
|
-
from:
|
|
2655
|
-
|
|
3120
|
+
from: import_kysely8.FromNode.create([
|
|
3121
|
+
import_kysely8.TableNode.create(mutationModel)
|
|
2656
3122
|
]),
|
|
2657
|
-
where:
|
|
3123
|
+
where: import_kysely8.WhereNode.create(conjunction(this.dialect, [
|
|
2658
3124
|
idConditions,
|
|
2659
3125
|
policyFilter
|
|
2660
3126
|
])),
|
|
@@ -2664,143 +3130,122 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2664
3130
|
return selectResult;
|
|
2665
3131
|
}
|
|
2666
3132
|
buildIdConditions(table, rows) {
|
|
2667
|
-
const idFields =
|
|
2668
|
-
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]))))));
|
|
2669
3135
|
}
|
|
2670
3136
|
getMutationModel(node) {
|
|
2671
|
-
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) => {
|
|
2672
3150
|
if (node2.from.froms.length !== 1) {
|
|
2673
|
-
throw new
|
|
3151
|
+
throw new QueryError("Only one from table is supported for delete");
|
|
2674
3152
|
}
|
|
2675
|
-
|
|
3153
|
+
const r2 = this.extractTableName(node2.from.froms[0]);
|
|
3154
|
+
return r2 ? {
|
|
3155
|
+
mutationModel: r2.model,
|
|
3156
|
+
alias: r2.alias
|
|
3157
|
+
} : void 0;
|
|
2676
3158
|
}).exhaustive();
|
|
2677
3159
|
if (!r) {
|
|
2678
|
-
throw new InternalError(`Unable to get table name for query node: ${node}`);
|
|
2679
|
-
}
|
|
2680
|
-
return r;
|
|
2681
|
-
}
|
|
2682
|
-
isCrudQueryNode(node) {
|
|
2683
|
-
return import_kysely7.SelectQueryNode.is(node) || import_kysely7.InsertQueryNode.is(node) || import_kysely7.UpdateQueryNode.is(node) || import_kysely7.DeleteQueryNode.is(node);
|
|
2684
|
-
}
|
|
2685
|
-
isMutationQueryNode(node) {
|
|
2686
|
-
return import_kysely7.InsertQueryNode.is(node) || import_kysely7.UpdateQueryNode.is(node) || import_kysely7.DeleteQueryNode.is(node);
|
|
2687
|
-
}
|
|
2688
|
-
buildPolicyFilter(model, alias, operation) {
|
|
2689
|
-
const policies = this.getModelPolicies(model, operation);
|
|
2690
|
-
if (policies.length === 0) {
|
|
2691
|
-
return falseNode(this.dialect);
|
|
2692
|
-
}
|
|
2693
|
-
const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.transformPolicyCondition(model, alias, operation, policy));
|
|
2694
|
-
const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.transformPolicyCondition(model, alias, operation, policy));
|
|
2695
|
-
let combinedPolicy;
|
|
2696
|
-
if (allows.length === 0) {
|
|
2697
|
-
combinedPolicy = falseNode(this.dialect);
|
|
2698
|
-
} else {
|
|
2699
|
-
combinedPolicy = disjunction(this.dialect, allows);
|
|
2700
|
-
if (denies.length !== 0) {
|
|
2701
|
-
const combinedDenies = conjunction(this.dialect, denies.map((d) => buildIsFalse(d, this.dialect)));
|
|
2702
|
-
combinedPolicy = conjunction(this.dialect, [
|
|
2703
|
-
combinedPolicy,
|
|
2704
|
-
combinedDenies
|
|
2705
|
-
]);
|
|
2706
|
-
}
|
|
2707
|
-
}
|
|
2708
|
-
return combinedPolicy;
|
|
2709
|
-
}
|
|
2710
|
-
transformSelectQuery(node) {
|
|
2711
|
-
let whereNode = node.where;
|
|
2712
|
-
node.from?.froms.forEach((from) => {
|
|
2713
|
-
const extractResult = this.extractTableName(from);
|
|
2714
|
-
if (extractResult) {
|
|
2715
|
-
const { model, alias } = extractResult;
|
|
2716
|
-
const filter = this.buildPolicyFilter(model, alias, "read");
|
|
2717
|
-
whereNode = import_kysely7.WhereNode.create(whereNode?.where ? conjunction(this.dialect, [
|
|
2718
|
-
whereNode.where,
|
|
2719
|
-
filter
|
|
2720
|
-
]) : filter);
|
|
2721
|
-
}
|
|
2722
|
-
});
|
|
2723
|
-
const baseResult = super.transformSelectQuery({
|
|
2724
|
-
...node,
|
|
2725
|
-
where: void 0
|
|
2726
|
-
});
|
|
2727
|
-
return {
|
|
2728
|
-
...baseResult,
|
|
2729
|
-
where: whereNode
|
|
2730
|
-
};
|
|
2731
|
-
}
|
|
2732
|
-
transformInsertQuery(node) {
|
|
2733
|
-
const result = super.transformInsertQuery(node);
|
|
2734
|
-
if (!node.returning) {
|
|
2735
|
-
return result;
|
|
2736
|
-
}
|
|
2737
|
-
if (this.onlyReturningId(node)) {
|
|
2738
|
-
return result;
|
|
2739
|
-
} else {
|
|
2740
|
-
const idFields = getIdFields(this.client.$schema, this.getMutationModel(node));
|
|
2741
|
-
return {
|
|
2742
|
-
...result,
|
|
2743
|
-
returning: import_kysely7.ReturningNode.create(idFields.map((field) => import_kysely7.SelectionNode.create(import_kysely7.ColumnNode.create(field))))
|
|
2744
|
-
};
|
|
3160
|
+
throw new InternalError(`Unable to get table name for query node: ${node}`);
|
|
2745
3161
|
}
|
|
3162
|
+
return r;
|
|
2746
3163
|
}
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
const mutationModel = this.getMutationModel(node);
|
|
2750
|
-
const filter = this.buildPolicyFilter(mutationModel, void 0, "update");
|
|
2751
|
-
return {
|
|
2752
|
-
...result,
|
|
2753
|
-
where: import_kysely7.WhereNode.create(result.where ? conjunction(this.dialect, [
|
|
2754
|
-
result.where.where,
|
|
2755
|
-
filter
|
|
2756
|
-
]) : filter)
|
|
2757
|
-
};
|
|
3164
|
+
isCrudQueryNode(node) {
|
|
3165
|
+
return import_kysely8.SelectQueryNode.is(node) || import_kysely8.InsertQueryNode.is(node) || import_kysely8.UpdateQueryNode.is(node) || import_kysely8.DeleteQueryNode.is(node);
|
|
2758
3166
|
}
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
3167
|
+
isMutationQueryNode(node) {
|
|
3168
|
+
return import_kysely8.InsertQueryNode.is(node) || import_kysely8.UpdateQueryNode.is(node) || import_kysely8.DeleteQueryNode.is(node);
|
|
3169
|
+
}
|
|
3170
|
+
buildPolicyFilter(model, alias, operation) {
|
|
3171
|
+
const m2mFilter = this.getModelPolicyFilterForManyToManyJoinTable(model, alias, operation);
|
|
3172
|
+
if (m2mFilter) {
|
|
3173
|
+
return m2mFilter;
|
|
3174
|
+
}
|
|
3175
|
+
const policies = this.getModelPolicies(model, operation);
|
|
3176
|
+
if (policies.length === 0) {
|
|
3177
|
+
return falseNode(this.dialect);
|
|
3178
|
+
}
|
|
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));
|
|
3181
|
+
let combinedPolicy;
|
|
3182
|
+
if (allows.length === 0) {
|
|
3183
|
+
combinedPolicy = falseNode(this.dialect);
|
|
3184
|
+
} else {
|
|
3185
|
+
combinedPolicy = disjunction(this.dialect, allows);
|
|
3186
|
+
if (denies.length !== 0) {
|
|
3187
|
+
const combinedDenies = conjunction(this.dialect, denies.map((d) => buildIsFalse(d, this.dialect)));
|
|
3188
|
+
combinedPolicy = conjunction(this.dialect, [
|
|
3189
|
+
combinedPolicy,
|
|
3190
|
+
combinedDenies
|
|
3191
|
+
]);
|
|
3192
|
+
}
|
|
3193
|
+
}
|
|
3194
|
+
return combinedPolicy;
|
|
2770
3195
|
}
|
|
2771
|
-
extractTableName(
|
|
2772
|
-
if (
|
|
3196
|
+
extractTableName(node) {
|
|
3197
|
+
if (import_kysely8.TableNode.is(node)) {
|
|
2773
3198
|
return {
|
|
2774
|
-
model:
|
|
3199
|
+
model: node.table.identifier.name
|
|
2775
3200
|
};
|
|
2776
3201
|
}
|
|
2777
|
-
if (
|
|
2778
|
-
const inner = this.extractTableName(
|
|
3202
|
+
if (import_kysely8.AliasNode.is(node)) {
|
|
3203
|
+
const inner = this.extractTableName(node.node);
|
|
2779
3204
|
if (!inner) {
|
|
2780
3205
|
return void 0;
|
|
2781
3206
|
}
|
|
2782
3207
|
return {
|
|
2783
3208
|
model: inner.model,
|
|
2784
|
-
alias:
|
|
3209
|
+
alias: import_kysely8.IdentifierNode.is(node.alias) ? node.alias.name : void 0
|
|
2785
3210
|
};
|
|
2786
3211
|
} else {
|
|
2787
3212
|
return void 0;
|
|
2788
3213
|
}
|
|
2789
3214
|
}
|
|
2790
|
-
|
|
2791
|
-
|
|
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, {
|
|
2792
3237
|
model,
|
|
2793
3238
|
alias,
|
|
2794
3239
|
operation,
|
|
2795
3240
|
auth: this.client.$auth
|
|
2796
3241
|
});
|
|
2797
3242
|
}
|
|
2798
|
-
getModelPolicies(
|
|
2799
|
-
const modelDef = requireModel(this.client.$schema,
|
|
3243
|
+
getModelPolicies(model, operation) {
|
|
3244
|
+
const modelDef = requireModel(this.client.$schema, model);
|
|
2800
3245
|
const result = [];
|
|
2801
3246
|
const extractOperations = /* @__PURE__ */ __name((expr2) => {
|
|
2802
|
-
(0,
|
|
2803
|
-
(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");
|
|
2804
3249
|
return expr2.value.split(",").filter((v) => !!v).map((v) => v.trim());
|
|
2805
3250
|
}, "extractOperations");
|
|
2806
3251
|
if (modelDef.attributes) {
|
|
@@ -2812,8 +3257,84 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2812
3257
|
}
|
|
2813
3258
|
return result;
|
|
2814
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
|
+
}
|
|
2815
3312
|
};
|
|
2816
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
|
+
|
|
2817
3338
|
// src/plugins/policy/plugin.ts
|
|
2818
3339
|
var PolicyPlugin = class {
|
|
2819
3340
|
static {
|
|
@@ -2828,6 +3349,11 @@ var PolicyPlugin = class {
|
|
|
2828
3349
|
get description() {
|
|
2829
3350
|
return "Enforces access policies defined in the schema.";
|
|
2830
3351
|
}
|
|
3352
|
+
get functions() {
|
|
3353
|
+
return {
|
|
3354
|
+
check
|
|
3355
|
+
};
|
|
3356
|
+
}
|
|
2831
3357
|
onKyselyQuery({
|
|
2832
3358
|
query,
|
|
2833
3359
|
client,
|
|
@@ -2844,13 +3370,13 @@ var PolicyPlugin = class {
|
|
|
2844
3370
|
};
|
|
2845
3371
|
|
|
2846
3372
|
// src/utils/clone.ts
|
|
2847
|
-
var
|
|
3373
|
+
var import_common_helpers9 = require("@zenstackhq/common-helpers");
|
|
2848
3374
|
function clone(value) {
|
|
2849
3375
|
if (Array.isArray(value)) {
|
|
2850
3376
|
return value.map((v) => clone(v));
|
|
2851
3377
|
}
|
|
2852
3378
|
if (typeof value === "object") {
|
|
2853
|
-
if (!value || !(0,
|
|
3379
|
+
if (!value || !(0, import_common_helpers9.isPlainObject)(value)) {
|
|
2854
3380
|
return value;
|
|
2855
3381
|
}
|
|
2856
3382
|
const result = {};
|
|
@@ -2863,16 +3389,6 @@ function clone(value) {
|
|
|
2863
3389
|
}
|
|
2864
3390
|
__name(clone, "clone");
|
|
2865
3391
|
|
|
2866
|
-
// src/client/contract.ts
|
|
2867
|
-
var TransactionIsolationLevel = /* @__PURE__ */ function(TransactionIsolationLevel2) {
|
|
2868
|
-
TransactionIsolationLevel2["ReadUncommitted"] = "read uncommitted";
|
|
2869
|
-
TransactionIsolationLevel2["ReadCommitted"] = "read committed";
|
|
2870
|
-
TransactionIsolationLevel2["RepeatableRead"] = "repeatable read";
|
|
2871
|
-
TransactionIsolationLevel2["Serializable"] = "serializable";
|
|
2872
|
-
TransactionIsolationLevel2["Snapshot"] = "snapshot";
|
|
2873
|
-
return TransactionIsolationLevel2;
|
|
2874
|
-
}({});
|
|
2875
|
-
|
|
2876
3392
|
// src/client/crud/operations/base.ts
|
|
2877
3393
|
var BaseOperationHandler = class {
|
|
2878
3394
|
static {
|
|
@@ -2917,7 +3433,7 @@ var BaseOperationHandler = class {
|
|
|
2917
3433
|
return getField(this.schema, model, field);
|
|
2918
3434
|
}
|
|
2919
3435
|
async exists(kysely, model, filter) {
|
|
2920
|
-
const idFields =
|
|
3436
|
+
const idFields = requireIdFields(this.schema, model);
|
|
2921
3437
|
const _filter = flattenCompoundUniqueFilters(this.schema, model, filter);
|
|
2922
3438
|
const query = kysely.selectFrom(model).where((eb) => eb.and(_filter)).select(idFields.map((f) => kysely.dynamic.ref(f))).limit(1).modifyEnd(this.makeContextComment({
|
|
2923
3439
|
model,
|
|
@@ -2926,7 +3442,7 @@ var BaseOperationHandler = class {
|
|
|
2926
3442
|
return this.executeQueryTakeFirst(kysely, query, "exists");
|
|
2927
3443
|
}
|
|
2928
3444
|
async read(kysely, model, args) {
|
|
2929
|
-
let query = this.dialect.buildSelectModel((0,
|
|
3445
|
+
let query = this.dialect.buildSelectModel((0, import_kysely10.expressionBuilder)(), model, model);
|
|
2930
3446
|
if (args) {
|
|
2931
3447
|
query = this.dialect.buildFilterSortTake(model, args, query, model);
|
|
2932
3448
|
}
|
|
@@ -3005,7 +3521,7 @@ var BaseOperationHandler = class {
|
|
|
3005
3521
|
if (!m2m) {
|
|
3006
3522
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation?.model ?? "", fromRelation?.field ?? "");
|
|
3007
3523
|
if (!ownedByModel) {
|
|
3008
|
-
const parentFkFields = this.buildFkAssignments(fromRelation.model, fromRelation.field, fromRelation.ids);
|
|
3524
|
+
const parentFkFields = await this.buildFkAssignments(kysely, fromRelation.model, fromRelation.field, fromRelation.ids);
|
|
3009
3525
|
Object.assign(createFields, parentFkFields);
|
|
3010
3526
|
} else {
|
|
3011
3527
|
updateParent = /* @__PURE__ */ __name((entity) => {
|
|
@@ -3045,17 +3561,16 @@ var BaseOperationHandler = class {
|
|
|
3045
3561
|
createFields = baseCreateResult.remainingFields;
|
|
3046
3562
|
}
|
|
3047
3563
|
const updatedData = this.fillGeneratedAndDefaultValues(modelDef, createFields);
|
|
3048
|
-
const idFields =
|
|
3564
|
+
const idFields = requireIdFields(this.schema, model);
|
|
3049
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({
|
|
3050
3566
|
model,
|
|
3051
3567
|
operation: "create"
|
|
3052
3568
|
}));
|
|
3053
3569
|
const createdEntity = await this.executeQueryTakeFirst(kysely, query, "create");
|
|
3054
3570
|
if (Object.keys(postCreateRelations).length > 0) {
|
|
3055
|
-
const
|
|
3056
|
-
|
|
3057
|
-
}
|
|
3058
|
-
await Promise.all(relationPromises);
|
|
3571
|
+
for (const [field, subPayload] of Object.entries(postCreateRelations)) {
|
|
3572
|
+
await this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
|
|
3573
|
+
}
|
|
3059
3574
|
}
|
|
3060
3575
|
if (fromRelation && m2m) {
|
|
3061
3576
|
await this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, createdEntity, m2m.joinTable);
|
|
@@ -3077,7 +3592,7 @@ var BaseOperationHandler = class {
|
|
|
3077
3592
|
}
|
|
3078
3593
|
});
|
|
3079
3594
|
const discriminatorField = getDiscriminatorField(this.schema, model);
|
|
3080
|
-
(0,
|
|
3595
|
+
(0, import_common_helpers10.invariant)(discriminatorField, `Base model "${model}" must have a discriminator field`);
|
|
3081
3596
|
thisCreateFields[discriminatorField] = forModel;
|
|
3082
3597
|
const baseEntity = await this.create(kysely, model, thisCreateFields, void 0, true);
|
|
3083
3598
|
const idValues = extractIdFields(baseEntity, this.schema, model);
|
|
@@ -3087,14 +3602,24 @@ var BaseOperationHandler = class {
|
|
|
3087
3602
|
remainingFields
|
|
3088
3603
|
};
|
|
3089
3604
|
}
|
|
3090
|
-
buildFkAssignments(model, relationField, entity) {
|
|
3605
|
+
async buildFkAssignments(kysely, model, relationField, entity) {
|
|
3091
3606
|
const parentFkFields = {};
|
|
3092
|
-
(0,
|
|
3093
|
-
(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");
|
|
3094
3609
|
const { keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
3095
3610
|
for (const pair of keyPairs) {
|
|
3096
3611
|
if (!(pair.pk in entity)) {
|
|
3097
|
-
|
|
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
|
+
}
|
|
3098
3623
|
}
|
|
3099
3624
|
Object.assign(parentFkFields, {
|
|
3100
3625
|
[pair.fk]: entity[pair.pk]
|
|
@@ -3115,15 +3640,15 @@ var BaseOperationHandler = class {
|
|
|
3115
3640
|
entity: rightEntity
|
|
3116
3641
|
}
|
|
3117
3642
|
].sort((a, b) => (
|
|
3118
|
-
// the
|
|
3643
|
+
// the implicit m2m join table's "A", "B" fk fields' order is determined
|
|
3119
3644
|
// by model name's sort order, and when identical (for self-relations),
|
|
3120
3645
|
// field name's sort order
|
|
3121
3646
|
a.model !== b.model ? a.model.localeCompare(b.model) : a.field.localeCompare(b.field)
|
|
3122
3647
|
));
|
|
3123
|
-
const firstIds =
|
|
3124
|
-
const secondIds =
|
|
3125
|
-
(0,
|
|
3126
|
-
(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");
|
|
3127
3652
|
if (action === "connect") {
|
|
3128
3653
|
const result = await kysely.insertInto(joinTable).values({
|
|
3129
3654
|
A: sortedRecords[0].entity[firstIds[0]],
|
|
@@ -3134,17 +3659,17 @@ var BaseOperationHandler = class {
|
|
|
3134
3659
|
]).doNothing()).execute();
|
|
3135
3660
|
return result[0];
|
|
3136
3661
|
} else {
|
|
3137
|
-
const eb = (0,
|
|
3662
|
+
const eb = (0, import_kysely10.expressionBuilder)();
|
|
3138
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();
|
|
3139
3664
|
return result[0];
|
|
3140
3665
|
}
|
|
3141
3666
|
}
|
|
3142
3667
|
resetManyToManyRelation(kysely, model, field, parentIds) {
|
|
3143
|
-
(0,
|
|
3668
|
+
(0, import_common_helpers10.invariant)(Object.keys(parentIds).length === 1, "parentIds must have exactly one field");
|
|
3144
3669
|
const parentId = Object.values(parentIds)[0];
|
|
3145
3670
|
const m2m = getManyToManyRelation(this.schema, model, field);
|
|
3146
|
-
(0,
|
|
3147
|
-
const eb = (0,
|
|
3671
|
+
(0, import_common_helpers10.invariant)(m2m, "not a many-to-many relation");
|
|
3672
|
+
const eb = (0, import_kysely10.expressionBuilder)();
|
|
3148
3673
|
return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
|
|
3149
3674
|
}
|
|
3150
3675
|
async processOwnedRelationForCreate(kysely, relationField, payload) {
|
|
@@ -3165,7 +3690,7 @@ var BaseOperationHandler = class {
|
|
|
3165
3690
|
}
|
|
3166
3691
|
case "connect": {
|
|
3167
3692
|
const referencedPkFields = relationField.relation.references;
|
|
3168
|
-
(0,
|
|
3693
|
+
(0, import_common_helpers10.invariant)(referencedPkFields, "relation must have fields info");
|
|
3169
3694
|
const extractedFks = extractFields(subPayload, referencedPkFields);
|
|
3170
3695
|
if (Object.keys(extractedFks).length === referencedPkFields.length) {
|
|
3171
3696
|
result = extractedFks;
|
|
@@ -3197,10 +3722,9 @@ var BaseOperationHandler = class {
|
|
|
3197
3722
|
}
|
|
3198
3723
|
return result;
|
|
3199
3724
|
}
|
|
3200
|
-
processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
|
|
3725
|
+
async processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
|
|
3201
3726
|
const relationFieldDef = this.requireField(contextModel, relationFieldName);
|
|
3202
3727
|
const relationModel = relationFieldDef.type;
|
|
3203
|
-
const tasks = [];
|
|
3204
3728
|
const fromRelationContext = {
|
|
3205
3729
|
model: contextModel,
|
|
3206
3730
|
field: relationFieldName,
|
|
@@ -3213,27 +3737,35 @@ var BaseOperationHandler = class {
|
|
|
3213
3737
|
}
|
|
3214
3738
|
switch (action) {
|
|
3215
3739
|
case "create": {
|
|
3216
|
-
|
|
3740
|
+
for (const item of enumerate(subPayload)) {
|
|
3741
|
+
await this.create(kysely, relationModel, item, fromRelationContext);
|
|
3742
|
+
}
|
|
3217
3743
|
break;
|
|
3218
3744
|
}
|
|
3219
3745
|
case "createMany": {
|
|
3220
|
-
(0,
|
|
3221
|
-
|
|
3746
|
+
(0, import_common_helpers10.invariant)(relationFieldDef.array, "relation must be an array for createMany");
|
|
3747
|
+
await this.createMany(kysely, relationModel, subPayload, false, fromRelationContext);
|
|
3222
3748
|
break;
|
|
3223
3749
|
}
|
|
3224
3750
|
case "connect": {
|
|
3225
|
-
|
|
3751
|
+
await this.connectRelation(kysely, relationModel, subPayload, fromRelationContext);
|
|
3226
3752
|
break;
|
|
3227
3753
|
}
|
|
3228
3754
|
case "connectOrCreate": {
|
|
3229
|
-
|
|
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
|
+
}
|
|
3230
3763
|
break;
|
|
3231
3764
|
}
|
|
3232
3765
|
default:
|
|
3233
3766
|
throw new QueryError(`Invalid relation action: ${action}`);
|
|
3234
3767
|
}
|
|
3235
3768
|
}
|
|
3236
|
-
return Promise.all(tasks);
|
|
3237
3769
|
}
|
|
3238
3770
|
async createMany(kysely, model, input, returnData, fromRelation) {
|
|
3239
3771
|
if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
|
|
@@ -3254,7 +3786,7 @@ var BaseOperationHandler = class {
|
|
|
3254
3786
|
const newItem = {};
|
|
3255
3787
|
for (const [name, value] of Object.entries(item)) {
|
|
3256
3788
|
const fieldDef = this.requireField(model, name);
|
|
3257
|
-
(0,
|
|
3789
|
+
(0, import_common_helpers10.invariant)(!fieldDef.relation, "createMany does not support relations");
|
|
3258
3790
|
newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
|
|
3259
3791
|
}
|
|
3260
3792
|
if (fromRelation) {
|
|
@@ -3304,7 +3836,7 @@ var BaseOperationHandler = class {
|
|
|
3304
3836
|
count: Number(result.numAffectedRows)
|
|
3305
3837
|
};
|
|
3306
3838
|
} else {
|
|
3307
|
-
const idFields =
|
|
3839
|
+
const idFields = requireIdFields(this.schema, model);
|
|
3308
3840
|
const result = await query.returning(idFields).execute();
|
|
3309
3841
|
return result;
|
|
3310
3842
|
}
|
|
@@ -3313,7 +3845,7 @@ var BaseOperationHandler = class {
|
|
|
3313
3845
|
const thisCreateRows = [];
|
|
3314
3846
|
const remainingFieldRows = [];
|
|
3315
3847
|
const discriminatorField = getDiscriminatorField(this.schema, model);
|
|
3316
|
-
(0,
|
|
3848
|
+
(0, import_common_helpers10.invariant)(discriminatorField, `Base model "${model}" must have a discriminator field`);
|
|
3317
3849
|
for (const createFields of createRows) {
|
|
3318
3850
|
const thisCreateFields = {};
|
|
3319
3851
|
const remainingFields = {};
|
|
@@ -3409,7 +3941,7 @@ var BaseOperationHandler = class {
|
|
|
3409
3941
|
}
|
|
3410
3942
|
} else {
|
|
3411
3943
|
const fromRelationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3412
|
-
(0,
|
|
3944
|
+
(0, import_common_helpers10.invariant)(fromRelationFieldDef.relation?.opposite);
|
|
3413
3945
|
parentWhere[fromRelationFieldDef.relation.opposite] = {
|
|
3414
3946
|
some: fromRelation.ids
|
|
3415
3947
|
};
|
|
@@ -3467,10 +3999,7 @@ var BaseOperationHandler = class {
|
|
|
3467
3999
|
throw new QueryError(`Relation update not allowed for field "${field}"`);
|
|
3468
4000
|
}
|
|
3469
4001
|
if (!thisEntity) {
|
|
3470
|
-
thisEntity = await this.
|
|
3471
|
-
where: combinedWhere,
|
|
3472
|
-
select: this.makeIdSelect(model)
|
|
3473
|
-
});
|
|
4002
|
+
thisEntity = await this.getEntityIds(kysely, model, combinedWhere);
|
|
3474
4003
|
if (!thisEntity) {
|
|
3475
4004
|
if (throwIfNotFound) {
|
|
3476
4005
|
throw new NotFoundError(model);
|
|
@@ -3488,7 +4017,7 @@ var BaseOperationHandler = class {
|
|
|
3488
4017
|
if (Object.keys(updateFields).length === 0) {
|
|
3489
4018
|
return combinedWhere;
|
|
3490
4019
|
} else {
|
|
3491
|
-
const idFields =
|
|
4020
|
+
const idFields = requireIdFields(this.schema, model);
|
|
3492
4021
|
const query = kysely.updateTable(model).where((eb) => this.dialect.buildFilter(eb, model, model, combinedWhere)).set(updateFields).returning(idFields).modifyEnd(this.makeContextComment({
|
|
3493
4022
|
model,
|
|
3494
4023
|
operation: "update"
|
|
@@ -3533,7 +4062,7 @@ var BaseOperationHandler = class {
|
|
|
3533
4062
|
if (!filter || typeof filter !== "object") {
|
|
3534
4063
|
return false;
|
|
3535
4064
|
}
|
|
3536
|
-
const idFields =
|
|
4065
|
+
const idFields = requireIdFields(this.schema, model);
|
|
3537
4066
|
return idFields.length === Object.keys(filter).length && idFields.every((field) => field in filter);
|
|
3538
4067
|
}
|
|
3539
4068
|
async processBaseModelUpdate(kysely, model, where, updateFields, throwIfNotFound) {
|
|
@@ -3554,20 +4083,20 @@ var BaseOperationHandler = class {
|
|
|
3554
4083
|
};
|
|
3555
4084
|
}
|
|
3556
4085
|
transformIncrementalUpdate(model, field, fieldDef, payload) {
|
|
3557
|
-
(0,
|
|
4086
|
+
(0, import_common_helpers10.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
|
|
3558
4087
|
const key = Object.keys(payload)[0];
|
|
3559
4088
|
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
|
|
3560
|
-
const eb = (0,
|
|
4089
|
+
const eb = (0, import_kysely10.expressionBuilder)();
|
|
3561
4090
|
const fieldRef = this.dialect.fieldRef(model, field, eb);
|
|
3562
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(() => {
|
|
3563
4092
|
throw new InternalError(`Invalid incremental update operation: ${key}`);
|
|
3564
4093
|
});
|
|
3565
4094
|
}
|
|
3566
4095
|
transformScalarListUpdate(model, field, fieldDef, payload) {
|
|
3567
|
-
(0,
|
|
4096
|
+
(0, import_common_helpers10.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
|
|
3568
4097
|
const key = Object.keys(payload)[0];
|
|
3569
4098
|
const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
|
|
3570
|
-
const eb = (0,
|
|
4099
|
+
const eb = (0, import_kysely10.expressionBuilder)();
|
|
3571
4100
|
const fieldRef = this.dialect.fieldRef(model, field, eb);
|
|
3572
4101
|
return (0, import_ts_pattern9.match)(key).with("set", () => value).with("push", () => {
|
|
3573
4102
|
return eb(fieldRef, "||", eb.val(ensureArray(value)));
|
|
@@ -3579,7 +4108,7 @@ var BaseOperationHandler = class {
|
|
|
3579
4108
|
return NUMERIC_FIELD_TYPES.includes(fieldDef.type) && !fieldDef.array;
|
|
3580
4109
|
}
|
|
3581
4110
|
makeContextComment(_context) {
|
|
3582
|
-
return
|
|
4111
|
+
return import_kysely10.sql``;
|
|
3583
4112
|
}
|
|
3584
4113
|
async updateMany(kysely, model, where, data, limit, returnData, filterModel) {
|
|
3585
4114
|
if (typeof data !== "object") {
|
|
@@ -3638,7 +4167,7 @@ var BaseOperationHandler = class {
|
|
|
3638
4167
|
count: Number(result.numAffectedRows)
|
|
3639
4168
|
};
|
|
3640
4169
|
} else {
|
|
3641
|
-
const idFields =
|
|
4170
|
+
const idFields = requireIdFields(this.schema, model);
|
|
3642
4171
|
const result = await query.returning(idFields).execute();
|
|
3643
4172
|
return result;
|
|
3644
4173
|
}
|
|
@@ -3661,11 +4190,10 @@ var BaseOperationHandler = class {
|
|
|
3661
4190
|
};
|
|
3662
4191
|
}
|
|
3663
4192
|
buildIdFieldRefs(kysely, model) {
|
|
3664
|
-
const idFields =
|
|
4193
|
+
const idFields = requireIdFields(this.schema, model);
|
|
3665
4194
|
return idFields.map((f) => kysely.dynamic.ref(`${model}.${f}`));
|
|
3666
4195
|
}
|
|
3667
4196
|
async processRelationUpdates(kysely, model, field, fieldDef, parentIds, args, throwIfNotFound) {
|
|
3668
|
-
const tasks = [];
|
|
3669
4197
|
const fieldModel = fieldDef.type;
|
|
3670
4198
|
const fromRelationContext = {
|
|
3671
4199
|
model,
|
|
@@ -3676,68 +4204,73 @@ var BaseOperationHandler = class {
|
|
|
3676
4204
|
for (const [key, value] of Object.entries(args)) {
|
|
3677
4205
|
switch (key) {
|
|
3678
4206
|
case "create": {
|
|
3679
|
-
(0,
|
|
3680
|
-
|
|
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
|
+
}
|
|
3681
4211
|
break;
|
|
3682
4212
|
}
|
|
3683
4213
|
case "createMany": {
|
|
3684
|
-
(0,
|
|
3685
|
-
|
|
4214
|
+
(0, import_common_helpers10.invariant)(fieldDef.array, "relation must be an array for createMany");
|
|
4215
|
+
await this.createMany(kysely, fieldModel, value, false, fromRelationContext);
|
|
3686
4216
|
break;
|
|
3687
4217
|
}
|
|
3688
4218
|
case "connect": {
|
|
3689
|
-
|
|
4219
|
+
await this.connectRelation(kysely, fieldModel, value, fromRelationContext);
|
|
3690
4220
|
break;
|
|
3691
4221
|
}
|
|
3692
4222
|
case "connectOrCreate": {
|
|
3693
|
-
|
|
4223
|
+
await this.connectOrCreateRelation(kysely, fieldModel, value, fromRelationContext);
|
|
3694
4224
|
break;
|
|
3695
4225
|
}
|
|
3696
4226
|
case "disconnect": {
|
|
3697
|
-
|
|
4227
|
+
await this.disconnectRelation(kysely, fieldModel, value, fromRelationContext);
|
|
3698
4228
|
break;
|
|
3699
4229
|
}
|
|
3700
4230
|
case "set": {
|
|
3701
|
-
(0,
|
|
3702
|
-
|
|
4231
|
+
(0, import_common_helpers10.invariant)(fieldDef.array, "relation must be an array");
|
|
4232
|
+
await this.setRelation(kysely, fieldModel, value, fromRelationContext);
|
|
3703
4233
|
break;
|
|
3704
4234
|
}
|
|
3705
4235
|
case "update": {
|
|
3706
|
-
|
|
4236
|
+
for (const _item of enumerate(value)) {
|
|
4237
|
+
const item = _item;
|
|
3707
4238
|
let where;
|
|
3708
4239
|
let data;
|
|
3709
|
-
if ("
|
|
4240
|
+
if ("data" in item && typeof item.data === "object") {
|
|
3710
4241
|
where = item.where;
|
|
3711
4242
|
data = item.data;
|
|
3712
4243
|
} else {
|
|
3713
4244
|
where = void 0;
|
|
3714
4245
|
data = item;
|
|
3715
4246
|
}
|
|
3716
|
-
|
|
3717
|
-
}
|
|
4247
|
+
await this.update(kysely, fieldModel, where, data, fromRelationContext, true, throwIfNotFound);
|
|
4248
|
+
}
|
|
3718
4249
|
break;
|
|
3719
4250
|
}
|
|
3720
4251
|
case "upsert": {
|
|
3721
|
-
|
|
4252
|
+
for (const _item of enumerate(value)) {
|
|
4253
|
+
const item = _item;
|
|
3722
4254
|
const updated = await this.update(kysely, fieldModel, item.where, item.update, fromRelationContext, true, false);
|
|
3723
|
-
if (updated) {
|
|
3724
|
-
|
|
3725
|
-
} else {
|
|
3726
|
-
return this.create(kysely, fieldModel, item.create, fromRelationContext);
|
|
4255
|
+
if (!updated) {
|
|
4256
|
+
await this.create(kysely, fieldModel, item.create, fromRelationContext);
|
|
3727
4257
|
}
|
|
3728
|
-
}
|
|
4258
|
+
}
|
|
3729
4259
|
break;
|
|
3730
4260
|
}
|
|
3731
4261
|
case "updateMany": {
|
|
3732
|
-
|
|
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
|
+
}
|
|
3733
4266
|
break;
|
|
3734
4267
|
}
|
|
3735
4268
|
case "delete": {
|
|
3736
|
-
|
|
4269
|
+
await this.deleteRelation(kysely, fieldModel, value, fromRelationContext, true);
|
|
3737
4270
|
break;
|
|
3738
4271
|
}
|
|
3739
4272
|
case "deleteMany": {
|
|
3740
|
-
|
|
4273
|
+
await this.deleteRelation(kysely, fieldModel, value, fromRelationContext, false);
|
|
3741
4274
|
break;
|
|
3742
4275
|
}
|
|
3743
4276
|
default: {
|
|
@@ -3745,7 +4278,6 @@ var BaseOperationHandler = class {
|
|
|
3745
4278
|
}
|
|
3746
4279
|
}
|
|
3747
4280
|
}
|
|
3748
|
-
await Promise.all(tasks);
|
|
3749
4281
|
return fromRelationContext.parentUpdates;
|
|
3750
4282
|
}
|
|
3751
4283
|
// #region relation manipulation
|
|
@@ -3756,18 +4288,22 @@ var BaseOperationHandler = class {
|
|
|
3756
4288
|
}
|
|
3757
4289
|
const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
|
|
3758
4290
|
if (m2m) {
|
|
3759
|
-
const
|
|
4291
|
+
const results = [];
|
|
4292
|
+
for (const d of _data) {
|
|
3760
4293
|
const ids = await this.getEntityIds(kysely, model, d);
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
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
|
+
}
|
|
3764
4300
|
if (_data.length > results.filter((r) => !!r).length) {
|
|
3765
4301
|
throw new NotFoundError(model);
|
|
3766
4302
|
}
|
|
3767
4303
|
} else {
|
|
3768
4304
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3769
4305
|
if (ownedByModel) {
|
|
3770
|
-
(0,
|
|
4306
|
+
(0, import_common_helpers10.invariant)(_data.length === 1, "only one entity can be connected");
|
|
3771
4307
|
const target = await this.readUnique(kysely, model, {
|
|
3772
4308
|
where: _data[0]
|
|
3773
4309
|
});
|
|
@@ -3780,7 +4316,7 @@ var BaseOperationHandler = class {
|
|
|
3780
4316
|
} else {
|
|
3781
4317
|
const relationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3782
4318
|
if (!relationFieldDef.array) {
|
|
3783
|
-
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 }) => ({
|
|
3784
4320
|
...acc,
|
|
3785
4321
|
[fk]: null
|
|
3786
4322
|
}), {})).modifyEnd(this.makeContextComment({
|
|
@@ -3808,16 +4344,16 @@ var BaseOperationHandler = class {
|
|
|
3808
4344
|
if (_data.length === 0) {
|
|
3809
4345
|
return;
|
|
3810
4346
|
}
|
|
3811
|
-
|
|
4347
|
+
for (const { where, create } of _data) {
|
|
3812
4348
|
const existing = await this.exists(kysely, model, where);
|
|
3813
4349
|
if (existing) {
|
|
3814
|
-
|
|
4350
|
+
await this.connectRelation(kysely, model, [
|
|
3815
4351
|
where
|
|
3816
4352
|
], fromRelation);
|
|
3817
4353
|
} else {
|
|
3818
|
-
|
|
4354
|
+
await this.create(kysely, model, create, fromRelation);
|
|
3819
4355
|
}
|
|
3820
|
-
}
|
|
4356
|
+
}
|
|
3821
4357
|
}
|
|
3822
4358
|
async disconnectRelation(kysely, model, data, fromRelation) {
|
|
3823
4359
|
let disconnectConditions = [];
|
|
@@ -3840,19 +4376,18 @@ var BaseOperationHandler = class {
|
|
|
3840
4376
|
}
|
|
3841
4377
|
const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
|
|
3842
4378
|
if (m2m) {
|
|
3843
|
-
const
|
|
4379
|
+
for (const d of disconnectConditions) {
|
|
3844
4380
|
const ids = await this.getEntityIds(kysely, model, d);
|
|
3845
4381
|
if (!ids) {
|
|
3846
4382
|
return;
|
|
3847
4383
|
}
|
|
3848
|
-
|
|
3849
|
-
}
|
|
3850
|
-
await Promise.all(actions);
|
|
4384
|
+
await this.handleManyToManyRelation(kysely, "disconnect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable);
|
|
4385
|
+
}
|
|
3851
4386
|
} else {
|
|
3852
4387
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3853
|
-
const eb = (0,
|
|
4388
|
+
const eb = (0, import_kysely10.expressionBuilder)();
|
|
3854
4389
|
if (ownedByModel) {
|
|
3855
|
-
(0,
|
|
4390
|
+
(0, import_common_helpers10.invariant)(disconnectConditions.length === 1, "only one entity can be disconnected");
|
|
3856
4391
|
const condition = disconnectConditions[0];
|
|
3857
4392
|
if (condition === true) {
|
|
3858
4393
|
for (const { fk } of keyPairs) {
|
|
@@ -3911,11 +4446,14 @@ var BaseOperationHandler = class {
|
|
|
3911
4446
|
const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
|
|
3912
4447
|
if (m2m) {
|
|
3913
4448
|
await this.resetManyToManyRelation(kysely, fromRelation.model, fromRelation.field, fromRelation.ids);
|
|
3914
|
-
const
|
|
4449
|
+
const results = [];
|
|
4450
|
+
for (const d of _data) {
|
|
3915
4451
|
const ids = await this.getEntityIds(kysely, model, d);
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
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
|
+
}
|
|
3919
4457
|
if (_data.length > results.filter((r) => !!r).length) {
|
|
3920
4458
|
throw new NotFoundError(model);
|
|
3921
4459
|
}
|
|
@@ -3981,7 +4519,7 @@ var BaseOperationHandler = class {
|
|
|
3981
4519
|
if (m2m) {
|
|
3982
4520
|
deleteFromModel = model;
|
|
3983
4521
|
const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3984
|
-
(0,
|
|
4522
|
+
(0, import_common_helpers10.invariant)(fieldDef.relation?.opposite);
|
|
3985
4523
|
deleteResult = await this.delete(kysely, model, {
|
|
3986
4524
|
AND: [
|
|
3987
4525
|
{
|
|
@@ -4005,7 +4543,7 @@ var BaseOperationHandler = class {
|
|
|
4005
4543
|
throw new NotFoundError(fromRelation.model);
|
|
4006
4544
|
}
|
|
4007
4545
|
const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
4008
|
-
(0,
|
|
4546
|
+
(0, import_common_helpers10.invariant)(fieldDef.relation?.opposite);
|
|
4009
4547
|
deleteResult = await this.delete(kysely, model, {
|
|
4010
4548
|
AND: [
|
|
4011
4549
|
// filter for parent
|
|
@@ -4135,7 +4673,7 @@ var BaseOperationHandler = class {
|
|
|
4135
4673
|
// reused the filter if it's a complete id filter (without extra fields)
|
|
4136
4674
|
// otherwise, read the entity by the filter
|
|
4137
4675
|
getEntityIds(kysely, model, uniqueFilter) {
|
|
4138
|
-
const idFields =
|
|
4676
|
+
const idFields = requireIdFields(this.schema, model);
|
|
4139
4677
|
if (
|
|
4140
4678
|
// all id fields are provided
|
|
4141
4679
|
idFields.every((f) => f in uniqueFilter && uniqueFilter[f] !== void 0) && // no non-id filter exists
|
|
@@ -4163,7 +4701,7 @@ var BaseOperationHandler = class {
|
|
|
4163
4701
|
for (const [key, value] of Object.entries(args)) {
|
|
4164
4702
|
if (value === void 0) {
|
|
4165
4703
|
delete args[key];
|
|
4166
|
-
} else if (value && (0,
|
|
4704
|
+
} else if (value && (0, import_common_helpers10.isPlainObject)(value)) {
|
|
4167
4705
|
this.doNormalizeArgs(value);
|
|
4168
4706
|
}
|
|
4169
4707
|
}
|
|
@@ -4237,7 +4775,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
4237
4775
|
if (field === "_all") {
|
|
4238
4776
|
query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as(`_count._all`));
|
|
4239
4777
|
} else {
|
|
4240
|
-
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}`));
|
|
4241
4779
|
}
|
|
4242
4780
|
}
|
|
4243
4781
|
});
|
|
@@ -4252,7 +4790,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
4252
4790
|
if (val === true) {
|
|
4253
4791
|
query = query.select((eb) => {
|
|
4254
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();
|
|
4255
|
-
return fn(
|
|
4793
|
+
return fn(import_kysely11.sql.ref(`$sub.${field}`)).as(`${key}.${field}`);
|
|
4256
4794
|
});
|
|
4257
4795
|
}
|
|
4258
4796
|
});
|
|
@@ -4299,7 +4837,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
|
|
|
4299
4837
|
};
|
|
4300
4838
|
|
|
4301
4839
|
// src/client/crud/operations/count.ts
|
|
4302
|
-
var
|
|
4840
|
+
var import_kysely12 = require("kysely");
|
|
4303
4841
|
var CountOperationHandler = class extends BaseOperationHandler {
|
|
4304
4842
|
static {
|
|
4305
4843
|
__name(this, "CountOperationHandler");
|
|
@@ -4323,7 +4861,7 @@ var CountOperationHandler = class extends BaseOperationHandler {
|
|
|
4323
4861
|
return subQuery.as(subQueryName);
|
|
4324
4862
|
});
|
|
4325
4863
|
if (parsedArgs?.select && typeof parsedArgs.select === "object") {
|
|
4326
|
-
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)));
|
|
4327
4865
|
const result = await this.executeQuery(this.kysely, query, "count");
|
|
4328
4866
|
return result.rows[0];
|
|
4329
4867
|
} else {
|
|
@@ -4359,7 +4897,7 @@ var CreateOperationHandler = class extends BaseOperationHandler {
|
|
|
4359
4897
|
});
|
|
4360
4898
|
});
|
|
4361
4899
|
if (!result && this.hasPolicyEnabled) {
|
|
4362
|
-
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`);
|
|
4363
4901
|
}
|
|
4364
4902
|
return result;
|
|
4365
4903
|
}
|
|
@@ -4405,15 +4943,15 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
|
4405
4943
|
omit: args.omit,
|
|
4406
4944
|
where: args.where
|
|
4407
4945
|
});
|
|
4408
|
-
if (!existing) {
|
|
4409
|
-
throw new NotFoundError(this.model);
|
|
4410
|
-
}
|
|
4411
4946
|
await this.safeTransaction(async (tx) => {
|
|
4412
4947
|
const result = await this.delete(tx, this.model, args.where);
|
|
4413
4948
|
if (result.count === 0) {
|
|
4414
4949
|
throw new NotFoundError(this.model);
|
|
4415
4950
|
}
|
|
4416
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
|
+
}
|
|
4417
4955
|
return existing;
|
|
4418
4956
|
}
|
|
4419
4957
|
async runDeleteMany(args) {
|
|
@@ -4447,7 +4985,7 @@ var FindOperationHandler = class extends BaseOperationHandler {
|
|
|
4447
4985
|
};
|
|
4448
4986
|
|
|
4449
4987
|
// src/client/crud/operations/group-by.ts
|
|
4450
|
-
var
|
|
4988
|
+
var import_kysely13 = require("kysely");
|
|
4451
4989
|
var import_ts_pattern13 = require("ts-pattern");
|
|
4452
4990
|
var GroupByOperationHandler = class extends BaseOperationHandler {
|
|
4453
4991
|
static {
|
|
@@ -4469,7 +5007,7 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
|
|
|
4469
5007
|
subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
|
|
4470
5008
|
return subQuery.as("$sub");
|
|
4471
5009
|
});
|
|
4472
|
-
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");
|
|
4473
5011
|
const bys = typeof parsedArgs.by === "string" ? [
|
|
4474
5012
|
parsedArgs.by
|
|
4475
5013
|
] : parsedArgs.by;
|
|
@@ -4584,7 +5122,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
4584
5122
|
});
|
|
4585
5123
|
if (!readBackResult) {
|
|
4586
5124
|
if (this.hasPolicyEnabled) {
|
|
4587
|
-
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");
|
|
4588
5126
|
} else {
|
|
4589
5127
|
return null;
|
|
4590
5128
|
}
|
|
@@ -4601,16 +5139,24 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
4601
5139
|
if (!args) {
|
|
4602
5140
|
return [];
|
|
4603
5141
|
}
|
|
4604
|
-
|
|
4605
|
-
const
|
|
4606
|
-
|
|
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, {
|
|
4607
5145
|
select: args.select,
|
|
4608
5146
|
omit: args.omit,
|
|
4609
5147
|
where: {
|
|
4610
|
-
OR:
|
|
5148
|
+
OR: updateResult2.map((item) => getIdValues(this.schema, this.model, item))
|
|
4611
5149
|
}
|
|
4612
5150
|
});
|
|
5151
|
+
return {
|
|
5152
|
+
readBackResult: readBackResult2,
|
|
5153
|
+
updateResult: updateResult2
|
|
5154
|
+
};
|
|
4613
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;
|
|
4614
5160
|
}
|
|
4615
5161
|
async runUpsert(args) {
|
|
4616
5162
|
const result = await this.safeTransaction(async (tx) => {
|
|
@@ -4626,18 +5172,32 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
4626
5172
|
});
|
|
4627
5173
|
});
|
|
4628
5174
|
if (!result && this.hasPolicyEnabled) {
|
|
4629
|
-
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");
|
|
4630
5176
|
}
|
|
4631
5177
|
return result;
|
|
4632
5178
|
}
|
|
4633
5179
|
};
|
|
4634
5180
|
|
|
4635
5181
|
// src/client/crud/validator.ts
|
|
4636
|
-
var
|
|
4637
|
-
var
|
|
5182
|
+
var import_common_helpers11 = require("@zenstackhq/common-helpers");
|
|
5183
|
+
var import_decimal3 = __toESM(require("decimal.js"), 1);
|
|
4638
5184
|
var import_json_stable_stringify = __toESM(require("json-stable-stringify"), 1);
|
|
4639
5185
|
var import_ts_pattern15 = require("ts-pattern");
|
|
4640
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
|
|
4641
5201
|
var InputValidator = class {
|
|
4642
5202
|
static {
|
|
4643
5203
|
__name(this, "InputValidator");
|
|
@@ -4699,7 +5259,7 @@ var InputValidator = class {
|
|
|
4699
5259
|
}
|
|
4700
5260
|
const { error } = schema.safeParse(args);
|
|
4701
5261
|
if (error) {
|
|
4702
|
-
throw new InputValidationError(`Invalid ${operation} args: ${error
|
|
5262
|
+
throw new InputValidationError(`Invalid ${operation} args: ${formatError(error)}`, error);
|
|
4703
5263
|
}
|
|
4704
5264
|
return args;
|
|
4705
5265
|
}
|
|
@@ -4743,7 +5303,7 @@ var InputValidator = class {
|
|
|
4743
5303
|
import_zod.z.bigint()
|
|
4744
5304
|
])).with("Decimal", () => import_zod.z.union([
|
|
4745
5305
|
import_zod.z.number(),
|
|
4746
|
-
import_zod.z.instanceof(
|
|
5306
|
+
import_zod.z.instanceof(import_decimal3.default),
|
|
4747
5307
|
import_zod.z.string()
|
|
4748
5308
|
])).with("DateTime", () => import_zod.z.union([
|
|
4749
5309
|
import_zod.z.date(),
|
|
@@ -4758,7 +5318,7 @@ var InputValidator = class {
|
|
|
4758
5318
|
return schema;
|
|
4759
5319
|
}
|
|
4760
5320
|
const typeDef = this.schema.typeDefs?.[type];
|
|
4761
|
-
(0,
|
|
5321
|
+
(0, import_common_helpers11.invariant)(typeDef, `Type definition "${type}" not found in schema`);
|
|
4762
5322
|
schema = import_zod.z.object(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
|
|
4763
5323
|
let fieldSchema = this.makePrimitiveSchema(def.type);
|
|
4764
5324
|
if (def.array) {
|
|
@@ -4826,7 +5386,7 @@ var InputValidator = class {
|
|
|
4826
5386
|
for (const uniqueField of uniqueFields) {
|
|
4827
5387
|
if ("defs" in uniqueField) {
|
|
4828
5388
|
fields[uniqueField.name] = import_zod.z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
|
|
4829
|
-
(0,
|
|
5389
|
+
(0, import_common_helpers11.invariant)(!def.relation, "unique field cannot be a relation");
|
|
4830
5390
|
let fieldSchema;
|
|
4831
5391
|
const enumDef = getEnum(this.schema, def.type);
|
|
4832
5392
|
if (enumDef) {
|
|
@@ -5032,9 +5592,16 @@ var InputValidator = class {
|
|
|
5032
5592
|
fields[field] = import_zod.z.boolean().optional();
|
|
5033
5593
|
}
|
|
5034
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) {
|
|
5035
5602
|
const toManyRelations = Object.values(modelDef.fields).filter((def) => def.relation && def.array);
|
|
5036
5603
|
if (toManyRelations.length > 0) {
|
|
5037
|
-
|
|
5604
|
+
return import_zod.z.union([
|
|
5038
5605
|
import_zod.z.literal(true),
|
|
5039
5606
|
import_zod.z.strictObject({
|
|
5040
5607
|
select: import_zod.z.strictObject(toManyRelations.reduce((acc, fieldDef) => ({
|
|
@@ -5048,8 +5615,9 @@ var InputValidator = class {
|
|
|
5048
5615
|
}), {}))
|
|
5049
5616
|
})
|
|
5050
5617
|
]).optional();
|
|
5618
|
+
} else {
|
|
5619
|
+
return void 0;
|
|
5051
5620
|
}
|
|
5052
|
-
return import_zod.z.strictObject(fields);
|
|
5053
5621
|
}
|
|
5054
5622
|
makeRelationSelectIncludeSchema(fieldDef) {
|
|
5055
5623
|
let objSchema = import_zod.z.strictObject({
|
|
@@ -5096,6 +5664,10 @@ var InputValidator = class {
|
|
|
5096
5664
|
fields[field] = this.makeRelationSelectIncludeSchema(fieldDef).optional();
|
|
5097
5665
|
}
|
|
5098
5666
|
}
|
|
5667
|
+
const _countSchema = this.makeCountSelectionSchema(modelDef);
|
|
5668
|
+
if (_countSchema) {
|
|
5669
|
+
fields["_count"] = _countSchema;
|
|
5670
|
+
}
|
|
5099
5671
|
return import_zod.z.strictObject(fields);
|
|
5100
5672
|
}
|
|
5101
5673
|
makeOrderBySchema(model, withRelation, WithAggregation) {
|
|
@@ -5162,13 +5734,15 @@ var InputValidator = class {
|
|
|
5162
5734
|
// #region Create
|
|
5163
5735
|
makeCreateSchema(model) {
|
|
5164
5736
|
const dataSchema = this.makeCreateDataSchema(model, false);
|
|
5165
|
-
|
|
5737
|
+
let schema = import_zod.z.strictObject({
|
|
5166
5738
|
data: dataSchema,
|
|
5167
5739
|
select: this.makeSelectSchema(model).optional(),
|
|
5168
5740
|
include: this.makeIncludeSchema(model).optional(),
|
|
5169
5741
|
omit: this.makeOmitSchema(model).optional()
|
|
5170
5742
|
});
|
|
5171
|
-
|
|
5743
|
+
schema = this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
5744
|
+
schema = this.refineForSelectOmitMutuallyExclusive(schema);
|
|
5745
|
+
return schema;
|
|
5172
5746
|
}
|
|
5173
5747
|
makeCreateManySchema(model) {
|
|
5174
5748
|
return this.makeCreateManyDataSchema(model, []).optional();
|
|
@@ -5293,11 +5867,11 @@ var InputValidator = class {
|
|
|
5293
5867
|
fields["delete"] = this.makeDeleteRelationDataSchema(fieldType, array, true).optional();
|
|
5294
5868
|
}
|
|
5295
5869
|
fields["update"] = array ? this.orArray(import_zod.z.strictObject({
|
|
5296
|
-
where: this.makeWhereSchema(fieldType, true),
|
|
5870
|
+
where: this.makeWhereSchema(fieldType, true).optional(),
|
|
5297
5871
|
data: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
5298
5872
|
}), true).optional() : import_zod.z.union([
|
|
5299
5873
|
import_zod.z.strictObject({
|
|
5300
|
-
where: this.makeWhereSchema(fieldType, true),
|
|
5874
|
+
where: this.makeWhereSchema(fieldType, true).optional(),
|
|
5301
5875
|
data: this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
5302
5876
|
}),
|
|
5303
5877
|
this.makeUpdateDataSchema(fieldType, withoutFields)
|
|
@@ -5357,14 +5931,16 @@ var InputValidator = class {
|
|
|
5357
5931
|
// #endregion
|
|
5358
5932
|
// #region Update
|
|
5359
5933
|
makeUpdateSchema(model) {
|
|
5360
|
-
|
|
5934
|
+
let schema = import_zod.z.strictObject({
|
|
5361
5935
|
where: this.makeWhereSchema(model, true),
|
|
5362
5936
|
data: this.makeUpdateDataSchema(model),
|
|
5363
5937
|
select: this.makeSelectSchema(model).optional(),
|
|
5364
5938
|
include: this.makeIncludeSchema(model).optional(),
|
|
5365
5939
|
omit: this.makeOmitSchema(model).optional()
|
|
5366
5940
|
});
|
|
5367
|
-
|
|
5941
|
+
schema = this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
5942
|
+
schema = this.refineForSelectOmitMutuallyExclusive(schema);
|
|
5943
|
+
return schema;
|
|
5368
5944
|
}
|
|
5369
5945
|
makeUpdateManySchema(model) {
|
|
5370
5946
|
return import_zod.z.strictObject({
|
|
@@ -5375,14 +5951,15 @@ var InputValidator = class {
|
|
|
5375
5951
|
}
|
|
5376
5952
|
makeUpdateManyAndReturnSchema(model) {
|
|
5377
5953
|
const base = this.makeUpdateManySchema(model);
|
|
5378
|
-
|
|
5954
|
+
let schema = base.extend({
|
|
5379
5955
|
select: this.makeSelectSchema(model).optional(),
|
|
5380
5956
|
omit: this.makeOmitSchema(model).optional()
|
|
5381
5957
|
});
|
|
5382
|
-
|
|
5958
|
+
schema = this.refineForSelectOmitMutuallyExclusive(schema);
|
|
5959
|
+
return schema;
|
|
5383
5960
|
}
|
|
5384
5961
|
makeUpsertSchema(model) {
|
|
5385
|
-
|
|
5962
|
+
let schema = import_zod.z.strictObject({
|
|
5386
5963
|
where: this.makeWhereSchema(model, true),
|
|
5387
5964
|
create: this.makeCreateDataSchema(model, false),
|
|
5388
5965
|
update: this.makeUpdateDataSchema(model),
|
|
@@ -5390,7 +5967,9 @@ var InputValidator = class {
|
|
|
5390
5967
|
include: this.makeIncludeSchema(model).optional(),
|
|
5391
5968
|
omit: this.makeOmitSchema(model).optional()
|
|
5392
5969
|
});
|
|
5393
|
-
|
|
5970
|
+
schema = this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
5971
|
+
schema = this.refineForSelectOmitMutuallyExclusive(schema);
|
|
5972
|
+
return schema;
|
|
5394
5973
|
}
|
|
5395
5974
|
makeUpdateDataSchema(model, withoutFields = [], withoutRelationFields = false) {
|
|
5396
5975
|
const uncheckedVariantFields = {};
|
|
@@ -5467,12 +6046,14 @@ var InputValidator = class {
|
|
|
5467
6046
|
// #endregion
|
|
5468
6047
|
// #region Delete
|
|
5469
6048
|
makeDeleteSchema(model) {
|
|
5470
|
-
|
|
6049
|
+
let schema = import_zod.z.strictObject({
|
|
5471
6050
|
where: this.makeWhereSchema(model, true),
|
|
5472
6051
|
select: this.makeSelectSchema(model).optional(),
|
|
5473
6052
|
include: this.makeIncludeSchema(model).optional()
|
|
5474
6053
|
});
|
|
5475
|
-
|
|
6054
|
+
schema = this.refineForSelectIncludeMutuallyExclusive(schema);
|
|
6055
|
+
schema = this.refineForSelectOmitMutuallyExclusive(schema);
|
|
6056
|
+
return schema;
|
|
5476
6057
|
}
|
|
5477
6058
|
makeDeleteManySchema(model) {
|
|
5478
6059
|
return import_zod.z.object({
|
|
@@ -5822,31 +6403,14 @@ function performanceNow() {
|
|
|
5822
6403
|
__name(performanceNow, "performanceNow");
|
|
5823
6404
|
|
|
5824
6405
|
// src/client/executor/zenstack-query-executor.ts
|
|
5825
|
-
var
|
|
5826
|
-
var
|
|
6406
|
+
var import_common_helpers13 = require("@zenstackhq/common-helpers");
|
|
6407
|
+
var import_kysely15 = require("kysely");
|
|
5827
6408
|
var import_ts_pattern16 = require("ts-pattern");
|
|
5828
6409
|
|
|
5829
|
-
// src/client/executor/kysely-utils.ts
|
|
5830
|
-
var import_kysely12 = require("kysely");
|
|
5831
|
-
function stripAlias(node) {
|
|
5832
|
-
if (import_kysely12.AliasNode.is(node)) {
|
|
5833
|
-
return {
|
|
5834
|
-
alias: node.alias,
|
|
5835
|
-
node: node.node
|
|
5836
|
-
};
|
|
5837
|
-
} else {
|
|
5838
|
-
return {
|
|
5839
|
-
alias: void 0,
|
|
5840
|
-
node
|
|
5841
|
-
};
|
|
5842
|
-
}
|
|
5843
|
-
}
|
|
5844
|
-
__name(stripAlias, "stripAlias");
|
|
5845
|
-
|
|
5846
6410
|
// src/client/executor/name-mapper.ts
|
|
5847
|
-
var
|
|
5848
|
-
var
|
|
5849
|
-
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 {
|
|
5850
6414
|
static {
|
|
5851
6415
|
__name(this, "QueryNameMapper");
|
|
5852
6416
|
}
|
|
@@ -5888,7 +6452,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5888
6452
|
})) : void 0;
|
|
5889
6453
|
return {
|
|
5890
6454
|
...super.transformSelectQuery(node),
|
|
5891
|
-
from:
|
|
6455
|
+
from: import_kysely14.FromNode.create(processedFroms.map((f) => f.node)),
|
|
5892
6456
|
joins,
|
|
5893
6457
|
selections: this.processSelectQuerySelections(node)
|
|
5894
6458
|
};
|
|
@@ -5914,7 +6478,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5914
6478
|
};
|
|
5915
6479
|
}
|
|
5916
6480
|
transformReference(node) {
|
|
5917
|
-
if (!
|
|
6481
|
+
if (!import_kysely14.ColumnNode.is(node.column)) {
|
|
5918
6482
|
return super.transformReference(node);
|
|
5919
6483
|
}
|
|
5920
6484
|
const scope = this.resolveFieldFromScopes(node.column.column.name, node.table?.table.identifier.name);
|
|
@@ -5922,12 +6486,12 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5922
6486
|
const mappedFieldName = this.mapFieldName(scope.model, node.column.column.name);
|
|
5923
6487
|
let mappedTableName = node.table?.table.identifier.name;
|
|
5924
6488
|
if (mappedTableName) {
|
|
5925
|
-
if (scope.alias &&
|
|
6489
|
+
if (scope.alias && import_kysely14.IdentifierNode.is(scope.alias) && scope.alias.name === mappedTableName) {
|
|
5926
6490
|
} else if (scope.model === mappedTableName) {
|
|
5927
6491
|
mappedTableName = this.mapTableName(scope.model);
|
|
5928
6492
|
}
|
|
5929
6493
|
}
|
|
5930
|
-
return
|
|
6494
|
+
return import_kysely14.ReferenceNode.create(import_kysely14.ColumnNode.create(mappedFieldName), mappedTableName ? import_kysely14.TableNode.create(mappedTableName) : void 0);
|
|
5931
6495
|
} else {
|
|
5932
6496
|
return super.transformReference(node);
|
|
5933
6497
|
}
|
|
@@ -5938,14 +6502,14 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5938
6502
|
return super.transformColumn(node);
|
|
5939
6503
|
}
|
|
5940
6504
|
const mappedName = this.mapFieldName(scope.model, node.column.name);
|
|
5941
|
-
return
|
|
6505
|
+
return import_kysely14.ColumnNode.create(mappedName);
|
|
5942
6506
|
}
|
|
5943
6507
|
transformUpdateQuery(node) {
|
|
5944
6508
|
if (!node.table) {
|
|
5945
6509
|
return super.transformUpdateQuery(node);
|
|
5946
6510
|
}
|
|
5947
6511
|
const { alias, node: innerTable } = stripAlias(node.table);
|
|
5948
|
-
if (!innerTable || !
|
|
6512
|
+
if (!innerTable || !import_kysely14.TableNode.is(innerTable)) {
|
|
5949
6513
|
return super.transformUpdateQuery(node);
|
|
5950
6514
|
}
|
|
5951
6515
|
return this.withScope({
|
|
@@ -5963,14 +6527,14 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5963
6527
|
const scopes = node.from.froms.map((node2) => {
|
|
5964
6528
|
const { alias, node: innerNode } = stripAlias(node2);
|
|
5965
6529
|
return {
|
|
5966
|
-
model:
|
|
6530
|
+
model: extractModelName(innerNode),
|
|
5967
6531
|
alias,
|
|
5968
6532
|
namesMapped: false
|
|
5969
6533
|
};
|
|
5970
6534
|
});
|
|
5971
6535
|
const froms = node.from.froms.map((from) => {
|
|
5972
6536
|
const { alias, node: innerNode } = stripAlias(from);
|
|
5973
|
-
if (
|
|
6537
|
+
if (import_kysely14.TableNode.is(innerNode)) {
|
|
5974
6538
|
return this.wrapAlias(this.processTableRef(innerNode), alias);
|
|
5975
6539
|
} else {
|
|
5976
6540
|
return super.transformNode(from);
|
|
@@ -5979,7 +6543,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5979
6543
|
return this.withScopes(scopes, () => {
|
|
5980
6544
|
return {
|
|
5981
6545
|
...super.transformDeleteQuery(node),
|
|
5982
|
-
from:
|
|
6546
|
+
from: import_kysely14.FromNode.create(froms)
|
|
5983
6547
|
};
|
|
5984
6548
|
});
|
|
5985
6549
|
}
|
|
@@ -5988,24 +6552,24 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5988
6552
|
processSelectQuerySelections(node) {
|
|
5989
6553
|
const selections = [];
|
|
5990
6554
|
for (const selection of node.selections ?? []) {
|
|
5991
|
-
if (
|
|
6555
|
+
if (import_kysely14.SelectAllNode.is(selection.selection)) {
|
|
5992
6556
|
const scope = this.scopes[this.scopes.length - 1];
|
|
5993
6557
|
if (scope?.model && !scope.namesMapped) {
|
|
5994
6558
|
selections.push(...this.createSelectAllFields(scope.model, scope.alias));
|
|
5995
6559
|
} else {
|
|
5996
6560
|
selections.push(super.transformSelection(selection));
|
|
5997
6561
|
}
|
|
5998
|
-
} else if (
|
|
6562
|
+
} else if (import_kysely14.ReferenceNode.is(selection.selection) || import_kysely14.ColumnNode.is(selection.selection)) {
|
|
5999
6563
|
const transformed = this.transformNode(selection.selection);
|
|
6000
|
-
if (
|
|
6001
|
-
selections.push(
|
|
6564
|
+
if (import_kysely14.AliasNode.is(transformed)) {
|
|
6565
|
+
selections.push(import_kysely14.SelectionNode.create(transformed));
|
|
6002
6566
|
} else {
|
|
6003
|
-
const origFieldName =
|
|
6004
|
-
const fieldName =
|
|
6567
|
+
const origFieldName = extractFieldName(selection.selection);
|
|
6568
|
+
const fieldName = extractFieldName(transformed);
|
|
6005
6569
|
if (fieldName !== origFieldName) {
|
|
6006
|
-
selections.push(
|
|
6570
|
+
selections.push(import_kysely14.SelectionNode.create(this.wrapAlias(transformed, origFieldName ? import_kysely14.IdentifierNode.create(origFieldName) : void 0)));
|
|
6007
6571
|
} else {
|
|
6008
|
-
selections.push(
|
|
6572
|
+
selections.push(import_kysely14.SelectionNode.create(transformed));
|
|
6009
6573
|
}
|
|
6010
6574
|
}
|
|
6011
6575
|
} else {
|
|
@@ -6019,7 +6583,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6019
6583
|
const scope = this.scopes[i];
|
|
6020
6584
|
if (qualifier) {
|
|
6021
6585
|
if (scope.alias) {
|
|
6022
|
-
if (scope.alias &&
|
|
6586
|
+
if (scope.alias && import_kysely14.IdentifierNode.is(scope.alias) && scope.alias.name === qualifier) {
|
|
6023
6587
|
return scope;
|
|
6024
6588
|
} else {
|
|
6025
6589
|
continue;
|
|
@@ -6065,16 +6629,16 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6065
6629
|
}
|
|
6066
6630
|
}
|
|
6067
6631
|
wrapAlias(node, alias) {
|
|
6068
|
-
return alias ?
|
|
6632
|
+
return alias ? import_kysely14.AliasNode.create(node, alias) : node;
|
|
6069
6633
|
}
|
|
6070
6634
|
processTableRef(node) {
|
|
6071
6635
|
if (!node) {
|
|
6072
6636
|
return node;
|
|
6073
6637
|
}
|
|
6074
|
-
if (!
|
|
6638
|
+
if (!import_kysely14.TableNode.is(node)) {
|
|
6075
6639
|
return super.transformNode(node);
|
|
6076
6640
|
}
|
|
6077
|
-
return
|
|
6641
|
+
return import_kysely14.TableNode.create(this.mapTableName(node.table.identifier.name));
|
|
6078
6642
|
}
|
|
6079
6643
|
getMappedName(def) {
|
|
6080
6644
|
const mapAttr = def.attributes?.find((attr) => attr.name === "@@map" || attr.name === "@map");
|
|
@@ -6110,14 +6674,14 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6110
6674
|
// convert a "from" node to a nested query if there are columns with name mapping
|
|
6111
6675
|
processSelectTable(node) {
|
|
6112
6676
|
const { alias, node: innerNode } = stripAlias(node);
|
|
6113
|
-
if (innerNode &&
|
|
6677
|
+
if (innerNode && import_kysely14.TableNode.is(innerNode)) {
|
|
6114
6678
|
const modelName = innerNode.table.identifier.name;
|
|
6115
6679
|
const mappedName = this.mapTableName(modelName);
|
|
6116
|
-
const finalAlias = alias ?? (mappedName !== modelName ?
|
|
6680
|
+
const finalAlias = alias ?? (mappedName !== modelName ? import_kysely14.IdentifierNode.create(modelName) : void 0);
|
|
6117
6681
|
return {
|
|
6118
|
-
node: this.wrapAlias(
|
|
6682
|
+
node: this.wrapAlias(import_kysely14.TableNode.create(mappedName), finalAlias),
|
|
6119
6683
|
scope: {
|
|
6120
|
-
alias: alias ??
|
|
6684
|
+
alias: alias ?? import_kysely14.IdentifierNode.create(modelName),
|
|
6121
6685
|
model: modelName,
|
|
6122
6686
|
namesMapped: !this.hasMappedColumns(modelName)
|
|
6123
6687
|
}
|
|
@@ -6137,12 +6701,12 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6137
6701
|
const modelDef = requireModel(this.schema, model);
|
|
6138
6702
|
return this.getModelFields(modelDef).map((fieldDef) => {
|
|
6139
6703
|
const columnName = this.mapFieldName(model, fieldDef.name);
|
|
6140
|
-
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);
|
|
6141
6705
|
if (columnName !== fieldDef.name) {
|
|
6142
|
-
const aliased =
|
|
6143
|
-
return
|
|
6706
|
+
const aliased = import_kysely14.AliasNode.create(columnRef, import_kysely14.IdentifierNode.create(fieldDef.name));
|
|
6707
|
+
return import_kysely14.SelectionNode.create(aliased);
|
|
6144
6708
|
} else {
|
|
6145
|
-
return
|
|
6709
|
+
return import_kysely14.SelectionNode.create(columnRef);
|
|
6146
6710
|
}
|
|
6147
6711
|
});
|
|
6148
6712
|
}
|
|
@@ -6152,57 +6716,44 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6152
6716
|
processSelections(selections) {
|
|
6153
6717
|
const result = [];
|
|
6154
6718
|
selections.forEach((selection) => {
|
|
6155
|
-
if (
|
|
6719
|
+
if (import_kysely14.SelectAllNode.is(selection.selection)) {
|
|
6156
6720
|
const processed = this.processSelectAll(selection.selection);
|
|
6157
6721
|
if (Array.isArray(processed)) {
|
|
6158
|
-
result.push(...processed.map((s) =>
|
|
6722
|
+
result.push(...processed.map((s) => import_kysely14.SelectionNode.create(s)));
|
|
6159
6723
|
} else {
|
|
6160
|
-
result.push(
|
|
6724
|
+
result.push(import_kysely14.SelectionNode.create(processed));
|
|
6161
6725
|
}
|
|
6162
6726
|
} else {
|
|
6163
|
-
result.push(
|
|
6727
|
+
result.push(import_kysely14.SelectionNode.create(this.processSelection(selection.selection)));
|
|
6164
6728
|
}
|
|
6165
6729
|
});
|
|
6166
6730
|
return result;
|
|
6167
6731
|
}
|
|
6168
6732
|
processSelection(node) {
|
|
6169
6733
|
let alias;
|
|
6170
|
-
if (!
|
|
6171
|
-
alias =
|
|
6734
|
+
if (!import_kysely14.AliasNode.is(node)) {
|
|
6735
|
+
alias = extractFieldName(node);
|
|
6172
6736
|
}
|
|
6173
6737
|
const result = super.transformNode(node);
|
|
6174
|
-
return this.wrapAlias(result, alias ?
|
|
6738
|
+
return this.wrapAlias(result, alias ? import_kysely14.IdentifierNode.create(alias) : void 0);
|
|
6175
6739
|
}
|
|
6176
6740
|
processSelectAll(node) {
|
|
6177
6741
|
const scope = this.scopes[this.scopes.length - 1];
|
|
6178
|
-
(0,
|
|
6742
|
+
(0, import_common_helpers12.invariant)(scope);
|
|
6179
6743
|
if (!scope.model || !this.hasMappedColumns(scope.model)) {
|
|
6180
6744
|
return super.transformSelectAll(node);
|
|
6181
6745
|
}
|
|
6182
6746
|
const modelDef = requireModel(this.schema, scope.model);
|
|
6183
6747
|
return this.getModelFields(modelDef).map((fieldDef) => {
|
|
6184
6748
|
const columnName = this.mapFieldName(modelDef.name, fieldDef.name);
|
|
6185
|
-
const columnRef =
|
|
6186
|
-
return columnName !== fieldDef.name ? this.wrapAlias(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;
|
|
6187
6751
|
});
|
|
6188
6752
|
}
|
|
6189
|
-
extractModelName(node) {
|
|
6190
|
-
const { node: innerNode } = stripAlias(node);
|
|
6191
|
-
return import_kysely13.TableNode.is(innerNode) ? innerNode.table.identifier.name : void 0;
|
|
6192
|
-
}
|
|
6193
|
-
extractFieldName(node) {
|
|
6194
|
-
if (import_kysely13.ReferenceNode.is(node) && import_kysely13.ColumnNode.is(node.column)) {
|
|
6195
|
-
return node.column.column.name;
|
|
6196
|
-
} else if (import_kysely13.ColumnNode.is(node)) {
|
|
6197
|
-
return node.column.name;
|
|
6198
|
-
} else {
|
|
6199
|
-
return void 0;
|
|
6200
|
-
}
|
|
6201
|
-
}
|
|
6202
6753
|
};
|
|
6203
6754
|
|
|
6204
6755
|
// src/client/executor/zenstack-query-executor.ts
|
|
6205
|
-
var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends
|
|
6756
|
+
var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely15.DefaultQueryExecutor {
|
|
6206
6757
|
static {
|
|
6207
6758
|
__name(this, "ZenStackQueryExecutor");
|
|
6208
6759
|
}
|
|
@@ -6258,13 +6809,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6258
6809
|
}
|
|
6259
6810
|
getMutationInfo(queryNode) {
|
|
6260
6811
|
const model = this.getMutationModel(queryNode);
|
|
6261
|
-
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, () => ({
|
|
6262
6813
|
action: "create",
|
|
6263
6814
|
where: void 0
|
|
6264
|
-
})).when(
|
|
6815
|
+
})).when(import_kysely15.UpdateQueryNode.is, (node) => ({
|
|
6265
6816
|
action: "update",
|
|
6266
6817
|
where: node.where
|
|
6267
|
-
})).when(
|
|
6818
|
+
})).when(import_kysely15.DeleteQueryNode.is, (node) => ({
|
|
6268
6819
|
action: "delete",
|
|
6269
6820
|
where: node.where
|
|
6270
6821
|
})).exhaustive();
|
|
@@ -6292,11 +6843,11 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6292
6843
|
result
|
|
6293
6844
|
};
|
|
6294
6845
|
}
|
|
6295
|
-
if ((
|
|
6846
|
+
if ((import_kysely15.InsertQueryNode.is(query) || import_kysely15.UpdateQueryNode.is(query)) && this.hasEntityMutationPluginsWithAfterMutationHooks) {
|
|
6296
6847
|
query = {
|
|
6297
6848
|
...query,
|
|
6298
|
-
returning:
|
|
6299
|
-
|
|
6849
|
+
returning: import_kysely15.ReturningNode.create([
|
|
6850
|
+
import_kysely15.SelectionNode.createSelectAll()
|
|
6300
6851
|
])
|
|
6301
6852
|
};
|
|
6302
6853
|
}
|
|
@@ -6313,7 +6864,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6313
6864
|
const mutationInfo = this.getMutationInfo(finalQuery);
|
|
6314
6865
|
let beforeMutationEntities;
|
|
6315
6866
|
const loadBeforeMutationEntities = /* @__PURE__ */ __name(async () => {
|
|
6316
|
-
if (beforeMutationEntities === void 0 && (
|
|
6867
|
+
if (beforeMutationEntities === void 0 && (import_kysely15.UpdateQueryNode.is(query) || import_kysely15.DeleteQueryNode.is(query))) {
|
|
6317
6868
|
beforeMutationEntities = await this.loadEntities(mutationInfo.model, mutationInfo.where, connection);
|
|
6318
6869
|
}
|
|
6319
6870
|
return beforeMutationEntities;
|
|
@@ -6355,7 +6906,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6355
6906
|
}
|
|
6356
6907
|
}
|
|
6357
6908
|
createClientForConnection(connection, inTx) {
|
|
6358
|
-
const innerExecutor = this.withConnectionProvider(new
|
|
6909
|
+
const innerExecutor = this.withConnectionProvider(new import_kysely15.SingleConnectionProvider(connection));
|
|
6359
6910
|
innerExecutor.suppressMutationHooks = true;
|
|
6360
6911
|
const innerClient = this.client.withExecutor(innerExecutor);
|
|
6361
6912
|
if (inTx) {
|
|
@@ -6373,7 +6924,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6373
6924
|
return (this.client.$options.plugins ?? []).some((plugin) => plugin.onEntityMutation?.runAfterMutationWithinTransaction);
|
|
6374
6925
|
}
|
|
6375
6926
|
isMutationNode(queryNode) {
|
|
6376
|
-
return
|
|
6927
|
+
return import_kysely15.InsertQueryNode.is(queryNode) || import_kysely15.UpdateQueryNode.is(queryNode) || import_kysely15.DeleteQueryNode.is(queryNode);
|
|
6377
6928
|
}
|
|
6378
6929
|
withPlugin(plugin) {
|
|
6379
6930
|
return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, [
|
|
@@ -6402,18 +6953,18 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6402
6953
|
return newExecutor;
|
|
6403
6954
|
}
|
|
6404
6955
|
getMutationModel(queryNode) {
|
|
6405
|
-
return (0, import_ts_pattern16.match)(queryNode).when(
|
|
6406
|
-
(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");
|
|
6407
6958
|
return node.into.table.identifier.name;
|
|
6408
|
-
}).when(
|
|
6409
|
-
(0,
|
|
6959
|
+
}).when(import_kysely15.UpdateQueryNode.is, (node) => {
|
|
6960
|
+
(0, import_common_helpers13.invariant)(node.table, "UpdateQueryNode must have a table");
|
|
6410
6961
|
const { node: tableNode } = stripAlias(node.table);
|
|
6411
|
-
(0,
|
|
6962
|
+
(0, import_common_helpers13.invariant)(import_kysely15.TableNode.is(tableNode), "UpdateQueryNode must use a TableNode");
|
|
6412
6963
|
return tableNode.table.identifier.name;
|
|
6413
|
-
}).when(
|
|
6414
|
-
(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");
|
|
6415
6966
|
const { node: tableNode } = stripAlias(node.from.froms[0]);
|
|
6416
|
-
(0,
|
|
6967
|
+
(0, import_common_helpers13.invariant)(import_kysely15.TableNode.is(tableNode), "DeleteQueryNode must use a TableNode");
|
|
6417
6968
|
return tableNode.table.identifier.name;
|
|
6418
6969
|
}).otherwise((node) => {
|
|
6419
6970
|
throw new InternalError(`Invalid query node: ${node}`);
|
|
@@ -6487,9 +7038,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6487
7038
|
}
|
|
6488
7039
|
andNodes(condition1, condition2) {
|
|
6489
7040
|
if (condition1 && condition2) {
|
|
6490
|
-
return
|
|
7041
|
+
return import_kysely15.WhereNode.create(import_kysely15.AndNode.create(condition1, condition2));
|
|
6491
7042
|
} else if (condition1) {
|
|
6492
|
-
return
|
|
7043
|
+
return import_kysely15.WhereNode.create(condition1);
|
|
6493
7044
|
} else {
|
|
6494
7045
|
return condition2;
|
|
6495
7046
|
}
|
|
@@ -6511,53 +7062,58 @@ __export(functions_exports, {
|
|
|
6511
7062
|
search: () => search,
|
|
6512
7063
|
startsWith: () => startsWith
|
|
6513
7064
|
});
|
|
6514
|
-
var
|
|
6515
|
-
var
|
|
7065
|
+
var import_common_helpers14 = require("@zenstackhq/common-helpers");
|
|
7066
|
+
var import_kysely16 = require("kysely");
|
|
6516
7067
|
var import_ts_pattern17 = require("ts-pattern");
|
|
6517
|
-
var contains = /* @__PURE__ */ __name((eb, args) =>
|
|
6518
|
-
const [field, search2, caseInsensitive = false] = args;
|
|
6519
|
-
if (!field) {
|
|
6520
|
-
throw new Error('"field" parameter is required');
|
|
6521
|
-
}
|
|
6522
|
-
if (!search2) {
|
|
6523
|
-
throw new Error('"search" parameter is required');
|
|
6524
|
-
}
|
|
6525
|
-
const searchExpr = eb.fn("CONCAT", [
|
|
6526
|
-
import_kysely15.sql.lit("%"),
|
|
6527
|
-
search2,
|
|
6528
|
-
import_kysely15.sql.lit("%")
|
|
6529
|
-
]);
|
|
6530
|
-
return eb(field, caseInsensitive ? "ilike" : "like", searchExpr);
|
|
6531
|
-
}, "contains");
|
|
7068
|
+
var contains = /* @__PURE__ */ __name((eb, args, context) => textMatch(eb, args, context, "contains"), "contains");
|
|
6532
7069
|
var search = /* @__PURE__ */ __name((_eb, _args) => {
|
|
6533
7070
|
throw new Error(`"search" function is not implemented yet`);
|
|
6534
7071
|
}, "search");
|
|
6535
|
-
var startsWith = /* @__PURE__ */ __name((eb, args) =>
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
}
|
|
6540
|
-
if (!search2) {
|
|
6541
|
-
throw new Error('"search" parameter is required');
|
|
6542
|
-
}
|
|
6543
|
-
return eb(field, "like", eb.fn("CONCAT", [
|
|
6544
|
-
search2,
|
|
6545
|
-
import_kysely15.sql.lit("%")
|
|
6546
|
-
]));
|
|
6547
|
-
}, "startsWith");
|
|
6548
|
-
var endsWith = /* @__PURE__ */ __name((eb, args) => {
|
|
6549
|
-
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;
|
|
6550
7076
|
if (!field) {
|
|
6551
7077
|
throw new Error('"field" parameter is required');
|
|
6552
7078
|
}
|
|
6553
7079
|
if (!search2) {
|
|
6554
7080
|
throw new Error('"search" parameter is required');
|
|
6555
7081
|
}
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
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");
|
|
6561
7117
|
var has = /* @__PURE__ */ __name((eb, args) => {
|
|
6562
7118
|
const [field, search2] = args;
|
|
6563
7119
|
if (!field) {
|
|
@@ -6595,18 +7151,16 @@ var isEmpty = /* @__PURE__ */ __name((eb, args, { dialect }) => {
|
|
|
6595
7151
|
if (!field) {
|
|
6596
7152
|
throw new Error('"field" parameter is required');
|
|
6597
7153
|
}
|
|
6598
|
-
return eb(dialect.buildArrayLength(eb, field), "=",
|
|
7154
|
+
return eb(dialect.buildArrayLength(eb, field), "=", import_kysely16.sql.lit(0));
|
|
6599
7155
|
}, "isEmpty");
|
|
6600
|
-
var now = /* @__PURE__ */ __name((
|
|
6601
|
-
return (0, import_ts_pattern17.match)(dialect.provider).with("postgresql", () => eb.fn("now")).with("sqlite", () => import_kysely15.sql.raw("CURRENT_TIMESTAMP")).exhaustive();
|
|
6602
|
-
}, "now");
|
|
7156
|
+
var now = /* @__PURE__ */ __name(() => import_kysely16.sql.raw("CURRENT_TIMESTAMP"), "now");
|
|
6603
7157
|
var currentModel = /* @__PURE__ */ __name((_eb, args, { model }) => {
|
|
6604
7158
|
let result = model;
|
|
6605
7159
|
const [casing] = args;
|
|
6606
7160
|
if (casing) {
|
|
6607
7161
|
result = processCasing(casing, result, model);
|
|
6608
7162
|
}
|
|
6609
|
-
return
|
|
7163
|
+
return import_kysely16.sql.lit(result);
|
|
6610
7164
|
}, "currentModel");
|
|
6611
7165
|
var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
6612
7166
|
let result = operation;
|
|
@@ -6614,21 +7168,30 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
|
6614
7168
|
if (casing) {
|
|
6615
7169
|
result = processCasing(casing, result, operation);
|
|
6616
7170
|
}
|
|
6617
|
-
return
|
|
7171
|
+
return import_kysely16.sql.lit(result);
|
|
6618
7172
|
}, "currentOperation");
|
|
6619
7173
|
function processCasing(casing, result, model) {
|
|
6620
7174
|
const opNode = casing.toOperationNode();
|
|
6621
|
-
(0,
|
|
6622
|
-
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(() => {
|
|
6623
7177
|
throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
|
|
6624
7178
|
});
|
|
6625
7179
|
return result;
|
|
6626
7180
|
}
|
|
6627
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");
|
|
6628
7191
|
|
|
6629
7192
|
// src/client/helpers/schema-db-pusher.ts
|
|
6630
|
-
var
|
|
6631
|
-
var
|
|
7193
|
+
var import_common_helpers15 = require("@zenstackhq/common-helpers");
|
|
7194
|
+
var import_kysely17 = require("kysely");
|
|
6632
7195
|
var import_toposort = __toESM(require("toposort"), 1);
|
|
6633
7196
|
var import_ts_pattern18 = require("ts-pattern");
|
|
6634
7197
|
var SchemaDbPusher = class {
|
|
@@ -6649,7 +7212,8 @@ var SchemaDbPusher = class {
|
|
|
6649
7212
|
await createEnum.execute();
|
|
6650
7213
|
}
|
|
6651
7214
|
}
|
|
6652
|
-
const
|
|
7215
|
+
const models = Object.values(this.schema.models).filter((m) => !m.isView);
|
|
7216
|
+
const sortedModels = this.sortModels(models);
|
|
6653
7217
|
for (const modelDef of sortedModels) {
|
|
6654
7218
|
const createTable = this.createModelTable(tx, modelDef);
|
|
6655
7219
|
await createTable.execute();
|
|
@@ -6658,7 +7222,7 @@ var SchemaDbPusher = class {
|
|
|
6658
7222
|
}
|
|
6659
7223
|
sortModels(models) {
|
|
6660
7224
|
const graph = [];
|
|
6661
|
-
for (const model of
|
|
7225
|
+
for (const model of models) {
|
|
6662
7226
|
let added = false;
|
|
6663
7227
|
if (model.baseModel) {
|
|
6664
7228
|
const baseDef = requireModel(this.schema, model.baseModel);
|
|
@@ -6743,7 +7307,7 @@ var SchemaDbPusher = class {
|
|
|
6743
7307
|
}
|
|
6744
7308
|
addUniqueConstraint(table, modelDef) {
|
|
6745
7309
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
6746
|
-
(0,
|
|
7310
|
+
(0, import_common_helpers15.invariant)(typeof value === "object", "expecting an object");
|
|
6747
7311
|
if ("type" in value) {
|
|
6748
7312
|
const fieldDef = modelDef.fields[key];
|
|
6749
7313
|
if (fieldDef.unique) {
|
|
@@ -6766,7 +7330,7 @@ var SchemaDbPusher = class {
|
|
|
6766
7330
|
if (fieldDef.default !== void 0) {
|
|
6767
7331
|
if (typeof fieldDef.default === "object" && "kind" in fieldDef.default) {
|
|
6768
7332
|
if (ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "now") {
|
|
6769
|
-
col = col.defaultTo(
|
|
7333
|
+
col = col.defaultTo(import_kysely17.sql`CURRENT_TIMESTAMP`);
|
|
6770
7334
|
}
|
|
6771
7335
|
} else {
|
|
6772
7336
|
col = col.defaultTo(fieldDef.default);
|
|
@@ -6786,7 +7350,7 @@ var SchemaDbPusher = class {
|
|
|
6786
7350
|
}
|
|
6787
7351
|
mapFieldType(fieldDef) {
|
|
6788
7352
|
if (this.schema.enums?.[fieldDef.type]) {
|
|
6789
|
-
return this.schema.provider.type === "postgresql" ?
|
|
7353
|
+
return this.schema.provider.type === "postgresql" ? import_kysely17.sql.ref(fieldDef.type) : "text";
|
|
6790
7354
|
}
|
|
6791
7355
|
if (this.isAutoIncrement(fieldDef) && this.schema.provider.type === "postgresql") {
|
|
6792
7356
|
return "serial";
|
|
@@ -6799,7 +7363,7 @@ var SchemaDbPusher = class {
|
|
|
6799
7363
|
throw new Error(`Unsupported field type: ${type}`);
|
|
6800
7364
|
});
|
|
6801
7365
|
if (fieldDef.array) {
|
|
6802
|
-
return
|
|
7366
|
+
return import_kysely17.sql.raw(`${result}[]`);
|
|
6803
7367
|
} else {
|
|
6804
7368
|
return result;
|
|
6805
7369
|
}
|
|
@@ -6811,7 +7375,7 @@ var SchemaDbPusher = class {
|
|
|
6811
7375
|
return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
|
|
6812
7376
|
}
|
|
6813
7377
|
addForeignKeyConstraint(table, model, fieldName, fieldDef) {
|
|
6814
|
-
(0,
|
|
7378
|
+
(0, import_common_helpers15.invariant)(fieldDef.relation, "field must be a relation");
|
|
6815
7379
|
if (!fieldDef.relation.fields || !fieldDef.relation.references) {
|
|
6816
7380
|
return table;
|
|
6817
7381
|
}
|
|
@@ -6868,16 +7432,15 @@ function valueToPromise(thing) {
|
|
|
6868
7432
|
__name(valueToPromise, "valueToPromise");
|
|
6869
7433
|
|
|
6870
7434
|
// src/client/result-processor.ts
|
|
6871
|
-
var import_common_helpers14 = require("@zenstackhq/common-helpers");
|
|
6872
|
-
var import_decimal2 = __toESM(require("decimal.js"), 1);
|
|
6873
|
-
var import_ts_pattern19 = require("ts-pattern");
|
|
6874
7435
|
var ResultProcessor = class {
|
|
6875
7436
|
static {
|
|
6876
7437
|
__name(this, "ResultProcessor");
|
|
6877
7438
|
}
|
|
6878
7439
|
schema;
|
|
6879
|
-
|
|
7440
|
+
dialect;
|
|
7441
|
+
constructor(schema, options) {
|
|
6880
7442
|
this.schema = schema;
|
|
7443
|
+
this.dialect = getCrudDialect(schema, options);
|
|
6881
7444
|
}
|
|
6882
7445
|
processResult(data, model, args) {
|
|
6883
7446
|
const result = this.doProcessResult(data, model);
|
|
@@ -6906,7 +7469,7 @@ var ResultProcessor = class {
|
|
|
6906
7469
|
}
|
|
6907
7470
|
if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
|
|
6908
7471
|
if (value) {
|
|
6909
|
-
const subRow = this.
|
|
7472
|
+
const subRow = this.dialect.transformOutput(value, "Json");
|
|
6910
7473
|
const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
|
|
6911
7474
|
const idValues = getIdValues(this.schema, subModel, subRow);
|
|
6912
7475
|
if (Object.values(idValues).some((v) => v === null || v === void 0)) {
|
|
@@ -6940,10 +7503,10 @@ var ResultProcessor = class {
|
|
|
6940
7503
|
processFieldValue(value, fieldDef) {
|
|
6941
7504
|
const type = fieldDef.type;
|
|
6942
7505
|
if (Array.isArray(value)) {
|
|
6943
|
-
value.forEach((v, i) => value[i] = this.
|
|
7506
|
+
value.forEach((v, i) => value[i] = this.dialect.transformOutput(v, type));
|
|
6944
7507
|
return value;
|
|
6945
7508
|
} else {
|
|
6946
|
-
return this.
|
|
7509
|
+
return this.dialect.transformOutput(value, type);
|
|
6947
7510
|
}
|
|
6948
7511
|
}
|
|
6949
7512
|
processRelation(value, fieldDef) {
|
|
@@ -6957,42 +7520,6 @@ var ResultProcessor = class {
|
|
|
6957
7520
|
}
|
|
6958
7521
|
return this.doProcessResult(relationData, fieldDef.type);
|
|
6959
7522
|
}
|
|
6960
|
-
transformScalar(value, type) {
|
|
6961
|
-
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
6962
|
-
return this.transformJson(value);
|
|
6963
|
-
} else {
|
|
6964
|
-
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);
|
|
6965
|
-
}
|
|
6966
|
-
}
|
|
6967
|
-
transformDecimal(value) {
|
|
6968
|
-
if (value instanceof import_decimal2.default) {
|
|
6969
|
-
return value;
|
|
6970
|
-
}
|
|
6971
|
-
(0, import_common_helpers14.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal2.default, `Expected string, number or Decimal, got ${typeof value}`);
|
|
6972
|
-
return new import_decimal2.default(value);
|
|
6973
|
-
}
|
|
6974
|
-
transformBigInt(value) {
|
|
6975
|
-
if (typeof value === "bigint") {
|
|
6976
|
-
return value;
|
|
6977
|
-
}
|
|
6978
|
-
(0, import_common_helpers14.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
6979
|
-
return BigInt(value);
|
|
6980
|
-
}
|
|
6981
|
-
transformBoolean(value) {
|
|
6982
|
-
return !!value;
|
|
6983
|
-
}
|
|
6984
|
-
transformDate(value) {
|
|
6985
|
-
if (typeof value === "number") {
|
|
6986
|
-
return new Date(value);
|
|
6987
|
-
} else if (typeof value === "string") {
|
|
6988
|
-
return new Date(Date.parse(value));
|
|
6989
|
-
} else {
|
|
6990
|
-
return value;
|
|
6991
|
-
}
|
|
6992
|
-
}
|
|
6993
|
-
transformBytes(value) {
|
|
6994
|
-
return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
|
|
6995
|
-
}
|
|
6996
7523
|
fixReversedResult(data, model, args) {
|
|
6997
7524
|
if (!data) {
|
|
6998
7525
|
return;
|
|
@@ -7017,12 +7544,6 @@ var ResultProcessor = class {
|
|
|
7017
7544
|
}
|
|
7018
7545
|
}
|
|
7019
7546
|
}
|
|
7020
|
-
transformJson(value) {
|
|
7021
|
-
return (0, import_ts_pattern19.match)(this.schema.provider.type).with("sqlite", () => {
|
|
7022
|
-
(0, import_common_helpers14.invariant)(typeof value === "string", "Expected string, got " + typeof value);
|
|
7023
|
-
return JSON.parse(value);
|
|
7024
|
-
}).otherwise(() => value);
|
|
7025
|
-
}
|
|
7026
7547
|
};
|
|
7027
7548
|
|
|
7028
7549
|
// src/client/client-impl.ts
|
|
@@ -7045,7 +7566,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7045
7566
|
this.schema = schema;
|
|
7046
7567
|
this.options = options;
|
|
7047
7568
|
this.$schema = schema;
|
|
7048
|
-
this.$options = options
|
|
7569
|
+
this.$options = options;
|
|
7049
7570
|
this.$options.functions = {
|
|
7050
7571
|
...functions_exports,
|
|
7051
7572
|
...this.$options.functions
|
|
@@ -7053,15 +7574,15 @@ var ClientImpl = class _ClientImpl {
|
|
|
7053
7574
|
if (baseClient) {
|
|
7054
7575
|
this.kyselyProps = {
|
|
7055
7576
|
...baseClient.kyselyProps,
|
|
7056
|
-
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))
|
|
7057
7578
|
};
|
|
7058
7579
|
this.kyselyRaw = baseClient.kyselyRaw;
|
|
7059
7580
|
this.auth = baseClient.auth;
|
|
7060
7581
|
} else {
|
|
7061
|
-
const driver = new ZenStackDriver(options.dialect.createDriver(), new
|
|
7582
|
+
const driver = new ZenStackDriver(options.dialect.createDriver(), new import_kysely18.Log(this.$options.log ?? []));
|
|
7062
7583
|
const compiler = options.dialect.createQueryCompiler();
|
|
7063
7584
|
const adapter = options.dialect.createAdapter();
|
|
7064
|
-
const connectionProvider = new
|
|
7585
|
+
const connectionProvider = new import_kysely18.DefaultConnectionProvider(driver);
|
|
7065
7586
|
this.kyselyProps = {
|
|
7066
7587
|
config: {
|
|
7067
7588
|
dialect: options.dialect,
|
|
@@ -7071,12 +7592,12 @@ var ClientImpl = class _ClientImpl {
|
|
|
7071
7592
|
driver,
|
|
7072
7593
|
executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
|
|
7073
7594
|
};
|
|
7074
|
-
this.kyselyRaw = new
|
|
7595
|
+
this.kyselyRaw = new import_kysely18.Kysely({
|
|
7075
7596
|
...this.kyselyProps,
|
|
7076
|
-
executor: new
|
|
7597
|
+
executor: new import_kysely18.DefaultQueryExecutor(compiler, adapter, connectionProvider, [])
|
|
7077
7598
|
});
|
|
7078
7599
|
}
|
|
7079
|
-
this.kysely = new
|
|
7600
|
+
this.kysely = new import_kysely18.Kysely(this.kyselyProps);
|
|
7080
7601
|
return createClientProxy(this);
|
|
7081
7602
|
}
|
|
7082
7603
|
get $qb() {
|
|
@@ -7096,7 +7617,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7096
7617
|
}
|
|
7097
7618
|
// implementation
|
|
7098
7619
|
async $transaction(input, options) {
|
|
7099
|
-
(0,
|
|
7620
|
+
(0, import_common_helpers16.invariant)(typeof input === "function" || Array.isArray(input) && input.every((p) => p.then && p.cb), "Invalid transaction input, expected a function or an array of ZenStackPromise");
|
|
7100
7621
|
if (typeof input === "function") {
|
|
7101
7622
|
return this.interactiveTransaction(input, options);
|
|
7102
7623
|
} else {
|
|
@@ -7105,7 +7626,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7105
7626
|
}
|
|
7106
7627
|
forceTransaction() {
|
|
7107
7628
|
if (!this.kysely.isTransaction) {
|
|
7108
|
-
this.kysely = new
|
|
7629
|
+
this.kysely = new import_kysely18.Transaction(this.kyselyProps);
|
|
7109
7630
|
}
|
|
7110
7631
|
}
|
|
7111
7632
|
async interactiveTransaction(callback, options) {
|
|
@@ -7212,7 +7733,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7212
7733
|
}
|
|
7213
7734
|
$executeRaw(query, ...values) {
|
|
7214
7735
|
return createZenStackPromise(async () => {
|
|
7215
|
-
const result = await (0,
|
|
7736
|
+
const result = await (0, import_kysely18.sql)(query, ...values).execute(this.kysely);
|
|
7216
7737
|
return Number(result.numAffectedRows ?? 0);
|
|
7217
7738
|
});
|
|
7218
7739
|
}
|
|
@@ -7225,7 +7746,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7225
7746
|
}
|
|
7226
7747
|
$queryRaw(query, ...values) {
|
|
7227
7748
|
return createZenStackPromise(async () => {
|
|
7228
|
-
const result = await (0,
|
|
7749
|
+
const result = await (0, import_kysely18.sql)(query, ...values).execute(this.kysely);
|
|
7229
7750
|
return result.rows;
|
|
7230
7751
|
});
|
|
7231
7752
|
}
|
|
@@ -7237,7 +7758,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7237
7758
|
});
|
|
7238
7759
|
}
|
|
7239
7760
|
createRawCompiledQuery(query, values) {
|
|
7240
|
-
const q =
|
|
7761
|
+
const q = import_kysely18.CompiledQuery.raw(query, values);
|
|
7241
7762
|
return {
|
|
7242
7763
|
...q,
|
|
7243
7764
|
$raw: true
|
|
@@ -7246,7 +7767,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7246
7767
|
};
|
|
7247
7768
|
function createClientProxy(client) {
|
|
7248
7769
|
const inputValidator = new InputValidator(client.$schema);
|
|
7249
|
-
const resultProcessor = new ResultProcessor(client.$schema);
|
|
7770
|
+
const resultProcessor = new ResultProcessor(client.$schema, client.$options);
|
|
7250
7771
|
return new Proxy(client, {
|
|
7251
7772
|
get: /* @__PURE__ */ __name((target, prop, receiver) => {
|
|
7252
7773
|
if (typeof prop === "string" && prop.startsWith("$")) {
|
|
@@ -7364,7 +7885,7 @@ function definePlugin(plugin) {
|
|
|
7364
7885
|
__name(definePlugin, "definePlugin");
|
|
7365
7886
|
|
|
7366
7887
|
// src/client/index.ts
|
|
7367
|
-
var
|
|
7888
|
+
var import_kysely19 = require("kysely");
|
|
7368
7889
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7369
7890
|
0 && (module.exports = {
|
|
7370
7891
|
InputValidationError,
|