mythix-orm 1.0.1
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/.eslintrc.js +94 -0
- package/.vscode/launch.json +34 -0
- package/.vscode/settings.json +10 -0
- package/LICENSE +21 -0
- package/README.md +15 -0
- package/lib/connection/connection-base.js +877 -0
- package/lib/connection/index.js +11 -0
- package/lib/connection/literals/average-literal.js +14 -0
- package/lib/connection/literals/count-literal.js +18 -0
- package/lib/connection/literals/distinct-literal.js +14 -0
- package/lib/connection/literals/index.js +23 -0
- package/lib/connection/literals/literal-base.js +62 -0
- package/lib/connection/literals/literal-field-base.js +45 -0
- package/lib/connection/literals/literal.js +11 -0
- package/lib/connection/literals/max-literal.js +14 -0
- package/lib/connection/literals/min-literal.js +14 -0
- package/lib/connection/literals/sum-literal.js +14 -0
- package/lib/connection/query-generator-base.js +864 -0
- package/lib/errors/base-error.js +14 -0
- package/lib/errors/connection/access-denied-error.js +13 -0
- package/lib/errors/connection/connection-acquire-timeout-error.js +13 -0
- package/lib/errors/connection/connection-refused-error.js +13 -0
- package/lib/errors/connection/connection-timed-out-error.js +13 -0
- package/lib/errors/connection/host-not-found-error.js +13 -0
- package/lib/errors/connection/host-not-reachable-error.js +13 -0
- package/lib/errors/connection/index.js +19 -0
- package/lib/errors/connection/invalid-connection-error.js +13 -0
- package/lib/errors/connection-base-error.js +13 -0
- package/lib/errors/database/exclusion-constraint-error.js +13 -0
- package/lib/errors/database/foreign-key-constraint-error.js +13 -0
- package/lib/errors/database/index.js +13 -0
- package/lib/errors/database/timeout-error.js +13 -0
- package/lib/errors/database/unknown-constraint-error.js +13 -0
- package/lib/errors/database-base-error.js +17 -0
- package/lib/errors/index.js +44 -0
- package/lib/field.js +18 -0
- package/lib/index.js +43 -0
- package/lib/model.js +1374 -0
- package/lib/proxy-class/index.js +3 -0
- package/lib/proxy-class/proxy-class.js +269 -0
- package/lib/query-engine/field-scope.js +99 -0
- package/lib/query-engine/index.js +13 -0
- package/lib/query-engine/model-scope.js +198 -0
- package/lib/query-engine/query-engine-base.js +325 -0
- package/lib/query-engine/query-engine.js +212 -0
- package/lib/types/concrete/bigint-type.js +62 -0
- package/lib/types/concrete/blob-type.js +46 -0
- package/lib/types/concrete/boolean-type.js +41 -0
- package/lib/types/concrete/char-type.js +39 -0
- package/lib/types/concrete/date-type.js +87 -0
- package/lib/types/concrete/datetime-type.js +92 -0
- package/lib/types/concrete/float-type.js +47 -0
- package/lib/types/concrete/foreign-key-type.js +208 -0
- package/lib/types/concrete/index.js +53 -0
- package/lib/types/concrete/integer-type.js +51 -0
- package/lib/types/concrete/string-type.js +44 -0
- package/lib/types/concrete/text-type.js +44 -0
- package/lib/types/concrete/uuid-base.js +77 -0
- package/lib/types/concrete/uuid-v1-type.js +99 -0
- package/lib/types/concrete/uuid-v3-type.js +108 -0
- package/lib/types/concrete/uuid-v4-type.js +90 -0
- package/lib/types/concrete/uuid-v5-type.js +108 -0
- package/lib/types/concrete/xid-type.js +58 -0
- package/lib/types/helpers/default-helpers.js +127 -0
- package/lib/types/helpers/index.js +35 -0
- package/lib/types/index.js +94 -0
- package/lib/types/type.js +244 -0
- package/lib/types/virtual/index.js +14 -0
- package/lib/types/virtual/model-type.js +141 -0
- package/lib/types/virtual/models-type.js +264 -0
- package/lib/types/virtual/relational-type-base.js +323 -0
- package/lib/utils/index.js +65 -0
- package/lib/utils/misc-utils.js +73 -0
- package/lib/utils/model-utils.js +704 -0
- package/lib/utils/query-utils.js +186 -0
- package/package.json +63 -0
- package/playground/test01.js +15 -0
- package/spec/connection/connection-base-spec.js +126 -0
- package/spec/connection/literals/average-literal-spec.js +45 -0
- package/spec/connection/literals/count-literal-spec.js +42 -0
- package/spec/connection/literals/distinct-literal-spec.js +42 -0
- package/spec/connection/literals/literal-spec.js +26 -0
- package/spec/connection/literals/max-literal-spec.js +42 -0
- package/spec/connection/literals/min-literal-spec.js +42 -0
- package/spec/connection/literals/sum-literal-spec.js +42 -0
- package/spec/helpers/default-helpers-spec.js +108 -0
- package/spec/model-spec.js +736 -0
- package/spec/proxy-class/proxy-class-spec.js +173 -0
- package/spec/query-engine/__snapshots__/QueryEngine-operations-query_operations_and_chaining-can_chain_query_conditions-001.snapshot +94 -0
- package/spec/query-engine/__snapshots__/QueryEngine-operations-query_operations_and_chaining-can_construct_a_query_context_with_a_model_call-001.snapshot +35 -0
- package/spec/query-engine/__snapshots__/QueryEngine-operations-query_operations_and_chaining-can_construct_a_query_context_with_a_model_sub-001.snapshot +35 -0
- package/spec/query-engine/__snapshots__/QueryEngine-operations-query_operations_and_chaining-can_set_a_default_scope_on_a_model-001.snapshot +57 -0
- package/spec/query-engine/__snapshots__/QueryEngine-operations-query_operations_and_chaining-can_unscope_default_scope_on_a_model-001.snapshot +35 -0
- package/spec/query-engine/query-engine-spec.js +99 -0
- package/spec/support/jasmine.json +13 -0
- package/spec/support/models/blob-test-model.js +19 -0
- package/spec/support/models/extended-user-model.js +38 -0
- package/spec/support/models/index.js +27 -0
- package/spec/support/models/number-model.js +24 -0
- package/spec/support/models/role-model.js +26 -0
- package/spec/support/models/role-thing-model.js +41 -0
- package/spec/support/models/scoped-user-model.js +13 -0
- package/spec/support/models/time-model.js +36 -0
- package/spec/support/models/user-model.js +70 -0
- package/spec/support/models/user-role-model.js +36 -0
- package/spec/support/models/user-thing-model.js +46 -0
- package/spec/support/models/validation-test-model.js +40 -0
- package/spec/support/snapshots.js +293 -0
- package/spec/support/test-helpers.js +13 -0
- package/spec/types/concrete/bigint-type-spec.js +84 -0
- package/spec/types/concrete/boolean-type-spec.js +83 -0
- package/spec/types/concrete/date-type-spec.js +85 -0
- package/spec/types/concrete/datetime-type-spec.js +87 -0
- package/spec/types/concrete/float-type-spec.js +71 -0
- package/spec/types/concrete/foreign-key-type-spec.js +64 -0
- package/spec/types/concrete/integer-type-spec.js +71 -0
- package/spec/types/concrete/string-type-spec.js +91 -0
- package/spec/types/concrete/uuid-v1-type-spec.js +73 -0
- package/spec/types/concrete/uuid-v4-type-spec.js +65 -0
- package/spec/types/type-spec.js +101 -0
- package/spec/types/virtual/model-types-spec.js +401 -0
- package/spec/utils/misc-utils-spec.js +61 -0
- package/spec/utils/model-utils-spec.js +55 -0
- package/spec/utils/query-utils-spec.js +105 -0
|
@@ -0,0 +1,877 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const moment = require('moment');
|
|
4
|
+
const EventEmitter = require('events');
|
|
5
|
+
const Nife = require('nife');
|
|
6
|
+
const SqlString = require('sqlstring');
|
|
7
|
+
const { QueryEngine } = require('../query-engine');
|
|
8
|
+
const Utils = require('../utils');
|
|
9
|
+
const ModelBase = require('../model');
|
|
10
|
+
const Literals = require('./literals');
|
|
11
|
+
const QueryGeneratorBase = require('./query-generator-base');
|
|
12
|
+
const Types = require('../types');
|
|
13
|
+
|
|
14
|
+
const LiteralBase = Literals.LiteralBase;
|
|
15
|
+
|
|
16
|
+
class ConnectionBase extends EventEmitter {
|
|
17
|
+
static dialect = 'none';
|
|
18
|
+
|
|
19
|
+
static _isMythixConnection = true;
|
|
20
|
+
|
|
21
|
+
static isConnectionClass(value) {
|
|
22
|
+
if (!value)
|
|
23
|
+
return false;
|
|
24
|
+
|
|
25
|
+
if (value.prototype instanceof ConnectionBase)
|
|
26
|
+
return true;
|
|
27
|
+
|
|
28
|
+
if (value._isMythixConnection)
|
|
29
|
+
return true;
|
|
30
|
+
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static isConnection(value) {
|
|
35
|
+
if (!value)
|
|
36
|
+
return false;
|
|
37
|
+
|
|
38
|
+
if (value instanceof ConnectionBase)
|
|
39
|
+
return true;
|
|
40
|
+
|
|
41
|
+
if (value.constructor && value.constructor._isMythixConnection)
|
|
42
|
+
return true;
|
|
43
|
+
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
constructor(_options) {
|
|
48
|
+
super();
|
|
49
|
+
|
|
50
|
+
this.setMaxListeners(0);
|
|
51
|
+
|
|
52
|
+
let options = Object.assign({
|
|
53
|
+
QueryEngine,
|
|
54
|
+
}, _options || {});
|
|
55
|
+
|
|
56
|
+
if (!options.queryGenerator)
|
|
57
|
+
options.queryGenerator = new QueryGeneratorBase(this);
|
|
58
|
+
|
|
59
|
+
Object.defineProperties(this, {
|
|
60
|
+
'dialect': {
|
|
61
|
+
enumberable: false,
|
|
62
|
+
configurable: true,
|
|
63
|
+
get: () => {
|
|
64
|
+
return this.constructor.dialect;
|
|
65
|
+
},
|
|
66
|
+
set: () => {
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
'_models': {
|
|
70
|
+
writable: true,
|
|
71
|
+
enumberable: false,
|
|
72
|
+
configurable: true,
|
|
73
|
+
value: {},
|
|
74
|
+
},
|
|
75
|
+
'_options': {
|
|
76
|
+
writable: true,
|
|
77
|
+
enumberable: false,
|
|
78
|
+
configurable: true,
|
|
79
|
+
value: options,
|
|
80
|
+
},
|
|
81
|
+
'_modelCache': {
|
|
82
|
+
writable: true,
|
|
83
|
+
enumberable: false,
|
|
84
|
+
configurable: true,
|
|
85
|
+
value: new Map(),
|
|
86
|
+
},
|
|
87
|
+
'queryGenerator': {
|
|
88
|
+
writable: true,
|
|
89
|
+
enumberable: false,
|
|
90
|
+
configurable: true,
|
|
91
|
+
value: options.queryGenerator,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
this.registerModels(options.models);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
_getFromModelCache(Model, key, defaultValue) {
|
|
99
|
+
let cache = this._modelCache.get(Model);
|
|
100
|
+
if (!cache)
|
|
101
|
+
return defaultValue;
|
|
102
|
+
|
|
103
|
+
let value = cache.get(key);
|
|
104
|
+
if (value == null)
|
|
105
|
+
return defaultValue;
|
|
106
|
+
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
_setToModelCache(Model, key, value) {
|
|
111
|
+
let cache = this._modelCache.get(Model);
|
|
112
|
+
if (!cache) {
|
|
113
|
+
cache = new Map();
|
|
114
|
+
this._modelCache.set(Model, cache);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
cache.set(key, value);
|
|
118
|
+
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
getOptions() {
|
|
123
|
+
return this._options;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
isStarted() {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
toQueryEngine(_queryEngine) {
|
|
131
|
+
let queryEngine = _queryEngine;
|
|
132
|
+
if (!queryEngine)
|
|
133
|
+
return;
|
|
134
|
+
|
|
135
|
+
if (!QueryEngine.isQuery(queryEngine)) {
|
|
136
|
+
if (Object.prototype.hasOwnProperty.call(queryEngine, 'where'))
|
|
137
|
+
queryEngine = queryEngine.where(this);
|
|
138
|
+
else
|
|
139
|
+
queryEngine = undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return queryEngine;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
registerModel(_Model) {
|
|
146
|
+
let Model = _Model.bindConnection(this);
|
|
147
|
+
|
|
148
|
+
this._models[Model.getModelName()] = Model;
|
|
149
|
+
|
|
150
|
+
return Model;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
registerModels(models) {
|
|
154
|
+
if (!models)
|
|
155
|
+
return;
|
|
156
|
+
|
|
157
|
+
let keys = Object.keys(models);
|
|
158
|
+
|
|
159
|
+
for (let i = 0, il = keys.length; i < il; i++) {
|
|
160
|
+
let key = keys[i];
|
|
161
|
+
let Model = models[key];
|
|
162
|
+
|
|
163
|
+
this.registerModel(Model);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return this._models;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
findModelField(finder) {
|
|
170
|
+
let modelMap = this.getModels();
|
|
171
|
+
let modelNames = Object.keys(modelMap);
|
|
172
|
+
let results = [];
|
|
173
|
+
|
|
174
|
+
for (let i = 0, il = modelNames.length; i < il; i++) {
|
|
175
|
+
let modelName = modelNames[i];
|
|
176
|
+
let Model = modelMap[modelName];
|
|
177
|
+
|
|
178
|
+
results = results.concat(Model.iterateFields(finder));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return results;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
parseQualifiedName(str) {
|
|
185
|
+
return Utils.parseQualifiedName(str);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
getModels() {
|
|
189
|
+
return this._models;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
getModel(modelName) {
|
|
193
|
+
if (typeof modelName === 'symbol')
|
|
194
|
+
return;
|
|
195
|
+
|
|
196
|
+
let def = this.parseQualifiedName(modelName);
|
|
197
|
+
return this._models[def.modelName];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
getField(fieldName, modelName) {
|
|
201
|
+
let def = this.parseQualifiedName(fieldName);
|
|
202
|
+
if (def.modelName == null)
|
|
203
|
+
def.modelName = modelName;
|
|
204
|
+
|
|
205
|
+
let Model = this.getModel(def.modelName);
|
|
206
|
+
if (!Model)
|
|
207
|
+
return;
|
|
208
|
+
|
|
209
|
+
return Model.getField(def.fieldNames[0]);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
getQueryEngineClass() {
|
|
213
|
+
let options = this.getOptions();
|
|
214
|
+
return options.QueryEngine;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
getQueryGenerator() {
|
|
218
|
+
return this.queryGenerator;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
setQueryGenerator(queryGenerator) {
|
|
222
|
+
this.queryGenerator = queryGenerator;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
_escape(value) {
|
|
226
|
+
return SqlString.escape(value);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
escape(field, _value) {
|
|
230
|
+
var value = _value;
|
|
231
|
+
if (value instanceof Literals.LiteralBase)
|
|
232
|
+
return value.toString(this);
|
|
233
|
+
|
|
234
|
+
value = field.type.serialize(value, this);
|
|
235
|
+
|
|
236
|
+
if (value === true) {
|
|
237
|
+
return 'TRUE';
|
|
238
|
+
} else if (value === false) {
|
|
239
|
+
return 'FALSE';
|
|
240
|
+
} else if (typeof value === 'bigint') {
|
|
241
|
+
return value.toString();
|
|
242
|
+
} else if (Array.isArray(value)) {
|
|
243
|
+
let arrayValue = this.prepareArrayValuesForSQL(value);
|
|
244
|
+
if (Nife.isEmpty(arrayValue))
|
|
245
|
+
return '';
|
|
246
|
+
|
|
247
|
+
return `(${arrayValue.map((item) => this.escape(field, item)).join(',')})`;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return this._escape(value);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
_escapeID(value) {
|
|
254
|
+
let parts = value.replace(/['"`]/g, '').split(/\.+/g);
|
|
255
|
+
return parts.map((part) => SqlString.escapeId(part).replace(/^`/, '"').replace(/`$/, '"')).join('.');
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
escapeID(value) {
|
|
259
|
+
if (value instanceof Literals.LiteralBase)
|
|
260
|
+
return value.toString(this.connection);
|
|
261
|
+
|
|
262
|
+
return this._escapeID(value);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
_averageLiteralToString(literal) {
|
|
266
|
+
if (!literal || !(literal instanceof LiteralBase))
|
|
267
|
+
return;
|
|
268
|
+
|
|
269
|
+
let queryGenerator = this.getQueryGenerator();
|
|
270
|
+
if (!queryGenerator)
|
|
271
|
+
return;
|
|
272
|
+
|
|
273
|
+
return queryGenerator._averageLiteralToString(literal);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
_countLiteralToString(literal) {
|
|
277
|
+
if (!literal || !(literal instanceof LiteralBase))
|
|
278
|
+
return;
|
|
279
|
+
|
|
280
|
+
let queryGenerator = this.getQueryGenerator();
|
|
281
|
+
if (!queryGenerator)
|
|
282
|
+
return;
|
|
283
|
+
|
|
284
|
+
return queryGenerator._countLiteralToString(literal);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
_distinctLiteralToString(literal) {
|
|
288
|
+
if (!literal || !(literal instanceof LiteralBase))
|
|
289
|
+
return;
|
|
290
|
+
|
|
291
|
+
let queryGenerator = this.getQueryGenerator();
|
|
292
|
+
if (!queryGenerator)
|
|
293
|
+
return;
|
|
294
|
+
|
|
295
|
+
return queryGenerator._distinctLiteralToString(literal);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
_maxLiteralToString(literal) {
|
|
299
|
+
if (!literal || !(literal instanceof LiteralBase))
|
|
300
|
+
return;
|
|
301
|
+
|
|
302
|
+
let queryGenerator = this.getQueryGenerator();
|
|
303
|
+
if (!queryGenerator)
|
|
304
|
+
return;
|
|
305
|
+
|
|
306
|
+
return queryGenerator._maxLiteralToString(literal);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
_minLiteralToString(literal) {
|
|
310
|
+
if (!literal || !(literal instanceof LiteralBase))
|
|
311
|
+
return;
|
|
312
|
+
|
|
313
|
+
let queryGenerator = this.getQueryGenerator();
|
|
314
|
+
if (!queryGenerator)
|
|
315
|
+
return;
|
|
316
|
+
|
|
317
|
+
return queryGenerator._minLiteralToString(literal);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
_sumLiteralToString(literal) {
|
|
321
|
+
if (!literal || !(literal instanceof LiteralBase))
|
|
322
|
+
return;
|
|
323
|
+
|
|
324
|
+
let queryGenerator = this.getQueryGenerator();
|
|
325
|
+
if (!queryGenerator)
|
|
326
|
+
return;
|
|
327
|
+
|
|
328
|
+
return queryGenerator._sumLiteralToString(literal);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
literalToString(literal) {
|
|
332
|
+
if (literal instanceof Literals.AverageLiteral)
|
|
333
|
+
return this._averageLiteralToString(literal);
|
|
334
|
+
else if (literal instanceof Literals.CountLiteral)
|
|
335
|
+
return this._countLiteralToString(literal);
|
|
336
|
+
else if (literal instanceof Literals.DistinctLiteral)
|
|
337
|
+
return this._distinctLiteralToString(literal);
|
|
338
|
+
else if (literal instanceof Literals.MaxLiteral)
|
|
339
|
+
return this._maxLiteralToString(literal);
|
|
340
|
+
else if (literal instanceof Literals.MinLiteral)
|
|
341
|
+
return this._minLiteralToString(literal);
|
|
342
|
+
else if (literal instanceof Literals.SumLiteral)
|
|
343
|
+
return this._sumLiteralToString(literal);
|
|
344
|
+
else if (literal instanceof Literals.Literal)
|
|
345
|
+
return literal.toString(this);
|
|
346
|
+
|
|
347
|
+
throw new Error(`${this.constructor.name}::literalToString: Unsupported literal ${literal}.`);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// eslint-disable-next-line no-unused-vars
|
|
351
|
+
_bigintTypeToString(type) {
|
|
352
|
+
return 'BIGINT';
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// eslint-disable-next-line no-unused-vars
|
|
356
|
+
_blobTypeToString(type) {
|
|
357
|
+
return 'BLOB';
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// eslint-disable-next-line no-unused-vars
|
|
361
|
+
_booleanTypeToString(type) {
|
|
362
|
+
return 'BOOLEAN';
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// eslint-disable-next-line no-unused-vars
|
|
366
|
+
_charTypeToString(type) {
|
|
367
|
+
return 'CHAR';
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// eslint-disable-next-line no-unused-vars
|
|
371
|
+
_dateTypeToString(type) {
|
|
372
|
+
return 'DATE';
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// eslint-disable-next-line no-unused-vars
|
|
376
|
+
_datetimeTypeToString(type) {
|
|
377
|
+
return 'DATETIME';
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// eslint-disable-next-line no-unused-vars
|
|
381
|
+
_floatTypeToString(type) {
|
|
382
|
+
return 'FLOAT';
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// eslint-disable-next-line no-unused-vars
|
|
386
|
+
_integerTypeToString(type) {
|
|
387
|
+
return 'INTEGER';
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// eslint-disable-next-line no-unused-vars
|
|
391
|
+
_stringTypeToString(type) {
|
|
392
|
+
return `VARCHAR(${type.length})`;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// eslint-disable-next-line no-unused-vars
|
|
396
|
+
_textTypeToString(type) {
|
|
397
|
+
return 'TEXT';
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// eslint-disable-next-line no-unused-vars
|
|
401
|
+
_uuidV1TypeToString(type) {
|
|
402
|
+
return `VARCHAR(${type.getTotalLength()})`;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// eslint-disable-next-line no-unused-vars
|
|
406
|
+
_uuidV3TypeToString(type) {
|
|
407
|
+
return `VARCHAR(${type.getTotalLength()})`;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// eslint-disable-next-line no-unused-vars
|
|
411
|
+
_uuidV4TypeToString(type) {
|
|
412
|
+
return `VARCHAR(${type.getTotalLength()})`;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// eslint-disable-next-line no-unused-vars
|
|
416
|
+
_uuidV5TypeToString(type) {
|
|
417
|
+
return `VARCHAR(${type.getTotalLength()})`;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// eslint-disable-next-line no-unused-vars
|
|
421
|
+
_xidTypeToString(type) {
|
|
422
|
+
return `VARCHAR(${type.getTotalLength()})`;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
typeToString(type, options) {
|
|
426
|
+
if (type instanceof Types.BigIntType)
|
|
427
|
+
return this._bigintTypeToString(type, options);
|
|
428
|
+
else if (type instanceof Types.BlobType)
|
|
429
|
+
return this._blobTypeToString(type, options);
|
|
430
|
+
else if (type instanceof Types.BooleanType)
|
|
431
|
+
return this._booleanTypeToString(type, options);
|
|
432
|
+
else if (type instanceof Types.CharType)
|
|
433
|
+
return this._charTypeToString(type, options);
|
|
434
|
+
else if (type instanceof Types.DateType)
|
|
435
|
+
return this._dateTypeToString(type, options);
|
|
436
|
+
else if (type instanceof Types.DateTimeType)
|
|
437
|
+
return this._datetimeTypeToString(type, options);
|
|
438
|
+
else if (type instanceof Types.FloatType)
|
|
439
|
+
return this._floatTypeToString(type, options);
|
|
440
|
+
else if (type instanceof Types.IntegerType)
|
|
441
|
+
return this._integerTypeToString(type, options);
|
|
442
|
+
else if (type instanceof Types.StringType)
|
|
443
|
+
return this._stringTypeToString(type, options);
|
|
444
|
+
else if (type instanceof Types.TextType)
|
|
445
|
+
return this._textTypeToString(type, options);
|
|
446
|
+
else if (type instanceof Types.UUIDV1Type)
|
|
447
|
+
return this._uuidV1TypeToString(type, options);
|
|
448
|
+
else if (type instanceof Types.UUIDV3Type)
|
|
449
|
+
return this._uuidV3TypeToString(type, options);
|
|
450
|
+
else if (type instanceof Types.UUIDV4Type)
|
|
451
|
+
return this._uuidV4TypeToString(type, options);
|
|
452
|
+
else if (type instanceof Types.UUIDV5Type)
|
|
453
|
+
return this._uuidV5TypeToString(type, options);
|
|
454
|
+
else if (type instanceof Types.XIDType)
|
|
455
|
+
return this._xidTypeToString(type, options);
|
|
456
|
+
|
|
457
|
+
throw new Error(`${this.constructor.name}::typeToString: Unsupported type ${type}.`);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
convertDateToDBTime(value) {
|
|
461
|
+
if (value instanceof Date || (value && value.constructor && value.constructor.name === 'Date'))
|
|
462
|
+
return value;
|
|
463
|
+
else if (moment.isMoment(value))
|
|
464
|
+
return value.toDate();
|
|
465
|
+
|
|
466
|
+
return value;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
ensureAllModelsAreInstances(Model, _models, options) {
|
|
470
|
+
if (!_models)
|
|
471
|
+
return [];
|
|
472
|
+
|
|
473
|
+
if (_models._mythixPreparedModels)
|
|
474
|
+
return _models._mythixPreparedModels.models;
|
|
475
|
+
|
|
476
|
+
let instantiatedModels = [];
|
|
477
|
+
let startIndex = options.startIndex || 0;
|
|
478
|
+
let models = Nife.toArray(_models);
|
|
479
|
+
let endIndex = models.length;
|
|
480
|
+
|
|
481
|
+
if (options.endIndex)
|
|
482
|
+
endIndex = Math.min(options.endIndex, endIndex);
|
|
483
|
+
else if (options.batchSize)
|
|
484
|
+
endIndex = Math.min(startIndex + options.batchSize, endIndex);
|
|
485
|
+
|
|
486
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
487
|
+
let model = models[i];
|
|
488
|
+
|
|
489
|
+
if (!ModelBase.isModel(model))
|
|
490
|
+
model = new Model(model, { connection: this });
|
|
491
|
+
|
|
492
|
+
instantiatedModels.push(model);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return instantiatedModels;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
prepareAllModelsForOperation(Model, _models, _options) {
|
|
499
|
+
if (!_models)
|
|
500
|
+
return {};
|
|
501
|
+
|
|
502
|
+
if (_models._mythixPreparedModels)
|
|
503
|
+
return _models._mythixPreparedModels;
|
|
504
|
+
|
|
505
|
+
if (Array.isArray(_models) && !_models.length)
|
|
506
|
+
return {};
|
|
507
|
+
|
|
508
|
+
let options = _options || {};
|
|
509
|
+
let finalizedModels = [];
|
|
510
|
+
let dirtyModels = [];
|
|
511
|
+
let dirtyFieldNames = {};
|
|
512
|
+
let dirtyFields = [];
|
|
513
|
+
let hasAllFieldNames = false;
|
|
514
|
+
let totalFieldCount = Model.getConcreteFieldCount();
|
|
515
|
+
let startIndex = options.startIndex || 0;
|
|
516
|
+
let models = Nife.toArray(_models);
|
|
517
|
+
let endIndex = models.length;
|
|
518
|
+
|
|
519
|
+
if (options.endIndex)
|
|
520
|
+
endIndex = Math.min(options.endIndex, endIndex);
|
|
521
|
+
else if (options.batchSize)
|
|
522
|
+
endIndex = Math.min(startIndex + options.batchSize, endIndex);
|
|
523
|
+
|
|
524
|
+
// Make sure all items are models,
|
|
525
|
+
// and find all the dirty fields
|
|
526
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
527
|
+
let model = models[i];
|
|
528
|
+
|
|
529
|
+
if (!ModelBase.isModel(model)) {
|
|
530
|
+
model = new Model(model, { connection: this });
|
|
531
|
+
} else if (model.isPersisted() && options.skipPersisted) {
|
|
532
|
+
if (model.isDirty())
|
|
533
|
+
dirtyModels.push(model);
|
|
534
|
+
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (!hasAllFieldNames) {
|
|
539
|
+
Object.assign(
|
|
540
|
+
dirtyFieldNames,
|
|
541
|
+
model._getDirtyFields({
|
|
542
|
+
update: options.isUpdateOperation,
|
|
543
|
+
insert: options.isInsertOperation,
|
|
544
|
+
}),
|
|
545
|
+
);
|
|
546
|
+
|
|
547
|
+
if (Object.keys(dirtyFieldNames).length >= totalFieldCount)
|
|
548
|
+
hasAllFieldNames = true;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
finalizedModels.push(model);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
let fieldNames = Object.keys(dirtyFieldNames);
|
|
555
|
+
for (let i = 0, il = fieldNames.length; i < il; i++) {
|
|
556
|
+
let fieldName = fieldNames[i];
|
|
557
|
+
let field = Model.getField(fieldName);
|
|
558
|
+
if (!field)
|
|
559
|
+
continue;
|
|
560
|
+
|
|
561
|
+
dirtyFields.push(field);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
let finalResult = { models: finalizedModels, dirtyFields, dirtyModels };
|
|
565
|
+
Object.defineProperties(finalResult, {
|
|
566
|
+
'_mythixPreparedModels': {
|
|
567
|
+
writable: true,
|
|
568
|
+
enumberable: false,
|
|
569
|
+
configurable: true,
|
|
570
|
+
value: finalResult,
|
|
571
|
+
},
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
return finalResult;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
splitModelAndSubModels(Model, primaryModel, _relationMap) {
|
|
578
|
+
const addModelInstance = (modelName, self) => {
|
|
579
|
+
let relatedModels = relationMap.get(modelName);
|
|
580
|
+
if (!relatedModels) {
|
|
581
|
+
relatedModels = new Set();
|
|
582
|
+
relationMap.set(modelName, relatedModels);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
relatedModels.add(self);
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
const splitSubModels = (Model, model) => {
|
|
589
|
+
if (alreadyVisitedMap.get(model))
|
|
590
|
+
return;
|
|
591
|
+
|
|
592
|
+
alreadyVisitedMap.set(model, true);
|
|
593
|
+
|
|
594
|
+
let modelName = Model.getModelName();
|
|
595
|
+
|
|
596
|
+
Model.iterateFields(({ field, fieldName }) => {
|
|
597
|
+
let fieldType = field.type;
|
|
598
|
+
if (!fieldType.isRelational())
|
|
599
|
+
return;
|
|
600
|
+
|
|
601
|
+
// We don't deal with multi-relational fields
|
|
602
|
+
if (fieldType.isManyRelation())
|
|
603
|
+
return;
|
|
604
|
+
|
|
605
|
+
let TargetModel = fieldType.getTargetModel(this);
|
|
606
|
+
let targetModelName = TargetModel.getModelName();
|
|
607
|
+
if (targetModelName === modelName || targetModelName === primaryModelName)
|
|
608
|
+
return;
|
|
609
|
+
|
|
610
|
+
let modelInstance = model[fieldName];
|
|
611
|
+
if (modelInstance == null)
|
|
612
|
+
return;
|
|
613
|
+
|
|
614
|
+
if (!(modelInstance instanceof TargetModel))
|
|
615
|
+
modelInstance = new TargetModel(modelInstance, { connection: this });
|
|
616
|
+
|
|
617
|
+
addModelInstance(targetModelName, modelInstance);
|
|
618
|
+
|
|
619
|
+
// Sub model data may have another
|
|
620
|
+
// model to create
|
|
621
|
+
splitSubModels(TargetModel, modelInstance, relationMap);
|
|
622
|
+
});
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
let alreadyVisitedMap = new Map();
|
|
626
|
+
let relationMap = _relationMap || new Map();
|
|
627
|
+
let primaryModelName = Model.getModelName();
|
|
628
|
+
|
|
629
|
+
splitSubModels(Model, primaryModel);
|
|
630
|
+
|
|
631
|
+
return relationMap;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// eslint-disable-next-line no-unused-vars
|
|
635
|
+
prepareAllModelsAndSubModelsForOperation(Model, models, _options) {
|
|
636
|
+
let primaryModelRelationMap = new Map();
|
|
637
|
+
let groupedModelMap = new Map();
|
|
638
|
+
let primaryModelName = Model.getModelName();
|
|
639
|
+
|
|
640
|
+
const addModelToGroup = (modelName, self) => {
|
|
641
|
+
let group = groupedModelMap.get(modelName);
|
|
642
|
+
if (!group) {
|
|
643
|
+
group = new Set();
|
|
644
|
+
groupedModelMap.set(modelName, group);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
group.add(self);
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
// Collect all primary models and sub-models
|
|
651
|
+
for (let i = 0, il = models.length; i < il; i++) {
|
|
652
|
+
let model = models[i];
|
|
653
|
+
if (!ModelBase.isModel(model))
|
|
654
|
+
model = new Model(model, { connection: this });
|
|
655
|
+
|
|
656
|
+
let subModels = this.splitModelAndSubModels(Model, model);
|
|
657
|
+
|
|
658
|
+
primaryModelRelationMap.set(model, subModels);
|
|
659
|
+
addModelToGroup(primaryModelName, model);
|
|
660
|
+
|
|
661
|
+
for (let [ modelName, models ] of subModels.entries()) {
|
|
662
|
+
for (let subModel of models.values())
|
|
663
|
+
addModelToGroup(modelName, subModel);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// Sort group map by model creation order
|
|
668
|
+
let sortedGroupedModelMap = new Map();
|
|
669
|
+
let sortedModelNames = Utils.sortModelNamesByCreationOrder(this, Array.from(groupedModelMap.keys()));
|
|
670
|
+
for (let i = 0, il = sortedModelNames.length; i < il; i++) {
|
|
671
|
+
let groupModelName = sortedModelNames[i];
|
|
672
|
+
let subModels = Array.from(groupedModelMap.get(groupModelName).values());
|
|
673
|
+
|
|
674
|
+
sortedGroupedModelMap.set(groupModelName, subModels);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// Now copy related field values between all instantiated models
|
|
678
|
+
for (let [ primaryModel, subModelMap ] of primaryModelRelationMap.entries()) {
|
|
679
|
+
for (let [ targetModelName, targetModels ] of subModelMap.entries()) {
|
|
680
|
+
let TargetModel = this.getModel(targetModelName);
|
|
681
|
+
|
|
682
|
+
for (let targetModel of targetModels.values()) {
|
|
683
|
+
if (targetModel !== primaryModel) {
|
|
684
|
+
Utils.setRelationalValues(this, TargetModel, targetModel, Model, primaryModel);
|
|
685
|
+
Utils.setRelationalValues(this, Model, primaryModel, TargetModel, targetModel);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
for (let [ sourceModelName, sourceModels ] of subModelMap.entries()) {
|
|
689
|
+
if (sourceModelName === targetModelName)
|
|
690
|
+
continue;
|
|
691
|
+
|
|
692
|
+
if (!TargetModel.isForeignKeyTargetModel(this, sourceModelName))
|
|
693
|
+
continue;
|
|
694
|
+
|
|
695
|
+
let SourceModel = this.getModel(sourceModelName);
|
|
696
|
+
for (let sourceModel of sourceModels.values()) {
|
|
697
|
+
if (sourceModel === primaryModel)
|
|
698
|
+
continue;
|
|
699
|
+
|
|
700
|
+
Utils.setRelationalValues(this, TargetModel, targetModel, SourceModel, sourceModel);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
return sortedGroupedModelMap;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
async bulkModelOperation(Model, _models, _options, beforeCallback, callback, afterCallback, afterOperationCallback) {
|
|
711
|
+
let models = _models;
|
|
712
|
+
if (!models)
|
|
713
|
+
return;
|
|
714
|
+
|
|
715
|
+
let inputIsArray = false;
|
|
716
|
+
if (!Array.isArray(models)) {
|
|
717
|
+
if (!models._mythixPreparedModels) {
|
|
718
|
+
if (models instanceof Map || models instanceof Set)
|
|
719
|
+
inputIsArray = true;
|
|
720
|
+
|
|
721
|
+
models = Nife.toArray(models).filter(Boolean);
|
|
722
|
+
} else {
|
|
723
|
+
inputIsArray = true;
|
|
724
|
+
}
|
|
725
|
+
} else {
|
|
726
|
+
inputIsArray = true;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
if (Nife.isEmpty(models))
|
|
730
|
+
return (inputIsArray) ? [] : undefined;
|
|
731
|
+
|
|
732
|
+
let queryGenerator = this.getQueryGenerator();
|
|
733
|
+
let options = Object.assign({}, _options || {});
|
|
734
|
+
let batchSize = options.batchSize || 500;
|
|
735
|
+
if (batchSize < 1)
|
|
736
|
+
throw new Error(`${this.constructor.name}::bulkModelOperation: "batchSize" can not be less than 1.`);
|
|
737
|
+
|
|
738
|
+
const computeBulkModels = async (Model, _models, options) => {
|
|
739
|
+
let models = Nife.toArray(_models);
|
|
740
|
+
let totalModels = models.length;
|
|
741
|
+
if (totalModels === 0)
|
|
742
|
+
return { results: finalResults, dirtyModels };
|
|
743
|
+
|
|
744
|
+
let offset = 0;
|
|
745
|
+
let finalResults = [];
|
|
746
|
+
let dirtyModels = [];
|
|
747
|
+
|
|
748
|
+
options.endIndex = 0;
|
|
749
|
+
|
|
750
|
+
while (options.endIndex < totalModels) {
|
|
751
|
+
options.startIndex = offset;
|
|
752
|
+
options.endIndex = offset + batchSize;
|
|
753
|
+
|
|
754
|
+
if (options.endIndex >= totalModels)
|
|
755
|
+
options.endIndex = totalModels;
|
|
756
|
+
|
|
757
|
+
// We need to run before callbacks first
|
|
758
|
+
// because this might change the fields
|
|
759
|
+
// that are dirty
|
|
760
|
+
let batchModelInstances = this.ensureAllModelsAreInstances(Model, models, options);
|
|
761
|
+
if (typeof beforeCallback === 'function')
|
|
762
|
+
await beforeCallback.call(this, Model, batchModelInstances, options, queryGenerator);
|
|
763
|
+
|
|
764
|
+
let preparedModels = this.prepareAllModelsForOperation(Model, batchModelInstances, Object.assign({}, options, { startIndex: 0, endIndex: batchModelInstances.length }));
|
|
765
|
+
if (preparedModels.models.length === 0) {
|
|
766
|
+
// no dirty models in this batch
|
|
767
|
+
offset += batchSize;
|
|
768
|
+
continue;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
await callback.call(this, Model, preparedModels, options, queryGenerator);
|
|
772
|
+
|
|
773
|
+
if (options.isInsertOperation)
|
|
774
|
+
dirtyModels = dirtyModels.concat(preparedModels.dirtyModels);
|
|
775
|
+
|
|
776
|
+
let batchModels = preparedModels.models;
|
|
777
|
+
if (batchModels) {
|
|
778
|
+
for (let i = 0, il = batchModels.length; i < il; i++) {
|
|
779
|
+
let batchModel = batchModels[i];
|
|
780
|
+
batchModel.clearDirty();
|
|
781
|
+
finalResults.push(batchModel);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
offset += batchSize;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
return { results: finalResults, dirtyModels };
|
|
789
|
+
};
|
|
790
|
+
|
|
791
|
+
if (options.isDeleteOperation) {
|
|
792
|
+
// For delete we DO NOT want to collect
|
|
793
|
+
// related models... just delete what we have
|
|
794
|
+
let { results } = await computeBulkModels(Model, models, options);
|
|
795
|
+
return (inputIsArray || !results) ? results : results[0];
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
let primaryModelName = Model.getModelName();
|
|
799
|
+
let groupedModelMap = this.prepareAllModelsAndSubModelsForOperation(Model, models, options);
|
|
800
|
+
let alreadyStored = {};
|
|
801
|
+
let allDirtyModels = new Set();
|
|
802
|
+
let primaryResult;
|
|
803
|
+
|
|
804
|
+
for (let [ modelName, models ] of groupedModelMap) {
|
|
805
|
+
let GroupModel = this.getModel(modelName);
|
|
806
|
+
let { results, dirtyModels } = await computeBulkModels(GroupModel, models, options);
|
|
807
|
+
|
|
808
|
+
// If prepareAllModelsForOperation found persisted
|
|
809
|
+
// models that were dirty, then add them here
|
|
810
|
+
if (dirtyModels && dirtyModels.length > 0) {
|
|
811
|
+
for (let i = 0, il = dirtyModels.length; i < il; i++)
|
|
812
|
+
allDirtyModels.add(dirtyModels[i]);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
alreadyStored[modelName] = true;
|
|
816
|
+
|
|
817
|
+
if (modelName === primaryModelName)
|
|
818
|
+
primaryResult = results;
|
|
819
|
+
|
|
820
|
+
for (let storedModel of results) {
|
|
821
|
+
for (let [ groupModelName, groupModels ] of groupedModelMap) {
|
|
822
|
+
if (groupModelName === modelName)
|
|
823
|
+
continue;
|
|
824
|
+
|
|
825
|
+
if (!alreadyStored[groupModelName])
|
|
826
|
+
continue;
|
|
827
|
+
|
|
828
|
+
let TargetModel = this.getModel(groupModelName);
|
|
829
|
+
if (!TargetModel.isForeignKeyTargetModel(this, modelName))
|
|
830
|
+
continue;
|
|
831
|
+
|
|
832
|
+
for (let targetModel of groupModels) {
|
|
833
|
+
Utils.setRelationalValues(this, TargetModel, targetModel, GroupModel, storedModel);
|
|
834
|
+
|
|
835
|
+
if (targetModel.isDirty())
|
|
836
|
+
allDirtyModels.add(targetModel);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
if (typeof afterCallback === 'function')
|
|
842
|
+
await afterCallback.call(this, GroupModel, results, options, queryGenerator);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
if (allDirtyModels.size > 0 && typeof afterOperationCallback === 'function')
|
|
846
|
+
await afterOperationCallback.call(this, Model, allDirtyModels, options, queryGenerator);
|
|
847
|
+
|
|
848
|
+
return (inputIsArray || !primaryResult) ? primaryResult : primaryResult[0];
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
setPersisted(_models, value) {
|
|
852
|
+
let models = _models;
|
|
853
|
+
if (models._mythixPreparedModels)
|
|
854
|
+
models = models.models;
|
|
855
|
+
|
|
856
|
+
if (Nife.isEmpty(models))
|
|
857
|
+
return;
|
|
858
|
+
|
|
859
|
+
for (let i = 0, il = models.length; i < il; i++) {
|
|
860
|
+
let model = models[i];
|
|
861
|
+
if (!model || !model._mythixModelInstance)
|
|
862
|
+
continue;
|
|
863
|
+
|
|
864
|
+
model._persisted = value;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
async start() {
|
|
869
|
+
throw new Error(`${this.constructor.name}::start: Child class is required to implement "start".`);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
async stop() {
|
|
873
|
+
this.removeAllListeners();
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
module.exports = ConnectionBase;
|