@fjell/lib-sequelize 4.4.14 → 4.4.16

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.
Files changed (91) hide show
  1. package/dist/{types/Operations.d.ts → Operations.d.ts} +5 -5
  2. package/dist/{types/SequelizeLibraryFactory.d.ts → SequelizeLibraryFactory.d.ts} +4 -4
  3. package/dist/{types/contained → contained}/SequelizeLibrary.d.ts +4 -4
  4. package/dist/index.js +1488 -0
  5. package/dist/index.js.map +7 -0
  6. package/dist/logger.d.ts +2 -0
  7. package/dist/{types/ops → ops}/all.d.ts +3 -3
  8. package/dist/{types/ops → ops}/create.d.ts +3 -3
  9. package/dist/{types/ops → ops}/find.d.ts +3 -3
  10. package/dist/{types/ops → ops}/get.d.ts +1 -1
  11. package/dist/{types/ops → ops}/one.d.ts +3 -3
  12. package/dist/{types/ops → ops}/remove.d.ts +4 -3
  13. package/dist/{types/ops → ops}/update.d.ts +3 -3
  14. package/dist/{types/primary → primary}/SequelizeLibrary.d.ts +4 -4
  15. package/package.json +17 -20
  16. package/dist/cjs/AggregationBuilder.cjs +0 -65
  17. package/dist/cjs/Coordinate.cjs +0 -24
  18. package/dist/cjs/Definition.cjs +0 -25
  19. package/dist/cjs/EventCoordinator.cjs +0 -54
  20. package/dist/cjs/KeyMaster.cjs +0 -151
  21. package/dist/cjs/OperationContext.cjs +0 -161
  22. package/dist/cjs/Operations.cjs +0 -34
  23. package/dist/cjs/Options.cjs +0 -46
  24. package/dist/cjs/QueryBuilder.cjs +0 -296
  25. package/dist/cjs/ReferenceBuilder.cjs +0 -76
  26. package/dist/cjs/RowProcessor.cjs +0 -56
  27. package/dist/cjs/SequelizeLibrary.cjs +0 -56
  28. package/dist/cjs/SequelizeLibraryFactory.cjs +0 -25
  29. package/dist/cjs/contained/SequelizeLibrary.cjs +0 -31
  30. package/dist/cjs/contained/index.cjs +0 -11
  31. package/dist/cjs/index.cjs +0 -26
  32. package/dist/cjs/logger.cjs +0 -10
  33. package/dist/cjs/ops/all.cjs +0 -145
  34. package/dist/cjs/ops/create.cjs +0 -252
  35. package/dist/cjs/ops/find.cjs +0 -47
  36. package/dist/cjs/ops/get.cjs +0 -92
  37. package/dist/cjs/ops/one.cjs +0 -27
  38. package/dist/cjs/ops/remove.cjs +0 -114
  39. package/dist/cjs/ops/update.cjs +0 -120
  40. package/dist/cjs/primary/SequelizeLibrary.cjs +0 -41
  41. package/dist/cjs/primary/index.cjs +0 -11
  42. package/dist/cjs/util/general.cjs +0 -48
  43. package/dist/cjs/util/relationshipUtils.cjs +0 -117
  44. package/dist/es/AggregationBuilder.js +0 -61
  45. package/dist/es/Coordinate.js +0 -19
  46. package/dist/es/Definition.js +0 -21
  47. package/dist/es/EventCoordinator.js +0 -48
  48. package/dist/es/KeyMaster.js +0 -146
  49. package/dist/es/OperationContext.js +0 -155
  50. package/dist/es/Operations.js +0 -30
  51. package/dist/es/Options.js +0 -23
  52. package/dist/es/QueryBuilder.js +0 -290
  53. package/dist/es/ReferenceBuilder.js +0 -72
  54. package/dist/es/RowProcessor.js +0 -52
  55. package/dist/es/SequelizeLibrary.js +0 -32
  56. package/dist/es/SequelizeLibraryFactory.js +0 -21
  57. package/dist/es/contained/SequelizeLibrary.js +0 -26
  58. package/dist/es/contained/index.js +0 -2
  59. package/dist/es/index.js +0 -11
  60. package/dist/es/logger.js +0 -6
  61. package/dist/es/ops/all.js +0 -141
  62. package/dist/es/ops/create.js +0 -248
  63. package/dist/es/ops/find.js +0 -43
  64. package/dist/es/ops/get.js +0 -88
  65. package/dist/es/ops/one.js +0 -23
  66. package/dist/es/ops/remove.js +0 -110
  67. package/dist/es/ops/update.js +0 -116
  68. package/dist/es/primary/SequelizeLibrary.js +0 -36
  69. package/dist/es/primary/index.js +0 -2
  70. package/dist/es/util/general.js +0 -44
  71. package/dist/es/util/relationshipUtils.js +0 -112
  72. package/dist/index.cjs +0 -1853
  73. package/dist/index.cjs.map +0 -1
  74. package/dist/types/AggregationBuilder.d.ts +0 -5
  75. package/dist/types/EventCoordinator.d.ts +0 -6
  76. package/dist/types/KeyMaster.d.ts +0 -4
  77. package/dist/types/OperationContext.d.ts +0 -72
  78. package/dist/types/QueryBuilder.d.ts +0 -12
  79. package/dist/types/ReferenceBuilder.d.ts +0 -4
  80. package/dist/types/RowProcessor.d.ts +0 -6
  81. package/dist/types/logger.d.ts +0 -2
  82. package/dist/types/util/general.d.ts +0 -4
  83. package/dist/types/util/relationshipUtils.d.ts +0 -21
  84. package/dist/{types/Coordinate.d.ts → Coordinate.d.ts} +0 -0
  85. package/dist/{types/Definition.d.ts → Definition.d.ts} +0 -0
  86. package/dist/{types/Options.d.ts → Options.d.ts} +1 -1
  87. package/dist/{types/Registry.d.ts → Registry.d.ts} +0 -0
  88. package/dist/{types/SequelizeLibrary.d.ts → SequelizeLibrary.d.ts} +1 -1
  89. /package/dist/{types/contained → contained}/index.d.ts +0 -0
  90. /package/dist/{types/index.d.ts → index.d.ts} +0 -0
  91. /package/dist/{types/primary → primary}/index.d.ts +0 -0
