@nocobase/database 0.7.4-alpha.7 → 0.7.6-alpha.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.
Files changed (101) hide show
  1. package/lib/collection.d.ts +7 -2
  2. package/lib/collection.js +20 -8
  3. package/lib/database.d.ts +2 -2
  4. package/lib/database.js +30 -6
  5. package/lib/decorators/must-have-filter-decorator.d.ts +2 -0
  6. package/lib/decorators/must-have-filter-decorator.js +25 -0
  7. package/lib/{transaction-decorator.d.ts → decorators/transaction-decorator.d.ts} +0 -0
  8. package/lib/{transaction-decorator.js → decorators/transaction-decorator.js} +1 -4
  9. package/lib/errors/identifier-error.d.ts +3 -0
  10. package/lib/errors/identifier-error.js +16 -0
  11. package/lib/fields/belongs-to-field.js +9 -0
  12. package/lib/fields/belongs-to-many-field.js +10 -0
  13. package/lib/fields/date-field.d.ts +1 -1
  14. package/lib/fields/date-field.js +1 -1
  15. package/lib/fields/field.d.ts +1 -1
  16. package/lib/fields/field.js +2 -3
  17. package/lib/fields/formula-field.d.ts +5 -5
  18. package/lib/fields/formula-field.js +123 -110
  19. package/lib/fields/has-many-field.js +9 -0
  20. package/lib/fields/has-one-field.js +9 -0
  21. package/lib/fields/index.d.ts +3 -1
  22. package/lib/fields/index.js +34 -1
  23. package/lib/fields/number-field.d.ts +6 -0
  24. package/lib/fields/number-field.js +10 -1
  25. package/lib/fields/radio-field.d.ts +3 -1
  26. package/lib/fields/radio-field.js +14 -11
  27. package/lib/fields/sequence-field.d.ts +31 -0
  28. package/lib/fields/sequence-field.js +299 -0
  29. package/lib/fields/sort-field.d.ts +4 -4
  30. package/lib/fields/sort-field.js +93 -80
  31. package/lib/filter-parser.js +10 -2
  32. package/lib/index.d.ts +1 -1
  33. package/lib/index.js +7 -0
  34. package/lib/magic-attribute-model.d.ts +1 -0
  35. package/lib/magic-attribute-model.js +207 -6
  36. package/lib/mock-database.js +1 -1
  37. package/lib/model.d.ts +5 -0
  38. package/lib/model.js +48 -6
  39. package/lib/operators/array.js +17 -9
  40. package/lib/operators/ne.d.ts +4 -0
  41. package/lib/operators/ne.js +3 -1
  42. package/lib/relation-repository/belongs-to-many-repository.js +6 -0
  43. package/lib/relation-repository/multiple-relation-repository.js +32 -9
  44. package/lib/relation-repository/relation-repository.js +7 -1
  45. package/lib/relation-repository/single-relation-repository.js +28 -0
  46. package/lib/repository.d.ts +6 -3
  47. package/lib/repository.js +42 -9
  48. package/lib/update-associations.js +48 -71
  49. package/lib/utils.d.ts +9 -0
  50. package/lib/utils.js +126 -0
  51. package/package.json +5 -3
  52. package/src/__tests__/collection.test.ts +47 -0
  53. package/src/__tests__/database.test.ts +2 -0
  54. package/src/__tests__/field-options/inddex.test.ts +43 -0
  55. package/src/__tests__/fields/array.test.ts +66 -0
  56. package/src/__tests__/fields/belongs-to-field.test.ts +35 -0
  57. package/src/__tests__/fields/belongs-to-many-field.test.ts +45 -0
  58. package/src/__tests__/fields/has-many-field.test.ts +22 -0
  59. package/src/__tests__/fields/has-one-field.test.ts +21 -0
  60. package/src/__tests__/fields/sequence-field.test.ts +455 -0
  61. package/src/__tests__/magic-attribute-model.test.ts +24 -0
  62. package/src/__tests__/model.changedWithAssociations.test.ts +46 -0
  63. package/src/__tests__/operator/ne.test.ts +12 -0
  64. package/src/__tests__/relation-repository/appends.test.ts +64 -0
  65. package/src/__tests__/relation-repository/belongs-to-many-repository.test.ts +23 -0
  66. package/src/__tests__/relation-repository/has-many-repository.test.ts +20 -0
  67. package/src/__tests__/relation-repository/hasone-repository.test.ts +68 -1
  68. package/src/__tests__/repository/find.test.ts +35 -0
  69. package/src/__tests__/repository/update.test.ts +35 -0
  70. package/src/__tests__/repository.test.ts +15 -0
  71. package/src/collection.ts +28 -13
  72. package/src/database.ts +18 -6
  73. package/src/decorators/must-have-filter-decorator.ts +17 -0
  74. package/src/{transaction-decorator.ts → decorators/transaction-decorator.ts} +1 -2
  75. package/src/errors/identifier-error.ts +6 -0
  76. package/src/fields/belongs-to-field.ts +9 -0
  77. package/src/fields/belongs-to-many-field.ts +15 -0
  78. package/src/fields/date-field.ts +1 -1
  79. package/src/fields/field.ts +3 -3
  80. package/src/fields/formula-field.ts +13 -13
  81. package/src/fields/has-many-field.ts +10 -0
  82. package/src/fields/has-one-field.ts +13 -0
  83. package/src/fields/index.ts +5 -2
  84. package/src/fields/number-field.ts +10 -0
  85. package/src/fields/radio-field.ts +22 -24
  86. package/src/fields/sequence-field.ts +200 -0
  87. package/src/fields/sort-field.ts +9 -9
  88. package/src/filter-parser.ts +6 -5
  89. package/src/index.ts +1 -1
  90. package/src/magic-attribute-model.ts +188 -6
  91. package/src/mock-database.ts +1 -1
  92. package/src/model.ts +34 -1
  93. package/src/operators/array.ts +17 -10
  94. package/src/operators/ne.ts +10 -6
  95. package/src/relation-repository/belongs-to-many-repository.ts +4 -0
  96. package/src/relation-repository/multiple-relation-repository.ts +26 -11
  97. package/src/relation-repository/relation-repository.ts +5 -1
  98. package/src/relation-repository/single-relation-repository.ts +27 -1
  99. package/src/repository.ts +40 -10
  100. package/src/update-associations.ts +41 -53
  101. package/src/utils.ts +71 -0
