1 | 'use strict';
|
2 |
|
3 | const DataTypes = require('./data-types');
|
4 | const SqlString = require('./sql-string');
|
5 | const _ = require('lodash');
|
6 | const uuidv1 = require('uuid/v1');
|
7 | const uuidv4 = require('uuid/v4');
|
8 | const Promise = require('./promise');
|
9 | const operators = require('./operators');
|
10 | const operatorsSet = new Set(_.values(operators));
|
11 |
|
12 | let inflection = require('inflection');
|
13 |
|
14 | exports.classToInvokable = require('./utils/classToInvokable').classToInvokable;
|
15 |
|
16 | exports.Promise = Promise;
|
17 |
|
18 | function useInflection(_inflection) {
|
19 | inflection = _inflection;
|
20 | }
|
21 | exports.useInflection = useInflection;
|
22 |
|
23 | function camelizeIf(str, condition) {
|
24 | let result = str;
|
25 |
|
26 | if (condition) {
|
27 | result = camelize(str);
|
28 | }
|
29 |
|
30 | return result;
|
31 | }
|
32 | exports.camelizeIf = camelizeIf;
|
33 |
|
34 | function underscoredIf(str, condition) {
|
35 | let result = str;
|
36 |
|
37 | if (condition) {
|
38 | result = underscore(str);
|
39 | }
|
40 |
|
41 | return result;
|
42 | }
|
43 | exports.underscoredIf = underscoredIf;
|
44 |
|
45 | function isPrimitive(val) {
|
46 | const type = typeof val;
|
47 | return type === 'string' || type === 'number' || type === 'boolean';
|
48 | }
|
49 | exports.isPrimitive = isPrimitive;
|
50 |
|
51 |
|
52 | function mergeDefaults(a, b) {
|
53 | return _.mergeWith(a, b, objectValue => {
|
54 |
|
55 | if (!_.isPlainObject(objectValue) && objectValue !== undefined) {
|
56 | return objectValue;
|
57 | }
|
58 | });
|
59 | }
|
60 | exports.mergeDefaults = mergeDefaults;
|
61 |
|
62 |
|
63 |
|
64 |
|
65 | function merge() {
|
66 | const result = {};
|
67 |
|
68 | for (const obj of arguments) {
|
69 | _.forOwn(obj, (value, key) => {
|
70 | if (value !== undefined) {
|
71 | if (!result[key]) {
|
72 | result[key] = value;
|
73 | } else if (_.isPlainObject(value) && _.isPlainObject(result[key])) {
|
74 | result[key] = merge(result[key], value);
|
75 | } else if (Array.isArray(value) && Array.isArray(result[key])) {
|
76 | result[key] = value.concat(result[key]);
|
77 | } else {
|
78 | result[key] = value;
|
79 | }
|
80 | }
|
81 | });
|
82 | }
|
83 |
|
84 | return result;
|
85 | }
|
86 | exports.merge = merge;
|
87 |
|
88 | function spliceStr(str, index, count, add) {
|
89 | return str.slice(0, index) + add + str.slice(index + count);
|
90 | }
|
91 | exports.spliceStr = spliceStr;
|
92 |
|
93 | function camelize(str) {
|
94 | return str.trim().replace(/[-_\s]+(.)?/g, (match, c) => c.toUpperCase());
|
95 | }
|
96 | exports.camelize = camelize;
|
97 |
|
98 | function underscore(str) {
|
99 | return inflection.underscore(str);
|
100 | }
|
101 | exports.underscore = underscore;
|
102 |
|
103 | function singularize(str) {
|
104 | return inflection.singularize(str);
|
105 | }
|
106 | exports.singularize = singularize;
|
107 |
|
108 | function pluralize(str) {
|
109 | return inflection.pluralize(str);
|
110 | }
|
111 | exports.pluralize = pluralize;
|
112 |
|
113 | function format(arr, dialect) {
|
114 | const timeZone = null;
|
115 |
|
116 | return SqlString.format(arr[0], arr.slice(1), timeZone, dialect);
|
117 | }
|
118 | exports.format = format;
|
119 |
|
120 | function formatNamedParameters(sql, parameters, dialect) {
|
121 | const timeZone = null;
|
122 | return SqlString.formatNamedParameters(sql, parameters, timeZone, dialect);
|
123 | }
|
124 | exports.formatNamedParameters = formatNamedParameters;
|
125 |
|
126 | function cloneDeep(obj, onlyPlain) {
|
127 | obj = obj || {};
|
128 | return _.cloneDeepWith(obj, elem => {
|
129 |
|
130 | if (Array.isArray(elem) || _.isPlainObject(elem)) {
|
131 | return undefined;
|
132 | }
|
133 |
|
134 |
|
135 |
|
136 | if (onlyPlain || typeof elem === 'object') {
|
137 | return elem;
|
138 | }
|
139 |
|
140 |
|
141 | if (elem && typeof elem.clone === 'function') {
|
142 | return elem.clone();
|
143 | }
|
144 | });
|
145 | }
|
146 | exports.cloneDeep = cloneDeep;
|
147 |
|
148 |
|
149 | function mapFinderOptions(options, Model) {
|
150 | if (options.attributes && Array.isArray(options.attributes)) {
|
151 | options.attributes = Model._injectDependentVirtualAttributes(options.attributes);
|
152 | options.attributes = options.attributes.filter(v => !Model._virtualAttributes.has(v));
|
153 | }
|
154 |
|
155 | mapOptionFieldNames(options, Model);
|
156 |
|
157 | return options;
|
158 | }
|
159 | exports.mapFinderOptions = mapFinderOptions;
|
160 |
|
161 |
|
162 | function mapOptionFieldNames(options, Model) {
|
163 | if (Array.isArray(options.attributes)) {
|
164 | options.attributes = options.attributes.map(attr => {
|
165 |
|
166 | if (typeof attr !== 'string') return attr;
|
167 |
|
168 | if (Model.rawAttributes[attr] && attr !== Model.rawAttributes[attr].field) {
|
169 | return [Model.rawAttributes[attr].field, attr];
|
170 | }
|
171 | return attr;
|
172 | });
|
173 | }
|
174 |
|
175 | if (options.where && _.isPlainObject(options.where)) {
|
176 | options.where = mapWhereFieldNames(options.where, Model);
|
177 | }
|
178 |
|
179 | return options;
|
180 | }
|
181 | exports.mapOptionFieldNames = mapOptionFieldNames;
|
182 |
|
183 | function mapWhereFieldNames(attributes, Model) {
|
184 | if (attributes) {
|
185 | getComplexKeys(attributes).forEach(attribute => {
|
186 | const rawAttribute = Model.rawAttributes[attribute];
|
187 |
|
188 | if (rawAttribute && rawAttribute.field !== rawAttribute.fieldName) {
|
189 | attributes[rawAttribute.field] = attributes[attribute];
|
190 | delete attributes[attribute];
|
191 | }
|
192 |
|
193 | if (_.isPlainObject(attributes[attribute])
|
194 | && !(rawAttribute && (
|
195 | rawAttribute.type instanceof DataTypes.HSTORE
|
196 | || rawAttribute.type instanceof DataTypes.JSON))) {
|
197 | attributes[attribute] = mapOptionFieldNames({
|
198 | where: attributes[attribute]
|
199 | }, Model).where;
|
200 | }
|
201 |
|
202 | if (Array.isArray(attributes[attribute])) {
|
203 | attributes[attribute].forEach((where, index) => {
|
204 | if (_.isPlainObject(where)) {
|
205 | attributes[attribute][index] = mapWhereFieldNames(where, Model);
|
206 | }
|
207 | });
|
208 | }
|
209 |
|
210 | });
|
211 | }
|
212 |
|
213 | return attributes;
|
214 | }
|
215 | exports.mapWhereFieldNames = mapWhereFieldNames;
|
216 |
|
217 |
|
218 | function mapValueFieldNames(dataValues, fields, Model) {
|
219 | const values = {};
|
220 |
|
221 | for (const attr of fields) {
|
222 | if (dataValues[attr] !== undefined && !Model._virtualAttributes.has(attr)) {
|
223 |
|
224 | if (Model.rawAttributes[attr] && Model.rawAttributes[attr].field && Model.rawAttributes[attr].field !== attr) {
|
225 | values[Model.rawAttributes[attr].field] = dataValues[attr];
|
226 | } else {
|
227 | values[attr] = dataValues[attr];
|
228 | }
|
229 | }
|
230 | }
|
231 |
|
232 | return values;
|
233 | }
|
234 | exports.mapValueFieldNames = mapValueFieldNames;
|
235 |
|
236 | function isColString(value) {
|
237 | return typeof value === 'string' && value[0] === '$' && value[value.length - 1] === '$';
|
238 | }
|
239 | exports.isColString = isColString;
|
240 |
|
241 | function canTreatArrayAsAnd(arr) {
|
242 | return arr.some(arg => _.isPlainObject(arg) || arg instanceof Where);
|
243 | }
|
244 | exports.canTreatArrayAsAnd = canTreatArrayAsAnd;
|
245 |
|
246 | function combineTableNames(tableName1, tableName2) {
|
247 | return tableName1.toLowerCase() < tableName2.toLowerCase() ? tableName1 + tableName2 : tableName2 + tableName1;
|
248 | }
|
249 | exports.combineTableNames = combineTableNames;
|
250 |
|
251 | function toDefaultValue(value, dialect) {
|
252 | if (typeof value === 'function') {
|
253 | const tmp = value();
|
254 | if (tmp instanceof DataTypes.ABSTRACT) {
|
255 | return tmp.toSql();
|
256 | }
|
257 | return tmp;
|
258 | }
|
259 | if (value instanceof DataTypes.UUIDV1) {
|
260 | return uuidv1();
|
261 | }
|
262 | if (value instanceof DataTypes.UUIDV4) {
|
263 | return uuidv4();
|
264 | }
|
265 | if (value instanceof DataTypes.NOW) {
|
266 | return now(dialect);
|
267 | }
|
268 | if (_.isPlainObject(value) || Array.isArray(value)) {
|
269 | return _.clone(value);
|
270 | }
|
271 | return value;
|
272 | }
|
273 | exports.toDefaultValue = toDefaultValue;
|
274 |
|
275 |
|
276 |
|
277 |
|
278 |
|
279 |
|
280 |
|
281 |
|
282 |
|
283 | function defaultValueSchemable(value) {
|
284 | if (value === undefined) { return false; }
|
285 |
|
286 |
|
287 |
|
288 | if (value instanceof DataTypes.NOW) { return false; }
|
289 |
|
290 | if (value instanceof DataTypes.UUIDV1 || value instanceof DataTypes.UUIDV4) { return false; }
|
291 |
|
292 | return typeof value !== 'function';
|
293 | }
|
294 | exports.defaultValueSchemable = defaultValueSchemable;
|
295 |
|
296 | function removeNullValuesFromHash(hash, omitNull, options) {
|
297 | let result = hash;
|
298 |
|
299 | options = options || {};
|
300 | options.allowNull = options.allowNull || [];
|
301 |
|
302 | if (omitNull) {
|
303 | const _hash = {};
|
304 |
|
305 | _.forIn(hash, (val, key) => {
|
306 | if (options.allowNull.includes(key) || key.endsWith('Id') || val !== null && val !== undefined) {
|
307 | _hash[key] = val;
|
308 | }
|
309 | });
|
310 |
|
311 | result = _hash;
|
312 | }
|
313 |
|
314 | return result;
|
315 | }
|
316 | exports.removeNullValuesFromHash = removeNullValuesFromHash;
|
317 |
|
318 | function stack() {
|
319 | const orig = Error.prepareStackTrace;
|
320 | Error.prepareStackTrace = (_, stack) => stack;
|
321 | const err = new Error();
|
322 | Error.captureStackTrace(err, stack);
|
323 | const errStack = err.stack;
|
324 | Error.prepareStackTrace = orig;
|
325 | return errStack;
|
326 | }
|
327 | exports.stack = stack;
|
328 |
|
329 | const dialects = new Set(['mariadb', 'mysql', 'postgres', 'sqlite', 'mssql']);
|
330 |
|
331 | function now(dialect) {
|
332 | const d = new Date();
|
333 | if (!dialects.has(dialect)) {
|
334 | d.setMilliseconds(0);
|
335 | }
|
336 | return d;
|
337 | }
|
338 | exports.now = now;
|
339 |
|
340 |
|
341 |
|
342 |
|
343 | const TICK_CHAR = '`';
|
344 | exports.TICK_CHAR = TICK_CHAR;
|
345 |
|
346 | function addTicks(s, tickChar) {
|
347 | tickChar = tickChar || TICK_CHAR;
|
348 | return tickChar + removeTicks(s, tickChar) + tickChar;
|
349 | }
|
350 | exports.addTicks = addTicks;
|
351 |
|
352 | function removeTicks(s, tickChar) {
|
353 | tickChar = tickChar || TICK_CHAR;
|
354 | return s.replace(new RegExp(tickChar, 'g'), '');
|
355 | }
|
356 | exports.removeTicks = removeTicks;
|
357 |
|
358 |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 |
|
369 |
|
370 |
|
371 |
|
372 |
|
373 |
|
374 |
|
375 |
|
376 |
|
377 |
|
378 |
|
379 |
|
380 |
|
381 |
|
382 |
|
383 |
|
384 |
|
385 |
|
386 |
|
387 | function flattenObjectDeep(value) {
|
388 | if (!_.isPlainObject(value)) return value;
|
389 | const flattenedObj = {};
|
390 |
|
391 | function flattenObject(obj, subPath) {
|
392 | Object.keys(obj).forEach(key => {
|
393 | const pathToProperty = subPath ? `${subPath}.${key}` : key;
|
394 | if (typeof obj[key] === 'object' && obj[key] !== null) {
|
395 | flattenObject(obj[key], pathToProperty);
|
396 | } else {
|
397 | flattenedObj[pathToProperty] = _.get(obj, key);
|
398 | }
|
399 | });
|
400 | return flattenedObj;
|
401 | }
|
402 |
|
403 | return flattenObject(value, undefined);
|
404 | }
|
405 | exports.flattenObjectDeep = flattenObjectDeep;
|
406 |
|
407 |
|
408 |
|
409 |
|
410 |
|
411 |
|
412 | class SequelizeMethod {}
|
413 | exports.SequelizeMethod = SequelizeMethod;
|
414 |
|
415 | class Fn extends SequelizeMethod {
|
416 | constructor(fn, args) {
|
417 | super();
|
418 | this.fn = fn;
|
419 | this.args = args;
|
420 | }
|
421 | clone() {
|
422 | return new Fn(this.fn, this.args);
|
423 | }
|
424 | }
|
425 | exports.Fn = Fn;
|
426 |
|
427 | class Col extends SequelizeMethod {
|
428 | constructor(col, ...args) {
|
429 | super();
|
430 | if (args.length > 0) {
|
431 | col = args;
|
432 | }
|
433 | this.col = col;
|
434 | }
|
435 | }
|
436 | exports.Col = Col;
|
437 |
|
438 | class Cast extends SequelizeMethod {
|
439 | constructor(val, type, json) {
|
440 | super();
|
441 | this.val = val;
|
442 | this.type = (type || '').trim();
|
443 | this.json = json || false;
|
444 | }
|
445 | }
|
446 | exports.Cast = Cast;
|
447 |
|
448 | class Literal extends SequelizeMethod {
|
449 | constructor(val) {
|
450 | super();
|
451 | this.val = val;
|
452 | }
|
453 | }
|
454 | exports.Literal = Literal;
|
455 |
|
456 | class Json extends SequelizeMethod {
|
457 | constructor(conditionsOrPath, value) {
|
458 | super();
|
459 | if (_.isObject(conditionsOrPath)) {
|
460 | this.conditions = conditionsOrPath;
|
461 | } else {
|
462 | this.path = conditionsOrPath;
|
463 | if (value) {
|
464 | this.value = value;
|
465 | }
|
466 | }
|
467 | }
|
468 | }
|
469 | exports.Json = Json;
|
470 |
|
471 | class Where extends SequelizeMethod {
|
472 | constructor(attribute, comparator, logic) {
|
473 | super();
|
474 | if (logic === undefined) {
|
475 | logic = comparator;
|
476 | comparator = '=';
|
477 | }
|
478 |
|
479 | this.attribute = attribute;
|
480 | this.comparator = comparator;
|
481 | this.logic = logic;
|
482 | }
|
483 | }
|
484 | exports.Where = Where;
|
485 |
|
486 |
|
487 |
|
488 |
|
489 |
|
490 |
|
491 |
|
492 |
|
493 |
|
494 |
|
495 | function getOperators(obj) {
|
496 | return Object.getOwnPropertySymbols(obj).filter(s => operatorsSet.has(s));
|
497 | }
|
498 | exports.getOperators = getOperators;
|
499 |
|
500 |
|
501 |
|
502 |
|
503 |
|
504 |
|
505 |
|
506 |
|
507 | function getComplexKeys(obj) {
|
508 | return getOperators(obj).concat(Object.keys(obj));
|
509 | }
|
510 | exports.getComplexKeys = getComplexKeys;
|
511 |
|
512 |
|
513 |
|
514 |
|
515 |
|
516 |
|
517 |
|
518 |
|
519 | function getComplexSize(obj) {
|
520 | return Array.isArray(obj) ? obj.length : getComplexKeys(obj).length;
|
521 | }
|
522 | exports.getComplexSize = getComplexSize;
|
523 |
|
524 |
|
525 |
|
526 |
|
527 |
|
528 |
|
529 |
|
530 |
|
531 | function isWhereEmpty(obj) {
|
532 | return !!obj && _.isEmpty(obj) && getOperators(obj).length === 0;
|
533 | }
|
534 | exports.isWhereEmpty = isWhereEmpty;
|
535 |
|
536 |
|
537 |
|
538 |
|
539 |
|
540 |
|
541 |
|
542 |
|
543 |
|
544 | function generateEnumName(tableName, columnName) {
|
545 | return `enum_${tableName}_${columnName}`;
|
546 | }
|
547 | exports.generateEnumName = generateEnumName;
|
548 |
|
549 |
|
550 |
|
551 |
|
552 |
|
553 |
|
554 |
|
555 |
|
556 | function camelizeObjectKeys(obj) {
|
557 | const newObj = new Object();
|
558 | Object.keys(obj).forEach(key => {
|
559 | newObj[camelize(key)] = obj[key];
|
560 | });
|
561 | return newObj;
|
562 | }
|
563 | exports.camelizeObjectKeys = camelizeObjectKeys;
|
564 |
|
565 |
|
566 |
|
567 |
|
568 |
|
569 |
|
570 |
|
571 |
|
572 |
|
573 |
|
574 |
|
575 |
|
576 |
|
577 |
|
578 | function defaults(object, ...sources) {
|
579 | object = Object(object);
|
580 |
|
581 | sources.forEach(source => {
|
582 | if (source) {
|
583 | source = Object(source);
|
584 |
|
585 | getComplexKeys(source).forEach(key => {
|
586 | const value = object[key];
|
587 | if (
|
588 | value === undefined ||
|
589 | _.eq(value, Object.prototype[key]) &&
|
590 | !Object.prototype.hasOwnProperty.call(object, key)
|
591 |
|
592 | ) {
|
593 | object[key] = source[key];
|
594 | }
|
595 | });
|
596 | }
|
597 | });
|
598 |
|
599 | return object;
|
600 | }
|
601 | exports.defaults = defaults;
|
602 |
|
603 |
|
604 |
|
605 |
|
606 |
|
607 |
|
608 |
|
609 |
|
610 |
|
611 |
|
612 |
|
613 | function nameIndex(index, tableName) {
|
614 | if (tableName.tableName) tableName = tableName.tableName;
|
615 |
|
616 | if (!Object.prototype.hasOwnProperty.call(index, 'name')) {
|
617 | const fields = index.fields.map(
|
618 | field => typeof field === 'string' ? field : field.name || field.attribute
|
619 | );
|
620 | index.name = underscore(`${tableName}_${fields.join('_')}`);
|
621 | }
|
622 |
|
623 | return index;
|
624 | }
|
625 | exports.nameIndex = nameIndex;
|
626 |
|
627 |
|
628 |
|
629 |
|
630 |
|
631 |
|
632 |
|
633 |
|
634 | function intersects(arr1, arr2) {
|
635 | return arr1.some(v => arr2.includes(v));
|
636 | }
|
637 | exports.intersects = intersects;
|