@nocobase/database 0.9.0-alpha.2 → 0.9.1-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 (103) hide show
  1. package/lib/collection-importer.js +1 -1
  2. package/lib/collection.d.ts +7 -1
  3. package/lib/collection.js +135 -61
  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 +26 -3
  7. package/lib/database.js +224 -61
  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 +1 -2
  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/index.d.ts +6 -4
  19. package/lib/index.js +59 -36
  20. package/lib/mock-database.d.ts +2 -0
  21. package/lib/mock-database.js +3 -1
  22. package/lib/model.js +10 -1
  23. package/lib/options-parser.js +3 -0
  24. package/lib/relation-repository/belongs-to-many-repository.js +4 -2
  25. package/lib/repository.js +5 -2
  26. package/lib/sync-runner.d.ts +1 -1
  27. package/lib/sync-runner.js +28 -18
  28. package/lib/types.d.ts +7 -1
  29. package/lib/update-associations.js +17 -3
  30. package/lib/update-guard.d.ts +1 -0
  31. package/lib/update-guard.js +6 -0
  32. package/lib/utils.d.ts +5 -0
  33. package/lib/utils.js +68 -0
  34. package/lib/value-parsers/array-value-parser.d.ts +8 -0
  35. package/lib/value-parsers/array-value-parser.js +76 -0
  36. package/lib/value-parsers/base-value-parser.d.ts +12 -0
  37. package/lib/value-parsers/base-value-parser.js +59 -0
  38. package/lib/value-parsers/boolean-value-parser.d.ts +4 -0
  39. package/lib/value-parsers/boolean-value-parser.js +46 -0
  40. package/lib/value-parsers/date-value-parser.d.ts +5 -0
  41. package/lib/value-parsers/date-value-parser.js +91 -0
  42. package/lib/value-parsers/index.d.ts +12 -0
  43. package/lib/value-parsers/index.js +102 -0
  44. package/lib/value-parsers/json-value-parser.d.ts +4 -0
  45. package/lib/value-parsers/json-value-parser.js +37 -0
  46. package/lib/value-parsers/number-value-parser.d.ts +4 -0
  47. package/lib/value-parsers/number-value-parser.js +49 -0
  48. package/lib/value-parsers/string-value-parser.d.ts +8 -0
  49. package/lib/value-parsers/string-value-parser.js +76 -0
  50. package/lib/value-parsers/to-many-value-parser.d.ts +13 -0
  51. package/lib/value-parsers/to-many-value-parser.js +169 -0
  52. package/lib/value-parsers/to-one-value-parser.d.ts +4 -0
  53. package/lib/value-parsers/to-one-value-parser.js +49 -0
  54. package/package.json +4 -3
  55. package/src/__tests__/bigint.test.ts +1 -1
  56. package/src/__tests__/collection-importer.test.ts +13 -1
  57. package/src/__tests__/collection.test.ts +19 -9
  58. package/src/__tests__/database.test.ts +32 -0
  59. package/src/__tests__/fields/sort-field.test.ts +23 -0
  60. package/src/__tests__/inhertits/collection-inherits.test.ts +7 -5
  61. package/src/__tests__/percent2float.test.ts +14 -0
  62. package/src/__tests__/postgres/schema.test.ts +120 -0
  63. package/src/__tests__/underscored-options.test.ts +207 -0
  64. package/src/__tests__/update-associations-through.test.ts +73 -0
  65. package/src/__tests__/value-parsers/base.test.ts +20 -0
  66. package/src/__tests__/value-parsers/date.test.ts +67 -0
  67. package/src/__tests__/value-parsers/number.test.ts +46 -0
  68. package/src/__tests__/value-parsers/to-many.test.ts +206 -0
  69. package/src/__tests__/value-parsers/to-one.test.ts +60 -0
  70. package/src/collection-importer.ts +2 -2
  71. package/src/collection.ts +97 -15
  72. package/src/database-utils/index.ts +38 -0
  73. package/src/database.ts +171 -33
  74. package/src/fields/array-field.ts +1 -1
  75. package/src/fields/belongs-to-field.ts +1 -1
  76. package/src/fields/belongs-to-many-field.ts +0 -1
  77. package/src/fields/field.ts +45 -16
  78. package/src/fields/has-many-field.ts +1 -1
  79. package/src/fields/has-one-field.ts +11 -7
  80. package/src/fields/number-field.ts +10 -6
  81. package/src/fields/sort-field.ts +13 -1
  82. package/src/index.ts +7 -4
  83. package/src/inherited-collection.ts +1 -0
  84. package/src/mock-database.ts +3 -1
  85. package/src/model.ts +11 -2
  86. package/src/options-parser.ts +5 -0
  87. package/src/relation-repository/belongs-to-many-repository.ts +4 -2
  88. package/src/repository.ts +8 -3
  89. package/src/sync-runner.ts +33 -19
  90. package/src/types.ts +12 -1
  91. package/src/update-associations.ts +12 -5
  92. package/src/update-guard.ts +6 -0
  93. package/src/utils.ts +94 -0
  94. package/src/value-parsers/array-value-parser.ts +30 -0
  95. package/src/value-parsers/base-value-parser.ts +40 -0
  96. package/src/value-parsers/boolean-value-parser.ts +29 -0
  97. package/src/value-parsers/date-value-parser.ts +38 -0
  98. package/src/value-parsers/index.ts +46 -0
  99. package/src/value-parsers/json-value-parser.ts +19 -0
  100. package/src/value-parsers/number-value-parser.ts +29 -0
  101. package/src/value-parsers/string-value-parser.ts +31 -0
  102. package/src/value-parsers/to-many-value-parser.ts +85 -0
  103. package/src/value-parsers/to-one-value-parser.ts +20 -0
