@nocobase/database 0.9.0-alpha.2 → 0.9.1-alpha.2

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 (125) hide show
  1. package/lib/collection-importer.js +1 -1
  2. package/lib/collection.d.ts +9 -2
  3. package/lib/collection.js +153 -63
  4. package/lib/database-utils/index.d.ts +8 -0
  5. package/lib/database-utils/index.js +59 -0
  6. package/lib/database.d.ts +32 -3
  7. package/lib/database.js +237 -64
  8. package/lib/fields/array-field.d.ts +1 -1
  9. package/lib/fields/array-field.js +2 -2
  10. package/lib/fields/belongs-to-many-field.js +8 -3
  11. package/lib/fields/field.d.ts +1 -0
  12. package/lib/fields/field.js +37 -15
  13. package/lib/fields/has-one-field.d.ts +1 -1
  14. package/lib/fields/has-one-field.js +9 -5
  15. package/lib/fields/number-field.d.ts +9 -6
  16. package/lib/fields/number-field.js +8 -6
  17. package/lib/fields/sort-field.js +15 -1
  18. package/lib/filter-parser.js +1 -1
  19. package/lib/index.d.ts +6 -4
  20. package/lib/index.js +59 -36
  21. package/lib/mock-database.d.ts +2 -0
  22. package/lib/mock-database.js +3 -1
  23. package/lib/model.js +10 -1
  24. package/lib/options-parser.js +3 -0
  25. package/lib/query-interface/mysql-query-interface.d.ts +7 -0
  26. package/lib/query-interface/mysql-query-interface.js +39 -0
  27. package/lib/query-interface/postgres-query-interface.d.ts +6 -0
  28. package/lib/query-interface/postgres-query-interface.js +41 -0
  29. package/lib/query-interface/query-interface-builder.d.ts +2 -0
  30. package/lib/query-interface/query-interface-builder.js +23 -0
  31. package/lib/query-interface/query-interface.d.ts +9 -0
  32. package/lib/query-interface/query-interface.js +18 -0
  33. package/lib/query-interface/sqlite-query-interface.d.ts +6 -0
  34. package/lib/query-interface/sqlite-query-interface.js +38 -0
  35. package/lib/relation-repository/belongs-to-many-repository.js +4 -2
  36. package/lib/relation-repository/multiple-relation-repository.js +2 -0
  37. package/lib/relation-repository/single-relation-repository.js +1 -0
  38. package/lib/repository.js +5 -2
  39. package/lib/sync-runner.d.ts +1 -1
  40. package/lib/sync-runner.js +29 -22
  41. package/lib/types.d.ts +7 -1
  42. package/lib/update-associations.js +17 -3
  43. package/lib/update-guard.d.ts +1 -0
  44. package/lib/update-guard.js +6 -0
  45. package/lib/utils.d.ts +5 -0
  46. package/lib/utils.js +78 -0
  47. package/lib/value-parsers/array-value-parser.d.ts +8 -0
  48. package/lib/value-parsers/array-value-parser.js +76 -0
  49. package/lib/value-parsers/base-value-parser.d.ts +12 -0
  50. package/lib/value-parsers/base-value-parser.js +59 -0
  51. package/lib/value-parsers/boolean-value-parser.d.ts +4 -0
  52. package/lib/value-parsers/boolean-value-parser.js +46 -0
  53. package/lib/value-parsers/date-value-parser.d.ts +5 -0
  54. package/lib/value-parsers/date-value-parser.js +91 -0
  55. package/lib/value-parsers/index.d.ts +12 -0
  56. package/lib/value-parsers/index.js +102 -0
  57. package/lib/value-parsers/json-value-parser.d.ts +4 -0
  58. package/lib/value-parsers/json-value-parser.js +37 -0
  59. package/lib/value-parsers/number-value-parser.d.ts +4 -0
  60. package/lib/value-parsers/number-value-parser.js +49 -0
  61. package/lib/value-parsers/string-value-parser.d.ts +8 -0
  62. package/lib/value-parsers/string-value-parser.js +76 -0
  63. package/lib/value-parsers/to-many-value-parser.d.ts +13 -0
  64. package/lib/value-parsers/to-many-value-parser.js +169 -0
  65. package/lib/value-parsers/to-one-value-parser.d.ts +4 -0
  66. package/lib/value-parsers/to-one-value-parser.js +49 -0
  67. package/package.json +5 -3
  68. package/src/__tests__/bigint.test.ts +1 -1
  69. package/src/__tests__/collection-importer.test.ts +13 -1
  70. package/src/__tests__/collection.test.ts +19 -9
  71. package/src/__tests__/database.test.ts +32 -0
  72. package/src/__tests__/fields/sort-field.test.ts +23 -0
  73. package/src/__tests__/filter.test.ts +60 -0
  74. package/src/__tests__/inhertits/collection-inherits.test.ts +7 -5
  75. package/src/__tests__/percent2float.test.ts +14 -0
  76. package/src/__tests__/postgres/schema.test.ts +120 -0
  77. package/src/__tests__/underscored-options.test.ts +207 -0
  78. package/src/__tests__/update-associations-through.test.ts +73 -0
  79. package/src/__tests__/value-parsers/base.test.ts +20 -0
  80. package/src/__tests__/value-parsers/date.test.ts +67 -0
  81. package/src/__tests__/value-parsers/number.test.ts +46 -0
  82. package/src/__tests__/value-parsers/to-many.test.ts +206 -0
  83. package/src/__tests__/value-parsers/to-one.test.ts +60 -0
  84. package/src/collection-importer.ts +2 -2
  85. package/src/collection.ts +115 -17
  86. package/src/database-utils/index.ts +38 -0
  87. package/src/database.ts +188 -36
  88. package/src/fields/array-field.ts +1 -1
  89. package/src/fields/belongs-to-field.ts +1 -1
  90. package/src/fields/belongs-to-many-field.ts +8 -3
  91. package/src/fields/field.ts +48 -17
  92. package/src/fields/has-many-field.ts +1 -1
  93. package/src/fields/has-one-field.ts +11 -7
  94. package/src/fields/number-field.ts +10 -6
  95. package/src/fields/sort-field.ts +13 -1
  96. package/src/filter-parser.ts +1 -1
  97. package/src/index.ts +7 -4
  98. package/src/inherited-collection.ts +1 -0
  99. package/src/mock-database.ts +3 -1
  100. package/src/model.ts +11 -2
  101. package/src/options-parser.ts +5 -0
  102. package/src/query-interface/mysql-query-interface.ts +20 -0
  103. package/src/query-interface/postgres-query-interface.ts +22 -0
  104. package/src/query-interface/query-interface-builder.ts +14 -0
  105. package/src/query-interface/query-interface.ts +12 -0
  106. package/src/query-interface/sqlite-query-interface.ts +18 -0
  107. package/src/relation-repository/belongs-to-many-repository.ts +4 -2
  108. package/src/relation-repository/multiple-relation-repository.ts +4 -0
  109. package/src/relation-repository/single-relation-repository.ts +2 -0
  110. package/src/repository.ts +8 -3
  111. package/src/sync-runner.ts +35 -24
  112. package/src/types.ts +12 -1
  113. package/src/update-associations.ts +12 -5
  114. package/src/update-guard.ts +6 -0
  115. package/src/utils.ts +95 -0
  116. package/src/value-parsers/array-value-parser.ts +30 -0
  117. package/src/value-parsers/base-value-parser.ts +40 -0
  118. package/src/value-parsers/boolean-value-parser.ts +29 -0
  119. package/src/value-parsers/date-value-parser.ts +38 -0
  120. package/src/value-parsers/index.ts +46 -0
  121. package/src/value-parsers/json-value-parser.ts +19 -0
  122. package/src/value-parsers/number-value-parser.ts +29 -0
  123. package/src/value-parsers/string-value-parser.ts +31 -0
  124. package/src/value-parsers/to-many-value-parser.ts +85 -0
  125. package/src/value-parsers/to-one-value-parser.ts +20 -0
