@nocobase/database 0.7.0-alpha.82 → 0.7.1-alpha.4

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.
Files changed (54) hide show
  1. package/lib/collection-importer.js +25 -42
  2. package/lib/collection.d.ts +6 -2
  3. package/lib/collection.js +37 -5
  4. package/lib/database.d.ts +21 -5
  5. package/lib/database.js +161 -49
  6. package/lib/fields/field.d.ts +4 -1
  7. package/lib/fields/field.js +117 -0
  8. package/lib/fields/formula-field.d.ts +19 -0
  9. package/lib/fields/formula-field.js +184 -0
  10. package/lib/fields/index.d.ts +3 -1
  11. package/lib/fields/index.js +13 -0
  12. package/lib/index.d.ts +1 -0
  13. package/lib/index.js +14 -0
  14. package/lib/migration.d.ts +35 -0
  15. package/lib/migration.js +90 -0
  16. package/lib/mock-database.d.ts +1 -0
  17. package/lib/mock-database.js +2 -1
  18. package/lib/model-hook.d.ts +5 -5
  19. package/lib/model-hook.js +26 -18
  20. package/lib/options-parser.js +65 -43
  21. package/lib/relation-repository/relation-repository.js +11 -1
  22. package/lib/relation-repository/single-relation-repository.js +8 -1
  23. package/lib/repository.js +12 -4
  24. package/lib/update-associations.js +1 -1
  25. package/package.json +9 -4
  26. package/src/__tests__/collection.test.ts +27 -0
  27. package/src/__tests__/database.test.ts +47 -0
  28. package/src/__tests__/fields/formula-field.test.ts +69 -0
  29. package/src/__tests__/fixtures/migrations/m1.ts +7 -0
  30. package/src/__tests__/fixtures/migrations/m2.ts +7 -0
  31. package/src/__tests__/hooks/afterCreateWithAssociations.test.ts +33 -0
  32. package/src/__tests__/migrator.test.ts +70 -0
  33. package/src/__tests__/model-hook.test.ts +54 -0
  34. package/src/__tests__/option-parser.test.ts +10 -6
  35. package/src/__tests__/relation-repository/belongs-to-many-repository.test.ts +1 -1
  36. package/src/__tests__/sequelize-hooks.test.ts +69 -0
  37. package/src/__tests__/sort.test.ts +51 -0
  38. package/src/__tests__/update-associations.test.ts +3 -3
  39. package/src/collection-importer.ts +12 -20
  40. package/src/collection.ts +26 -2
  41. package/src/database.ts +112 -29
  42. package/src/fields/field.ts +88 -1
  43. package/src/fields/formula-field.ts +106 -0
  44. package/src/fields/index.ts +3 -0
  45. package/src/index.ts +1 -0
  46. package/src/migration.ts +76 -0
  47. package/src/mock-database.ts +1 -0
  48. package/src/model-hook.ts +25 -21
  49. package/src/options-parser.ts +13 -9
  50. package/src/relation-repository/multiple-relation-repository.ts +8 -2
  51. package/src/relation-repository/relation-repository.ts +1 -0
  52. package/src/relation-repository/single-relation-repository.ts +5 -1
  53. package/src/repository.ts +16 -4
  54. package/src/update-associations.ts +1 -1
@@ -5,10 +5,20 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.ImporterReader = void 0;
7
7
 