package/lib/utils.js ADDED
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.checkIdentifier = checkIdentifier;
7
+ exports.handleAppendsQuery = handleAppendsQuery;
8
+ exports.md5 = md5;
9
+
10
+ function _crypto() {
11
+ const data = _interopRequireDefault(require("crypto"));
12
+
13
+ _crypto = function _crypto() {
14
+ return data;
15
+ };
16
+
17
+ return data;
18
+ }
19
+
20
+ var _identifierError = require("./errors/identifier-error");
21
+
22
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
+
24
+ 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; }
25
+
26
+ 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; }
27
+
28
+ 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; }
29
+
30
+ 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; } } }; }
31
+
32
+ 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); }
33
+
34
+ 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; }
35
+
36
+ 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); } }
37
+
38
+ 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); }); }; }
39
+
40
+ function handleAppendsQuery(_x) {
41
+ return _handleAppendsQuery.apply(this, arguments);
42
+ }
43
+
44
+ function _handleAppendsQuery() {
45
+ _handleAppendsQuery = _asyncToGenerator(function* (options) {
46
+ const templateModel = options.templateModel,
47
+ queryPromises = options.queryPromises;
48
+ const primaryKey = templateModel.constructor.primaryKeyAttribute;
49
+ const results = yield Promise.all(queryPromises);
50
+ let rows;
51
+
52
+ var _iterator = _createForOfIteratorHelper(results),
53
+ _step;
54
+
55
+ try {
56
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
57
+ const appendedResult = _step.value;
58
+
59
+ if (!rows) {
60
+ rows = appendedResult.rows;
61
+
62
+ if (rows.length == 0) {
63
+ return [];
64
+ }
65
+
66
+ const modelOptions = templateModel['_options'];
67
+
68
+ var _iterator2 = _createForOfIteratorHelper(rows),
69
+ _step2;
70
+
71
+ try {
72
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
73
+ const row = _step2.value;
74
+ row['_options'] = _objectSpread(_objectSpread({}, row['_options']), {}, {
75
+ include: modelOptions['include'],
76
+ includeNames: modelOptions['includeNames'],
77
+ includeMap: modelOptions['includeMap']
78
+ });
79
+ }
80
+ } catch (err) {
81
+ _iterator2.e(err);
82
+ } finally {
83
+ _iterator2.f();
84
+ }
85
+
86
+ continue;
87
+ }
88
+
89
+ for (let i = 0; i < appendedResult.rows.length; i++) {
90
+ const appendingRow = appendedResult.rows[i];
91
+ const key = appendedResult.include.association;
92
+ const val = appendingRow.get(key);
93
+ const rowKey = appendingRow.get(primaryKey);
94
+ const targetIndex = rows.findIndex(row => row.get(primaryKey) === rowKey);
95
+
96
+ if (targetIndex === -1) {
97
+ throw new Error('target row not found');
98
+ }
99
+
100
+ rows[targetIndex].set(key, val, {
101
+ raw: true
102
+ });
103
+ }
104
+ }
105
+ } catch (err) {
106
+ _iterator.e(err);
107
+ } finally {
108
+ _iterator.f();
109
+ }
110
+
111
+ return rows;
112
+ });
113
+ return _handleAppendsQuery.apply(this, arguments);
114
+ }
115
+
116
+ function md5(value) {
117
+ return _crypto().default.createHash('md5').update(value).digest('hex');
118
+ }
119
+
120
+ const MAX_IDENTIFIER_LENGTH = 63;
121
+
122
+ function checkIdentifier(value) {
123
+ if (value.length > MAX_IDENTIFIER_LENGTH) {
124
+ throw new _identifierError.IdentifierError(`Identifier ${value} is too long`);
125
+ }
126
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/database",
3
- "version": "0.7.4-alpha.7",
3
+ "version": "0.7.6-alpha.1",
4
4
  "description": "",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -12,12 +12,14 @@
12
12
  }
