@warlock.js/cascade 4.0.92 → 4.0.93
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/cjs/contracts/database-driver.contract.d.ts +118 -0
- package/cjs/contracts/database-driver.contract.d.ts.map +1 -1
- package/cjs/contracts/migration-driver.contract.d.ts +14 -0
- package/cjs/contracts/migration-driver.contract.d.ts.map +1 -1
- package/cjs/contracts/query-builder.contract.d.ts +410 -1
- package/cjs/contracts/query-builder.contract.d.ts.map +1 -1
- package/cjs/data-source/data-source-registry.d.ts +4 -0
- package/cjs/data-source/data-source-registry.d.ts.map +1 -1
- package/cjs/data-source/data-source-registry.js +7 -0
- package/cjs/data-source/data-source-registry.js.map +1 -1
- package/cjs/drivers/mongodb/mongodb-blueprint.d.ts.map +1 -0
- package/cjs/drivers/mongodb/mongodb-blueprint.js.map +1 -0
- package/{esm/drivers/mongo → cjs/drivers/mongodb}/mongodb-driver.d.ts +49 -0
- package/cjs/drivers/mongodb/mongodb-driver.d.ts.map +1 -0
- package/cjs/drivers/{mongo → mongodb}/mongodb-driver.js +125 -8
- package/cjs/drivers/mongodb/mongodb-driver.js.map +1 -0
- package/cjs/drivers/{mongo/mongo-id-generator.d.ts → mongodb/mongodb-id-generator.d.ts} +1 -1
- package/cjs/drivers/mongodb/mongodb-id-generator.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-id-generator.js → mongodb/mongodb-id-generator.js} +1 -1
- package/cjs/drivers/mongodb/mongodb-id-generator.js.map +1 -0
- package/cjs/drivers/{mongo/mongo-migration-driver.d.ts → mongodb/mongodb-migration-driver.d.ts} +10 -1
- package/cjs/drivers/mongodb/mongodb-migration-driver.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-migration-driver.js → mongodb/mongodb-migration-driver.js} +18 -1
- package/cjs/drivers/mongodb/mongodb-migration-driver.js.map +1 -0
- package/cjs/drivers/{mongo/mongo-query-builder.d.ts → mongodb/mongodb-query-builder.d.ts} +172 -4
- package/cjs/drivers/mongodb/mongodb-query-builder.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-query-builder.js → mongodb/mongodb-query-builder.js} +220 -14
- package/cjs/drivers/mongodb/mongodb-query-builder.js.map +1 -0
- package/{esm/drivers/mongo/mongo-query-operations.d.ts → cjs/drivers/mongodb/mongodb-query-operations.d.ts} +16 -16
- package/cjs/drivers/mongodb/mongodb-query-operations.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-query-operations.js → mongodb/mongodb-query-operations.js} +22 -22
- package/cjs/drivers/mongodb/mongodb-query-operations.js.map +1 -0
- package/cjs/drivers/{mongo/mongo-query-parser.d.ts → mongodb/mongodb-query-parser.d.ts} +2 -2
- package/cjs/drivers/mongodb/mongodb-query-parser.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-query-parser.js → mongodb/mongodb-query-parser.js} +87 -87
- package/cjs/drivers/mongodb/mongodb-query-parser.js.map +1 -0
- package/cjs/drivers/{mongo/mongo-sync-adapter.d.ts → mongodb/mongodb-sync-adapter.d.ts} +2 -2
- package/cjs/drivers/mongodb/mongodb-sync-adapter.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-sync-adapter.js → mongodb/mongodb-sync-adapter.js} +2 -2
- package/cjs/drivers/mongodb/mongodb-sync-adapter.js.map +1 -0
- package/{esm/drivers/mongo → cjs/drivers/mongodb}/types.d.ts +2 -2
- package/cjs/drivers/mongodb/types.d.ts.map +1 -0
- package/cjs/drivers/postgres/index.d.ts +16 -0
- package/cjs/drivers/postgres/index.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-blueprint.d.ts +64 -0
- package/cjs/drivers/postgres/postgres-blueprint.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-blueprint.js +121 -0
- package/cjs/drivers/postgres/postgres-blueprint.js.map +1 -0
- package/cjs/drivers/postgres/postgres-dialect.d.ts +135 -0
- package/cjs/drivers/postgres/postgres-dialect.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-dialect.js +245 -0
- package/cjs/drivers/postgres/postgres-dialect.js.map +1 -0
- package/cjs/drivers/postgres/postgres-driver.d.ts +360 -0
- package/cjs/drivers/postgres/postgres-driver.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-driver.js +763 -0
- package/cjs/drivers/postgres/postgres-driver.js.map +1 -0
- package/cjs/drivers/postgres/postgres-migration-driver.d.ts +297 -0
- package/cjs/drivers/postgres/postgres-migration-driver.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-migration-driver.js +578 -0
- package/cjs/drivers/postgres/postgres-migration-driver.js.map +1 -0
- package/cjs/drivers/postgres/postgres-query-builder.d.ts +824 -0
- package/cjs/drivers/postgres/postgres-query-builder.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-query-builder.js +1800 -0
- package/cjs/drivers/postgres/postgres-query-builder.js.map +1 -0
- package/cjs/drivers/postgres/postgres-query-parser.d.ts +308 -0
- package/cjs/drivers/postgres/postgres-query-parser.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-query-parser.js +706 -0
- package/cjs/drivers/postgres/postgres-query-parser.js.map +1 -0
- package/cjs/drivers/postgres/postgres-sync-adapter.d.ts +83 -0
- package/cjs/drivers/postgres/postgres-sync-adapter.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-sync-adapter.js +197 -0
- package/cjs/drivers/postgres/postgres-sync-adapter.js.map +1 -0
- package/cjs/drivers/postgres/types.d.ts +142 -0
- package/cjs/drivers/postgres/types.d.ts.map +1 -0
- package/cjs/drivers/sql/index.d.ts +10 -0
- package/cjs/drivers/sql/index.d.ts.map +1 -0
- package/cjs/drivers/sql/sql-dialect.contract.d.ts +203 -0
- package/cjs/drivers/sql/sql-dialect.contract.d.ts.map +1 -0
- package/cjs/drivers/sql/sql-types.d.ts +202 -0
- package/cjs/drivers/sql/sql-types.d.ts.map +1 -0
- package/cjs/index.d.ts +9 -6
- package/cjs/index.d.ts.map +1 -1
- package/cjs/index.js +1 -1
- package/cjs/migration/migration-runner.d.ts.map +1 -1
- package/cjs/migration/migration-runner.js +3 -0
- package/cjs/migration/migration-runner.js.map +1 -1
- package/cjs/model/model.d.ts +236 -1
- package/cjs/model/model.d.ts.map +1 -1
- package/cjs/model/model.js +203 -4
- package/cjs/model/model.js.map +1 -1
- package/cjs/relations/helpers.d.ts +156 -0
- package/cjs/relations/helpers.d.ts.map +1 -0
- package/cjs/relations/helpers.js +197 -0
- package/cjs/relations/helpers.js.map +1 -0
- package/cjs/relations/index.d.ts +33 -0
- package/cjs/relations/index.d.ts.map +1 -0
- package/cjs/relations/pivot-operations.d.ts +160 -0
- package/cjs/relations/pivot-operations.d.ts.map +1 -0
- package/cjs/relations/pivot-operations.js +293 -0
- package/cjs/relations/pivot-operations.js.map +1 -0
- package/cjs/relations/relation-loader.d.ts +194 -0
- package/cjs/relations/relation-loader.d.ts.map +1 -0
- package/cjs/relations/relation-loader.js +466 -0
- package/cjs/relations/relation-loader.js.map +1 -0
- package/cjs/relations/types.d.ts +280 -0
- package/cjs/relations/types.d.ts.map +1 -0
- package/cjs/sync/model-sync-operation.js +1 -1
- package/cjs/sync/model-sync-operation.js.map +1 -1
- package/cjs/utils/connect-to-database.d.ts.map +1 -1
- package/cjs/utils/connect-to-database.js +15 -3
- package/cjs/utils/connect-to-database.js.map +1 -1
- package/cjs/utils/define-model.d.ts +51 -29
- package/cjs/utils/define-model.d.ts.map +1 -1
- package/cjs/validation/rules/database-model-rule.js +1 -1
- package/cjs/validation/rules/database-model-rule.js.map +1 -1
- package/esm/contracts/database-driver.contract.d.ts +118 -0
- package/esm/contracts/database-driver.contract.d.ts.map +1 -1
- package/esm/contracts/migration-driver.contract.d.ts +14 -0
- package/esm/contracts/migration-driver.contract.d.ts.map +1 -1
- package/esm/contracts/query-builder.contract.d.ts +410 -1
- package/esm/contracts/query-builder.contract.d.ts.map +1 -1
- package/esm/data-source/data-source-registry.d.ts +4 -0
- package/esm/data-source/data-source-registry.d.ts.map +1 -1
- package/esm/data-source/data-source-registry.js +7 -0
- package/esm/data-source/data-source-registry.js.map +1 -1
- package/esm/drivers/mongodb/mongodb-blueprint.d.ts.map +1 -0
- package/esm/drivers/mongodb/mongodb-blueprint.js.map +1 -0
- package/{cjs/drivers/mongo → esm/drivers/mongodb}/mongodb-driver.d.ts +49 -0
- package/esm/drivers/mongodb/mongodb-driver.d.ts.map +1 -0
- package/esm/drivers/{mongo → mongodb}/mongodb-driver.js +121 -4
- package/esm/drivers/mongodb/mongodb-driver.js.map +1 -0
- package/esm/drivers/{mongo/mongo-id-generator.d.ts → mongodb/mongodb-id-generator.d.ts} +1 -1
- package/esm/drivers/mongodb/mongodb-id-generator.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-id-generator.js → mongodb/mongodb-id-generator.js} +1 -1
- package/esm/drivers/mongodb/mongodb-id-generator.js.map +1 -0
- package/esm/drivers/{mongo/mongo-migration-driver.d.ts → mongodb/mongodb-migration-driver.d.ts} +10 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-migration-driver.js → mongodb/mongodb-migration-driver.js} +18 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.js.map +1 -0
- package/esm/drivers/{mongo/mongo-query-builder.d.ts → mongodb/mongodb-query-builder.d.ts} +172 -4
- package/esm/drivers/mongodb/mongodb-query-builder.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-query-builder.js → mongodb/mongodb-query-builder.js} +218 -12
- package/esm/drivers/mongodb/mongodb-query-builder.js.map +1 -0
- package/{cjs/drivers/mongo/mongo-query-operations.d.ts → esm/drivers/mongodb/mongodb-query-operations.d.ts} +16 -16
- package/esm/drivers/mongodb/mongodb-query-operations.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-query-operations.js → mongodb/mongodb-query-operations.js} +22 -22
- package/esm/drivers/mongodb/mongodb-query-operations.js.map +1 -0
- package/esm/drivers/{mongo/mongo-query-parser.d.ts → mongodb/mongodb-query-parser.d.ts} +2 -2
- package/esm/drivers/mongodb/mongodb-query-parser.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-query-parser.js → mongodb/mongodb-query-parser.js} +87 -87
- package/esm/drivers/mongodb/mongodb-query-parser.js.map +1 -0
- package/esm/drivers/{mongo/mongo-sync-adapter.d.ts → mongodb/mongodb-sync-adapter.d.ts} +2 -2
- package/esm/drivers/mongodb/mongodb-sync-adapter.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-sync-adapter.js → mongodb/mongodb-sync-adapter.js} +2 -2
- package/esm/drivers/mongodb/mongodb-sync-adapter.js.map +1 -0
- package/{cjs/drivers/mongo → esm/drivers/mongodb}/types.d.ts +2 -2
- package/esm/drivers/mongodb/types.d.ts.map +1 -0
- package/esm/drivers/postgres/index.d.ts +16 -0
- package/esm/drivers/postgres/index.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-blueprint.d.ts +64 -0
- package/esm/drivers/postgres/postgres-blueprint.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-blueprint.js +121 -0
- package/esm/drivers/postgres/postgres-blueprint.js.map +1 -0
- package/esm/drivers/postgres/postgres-dialect.d.ts +135 -0
- package/esm/drivers/postgres/postgres-dialect.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-dialect.js +245 -0
- package/esm/drivers/postgres/postgres-dialect.js.map +1 -0
- package/esm/drivers/postgres/postgres-driver.d.ts +360 -0
- package/esm/drivers/postgres/postgres-driver.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-driver.js +763 -0
- package/esm/drivers/postgres/postgres-driver.js.map +1 -0
- package/esm/drivers/postgres/postgres-migration-driver.d.ts +297 -0
- package/esm/drivers/postgres/postgres-migration-driver.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-migration-driver.js +578 -0
- package/esm/drivers/postgres/postgres-migration-driver.js.map +1 -0
- package/esm/drivers/postgres/postgres-query-builder.d.ts +824 -0
- package/esm/drivers/postgres/postgres-query-builder.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-query-builder.js +1800 -0
- package/esm/drivers/postgres/postgres-query-builder.js.map +1 -0
- package/esm/drivers/postgres/postgres-query-parser.d.ts +308 -0
- package/esm/drivers/postgres/postgres-query-parser.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-query-parser.js +706 -0
- package/esm/drivers/postgres/postgres-query-parser.js.map +1 -0
- package/esm/drivers/postgres/postgres-sync-adapter.d.ts +83 -0
- package/esm/drivers/postgres/postgres-sync-adapter.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-sync-adapter.js +197 -0
- package/esm/drivers/postgres/postgres-sync-adapter.js.map +1 -0
- package/esm/drivers/postgres/types.d.ts +142 -0
- package/esm/drivers/postgres/types.d.ts.map +1 -0
- package/esm/drivers/sql/index.d.ts +10 -0
- package/esm/drivers/sql/index.d.ts.map +1 -0
- package/esm/drivers/sql/sql-dialect.contract.d.ts +203 -0
- package/esm/drivers/sql/sql-dialect.contract.d.ts.map +1 -0
- package/esm/drivers/sql/sql-types.d.ts +202 -0
- package/esm/drivers/sql/sql-types.d.ts.map +1 -0
- package/esm/index.d.ts +9 -6
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/migration/migration-runner.d.ts.map +1 -1
- package/esm/migration/migration-runner.js +3 -0
- package/esm/migration/migration-runner.js.map +1 -1
- package/esm/model/model.d.ts +236 -1
- package/esm/model/model.d.ts.map +1 -1
- package/esm/model/model.js +203 -4
- package/esm/model/model.js.map +1 -1
- package/esm/relations/helpers.d.ts +156 -0
- package/esm/relations/helpers.d.ts.map +1 -0
- package/esm/relations/helpers.js +197 -0
- package/esm/relations/helpers.js.map +1 -0
- package/esm/relations/index.d.ts +33 -0
- package/esm/relations/index.d.ts.map +1 -0
- package/esm/relations/pivot-operations.d.ts +160 -0
- package/esm/relations/pivot-operations.d.ts.map +1 -0
- package/esm/relations/pivot-operations.js +293 -0
- package/esm/relations/pivot-operations.js.map +1 -0
- package/esm/relations/relation-loader.d.ts +194 -0
- package/esm/relations/relation-loader.d.ts.map +1 -0
- package/esm/relations/relation-loader.js +466 -0
- package/esm/relations/relation-loader.js.map +1 -0
- package/esm/relations/types.d.ts +280 -0
- package/esm/relations/types.d.ts.map +1 -0
- package/esm/sync/model-sync-operation.js +1 -1
- package/esm/sync/model-sync-operation.js.map +1 -1
- package/esm/utils/connect-to-database.d.ts.map +1 -1
- package/esm/utils/connect-to-database.js +15 -3
- package/esm/utils/connect-to-database.js.map +1 -1
- package/esm/utils/define-model.d.ts +51 -29
- package/esm/utils/define-model.d.ts.map +1 -1
- package/esm/validation/rules/database-model-rule.js +1 -1
- package/esm/validation/rules/database-model-rule.js.map +1 -1
- package/package.json +4 -4
- package/cjs/drivers/mongo/mongo-id-generator.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-id-generator.js.map +0 -1
- package/cjs/drivers/mongo/mongo-migration-driver.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-migration-driver.js.map +0 -1
- package/cjs/drivers/mongo/mongo-query-builder.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-query-builder.js.map +0 -1
- package/cjs/drivers/mongo/mongo-query-operations.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-query-operations.js.map +0 -1
- package/cjs/drivers/mongo/mongo-query-parser.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-query-parser.js.map +0 -1
- package/cjs/drivers/mongo/mongo-sync-adapter.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-sync-adapter.js.map +0 -1
- package/cjs/drivers/mongo/mongodb-blueprint.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongodb-blueprint.js.map +0 -1
- package/cjs/drivers/mongo/mongodb-driver.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongodb-driver.js.map +0 -1
- package/cjs/drivers/mongo/types.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-id-generator.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-id-generator.js.map +0 -1
- package/esm/drivers/mongo/mongo-migration-driver.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-migration-driver.js.map +0 -1
- package/esm/drivers/mongo/mongo-query-builder.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-query-builder.js.map +0 -1
- package/esm/drivers/mongo/mongo-query-operations.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-query-operations.js.map +0 -1
- package/esm/drivers/mongo/mongo-query-parser.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-query-parser.js.map +0 -1
- package/esm/drivers/mongo/mongo-sync-adapter.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-sync-adapter.js.map +0 -1
- package/esm/drivers/mongo/mongodb-blueprint.d.ts.map +0 -1
- package/esm/drivers/mongo/mongodb-blueprint.js.map +0 -1
- package/esm/drivers/mongo/mongodb-driver.d.ts.map +0 -1
- package/esm/drivers/mongo/mongodb-driver.js.map +0 -1
- package/esm/drivers/mongo/types.d.ts.map +0 -1
- /package/cjs/drivers/{mongo → mongodb}/mongodb-blueprint.d.ts +0 -0
- /package/cjs/drivers/{mongo → mongodb}/mongodb-blueprint.js +0 -0
- /package/esm/drivers/{mongo → mongodb}/mongodb-blueprint.d.ts +0 -0
- /package/esm/drivers/{mongo → mongodb}/mongodb-blueprint.js +0 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pivot table operations for many-to-many relationships.
|
|
3
|
+
*
|
|
4
|
+
* This module provides methods for managing the pivot table in
|
|
5
|
+
* belongsToMany relationships: attach, detach, sync, and toggle.
|
|
6
|
+
*
|
|
7
|
+
* @module @warlock.js/cascade/relations/pivot-operations
|
|
8
|
+
*/
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// PIVOT OPERATIONS CLASS
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Manages pivot table operations for many-to-many relationships.
|
|
14
|
+
*
|
|
15
|
+
* Provides attach, detach, sync, and toggle operations for managing
|
|
16
|
+
* the connections between two models through a pivot table.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const pivotOps = new PivotOperations(post, "tags", tagsDefinition);
|
|
21
|
+
*
|
|
22
|
+
* // Attach tags
|
|
23
|
+
* await pivotOps.attach([1, 2, 3]);
|
|
24
|
+
*
|
|
25
|
+
* // Attach with pivot data
|
|
26
|
+
* await pivotOps.attach([4], { addedBy: userId });
|
|
27
|
+
*
|
|
28
|
+
* // Detach specific tags
|
|
29
|
+
* await pivotOps.detach([2]);
|
|
30
|
+
*
|
|
31
|
+
* // Sync (replace all)
|
|
32
|
+
* await pivotOps.sync([1, 5, 6]);
|
|
33
|
+
*
|
|
34
|
+
* // Toggle (attach if missing, detach if present)
|
|
35
|
+
* await pivotOps.toggle([1, 7]);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
class PivotOperations {
|
|
39
|
+
// ==========================================================================
|
|
40
|
+
// PRIVATE PROPERTIES
|
|
41
|
+
// ==========================================================================
|
|
42
|
+
/**
|
|
43
|
+
* The model instance performing the pivot operation.
|
|
44
|
+
*/
|
|
45
|
+
model;
|
|
46
|
+
/**
|
|
47
|
+
* The name of the relation.
|
|
48
|
+
*/
|
|
49
|
+
relationName;
|
|
50
|
+
/**
|
|
51
|
+
* The relation definition with pivot table configuration.
|
|
52
|
+
*/
|
|
53
|
+
definition;
|
|
54
|
+
/**
|
|
55
|
+
* The model class of the source model.
|
|
56
|
+
*/
|
|
57
|
+
modelClass;
|
|
58
|
+
// ==========================================================================
|
|
59
|
+
// CONSTRUCTOR
|
|
60
|
+
// ==========================================================================
|
|
61
|
+
/**
|
|
62
|
+
* Creates a new PivotOperations instance.
|
|
63
|
+
*
|
|
64
|
+
* @param model - The model instance performing the operation
|
|
65
|
+
* @param relationName - The name of the belongsToMany relation
|
|
66
|
+
* @param definition - The relation definition
|
|
67
|
+
* @param modelClass - The model class constructor
|
|
68
|
+
*/
|
|
69
|
+
constructor(model, relationName, definition, modelClass) {
|
|
70
|
+
if (definition.type !== "belongsToMany") {
|
|
71
|
+
throw new Error(`Pivot operations are only available for belongsToMany relations. ` +
|
|
72
|
+
`Relation "${relationName}" is of type "${definition.type}".`);
|
|
73
|
+
}
|
|
74
|
+
if (!definition.pivot) {
|
|
75
|
+
throw new Error(`Relation "${relationName}" is missing the pivot table configuration.`);
|
|
76
|
+
}
|
|
77
|
+
this.model = model;
|
|
78
|
+
this.relationName = relationName;
|
|
79
|
+
this.definition = definition;
|
|
80
|
+
this.modelClass = modelClass;
|
|
81
|
+
}
|
|
82
|
+
// ==========================================================================
|
|
83
|
+
// PUBLIC METHODS
|
|
84
|
+
// ==========================================================================
|
|
85
|
+
/**
|
|
86
|
+
* Attaches one or more related models via the pivot table.
|
|
87
|
+
*
|
|
88
|
+
* Creates new records in the pivot table linking this model to the
|
|
89
|
+
* specified related model IDs. Existing attachments are not duplicated.
|
|
90
|
+
*
|
|
91
|
+
* @param ids - The IDs of the related models to attach
|
|
92
|
+
* @param pivotData - Optional additional data to store in the pivot record
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* // Attach tags to a post
|
|
97
|
+
* await post.attach("tags", [1, 2, 3]);
|
|
98
|
+
*
|
|
99
|
+
* // Attach with additional pivot data
|
|
100
|
+
* await post.attach("tags", [4], { addedBy: currentUserId });
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
async attach(ids, pivotData) {
|
|
104
|
+
if (ids.length === 0)
|
|
105
|
+
return;
|
|
106
|
+
const { pivotTable, localKeyValue, pivotLocalKey, pivotForeignKey } = this.getPivotConfig();
|
|
107
|
+
// Get existing attachments to avoid duplicates
|
|
108
|
+
const existingIds = await this.getExistingPivotIds();
|
|
109
|
+
const newIds = ids.filter((id) => !existingIds.has(id));
|
|
110
|
+
if (newIds.length === 0)
|
|
111
|
+
return;
|
|
112
|
+
// Create pivot records
|
|
113
|
+
const records = newIds.map((id) => ({
|
|
114
|
+
[pivotLocalKey]: localKeyValue,
|
|
115
|
+
[pivotForeignKey]: id,
|
|
116
|
+
...pivotData,
|
|
117
|
+
}));
|
|
118
|
+
const dataSource = this.modelClass.getDataSource();
|
|
119
|
+
await dataSource.driver.insertMany(pivotTable, records);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Detaches one or more related models from the pivot table.
|
|
123
|
+
*
|
|
124
|
+
* Removes records from the pivot table. If no IDs are specified,
|
|
125
|
+
* all attachments for this model are removed.
|
|
126
|
+
*
|
|
127
|
+
* @param ids - Optional IDs to detach. If omitted, detaches all.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```typescript
|
|
131
|
+
* // Detach specific tags
|
|
132
|
+
* await post.detach("tags", [2, 3]);
|
|
133
|
+
*
|
|
134
|
+
* // Detach all tags
|
|
135
|
+
* await post.detach("tags");
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
async detach(ids) {
|
|
139
|
+
const { pivotTable, localKeyValue, pivotLocalKey, pivotForeignKey } = this.getPivotConfig();
|
|
140
|
+
const dataSource = this.modelClass.getDataSource();
|
|
141
|
+
// Build filter based on local key and optionally foreign keys
|
|
142
|
+
const filter = { [pivotLocalKey]: localKeyValue };
|
|
143
|
+
if (ids && ids.length > 0) {
|
|
144
|
+
// Use $in operator style for filtering by multiple IDs
|
|
145
|
+
filter[pivotForeignKey] = { $in: ids };
|
|
146
|
+
}
|
|
147
|
+
await dataSource.driver.deleteMany(pivotTable, filter);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Synchronizes the pivot table to match the specified IDs.
|
|
151
|
+
*
|
|
152
|
+
* Attaches any new IDs and detaches any IDs not in the list.
|
|
153
|
+
* After sync, the pivot table will contain exactly the specified IDs.
|
|
154
|
+
*
|
|
155
|
+
* @param ids - The IDs that should be attached after sync
|
|
156
|
+
* @param pivotData - Optional data for newly attached records
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* // Set tags to exactly [1, 3, 5], removing any others
|
|
161
|
+
* await post.sync("tags", [1, 3, 5]);
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
async sync(ids, pivotData) {
|
|
165
|
+
const existingIds = await this.getExistingPivotIds();
|
|
166
|
+
const newIdSet = new Set(ids);
|
|
167
|
+
// Find IDs to detach (in existing but not in new)
|
|
168
|
+
const toDetach = [];
|
|
169
|
+
for (const existingId of existingIds) {
|
|
170
|
+
if (!newIdSet.has(existingId)) {
|
|
171
|
+
toDetach.push(existingId);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Find IDs to attach (in new but not in existing)
|
|
175
|
+
const toAttach = ids.filter((id) => !existingIds.has(id));
|
|
176
|
+
// Perform operations
|
|
177
|
+
if (toDetach.length > 0) {
|
|
178
|
+
await this.detach(toDetach);
|
|
179
|
+
}
|
|
180
|
+
if (toAttach.length > 0) {
|
|
181
|
+
await this.attach(toAttach, pivotData);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Toggles the attachment status of the specified IDs.
|
|
186
|
+
*
|
|
187
|
+
* For each ID: if attached, detaches it; if not attached, attaches it.
|
|
188
|
+
*
|
|
189
|
+
* @param ids - The IDs to toggle
|
|
190
|
+
* @param pivotData - Optional data for newly attached records
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* // Toggle tags - attached become detached, detached become attached
|
|
195
|
+
* await post.toggle("tags", [1, 4]);
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
async toggle(ids, pivotData) {
|
|
199
|
+
if (ids.length === 0)
|
|
200
|
+
return;
|
|
201
|
+
const existingIds = await this.getExistingPivotIds();
|
|
202
|
+
const toAttach = [];
|
|
203
|
+
const toDetach = [];
|
|
204
|
+
for (const id of ids) {
|
|
205
|
+
if (existingIds.has(id)) {
|
|
206
|
+
toDetach.push(id);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
toAttach.push(id);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (toDetach.length > 0) {
|
|
213
|
+
await this.detach(toDetach);
|
|
214
|
+
}
|
|
215
|
+
if (toAttach.length > 0) {
|
|
216
|
+
await this.attach(toAttach, pivotData);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// ==========================================================================
|
|
220
|
+
// PRIVATE METHODS
|
|
221
|
+
// ==========================================================================
|
|
222
|
+
/**
|
|
223
|
+
* Gets the pivot table configuration.
|
|
224
|
+
*
|
|
225
|
+
* @returns The pivot configuration object
|
|
226
|
+
*/
|
|
227
|
+
getPivotConfig() {
|
|
228
|
+
const pivotTable = this.definition.pivot;
|
|
229
|
+
const localKey = this.definition.pivotLocalKey ?? "id";
|
|
230
|
+
const pivotLocalKey = this.definition.localKey ?? this.inferForeignKey(this.modelClass.name);
|
|
231
|
+
const pivotForeignKey = this.definition.foreignKey ?? this.inferForeignKey(this.definition.model);
|
|
232
|
+
const relatedKey = this.definition.pivotForeignKey ?? "id";
|
|
233
|
+
const localKeyValue = this.model.get(localKey);
|
|
234
|
+
return {
|
|
235
|
+
pivotTable,
|
|
236
|
+
localKeyValue,
|
|
237
|
+
pivotLocalKey,
|
|
238
|
+
pivotForeignKey,
|
|
239
|
+
relatedKey,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Gets all currently attached IDs from the pivot table.
|
|
244
|
+
*
|
|
245
|
+
* @returns A set of attached foreign key values
|
|
246
|
+
*/
|
|
247
|
+
async getExistingPivotIds() {
|
|
248
|
+
const { pivotTable, localKeyValue, pivotLocalKey, pivotForeignKey } = this.getPivotConfig();
|
|
249
|
+
const dataSource = this.modelClass.getDataSource();
|
|
250
|
+
const records = await dataSource.driver
|
|
251
|
+
.queryBuilder(pivotTable)
|
|
252
|
+
.select([pivotForeignKey])
|
|
253
|
+
.where(pivotLocalKey, localKeyValue)
|
|
254
|
+
.get();
|
|
255
|
+
const ids = new Set();
|
|
256
|
+
for (const record of records) {
|
|
257
|
+
const id = record[pivotForeignKey];
|
|
258
|
+
if (id !== undefined && id !== null) {
|
|
259
|
+
ids.add(id);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return ids;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Infers a foreign key name from a model name.
|
|
266
|
+
*
|
|
267
|
+
* @param modelName - The model class name
|
|
268
|
+
* @returns The inferred foreign key (e.g., "User" -> "userId")
|
|
269
|
+
*/
|
|
270
|
+
inferForeignKey(modelName) {
|
|
271
|
+
return `${modelName.charAt(0).toLowerCase()}${modelName.slice(1)}Id`;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// ============================================================================
|
|
275
|
+
// FACTORY FUNCTION
|
|
276
|
+
// ============================================================================
|
|
277
|
+
/**
|
|
278
|
+
* Creates a PivotOperations instance for a model and relation.
|
|
279
|
+
*
|
|
280
|
+
* @param model - The model instance
|
|
281
|
+
* @param relationName - The name of the belongsToMany relation
|
|
282
|
+
* @returns A PivotOperations instance
|
|
283
|
+
* @throws Error if the relation is not a belongsToMany or not defined
|
|
284
|
+
*/
|
|
285
|
+
function createPivotOperations(model, relationName) {
|
|
286
|
+
const ModelClass = model.constructor;
|
|
287
|
+
const relations = ModelClass
|
|
288
|
+
.relations;
|
|
289
|
+
if (!relations || !relations[relationName]) {
|
|
290
|
+
throw new Error(`Relation "${relationName}" is not defined on model "${ModelClass.name}".`);
|
|
291
|
+
}
|
|
292
|
+
return new PivotOperations(model, relationName, relations[relationName], ModelClass);
|
|
293
|
+
}export{PivotOperations,createPivotOperations};//# sourceMappingURL=pivot-operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pivot-operations.js","sources":["../../src/relations/pivot-operations.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Core relation loading logic for the Cascade ORM.
|
|
3
|
+
*
|
|
4
|
+
* The RelationLoader is responsible for efficiently loading related models
|
|
5
|
+
* while preventing N+1 query problems through batch loading strategies.
|
|
6
|
+
*
|
|
7
|
+
* @module @warlock.js/cascade/relations/relation-loader
|
|
8
|
+
*/
|
|
9
|
+
import type { ChildModel, Model } from "../model/model";
|
|
10
|
+
import type { RelationConstraints } from "./types";
|
|
11
|
+
/**
|
|
12
|
+
* Efficiently loads relationships for one or more model instances.
|
|
13
|
+
*
|
|
14
|
+
* The RelationLoader handles:
|
|
15
|
+
* - Batch loading to prevent N+1 query problems
|
|
16
|
+
* - Nested relation loading via dot notation
|
|
17
|
+
* - Constrained loading with query callbacks
|
|
18
|
+
* - All relation types (hasOne, hasMany, belongsTo, belongsToMany)
|
|
19
|
+
*
|
|
20
|
+
* @template TModel - The type of model being loaded
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const users = await User.query().get();
|
|
25
|
+
* const loader = new RelationLoader(users, User);
|
|
26
|
+
*
|
|
27
|
+
* // Load single relation
|
|
28
|
+
* await loader.load("posts");
|
|
29
|
+
*
|
|
30
|
+
* // Load multiple relations
|
|
31
|
+
* await loader.load(["posts", "organization"]);
|
|
32
|
+
*
|
|
33
|
+
* // Load nested relations
|
|
34
|
+
* await loader.load("posts.comments.author");
|
|
35
|
+
*
|
|
36
|
+
* // Load with constraints
|
|
37
|
+
* await loader.load("posts", {
|
|
38
|
+
* posts: (query) => query.where("isPublished", true),
|
|
39
|
+
* });
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare class RelationLoader<TModel extends Model = Model> {
|
|
43
|
+
/**
|
|
44
|
+
* The model instances to load relations for.
|
|
45
|
+
*/
|
|
46
|
+
private readonly models;
|
|
47
|
+
/**
|
|
48
|
+
* The model class constructor.
|
|
49
|
+
*/
|
|
50
|
+
private readonly modelClass;
|
|
51
|
+
/**
|
|
52
|
+
* Creates a new RelationLoader instance.
|
|
53
|
+
*
|
|
54
|
+
* @param models - The model instances to load relations for
|
|
55
|
+
* @param modelClass - The model class constructor
|
|
56
|
+
*/
|
|
57
|
+
constructor(models: TModel[], modelClass: ChildModel<TModel>);
|
|
58
|
+
/**
|
|
59
|
+
* Loads one or more relations for all model instances.
|
|
60
|
+
*
|
|
61
|
+
* @param relations - A single relation name, array of names, or constraints object
|
|
62
|
+
* @param constraints - Optional constraints to apply to the loading query
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* // Single relation
|
|
67
|
+
* await loader.load("posts");
|
|
68
|
+
*
|
|
69
|
+
* // Multiple relations
|
|
70
|
+
* await loader.load(["posts", "organization"]);
|
|
71
|
+
*
|
|
72
|
+
* // With constraints
|
|
73
|
+
* await loader.load("posts", {
|
|
74
|
+
* posts: (query) => query.where("status", "active"),
|
|
75
|
+
* });
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
load(relations: string | string[], constraints?: RelationConstraints): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Loads a single relation, handling nested relations via dot notation.
|
|
81
|
+
*
|
|
82
|
+
* @param name - The relation name, possibly with dot notation for nesting
|
|
83
|
+
* @param constraint - Optional constraint callback
|
|
84
|
+
*/
|
|
85
|
+
private loadRelation;
|
|
86
|
+
/**
|
|
87
|
+
* Loads a hasMany relation for all models.
|
|
88
|
+
*
|
|
89
|
+
* @param name - The relation name
|
|
90
|
+
* @param definition - The relation definition
|
|
91
|
+
* @param constraint - Optional constraint callback
|
|
92
|
+
*/
|
|
93
|
+
private loadHasMany;
|
|
94
|
+
/**
|
|
95
|
+
* Loads a hasOne relation for all models.
|
|
96
|
+
*
|
|
97
|
+
* @param name - The relation name
|
|
98
|
+
* @param definition - The relation definition
|
|
99
|
+
* @param constraint - Optional constraint callback
|
|
100
|
+
*/
|
|
101
|
+
private loadHasOne;
|
|
102
|
+
/**
|
|
103
|
+
* Loads a belongsTo relation for all models.
|
|
104
|
+
*
|
|
105
|
+
* @param name - The relation name
|
|
106
|
+
* @param definition - The relation definition
|
|
107
|
+
* @param constraint - Optional constraint callback
|
|
108
|
+
*/
|
|
109
|
+
private loadBelongsTo;
|
|
110
|
+
/**
|
|
111
|
+
* Loads a belongsToMany relation for all models.
|
|
112
|
+
*
|
|
113
|
+
* @param name - The relation name
|
|
114
|
+
* @param definition - The relation definition
|
|
115
|
+
* @param constraint - Optional constraint callback
|
|
116
|
+
*/
|
|
117
|
+
private loadBelongsToMany;
|
|
118
|
+
/**
|
|
119
|
+
* Loads nested relations recursively.
|
|
120
|
+
*
|
|
121
|
+
* @param parentRelation - The name of the parent relation
|
|
122
|
+
* @param remainingPath - The remaining path segments to load
|
|
123
|
+
* @param constraint - Optional constraint callback
|
|
124
|
+
*/
|
|
125
|
+
private loadNestedRelations;
|
|
126
|
+
/**
|
|
127
|
+
* Parses a dot-notation relation path into segments.
|
|
128
|
+
*
|
|
129
|
+
* @param path - The relation path (e.g., "posts.comments.author")
|
|
130
|
+
* @returns An array of relation names
|
|
131
|
+
*/
|
|
132
|
+
private parseNestedRelation;
|
|
133
|
+
/**
|
|
134
|
+
* Resolves a model class from the registry by name.
|
|
135
|
+
*
|
|
136
|
+
* @param name - The registered model name
|
|
137
|
+
* @returns The model class constructor
|
|
138
|
+
* @throws Error if the model is not found in the registry
|
|
139
|
+
*/
|
|
140
|
+
private resolveModelClass;
|
|
141
|
+
/**
|
|
142
|
+
* Gets the relation definition from the model class.
|
|
143
|
+
*
|
|
144
|
+
* @param name - The relation name
|
|
145
|
+
* @returns The relation definition or undefined
|
|
146
|
+
*/
|
|
147
|
+
private getRelationDefinition;
|
|
148
|
+
/**
|
|
149
|
+
* Collects unique key values from all models.
|
|
150
|
+
*
|
|
151
|
+
* @param key - The key to collect values for
|
|
152
|
+
* @returns An array of unique key values
|
|
153
|
+
*/
|
|
154
|
+
private collectKeyValues;
|
|
155
|
+
/**
|
|
156
|
+
* Groups records by a key value.
|
|
157
|
+
*
|
|
158
|
+
* @param records - The records to group
|
|
159
|
+
* @param key - The key to group by
|
|
160
|
+
* @returns A map of key values to records
|
|
161
|
+
*/
|
|
162
|
+
private groupBy;
|
|
163
|
+
/**
|
|
164
|
+
* Infers a foreign key name from a model name.
|
|
165
|
+
*
|
|
166
|
+
* @param modelName - The model class name
|
|
167
|
+
* @returns The inferred foreign key (e.g., "User" -> "userId")
|
|
168
|
+
*/
|
|
169
|
+
private inferForeignKey;
|
|
170
|
+
/**
|
|
171
|
+
* Sets a relation value on all models using a getter function.
|
|
172
|
+
*
|
|
173
|
+
* @param name - The relation name
|
|
174
|
+
* @param getter - Function that returns the relation value for each model
|
|
175
|
+
*/
|
|
176
|
+
private setRelationOnModels;
|
|
177
|
+
/**
|
|
178
|
+
* Gets a loaded relation from a model instance.
|
|
179
|
+
*
|
|
180
|
+
* @param model - The model instance
|
|
181
|
+
* @param name - The relation name
|
|
182
|
+
* @returns The loaded relation value or undefined
|
|
183
|
+
*/
|
|
184
|
+
private getLoadedRelation;
|
|
185
|
+
/**
|
|
186
|
+
* Sets a loaded relation on a model instance.
|
|
187
|
+
*
|
|
188
|
+
* @param model - The model instance
|
|
189
|
+
* @param name - The relation name
|
|
190
|
+
* @param value - The relation value
|
|
191
|
+
*/
|
|
192
|
+
private setLoadedRelation;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=relation-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relation-loader.d.ts","sourceRoot":"","sources":["../../src/relations/relation-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,KAAK,EAGV,mBAAmB,EAEpB,MAAM,SAAS,CAAC;AAMjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,cAAc,CAAC,MAAM,SAAS,KAAK,GAAG,KAAK;IAKtD;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAElC;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAMhD;;;;;OAKG;gBACgB,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC;IASnE;;;;;;;;;;;;;;;;;;;OAmBG;IACU,IAAI,CACf,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAC5B,WAAW,CAAC,EAAE,mBAAmB,GAChC,OAAO,CAAC,IAAI,CAAC;IAsBhB;;;;;OAKG;YACW,YAAY;IAuC1B;;;;;;OAMG;YACW,WAAW;IAoCzB;;;;;;OAMG;YACW,UAAU;IA0CxB;;;;;;OAMG;YACW,aAAa;IAuC3B;;;;;;OAMG;YACW,iBAAiB;IAoF/B;;;;;;OAMG;YACW,mBAAmB;IAwCjC;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAO7B;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAaxB;;;;;;OAMG;IACH,OAAO,CAAC,OAAO;IAgBf;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAIvB;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAOzB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;CAe1B"}
|