@@ -83,7 +83,7 @@ class ImporterReader {
83
83
  const mod = (0, _utils().requireModule)(_path().default.join(_this.directory, fileName));
84
84
  return typeof mod === 'function' ? mod() : mod;
85
85
  });
86
- return (yield Promise.all(modules)).filter(module => (0, _lodash().isPlainObject)(module));
86
+ return (yield Promise.all(modules)).filter(module => (0, _lodash().isPlainObject)(module)).map(module => (0, _lodash().cloneDeep)(module));
87
87
  })();
88
88
  }
89
89
 
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from 'events';
3
- import { ModelOptions, QueryInterfaceDropTableOptions, SyncOptions, Transactionable, ModelStatic } from 'sequelize';
3
+ import { ModelOptions, ModelStatic, QueryInterfaceDropTableOptions, SyncOptions, Transactionable } from 'sequelize';
4
4
  import { Database } from './database';
5
5
  import { Field, FieldOptions } from './fields';
6
6
  import { Model } from './model';
@@ -41,9 +41,12 @@ export declare class Collection<TModelAttributes extends {} = any, TCreationAttr
41
41
  repository: Repository<TModelAttributes, TCreationAttributes>;
42
42
  get filterTargetKey(): string;
43
43
  get name(): string;
44
+ get titleField(): string;
44
45
  get db(): Database;
