metal-orm 1.1.8 → 1.1.10
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/README.md +769 -764
- package/dist/index.cjs +2352 -226
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +605 -40
- package/dist/index.d.ts +605 -40
- package/dist/index.js +2324 -226
- package/dist/index.js.map +1 -1
- package/package.json +22 -17
- package/src/bulk/bulk-context.ts +83 -0
- package/src/bulk/bulk-delete-executor.ts +89 -0
- package/src/bulk/bulk-executor.base.ts +73 -0
- package/src/bulk/bulk-insert-executor.ts +74 -0
- package/src/bulk/bulk-types.ts +70 -0
- package/src/bulk/bulk-update-executor.ts +192 -0
- package/src/bulk/bulk-upsert-executor.ts +95 -0
- package/src/bulk/bulk-utils.ts +91 -0
- package/src/bulk/index.ts +18 -0
- package/src/codegen/typescript.ts +30 -21
- package/src/core/ast/expression-builders.ts +107 -10
- package/src/core/ast/expression-nodes.ts +52 -22
- package/src/core/ast/expression-visitor.ts +23 -13
- package/src/core/dialect/abstract.ts +30 -17
- package/src/core/dialect/mysql/index.ts +20 -5
- package/src/core/execution/db-executor.ts +96 -64
- package/src/core/execution/executors/better-sqlite3-executor.ts +94 -0
- package/src/core/execution/executors/mssql-executor.ts +66 -34
- package/src/core/execution/executors/mysql-executor.ts +98 -66
- package/src/core/execution/executors/postgres-executor.ts +33 -11
- package/src/core/execution/executors/sqlite-executor.ts +86 -30
- package/src/decorators/bootstrap.ts +482 -398
- package/src/decorators/column-decorator.ts +87 -96
- package/src/decorators/decorator-metadata.ts +100 -24
- package/src/decorators/entity.ts +27 -24
- package/src/decorators/relations.ts +231 -149
- package/src/decorators/transformers/transformer-decorators.ts +26 -29
- package/src/decorators/validators/country-validators-decorators.ts +9 -15
- package/src/dto/apply-filter.ts +568 -551
- package/src/index.ts +16 -9
- package/src/orm/entity-hydration.ts +116 -72
- package/src/orm/entity-metadata.ts +347 -301
- package/src/orm/entity-relations.ts +264 -207
- package/src/orm/entity.ts +199 -199
- package/src/orm/execute.ts +13 -13
- package/src/orm/lazy-batch/morph-many.ts +70 -0
- package/src/orm/lazy-batch/morph-one.ts +69 -0
- package/src/orm/lazy-batch/morph-to.ts +59 -0
- package/src/orm/lazy-batch.ts +4 -1
- package/src/orm/orm-session.ts +170 -104
- package/src/orm/pooled-executor-factory.ts +99 -58
- package/src/orm/query-logger.ts +49 -40
- package/src/orm/relation-change-processor.ts +198 -96
- package/src/orm/relations/belongs-to.ts +143 -143
- package/src/orm/relations/has-many.ts +204 -204
- package/src/orm/relations/has-one.ts +174 -174
- package/src/orm/relations/many-to-many.ts +288 -288
- package/src/orm/relations/morph-many.ts +156 -0
- package/src/orm/relations/morph-one.ts +151 -0
- package/src/orm/relations/morph-to.ts +162 -0
- package/src/orm/save-graph.ts +116 -1
- package/src/query-builder/expression-table-mapper.ts +5 -0
- package/src/query-builder/hydration-manager.ts +345 -345
- package/src/query-builder/hydration-planner.ts +178 -148
- package/src/query-builder/relation-conditions.ts +171 -151
- package/src/query-builder/relation-cte-builder.ts +5 -1
- package/src/query-builder/relation-filter-utils.ts +9 -6
- package/src/query-builder/relation-include-strategies.ts +44 -2
- package/src/query-builder/relation-join-strategies.ts +8 -1
- package/src/query-builder/relation-service.ts +250 -241
- package/src/query-builder/select/cursor-pagination.ts +323 -0
- package/src/query-builder/select/select-operations.ts +110 -105
- package/src/query-builder/select.ts +42 -1
- package/src/query-builder/update-include.ts +4 -0
- package/src/schema/relation.ts +296 -188
- package/src/schema/types.ts +138 -123
- package/src/tree/tree-decorator.ts +127 -137
package/dist/index.js
CHANGED
|
@@ -328,7 +328,13 @@ var RelationKinds = {
|
|
|
328
328
|
/** Many-to-one relationship */
|
|
329
329
|
BelongsTo: "BELONGS_TO",
|
|
330
330
|
/** Many-to-many relationship with pivot metadata */
|
|
331
|
-
BelongsToMany: "BELONGS_TO_MANY"
|
|
331
|
+
BelongsToMany: "BELONGS_TO_MANY",
|
|
332
|
+
/** Polymorphic inverse (child side) */
|
|
333
|
+
MorphTo: "MORPH_TO",
|
|
334
|
+
/** Polymorphic one-to-one (parent side) */
|
|
335
|
+
MorphOne: "MORPH_ONE",
|
|
336
|
+
/** Polymorphic one-to-many (parent side) */
|
|
337
|
+
MorphMany: "MORPH_MANY"
|
|
332
338
|
};
|
|
333
339
|
var hasMany = (target, foreignKey, localKey, cascade) => ({
|
|
334
340
|
type: RelationKinds.HasMany,
|
|
@@ -363,6 +369,32 @@ var belongsToMany = (target, pivotTable, options) => ({
|
|
|
363
369
|
defaultPivotColumns: options.defaultPivotColumns,
|
|
364
370
|
cascade: options.cascade
|
|
365
371
|
});
|
|
372
|
+
var isSingleTargetRelation = (rel) => rel.type !== RelationKinds.MorphTo;
|
|
373
|
+
var isMorphRelation = (rel) => rel.type === RelationKinds.MorphTo || rel.type === RelationKinds.MorphOne || rel.type === RelationKinds.MorphMany;
|
|
374
|
+
var morphTo = (opts) => ({
|
|
375
|
+
type: RelationKinds.MorphTo,
|
|
376
|
+
...opts
|
|
377
|
+
});
|
|
378
|
+
var morphOne = (target, opts) => ({
|
|
379
|
+
type: RelationKinds.MorphOne,
|
|
380
|
+
target,
|
|
381
|
+
morphName: opts.as,
|
|
382
|
+
typeField: opts.typeField ?? `${opts.as}Type`,
|
|
383
|
+
idField: opts.idField ?? `${opts.as}Id`,
|
|
384
|
+
typeValue: opts.typeValue,
|
|
385
|
+
localKey: opts.localKey,
|
|
386
|
+
cascade: opts.cascade
|
|
387
|
+
});
|
|
388
|
+
var morphMany = (target, opts) => ({
|
|
389
|
+
type: RelationKinds.MorphMany,
|
|
390
|
+
target,
|
|
391
|
+
morphName: opts.as,
|
|
392
|
+
typeField: opts.typeField ?? `${opts.as}Type`,
|
|
393
|
+
idField: opts.idField ?? `${opts.as}Id`,
|
|
394
|
+
typeValue: opts.typeValue,
|
|
395
|
+
localKey: opts.localKey,
|
|
396
|
+
cascade: opts.cascade
|
|
397
|
+
});
|
|
366
398
|
|
|
367
399
|
// src/core/ast/expression-nodes.ts
|
|
368
400
|
var operandTypes = /* @__PURE__ */ new Set([
|
|
@@ -490,6 +522,10 @@ var or = (...operands) => ({
|
|
|
490
522
|
operator: "OR",
|
|
491
523
|
operands
|
|
492
524
|
});
|
|
525
|
+
var not = (operand) => ({
|
|
526
|
+
type: "NotExpression",
|
|
527
|
+
operand
|
|
528
|
+
});
|
|
493
529
|
var isNull = (left2) => ({
|
|
494
530
|
type: "NullExpression",
|
|
495
531
|
left: toOperandNode(left2),
|
|
@@ -573,6 +609,18 @@ var collate = (expression, collation) => ({
|
|
|
573
609
|
expression: toOperand(expression),
|
|
574
610
|
collation
|
|
575
611
|
});
|
|
612
|
+
var isDistinctFrom = (left2, right2) => ({
|
|
613
|
+
type: "IsDistinctExpression",
|
|
614
|
+
left: toOperandNode(left2),
|
|
615
|
+
operator: "IS DISTINCT FROM",
|
|
616
|
+
right: toOperand(right2)
|
|
617
|
+
});
|
|
618
|
+
var isNotDistinctFrom = (left2, right2) => ({
|
|
619
|
+
type: "IsDistinctExpression",
|
|
620
|
+
left: toOperandNode(left2),
|
|
621
|
+
operator: "IS NOT DISTINCT FROM",
|
|
622
|
+
right: toOperand(right2)
|
|
623
|
+
});
|
|
576
624
|
|
|
577
625
|
// src/core/ast/window-functions.ts
|
|
578
626
|
var buildWindowFunction = (name, args = [], partitionBy, orderBy) => {
|
|
@@ -779,6 +827,9 @@ var visitExpression = (node, visitor) => {
|
|
|
779
827
|
case "LogicalExpression":
|
|
780
828
|
if (visitor.visitLogicalExpression) return visitor.visitLogicalExpression(node);
|
|
781
829
|
break;
|
|
830
|
+
case "NotExpression":
|
|
831
|
+
if (visitor.visitNotExpression) return visitor.visitNotExpression(node);
|
|
832
|
+
break;
|
|
782
833
|
case "NullExpression":
|
|
783
834
|
if (visitor.visitNullExpression) return visitor.visitNullExpression(node);
|
|
784
835
|
break;
|
|
@@ -797,6 +848,9 @@ var visitExpression = (node, visitor) => {
|
|
|
797
848
|
case "BitwiseExpression":
|
|
798
849
|
if (visitor.visitBitwiseExpression) return visitor.visitBitwiseExpression(node);
|
|
799
850
|
break;
|
|
851
|
+
case "IsDistinctExpression":
|
|
852
|
+
if (visitor.visitIsDistinctExpression) return visitor.visitIsDistinctExpression(node);
|
|
853
|
+
break;
|
|
800
854
|
default:
|
|
801
855
|
break;
|
|
802
856
|
}
|
|
@@ -1520,6 +1574,10 @@ var Dialect = class _Dialect {
|
|
|
1520
1574
|
});
|
|
1521
1575
|
return parts.join(` ${logical.operator} `);
|
|
1522
1576
|
});
|
|
1577
|
+
this.registerExpressionCompiler("NotExpression", (notExpr, ctx) => {
|
|
1578
|
+
const operand = this.compileExpression(notExpr.operand, ctx);
|
|
1579
|
+
return `NOT (${operand})`;
|
|
1580
|
+
});
|
|
1523
1581
|
this.registerExpressionCompiler("NullExpression", (nullExpr, ctx) => {
|
|
1524
1582
|
const left2 = this.compileOperand(nullExpr.left, ctx);
|
|
1525
1583
|
return `${left2} ${nullExpr.operator}`;
|
|
@@ -1553,6 +1611,11 @@ var Dialect = class _Dialect {
|
|
|
1553
1611
|
const right2 = this.compileOperand(bitwise.right, ctx);
|
|
1554
1612
|
return `${left2} ${bitwise.operator} ${right2}`;
|
|
1555
1613
|
});
|
|
1614
|
+
this.registerExpressionCompiler("IsDistinctExpression", (node, ctx) => {
|
|
1615
|
+
const left2 = this.compileOperand(node.left, ctx);
|
|
1616
|
+
const right2 = this.compileOperand(node.right, ctx);
|
|
1617
|
+
return `${left2} ${node.operator} ${right2}`;
|
|
1618
|
+
});
|
|
1556
1619
|
}
|
|
1557
1620
|
registerDefaultOperandCompilers() {
|
|
1558
1621
|
this.registerOperandCompiler("Literal", (literal, ctx) => ctx.addParameter(literal.value));
|
|
@@ -2474,6 +2537,18 @@ var MySqlDialect = class extends SqlDialectBase {
|
|
|
2474
2537
|
*/
|
|
2475
2538
|
constructor() {
|
|
2476
2539
|
super(new MysqlFunctionStrategy());
|
|
2540
|
+
this.registerExpressionCompiler(
|
|
2541
|
+
"IsDistinctExpression",
|
|
2542
|
+
(node, ctx) => {
|
|
2543
|
+
const left2 = this.compileOperand(node.left, ctx);
|
|
2544
|
+
const right2 = this.compileOperand(node.right, ctx);
|
|
2545
|
+
const spaceship = `${left2} <=> ${right2}`;
|
|
2546
|
+
if (node.operator === "IS NOT DISTINCT FROM") {
|
|
2547
|
+
return spaceship;
|
|
2548
|
+
}
|
|
2549
|
+
return `NOT (${spaceship})`;
|
|
2550
|
+
}
|
|
2551
|
+
);
|
|
2477
2552
|
}
|
|
2478
2553
|
/**
|
|
2479
2554
|
* Quotes an identifier using MySQL backtick syntax
|
|
@@ -3573,7 +3648,7 @@ var HydrationManager = class _HydrationManager {
|
|
|
3573
3648
|
*/
|
|
3574
3649
|
hasMultiplyingRelations(plan) {
|
|
3575
3650
|
return plan.relations.some(
|
|
3576
|
-
(rel) => rel.type === RelationKinds.HasMany || rel.type === RelationKinds.BelongsToMany
|
|
3651
|
+
(rel) => rel.type === RelationKinds.HasMany || rel.type === RelationKinds.BelongsToMany || rel.type === RelationKinds.MorphMany
|
|
3577
3652
|
);
|
|
3578
3653
|
}
|
|
3579
3654
|
/**
|
|
@@ -3907,6 +3982,36 @@ var HydrationPlanner = class _HydrationPlanner {
|
|
|
3907
3982
|
}
|
|
3908
3983
|
};
|
|
3909
3984
|
}
|
|
3985
|
+
case RelationKinds.MorphOne: {
|
|
3986
|
+
const morphRel = rel;
|
|
3987
|
+
const localKey = morphRel.localKey || findPrimaryKey(this.table);
|
|
3988
|
+
return {
|
|
3989
|
+
name: relationName,
|
|
3990
|
+
aliasPrefix,
|
|
3991
|
+
type: rel.type,
|
|
3992
|
+
targetTable: morphRel.target.name,
|
|
3993
|
+
targetPrimaryKey: findPrimaryKey(morphRel.target),
|
|
3994
|
+
foreignKey: morphRel.idField,
|
|
3995
|
+
localKey,
|
|
3996
|
+
columns
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3999
|
+
case RelationKinds.MorphMany: {
|
|
4000
|
+
const morphRel = rel;
|
|
4001
|
+
const localKey = morphRel.localKey || findPrimaryKey(this.table);
|
|
4002
|
+
return {
|
|
4003
|
+
name: relationName,
|
|
4004
|
+
aliasPrefix,
|
|
4005
|
+
type: rel.type,
|
|
4006
|
+
targetTable: morphRel.target.name,
|
|
4007
|
+
targetPrimaryKey: findPrimaryKey(morphRel.target),
|
|
4008
|
+
foreignKey: morphRel.idField,
|
|
4009
|
+
localKey,
|
|
4010
|
+
columns
|
|
4011
|
+
};
|
|
4012
|
+
}
|
|
4013
|
+
case RelationKinds.MorphTo:
|
|
4014
|
+
throw new Error("MorphTo relations do not support hydration planning via JOIN.");
|
|
3910
4015
|
}
|
|
3911
4016
|
}
|
|
3912
4017
|
};
|
|
@@ -4211,23 +4316,44 @@ var assertNever = (value) => {
|
|
|
4211
4316
|
};
|
|
4212
4317
|
var baseRelationCondition = (root, relation, rootAlias, targetTableName) => {
|
|
4213
4318
|
const rootTable = rootAlias || root.name;
|
|
4319
|
+
if (relation.type === RelationKinds.MorphTo) {
|
|
4320
|
+
throw new Error("MorphTo relations do not support the standard join condition builder");
|
|
4321
|
+
}
|
|
4214
4322
|
const targetTable = targetTableName ?? relation.target.name;
|
|
4215
|
-
const defaultLocalKey = relation.type === RelationKinds.HasMany || relation.type === RelationKinds.HasOne ? findPrimaryKey(root) : findPrimaryKey(relation.target);
|
|
4216
|
-
const localKey = relation.localKey || defaultLocalKey;
|
|
4217
4323
|
switch (relation.type) {
|
|
4218
4324
|
case RelationKinds.HasMany:
|
|
4219
|
-
case RelationKinds.HasOne:
|
|
4325
|
+
case RelationKinds.HasOne: {
|
|
4326
|
+
const defaultLocalKey = findPrimaryKey(root);
|
|
4327
|
+
const localKey = relation.localKey || defaultLocalKey;
|
|
4220
4328
|
return eq(
|
|
4221
4329
|
{ type: "Column", table: targetTable, name: relation.foreignKey },
|
|
4222
4330
|
{ type: "Column", table: rootTable, name: localKey }
|
|
4223
4331
|
);
|
|
4224
|
-
|
|
4332
|
+
}
|
|
4333
|
+
case RelationKinds.BelongsTo: {
|
|
4334
|
+
const defaultLocalKey = findPrimaryKey(relation.target);
|
|
4335
|
+
const localKey = relation.localKey || defaultLocalKey;
|
|
4225
4336
|
return eq(
|
|
4226
4337
|
{ type: "Column", table: targetTable, name: localKey },
|
|
4227
4338
|
{ type: "Column", table: rootTable, name: relation.foreignKey }
|
|
4228
4339
|
);
|
|
4340
|
+
}
|
|
4229
4341
|
case RelationKinds.BelongsToMany:
|
|
4230
4342
|
throw new Error("BelongsToMany relations do not support the standard join condition builder");
|
|
4343
|
+
case RelationKinds.MorphOne:
|
|
4344
|
+
case RelationKinds.MorphMany: {
|
|
4345
|
+
const morphRel = relation;
|
|
4346
|
+
const morphLocalKey = morphRel.localKey || findPrimaryKey(root);
|
|
4347
|
+
const baseCondition = eq(
|
|
4348
|
+
{ type: "Column", table: targetTable, name: morphRel.idField },
|
|
4349
|
+
{ type: "Column", table: rootTable, name: morphLocalKey }
|
|
4350
|
+
);
|
|
4351
|
+
const discriminatorCondition = eq(
|
|
4352
|
+
{ type: "Column", table: targetTable, name: morphRel.typeField },
|
|
4353
|
+
{ type: "Literal", value: morphRel.typeValue }
|
|
4354
|
+
);
|
|
4355
|
+
return and(baseCondition, discriminatorCondition);
|
|
4356
|
+
}
|
|
4231
4357
|
default:
|
|
4232
4358
|
return assertNever(relation);
|
|
4233
4359
|
}
|
|
@@ -4323,6 +4449,9 @@ var collectFromExpression = (expr, collector) => {
|
|
|
4323
4449
|
case "LogicalExpression":
|
|
4324
4450
|
expr.operands.forEach((operand) => collectFromExpression(operand, collector));
|
|
4325
4451
|
break;
|
|
4452
|
+
case "NotExpression":
|
|
4453
|
+
collectFromExpression(expr.operand, collector);
|
|
4454
|
+
break;
|
|
4326
4455
|
case "NullExpression":
|
|
4327
4456
|
collectFromOperand(expr.left, collector);
|
|
4328
4457
|
break;
|
|
@@ -4429,6 +4558,11 @@ var mapExpression = (expr, fromTable, toTable) => {
|
|
|
4429
4558
|
if (nextOperands.every((op, i) => op === expr.operands[i])) return expr;
|
|
4430
4559
|
return { ...expr, operands: nextOperands };
|
|
4431
4560
|
}
|
|
4561
|
+
case "NotExpression": {
|
|
4562
|
+
const operand = mapExpression(expr.operand, fromTable, toTable);
|
|
4563
|
+
if (operand === expr.operand) return expr;
|
|
4564
|
+
return { ...expr, operand };
|
|
4565
|
+
}
|
|
4432
4566
|
case "NullExpression": {
|
|
4433
4567
|
const left2 = mapOperand(expr.left, fromTable, toTable);
|
|
4434
4568
|
if (left2 === expr.left) return expr;
|
|
@@ -4729,6 +4863,9 @@ var addRelationJoin = (params) => {
|
|
|
4729
4863
|
);
|
|
4730
4864
|
return joins.reduce((curr, join) => curr.withJoin(join), state);
|
|
4731
4865
|
}
|
|
4866
|
+
if (!isSingleTargetRelation(relation)) {
|
|
4867
|
+
throw new Error("Polymorphic MorphTo relations do not support join-based strategies");
|
|
4868
|
+
}
|
|
4732
4869
|
let targetSource = tableSource ?? {
|
|
4733
4870
|
type: "Table",
|
|
4734
4871
|
name: relation.target.name,
|
|
@@ -4744,6 +4881,9 @@ var addRelationJoin = (params) => {
|
|
|
4744
4881
|
var updateRelationJoin = (params) => {
|
|
4745
4882
|
const { joins, joinIndex, relation, currentTable, currentAlias, options } = params;
|
|
4746
4883
|
const join = joins[joinIndex];
|
|
4884
|
+
if (!isSingleTargetRelation(relation)) {
|
|
4885
|
+
throw new Error("Polymorphic MorphTo relations do not support join updates");
|
|
4886
|
+
}
|
|
4747
4887
|
const targetName = resolveTargetTableName(join.table, relation.target.name);
|
|
4748
4888
|
const extra = remapExpressionTable(options.filter, relation.target.name, targetName);
|
|
4749
4889
|
if (relation.type === RelationKinds.BelongsToMany) {
|
|
@@ -4803,6 +4943,9 @@ var RelationCteBuilder = class {
|
|
|
4803
4943
|
if (!predicate) {
|
|
4804
4944
|
throw new Error("Unable to build filter CTE without predicates.");
|
|
4805
4945
|
}
|
|
4946
|
+
if (!isSingleTargetRelation(relation)) {
|
|
4947
|
+
throw new Error("Polymorphic MorphTo relations do not support filter CTEs");
|
|
4948
|
+
}
|
|
4806
4949
|
const columns = Object.keys(relation.target.columns).map((name) => ({
|
|
4807
4950
|
type: "Column",
|
|
4808
4951
|
table: relation.target.name,
|
|
@@ -4850,6 +4993,9 @@ var buildTypedSelection = (columns, prefix, keys, missingMsg, tableOverride) =>
|
|
|
4850
4993
|
}, {});
|
|
4851
4994
|
};
|
|
4852
4995
|
var resolveTargetColumns = (relation, options) => {
|
|
4996
|
+
if (!isSingleTargetRelation(relation)) {
|
|
4997
|
+
return [];
|
|
4998
|
+
}
|
|
4853
4999
|
const requestedColumns = options?.columns?.length ? [...options.columns] : Object.keys(relation.target.columns);
|
|
4854
5000
|
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
4855
5001
|
if (!requestedColumns.includes(targetPrimaryKey)) {
|
|
@@ -4941,11 +5087,41 @@ var belongsToManyStrategy = (context) => {
|
|
|
4941
5087
|
);
|
|
4942
5088
|
return { state, hydration };
|
|
4943
5089
|
};
|
|
5090
|
+
var morphIncludeStrategy = (context) => {
|
|
5091
|
+
let { state, hydration } = context;
|
|
5092
|
+
const relation = context.relation;
|
|
5093
|
+
const targetColumns = resolveTargetColumns(relation, context.options);
|
|
5094
|
+
const tableOverride = getJoinCorrelationName(state, context.relationName, relation.target.name);
|
|
5095
|
+
const targetSelection = buildTypedSelection(
|
|
5096
|
+
relation.target.columns,
|
|
5097
|
+
context.aliasPrefix,
|
|
5098
|
+
targetColumns,
|
|
5099
|
+
(key) => `Column '${key}' not found on relation '${context.relationName}'`,
|
|
5100
|
+
tableOverride
|
|
5101
|
+
);
|
|
5102
|
+
const relationSelectionResult = context.selectColumns(state, hydration, targetSelection);
|
|
5103
|
+
state = relationSelectionResult.state;
|
|
5104
|
+
hydration = relationSelectionResult.hydration;
|
|
5105
|
+
hydration = hydration.onRelationIncluded(
|
|
5106
|
+
state,
|
|
5107
|
+
relation,
|
|
5108
|
+
context.relationName,
|
|
5109
|
+
context.aliasPrefix,
|
|
5110
|
+
targetColumns
|
|
5111
|
+
);
|
|
5112
|
+
return { state, hydration };
|
|
5113
|
+
};
|
|
5114
|
+
var morphToIncludeStrategy = () => {
|
|
5115
|
+
throw new Error("MorphTo relations do not support JOIN-based include. Use lazy loading instead.");
|
|
5116
|
+
};
|
|
4944
5117
|
var relationIncludeStrategies = {
|
|
4945
5118
|
[RelationKinds.HasMany]: standardIncludeStrategy,
|
|
4946
5119
|
[RelationKinds.HasOne]: standardIncludeStrategy,
|
|
4947
5120
|
[RelationKinds.BelongsTo]: standardIncludeStrategy,
|
|
4948
|
-
[RelationKinds.BelongsToMany]: belongsToManyStrategy
|
|
5121
|
+
[RelationKinds.BelongsToMany]: belongsToManyStrategy,
|
|
5122
|
+
[RelationKinds.MorphOne]: morphIncludeStrategy,
|
|
5123
|
+
[RelationKinds.MorphMany]: morphIncludeStrategy,
|
|
5124
|
+
[RelationKinds.MorphTo]: morphToIncludeStrategy
|
|
4949
5125
|
};
|
|
4950
5126
|
|
|
4951
5127
|
// src/query-builder/relation-service.ts
|
|
@@ -5014,6 +5190,12 @@ var RelationService = class {
|
|
|
5014
5190
|
let state = this.state;
|
|
5015
5191
|
let hydration = this.hydration;
|
|
5016
5192
|
const relation = this.getRelation(relationName);
|
|
5193
|
+
if (relation.type === RelationKinds.MorphTo) {
|
|
5194
|
+
throw new Error(`MorphTo relation '${relationName}' does not support include() via JOIN. Use lazy loading ($load) instead.`);
|
|
5195
|
+
}
|
|
5196
|
+
if (!isSingleTargetRelation(relation)) {
|
|
5197
|
+
return { state, hydration };
|
|
5198
|
+
}
|
|
5017
5199
|
const aliasPrefix = options?.aliasPrefix ?? relationName;
|
|
5018
5200
|
const alreadyJoined = hasJoinForRelationKey(state.ast.joins, relationName);
|
|
5019
5201
|
const { selfFilters, crossFilters } = splitFilterExpressions(
|
|
@@ -5072,6 +5254,9 @@ var RelationService = class {
|
|
|
5072
5254
|
*/
|
|
5073
5255
|
applyRelationCorrelation(relationName, ast, additionalCorrelation) {
|
|
5074
5256
|
const relation = this.getRelation(relationName);
|
|
5257
|
+
if (relation.type === RelationKinds.MorphTo) {
|
|
5258
|
+
throw new Error(`MorphTo relation '${relationName}' does not support correlation-based operations.`);
|
|
5259
|
+
}
|
|
5075
5260
|
const rootAlias = this.state.ast.from.type === "Table" ? this.state.ast.from.alias : void 0;
|
|
5076
5261
|
let correlation = buildRelationCorrelation(this.table, relation, rootAlias);
|
|
5077
5262
|
if (additionalCorrelation) {
|
|
@@ -5531,6 +5716,45 @@ var populateHydrationCache = (entity, row, meta) => {
|
|
|
5531
5716
|
}
|
|
5532
5717
|
}
|
|
5533
5718
|
}
|
|
5719
|
+
for (const relationName of Object.keys(meta.table.relations)) {
|
|
5720
|
+
const relation = meta.table.relations[relationName];
|
|
5721
|
+
const data = row[relationName];
|
|
5722
|
+
if (relation.type === RelationKinds.MorphOne) {
|
|
5723
|
+
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
5724
|
+
const rootValue = entity[localKey];
|
|
5725
|
+
if (rootValue === void 0 || rootValue === null) continue;
|
|
5726
|
+
if (!data || typeof data !== "object") continue;
|
|
5727
|
+
const cache = /* @__PURE__ */ new Map();
|
|
5728
|
+
cache.set(toKey2(rootValue), data);
|
|
5729
|
+
meta.relationHydration.set(relationName, cache);
|
|
5730
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
5731
|
+
continue;
|
|
5732
|
+
}
|
|
5733
|
+
if (relation.type === RelationKinds.MorphMany) {
|
|
5734
|
+
if (!Array.isArray(data)) continue;
|
|
5735
|
+
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
5736
|
+
const rootValue = entity[localKey];
|
|
5737
|
+
if (rootValue === void 0 || rootValue === null) continue;
|
|
5738
|
+
const cache = /* @__PURE__ */ new Map();
|
|
5739
|
+
cache.set(toKey2(rootValue), data);
|
|
5740
|
+
meta.relationHydration.set(relationName, cache);
|
|
5741
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
5742
|
+
continue;
|
|
5743
|
+
}
|
|
5744
|
+
if (relation.type === RelationKinds.MorphTo) {
|
|
5745
|
+
if (!data || typeof data !== "object") continue;
|
|
5746
|
+
const morphTo2 = relation;
|
|
5747
|
+
const typeValue = entity[morphTo2.typeField];
|
|
5748
|
+
const idValue = entity[morphTo2.idField];
|
|
5749
|
+
if (!typeValue || idValue === void 0 || idValue === null) continue;
|
|
5750
|
+
const compositeKey = `${toKey2(typeValue)}:${toKey2(idValue)}`;
|
|
5751
|
+
const cache = /* @__PURE__ */ new Map();
|
|
5752
|
+
cache.set(compositeKey, data);
|
|
5753
|
+
meta.relationHydration.set(relationName, cache);
|
|
5754
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
5755
|
+
continue;
|
|
5756
|
+
}
|
|
5757
|
+
}
|
|
5534
5758
|
};
|
|
5535
5759
|
|
|
5536
5760
|
// src/orm/relations/has-many.ts
|
|
@@ -6203,113 +6427,519 @@ var DefaultManyToManyCollection = class {
|
|
|
6203
6427
|
}
|
|
6204
6428
|
};
|
|
6205
6429
|
|
|
6206
|
-
// src/orm/
|
|
6207
|
-
var hasColumns = (columns) => Boolean(columns && columns.length > 0);
|
|
6208
|
-
var buildColumnSelection = (table, columns, missingMsg) => {
|
|
6209
|
-
return columns.reduce((acc, column) => {
|
|
6210
|
-
const def = table.columns[column];
|
|
6211
|
-
if (!def) {
|
|
6212
|
-
throw new Error(missingMsg(column));
|
|
6213
|
-
}
|
|
6214
|
-
acc[column] = def;
|
|
6215
|
-
return acc;
|
|
6216
|
-
}, {});
|
|
6217
|
-
};
|
|
6218
|
-
var filterRow = (row, columns) => {
|
|
6219
|
-
const filtered = {};
|
|
6220
|
-
for (const column of columns) {
|
|
6221
|
-
if (column in row) {
|
|
6222
|
-
filtered[column] = row[column];
|
|
6223
|
-
}
|
|
6224
|
-
}
|
|
6225
|
-
return filtered;
|
|
6226
|
-
};
|
|
6227
|
-
var filterRows = (rows, columns) => rows.map((row) => filterRow(row, columns));
|
|
6228
|
-
var rowsFromResults = (results) => {
|
|
6229
|
-
const rows = [];
|
|
6230
|
-
for (const result of results) {
|
|
6231
|
-
const { columns, values } = result;
|
|
6232
|
-
for (const valueRow of values) {
|
|
6233
|
-
const row = {};
|
|
6234
|
-
columns.forEach((column, idx) => {
|
|
6235
|
-
row[column] = valueRow[idx];
|
|
6236
|
-
});
|
|
6237
|
-
rows.push(row);
|
|
6238
|
-
}
|
|
6239
|
-
}
|
|
6240
|
-
return rows;
|
|
6241
|
-
};
|
|
6242
|
-
var executeQuery = async (ctx, qb) => {
|
|
6243
|
-
const compiled = ctx.dialect.compileSelect(qb.getAST());
|
|
6244
|
-
const results = await ctx.executor.executeSql(compiled.sql, compiled.params);
|
|
6245
|
-
return rowsFromResults(results);
|
|
6246
|
-
};
|
|
6430
|
+
// src/orm/relations/morph-one.ts
|
|
6247
6431
|
var toKey7 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
6248
|
-
var
|
|
6249
|
-
const
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6432
|
+
var hideInternal5 = (obj, keys) => {
|
|
6433
|
+
for (const key of keys) {
|
|
6434
|
+
Object.defineProperty(obj, key, {
|
|
6435
|
+
value: obj[key],
|
|
6436
|
+
writable: false,
|
|
6437
|
+
configurable: false,
|
|
6438
|
+
enumerable: false
|
|
6439
|
+
});
|
|
6255
6440
|
}
|
|
6256
|
-
return collected;
|
|
6257
6441
|
};
|
|
6258
|
-
var
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6442
|
+
var hideWritable5 = (obj, keys) => {
|
|
6443
|
+
for (const key of keys) {
|
|
6444
|
+
const value = obj[key];
|
|
6445
|
+
Object.defineProperty(obj, key, {
|
|
6446
|
+
value,
|
|
6447
|
+
writable: true,
|
|
6448
|
+
configurable: true,
|
|
6449
|
+
enumerable: false
|
|
6450
|
+
});
|
|
6264
6451
|
}
|
|
6265
|
-
return executeQuery(ctx, qb);
|
|
6266
6452
|
};
|
|
6267
|
-
var
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6453
|
+
var DefaultMorphOneReference = class {
|
|
6454
|
+
constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, localKey) {
|
|
6455
|
+
this.ctx = ctx;
|
|
6456
|
+
this.meta = meta;
|
|
6457
|
+
this.root = root;
|
|
6458
|
+
this.relationName = relationName;
|
|
6459
|
+
this.relation = relation;
|
|
6460
|
+
this.rootTable = rootTable;
|
|
6461
|
+
this.loader = loader;
|
|
6462
|
+
this.createEntity = createEntity;
|
|
6463
|
+
this.localKey = localKey;
|
|
6464
|
+
hideInternal5(this, [
|
|
6465
|
+
"ctx",
|
|
6466
|
+
"meta",
|
|
6467
|
+
"root",
|
|
6468
|
+
"relationName",
|
|
6469
|
+
"relation",
|
|
6470
|
+
"rootTable",
|
|
6471
|
+
"loader",
|
|
6472
|
+
"createEntity",
|
|
6473
|
+
"localKey"
|
|
6474
|
+
]);
|
|
6475
|
+
hideWritable5(this, ["loaded", "current"]);
|
|
6476
|
+
this.populateFromHydrationCache();
|
|
6276
6477
|
}
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
const
|
|
6283
|
-
if (
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
lookup.set(key, row);
|
|
6478
|
+
loaded = false;
|
|
6479
|
+
current = null;
|
|
6480
|
+
async load() {
|
|
6481
|
+
if (this.loaded) return this.current;
|
|
6482
|
+
const map = await this.loader();
|
|
6483
|
+
const keyValue = this.root[this.localKey];
|
|
6484
|
+
if (keyValue === void 0 || keyValue === null) {
|
|
6485
|
+
this.loaded = true;
|
|
6486
|
+
return this.current;
|
|
6287
6487
|
}
|
|
6488
|
+
const row = map.get(toKey7(keyValue));
|
|
6489
|
+
this.current = row ? this.createEntity(row) : null;
|
|
6490
|
+
this.loaded = true;
|
|
6491
|
+
return this.current;
|
|
6288
6492
|
}
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
// src/orm/lazy-batch/has-many.ts
|
|
6293
|
-
var loadHasManyRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
6294
|
-
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
6295
|
-
const roots = ctx.getEntitiesForTable(rootTable);
|
|
6296
|
-
const keys = collectKeysFromRoots(roots, localKey);
|
|
6297
|
-
if (!keys.size) {
|
|
6298
|
-
return /* @__PURE__ */ new Map();
|
|
6299
|
-
}
|
|
6300
|
-
const fkColumn = relation.target.columns[relation.foreignKey];
|
|
6301
|
-
if (!fkColumn) return /* @__PURE__ */ new Map();
|
|
6302
|
-
const requestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
6303
|
-
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
6304
|
-
const selectedColumns = requestedColumns ? [...requestedColumns] : Object.keys(relation.target.columns);
|
|
6305
|
-
if (!selectedColumns.includes(targetPrimaryKey)) {
|
|
6306
|
-
selectedColumns.push(targetPrimaryKey);
|
|
6493
|
+
get() {
|
|
6494
|
+
return this.current;
|
|
6307
6495
|
}
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6496
|
+
set(data) {
|
|
6497
|
+
if (data === null) {
|
|
6498
|
+
return this.detachCurrent();
|
|
6499
|
+
}
|
|
6500
|
+
const entity = hasEntityMeta(data) ? data : this.createEntity(data);
|
|
6501
|
+
if (this.current && this.current !== entity) {
|
|
6502
|
+
this.ctx.registerRelationChange(
|
|
6503
|
+
this.root,
|
|
6504
|
+
this.relationKey,
|
|
6505
|
+
this.rootTable,
|
|
6506
|
+
this.relationName,
|
|
6507
|
+
this.relation,
|
|
6508
|
+
{ kind: "remove", entity: this.current }
|
|
6509
|
+
);
|
|
6510
|
+
}
|
|
6511
|
+
this.assignMorphKeys(entity);
|
|
6512
|
+
this.current = entity;
|
|
6513
|
+
this.loaded = true;
|
|
6514
|
+
this.ctx.registerRelationChange(
|
|
6515
|
+
this.root,
|
|
6516
|
+
this.relationKey,
|
|
6517
|
+
this.rootTable,
|
|
6518
|
+
this.relationName,
|
|
6519
|
+
this.relation,
|
|
6520
|
+
{ kind: "attach", entity }
|
|
6521
|
+
);
|
|
6522
|
+
return entity;
|
|
6523
|
+
}
|
|
6524
|
+
toJSON() {
|
|
6525
|
+
if (!this.current) return null;
|
|
6526
|
+
const entityWithToJSON = this.current;
|
|
6527
|
+
return typeof entityWithToJSON.toJSON === "function" ? entityWithToJSON.toJSON() : this.current;
|
|
6528
|
+
}
|
|
6529
|
+
detachCurrent() {
|
|
6530
|
+
const previous = this.current;
|
|
6531
|
+
if (!previous) return null;
|
|
6532
|
+
this.current = null;
|
|
6533
|
+
this.loaded = true;
|
|
6534
|
+
this.ctx.registerRelationChange(
|
|
6535
|
+
this.root,
|
|
6536
|
+
this.relationKey,
|
|
6537
|
+
this.rootTable,
|
|
6538
|
+
this.relationName,
|
|
6539
|
+
this.relation,
|
|
6540
|
+
{ kind: "remove", entity: previous }
|
|
6541
|
+
);
|
|
6542
|
+
return null;
|
|
6543
|
+
}
|
|
6544
|
+
assignMorphKeys(entity) {
|
|
6545
|
+
const keyValue = this.root[this.localKey];
|
|
6546
|
+
entity[this.relation.idField] = keyValue;
|
|
6547
|
+
entity[this.relation.typeField] = this.relation.typeValue;
|
|
6548
|
+
}
|
|
6549
|
+
get relationKey() {
|
|
6550
|
+
return `${this.rootTable.name}.${this.relationName}`;
|
|
6551
|
+
}
|
|
6552
|
+
populateFromHydrationCache() {
|
|
6553
|
+
const keyValue = this.root[this.localKey];
|
|
6554
|
+
if (keyValue === void 0 || keyValue === null) return;
|
|
6555
|
+
const row = getHydrationRecord(this.meta, this.relationName, keyValue);
|
|
6556
|
+
if (!row) return;
|
|
6557
|
+
this.current = this.createEntity(row);
|
|
6558
|
+
this.loaded = true;
|
|
6559
|
+
}
|
|
6560
|
+
};
|
|
6561
|
+
|
|
6562
|
+
// src/orm/relations/morph-many.ts
|
|
6563
|
+
var toKey8 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
6564
|
+
var hideInternal6 = (obj, keys) => {
|
|
6565
|
+
for (const key of keys) {
|
|
6566
|
+
Object.defineProperty(obj, key, {
|
|
6567
|
+
value: obj[key],
|
|
6568
|
+
writable: false,
|
|
6569
|
+
configurable: false,
|
|
6570
|
+
enumerable: false
|
|
6571
|
+
});
|
|
6572
|
+
}
|
|
6573
|
+
};
|
|
6574
|
+
var hideWritable6 = (obj, keys) => {
|
|
6575
|
+
for (const key of keys) {
|
|
6576
|
+
const value = obj[key];
|
|
6577
|
+
Object.defineProperty(obj, key, {
|
|
6578
|
+
value,
|
|
6579
|
+
writable: true,
|
|
6580
|
+
configurable: true,
|
|
6581
|
+
enumerable: false
|
|
6582
|
+
});
|
|
6583
|
+
}
|
|
6584
|
+
};
|
|
6585
|
+
var DefaultMorphManyCollection = class {
|
|
6586
|
+
constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, localKey) {
|
|
6587
|
+
this.ctx = ctx;
|
|
6588
|
+
this.meta = meta;
|
|
6589
|
+
this.root = root;
|
|
6590
|
+
this.relationName = relationName;
|
|
6591
|
+
this.relation = relation;
|
|
6592
|
+
this.rootTable = rootTable;
|
|
6593
|
+
this.loader = loader;
|
|
6594
|
+
this.createEntity = createEntity;
|
|
6595
|
+
this.localKey = localKey;
|
|
6596
|
+
hideInternal6(this, ["ctx", "meta", "root", "relationName", "relation", "rootTable", "loader", "createEntity", "localKey"]);
|
|
6597
|
+
hideWritable6(this, ["loaded", "items", "added", "removed"]);
|
|
6598
|
+
this.hydrateFromCache();
|
|
6599
|
+
}
|
|
6600
|
+
loaded = false;
|
|
6601
|
+
items = [];
|
|
6602
|
+
added = /* @__PURE__ */ new Set();
|
|
6603
|
+
removed = /* @__PURE__ */ new Set();
|
|
6604
|
+
async load() {
|
|
6605
|
+
if (this.loaded) return this.items;
|
|
6606
|
+
const map = await this.loader();
|
|
6607
|
+
const key = toKey8(this.root[this.localKey]);
|
|
6608
|
+
const rows = map.get(key) ?? [];
|
|
6609
|
+
this.items = rows.map((row) => this.createEntity(row));
|
|
6610
|
+
this.loaded = true;
|
|
6611
|
+
return this.items;
|
|
6612
|
+
}
|
|
6613
|
+
getItems() {
|
|
6614
|
+
return this.items;
|
|
6615
|
+
}
|
|
6616
|
+
get length() {
|
|
6617
|
+
return this.items.length;
|
|
6618
|
+
}
|
|
6619
|
+
[Symbol.iterator]() {
|
|
6620
|
+
return this.items[Symbol.iterator]();
|
|
6621
|
+
}
|
|
6622
|
+
add(data) {
|
|
6623
|
+
const keyValue = this.root[this.localKey];
|
|
6624
|
+
const childRow = {
|
|
6625
|
+
...data,
|
|
6626
|
+
[this.relation.idField]: keyValue,
|
|
6627
|
+
[this.relation.typeField]: this.relation.typeValue
|
|
6628
|
+
};
|
|
6629
|
+
const entity = this.createEntity(childRow);
|
|
6630
|
+
this.added.add(entity);
|
|
6631
|
+
this.items.push(entity);
|
|
6632
|
+
this.ctx.registerRelationChange(
|
|
6633
|
+
this.root,
|
|
6634
|
+
this.relationKey,
|
|
6635
|
+
this.rootTable,
|
|
6636
|
+
this.relationName,
|
|
6637
|
+
this.relation,
|
|
6638
|
+
{ kind: "add", entity }
|
|
6639
|
+
);
|
|
6640
|
+
return entity;
|
|
6641
|
+
}
|
|
6642
|
+
attach(entity) {
|
|
6643
|
+
const keyValue = this.root[this.localKey];
|
|
6644
|
+
entity[this.relation.idField] = keyValue;
|
|
6645
|
+
entity[this.relation.typeField] = this.relation.typeValue;
|
|
6646
|
+
this.ctx.markDirty(entity);
|
|
6647
|
+
this.items.push(entity);
|
|
6648
|
+
this.ctx.registerRelationChange(
|
|
6649
|
+
this.root,
|
|
6650
|
+
this.relationKey,
|
|
6651
|
+
this.rootTable,
|
|
6652
|
+
this.relationName,
|
|
6653
|
+
this.relation,
|
|
6654
|
+
{ kind: "attach", entity }
|
|
6655
|
+
);
|
|
6656
|
+
}
|
|
6657
|
+
remove(entity) {
|
|
6658
|
+
this.items = this.items.filter((item) => item !== entity);
|
|
6659
|
+
this.removed.add(entity);
|
|
6660
|
+
this.ctx.registerRelationChange(
|
|
6661
|
+
this.root,
|
|
6662
|
+
this.relationKey,
|
|
6663
|
+
this.rootTable,
|
|
6664
|
+
this.relationName,
|
|
6665
|
+
this.relation,
|
|
6666
|
+
{ kind: "remove", entity }
|
|
6667
|
+
);
|
|
6668
|
+
}
|
|
6669
|
+
clear() {
|
|
6670
|
+
for (const entity of [...this.items]) {
|
|
6671
|
+
this.remove(entity);
|
|
6672
|
+
}
|
|
6673
|
+
}
|
|
6674
|
+
get relationKey() {
|
|
6675
|
+
return `${this.rootTable.name}.${this.relationName}`;
|
|
6676
|
+
}
|
|
6677
|
+
hydrateFromCache() {
|
|
6678
|
+
const keyValue = this.root[this.localKey];
|
|
6679
|
+
if (keyValue === void 0 || keyValue === null) return;
|
|
6680
|
+
const rows = getHydrationRows(this.meta, this.relationName, keyValue);
|
|
6681
|
+
if (!rows?.length) return;
|
|
6682
|
+
this.items = rows.map((row) => this.createEntity(row));
|
|
6683
|
+
this.loaded = true;
|
|
6684
|
+
}
|
|
6685
|
+
toJSON() {
|
|
6686
|
+
return this.items.map((item) => {
|
|
6687
|
+
const entityWithToJSON = item;
|
|
6688
|
+
return typeof entityWithToJSON.toJSON === "function" ? entityWithToJSON.toJSON() : item;
|
|
6689
|
+
});
|
|
6690
|
+
}
|
|
6691
|
+
};
|
|
6692
|
+
|
|
6693
|
+
// src/orm/relations/morph-to.ts
|
|
6694
|
+
var toKey9 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
6695
|
+
var hideInternal7 = (obj, keys) => {
|
|
6696
|
+
for (const key of keys) {
|
|
6697
|
+
Object.defineProperty(obj, key, {
|
|
6698
|
+
value: obj[key],
|
|
6699
|
+
writable: false,
|
|
6700
|
+
configurable: false,
|
|
6701
|
+
enumerable: false
|
|
6702
|
+
});
|
|
6703
|
+
}
|
|
6704
|
+
};
|
|
6705
|
+
var hideWritable7 = (obj, keys) => {
|
|
6706
|
+
for (const key of keys) {
|
|
6707
|
+
const value = obj[key];
|
|
6708
|
+
Object.defineProperty(obj, key, {
|
|
6709
|
+
value,
|
|
6710
|
+
writable: true,
|
|
6711
|
+
configurable: true,
|
|
6712
|
+
enumerable: false
|
|
6713
|
+
});
|
|
6714
|
+
}
|
|
6715
|
+
};
|
|
6716
|
+
var DefaultMorphToReference = class {
|
|
6717
|
+
constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, resolveTargetTable) {
|
|
6718
|
+
this.ctx = ctx;
|
|
6719
|
+
this.meta = meta;
|
|
6720
|
+
this.root = root;
|
|
6721
|
+
this.relationName = relationName;
|
|
6722
|
+
this.relation = relation;
|
|
6723
|
+
this.rootTable = rootTable;
|
|
6724
|
+
this.loader = loader;
|
|
6725
|
+
this.createEntity = createEntity;
|
|
6726
|
+
this.resolveTargetTable = resolveTargetTable;
|
|
6727
|
+
hideInternal7(this, [
|
|
6728
|
+
"ctx",
|
|
6729
|
+
"meta",
|
|
6730
|
+
"root",
|
|
6731
|
+
"relationName",
|
|
6732
|
+
"relation",
|
|
6733
|
+
"rootTable",
|
|
6734
|
+
"loader",
|
|
6735
|
+
"createEntity",
|
|
6736
|
+
"resolveTargetTable"
|
|
6737
|
+
]);
|
|
6738
|
+
hideWritable7(this, ["loaded", "current"]);
|
|
6739
|
+
this.populateFromHydrationCache();
|
|
6740
|
+
}
|
|
6741
|
+
loaded = false;
|
|
6742
|
+
current = null;
|
|
6743
|
+
async load() {
|
|
6744
|
+
if (this.loaded) return this.current;
|
|
6745
|
+
const rootObj = this.root;
|
|
6746
|
+
const typeValue = rootObj[this.relation.typeField];
|
|
6747
|
+
const idValue = rootObj[this.relation.idField];
|
|
6748
|
+
if (!typeValue || idValue === void 0 || idValue === null) {
|
|
6749
|
+
this.loaded = true;
|
|
6750
|
+
return this.current;
|
|
6751
|
+
}
|
|
6752
|
+
const map = await this.loader();
|
|
6753
|
+
const compositeKey = `${toKey9(typeValue)}:${toKey9(idValue)}`;
|
|
6754
|
+
const row = map.get(compositeKey);
|
|
6755
|
+
if (row) {
|
|
6756
|
+
const targetTable = this.resolveTargetTable(toKey9(typeValue));
|
|
6757
|
+
if (targetTable) {
|
|
6758
|
+
this.current = this.createEntity(targetTable, row);
|
|
6759
|
+
}
|
|
6760
|
+
}
|
|
6761
|
+
this.loaded = true;
|
|
6762
|
+
return this.current;
|
|
6763
|
+
}
|
|
6764
|
+
get() {
|
|
6765
|
+
return this.current;
|
|
6766
|
+
}
|
|
6767
|
+
set(data) {
|
|
6768
|
+
if (data === null) {
|
|
6769
|
+
return this.detachCurrent();
|
|
6770
|
+
}
|
|
6771
|
+
const entity = hasEntityMeta(data) ? data : data;
|
|
6772
|
+
if (this.current && this.current !== entity) {
|
|
6773
|
+
this.ctx.registerRelationChange(
|
|
6774
|
+
this.root,
|
|
6775
|
+
this.relationKey,
|
|
6776
|
+
this.rootTable,
|
|
6777
|
+
this.relationName,
|
|
6778
|
+
this.relation,
|
|
6779
|
+
{ kind: "remove", entity: this.current }
|
|
6780
|
+
);
|
|
6781
|
+
}
|
|
6782
|
+
this.current = entity;
|
|
6783
|
+
this.loaded = true;
|
|
6784
|
+
this.ctx.registerRelationChange(
|
|
6785
|
+
this.root,
|
|
6786
|
+
this.relationKey,
|
|
6787
|
+
this.rootTable,
|
|
6788
|
+
this.relationName,
|
|
6789
|
+
this.relation,
|
|
6790
|
+
{ kind: "attach", entity }
|
|
6791
|
+
);
|
|
6792
|
+
return entity;
|
|
6793
|
+
}
|
|
6794
|
+
toJSON() {
|
|
6795
|
+
if (!this.current) return null;
|
|
6796
|
+
const entityWithToJSON = this.current;
|
|
6797
|
+
return typeof entityWithToJSON.toJSON === "function" ? entityWithToJSON.toJSON() : this.current;
|
|
6798
|
+
}
|
|
6799
|
+
detachCurrent() {
|
|
6800
|
+
const previous = this.current;
|
|
6801
|
+
if (!previous) return null;
|
|
6802
|
+
this.current = null;
|
|
6803
|
+
this.loaded = true;
|
|
6804
|
+
const rootObj = this.root;
|
|
6805
|
+
rootObj[this.relation.typeField] = null;
|
|
6806
|
+
rootObj[this.relation.idField] = null;
|
|
6807
|
+
this.ctx.registerRelationChange(
|
|
6808
|
+
this.root,
|
|
6809
|
+
this.relationKey,
|
|
6810
|
+
this.rootTable,
|
|
6811
|
+
this.relationName,
|
|
6812
|
+
this.relation,
|
|
6813
|
+
{ kind: "remove", entity: previous }
|
|
6814
|
+
);
|
|
6815
|
+
return null;
|
|
6816
|
+
}
|
|
6817
|
+
get relationKey() {
|
|
6818
|
+
return `${this.rootTable.name}.${this.relationName}`;
|
|
6819
|
+
}
|
|
6820
|
+
populateFromHydrationCache() {
|
|
6821
|
+
const rootObj = this.root;
|
|
6822
|
+
const typeValue = rootObj[this.relation.typeField];
|
|
6823
|
+
const idValue = rootObj[this.relation.idField];
|
|
6824
|
+
if (!typeValue || idValue === void 0 || idValue === null) return;
|
|
6825
|
+
const compositeKey = `${toKey9(typeValue)}:${toKey9(idValue)}`;
|
|
6826
|
+
const row = getHydrationRecord(this.meta, this.relationName, compositeKey);
|
|
6827
|
+
if (!row) return;
|
|
6828
|
+
const targetTable = this.resolveTargetTable(toKey9(typeValue));
|
|
6829
|
+
if (targetTable) {
|
|
6830
|
+
this.current = this.createEntity(targetTable, row);
|
|
6831
|
+
this.loaded = true;
|
|
6832
|
+
}
|
|
6833
|
+
}
|
|
6834
|
+
};
|
|
6835
|
+
|
|
6836
|
+
// src/orm/lazy-batch/shared.ts
|
|
6837
|
+
var hasColumns = (columns) => Boolean(columns && columns.length > 0);
|
|
6838
|
+
var buildColumnSelection = (table, columns, missingMsg) => {
|
|
6839
|
+
return columns.reduce((acc, column) => {
|
|
6840
|
+
const def = table.columns[column];
|
|
6841
|
+
if (!def) {
|
|
6842
|
+
throw new Error(missingMsg(column));
|
|
6843
|
+
}
|
|
6844
|
+
acc[column] = def;
|
|
6845
|
+
return acc;
|
|
6846
|
+
}, {});
|
|
6847
|
+
};
|
|
6848
|
+
var filterRow = (row, columns) => {
|
|
6849
|
+
const filtered = {};
|
|
6850
|
+
for (const column of columns) {
|
|
6851
|
+
if (column in row) {
|
|
6852
|
+
filtered[column] = row[column];
|
|
6853
|
+
}
|
|
6854
|
+
}
|
|
6855
|
+
return filtered;
|
|
6856
|
+
};
|
|
6857
|
+
var filterRows = (rows, columns) => rows.map((row) => filterRow(row, columns));
|
|
6858
|
+
var rowsFromResults = (results) => {
|
|
6859
|
+
const rows = [];
|
|
6860
|
+
for (const result of results) {
|
|
6861
|
+
const { columns, values } = result;
|
|
6862
|
+
for (const valueRow of values) {
|
|
6863
|
+
const row = {};
|
|
6864
|
+
columns.forEach((column, idx) => {
|
|
6865
|
+
row[column] = valueRow[idx];
|
|
6866
|
+
});
|
|
6867
|
+
rows.push(row);
|
|
6868
|
+
}
|
|
6869
|
+
}
|
|
6870
|
+
return rows;
|
|
6871
|
+
};
|
|
6872
|
+
var executeQuery = async (ctx, qb) => {
|
|
6873
|
+
const compiled = ctx.dialect.compileSelect(qb.getAST());
|
|
6874
|
+
const results = await ctx.executor.executeSql(compiled.sql, compiled.params);
|
|
6875
|
+
return rowsFromResults(results);
|
|
6876
|
+
};
|
|
6877
|
+
var toKey10 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
6878
|
+
var collectKeysFromRoots = (roots, key) => {
|
|
6879
|
+
const collected = /* @__PURE__ */ new Set();
|
|
6880
|
+
for (const tracked of roots) {
|
|
6881
|
+
const value = tracked.entity[key];
|
|
6882
|
+
if (value !== null && value !== void 0) {
|
|
6883
|
+
collected.add(value);
|
|
6884
|
+
}
|
|
6885
|
+
}
|
|
6886
|
+
return collected;
|
|
6887
|
+
};
|
|
6888
|
+
var buildInListValues = (keys) => Array.from(keys);
|
|
6889
|
+
var fetchRowsForKeys = async (ctx, table, column, keys, selection, filter) => {
|
|
6890
|
+
let qb = new SelectQueryBuilder(table).select(selection);
|
|
6891
|
+
qb = qb.where(inList(column, buildInListValues(keys)));
|
|
6892
|
+
if (filter) {
|
|
6893
|
+
qb = qb.where(filter);
|
|
6894
|
+
}
|
|
6895
|
+
return executeQuery(ctx, qb);
|
|
6896
|
+
};
|
|
6897
|
+
var groupRowsByMany = (rows, keyColumn) => {
|
|
6898
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
6899
|
+
for (const row of rows) {
|
|
6900
|
+
const value = row[keyColumn];
|
|
6901
|
+
if (value === null || value === void 0) continue;
|
|
6902
|
+
const key = toKey10(value);
|
|
6903
|
+
const bucket = grouped.get(key) ?? [];
|
|
6904
|
+
bucket.push(row);
|
|
6905
|
+
grouped.set(key, bucket);
|
|
6906
|
+
}
|
|
6907
|
+
return grouped;
|
|
6908
|
+
};
|
|
6909
|
+
var groupRowsByUnique = (rows, keyColumn) => {
|
|
6910
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
6911
|
+
for (const row of rows) {
|
|
6912
|
+
const value = row[keyColumn];
|
|
6913
|
+
if (value === null || value === void 0) continue;
|
|
6914
|
+
const key = toKey10(value);
|
|
6915
|
+
if (!lookup.has(key)) {
|
|
6916
|
+
lookup.set(key, row);
|
|
6917
|
+
}
|
|
6918
|
+
}
|
|
6919
|
+
return lookup;
|
|
6920
|
+
};
|
|
6921
|
+
|
|
6922
|
+
// src/orm/lazy-batch/has-many.ts
|
|
6923
|
+
var loadHasManyRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
6924
|
+
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
6925
|
+
const roots = ctx.getEntitiesForTable(rootTable);
|
|
6926
|
+
const keys = collectKeysFromRoots(roots, localKey);
|
|
6927
|
+
if (!keys.size) {
|
|
6928
|
+
return /* @__PURE__ */ new Map();
|
|
6929
|
+
}
|
|
6930
|
+
const fkColumn = relation.target.columns[relation.foreignKey];
|
|
6931
|
+
if (!fkColumn) return /* @__PURE__ */ new Map();
|
|
6932
|
+
const requestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
6933
|
+
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
6934
|
+
const selectedColumns = requestedColumns ? [...requestedColumns] : Object.keys(relation.target.columns);
|
|
6935
|
+
if (!selectedColumns.includes(targetPrimaryKey)) {
|
|
6936
|
+
selectedColumns.push(targetPrimaryKey);
|
|
6937
|
+
}
|
|
6938
|
+
const queryColumns = new Set(selectedColumns);
|
|
6939
|
+
queryColumns.add(relation.foreignKey);
|
|
6940
|
+
const selection = buildColumnSelection(
|
|
6941
|
+
relation.target,
|
|
6942
|
+
Array.from(queryColumns),
|
|
6313
6943
|
(column) => `Column '${column}' not found on relation '${relationName}'`
|
|
6314
6944
|
);
|
|
6315
6945
|
const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys, selection, options?.filter);
|
|
@@ -6466,12 +7096,12 @@ var loadBelongsToManyRelation = async (ctx, rootTable, relationName, relation, o
|
|
|
6466
7096
|
if (rootValue === null || rootValue === void 0 || targetValue === null || targetValue === void 0) {
|
|
6467
7097
|
continue;
|
|
6468
7098
|
}
|
|
6469
|
-
const bucket = rootLookup.get(
|
|
7099
|
+
const bucket = rootLookup.get(toKey10(rootValue)) ?? [];
|
|
6470
7100
|
bucket.push({
|
|
6471
7101
|
targetId: targetValue,
|
|
6472
7102
|
pivot: pivotVisibleColumns.size ? filterRow(pivot, pivotVisibleColumns) : {}
|
|
6473
7103
|
});
|
|
6474
|
-
rootLookup.set(
|
|
7104
|
+
rootLookup.set(toKey10(rootValue), bucket);
|
|
6475
7105
|
targetIds.add(targetValue);
|
|
6476
7106
|
}
|
|
6477
7107
|
if (!targetIds.size) {
|
|
@@ -6504,7 +7134,7 @@ var loadBelongsToManyRelation = async (ctx, rootTable, relationName, relation, o
|
|
|
6504
7134
|
for (const [rootId, entries] of rootLookup.entries()) {
|
|
6505
7135
|
const bucket = [];
|
|
6506
7136
|
for (const entry of entries) {
|
|
6507
|
-
const targetRow = targetMap.get(
|
|
7137
|
+
const targetRow = targetMap.get(toKey10(entry.targetId));
|
|
6508
7138
|
if (!targetRow) continue;
|
|
6509
7139
|
const row = targetRequestedColumns ? filterRow(targetRow, targetVisibleColumns) : { ...targetRow };
|
|
6510
7140
|
if (options?.pivot?.merge) {
|
|
@@ -6523,6 +7153,123 @@ var mergePivotIntoRow = (row, pivot) => {
|
|
|
6523
7153
|
}
|
|
6524
7154
|
};
|
|
6525
7155
|
|
|
7156
|
+
// src/orm/lazy-batch/morph-one.ts
|
|
7157
|
+
var loadMorphOneRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
7158
|
+
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
7159
|
+
const roots = ctx.getEntitiesForTable(rootTable);
|
|
7160
|
+
const keys = collectKeysFromRoots(roots, localKey);
|
|
7161
|
+
if (!keys.size) {
|
|
7162
|
+
return /* @__PURE__ */ new Map();
|
|
7163
|
+
}
|
|
7164
|
+
const fkColumn = relation.target.columns[relation.idField];
|
|
7165
|
+
if (!fkColumn) return /* @__PURE__ */ new Map();
|
|
7166
|
+
const requestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
7167
|
+
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
7168
|
+
const selectedColumns = requestedColumns ? [...requestedColumns] : Object.keys(relation.target.columns);
|
|
7169
|
+
if (!selectedColumns.includes(targetPrimaryKey)) {
|
|
7170
|
+
selectedColumns.push(targetPrimaryKey);
|
|
7171
|
+
}
|
|
7172
|
+
const queryColumns = new Set(selectedColumns);
|
|
7173
|
+
queryColumns.add(relation.idField);
|
|
7174
|
+
const selection = buildColumnSelection(
|
|
7175
|
+
relation.target,
|
|
7176
|
+
Array.from(queryColumns),
|
|
7177
|
+
(column) => `Column '${column}' not found on relation '${relationName}'`
|
|
7178
|
+
);
|
|
7179
|
+
const typeColumn = relation.target.columns[relation.typeField];
|
|
7180
|
+
const discriminatorFilter = eq(
|
|
7181
|
+
typeColumn ?? { type: "Column", table: relation.target.name, name: relation.typeField },
|
|
7182
|
+
{ type: "Literal", value: relation.typeValue }
|
|
7183
|
+
);
|
|
7184
|
+
const combinedFilter = options?.filter ? and(options.filter, discriminatorFilter) : discriminatorFilter;
|
|
7185
|
+
const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys, selection, combinedFilter);
|
|
7186
|
+
const grouped = groupRowsByUnique(rows, relation.idField);
|
|
7187
|
+
if (!requestedColumns) return grouped;
|
|
7188
|
+
const visibleColumns = new Set(selectedColumns);
|
|
7189
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
7190
|
+
for (const [key, row] of grouped.entries()) {
|
|
7191
|
+
filtered.set(key, filterRow(row, visibleColumns));
|
|
7192
|
+
}
|
|
7193
|
+
return filtered;
|
|
7194
|
+
};
|
|
7195
|
+
|
|
7196
|
+
// src/orm/lazy-batch/morph-many.ts
|
|
7197
|
+
var loadMorphManyRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
7198
|
+
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
7199
|
+
const roots = ctx.getEntitiesForTable(rootTable);
|
|
7200
|
+
const keys = collectKeysFromRoots(roots, localKey);
|
|
7201
|
+
if (!keys.size) {
|
|
7202
|
+
return /* @__PURE__ */ new Map();
|
|
7203
|
+
}
|
|
7204
|
+
const fkColumn = relation.target.columns[relation.idField];
|
|
7205
|
+
if (!fkColumn) return /* @__PURE__ */ new Map();
|
|
7206
|
+
const requestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
7207
|
+
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
7208
|
+
const selectedColumns = requestedColumns ? [...requestedColumns] : Object.keys(relation.target.columns);
|
|
7209
|
+
if (!selectedColumns.includes(targetPrimaryKey)) {
|
|
7210
|
+
selectedColumns.push(targetPrimaryKey);
|
|
7211
|
+
}
|
|
7212
|
+
const queryColumns = new Set(selectedColumns);
|
|
7213
|
+
queryColumns.add(relation.idField);
|
|
7214
|
+
const selection = buildColumnSelection(
|
|
7215
|
+
relation.target,
|
|
7216
|
+
Array.from(queryColumns),
|
|
7217
|
+
(column) => `Column '${column}' not found on relation '${relationName}'`
|
|
7218
|
+
);
|
|
7219
|
+
const typeColumn = relation.target.columns[relation.typeField];
|
|
7220
|
+
const discriminatorFilter = eq(
|
|
7221
|
+
typeColumn ?? { type: "Column", table: relation.target.name, name: relation.typeField },
|
|
7222
|
+
{ type: "Literal", value: relation.typeValue }
|
|
7223
|
+
);
|
|
7224
|
+
const combinedFilter = options?.filter ? and(options.filter, discriminatorFilter) : discriminatorFilter;
|
|
7225
|
+
const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys, selection, combinedFilter);
|
|
7226
|
+
const grouped = groupRowsByMany(rows, relation.idField);
|
|
7227
|
+
if (!requestedColumns) return grouped;
|
|
7228
|
+
const visibleColumns = new Set(selectedColumns);
|
|
7229
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
7230
|
+
for (const [key, bucket] of grouped.entries()) {
|
|
7231
|
+
filtered.set(key, filterRows(bucket, visibleColumns));
|
|
7232
|
+
}
|
|
7233
|
+
return filtered;
|
|
7234
|
+
};
|
|
7235
|
+
|
|
7236
|
+
// src/orm/lazy-batch/morph-to.ts
|
|
7237
|
+
var loadMorphToRelation = async (ctx, rootTable, _relationName, relation) => {
|
|
7238
|
+
const roots = ctx.getEntitiesForTable(rootTable);
|
|
7239
|
+
const result = /* @__PURE__ */ new Map();
|
|
7240
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
7241
|
+
for (const tracked of roots) {
|
|
7242
|
+
const entity = tracked.entity;
|
|
7243
|
+
const typeValue = entity[relation.typeField];
|
|
7244
|
+
const idValue = entity[relation.idField];
|
|
7245
|
+
if (!typeValue || idValue === void 0 || idValue === null) continue;
|
|
7246
|
+
const typeKey = toKey10(typeValue);
|
|
7247
|
+
const ids = grouped.get(typeKey) ?? /* @__PURE__ */ new Set();
|
|
7248
|
+
ids.add(idValue);
|
|
7249
|
+
grouped.set(typeKey, ids);
|
|
7250
|
+
}
|
|
7251
|
+
for (const [typeKey, ids] of grouped.entries()) {
|
|
7252
|
+
const targetTable = relation.targets[typeKey];
|
|
7253
|
+
if (!targetTable) continue;
|
|
7254
|
+
const targetPk = relation.targetKey || findPrimaryKey(targetTable);
|
|
7255
|
+
const pkColumn = targetTable.columns[targetPk];
|
|
7256
|
+
if (!pkColumn) continue;
|
|
7257
|
+
const selection = buildColumnSelection(
|
|
7258
|
+
targetTable,
|
|
7259
|
+
Object.keys(targetTable.columns),
|
|
7260
|
+
(column) => `Column '${column}' not found on target '${targetTable.name}'`
|
|
7261
|
+
);
|
|
7262
|
+
const rows = await fetchRowsForKeys(ctx, targetTable, pkColumn, ids, selection);
|
|
7263
|
+
for (const row of rows) {
|
|
7264
|
+
const pkValue = row[targetPk];
|
|
7265
|
+
if (pkValue === void 0 || pkValue === null) continue;
|
|
7266
|
+
const compositeKey = `${typeKey}:${toKey10(pkValue)}`;
|
|
7267
|
+
result.set(compositeKey, row);
|
|
7268
|
+
}
|
|
7269
|
+
}
|
|
7270
|
+
return result;
|
|
7271
|
+
};
|
|
7272
|
+
|
|
6526
7273
|
// src/orm/entity-relation-cache.ts
|
|
6527
7274
|
var relationLoaderCache = (meta, relationName, factory) => {
|
|
6528
7275
|
if (meta.relationCache.has(relationName)) {
|
|
@@ -6684,8 +7431,62 @@ var instantiateWrapper = (meta, relationName, relation, owner, createEntity) =>
|
|
|
6684
7431
|
many,
|
|
6685
7432
|
meta.table,
|
|
6686
7433
|
loader,
|
|
6687
|
-
(row) => createEntity(relation.target, row),
|
|
6688
|
-
localKey
|
|
7434
|
+
(row) => createEntity(relation.target, row),
|
|
7435
|
+
localKey
|
|
7436
|
+
);
|
|
7437
|
+
}
|
|
7438
|
+
case RelationKinds.MorphOne: {
|
|
7439
|
+
const morphOne2 = relation;
|
|
7440
|
+
const localKey = morphOne2.localKey || findPrimaryKey(meta.table);
|
|
7441
|
+
const loader = () => loadCached(
|
|
7442
|
+
() => loadMorphOneRelation(meta.ctx, meta.table, relationName, morphOne2, resolveOptions())
|
|
7443
|
+
);
|
|
7444
|
+
return new DefaultMorphOneReference(
|
|
7445
|
+
meta.ctx,
|
|
7446
|
+
metaBase,
|
|
7447
|
+
owner,
|
|
7448
|
+
relationName,
|
|
7449
|
+
morphOne2,
|
|
7450
|
+
meta.table,
|
|
7451
|
+
loader,
|
|
7452
|
+
(row) => createEntity(morphOne2.target, row),
|
|
7453
|
+
localKey
|
|
7454
|
+
);
|
|
7455
|
+
}
|
|
7456
|
+
case RelationKinds.MorphMany: {
|
|
7457
|
+
const morphMany2 = relation;
|
|
7458
|
+
const localKey = morphMany2.localKey || findPrimaryKey(meta.table);
|
|
7459
|
+
const loader = () => loadCached(
|
|
7460
|
+
() => loadMorphManyRelation(meta.ctx, meta.table, relationName, morphMany2, resolveOptions())
|
|
7461
|
+
);
|
|
7462
|
+
return new DefaultMorphManyCollection(
|
|
7463
|
+
meta.ctx,
|
|
7464
|
+
metaBase,
|
|
7465
|
+
owner,
|
|
7466
|
+
relationName,
|
|
7467
|
+
morphMany2,
|
|
7468
|
+
meta.table,
|
|
7469
|
+
loader,
|
|
7470
|
+
(row) => createEntity(morphMany2.target, row),
|
|
7471
|
+
localKey
|
|
7472
|
+
);
|
|
7473
|
+
}
|
|
7474
|
+
case RelationKinds.MorphTo: {
|
|
7475
|
+
const morphTo2 = relation;
|
|
7476
|
+
const loader = () => loadCached(
|
|
7477
|
+
() => loadMorphToRelation(meta.ctx, meta.table, relationName, morphTo2)
|
|
7478
|
+
);
|
|
7479
|
+
const resolveTargetTable = (typeValue) => morphTo2.targets[typeValue];
|
|
7480
|
+
return new DefaultMorphToReference(
|
|
7481
|
+
meta.ctx,
|
|
7482
|
+
metaBase,
|
|
7483
|
+
owner,
|
|
7484
|
+
relationName,
|
|
7485
|
+
morphTo2,
|
|
7486
|
+
meta.table,
|
|
7487
|
+
loader,
|
|
7488
|
+
(table, row) => createEntity(table, row),
|
|
7489
|
+
resolveTargetTable
|
|
6689
7490
|
);
|
|
6690
7491
|
}
|
|
6691
7492
|
default:
|
|
@@ -6713,7 +7514,7 @@ var createEntityProxy = (ctx, table, row, lazyRelations = [], lazyRelationOption
|
|
|
6713
7514
|
const isCollectionRelation = (relationName) => {
|
|
6714
7515
|
const rel = table.relations[relationName];
|
|
6715
7516
|
if (!rel) return false;
|
|
6716
|
-
return rel.type === RelationKinds.HasMany || rel.type === RelationKinds.BelongsToMany;
|
|
7517
|
+
return rel.type === RelationKinds.HasMany || rel.type === RelationKinds.BelongsToMany || rel.type === RelationKinds.MorphMany;
|
|
6717
7518
|
};
|
|
6718
7519
|
const buildJson = (self, options) => {
|
|
6719
7520
|
const json = {};
|
|
@@ -6895,9 +7696,11 @@ function rowsToQueryResult(rows) {
|
|
|
6895
7696
|
}
|
|
6896
7697
|
function createExecutorFromQueryRunner(runner) {
|
|
6897
7698
|
const supportsTransactions = typeof runner.beginTransaction === "function" && typeof runner.commitTransaction === "function" && typeof runner.rollbackTransaction === "function";
|
|
7699
|
+
const supportsSavepoints = supportsTransactions && typeof runner.savepoint === "function" && typeof runner.releaseSavepoint === "function" && typeof runner.rollbackToSavepoint === "function";
|
|
6898
7700
|
return {
|
|
6899
7701
|
capabilities: {
|
|
6900
|
-
transactions: supportsTransactions
|
|
7702
|
+
transactions: supportsTransactions,
|
|
7703
|
+
...supportsSavepoints ? { savepoints: true } : {}
|
|
6901
7704
|
},
|
|
6902
7705
|
async executeSql(sql, params) {
|
|
6903
7706
|
const rows = await runner.query(sql, params);
|
|
@@ -6922,6 +7725,24 @@ function createExecutorFromQueryRunner(runner) {
|
|
|
6922
7725
|
}
|
|
6923
7726
|
await runner.rollbackTransaction.call(runner);
|
|
6924
7727
|
},
|
|
7728
|
+
async savepoint(name) {
|
|
7729
|
+
if (!supportsSavepoints) {
|
|
7730
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
7731
|
+
}
|
|
7732
|
+
await runner.savepoint.call(runner, name);
|
|
7733
|
+
},
|
|
7734
|
+
async releaseSavepoint(name) {
|
|
7735
|
+
if (!supportsSavepoints) {
|
|
7736
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
7737
|
+
}
|
|
7738
|
+
await runner.releaseSavepoint.call(runner, name);
|
|
7739
|
+
},
|
|
7740
|
+
async rollbackToSavepoint(name) {
|
|
7741
|
+
if (!supportsSavepoints) {
|
|
7742
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
7743
|
+
}
|
|
7744
|
+
await runner.rollbackToSavepoint.call(runner, name);
|
|
7745
|
+
},
|
|
6925
7746
|
async dispose() {
|
|
6926
7747
|
await runner.dispose?.call(runner);
|
|
6927
7748
|
}
|
|
@@ -7296,6 +8117,9 @@ function buildWhereHasPredicate(env, context, relationFacet, createChildBuilder,
|
|
|
7296
8117
|
}
|
|
7297
8118
|
const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
|
|
7298
8119
|
const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
|
|
8120
|
+
if (!isSingleTargetRelation(relation)) {
|
|
8121
|
+
throw new Error(`Polymorphic relation '${relationName}' does not support whereHas/whereHasNot`);
|
|
8122
|
+
}
|
|
7299
8123
|
let subQb = createChildBuilder(relation.target);
|
|
7300
8124
|
if (callback) {
|
|
7301
8125
|
subQb = callback(subQb);
|
|
@@ -7310,6 +8134,193 @@ function buildWhereHasPredicate(env, context, relationFacet, createChildBuilder,
|
|
|
7310
8134
|
return negate ? notExists(finalSubAst) : exists(finalSubAst);
|
|
7311
8135
|
}
|
|
7312
8136
|
|
|
8137
|
+
// src/query-builder/select/cursor-pagination.ts
|
|
8138
|
+
function encodeCursor(payload) {
|
|
8139
|
+
return Buffer.from(JSON.stringify(payload)).toString("base64url");
|
|
8140
|
+
}
|
|
8141
|
+
function decodeCursor(cursor) {
|
|
8142
|
+
let parsed;
|
|
8143
|
+
try {
|
|
8144
|
+
parsed = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
|
|
8145
|
+
} catch {
|
|
8146
|
+
throw new Error("executeCursor: invalid cursor format");
|
|
8147
|
+
}
|
|
8148
|
+
if (typeof parsed !== "object" || parsed === null || parsed.v !== 2 || !Array.isArray(parsed.values) || typeof parsed.orderSig !== "string") {
|
|
8149
|
+
throw new Error("executeCursor: invalid cursor payload");
|
|
8150
|
+
}
|
|
8151
|
+
return parsed;
|
|
8152
|
+
}
|
|
8153
|
+
function buildOrderSignature(specs) {
|
|
8154
|
+
return specs.map((s) => `${s.table}.${s.column}:${s.direction}`).join(",");
|
|
8155
|
+
}
|
|
8156
|
+
function extractOrderSpecs(ast) {
|
|
8157
|
+
if (!ast.orderBy || ast.orderBy.length === 0) {
|
|
8158
|
+
throw new Error("executeCursor: ORDER BY is required for cursor pagination");
|
|
8159
|
+
}
|
|
8160
|
+
return ast.orderBy.map((ob) => {
|
|
8161
|
+
if (ob.nulls) {
|
|
8162
|
+
throw new Error("executeCursor: NULLS FIRST/LAST is not supported for cursor pagination");
|
|
8163
|
+
}
|
|
8164
|
+
const term = ob.term;
|
|
8165
|
+
if (!term || term.type !== "Column") {
|
|
8166
|
+
throw new Error(
|
|
8167
|
+
"executeCursor: only column references are supported in ORDER BY for cursor pagination"
|
|
8168
|
+
);
|
|
8169
|
+
}
|
|
8170
|
+
const col2 = term;
|
|
8171
|
+
return {
|
|
8172
|
+
table: col2.table,
|
|
8173
|
+
column: col2.name,
|
|
8174
|
+
valueKey: resolveOrderValueKey(ast, col2),
|
|
8175
|
+
direction: ob.direction
|
|
8176
|
+
};
|
|
8177
|
+
});
|
|
8178
|
+
}
|
|
8179
|
+
function resolveOrderValueKey(ast, col2) {
|
|
8180
|
+
const projectedColumn = ast.columns.find(
|
|
8181
|
+
(candidate) => candidate.type === "Column" && candidate.table === col2.table && candidate.name === col2.name
|
|
8182
|
+
);
|
|
8183
|
+
return projectedColumn?.alias ?? projectedColumn?.name ?? col2.alias ?? col2.name;
|
|
8184
|
+
}
|
|
8185
|
+
function buildKeysetPredicate(specs, values, mode) {
|
|
8186
|
+
if (values.length !== specs.length) {
|
|
8187
|
+
throw new Error("executeCursor: invalid cursor payload");
|
|
8188
|
+
}
|
|
8189
|
+
const branches = [];
|
|
8190
|
+
for (let i = 0; i < specs.length; i++) {
|
|
8191
|
+
const spec = specs[i];
|
|
8192
|
+
const colNode = { type: "Column", table: spec.table, name: spec.column };
|
|
8193
|
+
const value = values[i];
|
|
8194
|
+
if (value === null || value === void 0) {
|
|
8195
|
+
throw new Error("executeCursor: invalid cursor payload");
|
|
8196
|
+
}
|
|
8197
|
+
const literal = { type: "Literal", value };
|
|
8198
|
+
let operator;
|
|
8199
|
+
if (mode === "after") {
|
|
8200
|
+
operator = spec.direction === "ASC" ? ">" : "<";
|
|
8201
|
+
} else {
|
|
8202
|
+
operator = spec.direction === "ASC" ? "<" : ">";
|
|
8203
|
+
}
|
|
8204
|
+
const eqParts = [];
|
|
8205
|
+
for (let j = 0; j < i; j++) {
|
|
8206
|
+
const prevSpec = specs[j];
|
|
8207
|
+
const prevCol = { type: "Column", table: prevSpec.table, name: prevSpec.column };
|
|
8208
|
+
const prevValue = values[j];
|
|
8209
|
+
if (prevValue === null || prevValue === void 0) {
|
|
8210
|
+
throw new Error("executeCursor: invalid cursor payload");
|
|
8211
|
+
}
|
|
8212
|
+
const prevVal = { type: "Literal", value: prevValue };
|
|
8213
|
+
eqParts.push({
|
|
8214
|
+
type: "BinaryExpression",
|
|
8215
|
+
left: prevCol,
|
|
8216
|
+
operator: "=",
|
|
8217
|
+
right: prevVal
|
|
8218
|
+
});
|
|
8219
|
+
}
|
|
8220
|
+
const breakExpr = {
|
|
8221
|
+
type: "BinaryExpression",
|
|
8222
|
+
left: colNode,
|
|
8223
|
+
operator,
|
|
8224
|
+
right: literal
|
|
8225
|
+
};
|
|
8226
|
+
if (eqParts.length === 0) {
|
|
8227
|
+
branches.push(breakExpr);
|
|
8228
|
+
} else {
|
|
8229
|
+
branches.push(and(...eqParts, breakExpr));
|
|
8230
|
+
}
|
|
8231
|
+
}
|
|
8232
|
+
return branches.length === 1 ? branches[0] : or(...branches);
|
|
8233
|
+
}
|
|
8234
|
+
function buildCursorFromRow(row, specs) {
|
|
8235
|
+
const values = specs.map((spec) => {
|
|
8236
|
+
const value = row[spec.valueKey];
|
|
8237
|
+
if (value === null || value === void 0) {
|
|
8238
|
+
throw new Error("executeCursor: cursor pagination requires non-null ORDER BY values");
|
|
8239
|
+
}
|
|
8240
|
+
return value;
|
|
8241
|
+
});
|
|
8242
|
+
return encodeCursor({ v: 2, values, orderSig: buildOrderSignature(specs) });
|
|
8243
|
+
}
|
|
8244
|
+
function reverseDirection(direction) {
|
|
8245
|
+
return direction === "ASC" ? "DESC" : "ASC";
|
|
8246
|
+
}
|
|
8247
|
+
function createExecutionBuilder(builder, options) {
|
|
8248
|
+
const internals = builder.getInternals();
|
|
8249
|
+
const baseAst = internals.context.state.ast;
|
|
8250
|
+
const orderBy = options.reverseOrder && baseAst.orderBy ? baseAst.orderBy.map((order) => ({
|
|
8251
|
+
...order,
|
|
8252
|
+
direction: reverseDirection(order.direction)
|
|
8253
|
+
})) : baseAst.orderBy;
|
|
8254
|
+
const nextAst = {
|
|
8255
|
+
...baseAst,
|
|
8256
|
+
where: options.predicate ? baseAst.where ? and(baseAst.where, options.predicate) : options.predicate : baseAst.where,
|
|
8257
|
+
orderBy,
|
|
8258
|
+
limit: options.limit
|
|
8259
|
+
};
|
|
8260
|
+
const nextContext = {
|
|
8261
|
+
...internals.context,
|
|
8262
|
+
state: new SelectQueryState(builder.getTable(), nextAst)
|
|
8263
|
+
};
|
|
8264
|
+
return internals.clone(nextContext, internals.includeTree);
|
|
8265
|
+
}
|
|
8266
|
+
async function executeCursorQuery(builder, session, options) {
|
|
8267
|
+
const { first, after, last, before } = options;
|
|
8268
|
+
if (first != null && last != null) {
|
|
8269
|
+
throw new Error('executeCursor: "first" and "last" cannot be used together');
|
|
8270
|
+
}
|
|
8271
|
+
if (after != null && before != null) {
|
|
8272
|
+
throw new Error('executeCursor: "after" and "before" cannot be used together');
|
|
8273
|
+
}
|
|
8274
|
+
if (first == null && last == null) {
|
|
8275
|
+
throw new Error('executeCursor: either "first" or "last" must be provided');
|
|
8276
|
+
}
|
|
8277
|
+
const limit = first ?? last;
|
|
8278
|
+
if (!Number.isInteger(limit) || limit < 1) {
|
|
8279
|
+
throw new Error(`executeCursor: "${first != null ? "first" : "last"}" must be an integer >= 1`);
|
|
8280
|
+
}
|
|
8281
|
+
const isBackward = last != null;
|
|
8282
|
+
const cursor = after ?? before;
|
|
8283
|
+
const ast = builder.getInternals().context.state.ast;
|
|
8284
|
+
const specs = extractOrderSpecs(ast);
|
|
8285
|
+
let predicate;
|
|
8286
|
+
if (cursor) {
|
|
8287
|
+
const decoded = decodeCursor(cursor);
|
|
8288
|
+
const expectedSig = buildOrderSignature(specs);
|
|
8289
|
+
if (decoded.orderSig !== expectedSig) {
|
|
8290
|
+
throw new Error(
|
|
8291
|
+
"executeCursor: cursor ORDER BY signature does not match the current query. The ORDER BY clause must remain the same between paginated requests."
|
|
8292
|
+
);
|
|
8293
|
+
}
|
|
8294
|
+
predicate = buildKeysetPredicate(specs, decoded.values, isBackward ? "before" : "after");
|
|
8295
|
+
}
|
|
8296
|
+
const executionBuilder = createExecutionBuilder(builder, {
|
|
8297
|
+
predicate,
|
|
8298
|
+
limit: limit + 1,
|
|
8299
|
+
reverseOrder: isBackward
|
|
8300
|
+
});
|
|
8301
|
+
const rows = await executionBuilder.execute(session);
|
|
8302
|
+
const hasExtraItem = rows.length > limit;
|
|
8303
|
+
if (hasExtraItem) {
|
|
8304
|
+
rows.pop();
|
|
8305
|
+
}
|
|
8306
|
+
const orderedRows = isBackward ? rows.reverse() : rows;
|
|
8307
|
+
const items = orderedRows;
|
|
8308
|
+
const hasItems = items.length > 0;
|
|
8309
|
+
const hasNextPage2 = hasItems ? isBackward ? before != null : hasExtraItem : false;
|
|
8310
|
+
const hasPreviousPage = hasItems ? isBackward ? hasExtraItem : after != null : false;
|
|
8311
|
+
const startCursor = hasItems ? buildCursorFromRow(items[0], specs) : null;
|
|
8312
|
+
const endCursor = hasItems ? buildCursorFromRow(items[items.length - 1], specs) : null;
|
|
8313
|
+
return {
|
|
8314
|
+
items,
|
|
8315
|
+
pageInfo: {
|
|
8316
|
+
hasNextPage: hasNextPage2,
|
|
8317
|
+
hasPreviousPage,
|
|
8318
|
+
startCursor,
|
|
8319
|
+
endCursor
|
|
8320
|
+
}
|
|
8321
|
+
};
|
|
8322
|
+
}
|
|
8323
|
+
|
|
7313
8324
|
// src/query-builder/select/from-facet.ts
|
|
7314
8325
|
var SelectFromFacet = class {
|
|
7315
8326
|
/**
|
|
@@ -8336,7 +9347,38 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8336
9347
|
return executePagedQuery(builder, session, options, (sess) => builder.count(sess));
|
|
8337
9348
|
}
|
|
8338
9349
|
/**
|
|
8339
|
-
* Executes the query
|
|
9350
|
+
* Executes the query using cursor-based (keyset) pagination.
|
|
9351
|
+
* Requires a stable ORDER BY on selected, non-null columns.
|
|
9352
|
+
* Cursor pagination currently supports simple column references only and
|
|
9353
|
+
* the cursor token is opaque: it must be reused with the same ORDER BY signature.
|
|
9354
|
+
*
|
|
9355
|
+
* @param session - ORM session context
|
|
9356
|
+
* @param options - Cursor pagination options (`first`/`after` or `last`/`before`)
|
|
9357
|
+
* @returns Promise of cursor-paginated result with items and pageInfo
|
|
9358
|
+
* @example
|
|
9359
|
+
* const page1 = await selectFrom(users)
|
|
9360
|
+
* .orderBy(users.columns.createdAt, 'DESC')
|
|
9361
|
+
* .orderBy(users.columns.id, 'DESC')
|
|
9362
|
+
* .executeCursor(session, { first: 20 });
|
|
9363
|
+
*
|
|
9364
|
+
* // Next page
|
|
9365
|
+
* const page2 = await selectFrom(users)
|
|
9366
|
+
* .orderBy(users.columns.createdAt, 'DESC')
|
|
9367
|
+
* .orderBy(users.columns.id, 'DESC')
|
|
9368
|
+
* .executeCursor(session, { first: 20, after: page1.pageInfo.endCursor });
|
|
9369
|
+
*
|
|
9370
|
+
* // Previous page from a known cursor
|
|
9371
|
+
* const prevPage = await selectFrom(users)
|
|
9372
|
+
* .orderBy(users.columns.createdAt, 'DESC')
|
|
9373
|
+
* .orderBy(users.columns.id, 'DESC')
|
|
9374
|
+
* .executeCursor(session, { last: 20, before: page2.pageInfo.startCursor });
|
|
9375
|
+
*/
|
|
9376
|
+
async executeCursor(session, options) {
|
|
9377
|
+
const builder = this.ensureDefaultSelection();
|
|
9378
|
+
return executeCursorQuery(builder, session, options);
|
|
9379
|
+
}
|
|
9380
|
+
/**
|
|
9381
|
+
* Executes the query and returns an array of values for a single column.
|
|
8340
9382
|
* This is a convenience method to avoid manual `.map(r => r.column)`.
|
|
8341
9383
|
*
|
|
8342
9384
|
* @param column - The column name to extract
|
|
@@ -8664,6 +9706,7 @@ var isTableDef = (value) => {
|
|
|
8664
9706
|
|
|
8665
9707
|
// src/decorators/decorator-metadata.ts
|
|
8666
9708
|
var METADATA_KEY = "metal-orm:decorators";
|
|
9709
|
+
var LEGACY_METADATA_KEY = /* @__PURE__ */ Symbol.for("metal-orm:decorators:legacy");
|
|
8667
9710
|
var getOrCreateMetadataBag = (context) => {
|
|
8668
9711
|
const metadata = context.metadata || (context.metadata = {});
|
|
8669
9712
|
let bag = metadata[METADATA_KEY];
|
|
@@ -8673,16 +9716,65 @@ var getOrCreateMetadataBag = (context) => {
|
|
|
8673
9716
|
}
|
|
8674
9717
|
return bag;
|
|
8675
9718
|
};
|
|
9719
|
+
var getOrCreateMetadataBagOnConstructor = (ctor) => {
|
|
9720
|
+
const carrier = ctor;
|
|
9721
|
+
let bag = carrier[LEGACY_METADATA_KEY];
|
|
9722
|
+
if (!bag) {
|
|
9723
|
+
bag = { columns: [], relations: [], transformers: [] };
|
|
9724
|
+
carrier[LEGACY_METADATA_KEY] = bag;
|
|
9725
|
+
}
|
|
9726
|
+
return bag;
|
|
9727
|
+
};
|
|
8676
9728
|
var readMetadataBag = (context) => {
|
|
8677
9729
|
return context.metadata?.[METADATA_KEY];
|
|
8678
9730
|
};
|
|
8679
9731
|
var readMetadataBagFromConstructor = (ctor) => {
|
|
8680
9732
|
const metadataSymbol = Symbol.metadata;
|
|
8681
|
-
if (
|
|
8682
|
-
|
|
8683
|
-
|
|
9733
|
+
if (metadataSymbol) {
|
|
9734
|
+
const metadata = Reflect.get(ctor, metadataSymbol);
|
|
9735
|
+
const stage3Bag = metadata?.[METADATA_KEY];
|
|
9736
|
+
if (stage3Bag) {
|
|
9737
|
+
return stage3Bag;
|
|
9738
|
+
}
|
|
9739
|
+
}
|
|
9740
|
+
return ctor[LEGACY_METADATA_KEY];
|
|
8684
9741
|
};
|
|
8685
9742
|
var getDecoratorMetadata = (ctor) => readMetadataBagFromConstructor(ctor);
|
|
9743
|
+
var normalizePropertyName = (name) => {
|
|
9744
|
+
if (typeof name === "symbol") {
|
|
9745
|
+
return name.description ?? name.toString();
|
|
9746
|
+
}
|
|
9747
|
+
return name;
|
|
9748
|
+
};
|
|
9749
|
+
var isStage3FieldContext = (value) => {
|
|
9750
|
+
return typeof value === "object" && value !== null && "name" in value && "private" in value && "metadata" in value;
|
|
9751
|
+
};
|
|
9752
|
+
var resolveFieldDecoratorInfo = (targetOrValue, contextOrProperty, decoratorName) => {
|
|
9753
|
+
if (isStage3FieldContext(contextOrProperty)) {
|
|
9754
|
+
if (!contextOrProperty.name) {
|
|
9755
|
+
throw new Error(`${decoratorName} decorator requires a property name`);
|
|
9756
|
+
}
|
|
9757
|
+
if (contextOrProperty.private) {
|
|
9758
|
+
throw new Error(`${decoratorName} decorator does not support private fields`);
|
|
9759
|
+
}
|
|
9760
|
+
return {
|
|
9761
|
+
propertyName: normalizePropertyName(contextOrProperty.name),
|
|
9762
|
+
bag: getOrCreateMetadataBag(contextOrProperty)
|
|
9763
|
+
};
|
|
9764
|
+
}
|
|
9765
|
+
if (typeof contextOrProperty === "string" || typeof contextOrProperty === "symbol") {
|
|
9766
|
+
const legacyTarget = targetOrValue;
|
|
9767
|
+
const ctor = typeof legacyTarget === "function" ? legacyTarget : legacyTarget?.constructor;
|
|
9768
|
+
if (!ctor || typeof ctor !== "function" && typeof ctor !== "object") {
|
|
9769
|
+
throw new Error(`${decoratorName} decorator requires a class field target`);
|
|
9770
|
+
}
|
|
9771
|
+
return {
|
|
9772
|
+
propertyName: normalizePropertyName(contextOrProperty),
|
|
9773
|
+
bag: getOrCreateMetadataBagOnConstructor(ctor)
|
|
9774
|
+
};
|
|
9775
|
+
}
|
|
9776
|
+
throw new Error(`${decoratorName} decorator received an unsupported decorator context`);
|
|
9777
|
+
};
|
|
8686
9778
|
|
|
8687
9779
|
// src/decorators/bootstrap.ts
|
|
8688
9780
|
var unwrapTarget = (target) => {
|
|
@@ -8772,6 +9864,48 @@ var buildRelationDefinitions = (meta, tableMap) => {
|
|
|
8772
9864
|
);
|
|
8773
9865
|
break;
|
|
8774
9866
|
}
|
|
9867
|
+
case RelationKinds.MorphOne: {
|
|
9868
|
+
relations[name] = morphOne(
|
|
9869
|
+
resolveTableTarget(relation.target, tableMap),
|
|
9870
|
+
{
|
|
9871
|
+
as: relation.morphName,
|
|
9872
|
+
typeValue: relation.typeValue,
|
|
9873
|
+
typeField: relation.typeField,
|
|
9874
|
+
idField: relation.idField,
|
|
9875
|
+
localKey: relation.localKey,
|
|
9876
|
+
cascade: relation.cascade
|
|
9877
|
+
}
|
|
9878
|
+
);
|
|
9879
|
+
break;
|
|
9880
|
+
}
|
|
9881
|
+
case RelationKinds.MorphMany: {
|
|
9882
|
+
relations[name] = morphMany(
|
|
9883
|
+
resolveTableTarget(relation.target, tableMap),
|
|
9884
|
+
{
|
|
9885
|
+
as: relation.morphName,
|
|
9886
|
+
typeValue: relation.typeValue,
|
|
9887
|
+
typeField: relation.typeField,
|
|
9888
|
+
idField: relation.idField,
|
|
9889
|
+
localKey: relation.localKey,
|
|
9890
|
+
cascade: relation.cascade
|
|
9891
|
+
}
|
|
9892
|
+
);
|
|
9893
|
+
break;
|
|
9894
|
+
}
|
|
9895
|
+
case RelationKinds.MorphTo: {
|
|
9896
|
+
const resolvedTargets = {};
|
|
9897
|
+
for (const [typeValue, targetResolver] of Object.entries(relation.targets)) {
|
|
9898
|
+
resolvedTargets[typeValue] = resolveTableTarget(targetResolver, tableMap);
|
|
9899
|
+
}
|
|
9900
|
+
relations[name] = morphTo({
|
|
9901
|
+
typeField: relation.typeField,
|
|
9902
|
+
idField: relation.idField,
|
|
9903
|
+
targets: resolvedTargets,
|
|
9904
|
+
targetKey: relation.targetKey,
|
|
9905
|
+
cascade: relation.cascade
|
|
9906
|
+
});
|
|
9907
|
+
break;
|
|
9908
|
+
}
|
|
8775
9909
|
}
|
|
8776
9910
|
}
|
|
8777
9911
|
return relations;
|
|
@@ -8845,6 +9979,45 @@ var resolveSingleRelation = (relationName, relation, rootMeta) => {
|
|
|
8845
9979
|
}
|
|
8846
9980
|
);
|
|
8847
9981
|
}
|
|
9982
|
+
case RelationKinds.MorphOne: {
|
|
9983
|
+
return morphOne(
|
|
9984
|
+
resolveTableTarget(relation.target, tableMap),
|
|
9985
|
+
{
|
|
9986
|
+
as: relation.morphName,
|
|
9987
|
+
typeValue: relation.typeValue,
|
|
9988
|
+
typeField: relation.typeField,
|
|
9989
|
+
idField: relation.idField,
|
|
9990
|
+
localKey: relation.localKey,
|
|
9991
|
+
cascade: relation.cascade
|
|
9992
|
+
}
|
|
9993
|
+
);
|
|
9994
|
+
}
|
|
9995
|
+
case RelationKinds.MorphMany: {
|
|
9996
|
+
return morphMany(
|
|
9997
|
+
resolveTableTarget(relation.target, tableMap),
|
|
9998
|
+
{
|
|
9999
|
+
as: relation.morphName,
|
|
10000
|
+
typeValue: relation.typeValue,
|
|
10001
|
+
typeField: relation.typeField,
|
|
10002
|
+
idField: relation.idField,
|
|
10003
|
+
localKey: relation.localKey,
|
|
10004
|
+
cascade: relation.cascade
|
|
10005
|
+
}
|
|
10006
|
+
);
|
|
10007
|
+
}
|
|
10008
|
+
case RelationKinds.MorphTo: {
|
|
10009
|
+
const resolvedTargets = {};
|
|
10010
|
+
for (const [typeValue, targetResolver] of Object.entries(relation.targets)) {
|
|
10011
|
+
resolvedTargets[typeValue] = resolveTableTarget(targetResolver, tableMap);
|
|
10012
|
+
}
|
|
10013
|
+
return morphTo({
|
|
10014
|
+
typeField: relation.typeField,
|
|
10015
|
+
idField: relation.idField,
|
|
10016
|
+
targets: resolvedTargets,
|
|
10017
|
+
targetKey: relation.targetKey,
|
|
10018
|
+
cascade: relation.cascade
|
|
10019
|
+
});
|
|
10020
|
+
}
|
|
8848
10021
|
default:
|
|
8849
10022
|
throw new Error(`Unknown relation kind for relation '${relationName}'`);
|
|
8850
10023
|
}
|
|
@@ -12434,6 +13607,9 @@ var TypeScriptGenerator = class {
|
|
|
12434
13607
|
visitLogicalExpression(logical) {
|
|
12435
13608
|
return this.printLogicalExpression(logical);
|
|
12436
13609
|
}
|
|
13610
|
+
visitNotExpression(notExpr) {
|
|
13611
|
+
return this.printNotExpression(notExpr);
|
|
13612
|
+
}
|
|
12437
13613
|
visitNullExpression(nullExpr) {
|
|
12438
13614
|
return this.printNullExpression(nullExpr);
|
|
12439
13615
|
}
|
|
@@ -12509,6 +13685,9 @@ var TypeScriptGenerator = class {
|
|
|
12509
13685
|
${parts.join(",\n ")}
|
|
12510
13686
|
)`;
|
|
12511
13687
|
}
|
|
13688
|
+
printNotExpression(notExpr) {
|
|
13689
|
+
return `not(${this.printExpression(notExpr.operand)})`;
|
|
13690
|
+
}
|
|
12512
13691
|
printArithmeticExpression(expr) {
|
|
12513
13692
|
const left2 = this.printOperand(expr.left);
|
|
12514
13693
|
const right2 = this.printOperand(expr.right);
|
|
@@ -13202,6 +14381,15 @@ var RelationChangeProcessor = class {
|
|
|
13202
14381
|
case RelationKinds.BelongsTo:
|
|
13203
14382
|
await this.handleBelongsToChange(entry);
|
|
13204
14383
|
break;
|
|
14384
|
+
case RelationKinds.MorphOne:
|
|
14385
|
+
await this.handleMorphOneChange(entry);
|
|
14386
|
+
break;
|
|
14387
|
+
case RelationKinds.MorphMany:
|
|
14388
|
+
await this.handleMorphManyChange(entry);
|
|
14389
|
+
break;
|
|
14390
|
+
case RelationKinds.MorphTo:
|
|
14391
|
+
await this.handleMorphToChange(entry);
|
|
14392
|
+
break;
|
|
13205
14393
|
}
|
|
13206
14394
|
}
|
|
13207
14395
|
}
|
|
@@ -13404,6 +14592,86 @@ var RelationChangeProcessor = class {
|
|
|
13404
14592
|
}
|
|
13405
14593
|
return Object.keys(payload).length ? payload : void 0;
|
|
13406
14594
|
}
|
|
14595
|
+
async handleMorphOneChange(entry) {
|
|
14596
|
+
const relation = entry.relation;
|
|
14597
|
+
const target = entry.change.entity;
|
|
14598
|
+
if (!target) return;
|
|
14599
|
+
const tracked = this.unitOfWork.findTracked(target);
|
|
14600
|
+
if (!tracked) return;
|
|
14601
|
+
const localKey = relation.localKey || findPrimaryKey(entry.rootTable);
|
|
14602
|
+
const rootValue = entry.root[localKey];
|
|
14603
|
+
if (rootValue === void 0 || rootValue === null) return;
|
|
14604
|
+
if (entry.change.kind === "add" || entry.change.kind === "attach") {
|
|
14605
|
+
const child = tracked.entity;
|
|
14606
|
+
child[relation.idField] = rootValue;
|
|
14607
|
+
child[relation.typeField] = relation.typeValue;
|
|
14608
|
+
this.unitOfWork.markDirty(tracked.entity);
|
|
14609
|
+
return;
|
|
14610
|
+
}
|
|
14611
|
+
if (entry.change.kind === "remove") {
|
|
14612
|
+
const child = tracked.entity;
|
|
14613
|
+
if (relation.cascade === "all" || relation.cascade === "remove") {
|
|
14614
|
+
this.unitOfWork.markRemoved(child);
|
|
14615
|
+
return;
|
|
14616
|
+
}
|
|
14617
|
+
child[relation.idField] = null;
|
|
14618
|
+
child[relation.typeField] = null;
|
|
14619
|
+
this.unitOfWork.markDirty(child);
|
|
14620
|
+
}
|
|
14621
|
+
}
|
|
14622
|
+
async handleMorphManyChange(entry) {
|
|
14623
|
+
const relation = entry.relation;
|
|
14624
|
+
const target = entry.change.entity;
|
|
14625
|
+
if (!target) return;
|
|
14626
|
+
const tracked = this.unitOfWork.findTracked(target);
|
|
14627
|
+
if (!tracked) return;
|
|
14628
|
+
const localKey = relation.localKey || findPrimaryKey(entry.rootTable);
|
|
14629
|
+
const rootValue = entry.root[localKey];
|
|
14630
|
+
if (rootValue === void 0 || rootValue === null) return;
|
|
14631
|
+
if (entry.change.kind === "add" || entry.change.kind === "attach") {
|
|
14632
|
+
const child = tracked.entity;
|
|
14633
|
+
child[relation.idField] = rootValue;
|
|
14634
|
+
child[relation.typeField] = relation.typeValue;
|
|
14635
|
+
this.unitOfWork.markDirty(tracked.entity);
|
|
14636
|
+
return;
|
|
14637
|
+
}
|
|
14638
|
+
if (entry.change.kind === "remove") {
|
|
14639
|
+
const child = tracked.entity;
|
|
14640
|
+
if (relation.cascade === "all" || relation.cascade === "remove") {
|
|
14641
|
+
this.unitOfWork.markRemoved(child);
|
|
14642
|
+
return;
|
|
14643
|
+
}
|
|
14644
|
+
child[relation.idField] = null;
|
|
14645
|
+
child[relation.typeField] = null;
|
|
14646
|
+
this.unitOfWork.markDirty(child);
|
|
14647
|
+
}
|
|
14648
|
+
}
|
|
14649
|
+
async handleMorphToChange(entry) {
|
|
14650
|
+
const relation = entry.relation;
|
|
14651
|
+
const target = entry.change.entity;
|
|
14652
|
+
if (!target) return;
|
|
14653
|
+
if (entry.change.kind === "attach" || entry.change.kind === "add") {
|
|
14654
|
+
const targetEntity = target;
|
|
14655
|
+
for (const [typeValue, targetTable] of Object.entries(relation.targets)) {
|
|
14656
|
+
const targetPk = relation.targetKey || findPrimaryKey(targetTable);
|
|
14657
|
+
const pkValue = targetEntity[targetPk];
|
|
14658
|
+
if (pkValue !== void 0 && pkValue !== null) {
|
|
14659
|
+
const rootEntity = entry.root;
|
|
14660
|
+
rootEntity[relation.typeField] = typeValue;
|
|
14661
|
+
rootEntity[relation.idField] = pkValue;
|
|
14662
|
+
this.unitOfWork.markDirty(entry.root);
|
|
14663
|
+
break;
|
|
14664
|
+
}
|
|
14665
|
+
}
|
|
14666
|
+
return;
|
|
14667
|
+
}
|
|
14668
|
+
if (entry.change.kind === "remove") {
|
|
14669
|
+
const rootEntity = entry.root;
|
|
14670
|
+
rootEntity[relation.typeField] = null;
|
|
14671
|
+
rootEntity[relation.idField] = null;
|
|
14672
|
+
this.unitOfWork.markDirty(entry.root);
|
|
14673
|
+
}
|
|
14674
|
+
}
|
|
13407
14675
|
};
|
|
13408
14676
|
|
|
13409
14677
|
// src/orm/query-logger.ts
|
|
@@ -13420,6 +14688,9 @@ var createQueryLoggingExecutor = (executor, logger) => {
|
|
|
13420
14688
|
beginTransaction: () => executor.beginTransaction(),
|
|
13421
14689
|
commitTransaction: () => executor.commitTransaction(),
|
|
13422
14690
|
rollbackTransaction: () => executor.rollbackTransaction(),
|
|
14691
|
+
savepoint: executor.savepoint ? (name) => executor.savepoint(name) : void 0,
|
|
14692
|
+
releaseSavepoint: executor.releaseSavepoint ? (name) => executor.releaseSavepoint(name) : void 0,
|
|
14693
|
+
rollbackToSavepoint: executor.rollbackToSavepoint ? (name) => executor.rollbackToSavepoint(name) : void 0,
|
|
13423
14694
|
dispose: () => executor.dispose()
|
|
13424
14695
|
};
|
|
13425
14696
|
return wrapped;
|
|
@@ -13442,7 +14713,7 @@ var runInTransaction = async (executor, action) => {
|
|
|
13442
14713
|
};
|
|
13443
14714
|
|
|
13444
14715
|
// src/orm/save-graph.ts
|
|
13445
|
-
var
|
|
14716
|
+
var toKey11 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
13446
14717
|
var coerceColumnValue = (table, columnName, value, options) => {
|
|
13447
14718
|
if (value === null || value === void 0) return value;
|
|
13448
14719
|
const column = table.columns[columnName];
|
|
@@ -13504,11 +14775,11 @@ var isEntityInCollection = (items, pkName, entity) => {
|
|
|
13504
14775
|
if (items.includes(entity)) return true;
|
|
13505
14776
|
const entityPk = entity[pkName];
|
|
13506
14777
|
if (entityPk === void 0 || entityPk === null) return false;
|
|
13507
|
-
return items.some((item) =>
|
|
14778
|
+
return items.some((item) => toKey11(item[pkName]) === toKey11(entityPk));
|
|
13508
14779
|
};
|
|
13509
14780
|
var findInCollectionByPk = (items, pkName, pkValue) => {
|
|
13510
14781
|
if (pkValue === void 0 || pkValue === null) return void 0;
|
|
13511
|
-
return items.find((item) =>
|
|
14782
|
+
return items.find((item) => toKey11(item[pkName]) === toKey11(pkValue));
|
|
13512
14783
|
};
|
|
13513
14784
|
var extractPivotPayload = (payload) => {
|
|
13514
14785
|
const pivot = payload._pivot ?? payload.pivot;
|
|
@@ -13537,13 +14808,13 @@ var handleHasMany = async (session, root, relationName, relation, payload, optio
|
|
|
13537
14808
|
collection.attach(entity);
|
|
13538
14809
|
}
|
|
13539
14810
|
if (pkValue !== void 0 && pkValue !== null) {
|
|
13540
|
-
seen.add(
|
|
14811
|
+
seen.add(toKey11(pkValue));
|
|
13541
14812
|
}
|
|
13542
14813
|
}
|
|
13543
14814
|
if (options.pruneMissing) {
|
|
13544
14815
|
for (const item of [...collection.getItems()]) {
|
|
13545
14816
|
const pkValue = item[targetPk];
|
|
13546
|
-
if (pkValue !== void 0 && pkValue !== null && !seen.has(
|
|
14817
|
+
if (pkValue !== void 0 && pkValue !== null && !seen.has(toKey11(pkValue))) {
|
|
13547
14818
|
collection.remove(item);
|
|
13548
14819
|
}
|
|
13549
14820
|
}
|
|
@@ -13601,7 +14872,7 @@ var handleBelongsToMany = async (session, root, relationName, relation, payload,
|
|
|
13601
14872
|
if (typeof item === "number" || typeof item === "string") {
|
|
13602
14873
|
const id = item;
|
|
13603
14874
|
collection.attach(id);
|
|
13604
|
-
seen.add(
|
|
14875
|
+
seen.add(toKey11(id));
|
|
13605
14876
|
continue;
|
|
13606
14877
|
}
|
|
13607
14878
|
const asObj = item;
|
|
@@ -13619,18 +14890,89 @@ var handleBelongsToMany = async (session, root, relationName, relation, payload,
|
|
|
13619
14890
|
collection.attach(entity, pivotPayload);
|
|
13620
14891
|
}
|
|
13621
14892
|
if (pkValue !== void 0 && pkValue !== null) {
|
|
13622
|
-
seen.add(
|
|
14893
|
+
seen.add(toKey11(pkValue));
|
|
13623
14894
|
}
|
|
13624
14895
|
}
|
|
13625
14896
|
if (options.pruneMissing) {
|
|
13626
14897
|
for (const item of [...collection.getItems()]) {
|
|
13627
14898
|
const pkValue = item[targetPk];
|
|
13628
|
-
if (pkValue !== void 0 && pkValue !== null && !seen.has(
|
|
14899
|
+
if (pkValue !== void 0 && pkValue !== null && !seen.has(toKey11(pkValue))) {
|
|
13629
14900
|
collection.detach(item);
|
|
13630
14901
|
}
|
|
13631
14902
|
}
|
|
13632
14903
|
}
|
|
13633
14904
|
};
|
|
14905
|
+
var handleMorphOne = async (session, root, relationName, relation, payload, options) => {
|
|
14906
|
+
const ref = root[relationName];
|
|
14907
|
+
if (payload === void 0) return;
|
|
14908
|
+
if (payload === null) {
|
|
14909
|
+
ref.set(null);
|
|
14910
|
+
return;
|
|
14911
|
+
}
|
|
14912
|
+
const pk = findPrimaryKey(relation.target);
|
|
14913
|
+
if (typeof payload === "number" || typeof payload === "string") {
|
|
14914
|
+
const entity = ref.set({ [pk]: payload });
|
|
14915
|
+
if (entity) {
|
|
14916
|
+
await applyGraphToEntity(session, relation.target, entity, { [pk]: payload }, options);
|
|
14917
|
+
}
|
|
14918
|
+
return;
|
|
14919
|
+
}
|
|
14920
|
+
const attached = ref.set(payload);
|
|
14921
|
+
if (attached) {
|
|
14922
|
+
await applyGraphToEntity(session, relation.target, attached, payload, options);
|
|
14923
|
+
}
|
|
14924
|
+
};
|
|
14925
|
+
var handleMorphMany = async (session, root, relationName, relation, payload, options) => {
|
|
14926
|
+
if (!Array.isArray(payload)) return;
|
|
14927
|
+
const collection = root[relationName];
|
|
14928
|
+
await collection.load();
|
|
14929
|
+
const targetTable = relation.target;
|
|
14930
|
+
const targetPk = findPrimaryKey(targetTable);
|
|
14931
|
+
const existing = collection.getItems();
|
|
14932
|
+
const seen = /* @__PURE__ */ new Set();
|
|
14933
|
+
for (const item of payload) {
|
|
14934
|
+
if (item === null || item === void 0) continue;
|
|
14935
|
+
const asObj = typeof item === "object" ? item : { [targetPk]: item };
|
|
14936
|
+
const pkValue = asObj[targetPk];
|
|
14937
|
+
const current = findInCollectionByPk(existing, targetPk, pkValue) ?? (pkValue !== void 0 && pkValue !== null ? session.getEntity(targetTable, pkValue) : void 0);
|
|
14938
|
+
const entity = current ?? ensureEntity(session, targetTable, asObj, options);
|
|
14939
|
+
assignColumns(targetTable, entity, asObj, options);
|
|
14940
|
+
await applyGraphToEntity(session, targetTable, entity, asObj, options);
|
|
14941
|
+
if (!isEntityInCollection(collection.getItems(), targetPk, entity)) {
|
|
14942
|
+
collection.attach(entity);
|
|
14943
|
+
}
|
|
14944
|
+
if (pkValue !== void 0 && pkValue !== null) {
|
|
14945
|
+
seen.add(toKey11(pkValue));
|
|
14946
|
+
}
|
|
14947
|
+
}
|
|
14948
|
+
if (options.pruneMissing) {
|
|
14949
|
+
for (const item of [...collection.getItems()]) {
|
|
14950
|
+
const pkValue = item[targetPk];
|
|
14951
|
+
if (pkValue !== void 0 && pkValue !== null && !seen.has(toKey11(pkValue))) {
|
|
14952
|
+
collection.remove(item);
|
|
14953
|
+
}
|
|
14954
|
+
}
|
|
14955
|
+
}
|
|
14956
|
+
};
|
|
14957
|
+
var handleMorphTo = async (session, root, relationName, relation, payload, options) => {
|
|
14958
|
+
const ref = root[relationName];
|
|
14959
|
+
if (payload === void 0) return;
|
|
14960
|
+
if (payload === null) {
|
|
14961
|
+
ref.set(null);
|
|
14962
|
+
return;
|
|
14963
|
+
}
|
|
14964
|
+
const attached = ref.set(payload);
|
|
14965
|
+
if (attached) {
|
|
14966
|
+
for (const [, targetTable] of Object.entries(relation.targets)) {
|
|
14967
|
+
const pk = relation.targetKey || findPrimaryKey(targetTable);
|
|
14968
|
+
const pkValue = attached[pk];
|
|
14969
|
+
if (pkValue !== void 0 && pkValue !== null) {
|
|
14970
|
+
await applyGraphToEntity(session, targetTable, attached, payload, options);
|
|
14971
|
+
break;
|
|
14972
|
+
}
|
|
14973
|
+
}
|
|
14974
|
+
}
|
|
14975
|
+
};
|
|
13634
14976
|
var applyRelation = async (session, table, entity, relationName, relation, payload, options) => {
|
|
13635
14977
|
switch (relation.type) {
|
|
13636
14978
|
case RelationKinds.HasMany:
|
|
@@ -13641,6 +14983,12 @@ var applyRelation = async (session, table, entity, relationName, relation, paylo
|
|
|
13641
14983
|
return handleBelongsTo(session, entity, relationName, relation, payload, options);
|
|
13642
14984
|
case RelationKinds.BelongsToMany:
|
|
13643
14985
|
return handleBelongsToMany(session, entity, relationName, relation, payload, options);
|
|
14986
|
+
case RelationKinds.MorphOne:
|
|
14987
|
+
return handleMorphOne(session, entity, relationName, relation, payload, options);
|
|
14988
|
+
case RelationKinds.MorphMany:
|
|
14989
|
+
return handleMorphMany(session, entity, relationName, relation, payload, options);
|
|
14990
|
+
case RelationKinds.MorphTo:
|
|
14991
|
+
return handleMorphTo(session, entity, relationName, relation, payload, options);
|
|
13644
14992
|
}
|
|
13645
14993
|
};
|
|
13646
14994
|
var applyGraphToEntity = async (session, table, entity, payload, options) => {
|
|
@@ -13669,6 +15017,8 @@ var patchGraphInternal = async (session, entityClass, existing, payload, options
|
|
|
13669
15017
|
};
|
|
13670
15018
|
|
|
13671
15019
|
// src/orm/orm-session.ts
|
|
15020
|
+
var NESTED_TRANSACTIONS_REQUIRE_SAVEPOINTS = "Nested session.transaction calls require savepoint support in this executor";
|
|
15021
|
+
var ROLLBACK_ONLY_TRANSACTION = "Cannot commit transaction because an inner transaction failed";
|
|
13672
15022
|
var OrmSession = class {
|
|
13673
15023
|
/** The ORM instance */
|
|
13674
15024
|
orm;
|
|
@@ -13688,6 +15038,9 @@ var OrmSession = class {
|
|
|
13688
15038
|
tenantId;
|
|
13689
15039
|
interceptors;
|
|
13690
15040
|
saveGraphDefaults;
|
|
15041
|
+
transactionDepth = 0;
|
|
15042
|
+
savepointCounter = 0;
|
|
15043
|
+
rollbackOnly = false;
|
|
13691
15044
|
/**
|
|
13692
15045
|
* Creates a new OrmSession instance.
|
|
13693
15046
|
* @param opts - Session options
|
|
@@ -14030,16 +15383,43 @@ var OrmSession = class {
|
|
|
14030
15383
|
await this.commit();
|
|
14031
15384
|
return result;
|
|
14032
15385
|
}
|
|
14033
|
-
|
|
15386
|
+
const isOutermost = this.transactionDepth === 0;
|
|
15387
|
+
let savepointName = null;
|
|
15388
|
+
if (isOutermost) {
|
|
15389
|
+
this.rollbackOnly = false;
|
|
15390
|
+
await this.executor.beginTransaction();
|
|
15391
|
+
} else {
|
|
15392
|
+
this.assertSavepointSupport();
|
|
15393
|
+
savepointName = this.nextSavepointName();
|
|
15394
|
+
await this.executor.savepoint(savepointName);
|
|
15395
|
+
}
|
|
15396
|
+
this.transactionDepth += 1;
|
|
14034
15397
|
try {
|
|
14035
15398
|
const result = await fn8(this);
|
|
15399
|
+
this.throwIfRollbackOnly();
|
|
14036
15400
|
await this.flushWithHooks();
|
|
14037
|
-
|
|
14038
|
-
|
|
15401
|
+
this.throwIfRollbackOnly();
|
|
15402
|
+
if (isOutermost) {
|
|
15403
|
+
await this.executor.commitTransaction();
|
|
15404
|
+
await this.domainEvents.dispatch(this.unitOfWork.getTracked(), this);
|
|
15405
|
+
} else {
|
|
15406
|
+
await this.executor.releaseSavepoint(savepointName);
|
|
15407
|
+
}
|
|
14039
15408
|
return result;
|
|
14040
15409
|
} catch (err) {
|
|
14041
|
-
|
|
15410
|
+
if (isOutermost) {
|
|
15411
|
+
await this.rollback();
|
|
15412
|
+
} else {
|
|
15413
|
+
this.rollbackOnly = true;
|
|
15414
|
+
await this.executor.rollbackToSavepoint(savepointName);
|
|
15415
|
+
}
|
|
14042
15416
|
throw err;
|
|
15417
|
+
} finally {
|
|
15418
|
+
this.transactionDepth = Math.max(0, this.transactionDepth - 1);
|
|
15419
|
+
if (this.transactionDepth === 0) {
|
|
15420
|
+
this.rollbackOnly = false;
|
|
15421
|
+
this.savepointCounter = 0;
|
|
15422
|
+
}
|
|
14043
15423
|
}
|
|
14044
15424
|
}
|
|
14045
15425
|
/**
|
|
@@ -14049,6 +15429,9 @@ var OrmSession = class {
|
|
|
14049
15429
|
if (this.executor.capabilities.transactions) {
|
|
14050
15430
|
await this.executor.rollbackTransaction();
|
|
14051
15431
|
}
|
|
15432
|
+
this.transactionDepth = 0;
|
|
15433
|
+
this.savepointCounter = 0;
|
|
15434
|
+
this.rollbackOnly = false;
|
|
14052
15435
|
this.unitOfWork.reset();
|
|
14053
15436
|
this.relationChanges.reset();
|
|
14054
15437
|
}
|
|
@@ -14123,6 +15506,23 @@ var OrmSession = class {
|
|
|
14123
15506
|
resolveSaveGraphOptions(options) {
|
|
14124
15507
|
return { ...this.saveGraphDefaults ?? {}, ...options ?? {} };
|
|
14125
15508
|
}
|
|
15509
|
+
assertSavepointSupport() {
|
|
15510
|
+
if (!this.executor.capabilities.savepoints) {
|
|
15511
|
+
throw new Error(NESTED_TRANSACTIONS_REQUIRE_SAVEPOINTS);
|
|
15512
|
+
}
|
|
15513
|
+
if (typeof this.executor.savepoint !== "function" || typeof this.executor.releaseSavepoint !== "function" || typeof this.executor.rollbackToSavepoint !== "function") {
|
|
15514
|
+
throw new Error(NESTED_TRANSACTIONS_REQUIRE_SAVEPOINTS);
|
|
15515
|
+
}
|
|
15516
|
+
}
|
|
15517
|
+
nextSavepointName() {
|
|
15518
|
+
this.savepointCounter += 1;
|
|
15519
|
+
return `metalorm_sp_${this.savepointCounter}`;
|
|
15520
|
+
}
|
|
15521
|
+
throwIfRollbackOnly() {
|
|
15522
|
+
if (this.rollbackOnly) {
|
|
15523
|
+
throw new Error(ROLLBACK_ONLY_TRANSACTION);
|
|
15524
|
+
}
|
|
15525
|
+
}
|
|
14126
15526
|
};
|
|
14127
15527
|
var buildRelationChangeEntry = (root, relationKey, rootTable, relationName, relation, change) => ({
|
|
14128
15528
|
root,
|
|
@@ -14647,7 +16047,7 @@ var TREE_METADATA_KEY = /* @__PURE__ */ Symbol("metal-orm:tree");
|
|
|
14647
16047
|
function Tree(options = {}) {
|
|
14648
16048
|
return function(target, context) {
|
|
14649
16049
|
const config = resolveTreeConfig(options);
|
|
14650
|
-
const metadataBag = readMetadataBag(context) ?? readMetadataBagFromConstructor(target);
|
|
16050
|
+
const metadataBag = context ? readMetadataBag(context) ?? readMetadataBagFromConstructor(target) : readMetadataBagFromConstructor(target);
|
|
14651
16051
|
const metadata = {
|
|
14652
16052
|
config,
|
|
14653
16053
|
parentProperty: metadataBag?.tree?.parentProperty,
|
|
@@ -14659,28 +16059,22 @@ function Tree(options = {}) {
|
|
|
14659
16059
|
};
|
|
14660
16060
|
}
|
|
14661
16061
|
function TreeParent() {
|
|
14662
|
-
return function(
|
|
14663
|
-
|
|
14664
|
-
|
|
14665
|
-
|
|
14666
|
-
|
|
14667
|
-
|
|
14668
|
-
}
|
|
14669
|
-
const propertyName = String(context.name);
|
|
14670
|
-
const bag = getOrCreateMetadataBag(context);
|
|
16062
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16063
|
+
const { propertyName, bag } = resolveFieldDecoratorInfo(
|
|
16064
|
+
targetOrValue,
|
|
16065
|
+
contextOrProperty,
|
|
16066
|
+
"TreeParent"
|
|
16067
|
+
);
|
|
14671
16068
|
bag.tree = { ...bag.tree, parentProperty: propertyName };
|
|
14672
16069
|
};
|
|
14673
16070
|
}
|
|
14674
16071
|
function TreeChildren() {
|
|
14675
|
-
return function(
|
|
14676
|
-
|
|
14677
|
-
|
|
14678
|
-
|
|
14679
|
-
|
|
14680
|
-
|
|
14681
|
-
}
|
|
14682
|
-
const propertyName = String(context.name);
|
|
14683
|
-
const bag = getOrCreateMetadataBag(context);
|
|
16072
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16073
|
+
const { propertyName, bag } = resolveFieldDecoratorInfo(
|
|
16074
|
+
targetOrValue,
|
|
16075
|
+
contextOrProperty,
|
|
16076
|
+
"TreeChildren"
|
|
16077
|
+
);
|
|
14684
16078
|
bag.tree = { ...bag.tree, childrenProperty: propertyName };
|
|
14685
16079
|
};
|
|
14686
16080
|
}
|
|
@@ -14844,7 +16238,7 @@ function Entity(options = {}) {
|
|
|
14844
16238
|
const ctor = value;
|
|
14845
16239
|
const tableName = options.tableName ?? deriveTableNameFromConstructor(ctor);
|
|
14846
16240
|
setEntityTableName(ctor, tableName, options.hooks, options.type);
|
|
14847
|
-
const bag = readMetadataBag(context);
|
|
16241
|
+
const bag = context ? readMetadataBag(context) : readMetadataBagFromConstructor(ctor);
|
|
14848
16242
|
if (bag) {
|
|
14849
16243
|
const meta = ensureEntityMetadata(ctor);
|
|
14850
16244
|
for (const entry of bag.columns) {
|
|
@@ -14898,29 +16292,20 @@ var normalizeColumnInput = (input) => {
|
|
|
14898
16292
|
}
|
|
14899
16293
|
return column;
|
|
14900
16294
|
};
|
|
14901
|
-
var
|
|
14902
|
-
|
|
14903
|
-
|
|
14904
|
-
|
|
14905
|
-
|
|
14906
|
-
|
|
14907
|
-
var registerColumnFromContext = (context, column) => {
|
|
14908
|
-
if (!context.name) {
|
|
14909
|
-
throw new Error("Column decorator requires a property name");
|
|
14910
|
-
}
|
|
14911
|
-
if (context.private) {
|
|
14912
|
-
throw new Error("Column decorator does not support private fields");
|
|
14913
|
-
}
|
|
14914
|
-
const propertyName = normalizePropertyName(context.name);
|
|
14915
|
-
const bag = getOrCreateMetadataBag(context);
|
|
16295
|
+
var registerColumnFromContext = (targetOrValue, contextOrProperty, column) => {
|
|
16296
|
+
const { propertyName, bag } = resolveFieldDecoratorInfo(
|
|
16297
|
+
targetOrValue,
|
|
16298
|
+
contextOrProperty,
|
|
16299
|
+
"Column"
|
|
16300
|
+
);
|
|
14916
16301
|
if (!bag.columns.some((entry) => entry.propertyName === propertyName)) {
|
|
14917
16302
|
bag.columns.push({ propertyName, column: { ...column } });
|
|
14918
16303
|
}
|
|
14919
16304
|
};
|
|
14920
16305
|
function Column(definition) {
|
|
14921
16306
|
const normalized = normalizeColumnInput(definition);
|
|
14922
|
-
return function(
|
|
14923
|
-
registerColumnFromContext(
|
|
16307
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16308
|
+
registerColumnFromContext(targetOrValue, contextOrProperty, normalized);
|
|
14924
16309
|
};
|
|
14925
16310
|
}
|
|
14926
16311
|
function PrimaryKey(definition) {
|
|
@@ -14930,22 +16315,13 @@ function PrimaryKey(definition) {
|
|
|
14930
16315
|
}
|
|
14931
16316
|
|
|
14932
16317
|
// src/decorators/relations.ts
|
|
14933
|
-
var normalizePropertyName2 = (name) => {
|
|
14934
|
-
if (typeof name === "symbol") {
|
|
14935
|
-
return name.description ?? name.toString();
|
|
14936
|
-
}
|
|
14937
|
-
return name;
|
|
14938
|
-
};
|
|
14939
16318
|
var createFieldDecorator = (metadataFactory) => {
|
|
14940
|
-
return function(
|
|
14941
|
-
|
|
14942
|
-
|
|
14943
|
-
|
|
14944
|
-
|
|
14945
|
-
|
|
14946
|
-
}
|
|
14947
|
-
const propertyName = normalizePropertyName2(context.name);
|
|
14948
|
-
const bag = getOrCreateMetadataBag(context);
|
|
16319
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16320
|
+
const { propertyName, bag } = resolveFieldDecoratorInfo(
|
|
16321
|
+
targetOrValue,
|
|
16322
|
+
contextOrProperty,
|
|
16323
|
+
"Relation"
|
|
16324
|
+
);
|
|
14949
16325
|
const relationMetadata = metadataFactory(propertyName);
|
|
14950
16326
|
if (!bag.relations.some((entry) => entry.propertyName === propertyName)) {
|
|
14951
16327
|
bag.relations.push({ propertyName, relation: relationMetadata });
|
|
@@ -14997,6 +16373,43 @@ function BelongsToMany(options) {
|
|
|
14997
16373
|
cascade: options.cascade
|
|
14998
16374
|
}));
|
|
14999
16375
|
}
|
|
16376
|
+
function MorphTo(options) {
|
|
16377
|
+
return createFieldDecorator((propertyName) => ({
|
|
16378
|
+
kind: RelationKinds.MorphTo,
|
|
16379
|
+
propertyKey: propertyName,
|
|
16380
|
+
typeField: options.typeField,
|
|
16381
|
+
idField: options.idField,
|
|
16382
|
+
targets: options.targets,
|
|
16383
|
+
targetKey: options.targetKey,
|
|
16384
|
+
cascade: options.cascade
|
|
16385
|
+
}));
|
|
16386
|
+
}
|
|
16387
|
+
function MorphOne(options) {
|
|
16388
|
+
return createFieldDecorator((propertyName) => ({
|
|
16389
|
+
kind: RelationKinds.MorphOne,
|
|
16390
|
+
propertyKey: propertyName,
|
|
16391
|
+
target: options.target,
|
|
16392
|
+
morphName: options.morphName,
|
|
16393
|
+
typeValue: options.typeValue,
|
|
16394
|
+
typeField: options.typeField,
|
|
16395
|
+
idField: options.idField,
|
|
16396
|
+
localKey: options.localKey,
|
|
16397
|
+
cascade: options.cascade
|
|
16398
|
+
}));
|
|
16399
|
+
}
|
|
16400
|
+
function MorphMany(options) {
|
|
16401
|
+
return createFieldDecorator((propertyName) => ({
|
|
16402
|
+
kind: RelationKinds.MorphMany,
|
|
16403
|
+
propertyKey: propertyName,
|
|
16404
|
+
target: options.target,
|
|
16405
|
+
morphName: options.morphName,
|
|
16406
|
+
typeValue: options.typeValue,
|
|
16407
|
+
typeField: options.typeField,
|
|
16408
|
+
idField: options.idField,
|
|
16409
|
+
localKey: options.localKey,
|
|
16410
|
+
cascade: options.cascade
|
|
16411
|
+
}));
|
|
16412
|
+
}
|
|
15000
16413
|
|
|
15001
16414
|
// src/decorators/transformers/built-in/string-transformers.ts
|
|
15002
16415
|
var TrimTransformer = class {
|
|
@@ -15182,15 +16595,12 @@ var PatternValidator = class {
|
|
|
15182
16595
|
};
|
|
15183
16596
|
|
|
15184
16597
|
// src/decorators/transformers/transformer-decorators.ts
|
|
15185
|
-
var
|
|
15186
|
-
|
|
15187
|
-
|
|
15188
|
-
|
|
15189
|
-
|
|
15190
|
-
|
|
15191
|
-
var registerTransformerMetadata = (context, metadata) => {
|
|
15192
|
-
const propertyName = normalizePropertyName3(context.name);
|
|
15193
|
-
const bag = getOrCreateMetadataBag(context);
|
|
16598
|
+
var registerTransformerMetadata = (targetOrValue, contextOrProperty, metadata) => {
|
|
16599
|
+
const { propertyName, bag } = resolveFieldDecoratorInfo(
|
|
16600
|
+
targetOrValue,
|
|
16601
|
+
contextOrProperty,
|
|
16602
|
+
"Transformer"
|
|
16603
|
+
);
|
|
15194
16604
|
let existing = bag.transformers.find((t) => t.propertyName === propertyName);
|
|
15195
16605
|
if (!existing) {
|
|
15196
16606
|
existing = {
|
|
@@ -15219,64 +16629,64 @@ var registerTransformerMetadata = (context, metadata) => {
|
|
|
15219
16629
|
}
|
|
15220
16630
|
};
|
|
15221
16631
|
function Trim(options) {
|
|
15222
|
-
return function(
|
|
15223
|
-
registerTransformerMetadata(
|
|
16632
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16633
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15224
16634
|
sanitizers: [new TrimTransformer(options)]
|
|
15225
16635
|
});
|
|
15226
16636
|
};
|
|
15227
16637
|
}
|
|
15228
16638
|
function Lower() {
|
|
15229
|
-
return function(
|
|
15230
|
-
registerTransformerMetadata(
|
|
16639
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16640
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15231
16641
|
sanitizers: [new CaseTransformer("lower")]
|
|
15232
16642
|
});
|
|
15233
16643
|
};
|
|
15234
16644
|
}
|
|
15235
16645
|
function Upper() {
|
|
15236
|
-
return function(
|
|
15237
|
-
registerTransformerMetadata(
|
|
16646
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16647
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15238
16648
|
sanitizers: [new CaseTransformer("upper")]
|
|
15239
16649
|
});
|
|
15240
16650
|
};
|
|
15241
16651
|
}
|
|
15242
16652
|
function Capitalize() {
|
|
15243
|
-
return function(
|
|
15244
|
-
registerTransformerMetadata(
|
|
16653
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16654
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15245
16655
|
sanitizers: [new CaseTransformer("capitalize")]
|
|
15246
16656
|
});
|
|
15247
16657
|
};
|
|
15248
16658
|
}
|
|
15249
16659
|
function Title() {
|
|
15250
|
-
return function(
|
|
15251
|
-
registerTransformerMetadata(
|
|
16660
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16661
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15252
16662
|
sanitizers: [new CaseTransformer("title")]
|
|
15253
16663
|
});
|
|
15254
16664
|
};
|
|
15255
16665
|
}
|
|
15256
16666
|
function Alphanumeric(options) {
|
|
15257
|
-
return function(
|
|
15258
|
-
registerTransformerMetadata(
|
|
16667
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16668
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15259
16669
|
validators: [new AlphanumericValidator(options)]
|
|
15260
16670
|
});
|
|
15261
16671
|
};
|
|
15262
16672
|
}
|
|
15263
16673
|
function Email(options) {
|
|
15264
|
-
return function(
|
|
15265
|
-
registerTransformerMetadata(
|
|
16674
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16675
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15266
16676
|
validators: [new EmailValidator(options)]
|
|
15267
16677
|
});
|
|
15268
16678
|
};
|
|
15269
16679
|
}
|
|
15270
16680
|
function Length(options) {
|
|
15271
|
-
return function(
|
|
15272
|
-
registerTransformerMetadata(
|
|
16681
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16682
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15273
16683
|
validators: [new LengthValidator(options)]
|
|
15274
16684
|
});
|
|
15275
16685
|
};
|
|
15276
16686
|
}
|
|
15277
16687
|
function Pattern(options) {
|
|
15278
|
-
return function(
|
|
15279
|
-
registerTransformerMetadata(
|
|
16688
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16689
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15280
16690
|
validators: [new PatternValidator(options)]
|
|
15281
16691
|
});
|
|
15282
16692
|
};
|
|
@@ -15503,16 +16913,12 @@ var CEPValidator = class {
|
|
|
15503
16913
|
registerValidator("BR", "cpf", () => new CPFValidator());
|
|
15504
16914
|
registerValidator("BR", "cnpj", () => new CNPJValidator());
|
|
15505
16915
|
registerValidator("BR", "cep", () => new CEPValidator());
|
|
15506
|
-
var
|
|
15507
|
-
|
|
15508
|
-
return name.description ?? name.toString();
|
|
15509
|
-
}
|
|
15510
|
-
return name;
|
|
16916
|
+
var resolveCountryDecoratorInfo = (targetOrValue, contextOrProperty) => {
|
|
16917
|
+
return resolveFieldDecoratorInfo(targetOrValue, contextOrProperty, "Country validator");
|
|
15511
16918
|
};
|
|
15512
16919
|
function CPF(options) {
|
|
15513
|
-
return function(
|
|
15514
|
-
const propertyName =
|
|
15515
|
-
const bag = getOrCreateMetadataBag(context);
|
|
16920
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16921
|
+
const { propertyName, bag } = resolveCountryDecoratorInfo(targetOrValue, contextOrProperty);
|
|
15516
16922
|
let existing = bag.transformers.find((t) => t.propertyName === propertyName);
|
|
15517
16923
|
if (!existing) {
|
|
15518
16924
|
existing = {
|
|
@@ -15560,9 +16966,8 @@ function CPF(options) {
|
|
|
15560
16966
|
};
|
|
15561
16967
|
}
|
|
15562
16968
|
function CNPJ(options) {
|
|
15563
|
-
return function(
|
|
15564
|
-
const propertyName =
|
|
15565
|
-
const bag = getOrCreateMetadataBag(context);
|
|
16969
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16970
|
+
const { propertyName, bag } = resolveCountryDecoratorInfo(targetOrValue, contextOrProperty);
|
|
15566
16971
|
let existing = bag.transformers.find((t) => t.propertyName === propertyName);
|
|
15567
16972
|
if (!existing) {
|
|
15568
16973
|
existing = {
|
|
@@ -15610,9 +17015,8 @@ function CNPJ(options) {
|
|
|
15610
17015
|
};
|
|
15611
17016
|
}
|
|
15612
17017
|
function CEP(options) {
|
|
15613
|
-
return function(
|
|
15614
|
-
const propertyName =
|
|
15615
|
-
const bag = getOrCreateMetadataBag(context);
|
|
17018
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17019
|
+
const { propertyName, bag } = resolveCountryDecoratorInfo(targetOrValue, contextOrProperty);
|
|
15616
17020
|
let existing = bag.transformers.find((t) => t.propertyName === propertyName);
|
|
15617
17021
|
if (!existing) {
|
|
15618
17022
|
existing = {
|
|
@@ -15868,6 +17272,14 @@ var Pool = class {
|
|
|
15868
17272
|
};
|
|
15869
17273
|
|
|
15870
17274
|
// src/core/execution/executors/postgres-executor.ts
|
|
17275
|
+
var SAVEPOINT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
17276
|
+
var sanitizeSavepointName = (name) => {
|
|
17277
|
+
const trimmed = name.trim();
|
|
17278
|
+
if (!SAVEPOINT_NAME_PATTERN.test(trimmed)) {
|
|
17279
|
+
throw new Error(`Invalid savepoint name: "${name}"`);
|
|
17280
|
+
}
|
|
17281
|
+
return trimmed;
|
|
17282
|
+
};
|
|
15871
17283
|
function createPostgresExecutor(client) {
|
|
15872
17284
|
return createExecutorFromQueryRunner({
|
|
15873
17285
|
async query(sql, params) {
|
|
@@ -15882,11 +17294,24 @@ function createPostgresExecutor(client) {
|
|
|
15882
17294
|
},
|
|
15883
17295
|
async rollbackTransaction() {
|
|
15884
17296
|
await client.query("ROLLBACK");
|
|
17297
|
+
},
|
|
17298
|
+
async savepoint(name) {
|
|
17299
|
+
const savepoint = sanitizeSavepointName(name);
|
|
17300
|
+
await client.query(`SAVEPOINT ${savepoint}`);
|
|
17301
|
+
},
|
|
17302
|
+
async releaseSavepoint(name) {
|
|
17303
|
+
const savepoint = sanitizeSavepointName(name);
|
|
17304
|
+
await client.query(`RELEASE SAVEPOINT ${savepoint}`);
|
|
17305
|
+
},
|
|
17306
|
+
async rollbackToSavepoint(name) {
|
|
17307
|
+
const savepoint = sanitizeSavepointName(name);
|
|
17308
|
+
await client.query(`ROLLBACK TO SAVEPOINT ${savepoint}`);
|
|
15885
17309
|
}
|
|
15886
17310
|
});
|
|
15887
17311
|
}
|
|
15888
17312
|
|
|
15889
17313
|
// src/core/execution/executors/mysql-executor.ts
|
|
17314
|
+
var SAVEPOINT_NAME_PATTERN2 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
15890
17315
|
var isRowObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15891
17316
|
var isRowObjectArray = (value) => Array.isArray(value) && value.every(isRowObject);
|
|
15892
17317
|
var isMysqlResultHeader = (value) => isRowObject(value) && ("affectedRows" in value || "insertId" in value || "warningStatus" in value || "serverStatus" in value);
|
|
@@ -15898,6 +17323,13 @@ var headerToQueryResult = (header) => ({
|
|
|
15898
17323
|
rowsAffected: header.affectedRows
|
|
15899
17324
|
}
|
|
15900
17325
|
});
|
|
17326
|
+
var sanitizeSavepointName2 = (name) => {
|
|
17327
|
+
const trimmed = name.trim();
|
|
17328
|
+
if (!SAVEPOINT_NAME_PATTERN2.test(trimmed)) {
|
|
17329
|
+
throw new Error(`Invalid savepoint name: "${name}"`);
|
|
17330
|
+
}
|
|
17331
|
+
return trimmed;
|
|
17332
|
+
};
|
|
15901
17333
|
var normalizeMysqlResults = (rows) => {
|
|
15902
17334
|
if (!Array.isArray(rows)) {
|
|
15903
17335
|
return isMysqlResultHeader(rows) ? [headerToQueryResult(rows)] : [rowsToQueryResult([])];
|
|
@@ -15919,9 +17351,11 @@ var normalizeMysqlResults = (rows) => {
|
|
|
15919
17351
|
};
|
|
15920
17352
|
function createMysqlExecutor(client) {
|
|
15921
17353
|
const supportsTransactions = typeof client.beginTransaction === "function" && typeof client.commit === "function" && typeof client.rollback === "function";
|
|
17354
|
+
const supportsSavepoints = supportsTransactions;
|
|
15922
17355
|
return {
|
|
15923
17356
|
capabilities: {
|
|
15924
|
-
transactions: supportsTransactions
|
|
17357
|
+
transactions: supportsTransactions,
|
|
17358
|
+
...supportsSavepoints ? { savepoints: true } : {}
|
|
15925
17359
|
},
|
|
15926
17360
|
async executeSql(sql, params) {
|
|
15927
17361
|
const [rows] = await client.query(sql, params);
|
|
@@ -15945,17 +17379,55 @@ function createMysqlExecutor(client) {
|
|
|
15945
17379
|
}
|
|
15946
17380
|
await client.rollback();
|
|
15947
17381
|
},
|
|
17382
|
+
async savepoint(name) {
|
|
17383
|
+
if (!supportsSavepoints) {
|
|
17384
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17385
|
+
}
|
|
17386
|
+
const savepoint = sanitizeSavepointName2(name);
|
|
17387
|
+
await client.query(`SAVEPOINT ${savepoint}`);
|
|
17388
|
+
},
|
|
17389
|
+
async releaseSavepoint(name) {
|
|
17390
|
+
if (!supportsSavepoints) {
|
|
17391
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17392
|
+
}
|
|
17393
|
+
const savepoint = sanitizeSavepointName2(name);
|
|
17394
|
+
await client.query(`RELEASE SAVEPOINT ${savepoint}`);
|
|
17395
|
+
},
|
|
17396
|
+
async rollbackToSavepoint(name) {
|
|
17397
|
+
if (!supportsSavepoints) {
|
|
17398
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17399
|
+
}
|
|
17400
|
+
const savepoint = sanitizeSavepointName2(name);
|
|
17401
|
+
await client.query(`ROLLBACK TO SAVEPOINT ${savepoint}`);
|
|
17402
|
+
},
|
|
15948
17403
|
async dispose() {
|
|
15949
17404
|
}
|
|
15950
17405
|
};
|
|
15951
17406
|
}
|
|
15952
17407
|
|
|
15953
17408
|
// src/core/execution/executors/sqlite-executor.ts
|
|
17409
|
+
var SAVEPOINT_NAME_PATTERN3 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
17410
|
+
var sanitizeSavepointName3 = (name) => {
|
|
17411
|
+
const trimmed = name.trim();
|
|
17412
|
+
if (!SAVEPOINT_NAME_PATTERN3.test(trimmed)) {
|
|
17413
|
+
throw new Error(`Invalid savepoint name: "${name}"`);
|
|
17414
|
+
}
|
|
17415
|
+
return trimmed;
|
|
17416
|
+
};
|
|
15954
17417
|
function createSqliteExecutor(client) {
|
|
15955
17418
|
const supportsTransactions = typeof client.beginTransaction === "function" && typeof client.commitTransaction === "function" && typeof client.rollbackTransaction === "function";
|
|
17419
|
+
const supportsSavepoints = supportsTransactions;
|
|
17420
|
+
const executeControlStatement = async (sql) => {
|
|
17421
|
+
if (typeof client.run === "function") {
|
|
17422
|
+
await client.run(sql);
|
|
17423
|
+
return;
|
|
17424
|
+
}
|
|
17425
|
+
await client.all(sql);
|
|
17426
|
+
};
|
|
15956
17427
|
return {
|
|
15957
17428
|
capabilities: {
|
|
15958
|
-
transactions: supportsTransactions
|
|
17429
|
+
transactions: supportsTransactions,
|
|
17430
|
+
...supportsSavepoints ? { savepoints: true } : {}
|
|
15959
17431
|
},
|
|
15960
17432
|
async executeSql(sql, params) {
|
|
15961
17433
|
const rows = await client.all(sql, params);
|
|
@@ -15980,17 +17452,120 @@ function createSqliteExecutor(client) {
|
|
|
15980
17452
|
}
|
|
15981
17453
|
await client.rollbackTransaction();
|
|
15982
17454
|
},
|
|
17455
|
+
async savepoint(name) {
|
|
17456
|
+
if (!supportsSavepoints) {
|
|
17457
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17458
|
+
}
|
|
17459
|
+
const savepoint = sanitizeSavepointName3(name);
|
|
17460
|
+
if (typeof client.savepoint === "function") {
|
|
17461
|
+
await client.savepoint(savepoint);
|
|
17462
|
+
return;
|
|
17463
|
+
}
|
|
17464
|
+
await executeControlStatement(`SAVEPOINT ${savepoint}`);
|
|
17465
|
+
},
|
|
17466
|
+
async releaseSavepoint(name) {
|
|
17467
|
+
if (!supportsSavepoints) {
|
|
17468
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17469
|
+
}
|
|
17470
|
+
const savepoint = sanitizeSavepointName3(name);
|
|
17471
|
+
if (typeof client.releaseSavepoint === "function") {
|
|
17472
|
+
await client.releaseSavepoint(savepoint);
|
|
17473
|
+
return;
|
|
17474
|
+
}
|
|
17475
|
+
await executeControlStatement(`RELEASE SAVEPOINT ${savepoint}`);
|
|
17476
|
+
},
|
|
17477
|
+
async rollbackToSavepoint(name) {
|
|
17478
|
+
if (!supportsSavepoints) {
|
|
17479
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17480
|
+
}
|
|
17481
|
+
const savepoint = sanitizeSavepointName3(name);
|
|
17482
|
+
if (typeof client.rollbackToSavepoint === "function") {
|
|
17483
|
+
await client.rollbackToSavepoint(savepoint);
|
|
17484
|
+
return;
|
|
17485
|
+
}
|
|
17486
|
+
await executeControlStatement(`ROLLBACK TO SAVEPOINT ${savepoint}`);
|
|
17487
|
+
},
|
|
17488
|
+
async dispose() {
|
|
17489
|
+
}
|
|
17490
|
+
};
|
|
17491
|
+
}
|
|
17492
|
+
|
|
17493
|
+
// src/core/execution/executors/better-sqlite3-executor.ts
|
|
17494
|
+
var SAVEPOINT_NAME_PATTERN4 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
17495
|
+
var sanitizeSavepointName4 = (name) => {
|
|
17496
|
+
const trimmed = name.trim();
|
|
17497
|
+
if (!SAVEPOINT_NAME_PATTERN4.test(trimmed)) {
|
|
17498
|
+
throw new Error(`Invalid savepoint name: "${name}"`);
|
|
17499
|
+
}
|
|
17500
|
+
return trimmed;
|
|
17501
|
+
};
|
|
17502
|
+
function createBetterSqlite3Executor(client) {
|
|
17503
|
+
return {
|
|
17504
|
+
capabilities: {
|
|
17505
|
+
transactions: true,
|
|
17506
|
+
savepoints: true
|
|
17507
|
+
},
|
|
17508
|
+
async executeSql(sql, params) {
|
|
17509
|
+
const stmt = client.prepare(sql);
|
|
17510
|
+
let result;
|
|
17511
|
+
if (stmt.reader) {
|
|
17512
|
+
const rows = stmt.all(...params ?? []);
|
|
17513
|
+
result = rowsToQueryResult(rows);
|
|
17514
|
+
} else {
|
|
17515
|
+
const info = stmt.run(...params ?? []);
|
|
17516
|
+
result = {
|
|
17517
|
+
columns: [],
|
|
17518
|
+
values: [],
|
|
17519
|
+
meta: {
|
|
17520
|
+
rowsAffected: info.changes,
|
|
17521
|
+
insertId: typeof info.lastInsertRowid === "bigint" ? info.lastInsertRowid.toString() : info.lastInsertRowid
|
|
17522
|
+
}
|
|
17523
|
+
};
|
|
17524
|
+
}
|
|
17525
|
+
return toExecutionPayload([result]);
|
|
17526
|
+
},
|
|
17527
|
+
async beginTransaction() {
|
|
17528
|
+
client.prepare("BEGIN").run();
|
|
17529
|
+
},
|
|
17530
|
+
async commitTransaction() {
|
|
17531
|
+
client.prepare("COMMIT").run();
|
|
17532
|
+
},
|
|
17533
|
+
async rollbackTransaction() {
|
|
17534
|
+
client.prepare("ROLLBACK").run();
|
|
17535
|
+
},
|
|
17536
|
+
async savepoint(name) {
|
|
17537
|
+
const savepoint = sanitizeSavepointName4(name);
|
|
17538
|
+
client.prepare(`SAVEPOINT ${savepoint}`).run();
|
|
17539
|
+
},
|
|
17540
|
+
async releaseSavepoint(name) {
|
|
17541
|
+
const savepoint = sanitizeSavepointName4(name);
|
|
17542
|
+
client.prepare(`RELEASE SAVEPOINT ${savepoint}`).run();
|
|
17543
|
+
},
|
|
17544
|
+
async rollbackToSavepoint(name) {
|
|
17545
|
+
const savepoint = sanitizeSavepointName4(name);
|
|
17546
|
+
client.prepare(`ROLLBACK TO SAVEPOINT ${savepoint}`).run();
|
|
17547
|
+
},
|
|
15983
17548
|
async dispose() {
|
|
15984
17549
|
}
|
|
15985
17550
|
};
|
|
15986
17551
|
}
|
|
15987
17552
|
|
|
15988
17553
|
// src/core/execution/executors/mssql-executor.ts
|
|
17554
|
+
var SAVEPOINT_NAME_PATTERN5 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
17555
|
+
var sanitizeSavepointName5 = (name) => {
|
|
17556
|
+
const trimmed = name.trim();
|
|
17557
|
+
if (!SAVEPOINT_NAME_PATTERN5.test(trimmed)) {
|
|
17558
|
+
throw new Error(`Invalid savepoint name: "${name}"`);
|
|
17559
|
+
}
|
|
17560
|
+
return trimmed;
|
|
17561
|
+
};
|
|
15989
17562
|
function createMssqlExecutor(client) {
|
|
15990
17563
|
const supportsTransactions = typeof client.beginTransaction === "function" && typeof client.commit === "function" && typeof client.rollback === "function";
|
|
17564
|
+
const supportsSavepoints = supportsTransactions;
|
|
15991
17565
|
return {
|
|
15992
17566
|
capabilities: {
|
|
15993
|
-
transactions: supportsTransactions
|
|
17567
|
+
transactions: supportsTransactions,
|
|
17568
|
+
...supportsSavepoints ? { savepoints: true } : {}
|
|
15994
17569
|
},
|
|
15995
17570
|
async executeSql(sql, params) {
|
|
15996
17571
|
const { recordset, recordsets } = await client.query(sql, params);
|
|
@@ -16015,6 +17590,25 @@ function createMssqlExecutor(client) {
|
|
|
16015
17590
|
}
|
|
16016
17591
|
await client.rollback();
|
|
16017
17592
|
},
|
|
17593
|
+
async savepoint(name) {
|
|
17594
|
+
if (!supportsSavepoints) {
|
|
17595
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17596
|
+
}
|
|
17597
|
+
const savepoint = sanitizeSavepointName5(name);
|
|
17598
|
+
await client.query(`SAVE TRANSACTION ${savepoint}`);
|
|
17599
|
+
},
|
|
17600
|
+
async releaseSavepoint(_name) {
|
|
17601
|
+
if (!supportsSavepoints) {
|
|
17602
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17603
|
+
}
|
|
17604
|
+
},
|
|
17605
|
+
async rollbackToSavepoint(name) {
|
|
17606
|
+
if (!supportsSavepoints) {
|
|
17607
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17608
|
+
}
|
|
17609
|
+
const savepoint = sanitizeSavepointName5(name);
|
|
17610
|
+
await client.query(`ROLLBACK TRANSACTION ${savepoint}`);
|
|
17611
|
+
},
|
|
16018
17612
|
async dispose() {
|
|
16019
17613
|
}
|
|
16020
17614
|
};
|
|
@@ -16090,6 +17684,7 @@ var isQueryResult = (value) => typeof value === "object" && value !== null && Ar
|
|
|
16090
17684
|
var isRowArray = (value) => Array.isArray(value) && value.every((item) => typeof item === "object" && item !== null && !Array.isArray(item));
|
|
16091
17685
|
function createPooledExecutorFactory(opts) {
|
|
16092
17686
|
const { pool, adapter } = opts;
|
|
17687
|
+
const supportsSavepoints = typeof adapter.savepoint === "function" && typeof adapter.releaseSavepoint === "function" && typeof adapter.rollbackToSavepoint === "function";
|
|
16093
17688
|
const makeExecutor = (mode) => {
|
|
16094
17689
|
let lease = null;
|
|
16095
17690
|
const getLease = async () => {
|
|
@@ -16107,8 +17702,17 @@ function createPooledExecutorFactory(opts) {
|
|
|
16107
17702
|
}
|
|
16108
17703
|
return toExecutionPayload([rowsToQueryResult(rows)]);
|
|
16109
17704
|
};
|
|
17705
|
+
const requireActiveTransactionLease = () => {
|
|
17706
|
+
if (!lease) {
|
|
17707
|
+
throw new Error("savepoint operation called without an active transaction");
|
|
17708
|
+
}
|
|
17709
|
+
return lease;
|
|
17710
|
+
};
|
|
16110
17711
|
return {
|
|
16111
|
-
capabilities: {
|
|
17712
|
+
capabilities: {
|
|
17713
|
+
transactions: true,
|
|
17714
|
+
...supportsSavepoints ? { savepoints: true } : {}
|
|
17715
|
+
},
|
|
16112
17716
|
async executeSql(sql, params) {
|
|
16113
17717
|
if (mode === "sticky") {
|
|
16114
17718
|
const l2 = await getLease();
|
|
@@ -16152,6 +17756,27 @@ function createPooledExecutorFactory(opts) {
|
|
|
16152
17756
|
await l.release();
|
|
16153
17757
|
}
|
|
16154
17758
|
},
|
|
17759
|
+
async savepoint(name) {
|
|
17760
|
+
if (!supportsSavepoints) {
|
|
17761
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17762
|
+
}
|
|
17763
|
+
const l = requireActiveTransactionLease();
|
|
17764
|
+
await adapter.savepoint(l.resource, name);
|
|
17765
|
+
},
|
|
17766
|
+
async releaseSavepoint(name) {
|
|
17767
|
+
if (!supportsSavepoints) {
|
|
17768
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17769
|
+
}
|
|
17770
|
+
const l = requireActiveTransactionLease();
|
|
17771
|
+
await adapter.releaseSavepoint(l.resource, name);
|
|
17772
|
+
},
|
|
17773
|
+
async rollbackToSavepoint(name) {
|
|
17774
|
+
if (!supportsSavepoints) {
|
|
17775
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17776
|
+
}
|
|
17777
|
+
const l = requireActiveTransactionLease();
|
|
17778
|
+
await adapter.rollbackToSavepoint(l.resource, name);
|
|
17779
|
+
},
|
|
16155
17780
|
async dispose() {
|
|
16156
17781
|
if (!lease) return;
|
|
16157
17782
|
const l = lease;
|
|
@@ -16246,6 +17871,9 @@ var updateInclude = (qb, relationPath, updater) => {
|
|
|
16246
17871
|
filter: segmentOptions?.filter
|
|
16247
17872
|
});
|
|
16248
17873
|
}
|
|
17874
|
+
if (!isSingleTargetRelation(relation)) {
|
|
17875
|
+
continue;
|
|
17876
|
+
}
|
|
16249
17877
|
const joinForSegment = findJoinByRelationKey(state.ast.joins, relationKey);
|
|
16250
17878
|
currentAlias = joinForSegment ? getExposedName(joinForSegment.table) ?? relation.target.name : relation.target.name;
|
|
16251
17879
|
currentTable = relation.target;
|
|
@@ -16374,6 +18002,9 @@ function applyRelationFilter(qb, table, relationName, filter) {
|
|
|
16374
18002
|
`Relation filter "${relationName}" must include at least one of "some", "none", "every", "isEmpty", or "isNotEmpty".`
|
|
16375
18003
|
);
|
|
16376
18004
|
}
|
|
18005
|
+
if (!isSingleTargetRelation(relation)) {
|
|
18006
|
+
return qb;
|
|
18007
|
+
}
|
|
16377
18008
|
if (filter.some) {
|
|
16378
18009
|
const predicate = buildFilterExpression(relation.target, filter.some);
|
|
16379
18010
|
if (predicate) {
|
|
@@ -16419,6 +18050,9 @@ function applyRelationFilter(qb, table, relationName, filter) {
|
|
|
16419
18050
|
return qb;
|
|
16420
18051
|
}
|
|
16421
18052
|
var buildRelationSubqueryBase = (table, relation) => {
|
|
18053
|
+
if (!isSingleTargetRelation(relation)) {
|
|
18054
|
+
throw new Error("MorphTo relations do not support subquery-based filtering");
|
|
18055
|
+
}
|
|
16422
18056
|
const target = relation.target;
|
|
16423
18057
|
if (relation.type === RelationKinds.BelongsToMany) {
|
|
16424
18058
|
const many = relation;
|
|
@@ -16464,7 +18098,14 @@ var buildRelationSubqueryBase = (table, relation) => {
|
|
|
16464
18098
|
schema: target.schema
|
|
16465
18099
|
};
|
|
16466
18100
|
const correlation = buildRelationCorrelation(table, relation);
|
|
16467
|
-
|
|
18101
|
+
let groupByColumnName;
|
|
18102
|
+
if (relation.type === RelationKinds.BelongsTo) {
|
|
18103
|
+
groupByColumnName = relation.localKey || findPrimaryKey(target);
|
|
18104
|
+
} else if (relation.type === RelationKinds.MorphOne || relation.type === RelationKinds.MorphMany) {
|
|
18105
|
+
groupByColumnName = relation.idField;
|
|
18106
|
+
} else {
|
|
18107
|
+
groupByColumnName = relation.foreignKey;
|
|
18108
|
+
}
|
|
16468
18109
|
return {
|
|
16469
18110
|
from,
|
|
16470
18111
|
joins: [],
|
|
@@ -16496,6 +18137,9 @@ function buildRelationFilterExpression(table, relationName, filter) {
|
|
|
16496
18137
|
where
|
|
16497
18138
|
};
|
|
16498
18139
|
};
|
|
18140
|
+
if (!isSingleTargetRelation(relation)) {
|
|
18141
|
+
return null;
|
|
18142
|
+
}
|
|
16499
18143
|
if (filter.some) {
|
|
16500
18144
|
const predicate = buildFilterExpression(relation.target, filter.some);
|
|
16501
18145
|
if (predicate) {
|
|
@@ -19465,6 +21109,432 @@ var TagIndex = class {
|
|
|
19465
21109
|
};
|
|
19466
21110
|
}
|
|
19467
21111
|
};
|
|
21112
|
+
|
|
21113
|
+
// src/bulk/bulk-context.ts
|
|
21114
|
+
function createBulkExecutionContext(session) {
|
|
21115
|
+
const executionContext = session.getExecutionContext();
|
|
21116
|
+
return {
|
|
21117
|
+
session,
|
|
21118
|
+
executionContext,
|
|
21119
|
+
dialect: executionContext.dialect,
|
|
21120
|
+
supportsReturning: executionContext.dialect.supportsDmlReturningClause()
|
|
21121
|
+
};
|
|
21122
|
+
}
|
|
21123
|
+
async function executeCompiled(ctx, compiled) {
|
|
21124
|
+
const payload = await ctx.executionContext.interceptors.run(
|
|
21125
|
+
{ sql: compiled.sql, params: compiled.params },
|
|
21126
|
+
ctx.executionContext.executor
|
|
21127
|
+
);
|
|
21128
|
+
return extractResultSets(payload);
|
|
21129
|
+
}
|
|
21130
|
+
function extractResultSets(payload) {
|
|
21131
|
+
const result = payload;
|
|
21132
|
+
if (result.resultSets) {
|
|
21133
|
+
return result.resultSets;
|
|
21134
|
+
}
|
|
21135
|
+
return [];
|
|
21136
|
+
}
|
|
21137
|
+
function flattenQueryResults(resultSets) {
|
|
21138
|
+
const rows = [];
|
|
21139
|
+
for (const rs of resultSets) {
|
|
21140
|
+
for (const valueRow of rs.values) {
|
|
21141
|
+
const obj = {};
|
|
21142
|
+
rs.columns.forEach((col2, idx) => {
|
|
21143
|
+
const bare = col2.split(".").pop().replace(/^["`[\]]+|["`[\]]+$/g, "");
|
|
21144
|
+
obj[bare] = valueRow[idx];
|
|
21145
|
+
});
|
|
21146
|
+
rows.push(obj);
|
|
21147
|
+
}
|
|
21148
|
+
}
|
|
21149
|
+
return rows;
|
|
21150
|
+
}
|
|
21151
|
+
function resolveReturningColumns(ctx, table, returning) {
|
|
21152
|
+
if (!returning) return void 0;
|
|
21153
|
+
if (!ctx.supportsReturning) return void 0;
|
|
21154
|
+
if (returning === true) {
|
|
21155
|
+
return Object.values(table.columns).map((col2) => ({
|
|
21156
|
+
type: "Column",
|
|
21157
|
+
table: table.name,
|
|
21158
|
+
name: col2.name,
|
|
21159
|
+
alias: col2.name
|
|
21160
|
+
}));
|
|
21161
|
+
}
|
|
21162
|
+
return returning.map((col2) => ({
|
|
21163
|
+
type: "Column",
|
|
21164
|
+
table: table.name,
|
|
21165
|
+
name: col2.name,
|
|
21166
|
+
alias: col2.name
|
|
21167
|
+
}));
|
|
21168
|
+
}
|
|
21169
|
+
|
|
21170
|
+
// src/bulk/bulk-utils.ts
|
|
21171
|
+
function splitIntoChunks(items, size) {
|
|
21172
|
+
if (size < 1) throw new RangeError(`chunkSize must be >= 1, got ${size}`);
|
|
21173
|
+
const chunks = [];
|
|
21174
|
+
for (let i = 0; i < items.length; i += size) {
|
|
21175
|
+
chunks.push(items.slice(i, i + size));
|
|
21176
|
+
}
|
|
21177
|
+
return chunks;
|
|
21178
|
+
}
|
|
21179
|
+
async function runWithConcurrency(tasks, concurrency) {
|
|
21180
|
+
const limit = concurrency === "sequential" ? 1 : Math.max(1, concurrency);
|
|
21181
|
+
if (limit === 1) {
|
|
21182
|
+
const results2 = [];
|
|
21183
|
+
for (const task of tasks) {
|
|
21184
|
+
results2.push(await task());
|
|
21185
|
+
}
|
|
21186
|
+
return results2;
|
|
21187
|
+
}
|
|
21188
|
+
const results = new Array(tasks.length);
|
|
21189
|
+
let nextIndex = 0;
|
|
21190
|
+
const worker = async () => {
|
|
21191
|
+
while (nextIndex < tasks.length) {
|
|
21192
|
+
const i = nextIndex++;
|
|
21193
|
+
results[i] = await tasks[i]();
|
|
21194
|
+
}
|
|
21195
|
+
};
|
|
21196
|
+
const workers = Array.from({ length: Math.min(limit, tasks.length) }, worker);
|
|
21197
|
+
await Promise.all(workers);
|
|
21198
|
+
return results;
|
|
21199
|
+
}
|
|
21200
|
+
async function runChunk(task, chunkIndex, totalChunks, rowsInChunk, timing, onChunkComplete) {
|
|
21201
|
+
const start = timing || onChunkComplete ? Date.now() : 0;
|
|
21202
|
+
const result = await task();
|
|
21203
|
+
const elapsedMs = start ? Date.now() - start : 0;
|
|
21204
|
+
if (onChunkComplete) {
|
|
21205
|
+
await onChunkComplete({ chunkIndex, totalChunks, rowsInChunk, elapsedMs });
|
|
21206
|
+
}
|
|
21207
|
+
return result;
|
|
21208
|
+
}
|
|
21209
|
+
async function maybeTransaction(session, transactional, fn8) {
|
|
21210
|
+
if (!transactional) return fn8();
|
|
21211
|
+
const ormSession = session;
|
|
21212
|
+
return ormSession.transaction(fn8);
|
|
21213
|
+
}
|
|
21214
|
+
function aggregateOutcomes(outcomes) {
|
|
21215
|
+
const result = {
|
|
21216
|
+
processedRows: 0,
|
|
21217
|
+
chunksExecuted: outcomes.length,
|
|
21218
|
+
returning: []
|
|
21219
|
+
};
|
|
21220
|
+
for (const o of outcomes) {
|
|
21221
|
+
result.processedRows += o.processedRows;
|
|
21222
|
+
result.returning.push(...o.returning);
|
|
21223
|
+
}
|
|
21224
|
+
return result;
|
|
21225
|
+
}
|
|
21226
|
+
function aggregateOutcomesWithTimings(outcomes) {
|
|
21227
|
+
const result = aggregateOutcomes(outcomes);
|
|
21228
|
+
result.chunkTimings = outcomes.map((o) => o.elapsedMs);
|
|
21229
|
+
return result;
|
|
21230
|
+
}
|
|
21231
|
+
|
|
21232
|
+
// src/bulk/bulk-executor.base.ts
|
|
21233
|
+
var DEFAULT_CHUNK_SIZE = 500;
|
|
21234
|
+
var BulkBaseExecutor = class {
|
|
21235
|
+
session;
|
|
21236
|
+
table;
|
|
21237
|
+
ctx;
|
|
21238
|
+
options;
|
|
21239
|
+
chunks;
|
|
21240
|
+
totalChunks;
|
|
21241
|
+
constructor(session, table, rows, options = {}) {
|
|
21242
|
+
this.session = session;
|
|
21243
|
+
this.table = table;
|
|
21244
|
+
this.ctx = createBulkExecutionContext(session);
|
|
21245
|
+
this.options = {
|
|
21246
|
+
chunkSize: DEFAULT_CHUNK_SIZE,
|
|
21247
|
+
concurrency: "sequential",
|
|
21248
|
+
transactional: true,
|
|
21249
|
+
timing: false,
|
|
21250
|
+
...options
|
|
21251
|
+
};
|
|
21252
|
+
this.chunks = splitIntoChunks(rows, this.options.chunkSize);
|
|
21253
|
+
this.totalChunks = this.chunks.length;
|
|
21254
|
+
}
|
|
21255
|
+
async execute() {
|
|
21256
|
+
const buildTask = (chunk, chunkIndex) => async () => {
|
|
21257
|
+
return runChunk(
|
|
21258
|
+
() => this.executeChunk(chunk, chunkIndex),
|
|
21259
|
+
chunkIndex,
|
|
21260
|
+
this.totalChunks,
|
|
21261
|
+
chunk.length,
|
|
21262
|
+
this.options.timing,
|
|
21263
|
+
this.options.onChunkComplete
|
|
21264
|
+
);
|
|
21265
|
+
};
|
|
21266
|
+
const tasks = this.chunks.map((chunk, i) => buildTask(chunk, i));
|
|
21267
|
+
const outcomes = await maybeTransaction(
|
|
21268
|
+
this.session,
|
|
21269
|
+
this.options.transactional,
|
|
21270
|
+
() => runWithConcurrency(tasks, this.options.concurrency)
|
|
21271
|
+
);
|
|
21272
|
+
return this.options.timing ? aggregateOutcomesWithTimings(outcomes) : aggregateOutcomes(outcomes);
|
|
21273
|
+
}
|
|
21274
|
+
};
|
|
21275
|
+
|
|
21276
|
+
// src/bulk/bulk-insert-executor.ts
|
|
21277
|
+
var BulkInsertExecutor = class extends BulkBaseExecutor {
|
|
21278
|
+
constructor(session, table, rows, options = {}) {
|
|
21279
|
+
super(session, table, rows, options);
|
|
21280
|
+
}
|
|
21281
|
+
async executeChunk(chunk, chunkIndex) {
|
|
21282
|
+
const returningColumns = resolveReturningColumns(this.ctx, this.table, this.options.returning);
|
|
21283
|
+
let builder = new InsertQueryBuilder(this.table).values(chunk);
|
|
21284
|
+
if (this.options.onConflict) {
|
|
21285
|
+
const conflictColumns = this.options.onConflict.target?.columns ?? [];
|
|
21286
|
+
builder = builder.onConflict(conflictColumns);
|
|
21287
|
+
if (this.options.onConflict.action.type === "DoNothing") {
|
|
21288
|
+
builder = builder.doNothing();
|
|
21289
|
+
} else if (this.options.onConflict.action.type === "DoUpdate" && this.options.onConflict.action.set) {
|
|
21290
|
+
const setMap = {};
|
|
21291
|
+
for (const assignment of this.options.onConflict.action.set) {
|
|
21292
|
+
const colName = typeof assignment.column === "object" ? assignment.column.name : assignment.column;
|
|
21293
|
+
setMap[colName] = assignment.value;
|
|
21294
|
+
}
|
|
21295
|
+
builder = builder.doUpdate(setMap);
|
|
21296
|
+
}
|
|
21297
|
+
}
|
|
21298
|
+
const finalBuilder = builder;
|
|
21299
|
+
if (returningColumns?.length) {
|
|
21300
|
+
finalBuilder.returning(...returningColumns);
|
|
21301
|
+
}
|
|
21302
|
+
const compiled = finalBuilder.compile(this.ctx.dialect);
|
|
21303
|
+
const resultSets = await executeCompiled(this.ctx, compiled);
|
|
21304
|
+
return {
|
|
21305
|
+
processedRows: chunk.length,
|
|
21306
|
+
returning: returningColumns ? flattenQueryResults(resultSets) : [],
|
|
21307
|
+
elapsedMs: 0
|
|
21308
|
+
};
|
|
21309
|
+
}
|
|
21310
|
+
};
|
|
21311
|
+
async function bulkInsert(session, table, rows, options = {}) {
|
|
21312
|
+
if (!rows.length) {
|
|
21313
|
+
return { processedRows: 0, chunksExecuted: 0, returning: [] };
|
|
21314
|
+
}
|
|
21315
|
+
const executor = new BulkInsertExecutor(session, table, rows, options);
|
|
21316
|
+
return executor.execute();
|
|
21317
|
+
}
|
|
21318
|
+
|
|
21319
|
+
// src/bulk/bulk-update-executor.ts
|
|
21320
|
+
function resolveByColumns(table, by) {
|
|
21321
|
+
if (!by) return [findPrimaryKey(table)];
|
|
21322
|
+
return Array.isArray(by) ? by : [by];
|
|
21323
|
+
}
|
|
21324
|
+
var BulkUpdateExecutor = class extends BulkBaseExecutor {
|
|
21325
|
+
byColumns;
|
|
21326
|
+
constructor(session, table, rows, options = {}) {
|
|
21327
|
+
super(session, table, rows, options);
|
|
21328
|
+
this.byColumns = resolveByColumns(table, options.by);
|
|
21329
|
+
}
|
|
21330
|
+
async executeChunk(chunk, chunkIndex) {
|
|
21331
|
+
const allReturning = [];
|
|
21332
|
+
const returningColumns = resolveReturningColumns(this.ctx, this.table, this.options.returning);
|
|
21333
|
+
const extraWhere = this.options.where;
|
|
21334
|
+
for (const row of chunk) {
|
|
21335
|
+
const predicates = this.byColumns.map((colName) => {
|
|
21336
|
+
const col2 = this.table.columns[colName];
|
|
21337
|
+
if (!col2) {
|
|
21338
|
+
throw new Error(
|
|
21339
|
+
`bulkUpdate: column "${colName}" not found in table "${this.table.name}"`
|
|
21340
|
+
);
|
|
21341
|
+
}
|
|
21342
|
+
const val = row[colName];
|
|
21343
|
+
if (val === void 0) {
|
|
21344
|
+
throw new Error(
|
|
21345
|
+
`bulkUpdate: row is missing the identity column "${colName}" required by the "by" option`
|
|
21346
|
+
);
|
|
21347
|
+
}
|
|
21348
|
+
return eq(col2, val);
|
|
21349
|
+
});
|
|
21350
|
+
const whereExpr = predicates.length === 1 ? predicates[0] : predicates.reduce((acc, p) => and(acc, p), predicates[0]);
|
|
21351
|
+
const finalWhere = extraWhere ? and(whereExpr, extraWhere) : whereExpr;
|
|
21352
|
+
const bySet = new Set(this.byColumns);
|
|
21353
|
+
const setPayload = {};
|
|
21354
|
+
for (const [key, val] of Object.entries(row)) {
|
|
21355
|
+
if (!bySet.has(key) && key in this.table.columns) {
|
|
21356
|
+
setPayload[key] = val;
|
|
21357
|
+
}
|
|
21358
|
+
}
|
|
21359
|
+
if (!Object.keys(setPayload).length) continue;
|
|
21360
|
+
let builder = new UpdateQueryBuilder(this.table).set(setPayload).where(finalWhere);
|
|
21361
|
+
if (returningColumns?.length) {
|
|
21362
|
+
builder = builder.returning(...returningColumns);
|
|
21363
|
+
}
|
|
21364
|
+
const compiled = builder.compile(this.ctx.dialect);
|
|
21365
|
+
const resultSets = await executeCompiled(this.ctx, compiled);
|
|
21366
|
+
if (returningColumns) {
|
|
21367
|
+
allReturning.push(...flattenQueryResults(resultSets));
|
|
21368
|
+
}
|
|
21369
|
+
}
|
|
21370
|
+
return {
|
|
21371
|
+
processedRows: chunk.length,
|
|
21372
|
+
returning: allReturning,
|
|
21373
|
+
elapsedMs: 0
|
|
21374
|
+
};
|
|
21375
|
+
}
|
|
21376
|
+
};
|
|
21377
|
+
async function bulkUpdate(session, table, rows, options = {}) {
|
|
21378
|
+
if (!rows.length) {
|
|
21379
|
+
return { processedRows: 0, chunksExecuted: 0, returning: [] };
|
|
21380
|
+
}
|
|
21381
|
+
const executor = new BulkUpdateExecutor(session, table, rows, options);
|
|
21382
|
+
return executor.execute();
|
|
21383
|
+
}
|
|
21384
|
+
var DEFAULT_BULK_UPDATE_WHERE_CHUNK_SIZE = 500;
|
|
21385
|
+
async function bulkUpdateWhere(session, table, ids, set, options = {}) {
|
|
21386
|
+
if (!ids.length) {
|
|
21387
|
+
return { processedRows: 0, chunksExecuted: 0, returning: [] };
|
|
21388
|
+
}
|
|
21389
|
+
const {
|
|
21390
|
+
chunkSize = DEFAULT_BULK_UPDATE_WHERE_CHUNK_SIZE,
|
|
21391
|
+
concurrency = "sequential",
|
|
21392
|
+
transactional = true,
|
|
21393
|
+
timing = false,
|
|
21394
|
+
onChunkComplete,
|
|
21395
|
+
by,
|
|
21396
|
+
where: extraWhere,
|
|
21397
|
+
returning
|
|
21398
|
+
} = options;
|
|
21399
|
+
const ctx = createBulkExecutionContext(session);
|
|
21400
|
+
const byColumnName = by ?? findPrimaryKey(table);
|
|
21401
|
+
const byColumn = table.columns[byColumnName];
|
|
21402
|
+
if (!byColumn) {
|
|
21403
|
+
throw new Error(
|
|
21404
|
+
`bulkUpdateWhere: column "${byColumnName}" not found in table "${table.name}"`
|
|
21405
|
+
);
|
|
21406
|
+
}
|
|
21407
|
+
const returningColumns = resolveReturningColumns(ctx, table, returning);
|
|
21408
|
+
const chunks = splitIntoChunks(ids, chunkSize);
|
|
21409
|
+
const totalChunks = chunks.length;
|
|
21410
|
+
const buildTask = (chunk, chunkIndex) => async () => {
|
|
21411
|
+
return runChunk(
|
|
21412
|
+
async () => {
|
|
21413
|
+
const inExpr = inList(byColumn, chunk);
|
|
21414
|
+
const finalWhere = extraWhere ? and(inExpr, extraWhere) : inExpr;
|
|
21415
|
+
let builder = new UpdateQueryBuilder(table).set(set).where(finalWhere);
|
|
21416
|
+
if (returningColumns?.length) {
|
|
21417
|
+
builder = builder.returning(...returningColumns);
|
|
21418
|
+
}
|
|
21419
|
+
const compiled = builder.compile(ctx.dialect);
|
|
21420
|
+
const resultSets = await executeCompiled(ctx, compiled);
|
|
21421
|
+
return {
|
|
21422
|
+
processedRows: chunk.length,
|
|
21423
|
+
returning: returningColumns ? flattenQueryResults(resultSets) : [],
|
|
21424
|
+
elapsedMs: 0
|
|
21425
|
+
};
|
|
21426
|
+
},
|
|
21427
|
+
chunkIndex,
|
|
21428
|
+
totalChunks,
|
|
21429
|
+
chunk.length,
|
|
21430
|
+
timing,
|
|
21431
|
+
onChunkComplete
|
|
21432
|
+
);
|
|
21433
|
+
};
|
|
21434
|
+
const tasks = chunks.map((chunk, i) => buildTask(chunk, i));
|
|
21435
|
+
const outcomes = await maybeTransaction(
|
|
21436
|
+
session,
|
|
21437
|
+
transactional,
|
|
21438
|
+
() => runWithConcurrency(tasks, concurrency)
|
|
21439
|
+
);
|
|
21440
|
+
return timing ? aggregateOutcomesWithTimings(outcomes) : aggregateOutcomes(outcomes);
|
|
21441
|
+
}
|
|
21442
|
+
|
|
21443
|
+
// src/bulk/bulk-delete-executor.ts
|
|
21444
|
+
var BulkDeleteExecutor = class extends BulkBaseExecutor {
|
|
21445
|
+
byColumnName;
|
|
21446
|
+
constructor(session, table, ids, options = {}) {
|
|
21447
|
+
super(session, table, ids, options);
|
|
21448
|
+
this.byColumnName = options.by ?? findPrimaryKey(table);
|
|
21449
|
+
}
|
|
21450
|
+
async executeChunk(chunk, chunkIndex) {
|
|
21451
|
+
const byColumn = this.table.columns[this.byColumnName];
|
|
21452
|
+
if (!byColumn) {
|
|
21453
|
+
throw new Error(
|
|
21454
|
+
`bulkDelete: column "${this.byColumnName}" not found in table "${this.table.name}"`
|
|
21455
|
+
);
|
|
21456
|
+
}
|
|
21457
|
+
const extraWhere = this.options.where;
|
|
21458
|
+
const inExpr = inList(byColumn, chunk);
|
|
21459
|
+
const finalWhere = extraWhere ? and(inExpr, extraWhere) : inExpr;
|
|
21460
|
+
const builder = new DeleteQueryBuilder(this.table).where(finalWhere);
|
|
21461
|
+
const compiled = builder.compile(this.ctx.dialect);
|
|
21462
|
+
await executeCompiled(this.ctx, compiled);
|
|
21463
|
+
return {
|
|
21464
|
+
processedRows: chunk.length,
|
|
21465
|
+
returning: [],
|
|
21466
|
+
elapsedMs: 0
|
|
21467
|
+
};
|
|
21468
|
+
}
|
|
21469
|
+
};
|
|
21470
|
+
async function bulkDelete(session, table, ids, options = {}) {
|
|
21471
|
+
if (!ids.length) {
|
|
21472
|
+
return { processedRows: 0, chunksExecuted: 0, returning: [] };
|
|
21473
|
+
}
|
|
21474
|
+
const executor = new BulkDeleteExecutor(session, table, ids, options);
|
|
21475
|
+
return executor.execute();
|
|
21476
|
+
}
|
|
21477
|
+
async function bulkDeleteWhere(session, table, where, options = {}) {
|
|
21478
|
+
const { transactional = false } = options;
|
|
21479
|
+
const ctx = createBulkExecutionContext(session);
|
|
21480
|
+
const builder = new DeleteQueryBuilder(table).where(where);
|
|
21481
|
+
const compiled = builder.compile(ctx.dialect);
|
|
21482
|
+
const execute = async () => {
|
|
21483
|
+
await executeCompiled(ctx, compiled);
|
|
21484
|
+
return { processedRows: 0, chunksExecuted: 1, returning: [] };
|
|
21485
|
+
};
|
|
21486
|
+
return maybeTransaction(session, transactional, execute);
|
|
21487
|
+
}
|
|
21488
|
+
|
|
21489
|
+
// src/bulk/bulk-upsert-executor.ts
|
|
21490
|
+
var DEFAULT_CHUNK_SIZE2 = 500;
|
|
21491
|
+
var BulkUpsertExecutor = class extends BulkBaseExecutor {
|
|
21492
|
+
conflictTargetNodes;
|
|
21493
|
+
updateColumns;
|
|
21494
|
+
constructor(session, table, rows, options = {}) {
|
|
21495
|
+
super(session, table, rows, { ...options, chunkSize: options.chunkSize ?? DEFAULT_CHUNK_SIZE2 });
|
|
21496
|
+
const pkName = findPrimaryKey(table);
|
|
21497
|
+
const conflictTargetNames = options.conflictColumns ?? [pkName];
|
|
21498
|
+
this.conflictTargetNodes = conflictTargetNames.map((name) => ({
|
|
21499
|
+
type: "Column",
|
|
21500
|
+
table: table.name,
|
|
21501
|
+
name
|
|
21502
|
+
}));
|
|
21503
|
+
const conflictSet = new Set(conflictTargetNames);
|
|
21504
|
+
this.updateColumns = options.updateColumns ?? Object.keys(rows[0] ?? {}).filter((col2) => !conflictSet.has(col2) && col2 in table.columns);
|
|
21505
|
+
}
|
|
21506
|
+
async executeChunk(chunk, chunkIndex) {
|
|
21507
|
+
const returningColumns = resolveReturningColumns(this.ctx, this.table, this.options.returning);
|
|
21508
|
+
const set = {};
|
|
21509
|
+
for (const col2 of this.updateColumns) {
|
|
21510
|
+
set[col2] = { type: "ExcludedColumn", name: col2 };
|
|
21511
|
+
}
|
|
21512
|
+
let builder;
|
|
21513
|
+
if (this.updateColumns.length === 0) {
|
|
21514
|
+
builder = new InsertQueryBuilder(this.table).values(chunk).onConflict(this.conflictTargetNodes).doNothing();
|
|
21515
|
+
} else {
|
|
21516
|
+
builder = new InsertQueryBuilder(this.table).values(chunk).onConflict(this.conflictTargetNodes).doUpdate(set);
|
|
21517
|
+
}
|
|
21518
|
+
const finalBuilder = builder;
|
|
21519
|
+
if (returningColumns?.length) {
|
|
21520
|
+
finalBuilder.returning(...returningColumns);
|
|
21521
|
+
}
|
|
21522
|
+
const compiled = finalBuilder.compile(this.ctx.dialect);
|
|
21523
|
+
const resultSets = await executeCompiled(this.ctx, compiled);
|
|
21524
|
+
return {
|
|
21525
|
+
processedRows: chunk.length,
|
|
21526
|
+
returning: returningColumns ? flattenQueryResults(resultSets) : [],
|
|
21527
|
+
elapsedMs: 0
|
|
21528
|
+
};
|
|
21529
|
+
}
|
|
21530
|
+
};
|
|
21531
|
+
async function bulkUpsert(session, table, rows, options = {}) {
|
|
21532
|
+
if (!rows.length) {
|
|
21533
|
+
return { processedRows: 0, chunksExecuted: 0, returning: [] };
|
|
21534
|
+
}
|
|
21535
|
+
const executor = new BulkUpsertExecutor(session, table, rows, options);
|
|
21536
|
+
return executor.execute();
|
|
21537
|
+
}
|
|
19468
21538
|
export {
|
|
19469
21539
|
Alphanumeric,
|
|
19470
21540
|
AsyncLocalStorage,
|
|
@@ -19473,6 +21543,10 @@ export {
|
|
|
19473
21543
|
BigIntTypeStrategy,
|
|
19474
21544
|
BinaryTypeStrategy,
|
|
19475
21545
|
BooleanTypeStrategy,
|
|
21546
|
+
BulkDeleteExecutor,
|
|
21547
|
+
BulkInsertExecutor,
|
|
21548
|
+
BulkUpdateExecutor,
|
|
21549
|
+
BulkUpsertExecutor,
|
|
19476
21550
|
CEP,
|
|
19477
21551
|
CNPJ,
|
|
19478
21552
|
CPF,
|
|
@@ -19488,6 +21562,9 @@ export {
|
|
|
19488
21562
|
DefaultEntityMaterializer,
|
|
19489
21563
|
DefaultHasManyCollection,
|
|
19490
21564
|
DefaultManyToManyCollection,
|
|
21565
|
+
DefaultMorphManyCollection,
|
|
21566
|
+
DefaultMorphOneReference,
|
|
21567
|
+
DefaultMorphToReference,
|
|
19491
21568
|
DefaultTypeStrategy,
|
|
19492
21569
|
DeleteQueryBuilder,
|
|
19493
21570
|
DomainEventBus,
|
|
@@ -19503,6 +21580,9 @@ export {
|
|
|
19503
21580
|
Length,
|
|
19504
21581
|
Lower,
|
|
19505
21582
|
MemoryCacheAdapter,
|
|
21583
|
+
MorphMany,
|
|
21584
|
+
MorphOne,
|
|
21585
|
+
MorphTo,
|
|
19506
21586
|
MySqlDialect,
|
|
19507
21587
|
NestedSetStrategy,
|
|
19508
21588
|
Orm,
|
|
@@ -19561,6 +21641,12 @@ export {
|
|
|
19561
21641
|
bootstrapEntities,
|
|
19562
21642
|
buildFilterExpression,
|
|
19563
21643
|
buildScopeConditions,
|
|
21644
|
+
bulkDelete,
|
|
21645
|
+
bulkDeleteWhere,
|
|
21646
|
+
bulkInsert,
|
|
21647
|
+
bulkUpdate,
|
|
21648
|
+
bulkUpdateWhere,
|
|
21649
|
+
bulkUpsert,
|
|
19564
21650
|
calculateRowDepths,
|
|
19565
21651
|
calculateTotalPages,
|
|
19566
21652
|
callProcedure,
|
|
@@ -19593,6 +21679,7 @@ export {
|
|
|
19593
21679
|
count,
|
|
19594
21680
|
countAll,
|
|
19595
21681
|
createApiComponentsSection,
|
|
21682
|
+
createBetterSqlite3Executor,
|
|
19596
21683
|
createDeterministicNamingState,
|
|
19597
21684
|
createDtoToOpenApiSchema,
|
|
19598
21685
|
createEntityFromRow,
|
|
@@ -19694,12 +21781,16 @@ export {
|
|
|
19694
21781
|
isCastExpressionNode,
|
|
19695
21782
|
isCollateExpressionNode,
|
|
19696
21783
|
isComponentReference,
|
|
21784
|
+
isDistinctFrom,
|
|
19697
21785
|
isExpressionSelectionNode,
|
|
19698
21786
|
isFunctionNode,
|
|
21787
|
+
isMorphRelation,
|
|
21788
|
+
isNotDistinctFrom,
|
|
19699
21789
|
isNotNull,
|
|
19700
21790
|
isNull,
|
|
19701
21791
|
isNullableColumn,
|
|
19702
21792
|
isOperandNode,
|
|
21793
|
+
isSingleTargetRelation,
|
|
19703
21794
|
isTableDef2 as isTableDef,
|
|
19704
21795
|
isTreeConfig,
|
|
19705
21796
|
isValidDuration,
|
|
@@ -19723,6 +21814,9 @@ export {
|
|
|
19723
21814
|
loadBelongsToRelation,
|
|
19724
21815
|
loadHasManyRelation,
|
|
19725
21816
|
loadHasOneRelation,
|
|
21817
|
+
loadMorphManyRelation,
|
|
21818
|
+
loadMorphOneRelation,
|
|
21819
|
+
loadMorphToRelation,
|
|
19726
21820
|
localTime,
|
|
19727
21821
|
localTimestamp,
|
|
19728
21822
|
locate,
|
|
@@ -19744,11 +21838,15 @@ export {
|
|
|
19744
21838
|
minute,
|
|
19745
21839
|
mod,
|
|
19746
21840
|
month,
|
|
21841
|
+
morphMany,
|
|
21842
|
+
morphOne,
|
|
21843
|
+
morphTo,
|
|
19747
21844
|
mul,
|
|
19748
21845
|
neq,
|
|
19749
21846
|
nestedDtoToOpenApiSchema,
|
|
19750
21847
|
nestedWhereInputToOpenApiSchema,
|
|
19751
21848
|
normalizeColumnType,
|
|
21849
|
+
not,
|
|
19752
21850
|
notBetween,
|
|
19753
21851
|
notExists,
|
|
19754
21852
|
notInList,
|