@nocobase/database 0.7.4-alpha.4 → 0.7.5-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 (97) 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 +6 -4
  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/operators/array.js +17 -9
  38. package/lib/operators/ne.d.ts +4 -0
  39. package/lib/operators/ne.js +3 -1
  40. package/lib/relation-repository/belongs-to-many-repository.js +6 -0
  41. package/lib/relation-repository/multiple-relation-repository.js +32 -9
  42. package/lib/relation-repository/relation-repository.js +7 -1
  43. package/lib/relation-repository/single-relation-repository.js +28 -0
  44. package/lib/repository.d.ts +5 -3
  45. package/lib/repository.js +40 -9
  46. package/lib/update-associations.js +48 -71
  47. package/lib/utils.d.ts +9 -0
  48. package/lib/utils.js +126 -0
  49. package/package.json +5 -3
  50. package/src/__tests__/collection.test.ts +47 -0
  51. package/src/__tests__/database.test.ts +2 -0
  52. package/src/__tests__/field-options/inddex.test.ts +43 -0
  53. package/src/__tests__/fields/array.test.ts +66 -0
  54. package/src/__tests__/fields/belongs-to-field.test.ts +35 -0
  55. package/src/__tests__/fields/belongs-to-many-field.test.ts +45 -0
  56. package/src/__tests__/fields/has-many-field.test.ts +22 -0
  57. package/src/__tests__/fields/has-one-field.test.ts +21 -0
  58. package/src/__tests__/fields/sequence-field.test.ts +455 -0
  59. package/src/__tests__/magic-attribute-model.test.ts +24 -0
  60. package/src/__tests__/operator/ne.test.ts +12 -0
  61. package/src/__tests__/relation-repository/appends.test.ts +64 -0
  62. package/src/__tests__/relation-repository/belongs-to-many-repository.test.ts +23 -0
  63. package/src/__tests__/relation-repository/has-many-repository.test.ts +20 -0
  64. package/src/__tests__/relation-repository/hasone-repository.test.ts +68 -1
  65. package/src/__tests__/repository/find.test.ts +35 -0
  66. package/src/__tests__/repository/update.test.ts +35 -0
  67. package/src/__tests__/repository.test.ts +15 -0
  68. package/src/collection.ts +28 -13
  69. package/src/database.ts +11 -7
  70. package/src/decorators/must-have-filter-decorator.ts +17 -0
  71. package/src/{transaction-decorator.ts → decorators/transaction-decorator.ts} +1 -2
  72. package/src/errors/identifier-error.ts +6 -0
  73. package/src/fields/belongs-to-field.ts +9 -0
  74. package/src/fields/belongs-to-many-field.ts +15 -0
  75. package/src/fields/date-field.ts +1 -1
  76. package/src/fields/field.ts +3 -3
  77. package/src/fields/formula-field.ts +13 -13
  78. package/src/fields/has-many-field.ts +10 -0
  79. package/src/fields/has-one-field.ts +13 -0
  80. package/src/fields/index.ts +5 -2
  81. package/src/fields/number-field.ts +10 -0
  82. package/src/fields/radio-field.ts +22 -24
  83. package/src/fields/sequence-field.ts +200 -0
  84. package/src/fields/sort-field.ts +9 -9
  85. package/src/filter-parser.ts +6 -5
  86. package/src/index.ts +1 -1
  87. package/src/magic-attribute-model.ts +188 -6
  88. package/src/mock-database.ts +1 -1
  89. package/src/operators/array.ts +17 -10
  90. package/src/operators/ne.ts +10 -6
  91. package/src/relation-repository/belongs-to-many-repository.ts +4 -0
  92. package/src/relation-repository/multiple-relation-repository.ts +26 -11
  93. package/src/relation-repository/relation-repository.ts +5 -1
  94. package/src/relation-repository/single-relation-repository.ts +27 -1
  95. package/src/repository.ts +37 -10
  96. package/src/update-associations.ts +41 -53
  97. package/src/utils.ts +71 -0
@@ -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
  });