8
- function fs() {
9
- const data = _interopRequireWildcard(require("fs"));
8
+ function _path() {
9
+ const data = _interopRequireDefault(require("path"));
10
+
11
+ _path = function _path() {
12
+ return data;
13
+ };
10
14
 
11
- fs = function fs() {
15
+ return data;
16
+ }
17
+
18
+ function _promises() {
19
+ const data = require("fs/promises");
20
+
21
+ _promises = function _promises() {
12
22
  return data;
13
23
  };
14
24
 
@@ -16,7 +26,7 @@ function fs() {
16
26
  }
17
27
 
18
28
  function _lodash() {
19
- const data = _interopRequireDefault(require("lodash"));
29
+ const data = require("lodash");
20
30
 
21
31
  _lodash = function _lodash() {
22
32
  return data;
@@ -25,10 +35,10 @@ function _lodash() {
25
35
  return data;
26
36
  }
27
37
 
28
- function _path() {
29
- const data = _interopRequireDefault(require("path"));
38
+ function _utils() {
39
+ const data = require("@nocobase/utils");
30
40
 
31
- _path = function _path() {
41
+ _utils = function _utils() {
32
42
  return data;
33
43
  };
34
44
 
@@ -37,33 +47,10 @@ function _path() {
37
47
 
38
48
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
39
49
 
40
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
41
-
42
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
43
-
44
50
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
45
51
 
46
52
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
47
53
 
48
- function requireModule(_x) {
49
- return _requireModule.apply(this, arguments);
50
- }
51
-
52
- function _requireModule() {
53
- _requireModule = _asyncToGenerator(function* (module) {
54
- if (typeof module === 'string') {
55
- module = require(module);
56
- }
57
-
58
- if (typeof module !== 'object') {
59
- return module;
60
- }
61
-
62
- return module.__esModule ? module.default : module;
63
- });
64
- return _requireModule.apply(this, arguments);
65
- }
66
-
67
54
  class ImporterReader {
68
55
  constructor(directory, extensions) {
69
56
  this.directory = void 0;
@@ -81,9 +68,10 @@ class ImporterReader {
81
68
  var _this = this;
82
69
 
83
70
  return _asyncToGenerator(function* () {
84
- const modules = (yield fs().promises.readdir(_this.directory, {
71
+ const files = yield (0, _promises().readdir)(_this.directory, {
85
72
  encoding: 'utf-8'
86
- })).filter(fileName => {
73
+ });
74
+ const modules = files.filter(fileName => {
87
75
  if (fileName.endsWith('.d.ts')) {
88
76
  return false;
89
77
  }
@@ -91,16 +79,11 @@ class ImporterReader {
91
79
  const ext = _path().default.parse(fileName).ext.replace('.', '');
92
80
 
93
81
  return _this.extensions.has(ext);
94
- }).map( /*#__PURE__*/function () {
95
- var _ref = _asyncToGenerator(function* (fileName) {
96
- return yield requireModule(_path().default.join(_this.directory, fileName));
97
- });
98
-
99
- return function (_x2) {
100
- return _ref.apply(this, arguments);
101
- };
102
- }());
103
- return (yield Promise.all(modules)).filter(module => _lodash().default.isPlainObject(module));
82
+ }).map(fileName => {
83
+ const mod = (0, _utils().requireModule)(_path().default.join(_this.directory, fileName));
84
+ return typeof mod === 'function' ? mod() : mod;
85
+ });
86
+ return (yield Promise.all(modules)).filter(module => (0, _lodash().isPlainObject)(module));
104
87
  })();
105
88
  }
106
89
 
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from 'events';
3
- import { ModelCtor, ModelOptions, SyncOptions } from 'sequelize';
3
+ import { ModelCtor, ModelOptions, QueryInterfaceDropTableOptions, SyncOptions, Transactionable } from 'sequelize';
4
4
  import { Database } from './database';
5
5
  import { Field, FieldOptions } from './fields';
6
6
  import { Model } from './model';
@@ -40,6 +40,7 @@ export declare class Collection<TModelAttributes extends {} = any, TCreationAttr
40
40
  repository: Repository<TModelAttributes, TCreationAttributes>;
41
41
  get filterTargetKey(): string;
42
42
  get name(): string;
43
+ get db(): Database;
43
44
  constructor(options: CollectionOptions, context?: CollectionContext);
44
45
  private sequelizeModelOptions;
45
46
  /**
@@ -56,7 +57,10 @@ export declare class Collection<TModelAttributes extends {} = any, TCreationAttr
56
57
  setField(name: string, options: FieldOptions): Field;
57
58
  setFields(fields: FieldOptions[], resetFields?: boolean): void;
58
59
  resetFields(): void;
59
- removeField(name: any): boolean;
60
+ remove(): void;
61
+ removeFromDb(options?: QueryInterfaceDropTableOptions): Promise<void>;
62
+ existsInDb(options?: Transactionable): Promise<boolean>;
63
+ removeField(name: any): Field;
60
64
  /**
61
65
  * TODO
62
66
  */
package/lib/collection.js CHANGED
@@ -73,6 +73,10 @@ class Collection extends _events().EventEmitter {
73
73
  return this.options.name;
74
74
  }
75
75
 
76
+ get db() {
77
+ return this.context.database;
78
+ }
79
+
76
80
  constructor(options, context) {
77
81
  super();
78
82
  this.options = void 0;
@@ -247,6 +251,34 @@ class Collection extends _events().EventEmitter {
247
251
  }
248
252
  }
249
253
 
254
+ remove() {
255
+ this.context.database.removeCollection(this.name);
256
+ }
257
+
258
+ removeFromDb(options) {
259
+ var _this = this;
260
+
261
+ return _asyncToGenerator(function* () {
262
+ if (yield _this.existsInDb({
263
+ transaction: options === null || options === void 0 ? void 0 : options.transaction
264
+ })) {
265
+ const queryInterface = _this.db.sequelize.getQueryInterface();
266
+
267
+ yield queryInterface.dropTable(_this.model.tableName, options);
268
+ }
269
+
270
+ _this.remove();
271
+ })();
272
+ }
273
+
274
+ existsInDb(options) {
275
+ var _this2 = this;
276
+
277
+ return _asyncToGenerator(function* () {
278
+ return _this2.db.collectionExistsInDb(_this2.name, options);
279
+ })();
280
+ }
281
+
250
282
  removeField(name) {
251
283
  if (!this.fields.has(name)) {
252
284
  return;
@@ -259,7 +291,7 @@ class Collection extends _events().EventEmitter {
259
291
  this.emit('field.afterRemove', field);
260
292
  }
261
293
 
262
- return bool;
294
+ return field;
263
295
  }
264
296
  /**
265
297
  * TODO
@@ -325,11 +357,11 @@ class Collection extends _events().EventEmitter {
325
357
  }
326
358
 
327
359
  sync(syncOptions) {
328
- var _this = this;
360
+ var _this3 = this;
329
361
 
330
362
  return _asyncToGenerator(function* () {
331
- const modelNames = [_this.model.name];
332
- const associations = _this.model.associations;
363
+ const modelNames = [_this3.model.name];
364
+ const associations = _this3.model.associations;
333
365
 
334
366
  for (const associationKey in associations) {
335
367
  const association = associations[associationKey];
@@ -342,7 +374,7 @@ class Collection extends _events().EventEmitter {
342
374
 
343
375
  const models = []; // @ts-ignore
344
376
 
345
- _this.context.database.sequelize.modelManager.forEachModel(model => {
377
+ _this3.context.database.sequelize.modelManager.forEachModel(model => {
346
378
  if (modelNames.includes(model.name)) {
347
379
  models.push(model);
348
380
  }
package/lib/database.d.ts CHANGED
@@ -2,11 +2,13 @@
2
2
  import { AsyncEmitter } from '@nocobase/utils';
3
3
  import merge from 'deepmerge';
4
4
  import { EventEmitter } from 'events';
5
- import { ModelCtor, Options, QueryInterfaceDropAllTablesOptions, QueryOptions, Sequelize, SyncOptions } from 'sequelize';
5
+ import { ModelCtor, Options, QueryInterfaceDropAllTablesOptions, QueryOptions, Sequelize, SyncOptions, Transactionable } from 'sequelize';
6
+ import { Umzug } from 'umzug';
6
7
  import { Collection, CollectionOptions, RepositoryType } from './collection';
7
8
  import { ImportFileExtension } from './collection-importer';
8
9
  import * as FieldTypes from './fields';
9
10
  import { Field, FieldContext, RelationField } from './fields';
11
+ import { Migrations } from './migration';
10
12
  import { Model } from './model';
11
13
  import { ModelHook } from './model-hook';
12
14
  import { RelationRepository } from './relation-repository/relation-repository';
@@ -22,8 +24,9 @@ interface MapOf<T> {
22
24
  }
23
25
  export interface IDatabaseOptions extends Options {
24
26
  tablePrefix?: string;
27
+ migrator?: any;
25
28
  }
26
- export declare type DatabaseOptions = IDatabaseOptions | Sequelize;
29
+ export declare type DatabaseOptions = IDatabaseOptions;
27
30
  interface RegisterOperatorsContext {
28
31
  db?: Database;
29
32
  path?: string;
@@ -33,9 +36,17 @@ interface RegisterOperatorsContext {
33
36
  export interface CleanOptions extends QueryInterfaceDropAllTablesOptions {
34
37
  drop?: boolean;
35
38
  }
39
+ export declare type AddMigrationsOptions = {
40
+ context?: any;
41
+ namespace?: string;
42
+ extensions?: string[];
43
+ directory: string;
44
+ };
36
45
  declare type OperatorFunc = (value: any, ctx?: RegisterOperatorsContext) => any;
37
46
  export declare class Database extends EventEmitter implements AsyncEmitter {
38
47
  sequelize: Sequelize;
48
+ migrator: Umzug;
49
+ migrations: Migrations;
39
50
  fieldTypes: Map<any, any>;
40
51
  options: IDatabaseOptions;
41
52
  models: Map<string, ModelCtor<Model<any, any>>>;
@@ -50,6 +61,10 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
50
61
  mergeOptions?: any;
51
62
  }[]>;
52
63
  constructor(options: DatabaseOptions);
64
+ addMigration(item: any): void;
65
+ addMigrations(options: AddMigrationsOptions): void;
66
+ inDialect(...dialect: string[]): boolean;
67
+ private requireModule;
53
68
  /**
54
69
  * Add collection to database
55
70
  * @param options
@@ -62,7 +77,7 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
62
77
  */
63
78
  getCollection(name: string): Collection;
64
79
  hasCollection(name: string): boolean;
65
- removeCollection(name: string): void;
80
+ removeCollection(name: string): Collection<any, any>;
66
81
  getModel<M extends Model>(name: string): ModelCtor<M>;
67
82
  getRepository<R extends Repository>(name: string): R;
68
83
  getRepository<R extends RelationRepository>(name: string, relationId: string | number): R;
@@ -76,14 +91,15 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
76
91
  buildField(options: any, context: FieldContext): any;
77
92
  sync(options?: SyncOptions): Promise<Sequelize>;
78
93
  clean(options: CleanOptions): Promise<void>;
94
+ collectionExistsInDb(name: any, options?: Transactionable): Promise<boolean>;
79
95
  isSqliteMemory(): boolean;
80
96
  auth(options?: QueryOptions & {
81
- repeat?: number;
97
+ retry?: number;
82
98
  }): Promise<any>;
83
99
  reconnect(): Promise<void>;
84
100
  closed(): any;
85
101
  close(): Promise<void>;
86
- on(event: string | symbol, listener: (...args: any[]) => void): this;
102
+ on(event: string | symbol, listener: any): this;
87
103
  import(options: {
88
104
  directory: string;
89
105
  extensions?: ImportFileExtension[];
package/lib/database.js CHANGED
@@ -27,6 +27,16 @@ function _events() {
27
27
  return data;
28
28
  }
29
29
 
30
+ function _glob() {
31
+ const data = _interopRequireDefault(require("glob"));
32
+
33
+ _glob = function _glob() {
34
+ return data;
35
+ };
36
+
37
+ return data;
38
+ }
39
+
30
40
  function _lodash() {
31
41
  const data = _interopRequireDefault(require("lodash"));
32
42
 
@@ -57,18 +67,30 @@ function _sequelize() {
57
67
  return data;
58
68
  }
59
69
 
70
+ function _umzug() {
71
+ const data = require("umzug");
72
+
73
+ _umzug = function _umzug() {
74
+ return data;
75
+ };
76
+
77
+ return data;
78
+ }
79
+
60
80
  var _collection = require("./collection");
61
81
 
62
82
  var _collectionImporter = require("./collection-importer");
63
83
 
64
84
  var FieldTypes = _interopRequireWildcard(require("./fields"));
65
85
 
86
+ var _migration = require("./migration");
87
+
66
88
  var _modelHook = require("./model-hook");
67
89
 
68
90
  var _operators = _interopRequireDefault(require("./operators"));
69
91
 
70
92
  const _excluded = ["drop"],
71
- _excluded2 = ["repeat"];
93
+ _excluded2 = ["retry"];
72
94
 
73
95
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
74
96
 
@@ -76,8 +98,6 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
76
98
 
77
99
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
78
100
 
79
- function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
80
-
81
101
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
82
102
 
83
103
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
@@ -86,6 +106,8 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try
86
106
 
87
107
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
88
108
 
109
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
110
+
89
111
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
90
112
 
91
113
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
@@ -108,6 +130,8 @@ class Database extends _events().EventEmitter {
108
130
  constructor(options) {
109
131
  super();
110
132
  this.sequelize = void 0;
133
+ this.migrator = void 0;
134
+ this.migrations = void 0;
111
135
  this.fieldTypes = new Map();
112
136
  this.options = void 0;
113
137
  this.models = new Map();
@@ -119,28 +143,29 @@ class Database extends _events().EventEmitter {
119
143
  this.modelHook = void 0;
120
144
  this.delayCollectionExtend = new Map();
121
145
 
122
- if (options instanceof _sequelize().Sequelize) {
123
- this.sequelize = options;
124
- } else {
125
- const opts = _objectSpread({
126
- sync: {
127
- alter: {
128
- drop: false
129
- },
130
- force: false
131
- }
132
- }, options);
146
+ const opts = _objectSpread({
147
+ sync: {
148
+ alter: {
149
+ drop: false
150
+ },
151
+ force: false
152
+ }
153
+ }, options);
133
154
 
134
- if (options.storage && options.storage !== ':memory:') {
135
- if (!(0, _path().isAbsolute)(options.storage)) {
136
- opts.storage = (0, _path().resolve)(process.cwd(), options.storage);
137
- }
155
+ if (options.storage && options.storage !== ':memory:') {
156
+ if (!(0, _path().isAbsolute)(options.storage)) {
157
+ opts.storage = (0, _path().resolve)(process.cwd(), options.storage);
138
158
  }
159
+ }
139
160
 
140
- this.sequelize = new (_sequelize().Sequelize)(opts);
141
- this.options = opts;
161
+ if (options.dialect === 'sqlite') {
162
+ delete opts.timezone;
163
+ } else if (!opts.timezone) {
164
+ opts.timezone = '+00:00';
142
165
  }
143
166
 
167
+ this.sequelize = new (_sequelize().Sequelize)(opts);
168
+ this.options = opts;
144
169
  this.collections = new Map();
145
170
  this.modelHook = new _modelHook.ModelHook(this);
146
171
  this.on('afterDefineCollection', collection => {
@@ -170,6 +195,78 @@ class Database extends _events().EventEmitter {
170
195
  }
171
196
 
172
197
  this.initOperators();
198
+ const migratorOptions = this.options.migrator || {};
199
+
200
+ const context = _objectSpread({
201
+ db: this,
202
+ sequelize: this.sequelize,
203
+ queryInterface: this.sequelize.getQueryInterface()
204
+ }, migratorOptions.context);
205
+
206
+ this.migrations = new _migration.Migrations(context);
207
+ this.migrator = new (_umzug().Umzug)({
208
+ logger: migratorOptions.logger || console,
209
+ migrations: this.migrations.callback(),
210
+ context,
211
+ storage: new (_umzug().SequelizeStorage)(_objectSpread(_objectSpread({
212
+ modelName: `${this.options.tablePrefix || ''}migrations`
213
+ }, migratorOptions.storage), {}, {
214
+ sequelize: this.sequelize
215
+ }))
216
+ });
217
+ }
218
+
219
+ addMigration(item) {
220
+ return this.migrations.add(item);
221
+ }
222
+
223
+ addMigrations(options) {
224
+ const namespace = options.namespace,
225
+ context = options.context,
226
+ _options$extensions = options.extensions,
227
+ extensions = _options$extensions === void 0 ? ['js', 'ts'] : _options$extensions,
228
+ directory = options.directory;
229
+ const patten = `${directory}/*.{${extensions.join(',')}}`;
230
+
231
+ const files = _glob().default.sync(patten, {
232
+ ignore: ['**/*.d.ts']
233
+ });
234
+
235
+ var _iterator = _createForOfIteratorHelper(files),
236
+ _step;
237
+
238
+ try {
239
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
240
+ const file = _step.value;
241
+ let filename = (0, _path().basename)(file);
242
+ filename = filename.substring(0, filename.lastIndexOf('.')) || filename;
243
+ this.migrations.add({
244
+ name: namespace ? `${namespace}/${filename}` : filename,
245
+ migration: this.requireModule(file),
246
+ context
247
+ });
248
+ }
249
+ } catch (err) {
250
+ _iterator.e(err);
251
+ } finally {
252
+ _iterator.f();
253
+ }
254
+ }
255
+
256
+ inDialect(...dialect) {
257
+ return dialect.includes(this.sequelize.getDialect());
258
+ }
259
+
260
+ requireModule(module) {
261
+ if (typeof module === 'string') {
262
+ module = require(module);
263
+ }
264
+
265
+ if (typeof module !== 'object') {
266
+ return module;
267
+ }
268
+
269
+ return module.__esModule ? module.default : module;
173
270
  }
174
271
  /**
175
272
  * Add collection to database
@@ -209,10 +306,13 @@ class Database extends _events().EventEmitter {
209
306
  const collection = this.collections.get(name);
210
307
  this.emit('beforeRemoveCollection', collection);
211
308
  const result = this.collections.delete(name);
309
+ this.sequelize.modelManager.removeModel(collection.model);
212
310
 
213
311
  if (result) {
214
312
  this.emit('afterRemoveCollection', collection);
215
313
  }
314
+
315
+ return collection;
216
316
  }
217
317
 
218
318
  getModel(name) {
@@ -353,16 +453,27 @@ class Database extends _events().EventEmitter {
353
453
  })();
354
454
  }
355
455
 
456
+ collectionExistsInDb(name, options) {
457
+ var _this3 = this;
458
+
459
+ return _asyncToGenerator(function* () {
460
+ const tables = yield _this3.sequelize.getQueryInterface().showAllTables({
461
+ transaction: options === null || options === void 0 ? void 0 : options.transaction
462
+ });
463
+ return !!tables.find(table => table === `${_this3.getTablePrefix()}${name}`);
464
+ })();
465
+ }
466
+
356
467
  isSqliteMemory() {
357
468
  return this.sequelize.getDialect() === 'sqlite' && _lodash().default.get(this.options, 'storage') == ':memory:';
358
469
  }
359
470
 
360
471
  auth(options = {}) {
361
- var _this3 = this;
472
+ var _this4 = this;
362
473
 
363
474
  return _asyncToGenerator(function* () {
364
- const _options$repeat = options.repeat,
365
- repeat = _options$repeat === void 0 ? 10 : _options$repeat,
475
+ const _options$retry = options.retry,
476
+ retry = _options$retry === void 0 ? 10 : _options$retry,
366
477
  others = _objectWithoutProperties(options, _excluded2);
367
478
 
368
479
  const delay = ms => new Promise(yea => setTimeout(yea, ms));
@@ -372,11 +483,11 @@ class Database extends _events().EventEmitter {
372
483
  const authenticate = /*#__PURE__*/function () {
373
484
  var _ref = _asyncToGenerator(function* () {
374
485
  try {
375
- yield _this3.sequelize.authenticate(others);
486
+ yield _this4.sequelize.authenticate(others);
376
487
  console.log('Connection has been established successfully.');
377
488
  return true;
378
489
  } catch (error) {
379
- if (count >= repeat) {
490
+ if (count >= retry) {
380
491
  throw error;
381
492
  }
382
493
 
@@ -397,21 +508,21 @@ class Database extends _events().EventEmitter {
397
508
  }
398
509
 
399
510
  reconnect() {
400
- var _this4 = this;
511
+ var _this5 = this;
401
512
 
402
513
  return _asyncToGenerator(function* () {
403
- if (_this4.isSqliteMemory()) {
514
+ if (_this5.isSqliteMemory()) {
404
515
  return;
405
516
  } // @ts-ignore
406
517
 
407
518
 
408
- const ConnectionManager = _this4.sequelize.dialect.connectionManager.constructor; // @ts-ignore
519
+ const ConnectionManager = _this5.sequelize.dialect.connectionManager.constructor; // @ts-ignore
409
520
 
410
- const connectionManager = new ConnectionManager(_this4.sequelize.dialect, _this4.sequelize); // @ts-ignore
521
+ const connectionManager = new ConnectionManager(_this5.sequelize.dialect, _this5.sequelize); // @ts-ignore
411
522
 
412
- _this4.sequelize.dialect.connectionManager = connectionManager; // @ts-ignore
523
+ _this5.sequelize.dialect.connectionManager = connectionManager; // @ts-ignore
413
524
 
414
- _this4.sequelize.connectionManager = connectionManager;
525
+ _this5.sequelize.connectionManager = connectionManager;
415
526
  })();
416
527
  }
417
528
 
@@ -421,65 +532,66 @@ class Database extends _events().EventEmitter {
421
532
  }
422
533
 
423
534
  close() {
424
- var _this5 = this;
535
+ var _this6 = this;
425
536
 
426
537
  return _asyncToGenerator(function* () {
427
- if (_this5.isSqliteMemory()) {
538
+ if (_this6.isSqliteMemory()) {
428
539
  return;
429
540
  }
430
541
 
431
- return _this5.sequelize.close();
542
+ return _this6.sequelize.close();
432
543
  })();
433
544
  }
434
545
 
435
546
  on(event, listener) {
436
- const modelEventName = this.modelHook.isModelHook(event);
547
+ // NOTE: to match if event is a sequelize or model type
548
+ const type = this.modelHook.match(event);
437
549
 
438
- if (modelEventName && !this.modelHook.hasBindEvent(modelEventName)) {
439
- this.sequelize.addHook(modelEventName, this.modelHook.sequelizeHookBuilder(modelEventName));
440
- this.modelHook.bindEvent(modelEventName);
550
+ if (type && !this.modelHook.hasBoundEvent(type)) {
551
+ this.sequelize.addHook(type, this.modelHook.buildSequelizeHook(type));
552
+ this.modelHook.bindEvent(type);
441
553
  }
442
554
 
443
555
  return super.on(event, listener);
444
556
  }
445
557
 
446
558
  import(options) {
447
- var _this6 = this;
559
+ var _this7 = this;
448
560
 
449
561
  return _asyncToGenerator(function* () {
450
562
  const reader = new _collectionImporter.ImporterReader(options.directory, options.extensions);
451
563
  const modules = yield reader.read();
452
564
  const result = new Map();
453
565
 
454
- var _iterator = _createForOfIteratorHelper(modules),
455
- _step;
566
+ var _iterator2 = _createForOfIteratorHelper(modules),
567
+ _step2;
456
568
 
457
569
  try {
458
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
459
- const module = _step.value;
570
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
571
+ const module = _step2.value;
460
572
 
461
573
  if (module.extend) {
462
574
  const collectionName = module.collectionOptions.name;
463
575
 
464
- const existCollection = _this6.getCollection(collectionName);
576
+ const existCollection = _this7.getCollection(collectionName);
465
577
 
466
578
  if (existCollection) {
467
579
  existCollection.updateOptions(module.collectionOptions, module.mergeOptions);
468
580
  } else {
469
- const existDelayExtends = _this6.delayCollectionExtend.get(collectionName) || [];
581
+ const existDelayExtends = _this7.delayCollectionExtend.get(collectionName) || [];
470
582
 
471
- _this6.delayCollectionExtend.set(collectionName, [...existDelayExtends, module]);
583
+ _this7.delayCollectionExtend.set(collectionName, [...existDelayExtends, module]);
472
584
  }
473
585
  } else {
474
- const collection = _this6.collection(module);
586
+ const collection = _this7.collection(module);
475
587
 
476
588
  result.set(collection.name, collection);
477
589
  }
478
590
  }
479
591
  } catch (err) {
480
- _iterator.e(err);
592
+ _iterator2.e(err);
481
593
  } finally {
482
- _iterator.f();
594
+ _iterator2.f();
483
595
  }
484
596
 
485
597
  return result;