45
46
  constructor(options: CollectionOptions, context: CollectionContext);
46
47
  private checkOptions;
48
+ private checkTableName;
49
+ tableName(): any;
47
50
  private sequelizeModelOptions;
48
51
  /**
49
52
  * TODO
@@ -56,12 +59,13 @@ export declare class Collection<TModelAttributes extends {} = any, TCreationAttr
56
59
  hasField(name: string): boolean;
57
60
  getField<F extends Field>(name: string): F;
58
61
  addField(name: string, options: FieldOptions): Field;
62
+ checkFieldType(name: string, options: FieldOptions): void;
59
63
  setField(name: string, options: FieldOptions): Field;
60
64
  setFields(fields: FieldOptions[], resetFields?: boolean): void;
61
65
  resetFields(): void;
62
66
  remove(): void;
63
67
  removeFromDb(options?: QueryInterfaceDropTableOptions): Promise<void>;
64
- existsInDb(options?: Transactionable): Promise<boolean>;
68
+ existsInDb(options?: Transactionable): any;
65
69
  removeField(name: string): void | Field;
66
70
  /**
67
71
  * TODO
@@ -85,4 +89,7 @@ export declare class Collection<TModelAttributes extends {} = any, TCreationAttr
85
89
  sync(syncOptions?: SyncOptions): Promise<void>;
86
90
  isInherited(): boolean;
87
91
  isParent(): boolean;
92
+ addSchemaTableName(): any;
93
+ quotedTableName(): any;
94
+ collectionSchema(): string;
88
95
  }
package/lib/collection.js CHANGED
@@ -64,18 +64,26 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return
64
64
 
65
65
  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; }
66
66
 
67
- 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(_e) { throw _e; }, 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(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
68
-
69
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
70
-
71
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
72
-
73
67
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
74
68
 
75
69
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
76
70
 
77
71
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
78
72
 
73
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
74
+
75
+ 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."); }
76
+
77
+ function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
78
+
79
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
80
+
81
+ 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; } } }; }
82
+
83
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
84
+
85
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
86
+
79
87
  class Collection extends _events().EventEmitter {
80
88
  get filterTargetKey() {
81
89
  return _lodash().default.get(this.options, 'filterTargetKey', this.model.primaryKeyAttribute);
@@ -85,6 +93,10 @@ class Collection extends _events().EventEmitter {
85
93
  return this.options.name;
86
94
  }
87
95
 
96
+ get titleField() {
97
+ return this.options.titleField || this.model.primaryKeyAttribute;
98
+ }
99
+
88
100
  get db() {
89
101
  return this.context.database;
90
102
  }
@@ -97,9 +109,9 @@ class Collection extends _events().EventEmitter {
97
109
  this.fields = new Map();
98
110
  this.model = void 0;
99
111
  this.repository = void 0;
100
- this.checkOptions(options);
101
112
  this.context = context;
102
113
  this.options = options;
114
+ this.checkOptions(options);
103
115
  this.bindFieldEventListener();
104
116
  this.modelInit();
105
117
  this.db.modelCollection.set(this.model, this);
@@ -115,16 +127,46 @@ class Collection extends _events().EventEmitter {
115
127
 
116
128
  checkOptions(options) {
117
129
  (0, _utils.checkIdentifier)(options.name);
130
+ this.checkTableName();
118
131
  }
119
132
 
120
- sequelizeModelOptions() {
133
+ checkTableName() {
134
+ const tableName = this.tableName();
135
+
136
+ var _iterator = _createForOfIteratorHelper(this.db.collections),
137
+ _step;
138
+
139
+ try {
140
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
141
+ const _step$value = _slicedToArray(_step.value, 2),
142
+ k = _step$value[0],
143
+ collection = _step$value[1];
144
+
145
+ if (collection.name != this.options.name && tableName === collection.tableName()) {
146
+ throw new Error(`collection ${collection.name} and ${this.name} have same tableName "${tableName}"`);
147
+ }
148
+ }
149
+ } catch (err) {
150
+ _iterator.e(err);
151
+ } finally {
152
+ _iterator.f();
153
+ }
154
+ }
155
+
156
+ tableName() {
121
157
  const _this$options = this.options,
122
158
  name = _this$options.name,
123
159
  tableName = _this$options.tableName;
160
+ const tName = tableName || name;
161
+ return this.db.options.underscored ? (0, _utils.snakeCase)(tName) : tName;
162
+ }
163
+
164
+ sequelizeModelOptions() {
165
+ const name = this.options.name;
124
166
  return _objectSpread(_objectSpread({}, _lodash().default.omit(this.options, ['name', 'fields', 'model', 'targetKey'])), {}, {
125
167
  modelName: name,
126
168
  sequelize: this.context.database.sequelize,
127
- tableName: tableName || name
169
+ tableName: this.tableName()
128
170
  });
129
171
  }
130
172
  /**
@@ -217,8 +259,36 @@ class Collection extends _events().EventEmitter {
217
259
  return this.setField(name, options);
218
260
  }
219
261
 
262
+ checkFieldType(name, options) {
263
+ if (!this.db.options.underscored) {
264
+ return;
265
+ }
266
+
267
+ const fieldName = options.field || (0, _utils.snakeCase)(name);
268
+ const field = this.findField(f => {
269
+ if (f.name === name) {
270
+ return false;
271
+ }
272
+
273
+ if (f.field) {
274
+ return f.field === fieldName;
275
+ }
276
+
277
+ return (0, _utils.snakeCase)(f.name) === fieldName;
278
+ });
279
+
280
+ if (!field) {
281
+ return;
282
+ }
283
+
284
+ if (options.type !== field.type) {
285
+ throw new Error(`fields with same column must be of the same type ${JSON.stringify(options)}`);
286
+ }
287
+ }
288
+
220
289
  setField(name, options) {
221
290
  (0, _utils.checkIdentifier)(name);
291
+ this.checkFieldType(name, options);
222
292
  const database = this.context.database;
223
293
  const field = database.buildField(_objectSpread({
224
294
  name
@@ -240,14 +310,14 @@ class Collection extends _events().EventEmitter {
240
310
  this.emit('field.afterAdd', field); // refresh children models
241
311
 
242
312
  if (this.isParent()) {
243
- var _iterator = _createForOfIteratorHelper(this.context.database.inheritanceMap.getChildren(this.name, {
313
+ var _iterator2 = _createForOfIteratorHelper(this.context.database.inheritanceMap.getChildren(this.name, {
244
314
  deep: false
245
315
  })),
246
- _step;
316
+ _step2;
247
317
 
248
318
  try {
249
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
250
- const child = _step.value;
319
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
320
+ const child = _step2.value;
251
321
  const childCollection = this.db.getCollection(child);
252
322
  const existField = childCollection.getField(name);
253
323
 
@@ -258,9 +328,9 @@ class Collection extends _events().EventEmitter {
258
328
  }
259
329
  }
260
330
  } catch (err) {
261
- _iterator.e(err);
331
+ _iterator2.e(err);
262
332
  } finally {
263
- _iterator.f();
333
+ _iterator2.f();
264
334
  }
265
335
  }
266
336
 
@@ -276,12 +346,12 @@ class Collection extends _events().EventEmitter {
276
346
  this.resetFields();
277
347
  }
278
348
 
279
- var _iterator2 = _createForOfIteratorHelper(fields),
280
- _step2;
349
+ var _iterator3 = _createForOfIteratorHelper(fields),
350
+ _step3;
281
351
 
282
352
  try {
283
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
284
- const _ref = _step2.value;
353
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
354
+ const _ref = _step3.value;
285
355
 
286
356
  const name = _ref.name,
287
357
  options = _objectWithoutProperties(_ref, _excluded);
@@ -289,27 +359,27 @@ class Collection extends _events().EventEmitter {
289
359
  this.addField(name, options);
290
360
  }
291
361
  } catch (err) {
292
- _iterator2.e(err);
362
+ _iterator3.e(err);
293
363
  } finally {
294
- _iterator2.f();
364
+ _iterator3.f();
295
365
  }
296
366
  }
297
367
 
298
368
  resetFields() {
299
369
  const fieldNames = this.fields.keys();
300
370
 
301
- var _iterator3 = _createForOfIteratorHelper(fieldNames),
302
- _step3;
371
+ var _iterator4 = _createForOfIteratorHelper(fieldNames),
372
+ _step4;
303
373
 
304
374
  try {
305
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
306
- const fieldName = _step3.value;
375
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
376
+ const fieldName = _step4.value;
307
377
  this.removeField(fieldName);
308
378
  }
309
379
  } catch (err) {
310
- _iterator3.e(err);
380
+ _iterator4.e(err);
311
381
  } finally {
312
- _iterator3.f();
382
+ _iterator4.f();
313
383
  }
314
384
  }
315
385
 
@@ -326,7 +396,7 @@ class Collection extends _events().EventEmitter {
326
396
  })) {
327
397
  const queryInterface = _this.db.sequelize.getQueryInterface();
328
398
 
329
- yield queryInterface.dropTable(_this.model.tableName, options);
399
+ yield queryInterface.dropTable(_this.addSchemaTableName(), options);
330
400
  }
331
401
 
332
402
  _this.remove();
@@ -337,7 +407,7 @@ class Collection extends _events().EventEmitter {
337
407
  var _this2 = this;
338
408
 
339
409
  return _asyncToGenerator(function* () {
340
- return _this2.db.collectionExistsInDb(_this2.name, options);
410
+ return _this2.db.queryInterface.collectionTableExists(_this2, options);
341
411
  })();
342
412
  }
343
413
 
@@ -351,14 +421,14 @@ class Collection extends _events().EventEmitter {
351
421
 
352
422
  if (bool) {
353
423
  if (this.isParent()) {
354
- var _iterator4 = _createForOfIteratorHelper(this.db.inheritanceMap.getChildren(this.name, {
424
+ var _iterator5 = _createForOfIteratorHelper(this.db.inheritanceMap.getChildren(this.name, {
355
425
  deep: false
356
426
  })),
357
- _step4;
427
+ _step5;
358
428
 
359
429
  try {
360
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
361
- const child = _step4.value;
430
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
431
+ const child = _step5.value;
362
432
  const childCollection = this.db.getCollection(child);
363
433
  const existField = childCollection.getField(name);
364
434
 
@@ -367,9 +437,9 @@ class Collection extends _events().EventEmitter {
367
437
  }
368
438
  }
369
439
  } catch (err) {
370
- _iterator4.e(err);
440
+ _iterator5.e(err);
371
441
  } finally {
372
- _iterator4.f();
442
+ _iterator5.f();
373
443
  }
374
444
  }
375
445
 
@@ -388,6 +458,7 @@ class Collection extends _events().EventEmitter {
388
458
 
389
459
  newOptions = (0, _deepmerge().default)(this.options, newOptions, mergeOptions);
390
460
  this.context.database.emit('beforeUpdateCollection', this, newOptions);
461
+ this.options = newOptions;
391
462
  this.setFields(options.fields, false);
392
463
  this.setRepository(options.repository);
393
464
  this.context.database.emit('afterUpdateCollection', this);
@@ -444,7 +515,8 @@ class Collection extends _events().EventEmitter {
444
515
  addIndex(index) {
445
516
  if (!index) {
446
517
  return;
447
- }
518
+ } // collection defined indexes
519
+
448
520
 
449
521
  let indexes = this.model.options.indexes || [];
450
522
  let indexName = [];
@@ -475,12 +547,12 @@ class Collection extends _events().EventEmitter {
475
547
  return;
476
548
  }
477
549
 
478
- var _iterator5 = _createForOfIteratorHelper(indexes),
479
- _step5;
550
+ var _iterator6 = _createForOfIteratorHelper(indexes),
551
+ _step6;
480
552
 
481
553
  try {
482
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
483
- const item = _step5.value;
554
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
555
+ const item = _step6.value;
484
556
 
485
557
  if (_lodash().default.isEqual(item.fields, indexName)) {
486
558
  return;
@@ -493,9 +565,9 @@ class Collection extends _events().EventEmitter {
493
565
  }
494
566
  }
495
567
  } catch (err) {
496
- _iterator5.e(err);
568
+ _iterator6.e(err);
497
569
  } finally {
498
- _iterator5.f();
570
+ _iterator6.f();
499
571
  }
500
572
 
501
573
  if (!indexItem) {
@@ -503,7 +575,6 @@ class Collection extends _events().EventEmitter {
503
575
  }
504
576
 
505
577
  indexes.push(indexItem);
506
- this.model.options.indexes = indexes;
507
578
  const tableName = this.model.getTableName(); // @ts-ignore
508
579
 
509
580
  this.model._indexes = this.model.options.indexes // @ts-ignore
@@ -535,26 +606,15 @@ class Collection extends _events().EventEmitter {
535
606
  // @ts-ignore
536
607
  const indexes = this.model._indexes; // @ts-ignore
537
608
 
538
- this.model._indexes = indexes.filter(item => {
539
- var _iterator6 = _createForOfIteratorHelper(item.fields),
540
- _step6;
541
-
542
- try {
543
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
544
- const field = _step6.value;
545
-
546
- if (!this.model.rawAttributes[field]) {
547
- return false;
548
- }
549
- }
550
- } catch (err) {
551
- _iterator6.e(err);
552
- } finally {
553
- _iterator6.f();
609
+ this.model._indexes = _lodash().default.uniqBy(indexes.filter(item => {
610
+ return item.fields.every(field => Object.values(this.model.rawAttributes).find(fieldVal => fieldVal.field === field));
611
+ }).map(item => {
612
+ if (this.options.underscored) {
613
+ item.fields = item.fields.map(field => (0, _utils.snakeCase)(field));
554
614
  }
555
615
 
556
- return true;
557
- });
616
+ return item;
617
+ }), 'name');
558
618
  }
559
619
 
560
620
  sync(syncOptions) {
@@ -581,8 +641,8 @@ class Collection extends _events().EventEmitter {
581
641
  }
582
642
  });
583
643
 
584
- for (var _i = 0, _models = models; _i < _models.length; _i++) {
585
- const model = _models[_i];
644
+ for (var _i2 = 0, _models = models; _i2 < _models.length; _i2++) {
645
+ const model = _models[_i2];
586
646
  yield model.sync(syncOptions);
587
647
  }
588
648
  })();
@@ -596,6 +656,36 @@ class Collection extends _events().EventEmitter {
596
656
  return this.context.database.inheritanceMap.isParentNode(this.name);
597
657
  }
598
658
 
659
+ addSchemaTableName() {
660
+ const tableName = this.model.tableName;
661
+
662
+ if (this.collectionSchema()) {
663
+ return this.db.utils.addSchema(tableName, this.collectionSchema());
664
+ }
665
+
666
+ return tableName;
667
+ }
668
+
669
+ quotedTableName() {
670
+ return this.db.utils.quoteTable(this.addSchemaTableName());
671
+ }
672
+
673
+ collectionSchema() {
674
+ if (this.options.schema) {
675
+ return this.options.schema;
676
+ }
677
+
678
+ if (this.db.options.schema) {
679
+ return this.db.options.schema;
680
+ }
681
+
682
+ if (this.db.inDialect('postgres')) {
683
+ return 'public';
684
+ }
685
+
686
+ return undefined;
687
+ }
688
+
599
689
  }
600
690
 
601
691
  exports.Collection = Collection;
@@ -0,0 +1,8 @@
1
+ import Database from '../database';
2
+ export default class DatabaseUtils {
3
+ db: Database;
4
+ constructor(db: Database);
5
+ addSchema(tableName: any, schema?: any): any;
6
+ quoteTable(tableName: any): any;
7
+ schema(): string;
8
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ function _lodash() {
9
+ const data = _interopRequireDefault(require("lodash"));
10
+
11
+ _lodash = function _lodash() {
12
+ return data;
13
+ };
14
+
15
+ return data;
16
+ }
17
+
18
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
+
20
+ class DatabaseUtils {
21
+ constructor(db) {
22
+ this.db = void 0;
23
+ this.db = db;
24
+ }
25
+
26
+ addSchema(tableName, schema) {
27
+ if (this.db.options.schema && !schema) {
28
+ schema = this.db.options.schema;
29
+ }
30
+
31
+ if (schema) {
32
+ // @ts-ignore
33
+ tableName = this.db.sequelize.getQueryInterface().queryGenerator.addSchema({
34
+ tableName,
35
+ _schema: schema
36
+ });
37
+ }
38
+
39
+ return tableName;
40
+ }
41
+
42
+ quoteTable(tableName) {
43
+ const queryGenerator = this.db.sequelize.getQueryInterface().queryGenerator; // @ts-ignore
44
+
45
+ tableName = queryGenerator.quoteTable(_lodash().default.isPlainObject(tableName) ? tableName : this.addSchema(tableName));
46
+ return tableName;
47
+ }
48
+
49
+ schema() {
50
+ if (!this.db.inDialect('postgres')) {
51
+ return undefined;
52
+ }
53
+
54
+ return this.db.options.schema || 'public';
55
+ }
56
+
57
+ }
58
+
59
+ exports.default = DatabaseUtils;
package/lib/database.d.ts CHANGED
@@ -17,6 +17,10 @@ import { ModelHook } from './model-hook';
17
17
  import { RelationRepository } from './relation-repository/relation-repository';
18
18
  import { Repository } from './repository';
19
19
  import { AfterDefineCollectionListener, BeforeDefineCollectionListener, CreateListener, CreateWithAssociationsListener, DatabaseAfterDefineCollectionEventType, DatabaseAfterRemoveCollectionEventType, DatabaseBeforeDefineCollectionEventType, DatabaseBeforeRemoveCollectionEventType, DestroyListener, EventType, ModelCreateEventTypes, ModelCreateWithAssociationsEventTypes, ModelDestroyEventTypes, ModelSaveEventTypes, ModelSaveWithAssociationsEventTypes, ModelUpdateEventTypes, ModelUpdateWithAssociationsEventTypes, ModelValidateEventTypes, RemoveCollectionListener, SaveListener, SaveWithAssociationsListener, SyncListener, UpdateListener, UpdateWithAssociationsListener, ValidateListener } from './types';
20
+ import DatabaseUtils from './database-utils';
21
+ import { BaseValueParser } from './value-parsers';
22
+ import QueryInterface from './query-interface/query-interface';
23
+ import { Logger } from '@nocobase/logger';
20
24
  export interface MergeOptions extends merge.Options {
21
25
  }
22
26
  export interface PendingOptions {
@@ -30,6 +34,7 @@ export interface IDatabaseOptions extends Options {
30
34
  tablePrefix?: string;
31
35
  migrator?: any;
32
36
  usingBigIntForId?: boolean;
37
+ underscored?: boolean;
33
38
  }
34
39
  export declare type DatabaseOptions = IDatabaseOptions;
35
40
  interface RegisterOperatorsContext {
@@ -48,6 +53,20 @@ export declare type AddMigrationsOptions = {
48
53
  directory: string;
49
54
  };
50
55
  declare type OperatorFunc = (value: any, ctx?: RegisterOperatorsContext) => any;
56
+ export declare const DialectVersionAccessors: {
57
+ sqlite: {
58
+ sql: string;
59
+ get: (v: string) => string;
60
+ };
61
+ mysql: {
62
+ sql: string;
63
+ get: (v: string) => string;
64
+ };
65
+ postgres: {
66
+ sql: string;
67
+ get: (v: string) => string;
68
+ };
69
+ };
51
70
  declare class DatabaseVersion {
52
71
  db: Database;
53
72
  constructor(db: Database);
@@ -58,6 +77,7 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
58
77
  migrator: Umzug;
59
78
  migrations: Migrations;
60
79
  fieldTypes: Map<any, any>;
80
+ fieldValueParsers: Map<any, any>;
61
81
  options: IDatabaseOptions;
62
82
  models: Map<string, ModelStatic<Model<any, any>>>;
63
83
  repositories: Map<string, typeof Repository>;
@@ -66,6 +86,8 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
66
86
  pendingFields: Map<string, FieldTypes.RelationField[]>;
67
87
  modelCollection: Map<ModelStatic<any>, Collection<any, any>>;
68
88
  tableNameCollectionMap: Map<string, Collection<any, any>>;
89
+ queryInterface: QueryInterface;
90
+ utils: DatabaseUtils;
69
91
  referenceMap: ReferencesMap;
70
92
  inheritanceMap: InheritanceMap;
71
93
  importedFrom: Map<string, string[]>;
@@ -75,17 +97,21 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
75
97
  collectionOptions: CollectionOptions;
76
98
  mergeOptions?: any;
77
99
  }[]>;
100
+ logger: Logger;
78
101
  constructor(options: DatabaseOptions);
102
+ setLogger(logger: Logger): void;
79
103
  initListener(): void;
80
104
  addMigration(item: MigrationItem): void;
81
105
  addMigrations(options: AddMigrationsOptions): void;
82
106
  inDialect(...dialect: string[]): boolean;
107
+ escapeId(identifier: string): string;
83
108
  /**
84
109
  * Add collection to database
85
110
  * @param options
86
111
  */
