@fjell/lib-sequelize 4.4.4 → 4.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/AggregationBuilder.cjs +48 -14
- package/dist/cjs/KeyMaster.cjs +33 -11
- package/dist/cjs/OperationContext.cjs +161 -0
- package/dist/cjs/ReferenceBuilder.cjs +47 -5
- package/dist/cjs/RowProcessor.cjs +37 -22
- package/dist/cjs/ops/all.cjs +77 -18
- package/dist/cjs/ops/get.cjs +5 -2
- package/dist/cjs/ops/update.cjs +63 -7
- package/dist/cjs/util/relationshipUtils.cjs +2 -2
- package/dist/es/AggregationBuilder.js +48 -14
- package/dist/es/KeyMaster.js +33 -11
- package/dist/es/OperationContext.js +155 -0
- package/dist/es/ReferenceBuilder.js +47 -5
- package/dist/es/RowProcessor.js +37 -22
- package/dist/es/ops/all.js +77 -18
- package/dist/es/ops/get.js +5 -2
- package/dist/es/ops/update.js +63 -7
- package/dist/es/util/relationshipUtils.js +2 -2
- package/dist/index.cjs +461 -89
- package/dist/index.cjs.map +1 -1
- package/dist/types/AggregationBuilder.d.ts +2 -1
- package/dist/types/EventCoordinator.d.ts +6 -6
- package/dist/types/KeyMaster.d.ts +2 -2
- package/dist/types/OperationContext.d.ts +72 -0
- package/dist/types/ReferenceBuilder.d.ts +2 -1
- package/dist/types/RowProcessor.d.ts +2 -1
- package/dist/types/ops/all.d.ts +1 -1
- package/dist/types/ops/create.d.ts +2 -2
- package/dist/types/ops/update.d.ts +2 -2
- package/package.json +21 -22
package/dist/es/ops/all.js
CHANGED
|
@@ -3,8 +3,30 @@ import { buildQuery } from '../QueryBuilder.js';
|
|
|
3
3
|
import LibLogger from '../logger.js';
|
|
4
4
|
import { processRow } from '../RowProcessor.js';
|
|
5
5
|
import { Op } from 'sequelize';
|
|
6
|
+
import { buildRelationshipPath } from '../util/relationshipUtils.js';
|
|
7
|
+
import { contextManager } from '../OperationContext.js';
|
|
6
8
|
|
|
7
9
|
const logger = LibLogger.get('sequelize', 'ops', 'all');
|
|
10
|
+
// Helper function to merge includes avoiding duplicates
|
|
11
|
+
const mergeIncludes = (existingIncludes, newIncludes)=>{
|
|
12
|
+
const mergedIncludes = [
|
|
13
|
+
...existingIncludes
|
|
14
|
+
];
|
|
15
|
+
for (const newInclude of newIncludes){
|
|
16
|
+
const existingIndex = mergedIncludes.findIndex((existing)=>existing.as === newInclude.as && existing.model === newInclude.model);
|
|
17
|
+
if (existingIndex === -1) {
|
|
18
|
+
mergedIncludes.push(newInclude);
|
|
19
|
+
} else if (newInclude.include && mergedIncludes[existingIndex].include) {
|
|
20
|
+
mergedIncludes[existingIndex].include = [
|
|
21
|
+
...mergedIncludes[existingIndex].include,
|
|
22
|
+
...newInclude.include
|
|
23
|
+
];
|
|
24
|
+
} else if (newInclude.include) {
|
|
25
|
+
mergedIncludes[existingIndex].include = newInclude.include;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return mergedIncludes;
|
|
29
|
+
};
|
|
8
30
|
const getAllOperation = (models, definition, registry)=>{
|
|
9
31
|
const { coordinate, options: { references, aggregations } } = definition;
|
|
10
32
|
//#region Query
|
|
@@ -14,29 +36,64 @@ const getAllOperation = (models, definition, registry)=>{
|
|
|
14
36
|
locations
|
|
15
37
|
});
|
|
16
38
|
const loc = locations || [];
|
|
17
|
-
// SQ Libs don't support locations
|
|
18
|
-
if (loc.length > 1) {
|
|
19
|
-
throw new Error('Not implemented for more than one location key');
|
|
20
|
-
}
|
|
21
|
-
// We have the model here?
|
|
22
39
|
// @ts-ignore
|
|
23
40
|
const model = models[0];
|
|
24
|
-
//
|
|
41
|
+
// Build base query from itemQuery
|
|
25
42
|
const options = buildQuery(itemQuery, model);
|
|
26
|
-
//
|
|
27
|
-
if (loc.length
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
43
|
+
// Handle location keys if present
|
|
44
|
+
if (loc.length > 0) {
|
|
45
|
+
const { kta } = coordinate;
|
|
46
|
+
const directLocations = [];
|
|
47
|
+
const hierarchicalLocations = [];
|
|
48
|
+
const additionalIncludes = [];
|
|
49
|
+
// Categorize location keys as direct or hierarchical
|
|
50
|
+
for (const locKey of loc){
|
|
51
|
+
const relationshipInfo = buildRelationshipPath(model, locKey.kt, kta, true);
|
|
52
|
+
if (!relationshipInfo.found) {
|
|
53
|
+
const errorMessage = `Location key '${locKey.kt}' cannot be resolved on model '${model.name}' or through its relationships.`;
|
|
54
|
+
logger.error(errorMessage, {
|
|
55
|
+
locations: loc,
|
|
56
|
+
kta
|
|
57
|
+
});
|
|
58
|
+
throw new Error(errorMessage);
|
|
59
|
+
}
|
|
60
|
+
if (relationshipInfo.isDirect) {
|
|
61
|
+
directLocations.push(locKey);
|
|
62
|
+
} else {
|
|
63
|
+
hierarchicalLocations.push(locKey);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Handle direct location keys (simple foreign key constraints)
|
|
67
|
+
for (const locKey of directLocations){
|
|
68
|
+
const foreignKeyField = locKey.kt + 'Id';
|
|
31
69
|
options.where = {
|
|
32
70
|
...options.where,
|
|
33
|
-
[
|
|
34
|
-
[Op.eq]:
|
|
71
|
+
[foreignKeyField]: {
|
|
72
|
+
[Op.eq]: locKey.lk
|
|
35
73
|
}
|
|
36
74
|
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
75
|
+
}
|
|
76
|
+
// Handle hierarchical location keys (requires relationship traversal)
|
|
77
|
+
for (const locKey of hierarchicalLocations){
|
|
78
|
+
const relationshipInfo = buildRelationshipPath(model, locKey.kt, kta);
|
|
79
|
+
if (relationshipInfo.found && relationshipInfo.path) {
|
|
80
|
+
// Add the relationship constraint using the path
|
|
81
|
+
options.where = {
|
|
82
|
+
...options.where,
|
|
83
|
+
[relationshipInfo.path]: {
|
|
84
|
+
[Op.eq]: locKey.lk
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
// Add necessary includes for the relationship traversal
|
|
88
|
+
if (relationshipInfo.includes) {
|
|
89
|
+
additionalIncludes.push(...relationshipInfo.includes);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Merge additional includes with existing includes
|
|
94
|
+
if (additionalIncludes.length > 0) {
|
|
95
|
+
const existingIncludes = options.include || [];
|
|
96
|
+
options.include = mergeIncludes(existingIncludes, additionalIncludes);
|
|
40
97
|
}
|
|
41
98
|
}
|
|
42
99
|
logger.default('Configured this Item Query', {
|
|
@@ -45,9 +102,11 @@ const getAllOperation = (models, definition, registry)=>{
|
|
|
45
102
|
});
|
|
46
103
|
const matchingItems = await model.findAll(options);
|
|
47
104
|
// this.logger.default('Matching Items', { matchingItems });
|
|
105
|
+
// Get the current context from context manager
|
|
106
|
+
const context = contextManager.getCurrentContext();
|
|
48
107
|
// TODO: Move this Up!
|
|
49
108
|
return await Promise.all(matchingItems.map(async (row)=>{
|
|
50
|
-
const processedRow = await processRow(row, coordinate.kta, references, aggregations, registry);
|
|
109
|
+
const processedRow = await processRow(row, coordinate.kta, references, aggregations, registry, context);
|
|
51
110
|
return validateKeys(processedRow, coordinate.kta);
|
|
52
111
|
}));
|
|
53
112
|
};
|
|
@@ -55,4 +114,4 @@ const getAllOperation = (models, definition, registry)=>{
|
|
|
55
114
|
};
|
|
56
115
|
|
|
57
116
|
export { getAllOperation };
|
|
58
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
117
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxsLmpzIiwic291cmNlcyI6W10sInNvdXJjZXNDb250ZW50IjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OyJ9
|
package/dist/es/ops/get.js
CHANGED
|
@@ -3,6 +3,7 @@ import LibLogger from '../logger.js';
|
|
|
3
3
|
import { processRow } from '../RowProcessor.js';
|
|
4
4
|
import { NotFoundError } from '@fjell/lib';
|
|
5
5
|
import { buildRelationshipPath } from '../util/relationshipUtils.js';
|
|
6
|
+
import { contextManager } from '../OperationContext.js';
|
|
6
7
|
|
|
7
8
|
const logger = LibLogger.get('sequelize', 'ops', 'get');
|
|
8
9
|
// Helper function to process composite key and build query options
|
|
@@ -71,11 +72,13 @@ const getGetOperation = (models, definition, registry)=>{
|
|
|
71
72
|
if (!item) {
|
|
72
73
|
throw new NotFoundError('get', coordinate, key);
|
|
73
74
|
} else {
|
|
74
|
-
|
|
75
|
+
// Get the current context from context manager
|
|
76
|
+
const context = contextManager.getCurrentContext();
|
|
77
|
+
return validateKeys(await processRow(item, kta, references, aggregations, registry, context), kta);
|
|
75
78
|
}
|
|
76
79
|
};
|
|
77
80
|
return get;
|
|
78
81
|
};
|
|
79
82
|
|
|
80
83
|
export { getGetOperation };
|
|
81
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
84
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LmpzIiwic291cmNlcyI6W10sInNvdXJjZXNDb250ZW50IjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OyJ9
|
package/dist/es/ops/update.js
CHANGED
|
@@ -5,8 +5,30 @@ import LibLogger from '../logger.js';
|
|
|
5
5
|
import { processRow } from '../RowProcessor.js';
|
|
6
6
|
import { stringifyJSON } from '../util/general.js';
|
|
7
7
|
import { NotFoundError } from '@fjell/lib';
|
|
8
|
+
import { Op } from 'sequelize';
|
|
9
|
+
import { buildRelationshipPath } from '../util/relationshipUtils.js';
|
|
8
10
|
|
|
9
11
|
const logger = LibLogger.get('sequelize', 'ops', 'update');
|
|
12
|
+
// Helper function to merge includes avoiding duplicates
|
|
13
|
+
const mergeIncludes = (existingIncludes, newIncludes)=>{
|
|
14
|
+
const mergedIncludes = [
|
|
15
|
+
...existingIncludes
|
|
16
|
+
];
|
|
17
|
+
for (const newInclude of newIncludes){
|
|
18
|
+
const existingIndex = mergedIncludes.findIndex((existing)=>existing.as === newInclude.as && existing.model === newInclude.model);
|
|
19
|
+
if (existingIndex === -1) {
|
|
20
|
+
mergedIncludes.push(newInclude);
|
|
21
|
+
} else if (newInclude.include && mergedIncludes[existingIndex].include) {
|
|
22
|
+
mergedIncludes[existingIndex].include = [
|
|
23
|
+
...mergedIncludes[existingIndex].include,
|
|
24
|
+
...newInclude.include
|
|
25
|
+
];
|
|
26
|
+
} else if (newInclude.include) {
|
|
27
|
+
mergedIncludes[existingIndex].include = newInclude.include;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return mergedIncludes;
|
|
31
|
+
};
|
|
10
32
|
const getUpdateOperation = (models, definition, registry)=>{
|
|
11
33
|
const { options: { references, aggregations } } = definition;
|
|
12
34
|
const update = async (key, item)=>{
|
|
@@ -22,15 +44,49 @@ const getUpdateOperation = (models, definition, registry)=>{
|
|
|
22
44
|
const priKey = key;
|
|
23
45
|
response = await model.findByPk(priKey.pk);
|
|
24
46
|
} else if (isComKey(key)) {
|
|
25
|
-
var _comKey_loc_, _comKey_loc_1;
|
|
26
47
|
const comKey = key;
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
48
|
+
// Build query options for composite key with multiple location keys
|
|
49
|
+
const where = {
|
|
50
|
+
id: comKey.pk
|
|
51
|
+
};
|
|
52
|
+
const additionalIncludes = [];
|
|
53
|
+
// Process all location keys in the composite key
|
|
54
|
+
for (const locator of comKey.loc){
|
|
55
|
+
const relationshipInfo = buildRelationshipPath(model, locator.kt, kta, true);
|
|
56
|
+
if (!relationshipInfo.found) {
|
|
57
|
+
const errorMessage = `Composite key locator '${locator.kt}' cannot be resolved on model '${model.name}' or through its relationships.`;
|
|
58
|
+
logger.error(errorMessage, {
|
|
59
|
+
key: comKey,
|
|
60
|
+
kta
|
|
61
|
+
});
|
|
62
|
+
throw new Error(errorMessage);
|
|
63
|
+
}
|
|
64
|
+
if (relationshipInfo.isDirect) {
|
|
65
|
+
// Direct foreign key field
|
|
66
|
+
const fieldName = `${locator.kt}Id`;
|
|
67
|
+
where[fieldName] = locator.lk;
|
|
68
|
+
} else if (relationshipInfo.path) {
|
|
69
|
+
// Hierarchical relationship requiring traversal
|
|
70
|
+
where[relationshipInfo.path] = {
|
|
71
|
+
[Op.eq]: locator.lk
|
|
72
|
+
};
|
|
73
|
+
// Add necessary includes for relationship traversal
|
|
74
|
+
if (relationshipInfo.includes) {
|
|
75
|
+
additionalIncludes.push(...relationshipInfo.includes);
|
|
76
|
+
}
|
|
32
77
|
}
|
|
78
|
+
}
|
|
79
|
+
// Build final query options
|
|
80
|
+
const queryOptions = {
|
|
81
|
+
where
|
|
82
|
+
};
|
|
83
|
+
if (additionalIncludes.length > 0) {
|
|
84
|
+
queryOptions.include = mergeIncludes([], additionalIncludes);
|
|
85
|
+
}
|
|
86
|
+
logger.default('Composite key query for update', {
|
|
87
|
+
queryOptions
|
|
33
88
|
});
|
|
89
|
+
response = await model.findOne(queryOptions);
|
|
34
90
|
}
|
|
35
91
|
if (response) {
|
|
36
92
|
// Remove the key and events
|
|
@@ -54,4 +110,4 @@ const getUpdateOperation = (models, definition, registry)=>{
|
|
|
54
110
|
};
|
|
55
111
|
|
|
56
112
|
export { getUpdateOperation };
|
|
57
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
113
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLmpzIiwic291cmNlcyI6W10sInNvdXJjZXNDb250ZW50IjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7In0=
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
modelChain.push(currentModel);
|
|
22
22
|
}
|
|
23
23
|
// Build the full association path for the target field
|
|
24
|
-
const
|
|
25
|
-
const associationPath = `$${associationParts.join('.')}.${
|
|
24
|
+
const targetPrimaryKey = currentModel.primaryKeyAttribute || 'id';
|
|
25
|
+
const associationPath = `$${associationParts.join('.')}.${targetPrimaryKey}$`;
|
|
26
26
|
// Build nested includes structure iteratively (clearer than recursion)
|
|
27
27
|
let deepestInclude = null;
|
|
28
28
|
// Build from the deepest level back to the root
|