mythix-orm 1.7.2 → 1.8.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.
@@ -81,8 +81,12 @@ declare class ConnectionBase extends EventEmitter {
81
81
  public getOptions(): ConnectionBaseOptions;
82
82
  public isStarted(): boolean;
83
83
  public toQueryEngine(queryEngineLike: any): QueryEngine | undefined;
84
- public registerModel<T = ModelClass>(Model: T): T;
85
- public registerModels(models: Models | Array<ModelClass>): Models | undefined;
84
+ public registerModel<T = ModelClass>(Model: T, options?: GenericObject): T;
85
+ public registerModels(models: Models | Array<ModelClass>, options?: GenericObject): Models | undefined;
86
+ public getContextValue(key: any, defaultValue?: any): any;
87
+ public setContextValue(key: any, value: any): any;
88
+ public buildConnectionContext(connection?: ConnectionBase): Map<any, any>;
89
+ public createContext(callback: Function, connection?: ConnectionBase, thisArg?: any): Promise<any>;
86
90
  public findModelField(finder: IterateFieldsCallback): Array<Field>;
87
91
  public parseQualifiedName(fullyQualifiedName: string): FullyQualifiedFieldDefinition;
88
92
  public getModels(): Models;
@@ -227,7 +227,7 @@ class ConnectionBase extends EventEmitter {
227
227
  return;
228
228
 
229
229
  if (!QueryEngine.isQuery(queryEngine)) {
230
- if (Object.prototype.hasOwnProperty.call(queryEngine, 'where'))
230
+ if ('where' in queryEngine)
231
231
  queryEngine = queryEngine.where(this);
232
232
  else
233
233
  queryEngine = undefined;
@@ -236,15 +236,15 @@ class ConnectionBase extends EventEmitter {
236
236
  return queryEngine;
237
237
  }
238
238
 
239
- registerModel(_Model) {
240
- let Model = _Model.bindConnection(this);
239
+ registerModel(_Model, options) {
240
+ let Model = _Model.bindConnection(this, options);
241
241
 
242
242
  this._models[Model.getModelName()] = Model;
243
243
 
244
244
  return Model;
245
245
  }
246
246
 
247
- registerModels(models) {
247
+ registerModels(models, options) {
248
248
  if (!models)
249
249
  return;
250
250
 
@@ -254,12 +254,90 @@ class ConnectionBase extends EventEmitter {
254
254
  let key = keys[i];
255
255
  let Model = models[key];
256
256
 
257
- this.registerModel(Model);
257
+ this.registerModel(Model, options);
258
258
  }
259
259
 
260
260
  return this._models;
261
261
  }
262
262
 
263
+ /// Get a value from the `AsyncLocalStorage` context.
264
+ ///
265
+ /// [AsyncLocalStorage](https://nodejs.org/docs/latest-v16.x/api/async_context.html)
266
+ /// is used primarily for two purposes: 1) to provide a connection to models, and 2) to
267
+ /// pass a transaction connection down through the call stack. However, it can
268
+ /// also be used for any "context" level values the user wishes to store.
269
+ ///
270
+ /// Note:
271
+ /// An `AsyncLocalStorage` context might not exist when this call is made,
272
+ /// in which case this method will return `undefined`, or the `defaultValue`
273
+ /// if any was provided.
274
+ ///
275
+ /// Return: any
276
+ ///
277
+ /// Arguments:
278
+ /// key: any
279
+ /// The key for the value you wish to fetch.
280
+ /// The underlying "context" provided by `AsyncLocalStorage`
281
+ /// is a `Map`, so the "key" can be any value.
282
+ /// defaultValue?: any
283
+ /// The default value to return if there is no current `AsyncLocalStorage`
284
+ /// context, or if the requested key is not found.
285
+ getContextValue(key, defaultValue) {
286
+ return Utils.getContextValue(key, defaultValue);
287
+ }
288
+
289
+ /// Set a value onto the `AsyncLocalStorage` context.
290
+ ///
291
+ /// [AsyncLocalStorage](https://nodejs.org/docs/latest-v16.x/api/async_context.html)
292
+ /// is used primarily for two purposes: 1) to provide a connection to models, and 2) to
293
+ /// pass a transaction connection down through the call stack. However, it can
294
+ /// also be used for any "context" level values the user wishes to store.
295
+ ///
296
+ /// Note:
297
+ /// An `AsyncLocalStorage` context might not exist when this call is made,
298
+ /// in which case this method will do nothing, and silently return.
299
+ ///
300
+ /// Return: any
301
+ ///
302
+ /// Arguments:
303
+ /// key: any
304
+ /// The key for the value you wish to set.
305
+ /// The underlying "context" provided by `AsyncLocalStorage`
306
+ /// is a `Map`, so the "key" can be any value.
307
+ /// value: any
308
+ /// The value to set to the specified key.
309
+ setContextValue(key, value) {
310
+ return Utils.setContextValue(key, value);
311
+ }
312
+
313
+ buildConnectionContext(_connection) {
314
+ let connection = _connection || this;
315
+ let models = connection._models;
316
+ let modelNames = Object.keys(models);
317
+ let newContext = new Map();
318
+
319
+ newContext.set('connection', connection);
320
+
321
+ for (let i = 0, il = modelNames.length; i < il; i++) {
322
+ let modelName = modelNames[i];
323
+ let Model = models[modelName];
324
+ let currentModelScope = Model.getModelContext();
325
+
326
+ newContext.set(modelName, { ...currentModelScope, connection });
327
+ }
328
+
329
+ return newContext;
330
+ }
331
+
332
+ async createContext(callback, _connection, thisArg) {
333
+ let connection = _connection || this;
334
+ let context = this.buildConnectionContext(connection);
335
+
336
+ return await Utils.runInContext(context, async () => {
337
+ return await callback.call(thisArg, connection);
338
+ });
339
+ }
340
+
263
341
  findModelField(finder) {
264
342
  let modelMap = this.getModels();
265
343
  let modelNames = Object.keys(modelMap);
@@ -1248,7 +1326,7 @@ class ConnectionBase extends EventEmitter {
1248
1326
 
1249
1327
  // eslint-disable-next-line no-unused-vars
1250
1328
  async query(sql, options) {
1251
- throw new Error(`${this.constructor.name}::transaction: This operation is not supported for this connection type.`);
1329
+ throw new Error(`${this.constructor.name}::query: This operation is not supported for this connection type.`);
1252
1330
  }
1253
1331
 
1254
1332
  // eslint-disable-next-line no-unused-vars
package/lib/field.js CHANGED
@@ -67,6 +67,7 @@
67
67
  /// Interface:
68
68
  /// interface DefaultValueContext {
69
69
  /// _initial: boolean; // If `true`, then this is the initial set of the field's value.
70
+ /// _static: boolean; // If `true`, then this will be used in a "static" context, such as the `DEFAULT` of the DB.
70
71
  /// connection: Connection; // The connection from the model.
71
72
  /// data: object | undefined; // All attributes provided to the model upon instantiation.
72
73
  /// field: Field; // The field descriptor where this `defaultValue` is defined.
@@ -113,8 +114,15 @@
113
114
  /// This has no effect client-side in JavaScript. Even if `allowNull`
114
115
  /// is `false`, the field property on your model may still have a
115
116
  /// `null` value in JavaScript.
116
- /// index: boolean = false
117
+ /// index: Array<boolean | string> | boolean = false
117
118
  /// If `true`, then this field will be indexed in the database.
119
+ /// If an array is provided, then it must be an array containing
120
+ /// other field names to combine with this field to create a combined
121
+ /// index. For example: `index: [ true, 'firstName', 'lastName', [ 'firstName', 'lastName' ] ]`
122
+ /// would create four indexes: `true` means index this field, `firstName` would create
123
+ /// the combination index `this_field_first_name`, `lastName` would create the
124
+ /// combination index `this_field_last_name`, and `[ 'firstName', 'lastName ]` would
125
+ /// create the combination index `this_field_first_name_last_name`.
118
126
  /// unique: boolean = false
119
127
  /// If `true`, then add a unique constraint to this field in
120
128
  /// the underlying database.
package/lib/model.d.ts CHANGED
@@ -15,7 +15,7 @@ export declare interface ModelOptions extends GenericObject {
15
15
  export declare type ModelClass = typeof Model;
16
16
 
17
17
  export declare interface Models {
18
- [ key: string ]: ModelClass;
18
+ [key: string]: ModelClass;
19
19
  }
20
20
 
21
21
  export declare interface HookContext {
@@ -25,11 +25,11 @@ export declare interface HookContext {
25
25
  }
26
26
 
27
27
  export declare interface DirtyChanges {
28
- [ key: string ]: { previous: any; current: any };
28
+ [key: string]: { previous: any; current: any };
29
29
  }
30
30
 
31
- export declare type LooseFields = Array<Field | FieldDefinition> | { [ key: string ]: Field | FieldDefinition } | Map<string, Field | FieldDefinition> | Set<Field | FieldDefinition>;
32
- export declare type Fields = Array<Field> | { [ key: string ]: Field } | Map<string, Field> | Set<Field>;
31
+ export declare type LooseFields = Array<Field | FieldDefinition> | { [key: string]: Field | FieldDefinition } | Map<string, Field | FieldDefinition> | Set<Field | FieldDefinition>;
32
+ export declare type Fields = Array<Field> | { [key: string]: Field } | Map<string, Field> | Set<Field>;
33
33
 
34
34
  export declare interface IterateFieldsContext {
35
35
  field: Field;
@@ -54,6 +54,18 @@ export declare class Model {
54
54
  public static isModel(value: any): boolean;
55
55
  public static toString(showFields: boolean): string;
56
56
 
57
+ static getContextValue(key: any, defaultValue?: any): any;
58
+ getContextValue(key: any, defaultValue?: any): any;
59
+
60
+ static setContextValue(key: any, value: any): void;
61
+ setContextValue(key: any, value: any): void;
62
+
63
+ public static getModelContext(): GenericObject;
64
+ getModelContext(): GenericObject;
65
+
66
+ static updateModelContext(value: GenericObject): void;
67
+ updateModelContext(value: GenericObject): void;
68
+
57
69
  public static _getConnection(connection?: ConnectionBase): ConnectionBase;
58
70
  public _getConnection(connection?: ConnectionBase): ConnectionBase;
59
71
 
package/lib/model.js CHANGED
@@ -5,6 +5,7 @@ const Inflection = require('inflection');
5
5
  const Type = require('./types/type');
6
6
  const DefaultHelpers = require('./types/helpers/default-helpers');
7
7
  const Field = require('./field');
8
+ const AsyncStore = require('./utils/async-store');
8
9
  const ModelUtils = require('./utils/model-utils');
9
10
 
10
11
  /// Used as a unique key for cache.
@@ -45,24 +46,21 @@ function bindStaticWhereToModelClass(ModelClass) {
45
46
  set: function() {},
46
47
  get: function() {
47
48
  const self = this;
49
+ let connection = self._getConnection();
50
+ if (connection)
51
+ return self.getQueryEngine(connection);
48
52
 
49
53
  function unboundWhere(_connection, _propName) {
50
54
  let connection = _connection;
51
-
52
- if (arguments.length === 0) {
53
- connection = self._getConnection();
54
- if (!connection)
55
- throw new Error(`${self.getModelName()}::where: Model has no bound connection. You need to provide a connection by calling "${self.getModelName()}.where(connection)" instead.`);
56
-
57
- return self.getQueryEngine(connection);
58
- }
59
-
60
55
  if (!connection) {
61
56
  connection = self._getConnection();
62
57
  if (!connection)
63
58
  throw new Error(`${self.getModelName()}::where: Model has no bound connection. You need to provide a connection by calling "${self.getModelName()}.where(connection)" instead.`);
64
59
  }
65
60
 
61
+ if (arguments.length === 0)
62
+ return self.getQueryEngine(connection);
63
+
66
64
  let propName = _propName;
67
65
 
68
66
  if (connection.constructor && !connection.constructor._isMythixConnection) {
@@ -94,7 +92,12 @@ function bindStaticWhereToModelClass(ModelClass) {
94
92
  // This will throw an exception
95
93
  // if no connection is available
96
94
  let queryEngine = self.getQueryEngine(connection);
97
- return queryEngine[propName];
95
+ let prop = queryEngine[propName];
96
+
97
+ if (typeof prop === 'function' && typeof prop.bind === 'function')
98
+ prop = prop.bind(queryEngine);
99
+
100
+ return prop;
98
101
  },
99
102
  });
100
103
  },
@@ -223,6 +226,146 @@ class Model {
223
226
  return this.toString((depth !== 0));
224
227
  }
225
228
 
229
+ /// Get a value from the `AsyncLocalStorage` context.
230
+ ///
231
+ /// [AsyncLocalStorage](https://nodejs.org/docs/latest-v16.x/api/async_context.html)
232
+ /// is used primarily for two purposes: 1) to provide a connection to models, and 2) to
233
+ /// pass a transaction connection down through the call stack. However, it can
234
+ /// also be used for any "context" level values the user wishes to store.
235
+ ///
236
+ /// Note:
237
+ /// An `AsyncLocalStorage` context might not exist when this call is made,
238
+ /// in which case this method will return `undefined`, or the `defaultValue`
239
+ /// if any was provided.
240
+ ///
241
+ /// Return: any
242
+ ///
243
+ /// Arguments:
244
+ /// key: any
245
+ /// The key for the value you wish to fetch.
246
+ /// The underlying "context" provided by `AsyncLocalStorage`
247
+ /// is a `Map`, so the "key" can be any value.
248
+ /// defaultValue?: any
249
+ /// The default value to return if there is no current `AsyncLocalStorage`
250
+ /// context, or if the requested key is not found.
251
+ static getContextValue(key, defaultValue) {
252
+ return AsyncStore.getContextValue(key, defaultValue);
253
+ }
254
+
255
+ getContextValue(key, defaultValue) {
256
+ return this.constructor.getContextValue(key, defaultValue);
257
+ }
258
+
259
+ /// Set a value onto the `AsyncLocalStorage` context.
260
+ ///
261
+ /// [AsyncLocalStorage](https://nodejs.org/docs/latest-v16.x/api/async_context.html)
262
+ /// is used primarily for two purposes: 1) to provide a connection to models, and 2) to
263
+ /// pass a transaction connection down through the call stack. However, it can
264
+ /// also be used for any "context" level values the user wishes to store.
265
+ ///
266
+ /// Note:
267
+ /// An `AsyncLocalStorage` context might not exist when this call is made,
268
+ /// in which case this method will do nothing, and silently return.
269
+ ///
270
+ /// Return: any
271
+ ///
272
+ /// Arguments:
273
+ /// key: any
274
+ /// The key for the value you wish to set.
275
+ /// The underlying "context" provided by `AsyncLocalStorage`
276
+ /// is a `Map`, so the "key" can be any value.
277
+ /// value: any
278
+ /// The value to set to the specified key.
279
+ static setContextValue(key, value) {
280
+ return AsyncStore.setContextValue(key, value);
281
+ }
282
+
283
+ setContextValue(key, value) {
284
+ return this.constructor.setContextValue(key, value);
285
+ }
286
+
287
+ /// Get this Model class's "model context" from the `AsyncLocalStorage` context.
288
+ ///
289
+ /// [AsyncLocalStorage](https://nodejs.org/docs/latest-v16.x/api/async_context.html)
290
+ /// is used primarily for two purposes: 1) to provide a connection to models, and 2) to
291
+ /// pass a transaction connection down through the call stack. However, it can
292
+ /// also be used for any "context" level values the user wishes to store.
293
+ ///
294
+ /// When a <see>Connection.createContext</see> or <see>Connection.transaction</see>
295
+ /// call is made, a "model context" (that is just an Object instance) is created for each
296
+ /// model the connection is aware of, and the `connection` instance is added to this
297
+ /// context, allowing models to lookup the "context connection" when a call to
298
+ /// <see>Model._getConnection</see> is made. By default, these "model contexts"
299
+ /// that are stored inside the `AsyncLocalStorage` context only contain a "connection"
300
+ /// property. However, these model contexts were designed as Object instances so that
301
+ /// the user may also use them, or so they can be used for future features. Each model
302
+ /// also has its own "model context" so that if the application is using more than
303
+ /// one connection, then a different connection can be specified for each model and
304
+ /// stored in the same `AsyncLocalStorage` context.
305
+ ///
306
+ /// Note:
307
+ /// An `AsyncLocalStorage` context might not exist when this call is made,
308
+ /// in which case this method will simply return an empty object.
309
+ ///
310
+ /// Return: object
311
+ /// The model class's "model context" stored in `AsyncLocalStorage`.
312
+ /// This will be an empty object if no `AsyncLocalStorage` context is
313
+ /// available.
314
+ static getModelContext() {
315
+ return AsyncStore.getContextValue(this.getModelName(), {});
316
+ }
317
+
318
+ getModelContext() {
319
+ return this.constructor.getModelContext();
320
+ }
321
+
322
+ /// Update this Model class's "model context" from the `AsyncLocalStorage` context.
323
+ ///
324
+ /// [AsyncLocalStorage](https://nodejs.org/docs/latest-v16.x/api/async_context.html)
325
+ /// is used primarily for two purposes: 1) to provide a connection to models, and 2) to
326
+ /// pass a transaction connection down through the call stack. However, it can
327
+ /// also be used for any "context" level values the user wishes to store.
328
+ ///
329
+ /// When a <see>Connection.createContext</see> or <see>Connection.transaction</see>
330
+ /// call is made, a "model context" (that is just an Object instance) is created for each
331
+ /// model the connection is aware of, and the `connection` instance is added to this
332
+ /// context, allowing models to lookup the "context connection" when a call to
333
+ /// <see>Model._getConnection</see> is made. By default, these "model contexts"
334
+ /// that are stored inside the `AsyncLocalStorage` context only contain a "connection"
335
+ /// property. However, these model contexts were designed as Object instances so that
336
+ /// the user may also use them, or so they can be used for future features. Each model
337
+ /// also has its own "model context" so that if the application is using more than
338
+ /// one connection, then a different connection can be specified for each model and
339
+ /// stored in the same `AsyncLocalStorage` context.
340
+ ///
341
+ /// This method allows you to update this "model context" for the model. The `value`
342
+ /// argument **must** be an Object instance. You can specify any properties you want.
343
+ /// Just be cautious if you set a `connection` property, as you might overwrite any
344
+ /// connection currently set on the context. Any properties you set here will be available
345
+ /// in any child function calls (inside this context scope), and can be accessed via a
346
+ /// call to <see>Model.getModelContext</see>.
347
+ ///
348
+ /// Note:
349
+ /// An `AsyncLocalStorage` context might not exist when this call is made,
350
+ /// in which case this method will simply return an empty object.
351
+ ///
352
+ /// Return: undefined
353
+ ///
354
+ /// Arguments:
355
+ /// value: object
356
+ /// The new properties you wish to merge with the current "model context".
357
+ static updateModelContext(value) {
358
+ let context = AsyncStore.getContextValue(this.getModelName());
359
+ if (!context)
360
+ return;
361
+
362
+ Object.assign(context, value);
363
+ }
364
+
365
+ updateModelContext(value) {
366
+ return this.constructor.updateModelContext(value);
367
+ }
368
+
226
369
  /// Get the underlying connection bound to
227
370
  /// the model's class. Connection binding is
228
371
  /// optional, so this method can also be provided
@@ -233,6 +376,32 @@ class Model {
233
376
  /// or fallback to a "bound" connection (if one can
234
377
  /// be found).
235
378
  ///
379
+ /// This method will return a connection in the following
380
+ /// order: 1) The provided `connection` argument, if supplied,
381
+ /// 2) The `connection` property on the "model context" from
382
+ /// <see>Model.getModelContext</see> from `AsyncLocalStorage`,
383
+ /// if one is available, and 3) Finally the bound connection, if
384
+ /// available, which is found by searching the `static Model._mythixBoundConnection`
385
+ /// property of the class.
386
+ ///
387
+ /// Note:
388
+ /// This is a low-level "global fallback" method. Any connection for a model
389
+ /// will first be searched by calling <see>Model.getConnection</see>,
390
+ /// which will call this static method if no connection can be found.
391
+ /// The <see>Model.getConnection</see> will also search the model instance
392
+ /// for a `connection` property, which can be supplied to any model when
393
+ /// it is instantiated.
394
+ ///
395
+ /// Note:
396
+ // A provided `connection`, either via the model instance `model.connection`,
397
+ /// or via the provided `connection` argument to the <see>Model.getConnection</see>
398
+ /// method (and eventually this method) will take priority over any `connection`
399
+ /// provided by the "model context" from `AsyncLocalStorage`. This can be an important
400
+ /// detail when using <see>Connection.transaction</see> or <see>Connection.createContext</see>,
401
+ /// because if a connection is directly specified by the user, the transaction connection
402
+ /// **will not** take priority. So if you are using transactions or a connection context,
403
+ /// be careful how you directly specify connections.
404
+ ///
236
405
  /// Return: <see>Connection</see>
237
406
  ///
238
407
  /// Arguments:
@@ -243,7 +412,18 @@ class Model {
243
412
  /// then attempt to fallback to the bound connection,
244
413
  /// if any is available.
245
414
  static _getConnection(_connection) {
246
- return _connection || this._mythixBoundConnection;
415
+ if (_connection)
416
+ return _connection;
417
+
418
+ let { connection } = this.getModelContext();
419
+ if (connection)
420
+ return connection;
421
+
422
+ connection = AsyncStore.getContextValue('connection');
423
+ if (connection)
424
+ return connection;
425
+
426
+ return this._mythixBoundConnection;
247
427
  }
248
428
 
249
429
  /// See <see>Model.static _getConnection</see>
@@ -278,6 +458,14 @@ class Model {
278
458
  return this.constructor._getConnection();
279
459
  }
280
460
 
461
+ static getConnection(_connection) {
462
+ let connection = this._getConnection(_connection);
463
+ if (!connection)
464
+ throw new Error(`${this.getModelName()}::getConnection: No connection bound to model. You need to provide a connection for this operation.`);
465
+
466
+ return connection;
467
+ }
468
+
281
469
  /// Get the underlying connection bound to
282
470
  /// the model's class. Connection binding is
283
471
  /// optional, so this method can also be provided
@@ -290,6 +478,15 @@ class Model {
290
478
  /// you wish to provide your own model specific
291
479
  /// connection.
292
480
  ///
481
+ /// This method will also search for a `modelInstance.connection`,
482
+ /// and return that connection if found.
483
+ ///
484
+ /// Note:
485
+ /// `static getConnection` is simply a proxy for
486
+ /// `static _getConnection`, whereas this instance
487
+ /// method will also attempt to find a connection
488
+ /// on the model instance itself.
489
+ ///
293
490
  /// Return: <see>Connection</see>
294
491
  ///
295
492
  /// Arguments:
@@ -299,14 +496,6 @@ class Model {
299
496
  /// Otherwise, if not provided, or a falsy value,
300
497
  /// then attempt to fallback to the bound connection,
301
498
  /// if any is available.
302
- static getConnection(_connection) {
303
- let connection = this._getConnection(_connection);
304
- if (!connection)
305
- throw new Error(`${this.getModelName()}::getConnection: No connection bound to model. You need to provide a connection for this operation.`);
306
-
307
- return connection;
308
- }
309
-
310
499
  getConnection(_connection) {
311
500
  if (_connection)
312
501
  return _connection;
@@ -334,26 +523,28 @@ class Model {
334
523
  /// connection?: <see>Connection</see>
335
524
  /// The connection instance to bind to
336
525
  /// this model class.
337
- static bindConnection(connection) {
526
+ static bindConnection(connection, options) {
338
527
  let ModelClass = this;
339
528
 
340
529
  // Ensure that the model fields
341
530
  // are constructed properly
342
531
  ModelClass.getFields();
343
532
 
344
- let connectionOptions = connection.getOptions();
533
+ let connectionOptions = { ...(connection.getOptions() || {}), ...(options || {}) };
345
534
  if (connectionOptions && connectionOptions.bindModels === false) {
346
- let modelName = ModelClass.getModelName();
535
+ // let modelName = ModelClass.getModelName();
347
536
 
348
- ModelClass = class BoundModel extends ModelClass {
349
- static getModelName() {
350
- return modelName;
351
- }
352
- };
537
+ // ModelClass = class BoundModel extends ModelClass {
538
+ // static getModelName() {
539
+ // return modelName;
540
+ // }
541
+ // };
353
542
 
354
- ModelClass.fields = ModelClass.mergeFields();
355
- ModelClass._sortedFields = null; // Clear cache
356
- } else {
543
+ // ModelClass.fields = ModelClass.mergeFields();
544
+ // ModelClass._sortedFields = null; // Clear cache
545
+
546
+ return ModelClass;
547
+ } else if (connectionOptions.forceConnectionBinding !== true) {
357
548
  if (Object.prototype.hasOwnProperty.call(ModelClass, '_mythixBoundConnection') && ModelClass._mythixBoundConnection)
358
549
  throw new Error(`${this.getModelName()}:bindConnection: Model is already bound to a connection. You can not bind a model to a connection more than once.`);
359
550
  }
@@ -362,7 +553,7 @@ class Model {
362
553
  enumerable: false,
363
554
  configurable: true,
364
555
  get: () => {
365
- return ModelClass.getQueryEngine(connection);
556
+ return ModelClass.getQueryEngine(ModelClass._getConnection() || connection);
366
557
  },
367
558
  set: () => {},
368
559
  };
@@ -1424,6 +1615,7 @@ class Model {
1424
1615
  /// Prefix a field name with `+` to specify ASCending order, i.e.
1425
1616
  /// `[ "+User:id" ]`. Prefix the field name with `-` to specify
1426
1617
  /// DESCending order, i.e. `[ "-User:id" ]`.
1618
+ // eslint-disable-next-line no-unused-vars
1427
1619
  static defaultOrder(options) {
1428
1620
  }
1429
1621
 
@@ -27,6 +27,9 @@ const AUTO_CALL_CALLED = Symbol.for('@__autoCallCalled');
27
27
  const AUTO_CALL = Symbol.for('@__autoCall');
28
28
 
29
29
  function shouldSkipProxy(prop) {
30
+ if (prop === 'bind' || prop === 'call' || prop === 'apply')
31
+ return true;
32
+
30
33
  if (prop === PROXY || prop === TARGET || prop === SELF || prop === AUTO_CALL_CALLER || prop === AUTO_CALL_CALLED || prop === AUTO_CALL)
31
34
  return true;
32
35
 
@@ -20,6 +20,10 @@ const MiscUtils = require('../../utils/misc-utils');
20
20
  /// it is used to parse provided date strings, and when serializing the
21
21
  /// field (for example via <see>Model.toJSON</see>).
22
22
  ///
23
+ /// Note:
24
+ /// A `BigInt` timestamp is used to store the date
25
+ /// in the underlying database.
26
+ ///
23
27
  /// Example:
24
28
  /// class Dates extends Model {
25
29
  /// static fields = {
@@ -20,6 +20,10 @@ const MiscUtils = require('../../utils/misc-utils');
20
20
  /// it is used to parse provided date strings, and when serializing the
21
21
  /// field (for example via <see>Model.toJSON</see>).
22
22
  ///
23
+ /// Note:
24
+ /// A `BigInt` timestamp is used to store the date
25
+ /// and time in the underlying database.
26
+ ///
23
27
  /// Example:
24
28
  /// class DatesWithTimes extends Model {
25
29
  /// static fields = {
@@ -27,7 +27,7 @@ const Type = require('../type');
27
27
  /// then the side-effect will be that this field may be serialized
28
28
  /// and stored more often than actually needed. This system was
29
29
  /// designed this way because it is likely better to get a false
30
- /// positive and save your data, then not check at all and lose data.
30
+ /// positive and save your data than to not check at all and lose data.
31
31
  /// If needed, you can always create your own child type of
32
32
  /// `SerializedType`, and overload the `isDirty` method, or provided
33
33
  /// an `isDirty` method to the field `options` to check