mythix-orm 1.8.3 → 1.11.0
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/lib/connection/connection-base.d.ts +1 -0
- package/lib/connection/connection-base.js +71 -20
- package/lib/connection/literals/literal-base.js +20 -1
- package/lib/connection/query-generator-base.d.ts +1 -15
- package/lib/connection/query-generator-base.js +56 -584
- package/lib/field.js +9 -2
- package/lib/model.d.ts +17 -2
- package/lib/model.js +63 -71
- package/lib/query-engine/field-scope.js +58 -25
- package/lib/query-engine/model-scope.js +168 -35
- package/lib/query-engine/query-engine-base.js +153 -47
- package/lib/query-engine/query-engine.d.ts +37 -28
- package/lib/query-engine/query-engine.js +75 -71
- package/lib/types/concrete/datetime-type.js +1 -1
- package/lib/types/concrete/serialized-type.js +2 -2
- package/lib/types/virtual/model-type.js +3 -3
- package/lib/types/virtual/models-type.js +1 -1
- package/lib/types/virtual/relational-type-base.js +26 -26
- package/lib/utils/index.js +2 -2
- package/lib/utils/misc-utils.d.ts +0 -1
- package/lib/utils/misc-utils.js +0 -24
- package/lib/utils/model-utils.js +20 -19
- package/lib/utils/query-utils.d.ts +7 -0
- package/lib/utils/query-utils.js +175 -4
- package/package.json +1 -1
package/lib/utils/model-utils.js
CHANGED
|
@@ -9,8 +9,9 @@ function isUUID(value) {
|
|
|
9
9
|
return UUID.validate(value);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
function sanitizeFieldString(
|
|
13
|
-
|
|
12
|
+
function sanitizeFieldString(_str) {
|
|
13
|
+
let str = (typeof _str === 'symbol') ? (_str.toString()) : (_str + '');
|
|
14
|
+
return str.replace(/[^\w:.]+/g, '').replace(/([:.])+/g, '$1');
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
/// Parse a fully qualified field name.
|
|
@@ -126,19 +127,18 @@ function fieldToFullyQualifiedName(field, Model) {
|
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
function sortModelNamesByDependencyOrder(connection, _modelNames, dependencyHelper) {
|
|
129
|
-
const recursiveAdd = (modelName,
|
|
130
|
+
const recursiveAdd = (modelName, alreadyVisisted) => {
|
|
130
131
|
if (modelNames.indexOf(modelName) < 0)
|
|
131
132
|
return;
|
|
132
133
|
|
|
133
|
-
let depth = _depth || 0;
|
|
134
|
-
|
|
135
|
-
// eslint-disable-next-line no-magic-numbers
|
|
136
|
-
if (depth > 10)
|
|
137
|
-
throw new Error(`ModelUtils::sortModelNamesByDependencyOrder: Cyclic dependency detected with model "${modelName}".`);
|
|
138
|
-
|
|
139
134
|
if (finalOrder.has(modelName))
|
|
140
135
|
return;
|
|
141
136
|
|
|
137
|
+
if (alreadyVisited.has(modelName))
|
|
138
|
+
return;
|
|
139
|
+
|
|
140
|
+
alreadyVisited.add(modelName);
|
|
141
|
+
|
|
142
142
|
let dependentModelNames = modelOrderMap[modelName];
|
|
143
143
|
if (dependentModelNames == null) {
|
|
144
144
|
let Model = connection.getModel(modelName);
|
|
@@ -152,22 +152,23 @@ function sortModelNamesByDependencyOrder(connection, _modelNames, dependencyHelp
|
|
|
152
152
|
|
|
153
153
|
for (let j = 0, jl = dependentModelNames.length; j < jl; j++) {
|
|
154
154
|
let dependentModelName = dependentModelNames[j];
|
|
155
|
-
recursiveAdd(dependentModelName,
|
|
155
|
+
recursiveAdd(dependentModelName, alreadyVisited);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
finalOrder.set(modelName, dependentModelNames);
|
|
159
159
|
};
|
|
160
160
|
|
|
161
|
-
let modelOrderMap
|
|
162
|
-
let modelNames
|
|
163
|
-
let finalOrder
|
|
161
|
+
let modelOrderMap = {};
|
|
162
|
+
let modelNames = Nife.toArray(_modelNames).slice().sort();
|
|
163
|
+
let finalOrder = new Map();
|
|
164
|
+
let alreadyVisited = new Set();
|
|
164
165
|
|
|
165
166
|
for (let i = 0, il = modelNames.length; i < il; i++) {
|
|
166
167
|
let modelName = modelNames[i];
|
|
167
168
|
if (!modelName)
|
|
168
169
|
continue;
|
|
169
170
|
|
|
170
|
-
recursiveAdd(modelName);
|
|
171
|
+
recursiveAdd(modelName, alreadyVisited);
|
|
171
172
|
}
|
|
172
173
|
|
|
173
174
|
let sortedModelNames = Array.from(finalOrder.keys());
|
|
@@ -205,11 +206,11 @@ async function getRelationalModelStatusForField(connection, self, field, ...args
|
|
|
205
206
|
let primaryModelName = self.getModelName();
|
|
206
207
|
let relationalMap = {
|
|
207
208
|
[primaryModelName]: {
|
|
208
|
-
create:
|
|
209
|
-
instance:
|
|
210
|
-
modelName:
|
|
211
|
-
Model:
|
|
212
|
-
fields:
|
|
209
|
+
create: !self.isPersisted(),
|
|
210
|
+
instance: self,
|
|
211
|
+
modelName: primaryModelName,
|
|
212
|
+
Model: PrimaryModel,
|
|
213
|
+
fields: new Map(),
|
|
213
214
|
},
|
|
214
215
|
};
|
|
215
216
|
|
|
@@ -4,8 +4,15 @@ import { Model, ModelClass } from '../model';
|
|
|
4
4
|
import { QueryEngine } from '../query-engine';
|
|
5
5
|
|
|
6
6
|
export declare function parseFilterFieldAndOperator(fieldName: string): { field: string, operator: string };
|
|
7
|
+
|
|
7
8
|
export declare function generateQueryFromFilter(
|
|
8
9
|
connection: ConnectionBase,
|
|
9
10
|
Model: ModelClass,
|
|
10
11
|
filter: Array<GenericObject | Model> | GenericObject | Model,
|
|
11
12
|
): QueryEngine;
|
|
13
|
+
|
|
14
|
+
export declare function margeFields(
|
|
15
|
+
connection: ConnectionBase,
|
|
16
|
+
currentFields: Map<string, any>,
|
|
17
|
+
incomingFields: Array<any>
|
|
18
|
+
): Map<string, any>;
|
package/lib/utils/query-utils.js
CHANGED
|
@@ -34,19 +34,19 @@ const Nife = require('nife');
|
|
|
34
34
|
// WHERE firstName IN ('John', 'Bob', 'Mary')
|
|
35
35
|
|
|
36
36
|
const FILTER_OPERATORS = {
|
|
37
|
-
'=':
|
|
37
|
+
'=': (Model, fieldName, query, value) => {
|
|
38
38
|
return query.AND[fieldName].EQ(value);
|
|
39
39
|
},
|
|
40
40
|
'!=': (Model, fieldName, query, value) => {
|
|
41
41
|
return query.AND[fieldName].NEQ(value);
|
|
42
42
|
},
|
|
43
|
-
'>':
|
|
43
|
+
'>': (Model, fieldName, query, value) => {
|
|
44
44
|
return query.AND[fieldName].GT(value);
|
|
45
45
|
},
|
|
46
46
|
'>=': (Model, fieldName, query, value) => {
|
|
47
47
|
return query.AND[fieldName].GTE(value);
|
|
48
48
|
},
|
|
49
|
-
'<':
|
|
49
|
+
'<': (Model, fieldName, query, value) => {
|
|
50
50
|
return query.AND[fieldName].LT(value);
|
|
51
51
|
},
|
|
52
52
|
'<=': (Model, fieldName, query, value) => {
|
|
@@ -61,7 +61,7 @@ const FILTER_OPERATORS = {
|
|
|
61
61
|
return query.AND(Model.where[fieldName].LT(value[0]).OR[fieldName].GT(value[1]));
|
|
62
62
|
},
|
|
63
63
|
// Like
|
|
64
|
-
'*':
|
|
64
|
+
'*': (Model, fieldName, query, value) => {
|
|
65
65
|
return query.AND[fieldName].LIKE(value);
|
|
66
66
|
},
|
|
67
67
|
// NOT Like
|
|
@@ -180,7 +180,178 @@ function generateQueryFromFilter(connection, Model, _filter, _depth) {
|
|
|
180
180
|
return query;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
function margeFields(queryEngine, currentFields, _incomingFields, extraData, _options) {
|
|
184
|
+
const RESET = 0;
|
|
185
|
+
const ADD = 1;
|
|
186
|
+
const SUB = 2;
|
|
187
|
+
|
|
188
|
+
const getInitialMode = (incomingFields) => {
|
|
189
|
+
for (let i = 0, il = incomingFields.length; i < il; i++) {
|
|
190
|
+
let incomingField = incomingFields[i];
|
|
191
|
+
if (!incomingField)
|
|
192
|
+
continue;
|
|
193
|
+
|
|
194
|
+
if (typeof incomingField.isLiteral === 'function' && incomingField.isLiteral(incomingField))
|
|
195
|
+
return RESET;
|
|
196
|
+
|
|
197
|
+
if (typeof incomingField.isModelClass === 'function' && incomingField.isModelClass(incomingField))
|
|
198
|
+
return RESET;
|
|
199
|
+
|
|
200
|
+
if (typeof incomingField.isField === 'function' && incomingField.isField(incomingField))
|
|
201
|
+
return RESET;
|
|
202
|
+
|
|
203
|
+
if (!Nife.instanceOf(incomingField, 'string'))
|
|
204
|
+
RESET;
|
|
205
|
+
|
|
206
|
+
let firstChar = incomingField.charAt(0);
|
|
207
|
+
if (firstChar === '+')
|
|
208
|
+
return ADD;
|
|
209
|
+
|
|
210
|
+
if (firstChar === '-')
|
|
211
|
+
return SUB;
|
|
212
|
+
|
|
213
|
+
return RESET;
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const addOrRemove = (mode, key, item) => {
|
|
218
|
+
if (mode === ADD)
|
|
219
|
+
fields.set(key, { ...(extraData || {}), value: item });
|
|
220
|
+
else
|
|
221
|
+
fields.delete(key);
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const addOrRemoveAllModelFields = (mode, Model) => {
|
|
225
|
+
let modelName = Model.getModelName();
|
|
226
|
+
|
|
227
|
+
Model.iterateFields(({ field, fieldName }) => {
|
|
228
|
+
if (field.type.isVirtual())
|
|
229
|
+
return;
|
|
230
|
+
|
|
231
|
+
let fullFieldName = `${modelName}:${fieldName}`;
|
|
232
|
+
addOrRemove(mode, fullFieldName, field);
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
let context = queryEngine.getOperationContext();
|
|
237
|
+
let incomingFields = _incomingFields.filter(Boolean);
|
|
238
|
+
if (Nife.isEmpty(incomingFields))
|
|
239
|
+
return new Map();
|
|
240
|
+
|
|
241
|
+
let options = _options || {};
|
|
242
|
+
let connection = queryEngine.getConnection();
|
|
243
|
+
let RootModel = context.rootModel;
|
|
244
|
+
let rootModelName = RootModel.getModelName();
|
|
245
|
+
let mode = getInitialMode(incomingFields);
|
|
246
|
+
let fields = (mode === RESET) ? new Map() : new Map(currentFields);
|
|
247
|
+
let allQueryModels;
|
|
248
|
+
|
|
249
|
+
if (mode === RESET)
|
|
250
|
+
mode = ADD;
|
|
251
|
+
|
|
252
|
+
for (let i = 0, il = incomingFields.length; i < il; i++) {
|
|
253
|
+
let incomingField = incomingFields[i];
|
|
254
|
+
if (!incomingField)
|
|
255
|
+
continue;
|
|
256
|
+
|
|
257
|
+
if (typeof incomingField.isLiteral === 'function' && incomingField.isLiteral(incomingField)) {
|
|
258
|
+
if (!connection)
|
|
259
|
+
throw new Error('QueryUtils::margeFields: "connection" is required, but not found.');
|
|
260
|
+
|
|
261
|
+
let result = incomingField.toString(connection, options);
|
|
262
|
+
addOrRemove(mode, result, result);
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (typeof incomingField.isModelClass === 'function' && incomingField.isModelClass(incomingField)) {
|
|
267
|
+
addOrRemoveAllModelFields(mode, incomingField);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (typeof incomingField.isField === 'function' && incomingField.isField(incomingField)) {
|
|
272
|
+
let fullFieldName = `${incomingField.Model.getModelName()}:${incomingField.fieldName}`;
|
|
273
|
+
addOrRemove(mode, fullFieldName, incomingField);
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (!Nife.instanceOf(incomingField, 'string'))
|
|
278
|
+
continue;
|
|
279
|
+
|
|
280
|
+
if (!connection)
|
|
281
|
+
throw new Error('QueryUtils::margeFields: "connection" is required, but not found.');
|
|
282
|
+
|
|
283
|
+
if (!incomingField)
|
|
284
|
+
continue;
|
|
285
|
+
|
|
286
|
+
let firstChar = incomingField.charAt(0);
|
|
287
|
+
let currentMode = mode;
|
|
288
|
+
|
|
289
|
+
if (firstChar === '+') {
|
|
290
|
+
if (incomingField.length === 1) {
|
|
291
|
+
mode = ADD;
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
currentMode = ADD;
|
|
296
|
+
incomingField = incomingField.substring(1);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (firstChar === '-') {
|
|
300
|
+
if (incomingField.length === 1) {
|
|
301
|
+
mode = SUB;
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
currentMode = SUB;
|
|
306
|
+
incomingField = incomingField.substring(1);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (incomingField.charAt(0) === '@') {
|
|
310
|
+
incomingField = incomingField.substring(1);
|
|
311
|
+
addOrRemove(currentMode, incomingField, incomingField);
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (incomingField === '*') {
|
|
316
|
+
if (!allQueryModels)
|
|
317
|
+
allQueryModels = queryEngine.getAllModelsUsedInQuery();
|
|
318
|
+
|
|
319
|
+
for (let i = 0, il = allQueryModels.length; i < il; i++) {
|
|
320
|
+
let Model = allQueryModels[i];
|
|
321
|
+
addOrRemoveAllModelFields(currentMode, Model);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
let def = connection.parseQualifiedName(incomingField);
|
|
328
|
+
if (!def.modelName)
|
|
329
|
+
def.modelName = rootModelName;
|
|
330
|
+
|
|
331
|
+
let Model = connection.getModel(def.modelName);
|
|
332
|
+
if (!Model)
|
|
333
|
+
throw new Error(`QueryUtils::margeFields: Model "${def.modelName}" not found.`);
|
|
334
|
+
|
|
335
|
+
if (Nife.isEmpty(def.fieldNames)) {
|
|
336
|
+
addOrRemoveAllModelFields(currentMode, Model);
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
let modelName = Model.getModelName();
|
|
341
|
+
let fieldName = def.fieldNames[0];
|
|
342
|
+
let field = connection.getField(fieldName, modelName);
|
|
343
|
+
if (!field)
|
|
344
|
+
throw new Error(`QueryUtils::margeFields: Field "${fieldName}" not found.`);
|
|
345
|
+
|
|
346
|
+
let fullFieldName = `${modelName}:${fieldName}`;
|
|
347
|
+
addOrRemove(currentMode, fullFieldName, field);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return fields;
|
|
351
|
+
}
|
|
352
|
+
|
|
183
353
|
module.exports = {
|
|
184
354
|
parseFilterFieldAndOperator,
|
|
185
355
|
generateQueryFromFilter,
|
|
356
|
+
margeFields,
|
|
186
357
|
};
|