13
13
  ],
14
14
  "dependencies": {
15
- "@nocobase/utils": "0.7.4-alpha.7",
15
+ "@nocobase/utils": "0.7.6-alpha.1",
16
16
  "async-mutex": "^0.3.2",
17
+ "cron-parser": "4.4.0",
17
18
  "deepmerge": "^4.2.2",
18
19
  "flat": "^5.0.2",
19
20
  "glob": "^7.1.6",
20
21
  "mathjs": "^10.6.1",
22
+ "moment": "2.x",
21
23
  "semver": "^7.3.7",
22
24
  "sequelize": "^6.9.0",
23
25
  "umzug": "^3.1.1"
@@ -30,5 +32,5 @@
30
32
  "url": "git+https://github.com/nocobase/nocobase.git",
31
33
  "directory": "packages/database"
32
34
  },
33
- "gitHead": "77f22e6da464d19be111835316faf4b94cd80413"
35
+ "gitHead": "f20ce011a9ac516dc6aec110979f063a0e63f923"
34
36
  }
@@ -1,6 +1,7 @@
1
1
  import { Collection } from '../collection';
2
2
  import { Database } from '../database';
3
3
  import { mockDatabase } from './index';
4
+ import { IdentifierError } from '../errors/identifier-error';
4
5
 
