metal-orm 1.1.9 → 1.1.11
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 +2255 -284
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +559 -39
- package/dist/index.d.ts +559 -39
- package/dist/index.js +2227 -284
- package/dist/index.js.map +1 -1
- package/package.json +17 -12
- package/scripts/generate-entities/render.mjs +21 -12
- package/scripts/generate-entities/schema.mjs +87 -73
- package/scripts/generate-entities/tree-detection.mjs +67 -61
- package/src/bulk/bulk-context.ts +83 -0
- package/src/bulk/bulk-delete-executor.ts +87 -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 +93 -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/ddl/introspect/mysql.ts +113 -36
- 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/select-operations.ts +110 -105
- 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.cjs
CHANGED
|
@@ -50,6 +50,10 @@ __export(index_exports, {
|
|
|
50
50
|
BigIntTypeStrategy: () => BigIntTypeStrategy,
|
|
51
51
|
BinaryTypeStrategy: () => BinaryTypeStrategy,
|
|
52
52
|
BooleanTypeStrategy: () => BooleanTypeStrategy,
|
|
53
|
+
BulkDeleteExecutor: () => BulkDeleteExecutor,
|
|
54
|
+
BulkInsertExecutor: () => BulkInsertExecutor,
|
|
55
|
+
BulkUpdateExecutor: () => BulkUpdateExecutor,
|
|
56
|
+
BulkUpsertExecutor: () => BulkUpsertExecutor,
|
|
53
57
|
CEP: () => CEP,
|
|
54
58
|
CNPJ: () => CNPJ,
|
|
55
59
|
CPF: () => CPF,
|
|
@@ -65,6 +69,9 @@ __export(index_exports, {
|
|
|
65
69
|
DefaultEntityMaterializer: () => DefaultEntityMaterializer,
|
|
66
70
|
DefaultHasManyCollection: () => DefaultHasManyCollection,
|
|
67
71
|
DefaultManyToManyCollection: () => DefaultManyToManyCollection,
|
|
72
|
+
DefaultMorphManyCollection: () => DefaultMorphManyCollection,
|
|
73
|
+
DefaultMorphOneReference: () => DefaultMorphOneReference,
|
|
74
|
+
DefaultMorphToReference: () => DefaultMorphToReference,
|
|
68
75
|
DefaultTypeStrategy: () => DefaultTypeStrategy,
|
|
69
76
|
DeleteQueryBuilder: () => DeleteQueryBuilder,
|
|
70
77
|
DomainEventBus: () => DomainEventBus,
|
|
@@ -80,6 +87,9 @@ __export(index_exports, {
|
|
|
80
87
|
Length: () => Length,
|
|
81
88
|
Lower: () => Lower,
|
|
82
89
|
MemoryCacheAdapter: () => MemoryCacheAdapter,
|
|
90
|
+
MorphMany: () => MorphMany,
|
|
91
|
+
MorphOne: () => MorphOne,
|
|
92
|
+
MorphTo: () => MorphTo,
|
|
83
93
|
MySqlDialect: () => MySqlDialect,
|
|
84
94
|
NestedSetStrategy: () => NestedSetStrategy,
|
|
85
95
|
Orm: () => Orm,
|
|
@@ -138,6 +148,12 @@ __export(index_exports, {
|
|
|
138
148
|
bootstrapEntities: () => bootstrapEntities,
|
|
139
149
|
buildFilterExpression: () => buildFilterExpression,
|
|
140
150
|
buildScopeConditions: () => buildScopeConditions,
|
|
151
|
+
bulkDelete: () => bulkDelete,
|
|
152
|
+
bulkDeleteWhere: () => bulkDeleteWhere,
|
|
153
|
+
bulkInsert: () => bulkInsert,
|
|
154
|
+
bulkUpdate: () => bulkUpdate,
|
|
155
|
+
bulkUpdateWhere: () => bulkUpdateWhere,
|
|
156
|
+
bulkUpsert: () => bulkUpsert,
|
|
141
157
|
calculateRowDepths: () => calculateRowDepths,
|
|
142
158
|
calculateTotalPages: () => calculateTotalPages,
|
|
143
159
|
callProcedure: () => callProcedure,
|
|
@@ -170,6 +186,7 @@ __export(index_exports, {
|
|
|
170
186
|
count: () => count,
|
|
171
187
|
countAll: () => countAll,
|
|
172
188
|
createApiComponentsSection: () => createApiComponentsSection,
|
|
189
|
+
createBetterSqlite3Executor: () => createBetterSqlite3Executor,
|
|
173
190
|
createDeterministicNamingState: () => createDeterministicNamingState,
|
|
174
191
|
createDtoToOpenApiSchema: () => createDtoToOpenApiSchema,
|
|
175
192
|
createEntityFromRow: () => createEntityFromRow,
|
|
@@ -271,12 +288,16 @@ __export(index_exports, {
|
|
|
271
288
|
isCastExpressionNode: () => isCastExpressionNode,
|
|
272
289
|
isCollateExpressionNode: () => isCollateExpressionNode,
|
|
273
290
|
isComponentReference: () => isComponentReference,
|
|
291
|
+
isDistinctFrom: () => isDistinctFrom,
|
|
274
292
|
isExpressionSelectionNode: () => isExpressionSelectionNode,
|
|
275
293
|
isFunctionNode: () => isFunctionNode,
|
|
294
|
+
isMorphRelation: () => isMorphRelation,
|
|
295
|
+
isNotDistinctFrom: () => isNotDistinctFrom,
|
|
276
296
|
isNotNull: () => isNotNull,
|
|
277
297
|
isNull: () => isNull,
|
|
278
298
|
isNullableColumn: () => isNullableColumn,
|
|
279
299
|
isOperandNode: () => isOperandNode,
|
|
300
|
+
isSingleTargetRelation: () => isSingleTargetRelation,
|
|
280
301
|
isTableDef: () => isTableDef2,
|
|
281
302
|
isTreeConfig: () => isTreeConfig,
|
|
282
303
|
isValidDuration: () => isValidDuration,
|
|
@@ -300,6 +321,9 @@ __export(index_exports, {
|
|
|
300
321
|
loadBelongsToRelation: () => loadBelongsToRelation,
|
|
301
322
|
loadHasManyRelation: () => loadHasManyRelation,
|
|
302
323
|
loadHasOneRelation: () => loadHasOneRelation,
|
|
324
|
+
loadMorphManyRelation: () => loadMorphManyRelation,
|
|
325
|
+
loadMorphOneRelation: () => loadMorphOneRelation,
|
|
326
|
+
loadMorphToRelation: () => loadMorphToRelation,
|
|
303
327
|
localTime: () => localTime,
|
|
304
328
|
localTimestamp: () => localTimestamp,
|
|
305
329
|
locate: () => locate,
|
|
@@ -321,11 +345,15 @@ __export(index_exports, {
|
|
|
321
345
|
minute: () => minute,
|
|
322
346
|
mod: () => mod,
|
|
323
347
|
month: () => month,
|
|
348
|
+
morphMany: () => morphMany,
|
|
349
|
+
morphOne: () => morphOne,
|
|
350
|
+
morphTo: () => morphTo,
|
|
324
351
|
mul: () => mul,
|
|
325
352
|
neq: () => neq,
|
|
326
353
|
nestedDtoToOpenApiSchema: () => nestedDtoToOpenApiSchema,
|
|
327
354
|
nestedWhereInputToOpenApiSchema: () => nestedWhereInputToOpenApiSchema,
|
|
328
355
|
normalizeColumnType: () => normalizeColumnType,
|
|
356
|
+
not: () => not,
|
|
329
357
|
notBetween: () => notBetween,
|
|
330
358
|
notExists: () => notExists,
|
|
331
359
|
notInList: () => notInList,
|
|
@@ -732,7 +760,13 @@ var RelationKinds = {
|
|
|
732
760
|
/** Many-to-one relationship */
|
|
733
761
|
BelongsTo: "BELONGS_TO",
|
|
734
762
|
/** Many-to-many relationship with pivot metadata */
|
|
735
|
-
BelongsToMany: "BELONGS_TO_MANY"
|
|
763
|
+
BelongsToMany: "BELONGS_TO_MANY",
|
|
764
|
+
/** Polymorphic inverse (child side) */
|
|
765
|
+
MorphTo: "MORPH_TO",
|
|
766
|
+
/** Polymorphic one-to-one (parent side) */
|
|
767
|
+
MorphOne: "MORPH_ONE",
|
|
768
|
+
/** Polymorphic one-to-many (parent side) */
|
|
769
|
+
MorphMany: "MORPH_MANY"
|
|
736
770
|
};
|
|
737
771
|
var hasMany = (target, foreignKey, localKey, cascade) => ({
|
|
738
772
|
type: RelationKinds.HasMany,
|
|
@@ -767,6 +801,32 @@ var belongsToMany = (target, pivotTable, options) => ({
|
|
|
767
801
|
defaultPivotColumns: options.defaultPivotColumns,
|
|
768
802
|
cascade: options.cascade
|
|
769
803
|
});
|
|
804
|
+
var isSingleTargetRelation = (rel) => rel.type !== RelationKinds.MorphTo;
|
|
805
|
+
var isMorphRelation = (rel) => rel.type === RelationKinds.MorphTo || rel.type === RelationKinds.MorphOne || rel.type === RelationKinds.MorphMany;
|
|
806
|
+
var morphTo = (opts) => ({
|
|
807
|
+
type: RelationKinds.MorphTo,
|
|
808
|
+
...opts
|
|
809
|
+
});
|
|
810
|
+
var morphOne = (target, opts) => ({
|
|
811
|
+
type: RelationKinds.MorphOne,
|
|
812
|
+
target,
|
|
813
|
+
morphName: opts.as,
|
|
814
|
+
typeField: opts.typeField ?? `${opts.as}Type`,
|
|
815
|
+
idField: opts.idField ?? `${opts.as}Id`,
|
|
816
|
+
typeValue: opts.typeValue,
|
|
817
|
+
localKey: opts.localKey,
|
|
818
|
+
cascade: opts.cascade
|
|
819
|
+
});
|
|
820
|
+
var morphMany = (target, opts) => ({
|
|
821
|
+
type: RelationKinds.MorphMany,
|
|
822
|
+
target,
|
|
823
|
+
morphName: opts.as,
|
|
824
|
+
typeField: opts.typeField ?? `${opts.as}Type`,
|
|
825
|
+
idField: opts.idField ?? `${opts.as}Id`,
|
|
826
|
+
typeValue: opts.typeValue,
|
|
827
|
+
localKey: opts.localKey,
|
|
828
|
+
cascade: opts.cascade
|
|
829
|
+
});
|
|
770
830
|
|
|
771
831
|
// src/core/ast/expression-nodes.ts
|
|
772
832
|
var operandTypes = /* @__PURE__ */ new Set([
|
|
@@ -894,6 +954,10 @@ var or = (...operands) => ({
|
|
|
894
954
|
operator: "OR",
|
|
895
955
|
operands
|
|
896
956
|
});
|
|
957
|
+
var not = (operand) => ({
|
|
958
|
+
type: "NotExpression",
|
|
959
|
+
operand
|
|
960
|
+
});
|
|
897
961
|
var isNull = (left2) => ({
|
|
898
962
|
type: "NullExpression",
|
|
899
963
|
left: toOperandNode(left2),
|
|
@@ -977,6 +1041,18 @@ var collate = (expression, collation) => ({
|
|
|
977
1041
|
expression: toOperand(expression),
|
|
978
1042
|
collation
|
|
979
1043
|
});
|
|
1044
|
+
var isDistinctFrom = (left2, right2) => ({
|
|
1045
|
+
type: "IsDistinctExpression",
|
|
1046
|
+
left: toOperandNode(left2),
|
|
1047
|
+
operator: "IS DISTINCT FROM",
|
|
1048
|
+
right: toOperand(right2)
|
|
1049
|
+
});
|
|
1050
|
+
var isNotDistinctFrom = (left2, right2) => ({
|
|
1051
|
+
type: "IsDistinctExpression",
|
|
1052
|
+
left: toOperandNode(left2),
|
|
1053
|
+
operator: "IS NOT DISTINCT FROM",
|
|
1054
|
+
right: toOperand(right2)
|
|
1055
|
+
});
|
|
980
1056
|
|
|
981
1057
|
// src/core/ast/window-functions.ts
|
|
982
1058
|
var buildWindowFunction = (name, args = [], partitionBy, orderBy) => {
|
|
@@ -1183,6 +1259,9 @@ var visitExpression = (node, visitor) => {
|
|
|
1183
1259
|
case "LogicalExpression":
|
|
1184
1260
|
if (visitor.visitLogicalExpression) return visitor.visitLogicalExpression(node);
|
|
1185
1261
|
break;
|
|
1262
|
+
case "NotExpression":
|
|
1263
|
+
if (visitor.visitNotExpression) return visitor.visitNotExpression(node);
|
|
1264
|
+
break;
|
|
1186
1265
|
case "NullExpression":
|
|
1187
1266
|
if (visitor.visitNullExpression) return visitor.visitNullExpression(node);
|
|
1188
1267
|
break;
|
|
@@ -1201,6 +1280,9 @@ var visitExpression = (node, visitor) => {
|
|
|
1201
1280
|
case "BitwiseExpression":
|
|
1202
1281
|
if (visitor.visitBitwiseExpression) return visitor.visitBitwiseExpression(node);
|
|
1203
1282
|
break;
|
|
1283
|
+
case "IsDistinctExpression":
|
|
1284
|
+
if (visitor.visitIsDistinctExpression) return visitor.visitIsDistinctExpression(node);
|
|
1285
|
+
break;
|
|
1204
1286
|
default:
|
|
1205
1287
|
break;
|
|
1206
1288
|
}
|
|
@@ -1924,6 +2006,10 @@ var Dialect = class _Dialect {
|
|
|
1924
2006
|
});
|
|
1925
2007
|
return parts.join(` ${logical.operator} `);
|
|
1926
2008
|
});
|
|
2009
|
+
this.registerExpressionCompiler("NotExpression", (notExpr, ctx) => {
|
|
2010
|
+
const operand = this.compileExpression(notExpr.operand, ctx);
|
|
2011
|
+
return `NOT (${operand})`;
|
|
2012
|
+
});
|
|
1927
2013
|
this.registerExpressionCompiler("NullExpression", (nullExpr, ctx) => {
|
|
1928
2014
|
const left2 = this.compileOperand(nullExpr.left, ctx);
|
|
1929
2015
|
return `${left2} ${nullExpr.operator}`;
|
|
@@ -1957,6 +2043,11 @@ var Dialect = class _Dialect {
|
|
|
1957
2043
|
const right2 = this.compileOperand(bitwise.right, ctx);
|
|
1958
2044
|
return `${left2} ${bitwise.operator} ${right2}`;
|
|
1959
2045
|
});
|
|
2046
|
+
this.registerExpressionCompiler("IsDistinctExpression", (node, ctx) => {
|
|
2047
|
+
const left2 = this.compileOperand(node.left, ctx);
|
|
2048
|
+
const right2 = this.compileOperand(node.right, ctx);
|
|
2049
|
+
return `${left2} ${node.operator} ${right2}`;
|
|
2050
|
+
});
|
|
1960
2051
|
}
|
|
1961
2052
|
registerDefaultOperandCompilers() {
|
|
1962
2053
|
this.registerOperandCompiler("Literal", (literal, ctx) => ctx.addParameter(literal.value));
|
|
@@ -2878,6 +2969,18 @@ var MySqlDialect = class extends SqlDialectBase {
|
|
|
2878
2969
|
*/
|
|
2879
2970
|
constructor() {
|
|
2880
2971
|
super(new MysqlFunctionStrategy());
|
|
2972
|
+
this.registerExpressionCompiler(
|
|
2973
|
+
"IsDistinctExpression",
|
|
2974
|
+
(node, ctx) => {
|
|
2975
|
+
const left2 = this.compileOperand(node.left, ctx);
|
|
2976
|
+
const right2 = this.compileOperand(node.right, ctx);
|
|
2977
|
+
const spaceship = `${left2} <=> ${right2}`;
|
|
2978
|
+
if (node.operator === "IS NOT DISTINCT FROM") {
|
|
2979
|
+
return spaceship;
|
|
2980
|
+
}
|
|
2981
|
+
return `NOT (${spaceship})`;
|
|
2982
|
+
}
|
|
2983
|
+
);
|
|
2881
2984
|
}
|
|
2882
2985
|
/**
|
|
2883
2986
|
* Quotes an identifier using MySQL backtick syntax
|
|
@@ -3977,7 +4080,7 @@ var HydrationManager = class _HydrationManager {
|
|
|
3977
4080
|
*/
|
|
3978
4081
|
hasMultiplyingRelations(plan) {
|
|
3979
4082
|
return plan.relations.some(
|
|
3980
|
-
(rel) => rel.type === RelationKinds.HasMany || rel.type === RelationKinds.BelongsToMany
|
|
4083
|
+
(rel) => rel.type === RelationKinds.HasMany || rel.type === RelationKinds.BelongsToMany || rel.type === RelationKinds.MorphMany
|
|
3981
4084
|
);
|
|
3982
4085
|
}
|
|
3983
4086
|
/**
|
|
@@ -4311,6 +4414,36 @@ var HydrationPlanner = class _HydrationPlanner {
|
|
|
4311
4414
|
}
|
|
4312
4415
|
};
|
|
4313
4416
|
}
|
|
4417
|
+
case RelationKinds.MorphOne: {
|
|
4418
|
+
const morphRel = rel;
|
|
4419
|
+
const localKey = morphRel.localKey || findPrimaryKey(this.table);
|
|
4420
|
+
return {
|
|
4421
|
+
name: relationName,
|
|
4422
|
+
aliasPrefix,
|
|
4423
|
+
type: rel.type,
|
|
4424
|
+
targetTable: morphRel.target.name,
|
|
4425
|
+
targetPrimaryKey: findPrimaryKey(morphRel.target),
|
|
4426
|
+
foreignKey: morphRel.idField,
|
|
4427
|
+
localKey,
|
|
4428
|
+
columns
|
|
4429
|
+
};
|
|
4430
|
+
}
|
|
4431
|
+
case RelationKinds.MorphMany: {
|
|
4432
|
+
const morphRel = rel;
|
|
4433
|
+
const localKey = morphRel.localKey || findPrimaryKey(this.table);
|
|
4434
|
+
return {
|
|
4435
|
+
name: relationName,
|
|
4436
|
+
aliasPrefix,
|
|
4437
|
+
type: rel.type,
|
|
4438
|
+
targetTable: morphRel.target.name,
|
|
4439
|
+
targetPrimaryKey: findPrimaryKey(morphRel.target),
|
|
4440
|
+
foreignKey: morphRel.idField,
|
|
4441
|
+
localKey,
|
|
4442
|
+
columns
|
|
4443
|
+
};
|
|
4444
|
+
}
|
|
4445
|
+
case RelationKinds.MorphTo:
|
|
4446
|
+
throw new Error("MorphTo relations do not support hydration planning via JOIN.");
|
|
4314
4447
|
}
|
|
4315
4448
|
}
|
|
4316
4449
|
};
|
|
@@ -4615,23 +4748,44 @@ var assertNever = (value) => {
|
|
|
4615
4748
|
};
|
|
4616
4749
|
var baseRelationCondition = (root, relation, rootAlias, targetTableName) => {
|
|
4617
4750
|
const rootTable = rootAlias || root.name;
|
|
4751
|
+
if (relation.type === RelationKinds.MorphTo) {
|
|
4752
|
+
throw new Error("MorphTo relations do not support the standard join condition builder");
|
|
4753
|
+
}
|
|
4618
4754
|
const targetTable = targetTableName ?? relation.target.name;
|
|
4619
|
-
const defaultLocalKey = relation.type === RelationKinds.HasMany || relation.type === RelationKinds.HasOne ? findPrimaryKey(root) : findPrimaryKey(relation.target);
|
|
4620
|
-
const localKey = relation.localKey || defaultLocalKey;
|
|
4621
4755
|
switch (relation.type) {
|
|
4622
4756
|
case RelationKinds.HasMany:
|
|
4623
|
-
case RelationKinds.HasOne:
|
|
4757
|
+
case RelationKinds.HasOne: {
|
|
4758
|
+
const defaultLocalKey = findPrimaryKey(root);
|
|
4759
|
+
const localKey = relation.localKey || defaultLocalKey;
|
|
4624
4760
|
return eq(
|
|
4625
4761
|
{ type: "Column", table: targetTable, name: relation.foreignKey },
|
|
4626
4762
|
{ type: "Column", table: rootTable, name: localKey }
|
|
4627
4763
|
);
|
|
4628
|
-
|
|
4764
|
+
}
|
|
4765
|
+
case RelationKinds.BelongsTo: {
|
|
4766
|
+
const defaultLocalKey = findPrimaryKey(relation.target);
|
|
4767
|
+
const localKey = relation.localKey || defaultLocalKey;
|
|
4629
4768
|
return eq(
|
|
4630
4769
|
{ type: "Column", table: targetTable, name: localKey },
|
|
4631
4770
|
{ type: "Column", table: rootTable, name: relation.foreignKey }
|
|
4632
4771
|
);
|
|
4772
|
+
}
|
|
4633
4773
|
case RelationKinds.BelongsToMany:
|
|
4634
4774
|
throw new Error("BelongsToMany relations do not support the standard join condition builder");
|
|
4775
|
+
case RelationKinds.MorphOne:
|
|
4776
|
+
case RelationKinds.MorphMany: {
|
|
4777
|
+
const morphRel = relation;
|
|
4778
|
+
const morphLocalKey = morphRel.localKey || findPrimaryKey(root);
|
|
4779
|
+
const baseCondition = eq(
|
|
4780
|
+
{ type: "Column", table: targetTable, name: morphRel.idField },
|
|
4781
|
+
{ type: "Column", table: rootTable, name: morphLocalKey }
|
|
4782
|
+
);
|
|
4783
|
+
const discriminatorCondition = eq(
|
|
4784
|
+
{ type: "Column", table: targetTable, name: morphRel.typeField },
|
|
4785
|
+
{ type: "Literal", value: morphRel.typeValue }
|
|
4786
|
+
);
|
|
4787
|
+
return and(baseCondition, discriminatorCondition);
|
|
4788
|
+
}
|
|
4635
4789
|
default:
|
|
4636
4790
|
return assertNever(relation);
|
|
4637
4791
|
}
|
|
@@ -4727,6 +4881,9 @@ var collectFromExpression = (expr, collector) => {
|
|
|
4727
4881
|
case "LogicalExpression":
|
|
4728
4882
|
expr.operands.forEach((operand) => collectFromExpression(operand, collector));
|
|
4729
4883
|
break;
|
|
4884
|
+
case "NotExpression":
|
|
4885
|
+
collectFromExpression(expr.operand, collector);
|
|
4886
|
+
break;
|
|
4730
4887
|
case "NullExpression":
|
|
4731
4888
|
collectFromOperand(expr.left, collector);
|
|
4732
4889
|
break;
|
|
@@ -4833,6 +4990,11 @@ var mapExpression = (expr, fromTable, toTable) => {
|
|
|
4833
4990
|
if (nextOperands.every((op, i) => op === expr.operands[i])) return expr;
|
|
4834
4991
|
return { ...expr, operands: nextOperands };
|
|
4835
4992
|
}
|
|
4993
|
+
case "NotExpression": {
|
|
4994
|
+
const operand = mapExpression(expr.operand, fromTable, toTable);
|
|
4995
|
+
if (operand === expr.operand) return expr;
|
|
4996
|
+
return { ...expr, operand };
|
|
4997
|
+
}
|
|
4836
4998
|
case "NullExpression": {
|
|
4837
4999
|
const left2 = mapOperand(expr.left, fromTable, toTable);
|
|
4838
5000
|
if (left2 === expr.left) return expr;
|
|
@@ -5133,6 +5295,9 @@ var addRelationJoin = (params) => {
|
|
|
5133
5295
|
);
|
|
5134
5296
|
return joins.reduce((curr, join) => curr.withJoin(join), state);
|
|
5135
5297
|
}
|
|
5298
|
+
if (!isSingleTargetRelation(relation)) {
|
|
5299
|
+
throw new Error("Polymorphic MorphTo relations do not support join-based strategies");
|
|
5300
|
+
}
|
|
5136
5301
|
let targetSource = tableSource ?? {
|
|
5137
5302
|
type: "Table",
|
|
5138
5303
|
name: relation.target.name,
|
|
@@ -5148,6 +5313,9 @@ var addRelationJoin = (params) => {
|
|
|
5148
5313
|
var updateRelationJoin = (params) => {
|
|
5149
5314
|
const { joins, joinIndex, relation, currentTable, currentAlias, options } = params;
|
|
5150
5315
|
const join = joins[joinIndex];
|
|
5316
|
+
if (!isSingleTargetRelation(relation)) {
|
|
5317
|
+
throw new Error("Polymorphic MorphTo relations do not support join updates");
|
|
5318
|
+
}
|
|
5151
5319
|
const targetName = resolveTargetTableName(join.table, relation.target.name);
|
|
5152
5320
|
const extra = remapExpressionTable(options.filter, relation.target.name, targetName);
|
|
5153
5321
|
if (relation.type === RelationKinds.BelongsToMany) {
|
|
@@ -5207,6 +5375,9 @@ var RelationCteBuilder = class {
|
|
|
5207
5375
|
if (!predicate) {
|
|
5208
5376
|
throw new Error("Unable to build filter CTE without predicates.");
|
|
5209
5377
|
}
|
|
5378
|
+
if (!isSingleTargetRelation(relation)) {
|
|
5379
|
+
throw new Error("Polymorphic MorphTo relations do not support filter CTEs");
|
|
5380
|
+
}
|
|
5210
5381
|
const columns = Object.keys(relation.target.columns).map((name) => ({
|
|
5211
5382
|
type: "Column",
|
|
5212
5383
|
table: relation.target.name,
|
|
@@ -5254,6 +5425,9 @@ var buildTypedSelection = (columns, prefix, keys, missingMsg, tableOverride) =>
|
|
|
5254
5425
|
}, {});
|
|
5255
5426
|
};
|
|
5256
5427
|
var resolveTargetColumns = (relation, options) => {
|
|
5428
|
+
if (!isSingleTargetRelation(relation)) {
|
|
5429
|
+
return [];
|
|
5430
|
+
}
|
|
5257
5431
|
const requestedColumns = options?.columns?.length ? [...options.columns] : Object.keys(relation.target.columns);
|
|
5258
5432
|
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
5259
5433
|
if (!requestedColumns.includes(targetPrimaryKey)) {
|
|
@@ -5345,11 +5519,41 @@ var belongsToManyStrategy = (context) => {
|
|
|
5345
5519
|
);
|
|
5346
5520
|
return { state, hydration };
|
|
5347
5521
|
};
|
|
5522
|
+
var morphIncludeStrategy = (context) => {
|
|
5523
|
+
let { state, hydration } = context;
|
|
5524
|
+
const relation = context.relation;
|
|
5525
|
+
const targetColumns = resolveTargetColumns(relation, context.options);
|
|
5526
|
+
const tableOverride = getJoinCorrelationName(state, context.relationName, relation.target.name);
|
|
5527
|
+
const targetSelection = buildTypedSelection(
|
|
5528
|
+
relation.target.columns,
|
|
5529
|
+
context.aliasPrefix,
|
|
5530
|
+
targetColumns,
|
|
5531
|
+
(key) => `Column '${key}' not found on relation '${context.relationName}'`,
|
|
5532
|
+
tableOverride
|
|
5533
|
+
);
|
|
5534
|
+
const relationSelectionResult = context.selectColumns(state, hydration, targetSelection);
|
|
5535
|
+
state = relationSelectionResult.state;
|
|
5536
|
+
hydration = relationSelectionResult.hydration;
|
|
5537
|
+
hydration = hydration.onRelationIncluded(
|
|
5538
|
+
state,
|
|
5539
|
+
relation,
|
|
5540
|
+
context.relationName,
|
|
5541
|
+
context.aliasPrefix,
|
|
5542
|
+
targetColumns
|
|
5543
|
+
);
|
|
5544
|
+
return { state, hydration };
|
|
5545
|
+
};
|
|
5546
|
+
var morphToIncludeStrategy = () => {
|
|
5547
|
+
throw new Error("MorphTo relations do not support JOIN-based include. Use lazy loading instead.");
|
|
5548
|
+
};
|
|
5348
5549
|
var relationIncludeStrategies = {
|
|
5349
5550
|
[RelationKinds.HasMany]: standardIncludeStrategy,
|
|
5350
5551
|
[RelationKinds.HasOne]: standardIncludeStrategy,
|
|
5351
5552
|
[RelationKinds.BelongsTo]: standardIncludeStrategy,
|
|
5352
|
-
[RelationKinds.BelongsToMany]: belongsToManyStrategy
|
|
5553
|
+
[RelationKinds.BelongsToMany]: belongsToManyStrategy,
|
|
5554
|
+
[RelationKinds.MorphOne]: morphIncludeStrategy,
|
|
5555
|
+
[RelationKinds.MorphMany]: morphIncludeStrategy,
|
|
5556
|
+
[RelationKinds.MorphTo]: morphToIncludeStrategy
|
|
5353
5557
|
};
|
|
5354
5558
|
|
|
5355
5559
|
// src/query-builder/relation-service.ts
|
|
@@ -5418,6 +5622,12 @@ var RelationService = class {
|
|
|
5418
5622
|
let state = this.state;
|
|
5419
5623
|
let hydration = this.hydration;
|
|
5420
5624
|
const relation = this.getRelation(relationName);
|
|
5625
|
+
if (relation.type === RelationKinds.MorphTo) {
|
|
5626
|
+
throw new Error(`MorphTo relation '${relationName}' does not support include() via JOIN. Use lazy loading ($load) instead.`);
|
|
5627
|
+
}
|
|
5628
|
+
if (!isSingleTargetRelation(relation)) {
|
|
5629
|
+
return { state, hydration };
|
|
5630
|
+
}
|
|
5421
5631
|
const aliasPrefix = options?.aliasPrefix ?? relationName;
|
|
5422
5632
|
const alreadyJoined = hasJoinForRelationKey(state.ast.joins, relationName);
|
|
5423
5633
|
const { selfFilters, crossFilters } = splitFilterExpressions(
|
|
@@ -5476,6 +5686,9 @@ var RelationService = class {
|
|
|
5476
5686
|
*/
|
|
5477
5687
|
applyRelationCorrelation(relationName, ast, additionalCorrelation) {
|
|
5478
5688
|
const relation = this.getRelation(relationName);
|
|
5689
|
+
if (relation.type === RelationKinds.MorphTo) {
|
|
5690
|
+
throw new Error(`MorphTo relation '${relationName}' does not support correlation-based operations.`);
|
|
5691
|
+
}
|
|
5479
5692
|
const rootAlias = this.state.ast.from.type === "Table" ? this.state.ast.from.alias : void 0;
|
|
5480
5693
|
let correlation = buildRelationCorrelation(this.table, relation, rootAlias);
|
|
5481
5694
|
if (additionalCorrelation) {
|
|
@@ -5935,6 +6148,45 @@ var populateHydrationCache = (entity, row, meta) => {
|
|
|
5935
6148
|
}
|
|
5936
6149
|
}
|
|
5937
6150
|
}
|
|
6151
|
+
for (const relationName of Object.keys(meta.table.relations)) {
|
|
6152
|
+
const relation = meta.table.relations[relationName];
|
|
6153
|
+
const data = row[relationName];
|
|
6154
|
+
if (relation.type === RelationKinds.MorphOne) {
|
|
6155
|
+
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
6156
|
+
const rootValue = entity[localKey];
|
|
6157
|
+
if (rootValue === void 0 || rootValue === null) continue;
|
|
6158
|
+
if (!data || typeof data !== "object") continue;
|
|
6159
|
+
const cache = /* @__PURE__ */ new Map();
|
|
6160
|
+
cache.set(toKey2(rootValue), data);
|
|
6161
|
+
meta.relationHydration.set(relationName, cache);
|
|
6162
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
6163
|
+
continue;
|
|
6164
|
+
}
|
|
6165
|
+
if (relation.type === RelationKinds.MorphMany) {
|
|
6166
|
+
if (!Array.isArray(data)) continue;
|
|
6167
|
+
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
6168
|
+
const rootValue = entity[localKey];
|
|
6169
|
+
if (rootValue === void 0 || rootValue === null) continue;
|
|
6170
|
+
const cache = /* @__PURE__ */ new Map();
|
|
6171
|
+
cache.set(toKey2(rootValue), data);
|
|
6172
|
+
meta.relationHydration.set(relationName, cache);
|
|
6173
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
6174
|
+
continue;
|
|
6175
|
+
}
|
|
6176
|
+
if (relation.type === RelationKinds.MorphTo) {
|
|
6177
|
+
if (!data || typeof data !== "object") continue;
|
|
6178
|
+
const morphTo2 = relation;
|
|
6179
|
+
const typeValue = entity[morphTo2.typeField];
|
|
6180
|
+
const idValue = entity[morphTo2.idField];
|
|
6181
|
+
if (!typeValue || idValue === void 0 || idValue === null) continue;
|
|
6182
|
+
const compositeKey = `${toKey2(typeValue)}:${toKey2(idValue)}`;
|
|
6183
|
+
const cache = /* @__PURE__ */ new Map();
|
|
6184
|
+
cache.set(compositeKey, data);
|
|
6185
|
+
meta.relationHydration.set(relationName, cache);
|
|
6186
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
6187
|
+
continue;
|
|
6188
|
+
}
|
|
6189
|
+
}
|
|
5938
6190
|
};
|
|
5939
6191
|
|
|
5940
6192
|
// src/orm/relations/has-many.ts
|
|
@@ -6607,113 +6859,519 @@ var DefaultManyToManyCollection = class {
|
|
|
6607
6859
|
}
|
|
6608
6860
|
};
|
|
6609
6861
|
|
|
6610
|
-
// src/orm/
|
|
6611
|
-
var hasColumns = (columns) => Boolean(columns && columns.length > 0);
|
|
6612
|
-
var buildColumnSelection = (table, columns, missingMsg) => {
|
|
6613
|
-
return columns.reduce((acc, column) => {
|
|
6614
|
-
const def = table.columns[column];
|
|
6615
|
-
if (!def) {
|
|
6616
|
-
throw new Error(missingMsg(column));
|
|
6617
|
-
}
|
|
6618
|
-
acc[column] = def;
|
|
6619
|
-
return acc;
|
|
6620
|
-
}, {});
|
|
6621
|
-
};
|
|
6622
|
-
var filterRow = (row, columns) => {
|
|
6623
|
-
const filtered = {};
|
|
6624
|
-
for (const column of columns) {
|
|
6625
|
-
if (column in row) {
|
|
6626
|
-
filtered[column] = row[column];
|
|
6627
|
-
}
|
|
6628
|
-
}
|
|
6629
|
-
return filtered;
|
|
6630
|
-
};
|
|
6631
|
-
var filterRows = (rows, columns) => rows.map((row) => filterRow(row, columns));
|
|
6632
|
-
var rowsFromResults = (results) => {
|
|
6633
|
-
const rows = [];
|
|
6634
|
-
for (const result of results) {
|
|
6635
|
-
const { columns, values } = result;
|
|
6636
|
-
for (const valueRow of values) {
|
|
6637
|
-
const row = {};
|
|
6638
|
-
columns.forEach((column, idx) => {
|
|
6639
|
-
row[column] = valueRow[idx];
|
|
6640
|
-
});
|
|
6641
|
-
rows.push(row);
|
|
6642
|
-
}
|
|
6643
|
-
}
|
|
6644
|
-
return rows;
|
|
6645
|
-
};
|
|
6646
|
-
var executeQuery = async (ctx, qb) => {
|
|
6647
|
-
const compiled = ctx.dialect.compileSelect(qb.getAST());
|
|
6648
|
-
const results = await ctx.executor.executeSql(compiled.sql, compiled.params);
|
|
6649
|
-
return rowsFromResults(results);
|
|
6650
|
-
};
|
|
6862
|
+
// src/orm/relations/morph-one.ts
|
|
6651
6863
|
var toKey7 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
6652
|
-
var
|
|
6653
|
-
const
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6864
|
+
var hideInternal5 = (obj, keys) => {
|
|
6865
|
+
for (const key of keys) {
|
|
6866
|
+
Object.defineProperty(obj, key, {
|
|
6867
|
+
value: obj[key],
|
|
6868
|
+
writable: false,
|
|
6869
|
+
configurable: false,
|
|
6870
|
+
enumerable: false
|
|
6871
|
+
});
|
|
6659
6872
|
}
|
|
6660
|
-
return collected;
|
|
6661
6873
|
};
|
|
6662
|
-
var
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6874
|
+
var hideWritable5 = (obj, keys) => {
|
|
6875
|
+
for (const key of keys) {
|
|
6876
|
+
const value = obj[key];
|
|
6877
|
+
Object.defineProperty(obj, key, {
|
|
6878
|
+
value,
|
|
6879
|
+
writable: true,
|
|
6880
|
+
configurable: true,
|
|
6881
|
+
enumerable: false
|
|
6882
|
+
});
|
|
6668
6883
|
}
|
|
6669
|
-
return executeQuery(ctx, qb);
|
|
6670
6884
|
};
|
|
6671
|
-
var
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6885
|
+
var DefaultMorphOneReference = class {
|
|
6886
|
+
constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, localKey) {
|
|
6887
|
+
this.ctx = ctx;
|
|
6888
|
+
this.meta = meta;
|
|
6889
|
+
this.root = root;
|
|
6890
|
+
this.relationName = relationName;
|
|
6891
|
+
this.relation = relation;
|
|
6892
|
+
this.rootTable = rootTable;
|
|
6893
|
+
this.loader = loader;
|
|
6894
|
+
this.createEntity = createEntity;
|
|
6895
|
+
this.localKey = localKey;
|
|
6896
|
+
hideInternal5(this, [
|
|
6897
|
+
"ctx",
|
|
6898
|
+
"meta",
|
|
6899
|
+
"root",
|
|
6900
|
+
"relationName",
|
|
6901
|
+
"relation",
|
|
6902
|
+
"rootTable",
|
|
6903
|
+
"loader",
|
|
6904
|
+
"createEntity",
|
|
6905
|
+
"localKey"
|
|
6906
|
+
]);
|
|
6907
|
+
hideWritable5(this, ["loaded", "current"]);
|
|
6908
|
+
this.populateFromHydrationCache();
|
|
6680
6909
|
}
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
const
|
|
6687
|
-
if (
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
lookup.set(key, row);
|
|
6910
|
+
loaded = false;
|
|
6911
|
+
current = null;
|
|
6912
|
+
async load() {
|
|
6913
|
+
if (this.loaded) return this.current;
|
|
6914
|
+
const map = await this.loader();
|
|
6915
|
+
const keyValue = this.root[this.localKey];
|
|
6916
|
+
if (keyValue === void 0 || keyValue === null) {
|
|
6917
|
+
this.loaded = true;
|
|
6918
|
+
return this.current;
|
|
6691
6919
|
}
|
|
6920
|
+
const row = map.get(toKey7(keyValue));
|
|
6921
|
+
this.current = row ? this.createEntity(row) : null;
|
|
6922
|
+
this.loaded = true;
|
|
6923
|
+
return this.current;
|
|
6692
6924
|
}
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
// src/orm/lazy-batch/has-many.ts
|
|
6697
|
-
var loadHasManyRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
6698
|
-
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
6699
|
-
const roots = ctx.getEntitiesForTable(rootTable);
|
|
6700
|
-
const keys = collectKeysFromRoots(roots, localKey);
|
|
6701
|
-
if (!keys.size) {
|
|
6702
|
-
return /* @__PURE__ */ new Map();
|
|
6703
|
-
}
|
|
6704
|
-
const fkColumn = relation.target.columns[relation.foreignKey];
|
|
6705
|
-
if (!fkColumn) return /* @__PURE__ */ new Map();
|
|
6706
|
-
const requestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
6707
|
-
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
6708
|
-
const selectedColumns = requestedColumns ? [...requestedColumns] : Object.keys(relation.target.columns);
|
|
6709
|
-
if (!selectedColumns.includes(targetPrimaryKey)) {
|
|
6710
|
-
selectedColumns.push(targetPrimaryKey);
|
|
6925
|
+
get() {
|
|
6926
|
+
return this.current;
|
|
6711
6927
|
}
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6928
|
+
set(data) {
|
|
6929
|
+
if (data === null) {
|
|
6930
|
+
return this.detachCurrent();
|
|
6931
|
+
}
|
|
6932
|
+
const entity = hasEntityMeta(data) ? data : this.createEntity(data);
|
|
6933
|
+
if (this.current && this.current !== entity) {
|
|
6934
|
+
this.ctx.registerRelationChange(
|
|
6935
|
+
this.root,
|
|
6936
|
+
this.relationKey,
|
|
6937
|
+
this.rootTable,
|
|
6938
|
+
this.relationName,
|
|
6939
|
+
this.relation,
|
|
6940
|
+
{ kind: "remove", entity: this.current }
|
|
6941
|
+
);
|
|
6942
|
+
}
|
|
6943
|
+
this.assignMorphKeys(entity);
|
|
6944
|
+
this.current = entity;
|
|
6945
|
+
this.loaded = true;
|
|
6946
|
+
this.ctx.registerRelationChange(
|
|
6947
|
+
this.root,
|
|
6948
|
+
this.relationKey,
|
|
6949
|
+
this.rootTable,
|
|
6950
|
+
this.relationName,
|
|
6951
|
+
this.relation,
|
|
6952
|
+
{ kind: "attach", entity }
|
|
6953
|
+
);
|
|
6954
|
+
return entity;
|
|
6955
|
+
}
|
|
6956
|
+
toJSON() {
|
|
6957
|
+
if (!this.current) return null;
|
|
6958
|
+
const entityWithToJSON = this.current;
|
|
6959
|
+
return typeof entityWithToJSON.toJSON === "function" ? entityWithToJSON.toJSON() : this.current;
|
|
6960
|
+
}
|
|
6961
|
+
detachCurrent() {
|
|
6962
|
+
const previous = this.current;
|
|
6963
|
+
if (!previous) return null;
|
|
6964
|
+
this.current = null;
|
|
6965
|
+
this.loaded = true;
|
|
6966
|
+
this.ctx.registerRelationChange(
|
|
6967
|
+
this.root,
|
|
6968
|
+
this.relationKey,
|
|
6969
|
+
this.rootTable,
|
|
6970
|
+
this.relationName,
|
|
6971
|
+
this.relation,
|
|
6972
|
+
{ kind: "remove", entity: previous }
|
|
6973
|
+
);
|
|
6974
|
+
return null;
|
|
6975
|
+
}
|
|
6976
|
+
assignMorphKeys(entity) {
|
|
6977
|
+
const keyValue = this.root[this.localKey];
|
|
6978
|
+
entity[this.relation.idField] = keyValue;
|
|
6979
|
+
entity[this.relation.typeField] = this.relation.typeValue;
|
|
6980
|
+
}
|
|
6981
|
+
get relationKey() {
|
|
6982
|
+
return `${this.rootTable.name}.${this.relationName}`;
|
|
6983
|
+
}
|
|
6984
|
+
populateFromHydrationCache() {
|
|
6985
|
+
const keyValue = this.root[this.localKey];
|
|
6986
|
+
if (keyValue === void 0 || keyValue === null) return;
|
|
6987
|
+
const row = getHydrationRecord(this.meta, this.relationName, keyValue);
|
|
6988
|
+
if (!row) return;
|
|
6989
|
+
this.current = this.createEntity(row);
|
|
6990
|
+
this.loaded = true;
|
|
6991
|
+
}
|
|
6992
|
+
};
|
|
6993
|
+
|
|
6994
|
+
// src/orm/relations/morph-many.ts
|
|
6995
|
+
var toKey8 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
6996
|
+
var hideInternal6 = (obj, keys) => {
|
|
6997
|
+
for (const key of keys) {
|
|
6998
|
+
Object.defineProperty(obj, key, {
|
|
6999
|
+
value: obj[key],
|
|
7000
|
+
writable: false,
|
|
7001
|
+
configurable: false,
|
|
7002
|
+
enumerable: false
|
|
7003
|
+
});
|
|
7004
|
+
}
|
|
7005
|
+
};
|
|
7006
|
+
var hideWritable6 = (obj, keys) => {
|
|
7007
|
+
for (const key of keys) {
|
|
7008
|
+
const value = obj[key];
|
|
7009
|
+
Object.defineProperty(obj, key, {
|
|
7010
|
+
value,
|
|
7011
|
+
writable: true,
|
|
7012
|
+
configurable: true,
|
|
7013
|
+
enumerable: false
|
|
7014
|
+
});
|
|
7015
|
+
}
|
|
7016
|
+
};
|
|
7017
|
+
var DefaultMorphManyCollection = class {
|
|
7018
|
+
constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, localKey) {
|
|
7019
|
+
this.ctx = ctx;
|
|
7020
|
+
this.meta = meta;
|
|
7021
|
+
this.root = root;
|
|
7022
|
+
this.relationName = relationName;
|
|
7023
|
+
this.relation = relation;
|
|
7024
|
+
this.rootTable = rootTable;
|
|
7025
|
+
this.loader = loader;
|
|
7026
|
+
this.createEntity = createEntity;
|
|
7027
|
+
this.localKey = localKey;
|
|
7028
|
+
hideInternal6(this, ["ctx", "meta", "root", "relationName", "relation", "rootTable", "loader", "createEntity", "localKey"]);
|
|
7029
|
+
hideWritable6(this, ["loaded", "items", "added", "removed"]);
|
|
7030
|
+
this.hydrateFromCache();
|
|
7031
|
+
}
|
|
7032
|
+
loaded = false;
|
|
7033
|
+
items = [];
|
|
7034
|
+
added = /* @__PURE__ */ new Set();
|
|
7035
|
+
removed = /* @__PURE__ */ new Set();
|
|
7036
|
+
async load() {
|
|
7037
|
+
if (this.loaded) return this.items;
|
|
7038
|
+
const map = await this.loader();
|
|
7039
|
+
const key = toKey8(this.root[this.localKey]);
|
|
7040
|
+
const rows = map.get(key) ?? [];
|
|
7041
|
+
this.items = rows.map((row) => this.createEntity(row));
|
|
7042
|
+
this.loaded = true;
|
|
7043
|
+
return this.items;
|
|
7044
|
+
}
|
|
7045
|
+
getItems() {
|
|
7046
|
+
return this.items;
|
|
7047
|
+
}
|
|
7048
|
+
get length() {
|
|
7049
|
+
return this.items.length;
|
|
7050
|
+
}
|
|
7051
|
+
[Symbol.iterator]() {
|
|
7052
|
+
return this.items[Symbol.iterator]();
|
|
7053
|
+
}
|
|
7054
|
+
add(data) {
|
|
7055
|
+
const keyValue = this.root[this.localKey];
|
|
7056
|
+
const childRow = {
|
|
7057
|
+
...data,
|
|
7058
|
+
[this.relation.idField]: keyValue,
|
|
7059
|
+
[this.relation.typeField]: this.relation.typeValue
|
|
7060
|
+
};
|
|
7061
|
+
const entity = this.createEntity(childRow);
|
|
7062
|
+
this.added.add(entity);
|
|
7063
|
+
this.items.push(entity);
|
|
7064
|
+
this.ctx.registerRelationChange(
|
|
7065
|
+
this.root,
|
|
7066
|
+
this.relationKey,
|
|
7067
|
+
this.rootTable,
|
|
7068
|
+
this.relationName,
|
|
7069
|
+
this.relation,
|
|
7070
|
+
{ kind: "add", entity }
|
|
7071
|
+
);
|
|
7072
|
+
return entity;
|
|
7073
|
+
}
|
|
7074
|
+
attach(entity) {
|
|
7075
|
+
const keyValue = this.root[this.localKey];
|
|
7076
|
+
entity[this.relation.idField] = keyValue;
|
|
7077
|
+
entity[this.relation.typeField] = this.relation.typeValue;
|
|
7078
|
+
this.ctx.markDirty(entity);
|
|
7079
|
+
this.items.push(entity);
|
|
7080
|
+
this.ctx.registerRelationChange(
|
|
7081
|
+
this.root,
|
|
7082
|
+
this.relationKey,
|
|
7083
|
+
this.rootTable,
|
|
7084
|
+
this.relationName,
|
|
7085
|
+
this.relation,
|
|
7086
|
+
{ kind: "attach", entity }
|
|
7087
|
+
);
|
|
7088
|
+
}
|
|
7089
|
+
remove(entity) {
|
|
7090
|
+
this.items = this.items.filter((item) => item !== entity);
|
|
7091
|
+
this.removed.add(entity);
|
|
7092
|
+
this.ctx.registerRelationChange(
|
|
7093
|
+
this.root,
|
|
7094
|
+
this.relationKey,
|
|
7095
|
+
this.rootTable,
|
|
7096
|
+
this.relationName,
|
|
7097
|
+
this.relation,
|
|
7098
|
+
{ kind: "remove", entity }
|
|
7099
|
+
);
|
|
7100
|
+
}
|
|
7101
|
+
clear() {
|
|
7102
|
+
for (const entity of [...this.items]) {
|
|
7103
|
+
this.remove(entity);
|
|
7104
|
+
}
|
|
7105
|
+
}
|
|
7106
|
+
get relationKey() {
|
|
7107
|
+
return `${this.rootTable.name}.${this.relationName}`;
|
|
7108
|
+
}
|
|
7109
|
+
hydrateFromCache() {
|
|
7110
|
+
const keyValue = this.root[this.localKey];
|
|
7111
|
+
if (keyValue === void 0 || keyValue === null) return;
|
|
7112
|
+
const rows = getHydrationRows(this.meta, this.relationName, keyValue);
|
|
7113
|
+
if (!rows?.length) return;
|
|
7114
|
+
this.items = rows.map((row) => this.createEntity(row));
|
|
7115
|
+
this.loaded = true;
|
|
7116
|
+
}
|
|
7117
|
+
toJSON() {
|
|
7118
|
+
return this.items.map((item) => {
|
|
7119
|
+
const entityWithToJSON = item;
|
|
7120
|
+
return typeof entityWithToJSON.toJSON === "function" ? entityWithToJSON.toJSON() : item;
|
|
7121
|
+
});
|
|
7122
|
+
}
|
|
7123
|
+
};
|
|
7124
|
+
|
|
7125
|
+
// src/orm/relations/morph-to.ts
|
|
7126
|
+
var toKey9 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
7127
|
+
var hideInternal7 = (obj, keys) => {
|
|
7128
|
+
for (const key of keys) {
|
|
7129
|
+
Object.defineProperty(obj, key, {
|
|
7130
|
+
value: obj[key],
|
|
7131
|
+
writable: false,
|
|
7132
|
+
configurable: false,
|
|
7133
|
+
enumerable: false
|
|
7134
|
+
});
|
|
7135
|
+
}
|
|
7136
|
+
};
|
|
7137
|
+
var hideWritable7 = (obj, keys) => {
|
|
7138
|
+
for (const key of keys) {
|
|
7139
|
+
const value = obj[key];
|
|
7140
|
+
Object.defineProperty(obj, key, {
|
|
7141
|
+
value,
|
|
7142
|
+
writable: true,
|
|
7143
|
+
configurable: true,
|
|
7144
|
+
enumerable: false
|
|
7145
|
+
});
|
|
7146
|
+
}
|
|
7147
|
+
};
|
|
7148
|
+
var DefaultMorphToReference = class {
|
|
7149
|
+
constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, resolveTargetTable) {
|
|
7150
|
+
this.ctx = ctx;
|
|
7151
|
+
this.meta = meta;
|
|
7152
|
+
this.root = root;
|
|
7153
|
+
this.relationName = relationName;
|
|
7154
|
+
this.relation = relation;
|
|
7155
|
+
this.rootTable = rootTable;
|
|
7156
|
+
this.loader = loader;
|
|
7157
|
+
this.createEntity = createEntity;
|
|
7158
|
+
this.resolveTargetTable = resolveTargetTable;
|
|
7159
|
+
hideInternal7(this, [
|
|
7160
|
+
"ctx",
|
|
7161
|
+
"meta",
|
|
7162
|
+
"root",
|
|
7163
|
+
"relationName",
|
|
7164
|
+
"relation",
|
|
7165
|
+
"rootTable",
|
|
7166
|
+
"loader",
|
|
7167
|
+
"createEntity",
|
|
7168
|
+
"resolveTargetTable"
|
|
7169
|
+
]);
|
|
7170
|
+
hideWritable7(this, ["loaded", "current"]);
|
|
7171
|
+
this.populateFromHydrationCache();
|
|
7172
|
+
}
|
|
7173
|
+
loaded = false;
|
|
7174
|
+
current = null;
|
|
7175
|
+
async load() {
|
|
7176
|
+
if (this.loaded) return this.current;
|
|
7177
|
+
const rootObj = this.root;
|
|
7178
|
+
const typeValue = rootObj[this.relation.typeField];
|
|
7179
|
+
const idValue = rootObj[this.relation.idField];
|
|
7180
|
+
if (!typeValue || idValue === void 0 || idValue === null) {
|
|
7181
|
+
this.loaded = true;
|
|
7182
|
+
return this.current;
|
|
7183
|
+
}
|
|
7184
|
+
const map = await this.loader();
|
|
7185
|
+
const compositeKey = `${toKey9(typeValue)}:${toKey9(idValue)}`;
|
|
7186
|
+
const row = map.get(compositeKey);
|
|
7187
|
+
if (row) {
|
|
7188
|
+
const targetTable = this.resolveTargetTable(toKey9(typeValue));
|
|
7189
|
+
if (targetTable) {
|
|
7190
|
+
this.current = this.createEntity(targetTable, row);
|
|
7191
|
+
}
|
|
7192
|
+
}
|
|
7193
|
+
this.loaded = true;
|
|
7194
|
+
return this.current;
|
|
7195
|
+
}
|
|
7196
|
+
get() {
|
|
7197
|
+
return this.current;
|
|
7198
|
+
}
|
|
7199
|
+
set(data) {
|
|
7200
|
+
if (data === null) {
|
|
7201
|
+
return this.detachCurrent();
|
|
7202
|
+
}
|
|
7203
|
+
const entity = hasEntityMeta(data) ? data : data;
|
|
7204
|
+
if (this.current && this.current !== entity) {
|
|
7205
|
+
this.ctx.registerRelationChange(
|
|
7206
|
+
this.root,
|
|
7207
|
+
this.relationKey,
|
|
7208
|
+
this.rootTable,
|
|
7209
|
+
this.relationName,
|
|
7210
|
+
this.relation,
|
|
7211
|
+
{ kind: "remove", entity: this.current }
|
|
7212
|
+
);
|
|
7213
|
+
}
|
|
7214
|
+
this.current = entity;
|
|
7215
|
+
this.loaded = true;
|
|
7216
|
+
this.ctx.registerRelationChange(
|
|
7217
|
+
this.root,
|
|
7218
|
+
this.relationKey,
|
|
7219
|
+
this.rootTable,
|
|
7220
|
+
this.relationName,
|
|
7221
|
+
this.relation,
|
|
7222
|
+
{ kind: "attach", entity }
|
|
7223
|
+
);
|
|
7224
|
+
return entity;
|
|
7225
|
+
}
|
|
7226
|
+
toJSON() {
|
|
7227
|
+
if (!this.current) return null;
|
|
7228
|
+
const entityWithToJSON = this.current;
|
|
7229
|
+
return typeof entityWithToJSON.toJSON === "function" ? entityWithToJSON.toJSON() : this.current;
|
|
7230
|
+
}
|
|
7231
|
+
detachCurrent() {
|
|
7232
|
+
const previous = this.current;
|
|
7233
|
+
if (!previous) return null;
|
|
7234
|
+
this.current = null;
|
|
7235
|
+
this.loaded = true;
|
|
7236
|
+
const rootObj = this.root;
|
|
7237
|
+
rootObj[this.relation.typeField] = null;
|
|
7238
|
+
rootObj[this.relation.idField] = null;
|
|
7239
|
+
this.ctx.registerRelationChange(
|
|
7240
|
+
this.root,
|
|
7241
|
+
this.relationKey,
|
|
7242
|
+
this.rootTable,
|
|
7243
|
+
this.relationName,
|
|
7244
|
+
this.relation,
|
|
7245
|
+
{ kind: "remove", entity: previous }
|
|
7246
|
+
);
|
|
7247
|
+
return null;
|
|
7248
|
+
}
|
|
7249
|
+
get relationKey() {
|
|
7250
|
+
return `${this.rootTable.name}.${this.relationName}`;
|
|
7251
|
+
}
|
|
7252
|
+
populateFromHydrationCache() {
|
|
7253
|
+
const rootObj = this.root;
|
|
7254
|
+
const typeValue = rootObj[this.relation.typeField];
|
|
7255
|
+
const idValue = rootObj[this.relation.idField];
|
|
7256
|
+
if (!typeValue || idValue === void 0 || idValue === null) return;
|
|
7257
|
+
const compositeKey = `${toKey9(typeValue)}:${toKey9(idValue)}`;
|
|
7258
|
+
const row = getHydrationRecord(this.meta, this.relationName, compositeKey);
|
|
7259
|
+
if (!row) return;
|
|
7260
|
+
const targetTable = this.resolveTargetTable(toKey9(typeValue));
|
|
7261
|
+
if (targetTable) {
|
|
7262
|
+
this.current = this.createEntity(targetTable, row);
|
|
7263
|
+
this.loaded = true;
|
|
7264
|
+
}
|
|
7265
|
+
}
|
|
7266
|
+
};
|
|
7267
|
+
|
|
7268
|
+
// src/orm/lazy-batch/shared.ts
|
|
7269
|
+
var hasColumns = (columns) => Boolean(columns && columns.length > 0);
|
|
7270
|
+
var buildColumnSelection = (table, columns, missingMsg) => {
|
|
7271
|
+
return columns.reduce((acc, column) => {
|
|
7272
|
+
const def = table.columns[column];
|
|
7273
|
+
if (!def) {
|
|
7274
|
+
throw new Error(missingMsg(column));
|
|
7275
|
+
}
|
|
7276
|
+
acc[column] = def;
|
|
7277
|
+
return acc;
|
|
7278
|
+
}, {});
|
|
7279
|
+
};
|
|
7280
|
+
var filterRow = (row, columns) => {
|
|
7281
|
+
const filtered = {};
|
|
7282
|
+
for (const column of columns) {
|
|
7283
|
+
if (column in row) {
|
|
7284
|
+
filtered[column] = row[column];
|
|
7285
|
+
}
|
|
7286
|
+
}
|
|
7287
|
+
return filtered;
|
|
7288
|
+
};
|
|
7289
|
+
var filterRows = (rows, columns) => rows.map((row) => filterRow(row, columns));
|
|
7290
|
+
var rowsFromResults = (results) => {
|
|
7291
|
+
const rows = [];
|
|
7292
|
+
for (const result of results) {
|
|
7293
|
+
const { columns, values } = result;
|
|
7294
|
+
for (const valueRow of values) {
|
|
7295
|
+
const row = {};
|
|
7296
|
+
columns.forEach((column, idx) => {
|
|
7297
|
+
row[column] = valueRow[idx];
|
|
7298
|
+
});
|
|
7299
|
+
rows.push(row);
|
|
7300
|
+
}
|
|
7301
|
+
}
|
|
7302
|
+
return rows;
|
|
7303
|
+
};
|
|
7304
|
+
var executeQuery = async (ctx, qb) => {
|
|
7305
|
+
const compiled = ctx.dialect.compileSelect(qb.getAST());
|
|
7306
|
+
const results = await ctx.executor.executeSql(compiled.sql, compiled.params);
|
|
7307
|
+
return rowsFromResults(results);
|
|
7308
|
+
};
|
|
7309
|
+
var toKey10 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
7310
|
+
var collectKeysFromRoots = (roots, key) => {
|
|
7311
|
+
const collected = /* @__PURE__ */ new Set();
|
|
7312
|
+
for (const tracked of roots) {
|
|
7313
|
+
const value = tracked.entity[key];
|
|
7314
|
+
if (value !== null && value !== void 0) {
|
|
7315
|
+
collected.add(value);
|
|
7316
|
+
}
|
|
7317
|
+
}
|
|
7318
|
+
return collected;
|
|
7319
|
+
};
|
|
7320
|
+
var buildInListValues = (keys) => Array.from(keys);
|
|
7321
|
+
var fetchRowsForKeys = async (ctx, table, column, keys, selection, filter) => {
|
|
7322
|
+
let qb = new SelectQueryBuilder(table).select(selection);
|
|
7323
|
+
qb = qb.where(inList(column, buildInListValues(keys)));
|
|
7324
|
+
if (filter) {
|
|
7325
|
+
qb = qb.where(filter);
|
|
7326
|
+
}
|
|
7327
|
+
return executeQuery(ctx, qb);
|
|
7328
|
+
};
|
|
7329
|
+
var groupRowsByMany = (rows, keyColumn) => {
|
|
7330
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
7331
|
+
for (const row of rows) {
|
|
7332
|
+
const value = row[keyColumn];
|
|
7333
|
+
if (value === null || value === void 0) continue;
|
|
7334
|
+
const key = toKey10(value);
|
|
7335
|
+
const bucket = grouped.get(key) ?? [];
|
|
7336
|
+
bucket.push(row);
|
|
7337
|
+
grouped.set(key, bucket);
|
|
7338
|
+
}
|
|
7339
|
+
return grouped;
|
|
7340
|
+
};
|
|
7341
|
+
var groupRowsByUnique = (rows, keyColumn) => {
|
|
7342
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
7343
|
+
for (const row of rows) {
|
|
7344
|
+
const value = row[keyColumn];
|
|
7345
|
+
if (value === null || value === void 0) continue;
|
|
7346
|
+
const key = toKey10(value);
|
|
7347
|
+
if (!lookup.has(key)) {
|
|
7348
|
+
lookup.set(key, row);
|
|
7349
|
+
}
|
|
7350
|
+
}
|
|
7351
|
+
return lookup;
|
|
7352
|
+
};
|
|
7353
|
+
|
|
7354
|
+
// src/orm/lazy-batch/has-many.ts
|
|
7355
|
+
var loadHasManyRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
7356
|
+
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
7357
|
+
const roots = ctx.getEntitiesForTable(rootTable);
|
|
7358
|
+
const keys = collectKeysFromRoots(roots, localKey);
|
|
7359
|
+
if (!keys.size) {
|
|
7360
|
+
return /* @__PURE__ */ new Map();
|
|
7361
|
+
}
|
|
7362
|
+
const fkColumn = relation.target.columns[relation.foreignKey];
|
|
7363
|
+
if (!fkColumn) return /* @__PURE__ */ new Map();
|
|
7364
|
+
const requestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
7365
|
+
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
7366
|
+
const selectedColumns = requestedColumns ? [...requestedColumns] : Object.keys(relation.target.columns);
|
|
7367
|
+
if (!selectedColumns.includes(targetPrimaryKey)) {
|
|
7368
|
+
selectedColumns.push(targetPrimaryKey);
|
|
7369
|
+
}
|
|
7370
|
+
const queryColumns = new Set(selectedColumns);
|
|
7371
|
+
queryColumns.add(relation.foreignKey);
|
|
7372
|
+
const selection = buildColumnSelection(
|
|
7373
|
+
relation.target,
|
|
7374
|
+
Array.from(queryColumns),
|
|
6717
7375
|
(column) => `Column '${column}' not found on relation '${relationName}'`
|
|
6718
7376
|
);
|
|
6719
7377
|
const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys, selection, options?.filter);
|
|
@@ -6870,12 +7528,12 @@ var loadBelongsToManyRelation = async (ctx, rootTable, relationName, relation, o
|
|
|
6870
7528
|
if (rootValue === null || rootValue === void 0 || targetValue === null || targetValue === void 0) {
|
|
6871
7529
|
continue;
|
|
6872
7530
|
}
|
|
6873
|
-
const bucket = rootLookup.get(
|
|
7531
|
+
const bucket = rootLookup.get(toKey10(rootValue)) ?? [];
|
|
6874
7532
|
bucket.push({
|
|
6875
7533
|
targetId: targetValue,
|
|
6876
7534
|
pivot: pivotVisibleColumns.size ? filterRow(pivot, pivotVisibleColumns) : {}
|
|
6877
7535
|
});
|
|
6878
|
-
rootLookup.set(
|
|
7536
|
+
rootLookup.set(toKey10(rootValue), bucket);
|
|
6879
7537
|
targetIds.add(targetValue);
|
|
6880
7538
|
}
|
|
6881
7539
|
if (!targetIds.size) {
|
|
@@ -6908,7 +7566,7 @@ var loadBelongsToManyRelation = async (ctx, rootTable, relationName, relation, o
|
|
|
6908
7566
|
for (const [rootId, entries] of rootLookup.entries()) {
|
|
6909
7567
|
const bucket = [];
|
|
6910
7568
|
for (const entry of entries) {
|
|
6911
|
-
const targetRow = targetMap.get(
|
|
7569
|
+
const targetRow = targetMap.get(toKey10(entry.targetId));
|
|
6912
7570
|
if (!targetRow) continue;
|
|
6913
7571
|
const row = targetRequestedColumns ? filterRow(targetRow, targetVisibleColumns) : { ...targetRow };
|
|
6914
7572
|
if (options?.pivot?.merge) {
|
|
@@ -6927,6 +7585,123 @@ var mergePivotIntoRow = (row, pivot) => {
|
|
|
6927
7585
|
}
|
|
6928
7586
|
};
|
|
6929
7587
|
|
|
7588
|
+
// src/orm/lazy-batch/morph-one.ts
|
|
7589
|
+
var loadMorphOneRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
7590
|
+
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
7591
|
+
const roots = ctx.getEntitiesForTable(rootTable);
|
|
7592
|
+
const keys = collectKeysFromRoots(roots, localKey);
|
|
7593
|
+
if (!keys.size) {
|
|
7594
|
+
return /* @__PURE__ */ new Map();
|
|
7595
|
+
}
|
|
7596
|
+
const fkColumn = relation.target.columns[relation.idField];
|
|
7597
|
+
if (!fkColumn) return /* @__PURE__ */ new Map();
|
|
7598
|
+
const requestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
7599
|
+
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
7600
|
+
const selectedColumns = requestedColumns ? [...requestedColumns] : Object.keys(relation.target.columns);
|
|
7601
|
+
if (!selectedColumns.includes(targetPrimaryKey)) {
|
|
7602
|
+
selectedColumns.push(targetPrimaryKey);
|
|
7603
|
+
}
|
|
7604
|
+
const queryColumns = new Set(selectedColumns);
|
|
7605
|
+
queryColumns.add(relation.idField);
|
|
7606
|
+
const selection = buildColumnSelection(
|
|
7607
|
+
relation.target,
|
|
7608
|
+
Array.from(queryColumns),
|
|
7609
|
+
(column) => `Column '${column}' not found on relation '${relationName}'`
|
|
7610
|
+
);
|
|
7611
|
+
const typeColumn = relation.target.columns[relation.typeField];
|
|
7612
|
+
const discriminatorFilter = eq(
|
|
7613
|
+
typeColumn ?? { type: "Column", table: relation.target.name, name: relation.typeField },
|
|
7614
|
+
{ type: "Literal", value: relation.typeValue }
|
|
7615
|
+
);
|
|
7616
|
+
const combinedFilter = options?.filter ? and(options.filter, discriminatorFilter) : discriminatorFilter;
|
|
7617
|
+
const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys, selection, combinedFilter);
|
|
7618
|
+
const grouped = groupRowsByUnique(rows, relation.idField);
|
|
7619
|
+
if (!requestedColumns) return grouped;
|
|
7620
|
+
const visibleColumns = new Set(selectedColumns);
|
|
7621
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
7622
|
+
for (const [key, row] of grouped.entries()) {
|
|
7623
|
+
filtered.set(key, filterRow(row, visibleColumns));
|
|
7624
|
+
}
|
|
7625
|
+
return filtered;
|
|
7626
|
+
};
|
|
7627
|
+
|
|
7628
|
+
// src/orm/lazy-batch/morph-many.ts
|
|
7629
|
+
var loadMorphManyRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
7630
|
+
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
7631
|
+
const roots = ctx.getEntitiesForTable(rootTable);
|
|
7632
|
+
const keys = collectKeysFromRoots(roots, localKey);
|
|
7633
|
+
if (!keys.size) {
|
|
7634
|
+
return /* @__PURE__ */ new Map();
|
|
7635
|
+
}
|
|
7636
|
+
const fkColumn = relation.target.columns[relation.idField];
|
|
7637
|
+
if (!fkColumn) return /* @__PURE__ */ new Map();
|
|
7638
|
+
const requestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
7639
|
+
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
7640
|
+
const selectedColumns = requestedColumns ? [...requestedColumns] : Object.keys(relation.target.columns);
|
|
7641
|
+
if (!selectedColumns.includes(targetPrimaryKey)) {
|
|
7642
|
+
selectedColumns.push(targetPrimaryKey);
|
|
7643
|
+
}
|
|
7644
|
+
const queryColumns = new Set(selectedColumns);
|
|
7645
|
+
queryColumns.add(relation.idField);
|
|
7646
|
+
const selection = buildColumnSelection(
|
|
7647
|
+
relation.target,
|
|
7648
|
+
Array.from(queryColumns),
|
|
7649
|
+
(column) => `Column '${column}' not found on relation '${relationName}'`
|
|
7650
|
+
);
|
|
7651
|
+
const typeColumn = relation.target.columns[relation.typeField];
|
|
7652
|
+
const discriminatorFilter = eq(
|
|
7653
|
+
typeColumn ?? { type: "Column", table: relation.target.name, name: relation.typeField },
|
|
7654
|
+
{ type: "Literal", value: relation.typeValue }
|
|
7655
|
+
);
|
|
7656
|
+
const combinedFilter = options?.filter ? and(options.filter, discriminatorFilter) : discriminatorFilter;
|
|
7657
|
+
const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys, selection, combinedFilter);
|
|
7658
|
+
const grouped = groupRowsByMany(rows, relation.idField);
|
|
7659
|
+
if (!requestedColumns) return grouped;
|
|
7660
|
+
const visibleColumns = new Set(selectedColumns);
|
|
7661
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
7662
|
+
for (const [key, bucket] of grouped.entries()) {
|
|
7663
|
+
filtered.set(key, filterRows(bucket, visibleColumns));
|
|
7664
|
+
}
|
|
7665
|
+
return filtered;
|
|
7666
|
+
};
|
|
7667
|
+
|
|
7668
|
+
// src/orm/lazy-batch/morph-to.ts
|
|
7669
|
+
var loadMorphToRelation = async (ctx, rootTable, _relationName, relation) => {
|
|
7670
|
+
const roots = ctx.getEntitiesForTable(rootTable);
|
|
7671
|
+
const result = /* @__PURE__ */ new Map();
|
|
7672
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
7673
|
+
for (const tracked of roots) {
|
|
7674
|
+
const entity = tracked.entity;
|
|
7675
|
+
const typeValue = entity[relation.typeField];
|
|
7676
|
+
const idValue = entity[relation.idField];
|
|
7677
|
+
if (!typeValue || idValue === void 0 || idValue === null) continue;
|
|
7678
|
+
const typeKey = toKey10(typeValue);
|
|
7679
|
+
const ids = grouped.get(typeKey) ?? /* @__PURE__ */ new Set();
|
|
7680
|
+
ids.add(idValue);
|
|
7681
|
+
grouped.set(typeKey, ids);
|
|
7682
|
+
}
|
|
7683
|
+
for (const [typeKey, ids] of grouped.entries()) {
|
|
7684
|
+
const targetTable = relation.targets[typeKey];
|
|
7685
|
+
if (!targetTable) continue;
|
|
7686
|
+
const targetPk = relation.targetKey || findPrimaryKey(targetTable);
|
|
7687
|
+
const pkColumn = targetTable.columns[targetPk];
|
|
7688
|
+
if (!pkColumn) continue;
|
|
7689
|
+
const selection = buildColumnSelection(
|
|
7690
|
+
targetTable,
|
|
7691
|
+
Object.keys(targetTable.columns),
|
|
7692
|
+
(column) => `Column '${column}' not found on target '${targetTable.name}'`
|
|
7693
|
+
);
|
|
7694
|
+
const rows = await fetchRowsForKeys(ctx, targetTable, pkColumn, ids, selection);
|
|
7695
|
+
for (const row of rows) {
|
|
7696
|
+
const pkValue = row[targetPk];
|
|
7697
|
+
if (pkValue === void 0 || pkValue === null) continue;
|
|
7698
|
+
const compositeKey = `${typeKey}:${toKey10(pkValue)}`;
|
|
7699
|
+
result.set(compositeKey, row);
|
|
7700
|
+
}
|
|
7701
|
+
}
|
|
7702
|
+
return result;
|
|
7703
|
+
};
|
|
7704
|
+
|
|
6930
7705
|
// src/orm/entity-relation-cache.ts
|
|
6931
7706
|
var relationLoaderCache = (meta, relationName, factory) => {
|
|
6932
7707
|
if (meta.relationCache.has(relationName)) {
|
|
@@ -7031,65 +7806,119 @@ var instantiateWrapper = (meta, relationName, relation, owner, createEntity) =>
|
|
|
7031
7806
|
metaBase,
|
|
7032
7807
|
owner,
|
|
7033
7808
|
relationName,
|
|
7034
|
-
hasOne2,
|
|
7809
|
+
hasOne2,
|
|
7810
|
+
meta.table,
|
|
7811
|
+
loader,
|
|
7812
|
+
(row) => createEntity(hasOne2.target, row),
|
|
7813
|
+
localKey
|
|
7814
|
+
);
|
|
7815
|
+
}
|
|
7816
|
+
case RelationKinds.HasMany: {
|
|
7817
|
+
const hasMany2 = relation;
|
|
7818
|
+
const localKey = hasMany2.localKey || findPrimaryKey(meta.table);
|
|
7819
|
+
const loader = () => loadCached(
|
|
7820
|
+
() => loadHasManyRelation(meta.ctx, meta.table, relationName, hasMany2, resolveOptions())
|
|
7821
|
+
);
|
|
7822
|
+
return new DefaultHasManyCollection(
|
|
7823
|
+
meta.ctx,
|
|
7824
|
+
metaBase,
|
|
7825
|
+
owner,
|
|
7826
|
+
relationName,
|
|
7827
|
+
hasMany2,
|
|
7828
|
+
meta.table,
|
|
7829
|
+
loader,
|
|
7830
|
+
(row) => createEntity(relation.target, row),
|
|
7831
|
+
localKey
|
|
7832
|
+
);
|
|
7833
|
+
}
|
|
7834
|
+
case RelationKinds.BelongsTo: {
|
|
7835
|
+
const belongsTo2 = relation;
|
|
7836
|
+
const targetKey = belongsTo2.localKey || findPrimaryKey(belongsTo2.target);
|
|
7837
|
+
const loader = () => loadCached(
|
|
7838
|
+
() => loadBelongsToRelation(meta.ctx, meta.table, relationName, belongsTo2, resolveOptions())
|
|
7839
|
+
);
|
|
7840
|
+
return new DefaultBelongsToReference(
|
|
7841
|
+
meta.ctx,
|
|
7842
|
+
metaBase,
|
|
7843
|
+
owner,
|
|
7844
|
+
relationName,
|
|
7845
|
+
belongsTo2,
|
|
7846
|
+
meta.table,
|
|
7847
|
+
loader,
|
|
7848
|
+
(row) => createEntity(relation.target, row),
|
|
7849
|
+
targetKey
|
|
7850
|
+
);
|
|
7851
|
+
}
|
|
7852
|
+
case RelationKinds.BelongsToMany: {
|
|
7853
|
+
const many = relation;
|
|
7854
|
+
const localKey = many.localKey || findPrimaryKey(meta.table);
|
|
7855
|
+
const loader = () => loadCached(
|
|
7856
|
+
() => loadBelongsToManyRelation(meta.ctx, meta.table, relationName, many, resolveOptions())
|
|
7857
|
+
);
|
|
7858
|
+
return new DefaultManyToManyCollection(
|
|
7859
|
+
meta.ctx,
|
|
7860
|
+
metaBase,
|
|
7861
|
+
owner,
|
|
7862
|
+
relationName,
|
|
7863
|
+
many,
|
|
7035
7864
|
meta.table,
|
|
7036
7865
|
loader,
|
|
7037
|
-
(row) => createEntity(
|
|
7866
|
+
(row) => createEntity(relation.target, row),
|
|
7038
7867
|
localKey
|
|
7039
7868
|
);
|
|
7040
7869
|
}
|
|
7041
|
-
case RelationKinds.
|
|
7042
|
-
const
|
|
7043
|
-
const localKey =
|
|
7870
|
+
case RelationKinds.MorphOne: {
|
|
7871
|
+
const morphOne2 = relation;
|
|
7872
|
+
const localKey = morphOne2.localKey || findPrimaryKey(meta.table);
|
|
7044
7873
|
const loader = () => loadCached(
|
|
7045
|
-
() =>
|
|
7874
|
+
() => loadMorphOneRelation(meta.ctx, meta.table, relationName, morphOne2, resolveOptions())
|
|
7046
7875
|
);
|
|
7047
|
-
return new
|
|
7876
|
+
return new DefaultMorphOneReference(
|
|
7048
7877
|
meta.ctx,
|
|
7049
7878
|
metaBase,
|
|
7050
7879
|
owner,
|
|
7051
7880
|
relationName,
|
|
7052
|
-
|
|
7881
|
+
morphOne2,
|
|
7053
7882
|
meta.table,
|
|
7054
7883
|
loader,
|
|
7055
|
-
(row) => createEntity(
|
|
7884
|
+
(row) => createEntity(morphOne2.target, row),
|
|
7056
7885
|
localKey
|
|
7057
7886
|
);
|
|
7058
7887
|
}
|
|
7059
|
-
case RelationKinds.
|
|
7060
|
-
const
|
|
7061
|
-
const
|
|
7888
|
+
case RelationKinds.MorphMany: {
|
|
7889
|
+
const morphMany2 = relation;
|
|
7890
|
+
const localKey = morphMany2.localKey || findPrimaryKey(meta.table);
|
|
7062
7891
|
const loader = () => loadCached(
|
|
7063
|
-
() =>
|
|
7892
|
+
() => loadMorphManyRelation(meta.ctx, meta.table, relationName, morphMany2, resolveOptions())
|
|
7064
7893
|
);
|
|
7065
|
-
return new
|
|
7894
|
+
return new DefaultMorphManyCollection(
|
|
7066
7895
|
meta.ctx,
|
|
7067
7896
|
metaBase,
|
|
7068
7897
|
owner,
|
|
7069
7898
|
relationName,
|
|
7070
|
-
|
|
7899
|
+
morphMany2,
|
|
7071
7900
|
meta.table,
|
|
7072
7901
|
loader,
|
|
7073
|
-
(row) => createEntity(
|
|
7074
|
-
|
|
7902
|
+
(row) => createEntity(morphMany2.target, row),
|
|
7903
|
+
localKey
|
|
7075
7904
|
);
|
|
7076
7905
|
}
|
|
7077
|
-
case RelationKinds.
|
|
7078
|
-
const
|
|
7079
|
-
const localKey = many.localKey || findPrimaryKey(meta.table);
|
|
7906
|
+
case RelationKinds.MorphTo: {
|
|
7907
|
+
const morphTo2 = relation;
|
|
7080
7908
|
const loader = () => loadCached(
|
|
7081
|
-
() =>
|
|
7909
|
+
() => loadMorphToRelation(meta.ctx, meta.table, relationName, morphTo2)
|
|
7082
7910
|
);
|
|
7083
|
-
|
|
7911
|
+
const resolveTargetTable = (typeValue) => morphTo2.targets[typeValue];
|
|
7912
|
+
return new DefaultMorphToReference(
|
|
7084
7913
|
meta.ctx,
|
|
7085
7914
|
metaBase,
|
|
7086
7915
|
owner,
|
|
7087
7916
|
relationName,
|
|
7088
|
-
|
|
7917
|
+
morphTo2,
|
|
7089
7918
|
meta.table,
|
|
7090
7919
|
loader,
|
|
7091
|
-
(row) => createEntity(
|
|
7092
|
-
|
|
7920
|
+
(table, row) => createEntity(table, row),
|
|
7921
|
+
resolveTargetTable
|
|
7093
7922
|
);
|
|
7094
7923
|
}
|
|
7095
7924
|
default:
|
|
@@ -7117,7 +7946,7 @@ var createEntityProxy = (ctx, table, row, lazyRelations = [], lazyRelationOption
|
|
|
7117
7946
|
const isCollectionRelation = (relationName) => {
|
|
7118
7947
|
const rel = table.relations[relationName];
|
|
7119
7948
|
if (!rel) return false;
|
|
7120
|
-
return rel.type === RelationKinds.HasMany || rel.type === RelationKinds.BelongsToMany;
|
|
7949
|
+
return rel.type === RelationKinds.HasMany || rel.type === RelationKinds.BelongsToMany || rel.type === RelationKinds.MorphMany;
|
|
7121
7950
|
};
|
|
7122
7951
|
const buildJson = (self, options) => {
|
|
7123
7952
|
const json = {};
|
|
@@ -7299,9 +8128,11 @@ function rowsToQueryResult(rows) {
|
|
|
7299
8128
|
}
|
|
7300
8129
|
function createExecutorFromQueryRunner(runner) {
|
|
7301
8130
|
const supportsTransactions = typeof runner.beginTransaction === "function" && typeof runner.commitTransaction === "function" && typeof runner.rollbackTransaction === "function";
|
|
8131
|
+
const supportsSavepoints = supportsTransactions && typeof runner.savepoint === "function" && typeof runner.releaseSavepoint === "function" && typeof runner.rollbackToSavepoint === "function";
|
|
7302
8132
|
return {
|
|
7303
8133
|
capabilities: {
|
|
7304
|
-
transactions: supportsTransactions
|
|
8134
|
+
transactions: supportsTransactions,
|
|
8135
|
+
...supportsSavepoints ? { savepoints: true } : {}
|
|
7305
8136
|
},
|
|
7306
8137
|
async executeSql(sql, params) {
|
|
7307
8138
|
const rows = await runner.query(sql, params);
|
|
@@ -7326,6 +8157,24 @@ function createExecutorFromQueryRunner(runner) {
|
|
|
7326
8157
|
}
|
|
7327
8158
|
await runner.rollbackTransaction.call(runner);
|
|
7328
8159
|
},
|
|
8160
|
+
async savepoint(name) {
|
|
8161
|
+
if (!supportsSavepoints) {
|
|
8162
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
8163
|
+
}
|
|
8164
|
+
await runner.savepoint.call(runner, name);
|
|
8165
|
+
},
|
|
8166
|
+
async releaseSavepoint(name) {
|
|
8167
|
+
if (!supportsSavepoints) {
|
|
8168
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
8169
|
+
}
|
|
8170
|
+
await runner.releaseSavepoint.call(runner, name);
|
|
8171
|
+
},
|
|
8172
|
+
async rollbackToSavepoint(name) {
|
|
8173
|
+
if (!supportsSavepoints) {
|
|
8174
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
8175
|
+
}
|
|
8176
|
+
await runner.rollbackToSavepoint.call(runner, name);
|
|
8177
|
+
},
|
|
7329
8178
|
async dispose() {
|
|
7330
8179
|
await runner.dispose?.call(runner);
|
|
7331
8180
|
}
|
|
@@ -7700,6 +8549,9 @@ function buildWhereHasPredicate(env, context, relationFacet, createChildBuilder,
|
|
|
7700
8549
|
}
|
|
7701
8550
|
const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
|
|
7702
8551
|
const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
|
|
8552
|
+
if (!isSingleTargetRelation(relation)) {
|
|
8553
|
+
throw new Error(`Polymorphic relation '${relationName}' does not support whereHas/whereHasNot`);
|
|
8554
|
+
}
|
|
7703
8555
|
let subQb = createChildBuilder(relation.target);
|
|
7704
8556
|
if (callback) {
|
|
7705
8557
|
subQb = callback(subQb);
|
|
@@ -9286,6 +10138,7 @@ var isTableDef = (value) => {
|
|
|
9286
10138
|
|
|
9287
10139
|
// src/decorators/decorator-metadata.ts
|
|
9288
10140
|
var METADATA_KEY = "metal-orm:decorators";
|
|
10141
|
+
var LEGACY_METADATA_KEY = /* @__PURE__ */ Symbol.for("metal-orm:decorators:legacy");
|
|
9289
10142
|
var getOrCreateMetadataBag = (context) => {
|
|
9290
10143
|
const metadata = context.metadata || (context.metadata = {});
|
|
9291
10144
|
let bag = metadata[METADATA_KEY];
|
|
@@ -9295,16 +10148,65 @@ var getOrCreateMetadataBag = (context) => {
|
|
|
9295
10148
|
}
|
|
9296
10149
|
return bag;
|
|
9297
10150
|
};
|
|
10151
|
+
var getOrCreateMetadataBagOnConstructor = (ctor) => {
|
|
10152
|
+
const carrier = ctor;
|
|
10153
|
+
let bag = carrier[LEGACY_METADATA_KEY];
|
|
10154
|
+
if (!bag) {
|
|
10155
|
+
bag = { columns: [], relations: [], transformers: [] };
|
|
10156
|
+
carrier[LEGACY_METADATA_KEY] = bag;
|
|
10157
|
+
}
|
|
10158
|
+
return bag;
|
|
10159
|
+
};
|
|
9298
10160
|
var readMetadataBag = (context) => {
|
|
9299
10161
|
return context.metadata?.[METADATA_KEY];
|
|
9300
10162
|
};
|
|
9301
10163
|
var readMetadataBagFromConstructor = (ctor) => {
|
|
9302
10164
|
const metadataSymbol = Symbol.metadata;
|
|
9303
|
-
if (
|
|
9304
|
-
|
|
9305
|
-
|
|
10165
|
+
if (metadataSymbol) {
|
|
10166
|
+
const metadata = Reflect.get(ctor, metadataSymbol);
|
|
10167
|
+
const stage3Bag = metadata?.[METADATA_KEY];
|
|
10168
|
+
if (stage3Bag) {
|
|
10169
|
+
return stage3Bag;
|
|
10170
|
+
}
|
|
10171
|
+
}
|
|
10172
|
+
return ctor[LEGACY_METADATA_KEY];
|
|
9306
10173
|
};
|
|
9307
10174
|
var getDecoratorMetadata = (ctor) => readMetadataBagFromConstructor(ctor);
|
|
10175
|
+
var normalizePropertyName = (name) => {
|
|
10176
|
+
if (typeof name === "symbol") {
|
|
10177
|
+
return name.description ?? name.toString();
|
|
10178
|
+
}
|
|
10179
|
+
return name;
|
|
10180
|
+
};
|
|
10181
|
+
var isStage3FieldContext = (value) => {
|
|
10182
|
+
return typeof value === "object" && value !== null && "name" in value && "private" in value && "metadata" in value;
|
|
10183
|
+
};
|
|
10184
|
+
var resolveFieldDecoratorInfo = (targetOrValue, contextOrProperty, decoratorName) => {
|
|
10185
|
+
if (isStage3FieldContext(contextOrProperty)) {
|
|
10186
|
+
if (!contextOrProperty.name) {
|
|
10187
|
+
throw new Error(`${decoratorName} decorator requires a property name`);
|
|
10188
|
+
}
|
|
10189
|
+
if (contextOrProperty.private) {
|
|
10190
|
+
throw new Error(`${decoratorName} decorator does not support private fields`);
|
|
10191
|
+
}
|
|
10192
|
+
return {
|
|
10193
|
+
propertyName: normalizePropertyName(contextOrProperty.name),
|
|
10194
|
+
bag: getOrCreateMetadataBag(contextOrProperty)
|
|
10195
|
+
};
|
|
10196
|
+
}
|
|
10197
|
+
if (typeof contextOrProperty === "string" || typeof contextOrProperty === "symbol") {
|
|
10198
|
+
const legacyTarget = targetOrValue;
|
|
10199
|
+
const ctor = typeof legacyTarget === "function" ? legacyTarget : legacyTarget?.constructor;
|
|
10200
|
+
if (!ctor || typeof ctor !== "function" && typeof ctor !== "object") {
|
|
10201
|
+
throw new Error(`${decoratorName} decorator requires a class field target`);
|
|
10202
|
+
}
|
|
10203
|
+
return {
|
|
10204
|
+
propertyName: normalizePropertyName(contextOrProperty),
|
|
10205
|
+
bag: getOrCreateMetadataBagOnConstructor(ctor)
|
|
10206
|
+
};
|
|
10207
|
+
}
|
|
10208
|
+
throw new Error(`${decoratorName} decorator received an unsupported decorator context`);
|
|
10209
|
+
};
|
|
9308
10210
|
|
|
9309
10211
|
// src/decorators/bootstrap.ts
|
|
9310
10212
|
var unwrapTarget = (target) => {
|
|
@@ -9394,6 +10296,48 @@ var buildRelationDefinitions = (meta, tableMap) => {
|
|
|
9394
10296
|
);
|
|
9395
10297
|
break;
|
|
9396
10298
|
}
|
|
10299
|
+
case RelationKinds.MorphOne: {
|
|
10300
|
+
relations[name] = morphOne(
|
|
10301
|
+
resolveTableTarget(relation.target, tableMap),
|
|
10302
|
+
{
|
|
10303
|
+
as: relation.morphName,
|
|
10304
|
+
typeValue: relation.typeValue,
|
|
10305
|
+
typeField: relation.typeField,
|
|
10306
|
+
idField: relation.idField,
|
|
10307
|
+
localKey: relation.localKey,
|
|
10308
|
+
cascade: relation.cascade
|
|
10309
|
+
}
|
|
10310
|
+
);
|
|
10311
|
+
break;
|
|
10312
|
+
}
|
|
10313
|
+
case RelationKinds.MorphMany: {
|
|
10314
|
+
relations[name] = morphMany(
|
|
10315
|
+
resolveTableTarget(relation.target, tableMap),
|
|
10316
|
+
{
|
|
10317
|
+
as: relation.morphName,
|
|
10318
|
+
typeValue: relation.typeValue,
|
|
10319
|
+
typeField: relation.typeField,
|
|
10320
|
+
idField: relation.idField,
|
|
10321
|
+
localKey: relation.localKey,
|
|
10322
|
+
cascade: relation.cascade
|
|
10323
|
+
}
|
|
10324
|
+
);
|
|
10325
|
+
break;
|
|
10326
|
+
}
|
|
10327
|
+
case RelationKinds.MorphTo: {
|
|
10328
|
+
const resolvedTargets = {};
|
|
10329
|
+
for (const [typeValue, targetResolver] of Object.entries(relation.targets)) {
|
|
10330
|
+
resolvedTargets[typeValue] = resolveTableTarget(targetResolver, tableMap);
|
|
10331
|
+
}
|
|
10332
|
+
relations[name] = morphTo({
|
|
10333
|
+
typeField: relation.typeField,
|
|
10334
|
+
idField: relation.idField,
|
|
10335
|
+
targets: resolvedTargets,
|
|
10336
|
+
targetKey: relation.targetKey,
|
|
10337
|
+
cascade: relation.cascade
|
|
10338
|
+
});
|
|
10339
|
+
break;
|
|
10340
|
+
}
|
|
9397
10341
|
}
|
|
9398
10342
|
}
|
|
9399
10343
|
return relations;
|
|
@@ -9467,6 +10411,45 @@ var resolveSingleRelation = (relationName, relation, rootMeta) => {
|
|
|
9467
10411
|
}
|
|
9468
10412
|
);
|
|
9469
10413
|
}
|
|
10414
|
+
case RelationKinds.MorphOne: {
|
|
10415
|
+
return morphOne(
|
|
10416
|
+
resolveTableTarget(relation.target, tableMap),
|
|
10417
|
+
{
|
|
10418
|
+
as: relation.morphName,
|
|
10419
|
+
typeValue: relation.typeValue,
|
|
10420
|
+
typeField: relation.typeField,
|
|
10421
|
+
idField: relation.idField,
|
|
10422
|
+
localKey: relation.localKey,
|
|
10423
|
+
cascade: relation.cascade
|
|
10424
|
+
}
|
|
10425
|
+
);
|
|
10426
|
+
}
|
|
10427
|
+
case RelationKinds.MorphMany: {
|
|
10428
|
+
return morphMany(
|
|
10429
|
+
resolveTableTarget(relation.target, tableMap),
|
|
10430
|
+
{
|
|
10431
|
+
as: relation.morphName,
|
|
10432
|
+
typeValue: relation.typeValue,
|
|
10433
|
+
typeField: relation.typeField,
|
|
10434
|
+
idField: relation.idField,
|
|
10435
|
+
localKey: relation.localKey,
|
|
10436
|
+
cascade: relation.cascade
|
|
10437
|
+
}
|
|
10438
|
+
);
|
|
10439
|
+
}
|
|
10440
|
+
case RelationKinds.MorphTo: {
|
|
10441
|
+
const resolvedTargets = {};
|
|
10442
|
+
for (const [typeValue, targetResolver] of Object.entries(relation.targets)) {
|
|
10443
|
+
resolvedTargets[typeValue] = resolveTableTarget(targetResolver, tableMap);
|
|
10444
|
+
}
|
|
10445
|
+
return morphTo({
|
|
10446
|
+
typeField: relation.typeField,
|
|
10447
|
+
idField: relation.idField,
|
|
10448
|
+
targets: resolvedTargets,
|
|
10449
|
+
targetKey: relation.targetKey,
|
|
10450
|
+
cascade: relation.cascade
|
|
10451
|
+
});
|
|
10452
|
+
}
|
|
9470
10453
|
default:
|
|
9471
10454
|
throw new Error(`Unknown relation kind for relation '${relationName}'`);
|
|
9472
10455
|
}
|
|
@@ -11370,6 +12353,25 @@ var databaseFunction = {
|
|
|
11370
12353
|
fn: "DATABASE",
|
|
11371
12354
|
args: []
|
|
11372
12355
|
};
|
|
12356
|
+
var readMysqlField = (row, field) => {
|
|
12357
|
+
const record = row;
|
|
12358
|
+
if (Object.prototype.hasOwnProperty.call(record, field)) {
|
|
12359
|
+
return record[field];
|
|
12360
|
+
}
|
|
12361
|
+
const lower2 = field.toLowerCase();
|
|
12362
|
+
if (lower2 !== field && Object.prototype.hasOwnProperty.call(record, lower2)) {
|
|
12363
|
+
return record[lower2];
|
|
12364
|
+
}
|
|
12365
|
+
const upper2 = field.toUpperCase();
|
|
12366
|
+
if (upper2 !== field && Object.prototype.hasOwnProperty.call(record, upper2)) {
|
|
12367
|
+
return record[upper2];
|
|
12368
|
+
}
|
|
12369
|
+
return void 0;
|
|
12370
|
+
};
|
|
12371
|
+
var readMysqlStringField = (row, field) => {
|
|
12372
|
+
const value = readMysqlField(row, field);
|
|
12373
|
+
return typeof value === "string" ? value : void 0;
|
|
12374
|
+
};
|
|
11373
12375
|
var mysqlIntrospector = {
|
|
11374
12376
|
async introspect(ctx, options) {
|
|
11375
12377
|
const schema = options.schema;
|
|
@@ -11511,39 +12513,68 @@ var mysqlIntrospector = {
|
|
|
11511
12513
|
const indexRows = await runSelectNode(indexQuery, ctx);
|
|
11512
12514
|
const tableComments = /* @__PURE__ */ new Map();
|
|
11513
12515
|
tableRows.forEach((r) => {
|
|
11514
|
-
const
|
|
11515
|
-
|
|
11516
|
-
|
|
12516
|
+
const tableSchema = readMysqlStringField(r, "table_schema");
|
|
12517
|
+
const tableName = readMysqlStringField(r, "table_name");
|
|
12518
|
+
const tableComment = readMysqlStringField(r, "table_comment");
|
|
12519
|
+
if (!tableSchema || !tableName) return;
|
|
12520
|
+
const key = `${tableSchema}.${tableName}`;
|
|
12521
|
+
if (tableComment) {
|
|
12522
|
+
tableComments.set(key, tableComment);
|
|
11517
12523
|
}
|
|
11518
12524
|
});
|
|
11519
12525
|
const pkMap = /* @__PURE__ */ new Map();
|
|
11520
12526
|
pkRows.forEach((r) => {
|
|
11521
|
-
const
|
|
12527
|
+
const tableSchema = readMysqlStringField(r, "table_schema");
|
|
12528
|
+
const tableName = readMysqlStringField(r, "table_name");
|
|
12529
|
+
const columnName = readMysqlStringField(r, "column_name");
|
|
12530
|
+
if (!tableSchema || !tableName || !columnName) return;
|
|
12531
|
+
const key = `${tableSchema}.${tableName}`;
|
|
11522
12532
|
const list = pkMap.get(key) || [];
|
|
11523
|
-
list.push(
|
|
12533
|
+
list.push(columnName);
|
|
11524
12534
|
pkMap.set(key, list);
|
|
11525
12535
|
});
|
|
11526
12536
|
const fkMap = /* @__PURE__ */ new Map();
|
|
11527
12537
|
fkRows.forEach((r) => {
|
|
11528
|
-
const
|
|
12538
|
+
const tableSchema = readMysqlStringField(r, "table_schema");
|
|
12539
|
+
const tableName = readMysqlStringField(r, "table_name");
|
|
12540
|
+
const columnName = readMysqlStringField(r, "column_name");
|
|
12541
|
+
const constraintName = readMysqlStringField(r, "constraint_name");
|
|
12542
|
+
const referencedTableSchema = readMysqlStringField(r, "referenced_table_schema");
|
|
12543
|
+
const referencedTableName = readMysqlStringField(r, "referenced_table_name");
|
|
12544
|
+
const referencedColumnName = readMysqlStringField(r, "referenced_column_name");
|
|
12545
|
+
const deleteRule = readMysqlStringField(r, "delete_rule");
|
|
12546
|
+
const updateRule = readMysqlStringField(r, "update_rule");
|
|
12547
|
+
if (!tableSchema || !tableName || !columnName || !constraintName || !referencedTableSchema || !referencedTableName || !referencedColumnName) {
|
|
12548
|
+
return;
|
|
12549
|
+
}
|
|
12550
|
+
const key = `${tableSchema}.${tableName}.${columnName}`;
|
|
11529
12551
|
const list = fkMap.get(key) || [];
|
|
11530
12552
|
list.push({
|
|
11531
|
-
table: `${
|
|
11532
|
-
column:
|
|
11533
|
-
onDelete:
|
|
11534
|
-
onUpdate:
|
|
11535
|
-
name:
|
|
12553
|
+
table: `${referencedTableSchema}.${referencedTableName}`,
|
|
12554
|
+
column: referencedColumnName,
|
|
12555
|
+
onDelete: deleteRule,
|
|
12556
|
+
onUpdate: updateRule,
|
|
12557
|
+
name: constraintName
|
|
11536
12558
|
});
|
|
11537
12559
|
fkMap.set(key, list);
|
|
11538
12560
|
});
|
|
11539
12561
|
const tablesByKey = /* @__PURE__ */ new Map();
|
|
11540
12562
|
columnRows.forEach((r) => {
|
|
11541
|
-
const
|
|
11542
|
-
|
|
12563
|
+
const tableSchema = readMysqlStringField(r, "table_schema");
|
|
12564
|
+
const tableName = readMysqlStringField(r, "table_name");
|
|
12565
|
+
const columnName = readMysqlStringField(r, "column_name");
|
|
12566
|
+
const columnType = readMysqlStringField(r, "column_type") || readMysqlStringField(r, "data_type");
|
|
12567
|
+
const isNullable = readMysqlStringField(r, "is_nullable");
|
|
12568
|
+
const columnDefault = readMysqlField(r, "column_default");
|
|
12569
|
+
const extra = readMysqlStringField(r, "extra");
|
|
12570
|
+
const columnComment = readMysqlStringField(r, "column_comment");
|
|
12571
|
+
if (!tableSchema || !tableName || !columnName || !columnType || !isNullable) return;
|
|
12572
|
+
const key = `${tableSchema}.${tableName}`;
|
|
12573
|
+
if (!shouldIncludeTable(tableName, options)) return;
|
|
11543
12574
|
if (!tablesByKey.has(key)) {
|
|
11544
12575
|
tablesByKey.set(key, {
|
|
11545
|
-
name:
|
|
11546
|
-
schema:
|
|
12576
|
+
name: tableName,
|
|
12577
|
+
schema: tableSchema,
|
|
11547
12578
|
columns: [],
|
|
11548
12579
|
primaryKey: pkMap.get(key) || [],
|
|
11549
12580
|
indexes: [],
|
|
@@ -11551,17 +12582,16 @@ var mysqlIntrospector = {
|
|
|
11551
12582
|
});
|
|
11552
12583
|
}
|
|
11553
12584
|
const table = tablesByKey.get(key);
|
|
11554
|
-
const
|
|
11555
|
-
const comment = r.column_comment?.trim() ? r.column_comment : void 0;
|
|
12585
|
+
const comment = columnComment?.trim() ? columnComment : void 0;
|
|
11556
12586
|
const column = {
|
|
11557
|
-
name:
|
|
12587
|
+
name: columnName,
|
|
11558
12588
|
type: columnType,
|
|
11559
|
-
notNull:
|
|
11560
|
-
default:
|
|
11561
|
-
autoIncrement: typeof
|
|
12589
|
+
notNull: isNullable === "NO",
|
|
12590
|
+
default: columnDefault ?? void 0,
|
|
12591
|
+
autoIncrement: typeof extra === "string" && extra.includes("auto_increment"),
|
|
11562
12592
|
comment
|
|
11563
12593
|
};
|
|
11564
|
-
const fk = fkMap.get(`${key}.${
|
|
12594
|
+
const fk = fkMap.get(`${key}.${columnName}`)?.[0];
|
|
11565
12595
|
if (fk) {
|
|
11566
12596
|
column.references = {
|
|
11567
12597
|
table: fk.table,
|
|
@@ -11574,14 +12604,20 @@ var mysqlIntrospector = {
|
|
|
11574
12604
|
table.columns.push(column);
|
|
11575
12605
|
});
|
|
11576
12606
|
indexRows.forEach((r) => {
|
|
11577
|
-
const
|
|
12607
|
+
const tableSchema = readMysqlStringField(r, "table_schema");
|
|
12608
|
+
const tableName = readMysqlStringField(r, "table_name");
|
|
12609
|
+
const indexName = readMysqlStringField(r, "index_name");
|
|
12610
|
+
const nonUnique = readMysqlField(r, "non_unique");
|
|
12611
|
+
const colsValue = readMysqlField(r, "cols");
|
|
12612
|
+
if (!tableSchema || !tableName || !indexName) return;
|
|
12613
|
+
const key = `${tableSchema}.${tableName}`;
|
|
11578
12614
|
const table = tablesByKey.get(key);
|
|
11579
12615
|
if (!table) return;
|
|
11580
|
-
const cols = (typeof
|
|
12616
|
+
const cols = (typeof colsValue === "string" ? colsValue.split(",") : []).map((c) => ({ column: c.trim() }));
|
|
11581
12617
|
const idx = {
|
|
11582
|
-
name:
|
|
12618
|
+
name: indexName,
|
|
11583
12619
|
columns: cols,
|
|
11584
|
-
unique:
|
|
12620
|
+
unique: Number(nonUnique) === 0
|
|
11585
12621
|
};
|
|
11586
12622
|
table.indexes = table.indexes || [];
|
|
11587
12623
|
table.indexes.push(idx);
|
|
@@ -11643,25 +12679,35 @@ var mysqlIntrospector = {
|
|
|
11643
12679
|
const viewColumnRows = await runSelectNode(viewColumnsQuery, ctx);
|
|
11644
12680
|
const viewsByKey = /* @__PURE__ */ new Map();
|
|
11645
12681
|
for (const r of viewRows) {
|
|
11646
|
-
|
|
11647
|
-
const
|
|
12682
|
+
const tableSchema = readMysqlStringField(r, "table_schema");
|
|
12683
|
+
const tableName = readMysqlStringField(r, "table_name");
|
|
12684
|
+
const viewDefinition = readMysqlStringField(r, "view_definition");
|
|
12685
|
+
if (!tableSchema || !tableName) continue;
|
|
12686
|
+
if (!shouldIncludeView(tableName, options)) continue;
|
|
12687
|
+
const key = `${tableSchema}.${tableName}`;
|
|
11648
12688
|
viewsByKey.set(key, {
|
|
11649
|
-
name:
|
|
11650
|
-
schema:
|
|
12689
|
+
name: tableName,
|
|
12690
|
+
schema: tableSchema,
|
|
11651
12691
|
columns: [],
|
|
11652
|
-
definition:
|
|
12692
|
+
definition: viewDefinition || void 0
|
|
11653
12693
|
});
|
|
11654
12694
|
}
|
|
11655
12695
|
for (const r of viewColumnRows) {
|
|
11656
|
-
const
|
|
12696
|
+
const tableSchema = readMysqlStringField(r, "table_schema");
|
|
12697
|
+
const tableName = readMysqlStringField(r, "table_name");
|
|
12698
|
+
const columnName = readMysqlStringField(r, "column_name");
|
|
12699
|
+
const columnType = readMysqlStringField(r, "column_type") || readMysqlStringField(r, "data_type");
|
|
12700
|
+
const isNullable = readMysqlStringField(r, "is_nullable");
|
|
12701
|
+
const columnComment = readMysqlStringField(r, "column_comment");
|
|
12702
|
+
if (!tableSchema || !tableName || !columnName || !columnType || !isNullable) continue;
|
|
12703
|
+
const key = `${tableSchema}.${tableName}`;
|
|
11657
12704
|
const view = viewsByKey.get(key);
|
|
11658
12705
|
if (!view) continue;
|
|
11659
|
-
const columnType = r.column_type || r.data_type;
|
|
11660
12706
|
const column = {
|
|
11661
|
-
name:
|
|
12707
|
+
name: columnName,
|
|
11662
12708
|
type: columnType,
|
|
11663
|
-
notNull:
|
|
11664
|
-
comment:
|
|
12709
|
+
notNull: isNullable === "NO",
|
|
12710
|
+
comment: columnComment?.trim() || void 0
|
|
11665
12711
|
};
|
|
11666
12712
|
view.columns.push(column);
|
|
11667
12713
|
}
|
|
@@ -13056,6 +14102,9 @@ var TypeScriptGenerator = class {
|
|
|
13056
14102
|
visitLogicalExpression(logical) {
|
|
13057
14103
|
return this.printLogicalExpression(logical);
|
|
13058
14104
|
}
|
|
14105
|
+
visitNotExpression(notExpr) {
|
|
14106
|
+
return this.printNotExpression(notExpr);
|
|
14107
|
+
}
|
|
13059
14108
|
visitNullExpression(nullExpr) {
|
|
13060
14109
|
return this.printNullExpression(nullExpr);
|
|
13061
14110
|
}
|
|
@@ -13131,6 +14180,9 @@ var TypeScriptGenerator = class {
|
|
|
13131
14180
|
${parts.join(",\n ")}
|
|
13132
14181
|
)`;
|
|
13133
14182
|
}
|
|
14183
|
+
printNotExpression(notExpr) {
|
|
14184
|
+
return `not(${this.printExpression(notExpr.operand)})`;
|
|
14185
|
+
}
|
|
13134
14186
|
printArithmeticExpression(expr) {
|
|
13135
14187
|
const left2 = this.printOperand(expr.left);
|
|
13136
14188
|
const right2 = this.printOperand(expr.right);
|
|
@@ -13824,6 +14876,15 @@ var RelationChangeProcessor = class {
|
|
|
13824
14876
|
case RelationKinds.BelongsTo:
|
|
13825
14877
|
await this.handleBelongsToChange(entry);
|
|
13826
14878
|
break;
|
|
14879
|
+
case RelationKinds.MorphOne:
|
|
14880
|
+
await this.handleMorphOneChange(entry);
|
|
14881
|
+
break;
|
|
14882
|
+
case RelationKinds.MorphMany:
|
|
14883
|
+
await this.handleMorphManyChange(entry);
|
|
14884
|
+
break;
|
|
14885
|
+
case RelationKinds.MorphTo:
|
|
14886
|
+
await this.handleMorphToChange(entry);
|
|
14887
|
+
break;
|
|
13827
14888
|
}
|
|
13828
14889
|
}
|
|
13829
14890
|
}
|
|
@@ -14026,6 +15087,86 @@ var RelationChangeProcessor = class {
|
|
|
14026
15087
|
}
|
|
14027
15088
|
return Object.keys(payload).length ? payload : void 0;
|
|
14028
15089
|
}
|
|
15090
|
+
async handleMorphOneChange(entry) {
|
|
15091
|
+
const relation = entry.relation;
|
|
15092
|
+
const target = entry.change.entity;
|
|
15093
|
+
if (!target) return;
|
|
15094
|
+
const tracked = this.unitOfWork.findTracked(target);
|
|
15095
|
+
if (!tracked) return;
|
|
15096
|
+
const localKey = relation.localKey || findPrimaryKey(entry.rootTable);
|
|
15097
|
+
const rootValue = entry.root[localKey];
|
|
15098
|
+
if (rootValue === void 0 || rootValue === null) return;
|
|
15099
|
+
if (entry.change.kind === "add" || entry.change.kind === "attach") {
|
|
15100
|
+
const child = tracked.entity;
|
|
15101
|
+
child[relation.idField] = rootValue;
|
|
15102
|
+
child[relation.typeField] = relation.typeValue;
|
|
15103
|
+
this.unitOfWork.markDirty(tracked.entity);
|
|
15104
|
+
return;
|
|
15105
|
+
}
|
|
15106
|
+
if (entry.change.kind === "remove") {
|
|
15107
|
+
const child = tracked.entity;
|
|
15108
|
+
if (relation.cascade === "all" || relation.cascade === "remove") {
|
|
15109
|
+
this.unitOfWork.markRemoved(child);
|
|
15110
|
+
return;
|
|
15111
|
+
}
|
|
15112
|
+
child[relation.idField] = null;
|
|
15113
|
+
child[relation.typeField] = null;
|
|
15114
|
+
this.unitOfWork.markDirty(child);
|
|
15115
|
+
}
|
|
15116
|
+
}
|
|
15117
|
+
async handleMorphManyChange(entry) {
|
|
15118
|
+
const relation = entry.relation;
|
|
15119
|
+
const target = entry.change.entity;
|
|
15120
|
+
if (!target) return;
|
|
15121
|
+
const tracked = this.unitOfWork.findTracked(target);
|
|
15122
|
+
if (!tracked) return;
|
|
15123
|
+
const localKey = relation.localKey || findPrimaryKey(entry.rootTable);
|
|
15124
|
+
const rootValue = entry.root[localKey];
|
|
15125
|
+
if (rootValue === void 0 || rootValue === null) return;
|
|
15126
|
+
if (entry.change.kind === "add" || entry.change.kind === "attach") {
|
|
15127
|
+
const child = tracked.entity;
|
|
15128
|
+
child[relation.idField] = rootValue;
|
|
15129
|
+
child[relation.typeField] = relation.typeValue;
|
|
15130
|
+
this.unitOfWork.markDirty(tracked.entity);
|
|
15131
|
+
return;
|
|
15132
|
+
}
|
|
15133
|
+
if (entry.change.kind === "remove") {
|
|
15134
|
+
const child = tracked.entity;
|
|
15135
|
+
if (relation.cascade === "all" || relation.cascade === "remove") {
|
|
15136
|
+
this.unitOfWork.markRemoved(child);
|
|
15137
|
+
return;
|
|
15138
|
+
}
|
|
15139
|
+
child[relation.idField] = null;
|
|
15140
|
+
child[relation.typeField] = null;
|
|
15141
|
+
this.unitOfWork.markDirty(child);
|
|
15142
|
+
}
|
|
15143
|
+
}
|
|
15144
|
+
async handleMorphToChange(entry) {
|
|
15145
|
+
const relation = entry.relation;
|
|
15146
|
+
const target = entry.change.entity;
|
|
15147
|
+
if (!target) return;
|
|
15148
|
+
if (entry.change.kind === "attach" || entry.change.kind === "add") {
|
|
15149
|
+
const targetEntity = target;
|
|
15150
|
+
for (const [typeValue, targetTable] of Object.entries(relation.targets)) {
|
|
15151
|
+
const targetPk = relation.targetKey || findPrimaryKey(targetTable);
|
|
15152
|
+
const pkValue = targetEntity[targetPk];
|
|
15153
|
+
if (pkValue !== void 0 && pkValue !== null) {
|
|
15154
|
+
const rootEntity = entry.root;
|
|
15155
|
+
rootEntity[relation.typeField] = typeValue;
|
|
15156
|
+
rootEntity[relation.idField] = pkValue;
|
|
15157
|
+
this.unitOfWork.markDirty(entry.root);
|
|
15158
|
+
break;
|
|
15159
|
+
}
|
|
15160
|
+
}
|
|
15161
|
+
return;
|
|
15162
|
+
}
|
|
15163
|
+
if (entry.change.kind === "remove") {
|
|
15164
|
+
const rootEntity = entry.root;
|
|
15165
|
+
rootEntity[relation.typeField] = null;
|
|
15166
|
+
rootEntity[relation.idField] = null;
|
|
15167
|
+
this.unitOfWork.markDirty(entry.root);
|
|
15168
|
+
}
|
|
15169
|
+
}
|
|
14029
15170
|
};
|
|
14030
15171
|
|
|
14031
15172
|
// src/orm/query-logger.ts
|
|
@@ -14042,6 +15183,9 @@ var createQueryLoggingExecutor = (executor, logger) => {
|
|
|
14042
15183
|
beginTransaction: () => executor.beginTransaction(),
|
|
14043
15184
|
commitTransaction: () => executor.commitTransaction(),
|
|
14044
15185
|
rollbackTransaction: () => executor.rollbackTransaction(),
|
|
15186
|
+
savepoint: executor.savepoint ? (name) => executor.savepoint(name) : void 0,
|
|
15187
|
+
releaseSavepoint: executor.releaseSavepoint ? (name) => executor.releaseSavepoint(name) : void 0,
|
|
15188
|
+
rollbackToSavepoint: executor.rollbackToSavepoint ? (name) => executor.rollbackToSavepoint(name) : void 0,
|
|
14045
15189
|
dispose: () => executor.dispose()
|
|
14046
15190
|
};
|
|
14047
15191
|
return wrapped;
|
|
@@ -14064,7 +15208,7 @@ var runInTransaction = async (executor, action) => {
|
|
|
14064
15208
|
};
|
|
14065
15209
|
|
|
14066
15210
|
// src/orm/save-graph.ts
|
|
14067
|
-
var
|
|
15211
|
+
var toKey11 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
14068
15212
|
var coerceColumnValue = (table, columnName, value, options) => {
|
|
14069
15213
|
if (value === null || value === void 0) return value;
|
|
14070
15214
|
const column = table.columns[columnName];
|
|
@@ -14126,11 +15270,11 @@ var isEntityInCollection = (items, pkName, entity) => {
|
|
|
14126
15270
|
if (items.includes(entity)) return true;
|
|
14127
15271
|
const entityPk = entity[pkName];
|
|
14128
15272
|
if (entityPk === void 0 || entityPk === null) return false;
|
|
14129
|
-
return items.some((item) =>
|
|
15273
|
+
return items.some((item) => toKey11(item[pkName]) === toKey11(entityPk));
|
|
14130
15274
|
};
|
|
14131
15275
|
var findInCollectionByPk = (items, pkName, pkValue) => {
|
|
14132
15276
|
if (pkValue === void 0 || pkValue === null) return void 0;
|
|
14133
|
-
return items.find((item) =>
|
|
15277
|
+
return items.find((item) => toKey11(item[pkName]) === toKey11(pkValue));
|
|
14134
15278
|
};
|
|
14135
15279
|
var extractPivotPayload = (payload) => {
|
|
14136
15280
|
const pivot = payload._pivot ?? payload.pivot;
|
|
@@ -14159,13 +15303,13 @@ var handleHasMany = async (session, root, relationName, relation, payload, optio
|
|
|
14159
15303
|
collection.attach(entity);
|
|
14160
15304
|
}
|
|
14161
15305
|
if (pkValue !== void 0 && pkValue !== null) {
|
|
14162
|
-
seen.add(
|
|
15306
|
+
seen.add(toKey11(pkValue));
|
|
14163
15307
|
}
|
|
14164
15308
|
}
|
|
14165
15309
|
if (options.pruneMissing) {
|
|
14166
15310
|
for (const item of [...collection.getItems()]) {
|
|
14167
15311
|
const pkValue = item[targetPk];
|
|
14168
|
-
if (pkValue !== void 0 && pkValue !== null && !seen.has(
|
|
15312
|
+
if (pkValue !== void 0 && pkValue !== null && !seen.has(toKey11(pkValue))) {
|
|
14169
15313
|
collection.remove(item);
|
|
14170
15314
|
}
|
|
14171
15315
|
}
|
|
@@ -14223,7 +15367,7 @@ var handleBelongsToMany = async (session, root, relationName, relation, payload,
|
|
|
14223
15367
|
if (typeof item === "number" || typeof item === "string") {
|
|
14224
15368
|
const id = item;
|
|
14225
15369
|
collection.attach(id);
|
|
14226
|
-
seen.add(
|
|
15370
|
+
seen.add(toKey11(id));
|
|
14227
15371
|
continue;
|
|
14228
15372
|
}
|
|
14229
15373
|
const asObj = item;
|
|
@@ -14241,18 +15385,89 @@ var handleBelongsToMany = async (session, root, relationName, relation, payload,
|
|
|
14241
15385
|
collection.attach(entity, pivotPayload);
|
|
14242
15386
|
}
|
|
14243
15387
|
if (pkValue !== void 0 && pkValue !== null) {
|
|
14244
|
-
seen.add(
|
|
15388
|
+
seen.add(toKey11(pkValue));
|
|
14245
15389
|
}
|
|
14246
15390
|
}
|
|
14247
15391
|
if (options.pruneMissing) {
|
|
14248
15392
|
for (const item of [...collection.getItems()]) {
|
|
14249
15393
|
const pkValue = item[targetPk];
|
|
14250
|
-
if (pkValue !== void 0 && pkValue !== null && !seen.has(
|
|
15394
|
+
if (pkValue !== void 0 && pkValue !== null && !seen.has(toKey11(pkValue))) {
|
|
14251
15395
|
collection.detach(item);
|
|
14252
15396
|
}
|
|
14253
15397
|
}
|
|
14254
15398
|
}
|
|
14255
15399
|
};
|
|
15400
|
+
var handleMorphOne = async (session, root, relationName, relation, payload, options) => {
|
|
15401
|
+
const ref = root[relationName];
|
|
15402
|
+
if (payload === void 0) return;
|
|
15403
|
+
if (payload === null) {
|
|
15404
|
+
ref.set(null);
|
|
15405
|
+
return;
|
|
15406
|
+
}
|
|
15407
|
+
const pk = findPrimaryKey(relation.target);
|
|
15408
|
+
if (typeof payload === "number" || typeof payload === "string") {
|
|
15409
|
+
const entity = ref.set({ [pk]: payload });
|
|
15410
|
+
if (entity) {
|
|
15411
|
+
await applyGraphToEntity(session, relation.target, entity, { [pk]: payload }, options);
|
|
15412
|
+
}
|
|
15413
|
+
return;
|
|
15414
|
+
}
|
|
15415
|
+
const attached = ref.set(payload);
|
|
15416
|
+
if (attached) {
|
|
15417
|
+
await applyGraphToEntity(session, relation.target, attached, payload, options);
|
|
15418
|
+
}
|
|
15419
|
+
};
|
|
15420
|
+
var handleMorphMany = async (session, root, relationName, relation, payload, options) => {
|
|
15421
|
+
if (!Array.isArray(payload)) return;
|
|
15422
|
+
const collection = root[relationName];
|
|
15423
|
+
await collection.load();
|
|
15424
|
+
const targetTable = relation.target;
|
|
15425
|
+
const targetPk = findPrimaryKey(targetTable);
|
|
15426
|
+
const existing = collection.getItems();
|
|
15427
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15428
|
+
for (const item of payload) {
|
|
15429
|
+
if (item === null || item === void 0) continue;
|
|
15430
|
+
const asObj = typeof item === "object" ? item : { [targetPk]: item };
|
|
15431
|
+
const pkValue = asObj[targetPk];
|
|
15432
|
+
const current = findInCollectionByPk(existing, targetPk, pkValue) ?? (pkValue !== void 0 && pkValue !== null ? session.getEntity(targetTable, pkValue) : void 0);
|
|
15433
|
+
const entity = current ?? ensureEntity(session, targetTable, asObj, options);
|
|
15434
|
+
assignColumns(targetTable, entity, asObj, options);
|
|
15435
|
+
await applyGraphToEntity(session, targetTable, entity, asObj, options);
|
|
15436
|
+
if (!isEntityInCollection(collection.getItems(), targetPk, entity)) {
|
|
15437
|
+
collection.attach(entity);
|
|
15438
|
+
}
|
|
15439
|
+
if (pkValue !== void 0 && pkValue !== null) {
|
|
15440
|
+
seen.add(toKey11(pkValue));
|
|
15441
|
+
}
|
|
15442
|
+
}
|
|
15443
|
+
if (options.pruneMissing) {
|
|
15444
|
+
for (const item of [...collection.getItems()]) {
|
|
15445
|
+
const pkValue = item[targetPk];
|
|
15446
|
+
if (pkValue !== void 0 && pkValue !== null && !seen.has(toKey11(pkValue))) {
|
|
15447
|
+
collection.remove(item);
|
|
15448
|
+
}
|
|
15449
|
+
}
|
|
15450
|
+
}
|
|
15451
|
+
};
|
|
15452
|
+
var handleMorphTo = async (session, root, relationName, relation, payload, options) => {
|
|
15453
|
+
const ref = root[relationName];
|
|
15454
|
+
if (payload === void 0) return;
|
|
15455
|
+
if (payload === null) {
|
|
15456
|
+
ref.set(null);
|
|
15457
|
+
return;
|
|
15458
|
+
}
|
|
15459
|
+
const attached = ref.set(payload);
|
|
15460
|
+
if (attached) {
|
|
15461
|
+
for (const [, targetTable] of Object.entries(relation.targets)) {
|
|
15462
|
+
const pk = relation.targetKey || findPrimaryKey(targetTable);
|
|
15463
|
+
const pkValue = attached[pk];
|
|
15464
|
+
if (pkValue !== void 0 && pkValue !== null) {
|
|
15465
|
+
await applyGraphToEntity(session, targetTable, attached, payload, options);
|
|
15466
|
+
break;
|
|
15467
|
+
}
|
|
15468
|
+
}
|
|
15469
|
+
}
|
|
15470
|
+
};
|
|
14256
15471
|
var applyRelation = async (session, table, entity, relationName, relation, payload, options) => {
|
|
14257
15472
|
switch (relation.type) {
|
|
14258
15473
|
case RelationKinds.HasMany:
|
|
@@ -14263,6 +15478,12 @@ var applyRelation = async (session, table, entity, relationName, relation, paylo
|
|
|
14263
15478
|
return handleBelongsTo(session, entity, relationName, relation, payload, options);
|
|
14264
15479
|
case RelationKinds.BelongsToMany:
|
|
14265
15480
|
return handleBelongsToMany(session, entity, relationName, relation, payload, options);
|
|
15481
|
+
case RelationKinds.MorphOne:
|
|
15482
|
+
return handleMorphOne(session, entity, relationName, relation, payload, options);
|
|
15483
|
+
case RelationKinds.MorphMany:
|
|
15484
|
+
return handleMorphMany(session, entity, relationName, relation, payload, options);
|
|
15485
|
+
case RelationKinds.MorphTo:
|
|
15486
|
+
return handleMorphTo(session, entity, relationName, relation, payload, options);
|
|
14266
15487
|
}
|
|
14267
15488
|
};
|
|
14268
15489
|
var applyGraphToEntity = async (session, table, entity, payload, options) => {
|
|
@@ -14291,6 +15512,8 @@ var patchGraphInternal = async (session, entityClass, existing, payload, options
|
|
|
14291
15512
|
};
|
|
14292
15513
|
|
|
14293
15514
|
// src/orm/orm-session.ts
|
|
15515
|
+
var NESTED_TRANSACTIONS_REQUIRE_SAVEPOINTS = "Nested session.transaction calls require savepoint support in this executor";
|
|
15516
|
+
var ROLLBACK_ONLY_TRANSACTION = "Cannot commit transaction because an inner transaction failed";
|
|
14294
15517
|
var OrmSession = class {
|
|
14295
15518
|
/** The ORM instance */
|
|
14296
15519
|
orm;
|
|
@@ -14310,6 +15533,9 @@ var OrmSession = class {
|
|
|
14310
15533
|
tenantId;
|
|
14311
15534
|
interceptors;
|
|
14312
15535
|
saveGraphDefaults;
|
|
15536
|
+
transactionDepth = 0;
|
|
15537
|
+
savepointCounter = 0;
|
|
15538
|
+
rollbackOnly = false;
|
|
14313
15539
|
/**
|
|
14314
15540
|
* Creates a new OrmSession instance.
|
|
14315
15541
|
* @param opts - Session options
|
|
@@ -14652,16 +15878,43 @@ var OrmSession = class {
|
|
|
14652
15878
|
await this.commit();
|
|
14653
15879
|
return result;
|
|
14654
15880
|
}
|
|
14655
|
-
|
|
15881
|
+
const isOutermost = this.transactionDepth === 0;
|
|
15882
|
+
let savepointName = null;
|
|
15883
|
+
if (isOutermost) {
|
|
15884
|
+
this.rollbackOnly = false;
|
|
15885
|
+
await this.executor.beginTransaction();
|
|
15886
|
+
} else {
|
|
15887
|
+
this.assertSavepointSupport();
|
|
15888
|
+
savepointName = this.nextSavepointName();
|
|
15889
|
+
await this.executor.savepoint(savepointName);
|
|
15890
|
+
}
|
|
15891
|
+
this.transactionDepth += 1;
|
|
14656
15892
|
try {
|
|
14657
15893
|
const result = await fn8(this);
|
|
15894
|
+
this.throwIfRollbackOnly();
|
|
14658
15895
|
await this.flushWithHooks();
|
|
14659
|
-
|
|
14660
|
-
|
|
15896
|
+
this.throwIfRollbackOnly();
|
|
15897
|
+
if (isOutermost) {
|
|
15898
|
+
await this.executor.commitTransaction();
|
|
15899
|
+
await this.domainEvents.dispatch(this.unitOfWork.getTracked(), this);
|
|
15900
|
+
} else {
|
|
15901
|
+
await this.executor.releaseSavepoint(savepointName);
|
|
15902
|
+
}
|
|
14661
15903
|
return result;
|
|
14662
15904
|
} catch (err) {
|
|
14663
|
-
|
|
15905
|
+
if (isOutermost) {
|
|
15906
|
+
await this.rollback();
|
|
15907
|
+
} else {
|
|
15908
|
+
this.rollbackOnly = true;
|
|
15909
|
+
await this.executor.rollbackToSavepoint(savepointName);
|
|
15910
|
+
}
|
|
14664
15911
|
throw err;
|
|
15912
|
+
} finally {
|
|
15913
|
+
this.transactionDepth = Math.max(0, this.transactionDepth - 1);
|
|
15914
|
+
if (this.transactionDepth === 0) {
|
|
15915
|
+
this.rollbackOnly = false;
|
|
15916
|
+
this.savepointCounter = 0;
|
|
15917
|
+
}
|
|
14665
15918
|
}
|
|
14666
15919
|
}
|
|
14667
15920
|
/**
|
|
@@ -14671,6 +15924,9 @@ var OrmSession = class {
|
|
|
14671
15924
|
if (this.executor.capabilities.transactions) {
|
|
14672
15925
|
await this.executor.rollbackTransaction();
|
|
14673
15926
|
}
|
|
15927
|
+
this.transactionDepth = 0;
|
|
15928
|
+
this.savepointCounter = 0;
|
|
15929
|
+
this.rollbackOnly = false;
|
|
14674
15930
|
this.unitOfWork.reset();
|
|
14675
15931
|
this.relationChanges.reset();
|
|
14676
15932
|
}
|
|
@@ -14745,6 +16001,23 @@ var OrmSession = class {
|
|
|
14745
16001
|
resolveSaveGraphOptions(options) {
|
|
14746
16002
|
return { ...this.saveGraphDefaults ?? {}, ...options ?? {} };
|
|
14747
16003
|
}
|
|
16004
|
+
assertSavepointSupport() {
|
|
16005
|
+
if (!this.executor.capabilities.savepoints) {
|
|
16006
|
+
throw new Error(NESTED_TRANSACTIONS_REQUIRE_SAVEPOINTS);
|
|
16007
|
+
}
|
|
16008
|
+
if (typeof this.executor.savepoint !== "function" || typeof this.executor.releaseSavepoint !== "function" || typeof this.executor.rollbackToSavepoint !== "function") {
|
|
16009
|
+
throw new Error(NESTED_TRANSACTIONS_REQUIRE_SAVEPOINTS);
|
|
16010
|
+
}
|
|
16011
|
+
}
|
|
16012
|
+
nextSavepointName() {
|
|
16013
|
+
this.savepointCounter += 1;
|
|
16014
|
+
return `metalorm_sp_${this.savepointCounter}`;
|
|
16015
|
+
}
|
|
16016
|
+
throwIfRollbackOnly() {
|
|
16017
|
+
if (this.rollbackOnly) {
|
|
16018
|
+
throw new Error(ROLLBACK_ONLY_TRANSACTION);
|
|
16019
|
+
}
|
|
16020
|
+
}
|
|
14748
16021
|
};
|
|
14749
16022
|
var buildRelationChangeEntry = (root, relationKey, rootTable, relationName, relation, change) => ({
|
|
14750
16023
|
root,
|
|
@@ -15269,7 +16542,7 @@ var TREE_METADATA_KEY = /* @__PURE__ */ Symbol("metal-orm:tree");
|
|
|
15269
16542
|
function Tree(options = {}) {
|
|
15270
16543
|
return function(target, context) {
|
|
15271
16544
|
const config = resolveTreeConfig(options);
|
|
15272
|
-
const metadataBag = readMetadataBag(context) ?? readMetadataBagFromConstructor(target);
|
|
16545
|
+
const metadataBag = context ? readMetadataBag(context) ?? readMetadataBagFromConstructor(target) : readMetadataBagFromConstructor(target);
|
|
15273
16546
|
const metadata = {
|
|
15274
16547
|
config,
|
|
15275
16548
|
parentProperty: metadataBag?.tree?.parentProperty,
|
|
@@ -15281,28 +16554,22 @@ function Tree(options = {}) {
|
|
|
15281
16554
|
};
|
|
15282
16555
|
}
|
|
15283
16556
|
function TreeParent() {
|
|
15284
|
-
return function(
|
|
15285
|
-
|
|
15286
|
-
|
|
15287
|
-
|
|
15288
|
-
|
|
15289
|
-
|
|
15290
|
-
}
|
|
15291
|
-
const propertyName = String(context.name);
|
|
15292
|
-
const bag = getOrCreateMetadataBag(context);
|
|
16557
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16558
|
+
const { propertyName, bag } = resolveFieldDecoratorInfo(
|
|
16559
|
+
targetOrValue,
|
|
16560
|
+
contextOrProperty,
|
|
16561
|
+
"TreeParent"
|
|
16562
|
+
);
|
|
15293
16563
|
bag.tree = { ...bag.tree, parentProperty: propertyName };
|
|
15294
16564
|
};
|
|
15295
16565
|
}
|
|
15296
16566
|
function TreeChildren() {
|
|
15297
|
-
return function(
|
|
15298
|
-
|
|
15299
|
-
|
|
15300
|
-
|
|
15301
|
-
|
|
15302
|
-
|
|
15303
|
-
}
|
|
15304
|
-
const propertyName = String(context.name);
|
|
15305
|
-
const bag = getOrCreateMetadataBag(context);
|
|
16567
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16568
|
+
const { propertyName, bag } = resolveFieldDecoratorInfo(
|
|
16569
|
+
targetOrValue,
|
|
16570
|
+
contextOrProperty,
|
|
16571
|
+
"TreeChildren"
|
|
16572
|
+
);
|
|
15306
16573
|
bag.tree = { ...bag.tree, childrenProperty: propertyName };
|
|
15307
16574
|
};
|
|
15308
16575
|
}
|
|
@@ -15466,7 +16733,7 @@ function Entity(options = {}) {
|
|
|
15466
16733
|
const ctor = value;
|
|
15467
16734
|
const tableName = options.tableName ?? deriveTableNameFromConstructor(ctor);
|
|
15468
16735
|
setEntityTableName(ctor, tableName, options.hooks, options.type);
|
|
15469
|
-
const bag = readMetadataBag(context);
|
|
16736
|
+
const bag = context ? readMetadataBag(context) : readMetadataBagFromConstructor(ctor);
|
|
15470
16737
|
if (bag) {
|
|
15471
16738
|
const meta = ensureEntityMetadata(ctor);
|
|
15472
16739
|
for (const entry of bag.columns) {
|
|
@@ -15520,29 +16787,20 @@ var normalizeColumnInput = (input) => {
|
|
|
15520
16787
|
}
|
|
15521
16788
|
return column;
|
|
15522
16789
|
};
|
|
15523
|
-
var
|
|
15524
|
-
|
|
15525
|
-
|
|
15526
|
-
|
|
15527
|
-
|
|
15528
|
-
|
|
15529
|
-
var registerColumnFromContext = (context, column) => {
|
|
15530
|
-
if (!context.name) {
|
|
15531
|
-
throw new Error("Column decorator requires a property name");
|
|
15532
|
-
}
|
|
15533
|
-
if (context.private) {
|
|
15534
|
-
throw new Error("Column decorator does not support private fields");
|
|
15535
|
-
}
|
|
15536
|
-
const propertyName = normalizePropertyName(context.name);
|
|
15537
|
-
const bag = getOrCreateMetadataBag(context);
|
|
16790
|
+
var registerColumnFromContext = (targetOrValue, contextOrProperty, column) => {
|
|
16791
|
+
const { propertyName, bag } = resolveFieldDecoratorInfo(
|
|
16792
|
+
targetOrValue,
|
|
16793
|
+
contextOrProperty,
|
|
16794
|
+
"Column"
|
|
16795
|
+
);
|
|
15538
16796
|
if (!bag.columns.some((entry) => entry.propertyName === propertyName)) {
|
|
15539
16797
|
bag.columns.push({ propertyName, column: { ...column } });
|
|
15540
16798
|
}
|
|
15541
16799
|
};
|
|
15542
16800
|
function Column(definition) {
|
|
15543
16801
|
const normalized = normalizeColumnInput(definition);
|
|
15544
|
-
return function(
|
|
15545
|
-
registerColumnFromContext(
|
|
16802
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16803
|
+
registerColumnFromContext(targetOrValue, contextOrProperty, normalized);
|
|
15546
16804
|
};
|
|
15547
16805
|
}
|
|
15548
16806
|
function PrimaryKey(definition) {
|
|
@@ -15552,22 +16810,13 @@ function PrimaryKey(definition) {
|
|
|
15552
16810
|
}
|
|
15553
16811
|
|
|
15554
16812
|
// src/decorators/relations.ts
|
|
15555
|
-
var normalizePropertyName2 = (name) => {
|
|
15556
|
-
if (typeof name === "symbol") {
|
|
15557
|
-
return name.description ?? name.toString();
|
|
15558
|
-
}
|
|
15559
|
-
return name;
|
|
15560
|
-
};
|
|
15561
16813
|
var createFieldDecorator = (metadataFactory) => {
|
|
15562
|
-
return function(
|
|
15563
|
-
|
|
15564
|
-
|
|
15565
|
-
|
|
15566
|
-
|
|
15567
|
-
|
|
15568
|
-
}
|
|
15569
|
-
const propertyName = normalizePropertyName2(context.name);
|
|
15570
|
-
const bag = getOrCreateMetadataBag(context);
|
|
16814
|
+
return function(targetOrValue, contextOrProperty) {
|
|
16815
|
+
const { propertyName, bag } = resolveFieldDecoratorInfo(
|
|
16816
|
+
targetOrValue,
|
|
16817
|
+
contextOrProperty,
|
|
16818
|
+
"Relation"
|
|
16819
|
+
);
|
|
15571
16820
|
const relationMetadata = metadataFactory(propertyName);
|
|
15572
16821
|
if (!bag.relations.some((entry) => entry.propertyName === propertyName)) {
|
|
15573
16822
|
bag.relations.push({ propertyName, relation: relationMetadata });
|
|
@@ -15619,6 +16868,43 @@ function BelongsToMany(options) {
|
|
|
15619
16868
|
cascade: options.cascade
|
|
15620
16869
|
}));
|
|
15621
16870
|
}
|
|
16871
|
+
function MorphTo(options) {
|
|
16872
|
+
return createFieldDecorator((propertyName) => ({
|
|
16873
|
+
kind: RelationKinds.MorphTo,
|
|
16874
|
+
propertyKey: propertyName,
|
|
16875
|
+
typeField: options.typeField,
|
|
16876
|
+
idField: options.idField,
|
|
16877
|
+
targets: options.targets,
|
|
16878
|
+
targetKey: options.targetKey,
|
|
16879
|
+
cascade: options.cascade
|
|
16880
|
+
}));
|
|
16881
|
+
}
|
|
16882
|
+
function MorphOne(options) {
|
|
16883
|
+
return createFieldDecorator((propertyName) => ({
|
|
16884
|
+
kind: RelationKinds.MorphOne,
|
|
16885
|
+
propertyKey: propertyName,
|
|
16886
|
+
target: options.target,
|
|
16887
|
+
morphName: options.morphName,
|
|
16888
|
+
typeValue: options.typeValue,
|
|
16889
|
+
typeField: options.typeField,
|
|
16890
|
+
idField: options.idField,
|
|
16891
|
+
localKey: options.localKey,
|
|
16892
|
+
cascade: options.cascade
|
|
16893
|
+
}));
|
|
16894
|
+
}
|
|
16895
|
+
function MorphMany(options) {
|
|
16896
|
+
return createFieldDecorator((propertyName) => ({
|
|
16897
|
+
kind: RelationKinds.MorphMany,
|
|
16898
|
+
propertyKey: propertyName,
|
|
16899
|
+
target: options.target,
|
|
16900
|
+
morphName: options.morphName,
|
|
16901
|
+
typeValue: options.typeValue,
|
|
16902
|
+
typeField: options.typeField,
|
|
16903
|
+
idField: options.idField,
|
|
16904
|
+
localKey: options.localKey,
|
|
16905
|
+
cascade: options.cascade
|
|
16906
|
+
}));
|
|
16907
|
+
}
|
|
15622
16908
|
|
|
15623
16909
|
// src/decorators/transformers/built-in/string-transformers.ts
|
|
15624
16910
|
var TrimTransformer = class {
|
|
@@ -15804,15 +17090,12 @@ var PatternValidator = class {
|
|
|
15804
17090
|
};
|
|
15805
17091
|
|
|
15806
17092
|
// src/decorators/transformers/transformer-decorators.ts
|
|
15807
|
-
var
|
|
15808
|
-
|
|
15809
|
-
|
|
15810
|
-
|
|
15811
|
-
|
|
15812
|
-
|
|
15813
|
-
var registerTransformerMetadata = (context, metadata) => {
|
|
15814
|
-
const propertyName = normalizePropertyName3(context.name);
|
|
15815
|
-
const bag = getOrCreateMetadataBag(context);
|
|
17093
|
+
var registerTransformerMetadata = (targetOrValue, contextOrProperty, metadata) => {
|
|
17094
|
+
const { propertyName, bag } = resolveFieldDecoratorInfo(
|
|
17095
|
+
targetOrValue,
|
|
17096
|
+
contextOrProperty,
|
|
17097
|
+
"Transformer"
|
|
17098
|
+
);
|
|
15816
17099
|
let existing = bag.transformers.find((t) => t.propertyName === propertyName);
|
|
15817
17100
|
if (!existing) {
|
|
15818
17101
|
existing = {
|
|
@@ -15841,64 +17124,64 @@ var registerTransformerMetadata = (context, metadata) => {
|
|
|
15841
17124
|
}
|
|
15842
17125
|
};
|
|
15843
17126
|
function Trim(options) {
|
|
15844
|
-
return function(
|
|
15845
|
-
registerTransformerMetadata(
|
|
17127
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17128
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15846
17129
|
sanitizers: [new TrimTransformer(options)]
|
|
15847
17130
|
});
|
|
15848
17131
|
};
|
|
15849
17132
|
}
|
|
15850
17133
|
function Lower() {
|
|
15851
|
-
return function(
|
|
15852
|
-
registerTransformerMetadata(
|
|
17134
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17135
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15853
17136
|
sanitizers: [new CaseTransformer("lower")]
|
|
15854
17137
|
});
|
|
15855
17138
|
};
|
|
15856
17139
|
}
|
|
15857
17140
|
function Upper() {
|
|
15858
|
-
return function(
|
|
15859
|
-
registerTransformerMetadata(
|
|
17141
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17142
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15860
17143
|
sanitizers: [new CaseTransformer("upper")]
|
|
15861
17144
|
});
|
|
15862
17145
|
};
|
|
15863
17146
|
}
|
|
15864
17147
|
function Capitalize() {
|
|
15865
|
-
return function(
|
|
15866
|
-
registerTransformerMetadata(
|
|
17148
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17149
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15867
17150
|
sanitizers: [new CaseTransformer("capitalize")]
|
|
15868
17151
|
});
|
|
15869
17152
|
};
|
|
15870
17153
|
}
|
|
15871
17154
|
function Title() {
|
|
15872
|
-
return function(
|
|
15873
|
-
registerTransformerMetadata(
|
|
17155
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17156
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15874
17157
|
sanitizers: [new CaseTransformer("title")]
|
|
15875
17158
|
});
|
|
15876
17159
|
};
|
|
15877
17160
|
}
|
|
15878
17161
|
function Alphanumeric(options) {
|
|
15879
|
-
return function(
|
|
15880
|
-
registerTransformerMetadata(
|
|
17162
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17163
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15881
17164
|
validators: [new AlphanumericValidator(options)]
|
|
15882
17165
|
});
|
|
15883
17166
|
};
|
|
15884
17167
|
}
|
|
15885
17168
|
function Email(options) {
|
|
15886
|
-
return function(
|
|
15887
|
-
registerTransformerMetadata(
|
|
17169
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17170
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15888
17171
|
validators: [new EmailValidator(options)]
|
|
15889
17172
|
});
|
|
15890
17173
|
};
|
|
15891
17174
|
}
|
|
15892
17175
|
function Length(options) {
|
|
15893
|
-
return function(
|
|
15894
|
-
registerTransformerMetadata(
|
|
17176
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17177
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15895
17178
|
validators: [new LengthValidator(options)]
|
|
15896
17179
|
});
|
|
15897
17180
|
};
|
|
15898
17181
|
}
|
|
15899
17182
|
function Pattern(options) {
|
|
15900
|
-
return function(
|
|
15901
|
-
registerTransformerMetadata(
|
|
17183
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17184
|
+
registerTransformerMetadata(targetOrValue, contextOrProperty, {
|
|
15902
17185
|
validators: [new PatternValidator(options)]
|
|
15903
17186
|
});
|
|
15904
17187
|
};
|
|
@@ -16125,16 +17408,12 @@ var CEPValidator = class {
|
|
|
16125
17408
|
registerValidator("BR", "cpf", () => new CPFValidator());
|
|
16126
17409
|
registerValidator("BR", "cnpj", () => new CNPJValidator());
|
|
16127
17410
|
registerValidator("BR", "cep", () => new CEPValidator());
|
|
16128
|
-
var
|
|
16129
|
-
|
|
16130
|
-
return name.description ?? name.toString();
|
|
16131
|
-
}
|
|
16132
|
-
return name;
|
|
17411
|
+
var resolveCountryDecoratorInfo = (targetOrValue, contextOrProperty) => {
|
|
17412
|
+
return resolveFieldDecoratorInfo(targetOrValue, contextOrProperty, "Country validator");
|
|
16133
17413
|
};
|
|
16134
17414
|
function CPF(options) {
|
|
16135
|
-
return function(
|
|
16136
|
-
const propertyName =
|
|
16137
|
-
const bag = getOrCreateMetadataBag(context);
|
|
17415
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17416
|
+
const { propertyName, bag } = resolveCountryDecoratorInfo(targetOrValue, contextOrProperty);
|
|
16138
17417
|
let existing = bag.transformers.find((t) => t.propertyName === propertyName);
|
|
16139
17418
|
if (!existing) {
|
|
16140
17419
|
existing = {
|
|
@@ -16182,9 +17461,8 @@ function CPF(options) {
|
|
|
16182
17461
|
};
|
|
16183
17462
|
}
|
|
16184
17463
|
function CNPJ(options) {
|
|
16185
|
-
return function(
|
|
16186
|
-
const propertyName =
|
|
16187
|
-
const bag = getOrCreateMetadataBag(context);
|
|
17464
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17465
|
+
const { propertyName, bag } = resolveCountryDecoratorInfo(targetOrValue, contextOrProperty);
|
|
16188
17466
|
let existing = bag.transformers.find((t) => t.propertyName === propertyName);
|
|
16189
17467
|
if (!existing) {
|
|
16190
17468
|
existing = {
|
|
@@ -16232,9 +17510,8 @@ function CNPJ(options) {
|
|
|
16232
17510
|
};
|
|
16233
17511
|
}
|
|
16234
17512
|
function CEP(options) {
|
|
16235
|
-
return function(
|
|
16236
|
-
const propertyName =
|
|
16237
|
-
const bag = getOrCreateMetadataBag(context);
|
|
17513
|
+
return function(targetOrValue, contextOrProperty) {
|
|
17514
|
+
const { propertyName, bag } = resolveCountryDecoratorInfo(targetOrValue, contextOrProperty);
|
|
16238
17515
|
let existing = bag.transformers.find((t) => t.propertyName === propertyName);
|
|
16239
17516
|
if (!existing) {
|
|
16240
17517
|
existing = {
|
|
@@ -16490,6 +17767,14 @@ var Pool = class {
|
|
|
16490
17767
|
};
|
|
16491
17768
|
|
|
16492
17769
|
// src/core/execution/executors/postgres-executor.ts
|
|
17770
|
+
var SAVEPOINT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
17771
|
+
var sanitizeSavepointName = (name) => {
|
|
17772
|
+
const trimmed = name.trim();
|
|
17773
|
+
if (!SAVEPOINT_NAME_PATTERN.test(trimmed)) {
|
|
17774
|
+
throw new Error(`Invalid savepoint name: "${name}"`);
|
|
17775
|
+
}
|
|
17776
|
+
return trimmed;
|
|
17777
|
+
};
|
|
16493
17778
|
function createPostgresExecutor(client) {
|
|
16494
17779
|
return createExecutorFromQueryRunner({
|
|
16495
17780
|
async query(sql, params) {
|
|
@@ -16504,11 +17789,24 @@ function createPostgresExecutor(client) {
|
|
|
16504
17789
|
},
|
|
16505
17790
|
async rollbackTransaction() {
|
|
16506
17791
|
await client.query("ROLLBACK");
|
|
17792
|
+
},
|
|
17793
|
+
async savepoint(name) {
|
|
17794
|
+
const savepoint = sanitizeSavepointName(name);
|
|
17795
|
+
await client.query(`SAVEPOINT ${savepoint}`);
|
|
17796
|
+
},
|
|
17797
|
+
async releaseSavepoint(name) {
|
|
17798
|
+
const savepoint = sanitizeSavepointName(name);
|
|
17799
|
+
await client.query(`RELEASE SAVEPOINT ${savepoint}`);
|
|
17800
|
+
},
|
|
17801
|
+
async rollbackToSavepoint(name) {
|
|
17802
|
+
const savepoint = sanitizeSavepointName(name);
|
|
17803
|
+
await client.query(`ROLLBACK TO SAVEPOINT ${savepoint}`);
|
|
16507
17804
|
}
|
|
16508
17805
|
});
|
|
16509
17806
|
}
|
|
16510
17807
|
|
|
16511
17808
|
// src/core/execution/executors/mysql-executor.ts
|
|
17809
|
+
var SAVEPOINT_NAME_PATTERN2 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
16512
17810
|
var isRowObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16513
17811
|
var isRowObjectArray = (value) => Array.isArray(value) && value.every(isRowObject);
|
|
16514
17812
|
var isMysqlResultHeader = (value) => isRowObject(value) && ("affectedRows" in value || "insertId" in value || "warningStatus" in value || "serverStatus" in value);
|
|
@@ -16520,6 +17818,13 @@ var headerToQueryResult = (header) => ({
|
|
|
16520
17818
|
rowsAffected: header.affectedRows
|
|
16521
17819
|
}
|
|
16522
17820
|
});
|
|
17821
|
+
var sanitizeSavepointName2 = (name) => {
|
|
17822
|
+
const trimmed = name.trim();
|
|
17823
|
+
if (!SAVEPOINT_NAME_PATTERN2.test(trimmed)) {
|
|
17824
|
+
throw new Error(`Invalid savepoint name: "${name}"`);
|
|
17825
|
+
}
|
|
17826
|
+
return trimmed;
|
|
17827
|
+
};
|
|
16523
17828
|
var normalizeMysqlResults = (rows) => {
|
|
16524
17829
|
if (!Array.isArray(rows)) {
|
|
16525
17830
|
return isMysqlResultHeader(rows) ? [headerToQueryResult(rows)] : [rowsToQueryResult([])];
|
|
@@ -16541,9 +17846,11 @@ var normalizeMysqlResults = (rows) => {
|
|
|
16541
17846
|
};
|
|
16542
17847
|
function createMysqlExecutor(client) {
|
|
16543
17848
|
const supportsTransactions = typeof client.beginTransaction === "function" && typeof client.commit === "function" && typeof client.rollback === "function";
|
|
17849
|
+
const supportsSavepoints = supportsTransactions;
|
|
16544
17850
|
return {
|
|
16545
17851
|
capabilities: {
|
|
16546
|
-
transactions: supportsTransactions
|
|
17852
|
+
transactions: supportsTransactions,
|
|
17853
|
+
...supportsSavepoints ? { savepoints: true } : {}
|
|
16547
17854
|
},
|
|
16548
17855
|
async executeSql(sql, params) {
|
|
16549
17856
|
const [rows] = await client.query(sql, params);
|
|
@@ -16567,17 +17874,55 @@ function createMysqlExecutor(client) {
|
|
|
16567
17874
|
}
|
|
16568
17875
|
await client.rollback();
|
|
16569
17876
|
},
|
|
17877
|
+
async savepoint(name) {
|
|
17878
|
+
if (!supportsSavepoints) {
|
|
17879
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17880
|
+
}
|
|
17881
|
+
const savepoint = sanitizeSavepointName2(name);
|
|
17882
|
+
await client.query(`SAVEPOINT ${savepoint}`);
|
|
17883
|
+
},
|
|
17884
|
+
async releaseSavepoint(name) {
|
|
17885
|
+
if (!supportsSavepoints) {
|
|
17886
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17887
|
+
}
|
|
17888
|
+
const savepoint = sanitizeSavepointName2(name);
|
|
17889
|
+
await client.query(`RELEASE SAVEPOINT ${savepoint}`);
|
|
17890
|
+
},
|
|
17891
|
+
async rollbackToSavepoint(name) {
|
|
17892
|
+
if (!supportsSavepoints) {
|
|
17893
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17894
|
+
}
|
|
17895
|
+
const savepoint = sanitizeSavepointName2(name);
|
|
17896
|
+
await client.query(`ROLLBACK TO SAVEPOINT ${savepoint}`);
|
|
17897
|
+
},
|
|
16570
17898
|
async dispose() {
|
|
16571
17899
|
}
|
|
16572
17900
|
};
|
|
16573
17901
|
}
|
|
16574
17902
|
|
|
16575
17903
|
// src/core/execution/executors/sqlite-executor.ts
|
|
17904
|
+
var SAVEPOINT_NAME_PATTERN3 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
17905
|
+
var sanitizeSavepointName3 = (name) => {
|
|
17906
|
+
const trimmed = name.trim();
|
|
17907
|
+
if (!SAVEPOINT_NAME_PATTERN3.test(trimmed)) {
|
|
17908
|
+
throw new Error(`Invalid savepoint name: "${name}"`);
|
|
17909
|
+
}
|
|
17910
|
+
return trimmed;
|
|
17911
|
+
};
|
|
16576
17912
|
function createSqliteExecutor(client) {
|
|
16577
17913
|
const supportsTransactions = typeof client.beginTransaction === "function" && typeof client.commitTransaction === "function" && typeof client.rollbackTransaction === "function";
|
|
17914
|
+
const supportsSavepoints = supportsTransactions;
|
|
17915
|
+
const executeControlStatement = async (sql) => {
|
|
17916
|
+
if (typeof client.run === "function") {
|
|
17917
|
+
await client.run(sql);
|
|
17918
|
+
return;
|
|
17919
|
+
}
|
|
17920
|
+
await client.all(sql);
|
|
17921
|
+
};
|
|
16578
17922
|
return {
|
|
16579
17923
|
capabilities: {
|
|
16580
|
-
transactions: supportsTransactions
|
|
17924
|
+
transactions: supportsTransactions,
|
|
17925
|
+
...supportsSavepoints ? { savepoints: true } : {}
|
|
16581
17926
|
},
|
|
16582
17927
|
async executeSql(sql, params) {
|
|
16583
17928
|
const rows = await client.all(sql, params);
|
|
@@ -16602,17 +17947,120 @@ function createSqliteExecutor(client) {
|
|
|
16602
17947
|
}
|
|
16603
17948
|
await client.rollbackTransaction();
|
|
16604
17949
|
},
|
|
17950
|
+
async savepoint(name) {
|
|
17951
|
+
if (!supportsSavepoints) {
|
|
17952
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17953
|
+
}
|
|
17954
|
+
const savepoint = sanitizeSavepointName3(name);
|
|
17955
|
+
if (typeof client.savepoint === "function") {
|
|
17956
|
+
await client.savepoint(savepoint);
|
|
17957
|
+
return;
|
|
17958
|
+
}
|
|
17959
|
+
await executeControlStatement(`SAVEPOINT ${savepoint}`);
|
|
17960
|
+
},
|
|
17961
|
+
async releaseSavepoint(name) {
|
|
17962
|
+
if (!supportsSavepoints) {
|
|
17963
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17964
|
+
}
|
|
17965
|
+
const savepoint = sanitizeSavepointName3(name);
|
|
17966
|
+
if (typeof client.releaseSavepoint === "function") {
|
|
17967
|
+
await client.releaseSavepoint(savepoint);
|
|
17968
|
+
return;
|
|
17969
|
+
}
|
|
17970
|
+
await executeControlStatement(`RELEASE SAVEPOINT ${savepoint}`);
|
|
17971
|
+
},
|
|
17972
|
+
async rollbackToSavepoint(name) {
|
|
17973
|
+
if (!supportsSavepoints) {
|
|
17974
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
17975
|
+
}
|
|
17976
|
+
const savepoint = sanitizeSavepointName3(name);
|
|
17977
|
+
if (typeof client.rollbackToSavepoint === "function") {
|
|
17978
|
+
await client.rollbackToSavepoint(savepoint);
|
|
17979
|
+
return;
|
|
17980
|
+
}
|
|
17981
|
+
await executeControlStatement(`ROLLBACK TO SAVEPOINT ${savepoint}`);
|
|
17982
|
+
},
|
|
17983
|
+
async dispose() {
|
|
17984
|
+
}
|
|
17985
|
+
};
|
|
17986
|
+
}
|
|
17987
|
+
|
|
17988
|
+
// src/core/execution/executors/better-sqlite3-executor.ts
|
|
17989
|
+
var SAVEPOINT_NAME_PATTERN4 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
17990
|
+
var sanitizeSavepointName4 = (name) => {
|
|
17991
|
+
const trimmed = name.trim();
|
|
17992
|
+
if (!SAVEPOINT_NAME_PATTERN4.test(trimmed)) {
|
|
17993
|
+
throw new Error(`Invalid savepoint name: "${name}"`);
|
|
17994
|
+
}
|
|
17995
|
+
return trimmed;
|
|
17996
|
+
};
|
|
17997
|
+
function createBetterSqlite3Executor(client) {
|
|
17998
|
+
return {
|
|
17999
|
+
capabilities: {
|
|
18000
|
+
transactions: true,
|
|
18001
|
+
savepoints: true
|
|
18002
|
+
},
|
|
18003
|
+
async executeSql(sql, params) {
|
|
18004
|
+
const stmt = client.prepare(sql);
|
|
18005
|
+
let result;
|
|
18006
|
+
if (stmt.reader) {
|
|
18007
|
+
const rows = stmt.all(...params ?? []);
|
|
18008
|
+
result = rowsToQueryResult(rows);
|
|
18009
|
+
} else {
|
|
18010
|
+
const info = stmt.run(...params ?? []);
|
|
18011
|
+
result = {
|
|
18012
|
+
columns: [],
|
|
18013
|
+
values: [],
|
|
18014
|
+
meta: {
|
|
18015
|
+
rowsAffected: info.changes,
|
|
18016
|
+
insertId: typeof info.lastInsertRowid === "bigint" ? info.lastInsertRowid.toString() : info.lastInsertRowid
|
|
18017
|
+
}
|
|
18018
|
+
};
|
|
18019
|
+
}
|
|
18020
|
+
return toExecutionPayload([result]);
|
|
18021
|
+
},
|
|
18022
|
+
async beginTransaction() {
|
|
18023
|
+
client.prepare("BEGIN").run();
|
|
18024
|
+
},
|
|
18025
|
+
async commitTransaction() {
|
|
18026
|
+
client.prepare("COMMIT").run();
|
|
18027
|
+
},
|
|
18028
|
+
async rollbackTransaction() {
|
|
18029
|
+
client.prepare("ROLLBACK").run();
|
|
18030
|
+
},
|
|
18031
|
+
async savepoint(name) {
|
|
18032
|
+
const savepoint = sanitizeSavepointName4(name);
|
|
18033
|
+
client.prepare(`SAVEPOINT ${savepoint}`).run();
|
|
18034
|
+
},
|
|
18035
|
+
async releaseSavepoint(name) {
|
|
18036
|
+
const savepoint = sanitizeSavepointName4(name);
|
|
18037
|
+
client.prepare(`RELEASE SAVEPOINT ${savepoint}`).run();
|
|
18038
|
+
},
|
|
18039
|
+
async rollbackToSavepoint(name) {
|
|
18040
|
+
const savepoint = sanitizeSavepointName4(name);
|
|
18041
|
+
client.prepare(`ROLLBACK TO SAVEPOINT ${savepoint}`).run();
|
|
18042
|
+
},
|
|
16605
18043
|
async dispose() {
|
|
16606
18044
|
}
|
|
16607
18045
|
};
|
|
16608
18046
|
}
|
|
16609
18047
|
|
|
16610
18048
|
// src/core/execution/executors/mssql-executor.ts
|
|
18049
|
+
var SAVEPOINT_NAME_PATTERN5 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
18050
|
+
var sanitizeSavepointName5 = (name) => {
|
|
18051
|
+
const trimmed = name.trim();
|
|
18052
|
+
if (!SAVEPOINT_NAME_PATTERN5.test(trimmed)) {
|
|
18053
|
+
throw new Error(`Invalid savepoint name: "${name}"`);
|
|
18054
|
+
}
|
|
18055
|
+
return trimmed;
|
|
18056
|
+
};
|
|
16611
18057
|
function createMssqlExecutor(client) {
|
|
16612
18058
|
const supportsTransactions = typeof client.beginTransaction === "function" && typeof client.commit === "function" && typeof client.rollback === "function";
|
|
18059
|
+
const supportsSavepoints = supportsTransactions;
|
|
16613
18060
|
return {
|
|
16614
18061
|
capabilities: {
|
|
16615
|
-
transactions: supportsTransactions
|
|
18062
|
+
transactions: supportsTransactions,
|
|
18063
|
+
...supportsSavepoints ? { savepoints: true } : {}
|
|
16616
18064
|
},
|
|
16617
18065
|
async executeSql(sql, params) {
|
|
16618
18066
|
const { recordset, recordsets } = await client.query(sql, params);
|
|
@@ -16637,6 +18085,25 @@ function createMssqlExecutor(client) {
|
|
|
16637
18085
|
}
|
|
16638
18086
|
await client.rollback();
|
|
16639
18087
|
},
|
|
18088
|
+
async savepoint(name) {
|
|
18089
|
+
if (!supportsSavepoints) {
|
|
18090
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
18091
|
+
}
|
|
18092
|
+
const savepoint = sanitizeSavepointName5(name);
|
|
18093
|
+
await client.query(`SAVE TRANSACTION ${savepoint}`);
|
|
18094
|
+
},
|
|
18095
|
+
async releaseSavepoint(_name) {
|
|
18096
|
+
if (!supportsSavepoints) {
|
|
18097
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
18098
|
+
}
|
|
18099
|
+
},
|
|
18100
|
+
async rollbackToSavepoint(name) {
|
|
18101
|
+
if (!supportsSavepoints) {
|
|
18102
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
18103
|
+
}
|
|
18104
|
+
const savepoint = sanitizeSavepointName5(name);
|
|
18105
|
+
await client.query(`ROLLBACK TRANSACTION ${savepoint}`);
|
|
18106
|
+
},
|
|
16640
18107
|
async dispose() {
|
|
16641
18108
|
}
|
|
16642
18109
|
};
|
|
@@ -16712,6 +18179,7 @@ var isQueryResult = (value) => typeof value === "object" && value !== null && Ar
|
|
|
16712
18179
|
var isRowArray = (value) => Array.isArray(value) && value.every((item) => typeof item === "object" && item !== null && !Array.isArray(item));
|
|
16713
18180
|
function createPooledExecutorFactory(opts) {
|
|
16714
18181
|
const { pool, adapter } = opts;
|
|
18182
|
+
const supportsSavepoints = typeof adapter.savepoint === "function" && typeof adapter.releaseSavepoint === "function" && typeof adapter.rollbackToSavepoint === "function";
|
|
16715
18183
|
const makeExecutor = (mode) => {
|
|
16716
18184
|
let lease = null;
|
|
16717
18185
|
const getLease = async () => {
|
|
@@ -16729,8 +18197,17 @@ function createPooledExecutorFactory(opts) {
|
|
|
16729
18197
|
}
|
|
16730
18198
|
return toExecutionPayload([rowsToQueryResult(rows)]);
|
|
16731
18199
|
};
|
|
18200
|
+
const requireActiveTransactionLease = () => {
|
|
18201
|
+
if (!lease) {
|
|
18202
|
+
throw new Error("savepoint operation called without an active transaction");
|
|
18203
|
+
}
|
|
18204
|
+
return lease;
|
|
18205
|
+
};
|
|
16732
18206
|
return {
|
|
16733
|
-
capabilities: {
|
|
18207
|
+
capabilities: {
|
|
18208
|
+
transactions: true,
|
|
18209
|
+
...supportsSavepoints ? { savepoints: true } : {}
|
|
18210
|
+
},
|
|
16734
18211
|
async executeSql(sql, params) {
|
|
16735
18212
|
if (mode === "sticky") {
|
|
16736
18213
|
const l2 = await getLease();
|
|
@@ -16774,6 +18251,27 @@ function createPooledExecutorFactory(opts) {
|
|
|
16774
18251
|
await l.release();
|
|
16775
18252
|
}
|
|
16776
18253
|
},
|
|
18254
|
+
async savepoint(name) {
|
|
18255
|
+
if (!supportsSavepoints) {
|
|
18256
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
18257
|
+
}
|
|
18258
|
+
const l = requireActiveTransactionLease();
|
|
18259
|
+
await adapter.savepoint(l.resource, name);
|
|
18260
|
+
},
|
|
18261
|
+
async releaseSavepoint(name) {
|
|
18262
|
+
if (!supportsSavepoints) {
|
|
18263
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
18264
|
+
}
|
|
18265
|
+
const l = requireActiveTransactionLease();
|
|
18266
|
+
await adapter.releaseSavepoint(l.resource, name);
|
|
18267
|
+
},
|
|
18268
|
+
async rollbackToSavepoint(name) {
|
|
18269
|
+
if (!supportsSavepoints) {
|
|
18270
|
+
throw new Error("Savepoints are not supported by this executor");
|
|
18271
|
+
}
|
|
18272
|
+
const l = requireActiveTransactionLease();
|
|
18273
|
+
await adapter.rollbackToSavepoint(l.resource, name);
|
|
18274
|
+
},
|
|
16777
18275
|
async dispose() {
|
|
16778
18276
|
if (!lease) return;
|
|
16779
18277
|
const l = lease;
|
|
@@ -16868,6 +18366,9 @@ var updateInclude = (qb, relationPath, updater) => {
|
|
|
16868
18366
|
filter: segmentOptions?.filter
|
|
16869
18367
|
});
|
|
16870
18368
|
}
|
|
18369
|
+
if (!isSingleTargetRelation(relation)) {
|
|
18370
|
+
continue;
|
|
18371
|
+
}
|
|
16871
18372
|
const joinForSegment = findJoinByRelationKey(state.ast.joins, relationKey);
|
|
16872
18373
|
currentAlias = joinForSegment ? getExposedName(joinForSegment.table) ?? relation.target.name : relation.target.name;
|
|
16873
18374
|
currentTable = relation.target;
|
|
@@ -16996,6 +18497,9 @@ function applyRelationFilter(qb, table, relationName, filter) {
|
|
|
16996
18497
|
`Relation filter "${relationName}" must include at least one of "some", "none", "every", "isEmpty", or "isNotEmpty".`
|
|
16997
18498
|
);
|
|
16998
18499
|
}
|
|
18500
|
+
if (!isSingleTargetRelation(relation)) {
|
|
18501
|
+
return qb;
|
|
18502
|
+
}
|
|
16999
18503
|
if (filter.some) {
|
|
17000
18504
|
const predicate = buildFilterExpression(relation.target, filter.some);
|
|
17001
18505
|
if (predicate) {
|
|
@@ -17041,6 +18545,9 @@ function applyRelationFilter(qb, table, relationName, filter) {
|
|
|
17041
18545
|
return qb;
|
|
17042
18546
|
}
|
|
17043
18547
|
var buildRelationSubqueryBase = (table, relation) => {
|
|
18548
|
+
if (!isSingleTargetRelation(relation)) {
|
|
18549
|
+
throw new Error("MorphTo relations do not support subquery-based filtering");
|
|
18550
|
+
}
|
|
17044
18551
|
const target = relation.target;
|
|
17045
18552
|
if (relation.type === RelationKinds.BelongsToMany) {
|
|
17046
18553
|
const many = relation;
|
|
@@ -17086,7 +18593,14 @@ var buildRelationSubqueryBase = (table, relation) => {
|
|
|
17086
18593
|
schema: target.schema
|
|
17087
18594
|
};
|
|
17088
18595
|
const correlation = buildRelationCorrelation(table, relation);
|
|
17089
|
-
|
|
18596
|
+
let groupByColumnName;
|
|
18597
|
+
if (relation.type === RelationKinds.BelongsTo) {
|
|
18598
|
+
groupByColumnName = relation.localKey || findPrimaryKey(target);
|
|
18599
|
+
} else if (relation.type === RelationKinds.MorphOne || relation.type === RelationKinds.MorphMany) {
|
|
18600
|
+
groupByColumnName = relation.idField;
|
|
18601
|
+
} else {
|
|
18602
|
+
groupByColumnName = relation.foreignKey;
|
|
18603
|
+
}
|
|
17090
18604
|
return {
|
|
17091
18605
|
from,
|
|
17092
18606
|
joins: [],
|
|
@@ -17118,6 +18632,9 @@ function buildRelationFilterExpression(table, relationName, filter) {
|
|
|
17118
18632
|
where
|
|
17119
18633
|
};
|
|
17120
18634
|
};
|
|
18635
|
+
if (!isSingleTargetRelation(relation)) {
|
|
18636
|
+
return null;
|
|
18637
|
+
}
|
|
17121
18638
|
if (filter.some) {
|
|
17122
18639
|
const predicate = buildFilterExpression(relation.target, filter.some);
|
|
17123
18640
|
if (predicate) {
|
|
@@ -20087,6 +21604,432 @@ var TagIndex = class {
|
|
|
20087
21604
|
};
|
|
20088
21605
|
}
|
|
20089
21606
|
};
|
|
21607
|
+
|
|
21608
|
+
// src/bulk/bulk-context.ts
|
|
21609
|
+
function createBulkExecutionContext(session) {
|
|
21610
|
+
const executionContext = session.getExecutionContext();
|
|
21611
|
+
return {
|
|
21612
|
+
session,
|
|
21613
|
+
executionContext,
|
|
21614
|
+
dialect: executionContext.dialect,
|
|
21615
|
+
supportsReturning: executionContext.dialect.supportsDmlReturningClause()
|
|
21616
|
+
};
|
|
21617
|
+
}
|
|
21618
|
+
async function executeCompiled(ctx, compiled) {
|
|
21619
|
+
const payload = await ctx.executionContext.interceptors.run(
|
|
21620
|
+
{ sql: compiled.sql, params: compiled.params },
|
|
21621
|
+
ctx.executionContext.executor
|
|
21622
|
+
);
|
|
21623
|
+
return extractResultSets(payload);
|
|
21624
|
+
}
|
|
21625
|
+
function extractResultSets(payload) {
|
|
21626
|
+
const result = payload;
|
|
21627
|
+
if (result.resultSets) {
|
|
21628
|
+
return result.resultSets;
|
|
21629
|
+
}
|
|
21630
|
+
return [];
|
|
21631
|
+
}
|
|
21632
|
+
function flattenQueryResults(resultSets) {
|
|
21633
|
+
const rows = [];
|
|
21634
|
+
for (const rs of resultSets) {
|
|
21635
|
+
for (const valueRow of rs.values) {
|
|
21636
|
+
const obj = {};
|
|
21637
|
+
rs.columns.forEach((col2, idx) => {
|
|
21638
|
+
const bare = col2.split(".").pop().replace(/^["`[\]]+|["`[\]]+$/g, "");
|
|
21639
|
+
obj[bare] = valueRow[idx];
|
|
21640
|
+
});
|
|
21641
|
+
rows.push(obj);
|
|
21642
|
+
}
|
|
21643
|
+
}
|
|
21644
|
+
return rows;
|
|
21645
|
+
}
|
|
21646
|
+
function resolveReturningColumns(ctx, table, returning) {
|
|
21647
|
+
if (!returning) return void 0;
|
|
21648
|
+
if (!ctx.supportsReturning) return void 0;
|
|
21649
|
+
if (returning === true) {
|
|
21650
|
+
return Object.values(table.columns).map((col2) => ({
|
|
21651
|
+
type: "Column",
|
|
21652
|
+
table: table.name,
|
|
21653
|
+
name: col2.name,
|
|
21654
|
+
alias: col2.name
|
|
21655
|
+
}));
|
|
21656
|
+
}
|
|
21657
|
+
return returning.map((col2) => ({
|
|
21658
|
+
type: "Column",
|
|
21659
|
+
table: table.name,
|
|
21660
|
+
name: col2.name,
|
|
21661
|
+
alias: col2.name
|
|
21662
|
+
}));
|
|
21663
|
+
}
|
|
21664
|
+
|
|
21665
|
+
// src/bulk/bulk-utils.ts
|
|
21666
|
+
function splitIntoChunks(items, size) {
|
|
21667
|
+
if (size < 1) throw new RangeError(`chunkSize must be >= 1, got ${size}`);
|
|
21668
|
+
const chunks = [];
|
|
21669
|
+
for (let i = 0; i < items.length; i += size) {
|
|
21670
|
+
chunks.push(items.slice(i, i + size));
|
|
21671
|
+
}
|
|
21672
|
+
return chunks;
|
|
21673
|
+
}
|
|
21674
|
+
async function runWithConcurrency(tasks, concurrency) {
|
|
21675
|
+
const limit = concurrency === "sequential" ? 1 : Math.max(1, concurrency);
|
|
21676
|
+
if (limit === 1) {
|
|
21677
|
+
const results2 = [];
|
|
21678
|
+
for (const task of tasks) {
|
|
21679
|
+
results2.push(await task());
|
|
21680
|
+
}
|
|
21681
|
+
return results2;
|
|
21682
|
+
}
|
|
21683
|
+
const results = new Array(tasks.length);
|
|
21684
|
+
let nextIndex = 0;
|
|
21685
|
+
const worker = async () => {
|
|
21686
|
+
while (nextIndex < tasks.length) {
|
|
21687
|
+
const i = nextIndex++;
|
|
21688
|
+
results[i] = await tasks[i]();
|
|
21689
|
+
}
|
|
21690
|
+
};
|
|
21691
|
+
const workers = Array.from({ length: Math.min(limit, tasks.length) }, worker);
|
|
21692
|
+
await Promise.all(workers);
|
|
21693
|
+
return results;
|
|
21694
|
+
}
|
|
21695
|
+
async function runChunk(task, chunkIndex, totalChunks, rowsInChunk, timing, onChunkComplete) {
|
|
21696
|
+
const start = timing || onChunkComplete ? Date.now() : 0;
|
|
21697
|
+
const result = await task();
|
|
21698
|
+
const elapsedMs = start ? Date.now() - start : 0;
|
|
21699
|
+
if (onChunkComplete) {
|
|
21700
|
+
await onChunkComplete({ chunkIndex, totalChunks, rowsInChunk, elapsedMs });
|
|
21701
|
+
}
|
|
21702
|
+
return result;
|
|
21703
|
+
}
|
|
21704
|
+
async function maybeTransaction(session, transactional, fn8) {
|
|
21705
|
+
if (!transactional) return fn8();
|
|
21706
|
+
const ormSession = session;
|
|
21707
|
+
return ormSession.transaction(fn8);
|
|
21708
|
+
}
|
|
21709
|
+
function aggregateOutcomes(outcomes) {
|
|
21710
|
+
const result = {
|
|
21711
|
+
processedRows: 0,
|
|
21712
|
+
chunksExecuted: outcomes.length,
|
|
21713
|
+
returning: []
|
|
21714
|
+
};
|
|
21715
|
+
for (const o of outcomes) {
|
|
21716
|
+
result.processedRows += o.processedRows;
|
|
21717
|
+
result.returning.push(...o.returning);
|
|
21718
|
+
}
|
|
21719
|
+
return result;
|
|
21720
|
+
}
|
|
21721
|
+
function aggregateOutcomesWithTimings(outcomes) {
|
|
21722
|
+
const result = aggregateOutcomes(outcomes);
|
|
21723
|
+
result.chunkTimings = outcomes.map((o) => o.elapsedMs);
|
|
21724
|
+
return result;
|
|
21725
|
+
}
|
|
21726
|
+
|
|
21727
|
+
// src/bulk/bulk-executor.base.ts
|
|
21728
|
+
var DEFAULT_CHUNK_SIZE = 500;
|
|
21729
|
+
var BulkBaseExecutor = class {
|
|
21730
|
+
session;
|
|
21731
|
+
table;
|
|
21732
|
+
ctx;
|
|
21733
|
+
options;
|
|
21734
|
+
chunks;
|
|
21735
|
+
totalChunks;
|
|
21736
|
+
constructor(session, table, rows, options = {}) {
|
|
21737
|
+
this.session = session;
|
|
21738
|
+
this.table = table;
|
|
21739
|
+
this.ctx = createBulkExecutionContext(session);
|
|
21740
|
+
this.options = {
|
|
21741
|
+
chunkSize: DEFAULT_CHUNK_SIZE,
|
|
21742
|
+
concurrency: "sequential",
|
|
21743
|
+
transactional: true,
|
|
21744
|
+
timing: false,
|
|
21745
|
+
...options
|
|
21746
|
+
};
|
|
21747
|
+
this.chunks = splitIntoChunks(rows, this.options.chunkSize);
|
|
21748
|
+
this.totalChunks = this.chunks.length;
|
|
21749
|
+
}
|
|
21750
|
+
async execute() {
|
|
21751
|
+
const buildTask = (chunk, chunkIndex) => async () => {
|
|
21752
|
+
return runChunk(
|
|
21753
|
+
() => this.executeChunk(chunk, chunkIndex),
|
|
21754
|
+
chunkIndex,
|
|
21755
|
+
this.totalChunks,
|
|
21756
|
+
chunk.length,
|
|
21757
|
+
this.options.timing,
|
|
21758
|
+
this.options.onChunkComplete
|
|
21759
|
+
);
|
|
21760
|
+
};
|
|
21761
|
+
const tasks = this.chunks.map((chunk, i) => buildTask(chunk, i));
|
|
21762
|
+
const outcomes = await maybeTransaction(
|
|
21763
|
+
this.session,
|
|
21764
|
+
this.options.transactional,
|
|
21765
|
+
() => runWithConcurrency(tasks, this.options.concurrency)
|
|
21766
|
+
);
|
|
21767
|
+
return this.options.timing ? aggregateOutcomesWithTimings(outcomes) : aggregateOutcomes(outcomes);
|
|
21768
|
+
}
|
|
21769
|
+
};
|
|
21770
|
+
|
|
21771
|
+
// src/bulk/bulk-insert-executor.ts
|
|
21772
|
+
var BulkInsertExecutor = class extends BulkBaseExecutor {
|
|
21773
|
+
constructor(session, table, rows, options = {}) {
|
|
21774
|
+
super(session, table, rows, options);
|
|
21775
|
+
}
|
|
21776
|
+
async executeChunk(chunk, _chunkIndex) {
|
|
21777
|
+
const returningColumns = resolveReturningColumns(this.ctx, this.table, this.options.returning);
|
|
21778
|
+
let builder = new InsertQueryBuilder(this.table).values(chunk);
|
|
21779
|
+
if (this.options.onConflict) {
|
|
21780
|
+
const conflictColumns = this.options.onConflict.target?.columns ?? [];
|
|
21781
|
+
const conflictBuilder = builder.onConflict(conflictColumns);
|
|
21782
|
+
if (this.options.onConflict.action.type === "DoNothing") {
|
|
21783
|
+
builder = conflictBuilder.doNothing();
|
|
21784
|
+
} else if (this.options.onConflict.action.type === "DoUpdate" && this.options.onConflict.action.set) {
|
|
21785
|
+
const setMap = {};
|
|
21786
|
+
for (const assignment of this.options.onConflict.action.set) {
|
|
21787
|
+
const colName = typeof assignment.column === "object" ? assignment.column.name : assignment.column;
|
|
21788
|
+
setMap[colName] = assignment.value;
|
|
21789
|
+
}
|
|
21790
|
+
builder = conflictBuilder.doUpdate(setMap);
|
|
21791
|
+
}
|
|
21792
|
+
}
|
|
21793
|
+
const finalBuilder = builder;
|
|
21794
|
+
if (returningColumns?.length) {
|
|
21795
|
+
finalBuilder.returning(...returningColumns);
|
|
21796
|
+
}
|
|
21797
|
+
const compiled = finalBuilder.compile(this.ctx.dialect);
|
|
21798
|
+
const resultSets = await executeCompiled(this.ctx, compiled);
|
|
21799
|
+
return {
|
|
21800
|
+
processedRows: chunk.length,
|
|
21801
|
+
returning: returningColumns ? flattenQueryResults(resultSets) : [],
|
|
21802
|
+
elapsedMs: 0
|
|
21803
|
+
};
|
|
21804
|
+
}
|
|
21805
|
+
};
|
|
21806
|
+
async function bulkInsert(session, table, rows, options = {}) {
|
|
21807
|
+
if (!rows.length) {
|
|
21808
|
+
return { processedRows: 0, chunksExecuted: 0, returning: [] };
|
|
21809
|
+
}
|
|
21810
|
+
const executor = new BulkInsertExecutor(session, table, rows, options);
|
|
21811
|
+
return executor.execute();
|
|
21812
|
+
}
|
|
21813
|
+
|
|
21814
|
+
// src/bulk/bulk-update-executor.ts
|
|
21815
|
+
function resolveByColumns(table, by) {
|
|
21816
|
+
if (!by) return [findPrimaryKey(table)];
|
|
21817
|
+
return Array.isArray(by) ? by : [by];
|
|
21818
|
+
}
|
|
21819
|
+
var BulkUpdateExecutor = class extends BulkBaseExecutor {
|
|
21820
|
+
byColumns;
|
|
21821
|
+
constructor(session, table, rows, options = {}) {
|
|
21822
|
+
super(session, table, rows, options);
|
|
21823
|
+
this.byColumns = resolveByColumns(table, options.by);
|
|
21824
|
+
}
|
|
21825
|
+
async executeChunk(chunk, _chunkIndex) {
|
|
21826
|
+
const allReturning = [];
|
|
21827
|
+
const returningColumns = resolveReturningColumns(this.ctx, this.table, this.options.returning);
|
|
21828
|
+
const extraWhere = this.options.where;
|
|
21829
|
+
for (const row of chunk) {
|
|
21830
|
+
const predicates = this.byColumns.map((colName) => {
|
|
21831
|
+
const col2 = this.table.columns[colName];
|
|
21832
|
+
if (!col2) {
|
|
21833
|
+
throw new Error(
|
|
21834
|
+
`bulkUpdate: column "${colName}" not found in table "${this.table.name}"`
|
|
21835
|
+
);
|
|
21836
|
+
}
|
|
21837
|
+
const val = row[colName];
|
|
21838
|
+
if (val === void 0) {
|
|
21839
|
+
throw new Error(
|
|
21840
|
+
`bulkUpdate: row is missing the identity column "${colName}" required by the "by" option`
|
|
21841
|
+
);
|
|
21842
|
+
}
|
|
21843
|
+
return eq(col2, val);
|
|
21844
|
+
});
|
|
21845
|
+
const whereExpr = predicates.length === 1 ? predicates[0] : predicates.reduce((acc, p) => and(acc, p), predicates[0]);
|
|
21846
|
+
const finalWhere = extraWhere ? and(whereExpr, extraWhere) : whereExpr;
|
|
21847
|
+
const bySet = new Set(this.byColumns);
|
|
21848
|
+
const setPayload = {};
|
|
21849
|
+
for (const [key, val] of Object.entries(row)) {
|
|
21850
|
+
if (!bySet.has(key) && key in this.table.columns) {
|
|
21851
|
+
setPayload[key] = val;
|
|
21852
|
+
}
|
|
21853
|
+
}
|
|
21854
|
+
if (!Object.keys(setPayload).length) continue;
|
|
21855
|
+
let builder = new UpdateQueryBuilder(this.table).set(setPayload).where(finalWhere);
|
|
21856
|
+
if (returningColumns?.length) {
|
|
21857
|
+
builder = builder.returning(...returningColumns);
|
|
21858
|
+
}
|
|
21859
|
+
const compiled = builder.compile(this.ctx.dialect);
|
|
21860
|
+
const resultSets = await executeCompiled(this.ctx, compiled);
|
|
21861
|
+
if (returningColumns) {
|
|
21862
|
+
allReturning.push(...flattenQueryResults(resultSets));
|
|
21863
|
+
}
|
|
21864
|
+
}
|
|
21865
|
+
return {
|
|
21866
|
+
processedRows: chunk.length,
|
|
21867
|
+
returning: allReturning,
|
|
21868
|
+
elapsedMs: 0
|
|
21869
|
+
};
|
|
21870
|
+
}
|
|
21871
|
+
};
|
|
21872
|
+
async function bulkUpdate(session, table, rows, options = {}) {
|
|
21873
|
+
if (!rows.length) {
|
|
21874
|
+
return { processedRows: 0, chunksExecuted: 0, returning: [] };
|
|
21875
|
+
}
|
|
21876
|
+
const executor = new BulkUpdateExecutor(session, table, rows, options);
|
|
21877
|
+
return executor.execute();
|
|
21878
|
+
}
|
|
21879
|
+
var DEFAULT_BULK_UPDATE_WHERE_CHUNK_SIZE = 500;
|
|
21880
|
+
async function bulkUpdateWhere(session, table, ids, set, options = {}) {
|
|
21881
|
+
if (!ids.length) {
|
|
21882
|
+
return { processedRows: 0, chunksExecuted: 0, returning: [] };
|
|
21883
|
+
}
|
|
21884
|
+
const {
|
|
21885
|
+
chunkSize = DEFAULT_BULK_UPDATE_WHERE_CHUNK_SIZE,
|
|
21886
|
+
concurrency = "sequential",
|
|
21887
|
+
transactional = true,
|
|
21888
|
+
timing = false,
|
|
21889
|
+
onChunkComplete,
|
|
21890
|
+
by,
|
|
21891
|
+
where: extraWhere,
|
|
21892
|
+
returning
|
|
21893
|
+
} = options;
|
|
21894
|
+
const ctx = createBulkExecutionContext(session);
|
|
21895
|
+
const byColumnName = by ?? findPrimaryKey(table);
|
|
21896
|
+
const byColumn = table.columns[byColumnName];
|
|
21897
|
+
if (!byColumn) {
|
|
21898
|
+
throw new Error(
|
|
21899
|
+
`bulkUpdateWhere: column "${byColumnName}" not found in table "${table.name}"`
|
|
21900
|
+
);
|
|
21901
|
+
}
|
|
21902
|
+
const returningColumns = resolveReturningColumns(ctx, table, returning);
|
|
21903
|
+
const chunks = splitIntoChunks(ids, chunkSize);
|
|
21904
|
+
const totalChunks = chunks.length;
|
|
21905
|
+
const buildTask = (chunk, chunkIndex) => async () => {
|
|
21906
|
+
return runChunk(
|
|
21907
|
+
async () => {
|
|
21908
|
+
const inExpr = inList(byColumn, chunk);
|
|
21909
|
+
const finalWhere = extraWhere ? and(inExpr, extraWhere) : inExpr;
|
|
21910
|
+
let builder = new UpdateQueryBuilder(table).set(set).where(finalWhere);
|
|
21911
|
+
if (returningColumns?.length) {
|
|
21912
|
+
builder = builder.returning(...returningColumns);
|
|
21913
|
+
}
|
|
21914
|
+
const compiled = builder.compile(ctx.dialect);
|
|
21915
|
+
const resultSets = await executeCompiled(ctx, compiled);
|
|
21916
|
+
return {
|
|
21917
|
+
processedRows: chunk.length,
|
|
21918
|
+
returning: returningColumns ? flattenQueryResults(resultSets) : [],
|
|
21919
|
+
elapsedMs: 0
|
|
21920
|
+
};
|
|
21921
|
+
},
|
|
21922
|
+
chunkIndex,
|
|
21923
|
+
totalChunks,
|
|
21924
|
+
chunk.length,
|
|
21925
|
+
timing,
|
|
21926
|
+
onChunkComplete
|
|
21927
|
+
);
|
|
21928
|
+
};
|
|
21929
|
+
const tasks = chunks.map((chunk, i) => buildTask(chunk, i));
|
|
21930
|
+
const outcomes = await maybeTransaction(
|
|
21931
|
+
session,
|
|
21932
|
+
transactional,
|
|
21933
|
+
() => runWithConcurrency(tasks, concurrency)
|
|
21934
|
+
);
|
|
21935
|
+
return timing ? aggregateOutcomesWithTimings(outcomes) : aggregateOutcomes(outcomes);
|
|
21936
|
+
}
|
|
21937
|
+
|
|
21938
|
+
// src/bulk/bulk-delete-executor.ts
|
|
21939
|
+
var BulkDeleteExecutor = class extends BulkBaseExecutor {
|
|
21940
|
+
byColumnName;
|
|
21941
|
+
constructor(session, table, ids, options = {}) {
|
|
21942
|
+
super(session, table, ids, options);
|
|
21943
|
+
this.byColumnName = options.by ?? findPrimaryKey(table);
|
|
21944
|
+
}
|
|
21945
|
+
async executeChunk(chunk, _chunkIndex) {
|
|
21946
|
+
const byColumn = this.table.columns[this.byColumnName];
|
|
21947
|
+
if (!byColumn) {
|
|
21948
|
+
throw new Error(
|
|
21949
|
+
`bulkDelete: column "${this.byColumnName}" not found in table "${this.table.name}"`
|
|
21950
|
+
);
|
|
21951
|
+
}
|
|
21952
|
+
const extraWhere = this.options.where;
|
|
21953
|
+
const inExpr = inList(byColumn, chunk);
|
|
21954
|
+
const finalWhere = extraWhere ? and(inExpr, extraWhere) : inExpr;
|
|
21955
|
+
const builder = new DeleteQueryBuilder(this.table).where(finalWhere);
|
|
21956
|
+
const compiled = builder.compile(this.ctx.dialect);
|
|
21957
|
+
await executeCompiled(this.ctx, compiled);
|
|
21958
|
+
return {
|
|
21959
|
+
processedRows: chunk.length,
|
|
21960
|
+
returning: [],
|
|
21961
|
+
elapsedMs: 0
|
|
21962
|
+
};
|
|
21963
|
+
}
|
|
21964
|
+
};
|
|
21965
|
+
async function bulkDelete(session, table, ids, options = {}) {
|
|
21966
|
+
if (!ids.length) {
|
|
21967
|
+
return { processedRows: 0, chunksExecuted: 0, returning: [] };
|
|
21968
|
+
}
|
|
21969
|
+
const executor = new BulkDeleteExecutor(session, table, ids, options);
|
|
21970
|
+
return executor.execute();
|
|
21971
|
+
}
|
|
21972
|
+
async function bulkDeleteWhere(session, table, where, options = {}) {
|
|
21973
|
+
const { transactional = false } = options;
|
|
21974
|
+
const ctx = createBulkExecutionContext(session);
|
|
21975
|
+
const builder = new DeleteQueryBuilder(table).where(where);
|
|
21976
|
+
const compiled = builder.compile(ctx.dialect);
|
|
21977
|
+
const execute = async () => {
|
|
21978
|
+
await executeCompiled(ctx, compiled);
|
|
21979
|
+
return { processedRows: 0, chunksExecuted: 1, returning: [] };
|
|
21980
|
+
};
|
|
21981
|
+
return maybeTransaction(session, transactional, execute);
|
|
21982
|
+
}
|
|
21983
|
+
|
|
21984
|
+
// src/bulk/bulk-upsert-executor.ts
|
|
21985
|
+
var DEFAULT_CHUNK_SIZE2 = 500;
|
|
21986
|
+
var BulkUpsertExecutor = class extends BulkBaseExecutor {
|
|
21987
|
+
conflictTargetNodes;
|
|
21988
|
+
updateColumns;
|
|
21989
|
+
constructor(session, table, rows, options = {}) {
|
|
21990
|
+
super(session, table, rows, { ...options, chunkSize: options.chunkSize ?? DEFAULT_CHUNK_SIZE2 });
|
|
21991
|
+
const pkName = findPrimaryKey(table);
|
|
21992
|
+
const conflictTargetNames = options.conflictColumns ?? [pkName];
|
|
21993
|
+
this.conflictTargetNodes = conflictTargetNames.map((name) => ({
|
|
21994
|
+
type: "Column",
|
|
21995
|
+
table: table.name,
|
|
21996
|
+
name
|
|
21997
|
+
}));
|
|
21998
|
+
const conflictSet = new Set(conflictTargetNames);
|
|
21999
|
+
this.updateColumns = options.updateColumns ?? Object.keys(rows[0] ?? {}).filter((col2) => !conflictSet.has(col2) && col2 in table.columns);
|
|
22000
|
+
}
|
|
22001
|
+
async executeChunk(chunk, _chunkIndex) {
|
|
22002
|
+
const returningColumns = resolveReturningColumns(this.ctx, this.table, this.options.returning);
|
|
22003
|
+
const set = {};
|
|
22004
|
+
for (const col2 of this.updateColumns) {
|
|
22005
|
+
set[col2] = { type: "ExcludedColumn", name: col2 };
|
|
22006
|
+
}
|
|
22007
|
+
let builder;
|
|
22008
|
+
if (this.updateColumns.length === 0) {
|
|
22009
|
+
builder = new InsertQueryBuilder(this.table).values(chunk).onConflict(this.conflictTargetNodes).doNothing();
|
|
22010
|
+
} else {
|
|
22011
|
+
builder = new InsertQueryBuilder(this.table).values(chunk).onConflict(this.conflictTargetNodes).doUpdate(set);
|
|
22012
|
+
}
|
|
22013
|
+
const finalBuilder = builder;
|
|
22014
|
+
if (returningColumns?.length) {
|
|
22015
|
+
finalBuilder.returning(...returningColumns);
|
|
22016
|
+
}
|
|
22017
|
+
const compiled = finalBuilder.compile(this.ctx.dialect);
|
|
22018
|
+
const resultSets = await executeCompiled(this.ctx, compiled);
|
|
22019
|
+
return {
|
|
22020
|
+
processedRows: chunk.length,
|
|
22021
|
+
returning: returningColumns ? flattenQueryResults(resultSets) : [],
|
|
22022
|
+
elapsedMs: 0
|
|
22023
|
+
};
|
|
22024
|
+
}
|
|
22025
|
+
};
|
|
22026
|
+
async function bulkUpsert(session, table, rows, options = {}) {
|
|
22027
|
+
if (!rows.length) {
|
|
22028
|
+
return { processedRows: 0, chunksExecuted: 0, returning: [] };
|
|
22029
|
+
}
|
|
22030
|
+
const executor = new BulkUpsertExecutor(session, table, rows, options);
|
|
22031
|
+
return executor.execute();
|
|
22032
|
+
}
|
|
20090
22033
|
// Annotate the CommonJS export names for ESM import in node:
|
|
20091
22034
|
0 && (module.exports = {
|
|
20092
22035
|
Alphanumeric,
|
|
@@ -20096,6 +22039,10 @@ var TagIndex = class {
|
|
|
20096
22039
|
BigIntTypeStrategy,
|
|
20097
22040
|
BinaryTypeStrategy,
|
|
20098
22041
|
BooleanTypeStrategy,
|
|
22042
|
+
BulkDeleteExecutor,
|
|
22043
|
+
BulkInsertExecutor,
|
|
22044
|
+
BulkUpdateExecutor,
|
|
22045
|
+
BulkUpsertExecutor,
|
|
20099
22046
|
CEP,
|
|
20100
22047
|
CNPJ,
|
|
20101
22048
|
CPF,
|
|
@@ -20111,6 +22058,9 @@ var TagIndex = class {
|
|
|
20111
22058
|
DefaultEntityMaterializer,
|
|
20112
22059
|
DefaultHasManyCollection,
|
|
20113
22060
|
DefaultManyToManyCollection,
|
|
22061
|
+
DefaultMorphManyCollection,
|
|
22062
|
+
DefaultMorphOneReference,
|
|
22063
|
+
DefaultMorphToReference,
|
|
20114
22064
|
DefaultTypeStrategy,
|
|
20115
22065
|
DeleteQueryBuilder,
|
|
20116
22066
|
DomainEventBus,
|
|
@@ -20126,6 +22076,9 @@ var TagIndex = class {
|
|
|
20126
22076
|
Length,
|
|
20127
22077
|
Lower,
|
|
20128
22078
|
MemoryCacheAdapter,
|
|
22079
|
+
MorphMany,
|
|
22080
|
+
MorphOne,
|
|
22081
|
+
MorphTo,
|
|
20129
22082
|
MySqlDialect,
|
|
20130
22083
|
NestedSetStrategy,
|
|
20131
22084
|
Orm,
|
|
@@ -20184,6 +22137,12 @@ var TagIndex = class {
|
|
|
20184
22137
|
bootstrapEntities,
|
|
20185
22138
|
buildFilterExpression,
|
|
20186
22139
|
buildScopeConditions,
|
|
22140
|
+
bulkDelete,
|
|
22141
|
+
bulkDeleteWhere,
|
|
22142
|
+
bulkInsert,
|
|
22143
|
+
bulkUpdate,
|
|
22144
|
+
bulkUpdateWhere,
|
|
22145
|
+
bulkUpsert,
|
|
20187
22146
|
calculateRowDepths,
|
|
20188
22147
|
calculateTotalPages,
|
|
20189
22148
|
callProcedure,
|
|
@@ -20216,6 +22175,7 @@ var TagIndex = class {
|
|
|
20216
22175
|
count,
|
|
20217
22176
|
countAll,
|
|
20218
22177
|
createApiComponentsSection,
|
|
22178
|
+
createBetterSqlite3Executor,
|
|
20219
22179
|
createDeterministicNamingState,
|
|
20220
22180
|
createDtoToOpenApiSchema,
|
|
20221
22181
|
createEntityFromRow,
|
|
@@ -20317,12 +22277,16 @@ var TagIndex = class {
|
|
|
20317
22277
|
isCastExpressionNode,
|
|
20318
22278
|
isCollateExpressionNode,
|
|
20319
22279
|
isComponentReference,
|
|
22280
|
+
isDistinctFrom,
|
|
20320
22281
|
isExpressionSelectionNode,
|
|
20321
22282
|
isFunctionNode,
|
|
22283
|
+
isMorphRelation,
|
|
22284
|
+
isNotDistinctFrom,
|
|
20322
22285
|
isNotNull,
|
|
20323
22286
|
isNull,
|
|
20324
22287
|
isNullableColumn,
|
|
20325
22288
|
isOperandNode,
|
|
22289
|
+
isSingleTargetRelation,
|
|
20326
22290
|
isTableDef,
|
|
20327
22291
|
isTreeConfig,
|
|
20328
22292
|
isValidDuration,
|
|
@@ -20346,6 +22310,9 @@ var TagIndex = class {
|
|
|
20346
22310
|
loadBelongsToRelation,
|
|
20347
22311
|
loadHasManyRelation,
|
|
20348
22312
|
loadHasOneRelation,
|
|
22313
|
+
loadMorphManyRelation,
|
|
22314
|
+
loadMorphOneRelation,
|
|
22315
|
+
loadMorphToRelation,
|
|
20349
22316
|
localTime,
|
|
20350
22317
|
localTimestamp,
|
|
20351
22318
|
locate,
|
|
@@ -20367,11 +22334,15 @@ var TagIndex = class {
|
|
|
20367
22334
|
minute,
|
|
20368
22335
|
mod,
|
|
20369
22336
|
month,
|
|
22337
|
+
morphMany,
|
|
22338
|
+
morphOne,
|
|
22339
|
+
morphTo,
|
|
20370
22340
|
mul,
|
|
20371
22341
|
neq,
|
|
20372
22342
|
nestedDtoToOpenApiSchema,
|
|
20373
22343
|
nestedWhereInputToOpenApiSchema,
|
|
20374
22344
|
normalizeColumnType,
|
|
22345
|
+
not,
|
|
20375
22346
|
notBetween,
|
|
20376
22347
|
notExists,
|
|
20377
22348
|
notInList,
|