87
112
  collection<Attributes = any, CreateAttributes = Attributes>(options: CollectionOptions): Collection<Attributes, CreateAttributes>;
88
113
  getTablePrefix(): string;
114
+ getFieldByPath(path: string): any;
89
115
  /**
90
116
  * get exists collection by its name
91
117
  * @param name
@@ -100,6 +126,8 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
100
126
  addPendingField(field: RelationField): void;
101
127
  removePendingField(field: RelationField): void;
102
128
  registerFieldTypes(fieldTypes: MapOf<typeof Field>): void;
129
+ registerFieldValueParsers(parsers: MapOf<any>): void;
130
+ buildFieldValueParser<T extends BaseValueParser>(field: Field, ctx: any): T;
103
131
  registerModels(models: MapOf<ModelStatic<any>>): void;
104
132
  registerRepositories(repositories: MapOf<RepositoryType>): void;
105
133
  initOperators(): void;
@@ -107,11 +135,12 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
107
135
  buildField(options: any, context: FieldContext): any;
108
136
  sync(options?: SyncOptions): Promise<Sequelize>;
109
137
  clean(options: CleanOptions): Promise<void>;
110
- collectionExistsInDb(name: any, options?: Transactionable): Promise<boolean>;
138
+ collectionExistsInDb(name: string, options?: Transactionable): Promise<boolean>;
111
139
  isSqliteMemory(): boolean;
112
- auth(options?: QueryOptions & {
113
- retry?: number;
140
+ auth(options?: Omit<QueryOptions, 'retry'> & {
141
+ retry?: number | Pick<QueryOptions, 'retry'>;
114
142
  }): Promise<any>;
143
+ prepare(): Promise<void>;
115
144
  reconnect(): Promise<void>;
116
145
  closed(): any;
117
146
  close(): Promise<void>;