5
6
  describe('collection', () => {
6
7
  let db: Database;
@@ -258,4 +259,50 @@ describe('collection sync', () => {
258
259
  expect(tableFields['postId']).toBeDefined();
259
260
  expect(tableFields['tagId']).toBeDefined();
260
261
  });
262
+
263
+ test('limit table name length', async () => {
264
+ const longName =
265
+ 'this_is_a_very_long_table_name_that_should_be_truncated_this_is_a_very_long_table_name_that_should_be_truncated';
266
+
267
+ let error;
268
+
269
+ try {
270
+ const collection = new Collection(
271
+ {
272
+ name: longName,
273
+ fields: [{ type: 'string', name: 'test' }],
274
+ },
275
+ {
276
+ database: db,
277
+ },
278
+ );
279
+ } catch (e) {
280
+ error = e;
281
+ }
282
+
283
+ expect(error).toBeInstanceOf(IdentifierError);
284
+ });
285
+
286
+ test('limit field name length', async () => {
287
+ const longFieldName =
288
+ 'this_is_a_very_long_field_name_that_should_be_truncated_this_is_a_very_long_field_name_that_should_be_truncated';
289
+
290
+ let error;
291
+
292
+ try {
293
+ const collection = new Collection(
294
+ {
295
+ name: 'test',
296
+ fields: [{ type: 'string', name: longFieldName }],
297
+ },
298
+ {
299
+ database: db,
300
+ },
301
+ );
302
+ } catch (e) {
303
+ error = e;
304
+ }
305
+
306
+ expect(error).toBeInstanceOf(IdentifierError);
307
+ });
261
308
  });
@@ -268,8 +268,10 @@ describe('database', () => {
268
268
  });
269
269
 
270
270
  await Test.sync();
271
+ expect(Test.model.prototype).toBeInstanceOf(CustomModel);
271
272
 
272
273
  const test = await Test.model.create<any>();
274
+ expect(test).toBeInstanceOf(CustomModel);
273
275
  test.customMethod();
274
276
  expect(test.get('abc')).toBe('abc');
275
277
  });
@@ -0,0 +1,43 @@
1
+ import { mockDatabase } from '../';
2
+ import { Database } from '../../database';
3
+ import { md5 } from '../../utils';
4
+
5
+ describe('index field options', () => {
6
+ let db: Database;
7
+
8
+ beforeEach(async () => {
9
+ db = mockDatabase();
10
+ });
11
+
12
+ afterEach(async () => {
13
+ await db.close();
14
+ });
15
+
16
+ it('case 1', async () => {
17
+ const t1 = 't1234567890223456789032345678904234567890523456789';
18
+ const f1 = 'f1234567890223456789032345678904234567890523456789062345678901';
19
+ const f2 = 'f1234567890223456789032345678904234567890523456789062345678902';
20
+ db.collection({
21
+ name: t1,
22
+ fields: [
23
+ {
24
+ type: 'string',
25
+ name: f1,
26
+ index: true,
27
+ },
28
+ {
29
+ type: 'string',
30
+ name: f2,
31
+ index: true,
32
+ },
33
+ ],
34
+ });
35
+ await db.sync();
36
+ // @ts-ignore
37
+ const indexes = db.getModel(t1)._indexes;
38
+ const index1 = indexes.find((item) => item.fields.includes(f1));
39
+ const index2 = indexes.find((item) => item.fields.includes(f2));
40
+ expect('i_' + md5(db.getTablePrefix() + `${t1}_${f1}`)).toBe(index1.name);
41
+ expect('i_' + md5(db.getTablePrefix() + `${t1}_${f2}`)).toBe(index2.name);
42
+ });
43
+ });
@@ -0,0 +1,66 @@
1
+ import { mockDatabase } from '../';
2
+ import { Database } from '../../database';
3
+
4
+ describe('array field', () => {
5
+ let db: Database;
6
+
7
+ beforeEach(async () => {
8
+ db = mockDatabase();
9
+ });
10
+
11
+ afterEach(async () => {
12
+ await db.close();
13
+ });
14
+
15
+ it('should not be ambiguous', async () => {
16
+ db.collection({
17
+ name: 'a',
18
+ fields: [
19
+ {
20
+ type: 'array',
21
+ name: 'arr',
22
+ },
23
+ {
24
+ type: 'belongsToMany',
25
+ name: 'b',
26
+ target: 'b',
27
+ },
28
+ ],
29
+ });
30
+ db.collection({
31
+ name: 'b',
32
+ fields: [
33
+ {
34
+ type: 'array',
35
+ name: 'arr',
36
+ },
37
+ ],
38
+ });
39
+ await db.sync();
40
+ const repository = db.getRepository('a');
41
+ await repository.find({
42
+ filter: {
43
+ 'arr.$match': ['aa'],
44
+ },
45
+ appends: ['b'],
46
+ });
47
+ await repository.find({
48
+ filter: {
49
+ 'arr.$notMatch': ['aa'],
50
+ },
51
+ appends: ['b'],
52
+ });
53
+ await repository.find({
54
+ filter: {
55
+ 'arr.$anyOf': ['aa'],
56
+ },
57
+ appends: ['b'],
58
+ });
59
+ await repository.find({
60
+ filter: {
61
+ 'arr.$noneOf': ['aa'],
62
+ },
63
+ appends: ['b'],
64
+ });
65
+ });
66
+ });
@@ -1,5 +1,6 @@
1
1
  import { Database } from '../../database';
