@nocobase/database 0.9.3-alpha.1 → 0.9.4-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.
- package/lib/collection.d.ts +9 -9
- package/lib/collection.js +100 -96
- package/lib/database.d.ts +4 -4
- package/lib/database.js +25 -53
- package/lib/eager-loading/eager-loading-tree.d.ts +23 -0
- package/lib/eager-loading/eager-loading-tree.js +338 -0
- package/lib/filter-parser.d.ts +1 -7
- package/lib/filter-parser.js +27 -7
- package/lib/listeners/append-child-collection-name-after-repository-find.d.ts +5 -0
- package/lib/listeners/append-child-collection-name-after-repository-find.js +40 -0
- package/lib/listeners/index.js +2 -0
- package/lib/mock-database.js +3 -1
- package/lib/operators/string.js +1 -1
- package/lib/options-parser.js +4 -0
- package/lib/query-interface/postgres-query-interface.js +2 -2
- package/lib/relation-repository/belongs-to-many-repository.d.ts +2 -1
- package/lib/relation-repository/belongs-to-many-repository.js +58 -37
- package/lib/relation-repository/hasmany-repository.d.ts +2 -1
- package/lib/relation-repository/hasmany-repository.js +31 -16
- package/lib/relation-repository/multiple-relation-repository.js +8 -26
- package/lib/relation-repository/relation-repository.d.ts +1 -7
- package/lib/relation-repository/single-relation-repository.d.ts +1 -1
- package/lib/relation-repository/single-relation-repository.js +10 -16
- package/lib/repository.d.ts +11 -8
- package/lib/repository.js +104 -89
- package/lib/sql-parser/postgres.js +41 -0
- package/lib/update-guard.d.ts +1 -1
- package/lib/update-guard.js +16 -13
- package/lib/utils.d.ts +0 -7
- package/lib/utils.js +0 -76
- package/package.json +4 -4
- package/src/__tests__/eager-loading/eager-loading-tree.test.ts +393 -0
- package/src/__tests__/migrator.test.ts +4 -0
- package/src/__tests__/relation-repository/hasone-repository.test.ts +1 -0
- package/src/__tests__/repository/aggregation.test.ts +297 -0
- package/src/__tests__/repository/count.test.ts +1 -1
- package/src/__tests__/repository/find.test.ts +10 -1
- package/src/__tests__/repository.test.ts +30 -0
- package/src/__tests__/update-guard.test.ts +13 -0
- package/src/collection.ts +74 -66
- package/src/database.ts +26 -42
- package/src/eager-loading/eager-loading-tree.ts +304 -0
- package/src/filter-parser.ts +16 -2
- package/src/listeners/adjacency-list.ts +1 -3
- package/src/listeners/append-child-collection-name-after-repository-find.ts +31 -0
- package/src/listeners/index.ts +2 -0
- package/src/mock-database.ts +3 -1
- package/src/operators/notIn.ts +1 -0
- package/src/operators/string.ts +1 -1
- package/src/options-parser.ts +5 -0
- package/src/query-interface/postgres-query-interface.ts +1 -1
- package/src/relation-repository/belongs-to-many-repository.ts +33 -1
- package/src/relation-repository/hasmany-repository.ts +17 -0
- package/src/relation-repository/multiple-relation-repository.ts +14 -19
- package/src/relation-repository/single-relation-repository.ts +13 -15
- package/src/repository.ts +79 -36
- package/src/sql-parser/postgres.js +25505 -0
- package/src/update-guard.ts +21 -16
- package/src/utils.ts +0 -61
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { BelongsToManyRepository, HasManyRepository, mockDatabase } from '../../index';
|
|
2
|
+
import Database from '../../database';
|
|
3
|
+
import { Collection } from '../../collection';
|
|
4
|
+
|
|
5
|
+
describe('association aggregation', () => {
|
|
6
|
+
let db: Database;
|
|
7
|
+
|
|
8
|
+
let User: Collection;
|
|
9
|
+
let Post: Collection;
|
|
10
|
+
let Tag: Collection;
|
|
11
|
+
|
|
12
|
+
afterEach(async () => {
|
|
13
|
+
await db.close();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
beforeEach(async () => {
|
|
17
|
+
db = mockDatabase();
|
|
18
|
+
await db.clean({ drop: true });
|
|
19
|
+
|
|
20
|
+
User = db.collection({
|
|
21
|
+
name: 'users',
|
|
22
|
+
fields: [
|
|
23
|
+
{ type: 'string', name: 'name' },
|
|
24
|
+
{ type: 'integer', name: 'age' },
|
|
25
|
+
{ type: 'hasMany', name: 'posts' },
|
|
26
|
+
{
|
|
27
|
+
type: 'belongsToMany',
|
|
28
|
+
name: 'tags',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
Post = db.collection({
|
|
34
|
+
name: 'posts',
|
|
35
|
+
fields: [
|
|
36
|
+
{
|
|
37
|
+
type: 'string',
|
|
38
|
+
name: 'title',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: 'string',
|
|
42
|
+
name: 'category',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
type: 'integer',
|
|
46
|
+
name: 'readCount',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: 'belongsTo',
|
|
50
|
+
name: 'user',
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
Tag = db.collection({
|
|
56
|
+
name: 'tags',
|
|
57
|
+
fields: [
|
|
58
|
+
{
|
|
59
|
+
type: 'string',
|
|
60
|
+
name: 'name',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
type: 'integer',
|
|
64
|
+
name: 'score',
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await db.sync();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('belongs to many', () => {
|
|
73
|
+
beforeEach(async () => {
|
|
74
|
+
await User.repository.create({
|
|
75
|
+
values: [
|
|
76
|
+
{
|
|
77
|
+
name: 'u1',
|
|
78
|
+
age: 1,
|
|
79
|
+
tags: [
|
|
80
|
+
{ name: 't1', score: 1 },
|
|
81
|
+
{ name: 't2', score: 2 },
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'u2',
|
|
86
|
+
age: 2,
|
|
87
|
+
tags: [
|
|
88
|
+
{ name: 't3', score: 3 },
|
|
89
|
+
{ name: 't4', score: 4 },
|
|
90
|
+
{ name: 't5', score: 4 },
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should sum field', async () => {
|
|
98
|
+
const user1 = await User.repository.findOne({
|
|
99
|
+
filter: {
|
|
100
|
+
name: 'u1',
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const TagRepository = await db.getRepository<BelongsToManyRepository>('users.tags', user1.get('id'));
|
|
105
|
+
|
|
106
|
+
const sumResult = await TagRepository.aggregate({
|
|
107
|
+
field: 'score',
|
|
108
|
+
method: 'sum',
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
expect(sumResult).toEqual(3);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should sum with filter', async () => {
|
|
115
|
+
const user1 = await User.repository.findOne({
|
|
116
|
+
filter: {
|
|
117
|
+
name: 'u2',
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const TagRepository = await db.getRepository<BelongsToManyRepository>('users.tags', user1.get('id'));
|
|
122
|
+
|
|
123
|
+
const sumResult = await TagRepository.aggregate({
|
|
124
|
+
field: 'score',
|
|
125
|
+
method: 'sum',
|
|
126
|
+
filter: {
|
|
127
|
+
score: 4,
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
expect(sumResult).toEqual(8);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should sum with distinct', async () => {
|
|
135
|
+
const user1 = await User.repository.findOne({
|
|
136
|
+
filter: {
|
|
137
|
+
name: 'u2',
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const TagRepository = await db.getRepository<BelongsToManyRepository>('users.tags', user1.get('id'));
|
|
142
|
+
|
|
143
|
+
const sumResult = await TagRepository.aggregate({
|
|
144
|
+
field: 'score',
|
|
145
|
+
method: 'sum',
|
|
146
|
+
distinct: true,
|
|
147
|
+
filter: {
|
|
148
|
+
score: 4,
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
expect(sumResult).toEqual(4);
|
|
153
|
+
});
|
|
154
|
+
it('should sum with association filter', async () => {
|
|
155
|
+
const sumResult = await User.repository.aggregate({
|
|
156
|
+
field: 'age',
|
|
157
|
+
method: 'sum',
|
|
158
|
+
filter: {
|
|
159
|
+
'tags.score': 4,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
expect(sumResult).toEqual(2);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe('has many', () => {
|
|
168
|
+
beforeEach(async () => {
|
|
169
|
+
await User.repository.create({
|
|
170
|
+
values: [
|
|
171
|
+
{
|
|
172
|
+
name: 'u1',
|
|
173
|
+
age: 1,
|
|
174
|
+
posts: [
|
|
175
|
+
{ title: 'p1', category: 'c1', readCount: 1 },
|
|
176
|
+
{ title: 'p2', category: 'c2', readCount: 2 },
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: 'u2',
|
|
181
|
+
age: 2,
|
|
182
|
+
posts: [
|
|
183
|
+
{ title: 'p3', category: 'c3', readCount: 3 },
|
|
184
|
+
{ title: 'p4', category: 'c4', readCount: 4 },
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('should sum field', async () => {
|
|
192
|
+
const user1 = await User.repository.findOne({
|
|
193
|
+
filter: {
|
|
194
|
+
name: 'u1',
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const PostRepository = await db.getRepository<HasManyRepository>('users.posts', user1.get('id'));
|
|
199
|
+
const sumResult = await PostRepository.aggregate({
|
|
200
|
+
field: 'readCount',
|
|
201
|
+
method: 'sum',
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
expect(sumResult).toEqual(3);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('should sum with filter', async () => {
|
|
208
|
+
const user1 = await User.repository.findOne({
|
|
209
|
+
filter: {
|
|
210
|
+
name: 'u1',
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const PostRepository = await db.getRepository<HasManyRepository>('users.posts', user1.get('id'));
|
|
215
|
+
const sumResult = await PostRepository.aggregate({
|
|
216
|
+
field: 'readCount',
|
|
217
|
+
method: 'sum',
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
expect(sumResult).toEqual(3);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
describe('Aggregation', () => {
|
|
226
|
+
let db: Database;
|
|
227
|
+
|
|
228
|
+
let User: Collection;
|
|
229
|
+
afterEach(async () => {
|
|
230
|
+
await db.close();
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
beforeEach(async () => {
|
|
234
|
+
db = mockDatabase();
|
|
235
|
+
await db.clean({ drop: true });
|
|
236
|
+
|
|
237
|
+
User = db.collection({
|
|
238
|
+
name: 'users',
|
|
239
|
+
fields: [
|
|
240
|
+
{
|
|
241
|
+
type: 'string',
|
|
242
|
+
name: 'name',
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
type: 'integer',
|
|
246
|
+
name: 'age',
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
await db.sync();
|
|
252
|
+
|
|
253
|
+
await User.repository.create({
|
|
254
|
+
values: [
|
|
255
|
+
{ name: 'u1', age: 1 },
|
|
256
|
+
{ name: 'u2', age: 2 },
|
|
257
|
+
{ name: 'u3', age: 3 },
|
|
258
|
+
{ name: 'u4', age: 4 },
|
|
259
|
+
{ name: 'u5', age: 5 },
|
|
260
|
+
{ name: 'u5', age: 5 },
|
|
261
|
+
],
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
describe('sum', () => {
|
|
266
|
+
it('should sum field', async () => {
|
|
267
|
+
const sumResult = await User.repository.aggregate({
|
|
268
|
+
method: 'sum',
|
|
269
|
+
field: 'age',
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
expect(sumResult).toEqual(20);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('should sum with distinct', async () => {
|
|
276
|
+
const sumResult = await User.repository.aggregate({
|
|
277
|
+
method: 'sum',
|
|
278
|
+
field: 'age',
|
|
279
|
+
distinct: true,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
expect(sumResult).toEqual(15);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('should sum with filter', async () => {
|
|
286
|
+
const sumResult = await User.repository.aggregate({
|
|
287
|
+
method: 'sum',
|
|
288
|
+
field: 'age',
|
|
289
|
+
filter: {
|
|
290
|
+
name: 'u5',
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
expect(sumResult).toEqual(10);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
});
|
|
@@ -176,7 +176,7 @@ describe('find with associations', () => {
|
|
|
176
176
|
},
|
|
177
177
|
});
|
|
178
178
|
|
|
179
|
-
expect(filterResult[0].user.department).toBeDefined();
|
|
179
|
+
expect(filterResult[0].get('user').get('department')).toBeDefined();
|
|
180
180
|
});
|
|
181
181
|
|
|
182
182
|
it('should filter by association field', async () => {
|
|
@@ -440,6 +440,15 @@ describe('repository find', () => {
|
|
|
440
440
|
expect(Object.keys(data)).toEqual(['id', 'posts']);
|
|
441
441
|
expect(Object.keys(data['posts'])).not.toContain('id');
|
|
442
442
|
});
|
|
443
|
+
|
|
444
|
+
test('find one with appends', async () => {
|
|
445
|
+
const profile = await Profile.repository.findOne({
|
|
446
|
+
filterByTk: 1,
|
|
447
|
+
appends: ['user.name'],
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
expect(profile.get('user').get('name')).toEqual('u1');
|
|
451
|
+
});
|
|
443
452
|
});
|
|
444
453
|
|
|
445
454
|
describe('find', () => {
|
|
@@ -54,6 +54,7 @@ describe('repository.find', () => {
|
|
|
54
54
|
let User: Collection;
|
|
55
55
|
let Post: Collection;
|
|
56
56
|
let Comment: Collection;
|
|
57
|
+
let Tag: Collection;
|
|
57
58
|
|
|
58
59
|
beforeEach(async () => {
|
|
59
60
|
db = mockDatabase();
|
|
@@ -70,8 +71,18 @@ describe('repository.find', () => {
|
|
|
70
71
|
{ type: 'string', name: 'name' },
|
|
71
72
|
{ type: 'belongsTo', name: 'user' },
|
|
72
73
|
{ type: 'hasMany', name: 'comments' },
|
|
74
|
+
{ type: 'belongsToMany', name: 'tags' },
|
|
73
75
|
],
|
|
74
76
|
});
|
|
77
|
+
|
|
78
|
+
Tag = db.collection({
|
|
79
|
+
name: 'tags',
|
|
80
|
+
fields: [
|
|
81
|
+
{ type: 'string', name: 'name' },
|
|
82
|
+
{ type: 'belongsToMany', name: 'posts' },
|
|
83
|
+
],
|
|
84
|
+
});
|
|
85
|
+
|
|
75
86
|
Comment = db.collection({
|
|
76
87
|
name: 'comments',
|
|
77
88
|
fields: [
|
|
@@ -80,6 +91,10 @@ describe('repository.find', () => {
|
|
|
80
91
|
],
|
|
81
92
|
});
|
|
82
93
|
await db.sync();
|
|
94
|
+
|
|
95
|
+
const tags = await Tag.repository.create({
|
|
96
|
+
values: [{ name: 't1' }, { name: 't2' }],
|
|
97
|
+
});
|
|
83
98
|
await User.repository.createMany({
|
|
84
99
|
records: [
|
|
85
100
|
{
|
|
@@ -88,18 +103,22 @@ describe('repository.find', () => {
|
|
|
88
103
|
{
|
|
89
104
|
name: 'post11',
|
|
90
105
|
comments: [{ name: 'comment111' }, { name: 'comment112' }, { name: 'comment113' }],
|
|
106
|
+
tags: [{ id: tags[0].get('id') }],
|
|
91
107
|
},
|
|
92
108
|
{
|
|
93
109
|
name: 'post12',
|
|
94
110
|
comments: [{ name: 'comment121' }, { name: 'comment122' }, { name: 'comment123' }],
|
|
111
|
+
tags: [{ id: tags[1].get('id') }, { id: tags[0].get('id') }],
|
|
95
112
|
},
|
|
96
113
|
{
|
|
97
114
|
name: 'post13',
|
|
98
115
|
comments: [{ name: 'comment131' }, { name: 'comment132' }, { name: 'comment133' }],
|
|
116
|
+
tags: [{ id: tags[0].get('id') }],
|
|
99
117
|
},
|
|
100
118
|
{
|
|
101
119
|
name: 'post14',
|
|
102
120
|
comments: [{ name: 'comment141' }, { name: 'comment142' }, { name: 'comment143' }],
|
|
121
|
+
tags: [{ id: tags[1].get('id') }],
|
|
103
122
|
},
|
|
104
123
|
],
|
|
105
124
|
},
|
|
@@ -109,6 +128,7 @@ describe('repository.find', () => {
|
|
|
109
128
|
{
|
|
110
129
|
name: 'post21',
|
|
111
130
|
comments: [{ name: 'comment211' }, { name: 'comment212' }, { name: 'comment213' }],
|
|
131
|
+
tags: [{ id: tags[0].get('id') }, { id: tags[1].get('id') }],
|
|
112
132
|
},
|
|
113
133
|
{
|
|
114
134
|
name: 'post22',
|
|
@@ -144,6 +164,16 @@ describe('repository.find', () => {
|
|
|
144
164
|
await db.close();
|
|
145
165
|
});
|
|
146
166
|
|
|
167
|
+
it('should appends with belongs to association', async () => {
|
|
168
|
+
const posts = await Post.repository.find({
|
|
169
|
+
appends: ['user'],
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
posts.forEach((post) => {
|
|
173
|
+
expect(post.get('user')).toBeDefined();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
147
177
|
test('find pk with filter', async () => {
|
|
148
178
|
const Test = db.collection({
|
|
149
179
|
name: 'tests',
|
|
@@ -108,6 +108,19 @@ describe('update-guard', () => {
|
|
|
108
108
|
});
|
|
109
109
|
});
|
|
110
110
|
|
|
111
|
+
test('association with null array', () => {
|
|
112
|
+
const values = {
|
|
113
|
+
name: 'u1',
|
|
114
|
+
posts: [null],
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const guard = new UpdateGuard();
|
|
118
|
+
guard.setModel(User.model);
|
|
119
|
+
const sanitized = guard.sanitize(values);
|
|
120
|
+
|
|
121
|
+
expect(sanitized).toEqual({ name: 'u1', posts: [null] });
|
|
122
|
+
});
|
|
123
|
+
|
|
111
124
|
test('association black list', () => {
|
|
112
125
|
const values = {
|
|
113
126
|
name: 'username123',
|
package/src/collection.ts
CHANGED
|
@@ -79,6 +79,31 @@ export class Collection<
|
|
|
79
79
|
model: ModelStatic<Model>;
|
|
80
80
|
repository: Repository<TModelAttributes, TCreationAttributes>;
|
|
81
81
|
|
|
82
|
+
constructor(options: CollectionOptions, context: CollectionContext) {
|
|
83
|
+
super();
|
|
84
|
+
this.context = context;
|
|
85
|
+
this.options = options;
|
|
86
|
+
|
|
87
|
+
this.checkOptions(options);
|
|
88
|
+
|
|
89
|
+
this.bindFieldEventListener();
|
|
90
|
+
this.modelInit();
|
|
91
|
+
|
|
92
|
+
this.db.modelCollection.set(this.model, this);
|
|
93
|
+
|
|
94
|
+
// set tableName to collection map
|
|
95
|
+
// the form of key is `${schema}.${tableName}` if schema exists
|
|
96
|
+
// otherwise is `${tableName}`
|
|
97
|
+
this.db.tableNameCollectionMap.set(this.getTableNameWithSchemaAsString(), this);
|
|
98
|
+
|
|
99
|
+
if (!options.inherits) {
|
|
100
|
+
this.setFields(options.fields);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this.setRepository(options.repository);
|
|
104
|
+
this.setSortable(options.sortable);
|
|
105
|
+
}
|
|
106
|
+
|
|
82
107
|
get filterTargetKey() {
|
|
83
108
|
const targetKey = lodash.get(this.options, 'filterTargetKey', this.model.primaryKeyAttribute);
|
|
84
109
|
if (!targetKey && this.model.rawAttributes['id']) {
|
|
@@ -116,65 +141,12 @@ export class Collection<
|
|
|
116
141
|
}
|
|
117
142
|
}
|
|
118
143
|
|
|
119
|
-
constructor(options: CollectionOptions, context: CollectionContext) {
|
|
120
|
-
super();
|
|
121
|
-
this.context = context;
|
|
122
|
-
this.options = options;
|
|
123
|
-
|
|
124
|
-
this.checkOptions(options);
|
|
125
|
-
|
|
126
|
-
this.bindFieldEventListener();
|
|
127
|
-
this.modelInit();
|
|
128
|
-
|
|
129
|
-
this.db.modelCollection.set(this.model, this);
|
|
130
|
-
|
|
131
|
-
// set tableName to collection map
|
|
132
|
-
// the form of key is `${schema}.${tableName}` if schema exists
|
|
133
|
-
// otherwise is `${tableName}`
|
|
134
|
-
this.db.tableNameCollectionMap.set(this.getTableNameWithSchemaAsString(), this);
|
|
135
|
-
|
|
136
|
-
if (!options.inherits) {
|
|
137
|
-
this.setFields(options.fields);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
this.setRepository(options.repository);
|
|
141
|
-
this.setSortable(options.sortable);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
private checkOptions(options: CollectionOptions) {
|
|
145
|
-
checkIdentifier(options.name);
|
|
146
|
-
this.checkTableName();
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
private checkTableName() {
|
|
150
|
-
const tableName = this.tableName();
|
|
151
|
-
for (const [k, collection] of this.db.collections) {
|
|
152
|
-
if (
|
|
153
|
-
collection.name != this.options.name &&
|
|
154
|
-
tableName === collection.tableName() &&
|
|
155
|
-
collection.collectionSchema() === this.collectionSchema()
|
|
156
|
-
) {
|
|
157
|
-
throw new Error(`collection ${collection.name} and ${this.name} have same tableName "${tableName}"`);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
144
|
tableName() {
|
|
163
145
|
const { name, tableName } = this.options;
|
|
164
146
|
const tName = tableName || name;
|
|
165
147
|
return this.options.underscored ? snakeCase(tName) : tName;
|
|
166
148
|
}
|
|
167
149
|
|
|
168
|
-
protected sequelizeModelOptions() {
|
|
169
|
-
const { name } = this.options;
|
|
170
|
-
return {
|
|
171
|
-
..._.omit(this.options, ['name', 'fields', 'model', 'targetKey']),
|
|
172
|
-
modelName: name,
|
|
173
|
-
sequelize: this.context.database.sequelize,
|
|
174
|
-
tableName: this.tableName(),
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
|
|
178
150
|
/**
|
|
179
151
|
* TODO
|
|
180
152
|
*/
|
|
@@ -232,17 +204,6 @@ export class Collection<
|
|
|
232
204
|
this.repository = new repo(this);
|
|
233
205
|
}
|
|
234
206
|
|
|
235
|
-
private bindFieldEventListener() {
|
|
236
|
-
this.on('field.afterAdd', (field: Field) => {
|
|
237
|
-
field.bind();
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
this.on('field.afterRemove', (field: Field) => {
|
|
241
|
-
field.unbind();
|
|
242
|
-
this.db.emit('field.afterRemove', field);
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
|
|
246
207
|
forEachField(callback: (field: Field) => void) {
|
|
247
208
|
return [...this.fields.values()].forEach(callback);
|
|
248
209
|
}
|
|
@@ -299,12 +260,20 @@ export class Collection<
|
|
|
299
260
|
const [sourceCollectionName, sourceFieldName] = options.source.split('.');
|
|
300
261
|
const sourceCollection = this.db.collections.get(sourceCollectionName);
|
|
301
262
|
if (!sourceCollection) {
|
|
302
|
-
|
|
263
|
+
this.db.logger.warn(
|
|
303
264
|
`source collection "${sourceCollectionName}" not found for field "${name}" at collection "${this.name}"`,
|
|
304
265
|
);
|
|
305
266
|
}
|
|
267
|
+
|
|
306
268
|
const sourceField = sourceCollection.fields.get(sourceFieldName);
|
|
307
|
-
|
|
269
|
+
|
|
270
|
+
if (!sourceField) {
|
|
271
|
+
this.db.logger.warn(
|
|
272
|
+
`source field "${sourceFieldName}" not found for field "${name}" at collection "${this.name}"`,
|
|
273
|
+
);
|
|
274
|
+
} else {
|
|
275
|
+
options = { ...sourceField.options, ...options };
|
|
276
|
+
}
|
|
308
277
|
}
|
|
309
278
|
|
|
310
279
|
this.emit('field.beforeAdd', name, options, { collection: this });
|
|
@@ -678,4 +647,43 @@ export class Collection<
|
|
|
678
647
|
public isView() {
|
|
679
648
|
return false;
|
|
680
649
|
}
|
|
650
|
+
|
|
651
|
+
protected sequelizeModelOptions() {
|
|
652
|
+
const { name } = this.options;
|
|
653
|
+
return {
|
|
654
|
+
..._.omit(this.options, ['name', 'fields', 'model', 'targetKey']),
|
|
655
|
+
modelName: name,
|
|
656
|
+
sequelize: this.context.database.sequelize,
|
|
657
|
+
tableName: this.tableName(),
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
private checkOptions(options: CollectionOptions) {
|
|
662
|
+
checkIdentifier(options.name);
|
|
663
|
+
this.checkTableName();
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
private checkTableName() {
|
|
667
|
+
const tableName = this.tableName();
|
|
668
|
+
for (const [k, collection] of this.db.collections) {
|
|
669
|
+
if (
|
|
670
|
+
collection.name != this.options.name &&
|
|
671
|
+
tableName === collection.tableName() &&
|
|
672
|
+
collection.collectionSchema() === this.collectionSchema()
|
|
673
|
+
) {
|
|
674
|
+
throw new Error(`collection ${collection.name} and ${this.name} have same tableName "${tableName}"`);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
private bindFieldEventListener() {
|
|
680
|
+
this.on('field.afterAdd', (field: Field) => {
|
|
681
|
+
field.bind();
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
this.on('field.afterRemove', (field: Field) => {
|
|
685
|
+
field.unbind();
|
|
686
|
+
this.db.emit('field.afterRemove', field);
|
|
687
|
+
});
|
|
688
|
+
}
|
|
681
689
|
}
|