@@ -1,146 +0,0 @@
1
- import LibLogger from './logger.js';
2
- import { buildRelationshipPath } from './util/relationshipUtils.js';
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 hierarchy
25
- // Find the path through the key type array
26
- const locatorIndex = kta.indexOf(locatorType);
27
- if (locatorIndex === -1) {
28
- throw new Error(`Locator type '${locatorType}' not found in key type array`);
29
- }
30
- // Start from the current item (index 0 in kta)
31
- let currentObject = item;
32
- // Traverse through each intermediate relationship to reach the target
33
- for(let i = 1; i < locatorIndex; i++){
34
- const intermediateType = kta[i];
35
- // Check if the intermediate relationship object is loaded
36
- if (currentObject[intermediateType] && typeof currentObject[intermediateType] === 'object') {
37
- currentObject = currentObject[intermediateType];
38
- } else {
39
- // Try the foreign key approach if the relationship object isn't loaded
40
- const foreignKeyField = `${intermediateType}Id`;
41
- if (typeof currentObject[foreignKeyField] !== 'undefined' && currentObject[foreignKeyField] !== null) {
42
- // We have the foreign key but not the loaded object, we can't traverse further
43
- throw new Error(`Intermediate relationship '${intermediateType}' is not loaded. Cannot traverse to '${locatorType}'. Either include the relationship in your query or ensure it's loaded.`);
44
- }
45
- throw new Error(`Intermediate relationship '${intermediateType}' is missing in the relationship chain. Expected path: ${kta.slice(0, locatorIndex + 1).join(' → ')}`);
46
- }
47
- }
48
- // Now extract the target locator value from the current object
49
- // First try to get it from the loaded relationship object
50
- if (currentObject[locatorType] && typeof currentObject[locatorType] === 'object' && typeof currentObject[locatorType].id !== 'undefined') {
51
- return currentObject[locatorType].id;
52
- }
53
- // If the relationship object isn't loaded, try the foreign key field
54
- const foreignKeyField = `${locatorType}Id`;
55
- if (typeof currentObject[foreignKeyField] !== 'undefined' && currentObject[foreignKeyField] !== null) {
56
- return currentObject[foreignKeyField];
57
- }
58
- throw new Error(`Unable to extract location key for '${locatorType}'. Neither the relationship object nor direct foreign key is available. Traversal path: ${kta.slice(0, locatorIndex + 1).join(' → ')}`);
59
- }
60
- };
61
- const removeKey = (item)=>{
62
- logger.default('Removing Key', {
63
- item
64
- });
65
- delete item.key;
66
- return item;
67
- };
68
- // export const populateKey = <
69
- // S extends string,
70
- // L1 extends string = never,
71
- // L2 extends string = never,
72
- // L3 extends string = never,
73
- // L4 extends string = never,
74
- // L5 extends string = never
75
- // >(
76
- // item: ItemProperties<S, L1, L2, L3, L4, L5>,
77
- // keyTypes: AllItemTypeArrays<S, L1, L2, L3, L4, L5>
78
- // ): ItemProperties<S, L1, L2, L3, L4, L5> => {
79
- // if (keyTypes.length === 1) {
80
- // item.key = { kt: keyTypes[0], pk: item.id };
81
- // delete item.id;
82
- // } else if (keyTypes.length === 2) {
83
- // item.key = {
84
- // kt: keyTypes[0], pk: item.id,
85
- // // TODO: Shouldn't this be inspecting the model to get the primary key type?
86
- // loc: [{ kt: keyTypes[1], lk: item[keyTypes[1] + 'Id'] }],
87
- // };
88
- // delete item.id;
89
- // delete item[keyTypes[1] + 'Id'];
90
- // } else {
91
- // throw new Error('Not implemented');
92
- // }
93
- // return item;
94
- // }
95
- const addKey = (model, item, keyTypes)=>{
96
- logger.default('Adding Key', {
97
- item
98
- });
99
- const key = {};
100
- const modelClass = model.constructor;
101
- const primaryKeyAttr = modelClass.primaryKeyAttribute;
102
- if (Array.isArray(keyTypes) && keyTypes.length > 1) {
103
- const type = [
104
- ...keyTypes
105
- ];
106
- const pkType = type.shift();
107
- Object.assign(key, {
108
- kt: pkType,
109
- pk: item[primaryKeyAttr]
110
- });
111
- // Build location keys for composite key
112
- const locationKeys = [];
113
- for (const locatorType of type){
114
- try {
115
- const lk = extractLocationKeyValue(modelClass, item, locatorType, keyTypes);
116
- locationKeys.push({
117
- kt: locatorType,
118
- lk
119
- });
120
- } catch (error) {
121
- const errorMessage = error instanceof Error ? error.message : String(error);
122
- logger.error(`Failed to extract location key for '${locatorType}'`, {
123
- error: errorMessage,
124
- item,
125
- keyTypes
126
- });
127
- throw error;
128
- }
129
- }
130
- Object.assign(key, {
131
- loc: locationKeys
132
- });
133
- } else {
134
- Object.assign(key, {
135
- kt: keyTypes[0],
136
- pk: item[primaryKeyAttr]
137
- });
138
- }
139
- Object.assign(item, {
140
- key
141
- });
142
- return item;
143
- };
144
-
145
- export { addKey, removeKey };
146
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiS2V5TWFzdGVyLmpzIiwic291cmNlcyI6W10sInNvdXJjZXNDb250ZW50IjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7In0=
@@ -1,155 +0,0 @@
1
- import LibLogger from './logger.js';
2
-
3
- function _define_property(obj, key, value) {
4
- if (key in obj) {
5
- Object.defineProperty(obj, key, {
6
- value: value,
7
- enumerable: true,
8
- configurable: true,
9
- writable: true
10
- });
11
- } else {
12
- obj[key] = value;
13
- }
14
- return obj;
15
- }
16
- const logger = LibLogger.get('sequelize', 'OperationContext');
17
- /**
18
- * Serialize an ItemKey to a string for use in sets and maps
19
- */ const serializeKey = (key)=>{
20
- if ('pk' in key && 'kt' in key && !('loc' in key)) {
21
- // PriKey
22
- return `${key.kt}:${key.pk}`;
23
- } else if ('pk' in key && 'kt' in key && 'loc' in key) {
24
- // ComKey
25
- const locStr = key.loc.map((l)=>`${l.kt}:${l.lk}`).join(',');
26
- return `${key.kt}:${key.pk}|${locStr}`;
27
- }
28
- throw new Error(`Unsupported key type: ${JSON.stringify(key)}`);
29
- };
30
- /**
31
- * Create a new OperationContext
32
- */ const createOperationContext = ()=>{
33
- const inProgress = new Set();
34
- const cache = new Map();
35
- return {
36
- inProgress,
37
- cache,
38
- markInProgress (key) {
39
- const serialized = serializeKey(key);
40
- logger.default('Marking key as in progress', {
41
- key,
42
- serialized
43
- });
44
- inProgress.add(serialized);
45
- },
46
- markComplete (key) {
47
- const serialized = serializeKey(key);
48
- logger.default('Marking key as complete', {
49
- key,
50
- serialized
51
- });
52
- inProgress.delete(serialized);
53
- },
54
- isInProgress (key) {
55
- const serialized = serializeKey(key);
56
- const result = inProgress.has(serialized);
57
- logger.default('Checking if key is in progress', {
58
- key,
59
- serialized,
60
- result
61
- });
62
- return result;
63
- },
64
- getCached (key) {
65
- const serialized = serializeKey(key);
66
- const result = cache.get(serialized);
67
- logger.default('Getting cached item', {
68
- key,
69
- serialized,
70
- found: !!result
71
- });
72
- return result;
73
- },
74
- setCached (key, item) {
75
- const serialized = serializeKey(key);
76
- logger.default('Caching item', {
77
- key,
78
- serialized
79
- });
80
- cache.set(serialized, item);
81
- },
82
- isCached (key) {
83
- const serialized = serializeKey(key);
84
- const result = cache.has(serialized);
85
- logger.default('Checking if key is cached', {
86
- key,
87
- serialized,
88
- result
89
- });
90
- return result;
91
- }
92
- };
93
- };
94
- /**
95
- * Context Manager for sharing context across operations without changing public interfaces
96
- */ class ContextManager {
97
- /**
98
- * Set the current context for the current operation chain
99
- */ setCurrentContext(context) {
100
- const contextId = Math.random().toString(36).substring(7);
101
- this.contexts.set(contextId, context);
102
- this.currentContextId = contextId;
103
- logger.default('Set current context', {
104
- contextId
105
- });
106
- return contextId;
107
- }
108
- /**
109
- * Get the current context if one is set
110
- */ getCurrentContext() {
111
- if (this.currentContextId) {
112
- const context = this.contexts.get(this.currentContextId);
113
- logger.default('Got current context', {
114
- contextId: this.currentContextId,
115
- found: !!context
116
- });
117
- return context;
118
- }
119
- return;
120
- }
121
- /**
122
- * Clear the current context
123
- */ clearCurrentContext() {
124
- if (this.currentContextId) {
125
- logger.default('Clearing current context', {
126
- contextId: this.currentContextId
127
- });
128
- this.contexts.delete(this.currentContextId);
129
- this.currentContextId = null;
130
- }
131
- }
132
- /**
133
- * Execute a function with a specific context set as current
134
- */ async withContext(context, fn) {
135
- const previousContextId = this.currentContextId;
136
- this.setCurrentContext(context);
137
- try {
138
- return await fn();
139
- } finally{
140
- this.clearCurrentContext();
141
- if (previousContextId) {
142
- this.currentContextId = previousContextId;
143
- }
144
- }
145
- }
146
- constructor(){
147
- _define_property(this, "contexts", new Map());
148
- _define_property(this, "currentContextId", null);
149
- }
150
- }
151
- // Global context manager instance
152
- const contextManager = new ContextManager();
153
-
154
- export { contextManager, createOperationContext, serializeKey };
155
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3BlcmF0aW9uQ29udGV4dC5qcyIsInNvdXJjZXMiOltdLCJzb3VyY2VzQ29udGVudCI6W10sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OyJ9
@@ -1,30 +0,0 @@
1
- import { getAllOperation } from './ops/all.js';
2
- import { getCreateOperation } from './ops/create.js';
3
- import { getFindOperation } from './ops/find.js';
4
- import { getGetOperation } from './ops/get.js';
5
- import { getOneOperation } from './ops/one.js';
6
- import { getRemoveOperation } from './ops/remove.js';
7
- import { getUpdateOperation } from './ops/update.js';
8
-
9
- const createOperations = (models, coordinate, registry, options)=>{
10
- const operations = {};
11
- // Create a definition-like object for backward compatibility with existing operation functions
12
- const definition = {
13
- coordinate,
14
- options
15
- };
16
- operations.all = getAllOperation(models, definition, registry);
17
- operations.one = getOneOperation(models, definition, registry);
18
- operations.create = getCreateOperation(models, definition, registry);
19
- operations.update = getUpdateOperation(models, definition, registry);
20
- operations.get = getGetOperation(models, definition, registry);
21
- operations.remove = getRemoveOperation(models, definition);
22
- operations.find = getFindOperation(models, definition, registry);
23
- operations.upsert = async ()=>{
24
- throw new Error('Not implemented');
25
- };
26
- return operations;
27
- };
28
-
29
- export { createOperations };
30
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3BlcmF0aW9ucy5qcyIsInNvdXJjZXMiOltdLCJzb3VyY2VzQ29udGVudCI6W10sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsifQ==
@@ -1,23 +0,0 @@
1
- import * as Library from '@fjell/lib';
2
-
3
- const DEFAULT_SEQUELIZE_OPTIONS = {
4
- deleteOnRemove: false,
5
- references: [],
6
- aggregations: []
7
- };
8
- const createOptions = (sequelizeOptions)=>{
9
- // Create the base lib options
10
- const baseOptions = Library.createOptions(sequelizeOptions);
11
- var _sequelizeOptions_deleteOnRemove, _sequelizeOptions_references, _sequelizeOptions_aggregations;
12
- // Add Sequelize-specific defaults
13
- const result = {
14
- ...baseOptions,
15
- deleteOnRemove: (_sequelizeOptions_deleteOnRemove = sequelizeOptions === null || sequelizeOptions === void 0 ? void 0 : sequelizeOptions.deleteOnRemove) !== null && _sequelizeOptions_deleteOnRemove !== void 0 ? _sequelizeOptions_deleteOnRemove : DEFAULT_SEQUELIZE_OPTIONS.deleteOnRemove,
16
- references: (_sequelizeOptions_references = sequelizeOptions === null || sequelizeOptions === void 0 ? void 0 : sequelizeOptions.references) !== null && _sequelizeOptions_references !== void 0 ? _sequelizeOptions_references : DEFAULT_SEQUELIZE_OPTIONS.references,
17
- aggregations: (_sequelizeOptions_aggregations = sequelizeOptions === null || sequelizeOptions === void 0 ? void 0 : sequelizeOptions.aggregations) !== null && _sequelizeOptions_aggregations !== void 0 ? _sequelizeOptions_aggregations : DEFAULT_SEQUELIZE_OPTIONS.aggregations
18
- };
19
- return result;
20
- };
21
-
22
- export { createOptions };
23
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3B0aW9ucy5qcyIsInNvdXJjZXMiOltdLCJzb3VyY2VzQ29udGVudCI6W10sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OyJ9
@@ -1,290 +0,0 @@
1
- import { isCondition, isPriKey, isComKey } from '@fjell/core';
2
- import { Op } from 'sequelize';
3
- import LibLogger from './logger.js';
4
- import { stringifyJSON } from './util/general.js';
5
-
6
- const logger = LibLogger.get('sequelize', 'QueryBuilder');
7
- const addDeleteQuery = (options, model)=>{
8
- logger.default(`QueryBuilder adding delete query with options: ${stringifyJSON(options)}`);
9
- if (model.getAttributes().deletedAt) {
10
- options.where['deletedAt'] = {
11
- [Op.eq]: null
12
- };
13
- } else if (model.getAttributes().isDeleted) {
14
- options.where['isDeleted'] = {
15
- [Op.eq]: false
16
- };
17
- }
18
- return options;
19
- };
20
- const addEventQueries = (options, events, model)=>{
21
- logger.default(`QueryBuilder adding event queries with options: ${stringifyJSON(options)}, events: ${stringifyJSON(events)}`);
22
- Object.keys(events).forEach((key)=>{
23
- if (!model.getAttributes()[`${key}At`]) {
24
- throw new Error(`Event ${key} is not supported on this model, column ${key}At not found`);
25
- }
26
- let whereClauses = {};
27
- const event = events[key];
28
- if (event.start) {
29
- whereClauses = {
30
- ...whereClauses,
31
- [Op.gte]: new Date(event.start)
32
- };
33
- }
34
- if (event.end) {
35
- whereClauses = {
36
- ...whereClauses,
37
- [Op.lt]: new Date(event.end)
38
- };
39
- }
40
- if (event.by) {
41
- if (!model.getAttributes()[`${key}By`]) {
42
- throw new Error(`Event ${key} is not supported on this model, column ${key}By not found`);
43
- }
44
- whereClauses = {
45
- ...whereClauses,
46
- [Op.eq]: event.by
47
- };
48
- }
49
- options.where[`${key}At`] = whereClauses;
50
- });
51
- return options;
52
- };
53
- // Add the references to the query
54
- const addReferenceQueries = (options, references, model)=>{
55
- logger.default(`QueryBuilder adding reference queries with options: ${stringifyJSON(options)}, references: ${stringifyJSON(references)}`);
56
- Object.keys(references).forEach((key)=>{
57
- logger.default(`QueryBuilder adding reference query for key: ${key}, references: ${stringifyJSON(references)}`);
58
- if (!model.getAttributes()[`${key}Id`]) {
59
- throw new Error(`Reference ${key} is not supported on this model, column ${key}Id not found`);
60
- }
61
- if (isPriKey(references[key])) {
62
- const priKey = references[key];
63
- if (priKey.pk == null || priKey.pk === '' || typeof priKey.pk === 'object' && Object.keys(priKey.pk).length === 0) {
64
- logger.error(`Reference key '${key}' has invalid pk value: ${stringifyJSON(priKey.pk)}`, {
65
- priKey,
66
- references
67
- });
68
- throw new Error(`Reference key '${key}' has invalid pk value: ${stringifyJSON(priKey.pk)}`);
69
- }
70
- logger.trace(`[QueryBuilder] Setting reference where clause: ${key}Id = ${stringifyJSON(priKey.pk)} (type: ${typeof priKey.pk})`);
71
- options.where[`${key}Id`] = {
72
- [Op.eq]: priKey.pk
73
- };
74
- } else if (isComKey(references[key])) {
75
- throw new Error('ComKeys are not supported in Sequelize');
76
- }
77
- });
78
- return options;
79
- };
80
- const addCompoundCondition = (options, compoundCondition, model)=>{
81
- // Ensure options.where exists
82
- options.where = options.where || {};
83
- let compoundOp;
84
- const compoundType = compoundCondition.compoundType;
85
- if (compoundType === "AND") {
86
- compoundOp = Op.and;
87
- } else {
88
- compoundOp = Op.or;
89
- }
90
- let conditions = {};
91
- compoundCondition.conditions.forEach((condition)=>{
92
- if (isCondition(condition)) {
93
- conditions = addCondition(conditions, condition, model);
94
- } else {
95
- throw new Error('Nest Compound conditions not supported');
96
- }
97
- });
98
- // Merge with existing where conditions instead of replacing
99
- if (Object.keys(options.where).length > 0) {
100
- // If there are existing conditions, wrap everything in an AND
101
- options.where = {
102
- [Op.and]: [
103
- options.where,
104
- {
105
- [compoundOp]: conditions
106
- }
107
- ]
108
- };
109
- } else {
110
- // If no existing conditions, just set the compound condition
111
- options.where[compoundOp] = conditions;
112
- }
113
- return options;
114
- };
115
- const getSequelizeOperator = (operator)=>{
116
- if (operator === '==') {
117
- return Op.eq;
118
- } else if (operator === '<') {
119
- return Op.lt;
120
- } else if (operator === '>') {
121
- return Op.gt;
122
- } else if (operator === '<=') {
123
- return Op.lte;
124
- } else if (operator === '>=') {
125
- return Op.gte;
126
- } else if (operator === 'in') {
127
- return Op.in;
128
- } else {
129
- throw new Error(`Operator ${operator} not supported`);
130
- }
131
- };
132
- const addAssociationCondition = (conditions, condition, model)=>{
133
- const [associationName, attributeName] = condition.column.split('.', 2);
134
- // Check if the association exists on the model
135
- if (!model.associations || !model.associations[associationName]) {
136
- throw new Error(`Association ${associationName} not found on model ${model.name}`);
137
- }
138
- const association = model.associations[associationName];
139
- const associatedModel = association.target;
140
- // Check if the attribute exists on the associated model
141
- if (!associatedModel.getAttributes()[attributeName]) {
142
- throw new Error(`Attribute ${attributeName} not found on associated model ${associatedModel.name} for association ${associationName}`);
143
- }
144
- // Use Sequelize's $association.attribute$ syntax for querying associated models
145
- const sequelizeAssociationColumn = `$${associationName}.${attributeName}$`;
146
- const conditionOp = getSequelizeOperator(condition.operator);
147
- if (condition.value == null && condition.operator !== '==' && condition.operator !== 'in') {
148
- logger.error(`Association condition for '${associationName}.${attributeName}' has undefined/null value`, {
149
- condition
150
- });
151
- throw new Error(`Association condition for '${associationName}.${attributeName}' has undefined/null value`);
152
- }
153
- logger.trace(`[QueryBuilder] Setting association condition: ${sequelizeAssociationColumn} = ${stringifyJSON(condition.value)} (type: ${typeof condition.value})`);
154
- conditions[sequelizeAssociationColumn] = {
155
- [conditionOp]: condition.value
156
- };
157
- return conditions;
158
- };
159
- const addAttributeCondition = (conditions, condition, model)=>{
160
- const conditionColumn = condition.column;
161
- if (!model.getAttributes()[conditionColumn]) {
162
- throw new Error(`Condition column ${conditionColumn} not found on model ${model.name}`);
163
- }
164
- const conditionOp = getSequelizeOperator(condition.operator);
165
- if (condition.value == null && condition.operator !== '==' && condition.operator !== 'in') {
166
- logger.error(`Attribute condition for '${conditionColumn}' has undefined/null value`, {
167
- condition
168
- });
169
- throw new Error(`Attribute condition for '${conditionColumn}' has undefined/null value`);
170
- }
171
- logger.trace(`[QueryBuilder] Setting attribute condition: ${conditionColumn} = ${stringifyJSON(condition.value)} (type: ${typeof condition.value})`);
172
- conditions[conditionColumn] = {
173
- [conditionOp]: condition.value
174
- };
175
- return conditions;
176
- };
177
- const addCondition = (conditions, condition, model)=>{
178
- const conditionColumn = condition.column;
179
- // Check if this is an association query (contains a dot)
180
- if (conditionColumn.includes('.')) {
181
- return addAssociationCondition(conditions, condition, model);
182
- }
183
- // Handle regular column queries
184
- return addAttributeCondition(conditions, condition, model);
185
- };
186
- const collectAssociationsFromConditions = (conditions)=>{
187
- const associations = new Set();
188
- const processObject = (obj)=>{
189
- if (typeof obj === 'object' && obj !== null) {
190
- // Check string keys
191
- Object.keys(obj).forEach((key)=>{
192
- // Check if this is an association reference ($association.attribute$)
193
- if (typeof key === 'string' && key.startsWith('$') && key.endsWith('$') && key.includes('.')) {
194
- const associationName = key.substring(1, key.indexOf('.'));
195
- associations.add(associationName);
196
- }
197
- // Recursively process nested objects
198
- if (typeof obj[key] === 'object') {
199
- processObject(obj[key]);
200
- }
201
- });
202
- // Also check Symbol keys (for compound conditions like Op.and, Op.or)
203
- Object.getOwnPropertySymbols(obj).forEach((symbol)=>{
204
- if (typeof obj[symbol] === 'object') {
205
- processObject(obj[symbol]);
206
- }
207
- });
208
- }
209
- // Handle arrays (for compound conditions that might be arrays)
210
- if (Array.isArray(obj)) {
211
- obj.forEach((item)=>{
212
- if (typeof item === 'object') {
213
- processObject(item);
214
- }
215
- });
216
- }
217
- };
218
- processObject(conditions);
219
- return associations;
220
- };
221
- const addAssociationIncludes = (options, model)=>{
222
- // Collect all association names used in conditions
223
- const referencedAssociations = collectAssociationsFromConditions(options.where);
224
- if (referencedAssociations.size > 0) {
225
- options.include = options.include || [];
226
- // Add each referenced association to the include array
227
- referencedAssociations.forEach((associationName)=>{
228
- // Check if this association is already included
229
- const alreadyIncluded = options.include.some((inc)=>typeof inc === 'string' && inc === associationName || typeof inc === 'object' && inc.association === associationName);
230
- if (!alreadyIncluded && model.associations && model.associations[associationName]) {
231
- options.include.push({
232
- model: model.associations[associationName].target,
233
- as: associationName,
234
- required: false // Use LEFT JOIN so records without associations are still returned
235
- });
236
- }
237
- });
238
- }
239
- return options;
240
- };
241
- const buildQuery = (itemQuery, model)=>{
242
- logger.default(`QueryBuilder build called with itemQuery: ${stringifyJSON(itemQuery)}`);
243
- let options = {
244
- where: {}
245
- };
246
- if (itemQuery.compoundCondition) {
247
- logger.default(`QueryBuilder adding conditions: ${stringifyJSON(itemQuery.compoundCondition)}`);
248
- options = addCompoundCondition(options, itemQuery.compoundCondition, model);
249
- }
250
- // If the model has a deletedAt column, we need to add a delete query
251
- if (model.getAttributes().deletedAt || model.getAttributes().isDeleted) {
252
- options = addDeleteQuery(options, model);
253
- }
254
- if (itemQuery.refs) {
255
- options = addReferenceQueries(options, itemQuery.refs, model);
256
- }
257
- if (itemQuery.events) {
258
- options = addEventQueries(options, itemQuery.events, model);
259
- }
260
- // TODO: Once we start to support Aggs on the server-side, we'll need to parse agg queries
261
- // Apply a limit to the result set
262
- if (itemQuery.limit) {
263
- logger.default(`QueryBuilder applying limit: ${itemQuery.limit}`);
264
- options.limit = itemQuery.limit;
265
- }
266
- // Apply an offset to the result set
267
- if (itemQuery.offset) {
268
- options.offset = itemQuery.offset;
269
- }
270
- // Add orderBy to the query
271
- if (itemQuery.orderBy) {
272
- itemQuery.orderBy.forEach((orderBy)=>{
273
- if (!model.getAttributes()[orderBy.field]) {
274
- throw new Error(`Order by field ${orderBy.field} not found on model ${model.name}`);
275
- }
276
- options.order = [
277
- [
278
- orderBy.field,
279
- orderBy.direction
280
- ]
281
- ];
282
- });
283
- }
284
- // Add includes for any associations referenced in conditions
285
- options = addAssociationIncludes(options, model);
286
- return options;
287
- };
288
-
289
- export { addCompoundCondition, addCondition, buildQuery };
290
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUXVlcnlCdWlsZGVyLmpzIiwic291cmNlcyI6W10sInNvdXJjZXNDb250ZW50IjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7In0=