2
2
  import { mockDatabase } from '../';
3
+ import { IdentifierError } from '../../errors/identifier-error';
3
4
 
4
5
  describe('belongs to field', () => {
5
6
  let db: Database;
@@ -28,12 +29,16 @@ describe('belongs to field', () => {
28
29
  { type: 'belongsTo', name: 'post' },
29
30
  ],
30
31
  });
32
+
31
33
  expect(Comment.model.associations.post).toBeUndefined();
34
+
32
35
  const Post = db.collection({
33
36
  name: 'posts',
34
37
  fields: [{ type: 'string', name: 'title' }],
35
38
  });
39
+
36
40
  const association = Comment.model.associations.post;
41
+
37
42
  expect(Comment.model.associations.post).toBeDefined();
38
43
  expect(association.foreignKey).toBe('postId');
39
44
  // @ts-ignore
@@ -77,11 +82,41 @@ describe('belongs to field', () => {
77
82
  const association = Comment.model.associations.post;
78
83
  expect(association).toBeDefined();
79
84
  expect(association.foreignKey).toBe('postKey');
85
+
80
86
  // @ts-ignore
81
87
  expect(association.targetKey).toBe('key');
82
88
  expect(Comment.model.rawAttributes['postKey']).toBeDefined();
83
89
  });
84
90
 
91
+ it('should throw error when foreignKey is too long', async () => {
92
+ const Post = db.collection({
93
+ name: 'posts',
94
+ fields: [{ type: 'string', name: 'key', unique: true }],
95
+ });
96
+
97
+ const longForeignKey = 'a'.repeat(128);
98
+
99
+ let error;
100
+
101
+ try {
102
+ const Comment = db.collection({
103
+ name: 'comments1',
104
+ fields: [
105
+ {
106
+ type: 'belongsTo',
107
+ name: 'post',
108
+ targetKey: 'key',
109
+ foreignKey: longForeignKey,
110
+ },
111
+ ],
112
+ });
113
+ } catch (e) {
114
+ error = e;
115
+ }
116
+
117
+ expect(error).toBeInstanceOf(IdentifierError);
118
+ });
119
+
85
120
  it('custom name and target', async () => {
86
121
  const Comment = db.collection({
87
122
  name: 'comments',
@@ -1,5 +1,6 @@
1
1
  import { mockDatabase } from '../';
2
2
  import { Database } from '../../database';
3
+ import { IdentifierError } from '../../errors/identifier-error';
3
4
 
4
5
  describe('belongs to many field', () => {
5
6
  let db: Database;
@@ -58,4 +59,48 @@ describe('belongs to many field', () => {
58
59
  expect(PostTag.model.rawAttributes['postId']).toBeDefined();
59
60
  expect(PostTag.model.rawAttributes['tagId']).toBeDefined();
60
61
  });
62
+
63
+ it('should throw error when foreignKey is too long', async () => {
64
+ const Post = db.collection({
65
+ name: 'posts',
66
+ fields: [
67
+ { type: 'string', name: 'name' },
68
+ { type: 'belongsToMany', name: 'tags', foreignKey: 'a'.repeat(128) },
69
+ ],
70
+ });
71
+
72
+ let error;
73
+ try {
74
+ const Tag = db.collection({
75
+ name: 'tags',
76
+ fields: [{ type: 'string', name: 'name' }],
77
+ });
78
+ } catch (e) {
79
+ error = e;
80
+ }
81
+
82
+ expect(error).toBeInstanceOf(IdentifierError);
83
+ });
84
+
85
+ it('should throw error when through is too long', async () => {
86
+ const Post = db.collection({
87
+ name: 'posts',
88
+ fields: [
89
+ { type: 'string', name: 'name' },
90
+ { type: 'belongsToMany', name: 'tags', through: 'a'.repeat(128) },
91
+ ],
92
+ });
93
+
94
+ let error;
95
+ try {
96
+ const Tag = db.collection({
97
+ name: 'tags',
98
+ fields: [{ type: 'string', name: 'name' }],
99
+ });
100
+ } catch (e) {
101
+ error = e;
102
+ }
103
+
104
+ expect(error).toBeInstanceOf(IdentifierError);
105
+ });
61
106
  });
@@ -1,6 +1,7 @@
1
1
  import { Database } from '../../database';
2
2
  import { mockDatabase } from '../';
3
3
  import { makeWatchHost } from 'ts-loader/dist/servicesHost';
4
+ import { IdentifierError } from '../../errors/identifier-error';
4
5
 
5
6
  describe('has many field', () => {
6
7
  let db: Database;
@@ -149,4 +150,25 @@ describe('has many field', () => {
149
150
  Comment.removeField('post');
150
151
  expect(Comment.model.rawAttributes.postId).toBeUndefined();
151
152
  });
153
+
154
+ it('should throw error when foreignKey is too long', async () => {
155
+ const longForeignKey = 'a'.repeat(64);
156
+
157
+ const Post = db.collection({
158
+ name: 'posts',
159
+ fields: [{ type: 'hasMany', name: 'comments', foreignKey: longForeignKey }],
160
+ });
161
+
162
+ let error;
163
+ try {
164
+ const Comment = db.collection({
165
+ name: 'comments',
166
+ fields: [{ type: 'belongsTo', name: 'post' }],
167
+ });
168
+ } catch (e) {
169
+ error = e;
170
+ }
171
+
172
+ expect(error).toBeInstanceOf(IdentifierError);
173
+ });
152
174
  });
@@ -1,5 +1,6 @@
1
1
  import { Database } from '../../database';
2
2
  import { mockDatabase } from '../';
3
+ import { IdentifierError } from '../../errors/identifier-error';
3
4
 
4
5
  describe('has many field', () => {
5
6
  let db: Database;
@@ -64,4 +65,24 @@ describe('has many field', () => {
64
65
  Profile.removeField('user');
65
66
  expect(Profile.model.rawAttributes.userId).toBeUndefined();
66
67
  });
68
+
69
+ it('should throw error when foreignKey is too long', async () => {
70
+ const longForeignKey = 'a'.repeat(128);
71
+
72
+ const User = db.collection({
73
+ name: 'users',
74
+ fields: [{ type: 'hasOne', name: 'profile', foreignKey: longForeignKey }],
75
+ });
76
+
77
+ let error;
78
+ try {
79
+ const Profile = db.collection({
80
+ name: 'profiles',
81
+ fields: [{ type: 'belongsTo', name: 'user' }],
82
+ });
83
+ } catch (e) {
84
+ error = e;
85
+ }
86
+ expect(error).toBeInstanceOf(IdentifierError);
87
+ });
67
88
  });