@fjell/lib-sequelize 4.4.1 → 4.4.2
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/EventCoordinator.cjs +20 -1
- package/dist/cjs/KeyMaster.cjs +62 -24
- package/dist/cjs/Operations.cjs +2 -2
- package/dist/cjs/QueryBuilder.cjs +123 -21
- package/dist/cjs/RowProcessor.cjs +1 -1
- package/dist/cjs/ops/create.cjs +137 -6
- package/dist/cjs/ops/get.cjs +44 -8
- package/dist/cjs/ops/remove.cjs +48 -9
- package/dist/cjs/ops/update.cjs +4 -2
- package/dist/cjs/util/relationshipUtils.cjs +117 -0
- package/dist/es/EventCoordinator.js +20 -2
- package/dist/es/KeyMaster.js +62 -24
- package/dist/es/Operations.js +2 -2
- package/dist/es/QueryBuilder.js +123 -21
- package/dist/es/RowProcessor.js +1 -1
- package/dist/es/ops/create.js +137 -6
- package/dist/es/ops/get.js +44 -8
- package/dist/es/ops/remove.js +48 -9
- package/dist/es/ops/update.js +5 -3
- package/dist/es/util/relationshipUtils.js +112 -0
- package/dist/index.cjs +536 -67
- package/dist/index.cjs.map +1 -1
- package/dist/types/EventCoordinator.d.ts +1 -0
- package/dist/types/KeyMaster.d.ts +2 -1
- package/dist/types/QueryBuilder.d.ts +1 -0
- package/dist/types/ops/create.d.ts +1 -1
- package/dist/types/util/relationshipUtils.d.ts +21 -0
- package/package.json +7 -7
package/dist/cjs/ops/remove.cjs
CHANGED
|
@@ -6,8 +6,45 @@ const core = require('@fjell/core');
|
|
|
6
6
|
const EventCoordinator = require('../EventCoordinator.cjs');
|
|
7
7
|
const KeyMaster = require('../KeyMaster.cjs');
|
|
8
8
|
const logger$1 = require('../logger.cjs');
|
|
9
|
+
const relationshipUtils = require('../util/relationshipUtils.cjs');
|
|
9
10
|
|
|
10
11
|
const logger = logger$1.default.get('sequelize', 'ops', 'remove');
|
|
12
|
+
// Helper function to process composite key and build query options
|
|
13
|
+
const processCompositeKey = (comKey, model, kta)=>{
|
|
14
|
+
const where = {
|
|
15
|
+
id: comKey.pk
|
|
16
|
+
};
|
|
17
|
+
const includes = [];
|
|
18
|
+
for (const locator of comKey.loc){
|
|
19
|
+
const relationshipInfo = relationshipUtils.buildRelationshipPath(model, locator.kt, kta);
|
|
20
|
+
if (!relationshipInfo.found) {
|
|
21
|
+
const errorMessage = `Composite key locator '${locator.kt}' cannot be resolved on model '${model.name}' or through its relationships.`;
|
|
22
|
+
logger.error(errorMessage, {
|
|
23
|
+
key: comKey,
|
|
24
|
+
kta
|
|
25
|
+
});
|
|
26
|
+
throw new Error(errorMessage);
|
|
27
|
+
}
|
|
28
|
+
if (relationshipInfo.path) {
|
|
29
|
+
// This requires a relationship traversal
|
|
30
|
+
where[relationshipInfo.path] = locator.lk;
|
|
31
|
+
if (relationshipInfo.includes) {
|
|
32
|
+
includes.push(...relationshipInfo.includes);
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
// This is a direct field
|
|
36
|
+
const fieldName = `${locator.kt}Id`;
|
|
37
|
+
where[fieldName] = locator.lk;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const result = {
|
|
41
|
+
where
|
|
42
|
+
};
|
|
43
|
+
if (includes.length > 0) {
|
|
44
|
+
result.include = includes;
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
11
48
|
const getRemoveOperation = (models, definition, // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
12
49
|
registry)=>{
|
|
13
50
|
const { coordinate, options } = definition;
|
|
@@ -28,14 +65,16 @@ registry)=>{
|
|
|
28
65
|
if (core.isPriKey(key)) {
|
|
29
66
|
item = await model.findByPk(key.pk);
|
|
30
67
|
} else if (core.isComKey(key)) {
|
|
31
|
-
|
|
68
|
+
// This is a composite key, so we need to build a where clause based on the composite key's locators
|
|
32
69
|
const comKey = key;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
[(comKey === null || comKey === void 0 ? void 0 : (_comKey_loc_ = comKey.loc[0]) === null || _comKey_loc_ === void 0 ? void 0 : _comKey_loc_.kt) + 'Id']: comKey === null || comKey === void 0 ? void 0 : (_comKey_loc_1 = comKey.loc[0]) === null || _comKey_loc_1 === void 0 ? void 0 : _comKey_loc_1.lk
|
|
37
|
-
}
|
|
70
|
+
const queryOptions = processCompositeKey(comKey, model, kta);
|
|
71
|
+
logger.default('Composite key query', {
|
|
72
|
+
queryOptions
|
|
38
73
|
});
|
|
74
|
+
item = await model.findOne(queryOptions);
|
|
75
|
+
}
|
|
76
|
+
if (!item) {
|
|
77
|
+
throw new Error(`Item not found for removal with key: ${core.abbrevIK(key)}`);
|
|
39
78
|
}
|
|
40
79
|
const isDeletedAttribute = model.getAttributes().isDeleted;
|
|
41
80
|
const deletedAtAttribute = model.getAttributes().deletedAt;
|
|
@@ -51,14 +90,14 @@ registry)=>{
|
|
|
51
90
|
returnItem = item === null || item === void 0 ? void 0 : item.get({
|
|
52
91
|
plain: true
|
|
53
92
|
});
|
|
54
|
-
returnItem = KeyMaster.addKey(returnItem, kta);
|
|
93
|
+
returnItem = KeyMaster.addKey(item, returnItem, kta);
|
|
55
94
|
returnItem = EventCoordinator.populateEvents(returnItem);
|
|
56
95
|
} else if (options.deleteOnRemove) {
|
|
57
96
|
await (item === null || item === void 0 ? void 0 : item.destroy());
|
|
58
97
|
returnItem = item === null || item === void 0 ? void 0 : item.get({
|
|
59
98
|
plain: true
|
|
60
99
|
});
|
|
61
|
-
returnItem = KeyMaster.addKey(returnItem, kta);
|
|
100
|
+
returnItem = KeyMaster.addKey(item, returnItem, kta);
|
|
62
101
|
returnItem = EventCoordinator.populateEvents(returnItem);
|
|
63
102
|
} else {
|
|
64
103
|
throw new Error('No deletedAt or isDeleted attribute found in model, and deleteOnRemove is not set');
|
|
@@ -69,4 +108,4 @@ registry)=>{
|
|
|
69
108
|
};
|
|
70
109
|
|
|
71
110
|
exports.getRemoveOperation = getRemoveOperation;
|
|
72
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
111
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3ZlLmNqcyIsInNvdXJjZXMiOltdLCJzb3VyY2VzQ29udGVudCI6W10sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsifQ==
|
package/dist/cjs/ops/update.cjs
CHANGED
|
@@ -39,7 +39,9 @@ const getUpdateOperation = (models, definition, registry)=>{
|
|
|
39
39
|
if (response) {
|
|
40
40
|
// Remove the key and events
|
|
41
41
|
let updateProps = KeyMaster.removeKey(item);
|
|
42
|
-
|
|
42
|
+
// TODO: We need the opposite of processRow, something to step down from fjell to database.
|
|
43
|
+
updateProps = EventCoordinator.extractEvents(updateProps);
|
|
44
|
+
updateProps = EventCoordinator.removeEvents(updateProps);
|
|
43
45
|
logger.default('Response: %s', general.stringifyJSON(response));
|
|
44
46
|
logger.default('Update Properties: %s', general.stringifyJSON(updateProps));
|
|
45
47
|
// Update the object
|
|
@@ -56,4 +58,4 @@ const getUpdateOperation = (models, definition, registry)=>{
|
|
|
56
58
|
};
|
|
57
59
|
|
|
58
60
|
exports.getUpdateOperation = getUpdateOperation;
|
|
59
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
61
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLmNqcyIsInNvdXJjZXMiOltdLCJzb3VyY2VzQ29udGVudCI6W10sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7In0=
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
/* eslint-disable indent */ /**
|
|
6
|
+
* Helper function to build relationship chain includes
|
|
7
|
+
*/ const buildRelationshipChain = (targetModel, kta, currentIndex, targetIndex)=>{
|
|
8
|
+
// Build the association path and validate relationships exist
|
|
9
|
+
const associationParts = [];
|
|
10
|
+
const modelChain = [
|
|
11
|
+
targetModel
|
|
12
|
+
];
|
|
13
|
+
let currentModel = targetModel;
|
|
14
|
+
// Validate that all associations exist and build model chain
|
|
15
|
+
for(let i = currentIndex + 1; i <= targetIndex; i++){
|
|
16
|
+
const intermediateType = kta[i];
|
|
17
|
+
const associationName = intermediateType;
|
|
18
|
+
if (!currentModel.associations || !currentModel.associations[associationName]) {
|
|
19
|
+
return {
|
|
20
|
+
success: false
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
associationParts.push(associationName);
|
|
24
|
+
currentModel = currentModel.associations[associationName].target;
|
|
25
|
+
modelChain.push(currentModel);
|
|
26
|
+
}
|
|
27
|
+
// Build the full association path for the target field
|
|
28
|
+
const targetType = kta[targetIndex];
|
|
29
|
+
const associationPath = `$${associationParts.join('.')}.${targetType}Id$`;
|
|
30
|
+
// Build nested includes structure iteratively (clearer than recursion)
|
|
31
|
+
let deepestInclude = null;
|
|
32
|
+
// Build from the deepest level back to the root
|
|
33
|
+
for(let i = targetIndex; i > currentIndex; i--){
|
|
34
|
+
const currentType = kta[i];
|
|
35
|
+
const modelIndex = i - currentIndex;
|
|
36
|
+
const includeObj = {
|
|
37
|
+
model: modelChain[modelIndex],
|
|
38
|
+
as: currentType,
|
|
39
|
+
required: true
|
|
40
|
+
};
|
|
41
|
+
if (deepestInclude) {
|
|
42
|
+
includeObj.include = [
|
|
43
|
+
deepestInclude
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
deepestInclude = includeObj;
|
|
47
|
+
}
|
|
48
|
+
const includes = deepestInclude ? [
|
|
49
|
+
deepestInclude
|
|
50
|
+
] : [];
|
|
51
|
+
return {
|
|
52
|
+
success: true,
|
|
53
|
+
path: associationPath,
|
|
54
|
+
includes
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Helper function to build relationship path for a locator
|
|
59
|
+
* @param includeIsDirect Whether to include the isDirect flag in the result
|
|
60
|
+
*/ const buildRelationshipPath = (targetModel, locatorType, kta, includeIsDirect = false)=>{
|
|
61
|
+
// First check if the field exists directly
|
|
62
|
+
const directFieldName = `${locatorType}Id`;
|
|
63
|
+
const attributes = targetModel.getAttributes();
|
|
64
|
+
if (attributes && attributes[directFieldName]) {
|
|
65
|
+
const result = {
|
|
66
|
+
found: true
|
|
67
|
+
};
|
|
68
|
+
if (includeIsDirect) {
|
|
69
|
+
result.isDirect = true;
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
// If not direct, look for relationship path
|
|
74
|
+
const targetIndex = kta.indexOf(locatorType);
|
|
75
|
+
if (targetIndex === -1) {
|
|
76
|
+
const result = {
|
|
77
|
+
found: false
|
|
78
|
+
};
|
|
79
|
+
if (includeIsDirect) {
|
|
80
|
+
result.isDirect = false;
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
const currentIndex = 0; // We're always looking from the base model
|
|
85
|
+
if (targetIndex <= currentIndex) {
|
|
86
|
+
const result = {
|
|
87
|
+
found: false
|
|
88
|
+
};
|
|
89
|
+
if (includeIsDirect) {
|
|
90
|
+
result.isDirect = false;
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
const chainResult = buildRelationshipChain(targetModel, kta, currentIndex, targetIndex);
|
|
95
|
+
if (chainResult.success) {
|
|
96
|
+
const result = {
|
|
97
|
+
found: true,
|
|
98
|
+
path: chainResult.path,
|
|
99
|
+
includes: chainResult.includes
|
|
100
|
+
};
|
|
101
|
+
if (includeIsDirect) {
|
|
102
|
+
result.isDirect = false;
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
const result = {
|
|
107
|
+
found: false
|
|
108
|
+
};
|
|
109
|
+
if (includeIsDirect) {
|
|
110
|
+
result.isDirect = false;
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
exports.buildRelationshipChain = buildRelationshipChain;
|
|
116
|
+
exports.buildRelationshipPath = buildRelationshipPath;
|
|
117
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVsYXRpb25zaGlwVXRpbHMuY2pzIiwic291cmNlcyI6W10sInNvdXJjZXNDb250ZW50IjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OyJ9
|
|
@@ -18,6 +18,24 @@ const populateEvents = (item)=>{
|
|
|
18
18
|
item.events = events;
|
|
19
19
|
return item;
|
|
20
20
|
};
|
|
21
|
+
const extractEvents = (item)=>{
|
|
22
|
+
logger.default('Extracting Events to database fields', {
|
|
23
|
+
item
|
|
24
|
+
});
|
|
25
|
+
if (item.events) {
|
|
26
|
+
var _item_events_created, _item_events_updated, _item_events_deleted;
|
|
27
|
+
if ((_item_events_created = item.events.created) === null || _item_events_created === void 0 ? void 0 : _item_events_created.at) {
|
|
28
|
+
item.createdAt = item.events.created.at;
|
|
29
|
+
}
|
|
30
|
+
if ((_item_events_updated = item.events.updated) === null || _item_events_updated === void 0 ? void 0 : _item_events_updated.at) {
|
|
31
|
+
item.updatedAt = item.events.updated.at;
|
|
32
|
+
}
|
|
33
|
+
if ((_item_events_deleted = item.events.deleted) === null || _item_events_deleted === void 0 ? void 0 : _item_events_deleted.at) {
|
|
34
|
+
item.deletedAt = item.events.deleted.at;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return item;
|
|
38
|
+
};
|
|
21
39
|
const removeEvents = (item)=>{
|
|
22
40
|
logger.default('Removing Events', {
|
|
23
41
|
item
|
|
@@ -26,5 +44,5 @@ const removeEvents = (item)=>{
|
|
|
26
44
|
return item;
|
|
27
45
|
};
|
|
28
46
|
|
|
29
|
-
export { populateEvents, removeEvents };
|
|
30
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
47
|
+
export { extractEvents, populateEvents, removeEvents };
|
|
48
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRXZlbnRDb29yZGluYXRvci5qcyIsInNvdXJjZXMiOltdLCJzb3VyY2VzQ29udGVudCI6W10sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsifQ==
|
package/dist/es/KeyMaster.js
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
import LibLogger from './logger.js';
|
|
2
|
+
import { buildRelationshipPath } from './util/relationshipUtils.js';
|
|
2
3
|
|
|
3
4
|
const logger = LibLogger.get('sequelize', 'KeyMaster');
|
|
5
|
+
// Helper function to extract location key value from item
|
|
6
|
+
const extractLocationKeyValue = (model, item, locatorType, kta)=>{
|
|
7
|
+
logger.default('Extracting location key value', {
|
|
8
|
+
locatorType,
|
|
9
|
+
kta
|
|
10
|
+
});
|
|
11
|
+
const relationshipInfo = buildRelationshipPath(model, locatorType, kta, true);
|
|
12
|
+
if (!relationshipInfo.found) {
|
|
13
|
+
throw new Error(`Location key '${locatorType}' cannot be resolved on model '${model.name}' or through its relationships.`);
|
|
14
|
+
}
|
|
15
|
+
if (relationshipInfo.isDirect) {
|
|
16
|
+
// Direct foreign key field
|
|
17
|
+
const foreignKeyField = `${locatorType}Id`;
|
|
18
|
+
const value = item[foreignKeyField];
|
|
19
|
+
if (typeof value === 'undefined' || value === null) {
|
|
20
|
+
throw new Error(`Direct foreign key field '${foreignKeyField}' is missing or null in item`);
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
} else {
|
|
24
|
+
// Need to traverse relationship
|
|
25
|
+
// Try to get the value from the loaded relationship object
|
|
26
|
+
const relationshipObject = item[locatorType];
|
|
27
|
+
if (relationshipObject && typeof relationshipObject.id !== 'undefined') {
|
|
28
|
+
return relationshipObject.id;
|
|
29
|
+
}
|
|
30
|
+
// If the relationship object isn't loaded, we might need to look at the foreign key field
|
|
31
|
+
// This handles cases where we have the foreign key but not the full object
|
|
32
|
+
const foreignKeyField = `${locatorType}Id`;
|
|
33
|
+
if (typeof item[foreignKeyField] !== 'undefined' && item[foreignKeyField] !== null) {
|
|
34
|
+
return item[foreignKeyField];
|
|
35
|
+
}
|
|
36
|
+
throw new Error(`Unable to extract location key for '${locatorType}'. Neither the relationship object nor direct foreign key is available.`);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
4
39
|
const removeKey = (item)=>{
|
|
5
40
|
logger.default('Removing Key', {
|
|
6
41
|
item
|
|
@@ -35,11 +70,13 @@ const removeKey = (item)=>{
|
|
|
35
70
|
// }
|
|
36
71
|
// return item;
|
|
37
72
|
// }
|
|
38
|
-
const addKey = (item, keyTypes)=>{
|
|
73
|
+
const addKey = (model, item, keyTypes)=>{
|
|
39
74
|
logger.default('Adding Key', {
|
|
40
75
|
item
|
|
41
76
|
});
|
|
42
77
|
const key = {};
|
|
78
|
+
const modelClass = model.constructor;
|
|
79
|
+
const primaryKeyAttr = modelClass.primaryKeyAttribute;
|
|
43
80
|
if (Array.isArray(keyTypes) && keyTypes.length > 1) {
|
|
44
81
|
const type = [
|
|
45
82
|
...keyTypes
|
|
@@ -47,33 +84,34 @@ const addKey = (item, keyTypes)=>{
|
|
|
47
84
|
const pkType = type.shift();
|
|
48
85
|
Object.assign(key, {
|
|
49
86
|
kt: pkType,
|
|
50
|
-
pk: item
|
|
87
|
+
pk: item[primaryKeyAttr]
|
|
51
88
|
});
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
} else if (type.length === 5) {
|
|
71
|
-
throw new Error('Not implemented');
|
|
89
|
+
// Build location keys for composite key
|
|
90
|
+
const locationKeys = [];
|
|
91
|
+
for (const locatorType of type){
|
|
92
|
+
try {
|
|
93
|
+
const lk = extractLocationKeyValue(modelClass, item, locatorType, keyTypes);
|
|
94
|
+
locationKeys.push({
|
|
95
|
+
kt: locatorType,
|
|
96
|
+
lk
|
|
97
|
+
});
|
|
98
|
+
} catch (error) {
|
|
99
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
100
|
+
logger.error(`Failed to extract location key for '${locatorType}'`, {
|
|
101
|
+
error: errorMessage,
|
|
102
|
+
item,
|
|
103
|
+
keyTypes
|
|
104
|
+
});
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
72
107
|
}
|
|
108
|
+
Object.assign(key, {
|
|
109
|
+
loc: locationKeys
|
|
110
|
+
});
|
|
73
111
|
} else {
|
|
74
112
|
Object.assign(key, {
|
|
75
113
|
kt: keyTypes[0],
|
|
76
|
-
pk: item
|
|
114
|
+
pk: item[primaryKeyAttr]
|
|
77
115
|
});
|
|
78
116
|
}
|
|
79
117
|
Object.assign(item, {
|
|
@@ -83,4 +121,4 @@ const addKey = (item, keyTypes)=>{
|
|
|
83
121
|
};
|
|
84
122
|
|
|
85
123
|
export { addKey, removeKey };
|
|
86
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
124
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiS2V5TWFzdGVyLmpzIiwic291cmNlcyI6W10sInNvdXJjZXNDb250ZW50IjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsifQ==
|
package/dist/es/Operations.js
CHANGED
|
@@ -10,12 +10,12 @@ const createOperations = (models, definition, registry)=>{
|
|
|
10
10
|
const operations = {};
|
|
11
11
|
operations.all = getAllOperation(models, definition, registry);
|
|
12
12
|
operations.one = getOneOperation(models, definition, registry);
|
|
13
|
-
operations.create = getCreateOperation();
|
|
13
|
+
operations.create = getCreateOperation(models, definition, registry);
|
|
14
14
|
operations.update = getUpdateOperation(models, definition, registry);
|
|
15
15
|
operations.get = getGetOperation(models, definition, registry);
|
|
16
16
|
operations.remove = getRemoveOperation(models, definition);
|
|
17
17
|
operations.find = getFindOperation(models, definition, registry);
|
|
18
|
-
operations.upsert = ()=>{
|
|
18
|
+
operations.upsert = async ()=>{
|
|
19
19
|
throw new Error('Not implemented');
|
|
20
20
|
};
|
|
21
21
|
return operations;
|
package/dist/es/QueryBuilder.js
CHANGED
|
@@ -80,7 +80,8 @@ const addReferenceQueries = (options, references, model)=>{
|
|
|
80
80
|
return options;
|
|
81
81
|
};
|
|
82
82
|
const addCompoundCondition = (options, compoundCondition, model)=>{
|
|
83
|
-
|
|
83
|
+
// Ensure options.where exists
|
|
84
|
+
options.where = options.where || {};
|
|
84
85
|
let compoundOp;
|
|
85
86
|
const compoundType = compoundCondition.compoundType;
|
|
86
87
|
if (compoundType === "AND") {
|
|
@@ -96,36 +97,135 @@ const addCompoundCondition = (options, compoundCondition, model)=>{
|
|
|
96
97
|
throw new Error('Nest Compound conditions not supported');
|
|
97
98
|
}
|
|
98
99
|
});
|
|
99
|
-
where
|
|
100
|
-
options.where
|
|
100
|
+
// Merge with existing where conditions instead of replacing
|
|
101
|
+
if (Object.keys(options.where).length > 0) {
|
|
102
|
+
// If there are existing conditions, wrap everything in an AND
|
|
103
|
+
options.where = {
|
|
104
|
+
[Op.and]: [
|
|
105
|
+
options.where,
|
|
106
|
+
{
|
|
107
|
+
[compoundOp]: conditions
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
};
|
|
111
|
+
} else {
|
|
112
|
+
// If no existing conditions, just set the compound condition
|
|
113
|
+
options.where[compoundOp] = conditions;
|
|
114
|
+
}
|
|
101
115
|
return options;
|
|
102
116
|
};
|
|
103
|
-
const
|
|
104
|
-
|
|
117
|
+
const getSequelizeOperator = (operator)=>{
|
|
118
|
+
if (operator === '==') {
|
|
119
|
+
return Op.eq;
|
|
120
|
+
} else if (operator === '<') {
|
|
121
|
+
return Op.lt;
|
|
122
|
+
} else if (operator === '>') {
|
|
123
|
+
return Op.gt;
|
|
124
|
+
} else if (operator === '<=') {
|
|
125
|
+
return Op.lte;
|
|
126
|
+
} else if (operator === '>=') {
|
|
127
|
+
return Op.gte;
|
|
128
|
+
} else if (operator === 'in') {
|
|
129
|
+
return Op.in;
|
|
130
|
+
} else {
|
|
131
|
+
throw new Error(`Operator ${operator} not supported`);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const addAssociationCondition = (conditions, condition, model)=>{
|
|
135
|
+
const [associationName, attributeName] = condition.column.split('.', 2);
|
|
136
|
+
// Check if the association exists on the model
|
|
137
|
+
if (!model.associations || !model.associations[associationName]) {
|
|
138
|
+
throw new Error(`Association ${associationName} not found on model ${model.name}`);
|
|
139
|
+
}
|
|
140
|
+
const association = model.associations[associationName];
|
|
141
|
+
const associatedModel = association.target;
|
|
142
|
+
// Check if the attribute exists on the associated model
|
|
143
|
+
if (!associatedModel.getAttributes()[attributeName]) {
|
|
144
|
+
throw new Error(`Attribute ${attributeName} not found on associated model ${associatedModel.name} for association ${associationName}`);
|
|
145
|
+
}
|
|
146
|
+
// Use Sequelize's $association.attribute$ syntax for querying associated models
|
|
147
|
+
const sequelizeAssociationColumn = `$${associationName}.${attributeName}$`;
|
|
148
|
+
const conditionOp = getSequelizeOperator(condition.operator);
|
|
149
|
+
conditions[sequelizeAssociationColumn] = {
|
|
150
|
+
[conditionOp]: condition.value
|
|
151
|
+
};
|
|
152
|
+
return conditions;
|
|
153
|
+
};
|
|
154
|
+
const addAttributeCondition = (conditions, condition, model)=>{
|
|
105
155
|
const conditionColumn = condition.column;
|
|
106
156
|
if (!model.getAttributes()[conditionColumn]) {
|
|
107
157
|
throw new Error(`Condition column ${conditionColumn} not found on model ${model.name}`);
|
|
108
158
|
}
|
|
109
|
-
|
|
110
|
-
conditionOp = Op.eq;
|
|
111
|
-
} else if (condition.operator === '<') {
|
|
112
|
-
conditionOp = Op.lt;
|
|
113
|
-
} else if (condition.operator === '>') {
|
|
114
|
-
conditionOp = Op.gt;
|
|
115
|
-
} else if (condition.operator === '<=') {
|
|
116
|
-
conditionOp = Op.lte;
|
|
117
|
-
} else if (condition.operator === '>=') {
|
|
118
|
-
conditionOp = Op.gte;
|
|
119
|
-
} else if (condition.operator === 'in') {
|
|
120
|
-
conditionOp = Op.in;
|
|
121
|
-
} else {
|
|
122
|
-
throw new Error(`Operator ${condition.operator} not supported`);
|
|
123
|
-
}
|
|
159
|
+
const conditionOp = getSequelizeOperator(condition.operator);
|
|
124
160
|
conditions[conditionColumn] = {
|
|
125
161
|
[conditionOp]: condition.value
|
|
126
162
|
};
|
|
127
163
|
return conditions;
|
|
128
164
|
};
|
|
165
|
+
const addCondition = (conditions, condition, model)=>{
|
|
166
|
+
const conditionColumn = condition.column;
|
|
167
|
+
// Check if this is an association query (contains a dot)
|
|
168
|
+
if (conditionColumn.includes('.')) {
|
|
169
|
+
return addAssociationCondition(conditions, condition, model);
|
|
170
|
+
}
|
|
171
|
+
// Handle regular column queries
|
|
172
|
+
return addAttributeCondition(conditions, condition, model);
|
|
173
|
+
};
|
|
174
|
+
const collectAssociationsFromConditions = (conditions)=>{
|
|
175
|
+
const associations = new Set();
|
|
176
|
+
const processObject = (obj)=>{
|
|
177
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
178
|
+
// Check string keys
|
|
179
|
+
Object.keys(obj).forEach((key)=>{
|
|
180
|
+
// Check if this is an association reference ($association.attribute$)
|
|
181
|
+
if (typeof key === 'string' && key.startsWith('$') && key.endsWith('$') && key.includes('.')) {
|
|
182
|
+
const associationName = key.substring(1, key.indexOf('.'));
|
|
183
|
+
associations.add(associationName);
|
|
184
|
+
}
|
|
185
|
+
// Recursively process nested objects
|
|
186
|
+
if (typeof obj[key] === 'object') {
|
|
187
|
+
processObject(obj[key]);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
// Also check Symbol keys (for compound conditions like Op.and, Op.or)
|
|
191
|
+
Object.getOwnPropertySymbols(obj).forEach((symbol)=>{
|
|
192
|
+
if (typeof obj[symbol] === 'object') {
|
|
193
|
+
processObject(obj[symbol]);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// Handle arrays (for compound conditions that might be arrays)
|
|
198
|
+
if (Array.isArray(obj)) {
|
|
199
|
+
obj.forEach((item)=>{
|
|
200
|
+
if (typeof item === 'object') {
|
|
201
|
+
processObject(item);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
processObject(conditions);
|
|
207
|
+
return associations;
|
|
208
|
+
};
|
|
209
|
+
const addAssociationIncludes = (options, model)=>{
|
|
210
|
+
// Collect all association names used in conditions
|
|
211
|
+
const referencedAssociations = collectAssociationsFromConditions(options.where);
|
|
212
|
+
if (referencedAssociations.size > 0) {
|
|
213
|
+
options.include = options.include || [];
|
|
214
|
+
// Add each referenced association to the include array
|
|
215
|
+
referencedAssociations.forEach((associationName)=>{
|
|
216
|
+
// Check if this association is already included
|
|
217
|
+
const alreadyIncluded = options.include.some((inc)=>typeof inc === 'string' && inc === associationName || typeof inc === 'object' && inc.association === associationName);
|
|
218
|
+
if (!alreadyIncluded && model.associations && model.associations[associationName]) {
|
|
219
|
+
options.include.push({
|
|
220
|
+
model: model.associations[associationName].target,
|
|
221
|
+
as: associationName,
|
|
222
|
+
required: false // Use LEFT JOIN so records without associations are still returned
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
return options;
|
|
228
|
+
};
|
|
129
229
|
const buildQuery = (itemQuery, model)=>{
|
|
130
230
|
logger.default('build', {
|
|
131
231
|
itemQuery
|
|
@@ -175,8 +275,10 @@ const buildQuery = (itemQuery, model)=>{
|
|
|
175
275
|
];
|
|
176
276
|
});
|
|
177
277
|
}
|
|
278
|
+
// Add includes for any associations referenced in conditions
|
|
279
|
+
options = addAssociationIncludes(options, model);
|
|
178
280
|
return options;
|
|
179
281
|
};
|
|
180
282
|
|
|
181
283
|
export { addCompoundCondition, addCondition, buildQuery };
|
|
182
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
284
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUXVlcnlCdWlsZGVyLmpzIiwic291cmNlcyI6W10sInNvdXJjZXNDb250ZW50IjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7In0=
|
package/dist/es/RowProcessor.js
CHANGED
|
@@ -14,7 +14,7 @@ const processRow = async (row, keyTypes, referenceDefinitions, aggregationDefini
|
|
|
14
14
|
plain: true
|
|
15
15
|
});
|
|
16
16
|
logger.default('Adding Key to Item with Key Types: %s', stringifyJSON(keyTypes));
|
|
17
|
-
item = addKey(item, keyTypes);
|
|
17
|
+
item = addKey(row, item, keyTypes);
|
|
18
18
|
item = populateEvents(item);
|
|
19
19
|
logger.default('Key Added to Item: %s', stringifyJSON(item.key));
|
|
20
20
|
if (referenceDefinitions && referenceDefinitions.length > 0) {
|