diff --git a/packages/core/database/src/__tests__/option-parser.test.ts b/packages/core/database/src/__tests__/option-parser.test.ts index b20d1e9f6..91d0c4fc1 100644 --- a/packages/core/database/src/__tests__/option-parser.test.ts +++ b/packages/core/database/src/__tests__/option-parser.test.ts @@ -112,80 +112,114 @@ describe('option parser', () => { ]); }); - test('option parser with fields option', async () => { - let options: any = { - fields: ['id', 'posts'], - }; - // 转换为 attributes: ['id'], include: [{association: 'posts'}] - let parser = new OptionsParser(options, { - collection: User, + describe('options parser with fields option', () => { + it('should handle field and association', () => { + const options: any = { + fields: ['id', 'posts'], + }; + + // 转换为 attributes: ['id'], include: [{association: 'posts'}] + const parser = new OptionsParser(options, { + collection: User, + }); + + const params = parser.toSequelizeParams(); + + console.log(params); + expect(params['attributes']).toContain('id'); + expect(params['include'][0]['association']).toEqual('posts'); }); - let params = parser.toSequelizeParams(); - expect(params['attributes']).toContain('id'); - expect(params['include'][0]['association']).toEqual('posts'); + it('should handle field with association', () => { + const options = { + appends: ['posts'], + }; - // only appends - options = { - appends: ['posts'], - }; + const parser = new OptionsParser(options, { + collection: User, + }); + const params = parser.toSequelizeParams(); - parser = new OptionsParser(options, { - collection: User, + expect(params['attributes']['include']).toEqual([]); + expect(params['include'][0]['association']).toEqual('posts'); }); - params = parser.toSequelizeParams(); - expect(params['attributes']['include']).toEqual([]); - expect(params['include'][0]['association']).toEqual('posts'); - // fields with association field - options = { - fields: ['id', 'posts.title'], - }; + it('should handle field with association field', () => { + // fields with association field + const options = { + fields: ['id', 'posts.title'], + }; - parser = new OptionsParser(options, { - collection: User, + const parser = new OptionsParser(options, { + collection: User, + }); + + const params = parser.toSequelizeParams(); + expect(params['attributes']).toContain('id'); + expect(params['include'][0]['association']).toEqual('posts'); + expect(params['include'][0]['attributes']).toContain('title'); }); - params = parser.toSequelizeParams(); - expect(params['attributes']).toContain('id'); - expect(params['include'][0]['association']).toEqual('posts'); - expect(params['include'][0]['attributes']).toContain('title'); - // fields with nested field - options = { - fields: ['id', 'posts', 'posts.comments.content'], - }; + it('should handle nested fields option', () => { + const options = { + fields: ['posts', 'posts.title'], + }; - parser = new OptionsParser(options, { - collection: User, + const parser = new OptionsParser(options, { + collection: User, + }); + + const params = parser.toSequelizeParams(); + const postAssociationParams = params['include'][0]; + expect(postAssociationParams['attributes']).toEqual({ include: [] }); }); - params = parser.toSequelizeParams(); - expect(params['attributes']).toContain('id'); - expect(params['include'][0]['association']).toEqual('posts'); - expect(params['include'][0]['attributes']).toEqual({ include: [] }); - expect(params['include'][0]['include'][0]['association']).toEqual('comments'); - // fields with expect - options = { - except: ['id'], - }; - parser = new OptionsParser(options, { - collection: User, + it('should handle fields with association & association field', () => { + // fields with nested field + const options = { + fields: ['id', 'posts', 'posts.comments.content'], + }; + + const parser = new OptionsParser(options, { + collection: User, + }); + + const params = parser.toSequelizeParams(); + const postAssociationParams = params['include'][0]; + + expect(params['attributes']).toContain('id'); + expect(postAssociationParams['association']).toEqual('posts'); + expect(postAssociationParams['attributes']).toEqual({ include: [] }); + expect(postAssociationParams['include'][0]['association']).toEqual('comments'); }); - params = parser.toSequelizeParams(); - expect(params['attributes']['exclude']).toContain('id'); - // expect with association - options = { - fields: ['posts'], - except: ['posts.id'], - }; + it('should handle except option', () => { + // fields with expect + const options = { + except: ['id'], + }; + const parser = new OptionsParser(options, { + collection: User, + }); - parser = new OptionsParser(options, { - collection: User, + const params = parser.toSequelizeParams(); + expect(params['attributes']['exclude']).toContain('id'); }); - params = parser.toSequelizeParams(); - expect(params['include'][0]['attributes']['exclude']).toContain('id'); + it('should handle fields with except option', () => { + // expect with association + const options = { + fields: ['posts'], + except: ['posts.id'], + }; + + const parser = new OptionsParser(options, { + collection: User, + }); + const params = parser.toSequelizeParams(); + + expect(params['include'][0]['attributes']['exclude']).toContain('id'); + }); }); test('option parser with multiple association', () => { diff --git a/packages/core/database/src/__tests__/repository/find.test.ts b/packages/core/database/src/__tests__/repository/find.test.ts index e3732fe02..693a37f96 100644 --- a/packages/core/database/src/__tests__/repository/find.test.ts +++ b/packages/core/database/src/__tests__/repository/find.test.ts @@ -378,23 +378,33 @@ describe('repository find', () => { }); }); - it('should only output filed in fields args', async () => { - const resp = await User.model.findOne({ - attributes: [], - include: [ - { - association: 'profile', - attributes: ['salary'], - }, - ], + describe('find with fields', () => { + it('should only output filed in fields args', async () => { + const users = await User.repository.find({ + fields: ['profile.salary'], + }); + + const firstUser = users[0].toJSON(); + expect(Object.keys(firstUser)).toEqual(['profile']); + expect(Object.keys(firstUser.profile)).toEqual(['salary']); }); - const users = await User.repository.find({ - fields: ['profile', 'profile.salary', 'profile.id'], - }); + it('should output all fields when field has relation field', async () => { + const users = await User.repository.find({ + fields: ['profile.salary', 'profile'], + }); - const firstUser = users[0].toJSON(); - expect(Object.keys(firstUser)).toEqual(['profile']); + const firstUser = users[0].toJSON(); + expect(Object.keys(firstUser)).toEqual(['profile']); + expect(Object.keys(firstUser.profile)).toEqual([ + 'id', + 'createdAt', + 'updatedAt', + 'salary', + 'userId', + 'description', + ]); + }); }); it('append with associations', async () => { diff --git a/packages/core/database/src/options-parser.ts b/packages/core/database/src/options-parser.ts index 330b97aa1..742a04808 100644 --- a/packages/core/database/src/options-parser.ts +++ b/packages/core/database/src/options-parser.ts @@ -240,6 +240,9 @@ export class OptionsParser { protected parseAppends(appends: Appends, filterParams: any) { if (!appends) return filterParams; + // sort appends by path length + appends = lodash.sortBy(appends, (append) => append.split('.').length); + /** * set include params * @param model @@ -287,6 +290,25 @@ export class OptionsParser { // if include from filter, remove fromFilter attribute if (existIncludeIndex != -1) { delete queryParams['include'][existIncludeIndex]['fromFilter']; + + // set include attributes to all attributes + if ( + Array.isArray(queryParams['include'][existIncludeIndex]['attributes']) && + queryParams['include'][existIncludeIndex]['attributes'].length == 0 + ) { + queryParams['include'][existIncludeIndex]['attributes'] = { + include: [], + }; + } + } + + if ( + lastLevel && + existIncludeIndex != -1 && + lodash.get(queryParams, ['include', existIncludeIndex, 'attributes', 'include'])?.length == 0 + ) { + // if append is last level and association exists, ignore it + return; } // if association not exist, create it