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.
@@ -9,8 +9,9 @@ function isUUID(value) {
9
9
  return UUID.validate(value);
10
10
  }
11
11
 
12
- function sanitizeFieldString(str) {
13
- return ('' + str).replace(/[^\w:.]+/g, '').replace(/([:.])+/g, '$1');
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, _depth) => {
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, depth + 1);
155
+ recursiveAdd(dependentModelName, alreadyVisited);
156
156
  }
157
157
 
158
158
  finalOrder.set(modelName, dependentModelNames);
159
159
  };
160
160
 
161
- let modelOrderMap = {};
162
- let modelNames = Nife.toArray(_modelNames).slice().sort();
163
- let finalOrder = new Map();
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: !self.isPersisted(),
209
- instance: self,
210
- modelName: primaryModelName,
211
- Model: PrimaryModel,
212
- fields: new Map(),
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>;
@@ -34,19 +34,19 @@ const Nife = require('nife');
34
34
  // WHERE firstName IN ('John', 'Bob', 'Mary')
35
35
 
36
36
  const FILTER_OPERATORS = {
37
- '=': (Model, fieldName, query, value) => {
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
- '>': (Model, fieldName, query, value) => {
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
- '<': (Model, fieldName, query, value) => {
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
- '*': (Model, fieldName, query, value) => {
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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mythix-orm",
3
- "version": "1.8.3",
3
+ "version": "1.11.0",
4
4
  "description": "ORM for Mythix framework",
5
5
  "main": "lib/index",
6
6
  "type": "commonjs",