@@ -0,0 +1,207 @@
1
+ import { Database, mockDatabase } from '@nocobase/database';
2
+
3
+ describe('underscored options', () => {
4
+ let db: Database;
5
+
6
+ beforeEach(async () => {
7
+ db = mockDatabase({
8
+ underscored: true,
9
+ });
10
+
11
+ await db.clean({ drop: true });
12
+ });
13
+
14
+ afterEach(async () => {
15
+ await db.close();
16
+ });
17
+
18
+ it('should set two field with same type', async () => {
19
+ const collection = db.collection({
20
+ name: 'test',
21
+ fields: [
22
+ {
23
+ type: 'string',
24
+ name: 'test_field',
25
+ },
26
+ {
27
+ type: 'string',
28
+ name: 'testField',
29
+ },
30
+ ],
31
+ });
32
+
33
+ await db.sync();
34
+ });
35
+
36
+ it('should not set two field with difference type but same field name', async () => {
37
+ const collection = db.collection({
38
+ name: 'test',
39
+ fields: [
40
+ {
41
+ type: 'string',
42
+ name: 'test_field',
43
+ },
44
+ ],
45
+ });
46
+
47
+ expect(() => {
48
+ collection.addField('testField', { type: 'integer' });
49
+ }).toThrowError();
50
+
51
+ expect(() => {
52
+ collection.addField('test123', { type: 'integer', field: 'test_field' });
53
+ }).toThrowError();
54
+ });
55
+
56
+ it('should create index', async () => {
57
+ const collectionA = db.collection({
58
+ name: 'testCollection',
59
+ fields: [
60
+ {
61
+ type: 'string',
62
+ name: 'aField',
63
+ },
64
+ {
65
+ type: 'string',
66
+ name: 'bField',
67
+ },
68
+ ],
69
+ indexes: [
70
+ {
71
+ type: 'UNIQUE',
72
+ fields: ['aField', 'bField'],
73
+ },
74
+ ],
75
+ });
76
+
77
+ await db.sync();
78
+ });
79
+
80
+ it('should use underscored option', async () => {
81
+ const collectionA = db.collection({
82
+ name: 'testCollection',
83
+ underscored: true,
84
+ fields: [
85
+ {
86
+ type: 'string',
87
+ name: 'testField',
88
+ },
89
+ ],
90
+ });
91
+
92
+ await db.sync();
93
+
94
+ const tableName = collectionA.model.tableName;
95
+
96
+ expect(tableName.includes('test_collection')).toBeTruthy();
97
+
98
+ const repository = db.getRepository('testCollection');
99
+
100
+ await repository.create({
101
+ values: {
102
+ testField: 'test',
103
+ },
104
+ });
105
+
106
+ const record = await repository.findOne({});
107
+
108
+ expect(record.get('testField')).toBe('test');
109
+ });
110
+
111
+ it('should use database options', async () => {
112
+ const collectionA = db.collection({
113
+ name: 'testCollection',
114
+ fields: [
115
+ {
116
+ type: 'string',
117
+ name: 'testField',
118
+ },
119
+ ],
120
+ });
121
+
122
+ await db.sync();
123
+
124
+ const tableName = collectionA.model.tableName;
125
+
126
+ expect(tableName.includes('test_collection')).toBeTruthy();
127
+ });
128
+
129
+ test('through table', async () => {
130
+ db.collection({
131
+ name: 'posts',
132
+ fields: [
133
+ {
134
+ type: 'string',
135
+ name: 'name',
136
+ },
137
+ {
138
+ type: 'belongsToMany',
139
+ name: 'tags',
140
+ through: 'collectionCategory',
141
+ target: 'posts',
142
+ sourceKey: 'name',
143
+ foreignKey: 'postsName',
144
+ targetKey: 'name',
145
+ otherKey: 'tagsName',
146
+ },
147
+ ],
148
+ });
149
+
150
+ db.collection({
151
+ name: 'tags',
152
+ fields: [
153
+ {
154
+ type: 'string',
155
+ name: 'name',
156
+ },
157
+ {
158
+ type: 'belongsToMany',
159
+ name: 'posts',
160
+ target: 'posts',
161
+ through: 'collectionCategory',
162
+ sourceKey: 'name',
163
+ foreignKey: 'tagsName',
164
+ targetKey: 'name',
165
+ otherKey: 'postsName',
166
+ },
167
+ ],
168
+ });
169
+
170
+ await db.sync();
171
+
172
+ const through = db.getCollection('collectionCategory');
173
+
174
+ expect(through.model.tableName.includes('collection_category')).toBeTruthy();
175
+ });
176
+
177
+ test('db collectionExists', async () => {
178
+ const collectionA = db.collection({
179
+ name: 'testCollection',
180
+ underscored: true,
181
+ fields: [
182
+ {
183
+ type: 'string',
184
+ name: 'testField',
185
+ },
186
+ ],
187
+ });
188
+
189
+ expect(await db.collectionExistsInDb('testCollection')).toBeFalsy();
190
+
191
+ await db.sync();
192
+
193
+ expect(await db.collectionExistsInDb('testCollection')).toBeTruthy();
194
+ });
195
+
196
+ it('should throw error when table names conflict', async () => {
197
+ db.collection({
198
+ name: 'b1_z',
199
+ });
200
+
201
+ expect(() => {
202
+ db.collection({
203
+ name: 'b1Z',
204
+ });
205
+ }).toThrowError();
206
+ });
207
+ });
@@ -0,0 +1,73 @@
1
+ import { Database } from '../database';
2
+ import { mockDatabase } from './';
3
+
4
+ describe('update through', () => {
5
+ let db: Database;
6
+ beforeEach(async () => {
7
+ db = mockDatabase();
8
+ await db.clean({ drop: true });
9
+ });
10
+
11
+ afterEach(async () => {
12
+ await db.close();
13
+ });
14
+
15
+ it('should not be reset', async () => {
16
+ db.collection({
17
+ name: 'c',
18
+ autoGenId: true,
19
+ fields: [
20
+ {
21
+ name: 'id',
22
+ type: 'integer',
23
+ primaryKey: true,
24
+ autoIncrement: true,
25
+ },
26
+ ],
27
+ });
28
+ db.collection({
29
+ name: 'a',
30
+ fields: [
31
+ {
32
+ type: 'string',
33
+ name: 'name',
34
+ },
35
+ {
36
+ type: 'belongsToMany',
37
+ name: 'b',
38
+ target: 'b',
39
+ through: 'c',
40
+ },
41
+ ],
42
+ });
43
+ db.collection({
44
+ name: 'b',
45
+ fields: [],
46
+ });
47
+ await db.sync();
48
+ const callback1 = jest.fn();
49
+ const callback2 = jest.fn();
50
+ db.on('c.afterCreate', callback1);
51
+ db.on('c.afterBulkCreate', callback2);
52
+ const b = await db.getRepository('b').create({
53
+ values: {},
54
+ });
55
+ const a = await db.getRepository('a').create({
56
+ values: {
57
+ b: [b.toJSON()],
58
+ },
59
+ });
60
+ const c1 = await db.getRepository('c').findOne();
61
+ await db.getRepository('a').update({
62
+ filterByTk: a.id,
63
+ values: {
64
+ b: [b.toJSON()],
65
+ },
66
+ });
67
+
68
+ const c2 = await db.getRepository('c').findOne();
69
+ expect(c1.get('id')).toBe(c2.get('id'));
70
+ expect(callback1).toHaveBeenCalledTimes(1);
71
+ expect(callback2).toHaveBeenCalledTimes(1);
72
+ });
73
+ });
@@ -0,0 +1,20 @@
1
+ import { BaseValueParser as ValueParser } from '../../value-parsers';
2
+
3
+ describe('number value parser', () => {
4
+ let parser: ValueParser;
5
+
6
+ beforeEach(() => {
7
+ parser = new ValueParser({}, {});
8
+ });
9
+
10
+ it('should be converted to an array', () => {
11
+ expect(parser.toArr('A/B', '/')).toEqual(['A', 'B']);
12
+ expect(parser.toArr('A,B')).toEqual(['A', 'B']);
13
+ expect(parser.toArr('A, B')).toEqual(['A', 'B']);
14
+ expect(parser.toArr('A, B')).toEqual(['A', 'B']);
15
+ expect(parser.toArr('A, B ')).toEqual(['A', 'B']);
16
+ expect(parser.toArr('A, B ')).toEqual(['A', 'B']);
17
+ expect(parser.toArr('A、 B')).toEqual(['A', 'B']);
18
+ expect(parser.toArr('A ,, B')).toEqual(['A', 'B']);
19
+ });
20
+ });
@@ -0,0 +1,67 @@
1
+ import moment from 'moment';
2
+ import { Database, mockDatabase } from '../..';
3
+ import { DateValueParser } from '../../value-parsers';
4
+
5
+ describe('number value parser', () => {
6
+ let parser: DateValueParser;
7
+ let db: Database;
8
+
9
+ beforeEach(() => {
10
+ db = mockDatabase();
11
+ db.collection({
12
+ name: 'tests',
13
+ fields: [
14
+ {
15
+ name: 'date',
16
+ type: 'date',
17
+ },
18
+ {
19
+ name: 'dateOnly',
20
+ type: 'date',
21
+ uiSchema: {
22
+ ['x-component-props']: {
23
+ showTime: false,
24
+ gmt: false,
25
+ },
26
+ },
27
+ },
28
+ {
29
+ name: 'dateTime',
30
+ type: 'date',
31
+ uiSchema: {
32
+ ['x-component-props']: {
33
+ showTime: true,
34
+ },
35
+ },
36
+ },
37
+ {
38
+ name: 'dateTimeGmt',
39
+ type: 'date',
40
+ uiSchema: {
41
+ ['x-component-props']: {
42
+ showTime: true,
43
+ gmt: true,
44
+ },
45
+ },
46
+ },
47
+ ],
48
+ });
49
+ parser = new DateValueParser({}, {});
50
+ });
51
+
52
+ const expectValue = (value, field = 'date') => {
53
+ const collection = db.getCollection('tests');
54
+ parser = new DateValueParser(collection.getField(field), {});
55
+ parser.setValue(value);
56
+ return expect(parser.getValue());
57
+ };
58
+
59
+ it('should be correct', () => {
60
+ expectValue(42510).toBe('2016-05-20T00:00:00.000Z');
61
+ expectValue('42510').toBe('2016-05-20T00:00:00.000Z');
62
+ expectValue('2016-05-20T00:00:00.000Z').toBe('2016-05-20T00:00:00.000Z');
63
+ expectValue('2016-05-20 04:22:22', 'dateOnly').toBe('2016-05-20T00:00:00.000Z');
64
+ expectValue('2016-05-20 01:00:00', 'dateTime').toBe(moment('2016-05-20 01:00:00').toISOString());
65
+ expectValue('2016-05-20 01:00:00', 'dateTimeGmt').toBe('2016-05-20T01:00:00.000Z');
66
+ });
67
+ });
@@ -0,0 +1,46 @@
1
+ import { NumberValueParser } from '../../value-parsers';
2
+
3
+ describe('number value parser', () => {
4
+ let parser: NumberValueParser;
5
+
6
+ beforeEach(() => {
7
+ parser = new NumberValueParser({}, {});
8
+ });
9
+
10
+ const expectValue = (value) => {
11
+ parser = new NumberValueParser({}, {});
12
+ parser.setValue(value);
13
+ return expect(parser.getValue());
14
+ };
15
+
16
+ it('should be number', () => {
17
+ expectValue(123).toBe(123);
18
+ expect(parser.errors.length === 0).toBeTruthy();
19
+ expectValue('123').toBe(123);
20
+ expect(parser.errors.length === 0).toBeTruthy();
21
+ expectValue('123%').toBe(1.23);
22
+ expect(parser.errors.length === 0).toBeTruthy();
23
+ expectValue('22.5507%').toBe(0.225507);
24
+ expect(parser.errors.length === 0).toBeTruthy();
25
+ });
26
+
27
+ it('should be null', () => {
28
+ expectValue('').toBe(null);
29
+ expect(parser.errors.length === 0).toBeTruthy();
30
+ expectValue('n/a').toBe(null);
31
+ expect(parser.errors.length === 0).toBeTruthy();
32
+ expectValue('-').toBe(null);
33
+ expect(parser.errors.length === 0).toBeTruthy();
34
+ });
35
+
36
+ it('should be errors', () => {
37
+ expectValue({}).toBe(null);
38
+ expect(parser.errors.length > 0).toBeTruthy();
39
+ expectValue('123a').toBe(null);
40
+ expect(parser.errors.length > 0).toBeTruthy();
41
+ expectValue('123a%').toBe(null);
42
+ expect(parser.errors.length > 0).toBeTruthy();
43
+ expectValue('aaa').toBe(null);
44
+ expect(parser.errors.length > 0).toBeTruthy();
45
+ });
46
+ });
@@ -0,0 +1,206 @@
1
+ import { Database, mockDatabase } from '../..';
2
+ import { ToManyValueParser } from '../../value-parsers';
3
+
4
+ describe('number value parser', () => {
5
+ let parser: ToManyValueParser;
6
+ let db: Database;
7
+
8
+ beforeEach(async () => {
9
+ db = mockDatabase();
10
+ db.collection({
11
+ name: 'posts',
12
+ fields: [
13
+ {
14
+ type: 'belongsToMany',
15
+ name: 'tags',
16
+ },
17
+ {
18
+ type: 'belongsToMany',
19
+ name: 'attachments',
20
+ interface: 'attachment',
21
+ },
22
+ ],
23
+ });
24
+ db.collection({
25
+ name: 'attachments',
26
+ fields: [],
27
+ });
28
+ db.collection({
29
+ name: 'tags',
30
+ fields: [
31
+ {
32
+ type: 'string',
33
+ name: 'name',
34
+ },
35
+ ],
36
+ });
37
+ await db.sync();
38
+ const tag = db.getRepository('tags');
39
+ await tag.create({
40
+ values: { name: 'tag1' },
41
+ });
42
+ });
43
+
44
+ afterEach(async () => {
45
+ await db.close();
46
+ });
47
+
48
+ const setValue = async (value) => {
49
+ const post = db.getCollection('posts');
50
+ parser = new ToManyValueParser(post.getField('tags'), {
51
+ column: {
52
+ dataIndex: ['tags', 'name'],
53
+ },
54
+ });
55
+ await parser.setValue(value);
56
+ };
57
+
58
+ const setAttachment = async (value) => {
59
+ const post = db.getCollection('posts');
60
+ parser = new ToManyValueParser(post.getField('attachments'), {});
61
+ await parser.setValue(value);
62
+ };
63
+
64
+ it('should be [1]', async () => {
65
+ await setValue('tag1');
66
+ expect(parser.errors.length).toBe(0);
67
+ expect(parser.getValue()).toEqual([1]);
68
+ });
69
+
70
+ it('should be null', async () => {
71
+ await setValue('tag2');
72
+ expect(parser.errors.length).toBe(1);
73
+ expect(parser.getValue()).toBeNull();
74
+ });
75
+
76
+ it('should be attachment', async () => {
77
+ await setAttachment('https://www.nocobase.com/images/logo.png');
78
+ expect(parser.errors.length).toBe(0);
79
+ expect(parser.getValue()).toMatchObject([
80
+ {
81
+ title: 'logo.png',
82
+ extname: '.png',
83
+ filename: 'logo.png',
84
+ url: 'https://www.nocobase.com/images/logo.png',
85
+ },
86
+ ]);
87
+ });
88
+ });
89
+
90
+ describe.only('china region', () => {
91
+ let parser: ToManyValueParser;
92
+ let db: Database;
93
+
94
+ beforeEach(async () => {
95
+ db = mockDatabase();
96
+ db.collection({
97
+ name: 'users',
98
+ fields: [
99
+ {
100
+ type: 'belongsToMany',
101
+ name: 'chinaRegion',
102
+ target: 'chinaRegions',
103
+ interface: 'chinaRegion',
104
+ targetKey: 'code',
105
+ sortBy: 'level',
106
+ },
107
+ ],
108
+ });
109
+ db.collection({
110
+ name: 'chinaRegions',
111
+ autoGenId: false,
112
+ fields: [
113
+ {
114
+ name: 'code',
115
+ type: 'string',
116
+ // unique: true,
117
+ primaryKey: true,
118
+ },
119
+ {
120
+ name: 'name',
121
+ type: 'string',
122
+ },
123
+ {
124
+ name: 'parent',
125
+ type: 'belongsTo',
126
+ target: 'chinaRegions',
127
+ targetKey: 'code',
128
+ foreignKey: 'parentCode',
129
+ },
130
+ {
131
+ name: 'children',
132
+ type: 'hasMany',
133
+ target: 'chinaRegions',
134
+ sourceKey: 'code',
135
+ foreignKey: 'parentCode',
136
+ },
137
+ {
138
+ name: 'level',
139
+ type: 'integer',
140
+ },
141
+ ],
142
+ });
143
+ await db.sync();
144
+ const areas = require('china-division/dist/areas.json');
145
+ const cities = require('china-division/dist/cities.json');
146
+ const provinces = require('china-division/dist/provinces.json');
147
+ const ChinaRegion = db.getModel('chinaRegions');
148
+ await ChinaRegion.bulkCreate(
149
+ provinces.map((item) => ({
150
+ code: item.code,
151
+ name: item.name,
152
+ level: 1,
153
+ })),
154
+ );
155
+ await ChinaRegion.bulkCreate(
156
+ cities.map((item) => ({
157
+ code: item.code,
158
+ name: item.name,
159
+ level: 2,
160
+ parentCode: item.provinceCode,
161
+ })),
162
+ );
163
+ await ChinaRegion.bulkCreate(
164
+ areas.map((item) => ({
165
+ code: item.code,
166
+ name: item.name,
167
+ level: 3,
168
+ parentCode: item.cityCode,
169
+ })),
170
+ );
171
+ });
172
+
173
+ afterEach(async () => {
174
+ await db.close();
175
+ });
176
+
177
+ const setValue = async (value) => {
178
+ const r = db.getCollection('users');
179
+ parser = new ToManyValueParser(r.getField('chinaRegion'), {});
180
+ await parser.setValue(value);
181
+ };
182
+
183
+ it('should be correct', async () => {
184
+ await setValue('北京市/市辖区');
185
+ expect(parser.errors.length).toBe(0);
186
+ expect(parser.getValue()).toEqual(['11', '1101']);
187
+
188
+ await setValue('北京市 / 市辖区');
189
+ expect(parser.errors.length).toBe(0);
190
+ expect(parser.getValue()).toEqual(['11', '1101']);
191
+
192
+ await setValue('天津市 / 市辖区');
193
+ expect(parser.errors.length).toBe(0);
194
+ expect(parser.getValue()).toEqual(['12', '1201']);
195
+ });
196
+
197
+ it('should be null', async () => {
198
+ await setValue('北京市2 / 市辖区');
199
+ expect(parser.errors.length).toBe(1);
200
+ expect(parser.getValue()).toBeNull();
201
+
202
+ await setValue('北京市 / 市辖区 2');
203
+ expect(parser.errors.length).toBe(1);
204
+ expect(parser.getValue()).toBeNull();
205
+ });
206
+ });
@@ -0,0 +1,60 @@
1
+ import { Database, mockDatabase } from '../..';
2
+ import { ToManyValueParser } from '../../value-parsers';
3
+
4
+ describe('number value parser', () => {
5
+ let parser: ToManyValueParser;
6
+ let db: Database;
7
+
8
+ beforeEach(async () => {
9
+ db = mockDatabase();
10
+ db.collection({
11
+ name: 'posts',
12
+ fields: [
13
+ {
14
+ type: 'belongsTo',
15
+ name: 'user',
16
+ },
17
+ ],
18
+ });
19
+ db.collection({
20
+ name: 'users',
21
+ fields: [
22
+ {
23
+ type: 'string',
24
+ name: 'name',
25
+ },
26
+ ],
27
+ });
28
+ await db.sync();
29
+ const r = db.getRepository('users');
30
+ await r.create({
31
+ values: { name: 'user1' },
32
+ });
33
+ });
34
+
35
+ afterEach(async () => {
36
+ await db.close();
37
+ });
38
+
39
+ const setValue = async (value) => {
40
+ const post = db.getCollection('posts');
41
+ parser = new ToManyValueParser(post.getField('user'), {
42
+ column: {
43
+ dataIndex: ['user', 'name'],
44
+ },
45
+ });
46
+ await parser.setValue(value);
47
+ };
48
+
49
+ it('should be correct', async () => {
50
+ await setValue('user1');
51
+ expect(parser.errors.length).toBe(0);
52
+ expect(parser.getValue()).toEqual([1]);
53
+ });
54
+
55
+ it('should be null', async () => {
56
+ await setValue('user2');
57
+ expect(parser.errors.length).toBe(1);
58
+ expect(parser.getValue()).toBeNull();
59
+ });
60
+ });
@@ -1,6 +1,6 @@
1
1
  import path from 'path';
2
2
  import { readdir } from 'fs/promises';
3
- import { isPlainObject } from 'lodash';
3
+ import { cloneDeep, isPlainObject } from 'lodash';
4
4
  import { requireModule } from '@nocobase/utils';
5
5
 
6
6
  export type ImportFileExtension = 'js' | 'ts' | 'json';
@@ -36,6 +36,6 @@ export class ImporterReader {
36
36
  return typeof mod === 'function' ? mod() : mod;
37
37
  });
38
38
 
39
- return (await Promise.all(modules)).filter((module) => isPlainObject(module));
39
+ return (await Promise.all(modules)).filter((module) => isPlainObject(module)).map((module) => cloneDeep(module));
40
40
  }
41
41
  }