diff --git a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many-custom-name.resolver.graphql b/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many-custom-name.resolver.graphql deleted file mode 100644 index c95cfe65d..000000000 --- a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many-custom-name.resolver.graphql +++ /dev/null @@ -1,134 +0,0 @@ -type TestResolverDTO { - id: ID! - stringField: String! - tests( - """Limit or page results.""" - paging: CursorPaging = {first: 10} - - """Specify to filter the records returned.""" - filter: TestRelationDTOFilter = {} - - """Specify to sort results.""" - sorting: [TestRelationDTOSort!] = [] - ): TestResolverDTOTestsConnection! -} - -input CursorPaging { - """Paginate before opaque cursor""" - before: ConnectionCursor - - """Paginate after opaque cursor""" - after: ConnectionCursor - - """Paginate first""" - first: Int - - """Paginate last""" - last: Int -} - -"""Cursor for paging through collections""" -scalar ConnectionCursor - -input TestRelationDTOFilter { - and: [TestRelationDTOFilter!] - or: [TestRelationDTOFilter!] - id: IDFilterComparison - testResolverId: StringFieldComparison -} - -input IDFilterComparison { - is: Boolean - isNot: Boolean - eq: ID - neq: ID - gt: ID - gte: ID - lt: ID - lte: ID - like: ID - notLike: ID - iLike: ID - notILike: ID - in: [ID!] - notIn: [ID!] -} - -input StringFieldComparison { - is: Boolean - isNot: Boolean - eq: String - neq: String - gt: String - gte: String - lt: String - lte: String - like: String - notLike: String - iLike: String - notILike: String - in: [String!] - notIn: [String!] -} - -input TestRelationDTOSort { - field: TestRelationDTOSortFields! - direction: SortDirection! - nulls: SortNulls -} - -enum TestRelationDTOSortFields { - id - testResolverId -} - -"""Sort Directions""" -enum SortDirection { - ASC - DESC -} - -"""Sort Nulls Options""" -enum SortNulls { - NULLS_FIRST - NULLS_LAST -} - -type TestRelationDTO { - id: ID! - testResolverId: String! -} - -type TestRelationDTOEdge { - """The node containing the TestRelationDTO""" - node: TestRelationDTO! - - """Cursor for this node.""" - cursor: ConnectionCursor! -} - -type PageInfo { - """true if paging forward and there are more records.""" - hasNextPage: Boolean - - """true if paging backwards and there are more records.""" - hasPreviousPage: Boolean - - """The cursor of the first returned record.""" - startCursor: ConnectionCursor - - """The cursor of the last returned record.""" - endCursor: ConnectionCursor -} - -type TestResolverDTOTestsConnection { - """Paging information""" - pageInfo: PageInfo! - - """Array of edges.""" - edges: [TestRelationDTOEdge!]! -} - -type Query { - test: TestResolverDTO! -} diff --git a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many-disabled.resolver.graphql b/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many-disabled.resolver.graphql deleted file mode 100644 index 0a583ce78..000000000 --- a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many-disabled.resolver.graphql +++ /dev/null @@ -1,38 +0,0 @@ -type TestResolverDTO { - id: ID! - stringField: String! -} - -type TestRelationDTO { - id: ID! - testResolverId: String! -} - -type TestRelationDTOEdge { - """The node containing the TestRelationDTO""" - node: TestRelationDTO! - - """Cursor for this node.""" - cursor: ConnectionCursor! -} - -"""Cursor for paging through collections""" -scalar ConnectionCursor - -type PageInfo { - """true if paging forward and there are more records.""" - hasNextPage: Boolean - - """true if paging backwards and there are more records.""" - hasPreviousPage: Boolean - - """The cursor of the first returned record.""" - startCursor: ConnectionCursor - - """The cursor of the last returned record.""" - endCursor: ConnectionCursor -} - -type Query { - test: TestResolverDTO! -} diff --git a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many.resolver.graphql b/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many.resolver.graphql deleted file mode 100644 index 62a0fadcb..000000000 --- a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many.resolver.graphql +++ /dev/null @@ -1,134 +0,0 @@ -type TestResolverDTO { - id: ID! - stringField: String! - relations( - """Limit or page results.""" - paging: CursorPaging = {first: 10} - - """Specify to filter the records returned.""" - filter: TestRelationDTOFilter = {} - - """Specify to sort results.""" - sorting: [TestRelationDTOSort!] = [] - ): TestResolverDTORelationsConnection! -} - -input CursorPaging { - """Paginate before opaque cursor""" - before: ConnectionCursor - - """Paginate after opaque cursor""" - after: ConnectionCursor - - """Paginate first""" - first: Int - - """Paginate last""" - last: Int -} - -"""Cursor for paging through collections""" -scalar ConnectionCursor - -input TestRelationDTOFilter { - and: [TestRelationDTOFilter!] - or: [TestRelationDTOFilter!] - id: IDFilterComparison - testResolverId: StringFieldComparison -} - -input IDFilterComparison { - is: Boolean - isNot: Boolean - eq: ID - neq: ID - gt: ID - gte: ID - lt: ID - lte: ID - like: ID - notLike: ID - iLike: ID - notILike: ID - in: [ID!] - notIn: [ID!] -} - -input StringFieldComparison { - is: Boolean - isNot: Boolean - eq: String - neq: String - gt: String - gte: String - lt: String - lte: String - like: String - notLike: String - iLike: String - notILike: String - in: [String!] - notIn: [String!] -} - -input TestRelationDTOSort { - field: TestRelationDTOSortFields! - direction: SortDirection! - nulls: SortNulls -} - -enum TestRelationDTOSortFields { - id - testResolverId -} - -"""Sort Directions""" -enum SortDirection { - ASC - DESC -} - -"""Sort Nulls Options""" -enum SortNulls { - NULLS_FIRST - NULLS_LAST -} - -type TestRelationDTO { - id: ID! - testResolverId: String! -} - -type TestRelationDTOEdge { - """The node containing the TestRelationDTO""" - node: TestRelationDTO! - - """Cursor for this node.""" - cursor: ConnectionCursor! -} - -type PageInfo { - """true if paging forward and there are more records.""" - hasNextPage: Boolean - - """true if paging backwards and there are more records.""" - hasPreviousPage: Boolean - - """The cursor of the first returned record.""" - startCursor: ConnectionCursor - - """The cursor of the last returned record.""" - endCursor: ConnectionCursor -} - -type TestResolverDTORelationsConnection { - """Paging information""" - pageInfo: PageInfo! - - """Array of edges.""" - edges: [TestRelationDTOEdge!]! -} - -type Query { - test: TestResolverDTO! -} diff --git a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one-custom-name.resolver.graphql b/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one-custom-name.resolver.graphql deleted file mode 100644 index 26e9b781b..000000000 --- a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one-custom-name.resolver.graphql +++ /dev/null @@ -1,39 +0,0 @@ -type TestResolverDTO { - id: ID! - stringField: String! - test: TestRelationDTO! -} - -type TestRelationDTO { - id: ID! - testResolverId: String! -} - -type TestRelationDTOEdge { - """The node containing the TestRelationDTO""" - node: TestRelationDTO! - - """Cursor for this node.""" - cursor: ConnectionCursor! -} - -"""Cursor for paging through collections""" -scalar ConnectionCursor - -type PageInfo { - """true if paging forward and there are more records.""" - hasNextPage: Boolean - - """true if paging backwards and there are more records.""" - hasPreviousPage: Boolean - - """The cursor of the first returned record.""" - startCursor: ConnectionCursor - - """The cursor of the last returned record.""" - endCursor: ConnectionCursor -} - -type Query { - test: TestResolverDTO! -} diff --git a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one-disabled.resolver.graphql b/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one-disabled.resolver.graphql deleted file mode 100644 index 0a583ce78..000000000 --- a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one-disabled.resolver.graphql +++ /dev/null @@ -1,38 +0,0 @@ -type TestResolverDTO { - id: ID! - stringField: String! -} - -type TestRelationDTO { - id: ID! - testResolverId: String! -} - -type TestRelationDTOEdge { - """The node containing the TestRelationDTO""" - node: TestRelationDTO! - - """Cursor for this node.""" - cursor: ConnectionCursor! -} - -"""Cursor for paging through collections""" -scalar ConnectionCursor - -type PageInfo { - """true if paging forward and there are more records.""" - hasNextPage: Boolean - - """true if paging backwards and there are more records.""" - hasPreviousPage: Boolean - - """The cursor of the first returned record.""" - startCursor: ConnectionCursor - - """The cursor of the last returned record.""" - endCursor: ConnectionCursor -} - -type Query { - test: TestResolverDTO! -} diff --git a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one-nullable.resolver.graphql b/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one-nullable.resolver.graphql deleted file mode 100644 index ff871e43d..000000000 --- a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one-nullable.resolver.graphql +++ /dev/null @@ -1,39 +0,0 @@ -type TestResolverDTO { - id: ID! - stringField: String! - relation: TestRelationDTO -} - -type TestRelationDTO { - id: ID! - testResolverId: String! -} - -type TestRelationDTOEdge { - """The node containing the TestRelationDTO""" - node: TestRelationDTO! - - """Cursor for this node.""" - cursor: ConnectionCursor! -} - -"""Cursor for paging through collections""" -scalar ConnectionCursor - -type PageInfo { - """true if paging forward and there are more records.""" - hasNextPage: Boolean - - """true if paging backwards and there are more records.""" - hasPreviousPage: Boolean - - """The cursor of the first returned record.""" - startCursor: ConnectionCursor - - """The cursor of the last returned record.""" - endCursor: ConnectionCursor -} - -type Query { - test: TestResolverDTO! -} diff --git a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one.resolver.graphql b/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one.resolver.graphql deleted file mode 100644 index 5f6d3d86c..000000000 --- a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-one.resolver.graphql +++ /dev/null @@ -1,39 +0,0 @@ -type TestResolverDTO { - id: ID! - stringField: String! - relation: TestRelationDTO! -} - -type TestRelationDTO { - id: ID! - testResolverId: String! -} - -type TestRelationDTOEdge { - """The node containing the TestRelationDTO""" - node: TestRelationDTO! - - """Cursor for this node.""" - cursor: ConnectionCursor! -} - -"""Cursor for paging through collections""" -scalar ConnectionCursor - -type PageInfo { - """true if paging forward and there are more records.""" - hasNextPage: Boolean - - """true if paging backwards and there are more records.""" - hasPreviousPage: Boolean - - """The cursor of the first returned record.""" - startCursor: ConnectionCursor - - """The cursor of the last returned record.""" - endCursor: ConnectionCursor -} - -type Query { - test: TestResolverDTO! -} diff --git a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many-nullable.resolver.graphql b/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation.resolver.graphql similarity index 72% rename from packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many-nullable.resolver.graphql rename to packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation.resolver.graphql index 6f9463be9..087e7a386 100644 --- a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation-many-nullable.resolver.graphql +++ b/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/federation/federation-relation.resolver.graphql @@ -1,7 +1,12 @@ -type TestResolverDTO { +type TestRelationDTO { + id: ID! + testResolverId: String! +} + +type TestFederated { id: ID! stringField: String! - relations( + relationConnections( """Limit or page results.""" paging: CursorPaging = {first: 10} @@ -10,7 +15,26 @@ type TestResolverDTO { """Specify to sort results.""" sorting: [TestRelationDTOSort!] = [] - ): TestResolverDTORelationsConnection + ): TestFederatedRelationConnectionsConnection! + relationsNoPagings( + """Specify to filter the records returned.""" + filter: TestRelationDTOFilter = {} + + """Specify to sort results.""" + sorting: [TestRelationDTOSort!] = [] + ): [TestRelationDTO!]! + relations( + """Limit or page results.""" + paging: OffsetPaging = {limit: 10} + + """Specify to filter the records returned.""" + filter: TestRelationDTOFilter = {} + + """Specify to sort results.""" + sorting: [TestRelationDTOSort!] = [] + ): [TestRelationDTO!]! + custom: TestRelationDTO! + relation: TestRelationDTO! } input CursorPaging { @@ -94,9 +118,12 @@ enum SortNulls { NULLS_LAST } -type TestRelationDTO { - id: ID! - testResolverId: String! +input OffsetPaging { + """Limit the number of records returned""" + limit: Int + + """Offset to start returning records from""" + offset: Int } type TestRelationDTOEdge { @@ -121,7 +148,7 @@ type PageInfo { endCursor: ConnectionCursor } -type TestResolverDTORelationsConnection { +type TestFederatedRelationConnectionsConnection { """Paging information""" pageInfo: PageInfo! @@ -130,5 +157,5 @@ type TestResolverDTORelationsConnection { } type Query { - test: TestResolverDTO! + test: TestFederated! } diff --git a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/index.ts b/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/index.ts index 12f616bd8..b0edeae85 100644 --- a/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/index.ts +++ b/packages/query-graphql/__tests__/resolvers/federation/__fixtures__/index.ts @@ -6,27 +6,6 @@ export { TestRelationDTO } from './test-relation.dto'; export const federationRelationEmptySDL = readGraphql( resolve(__dirname, 'federation', 'federation-relation-empty.resolver.graphql'), ); -export const federationRelationOneSDL = readGraphql( - resolve(__dirname, 'federation', 'federation-relation-one.resolver.graphql'), -); -export const federationRelationOneCustomNameSDL = readGraphql( - resolve(__dirname, 'federation', 'federation-relation-one-custom-name.resolver.graphql'), -); -export const federationRelationOneNullableSDL = readGraphql( - resolve(__dirname, 'federation', 'federation-relation-one-nullable.resolver.graphql'), -); -export const federationRelationOneDisabledSDL = readGraphql( - resolve(__dirname, 'federation', 'federation-relation-one-disabled.resolver.graphql'), -); -export const federationRelationManySDL = readGraphql( - resolve(__dirname, 'federation', 'federation-relation-many.resolver.graphql'), -); -export const federationRelationManyCustomNameSDL = readGraphql( - resolve(__dirname, 'federation', 'federation-relation-many-custom-name.resolver.graphql'), -); -export const federationRelationManyNullableSDL = readGraphql( - resolve(__dirname, 'federation', 'federation-relation-many-nullable.resolver.graphql'), -); -export const federationRelationManyDisabledSDL = readGraphql( - resolve(__dirname, 'federation', 'federation-relation-many-disabled.resolver.graphql'), +export const federationRelationSDL = readGraphql( + resolve(__dirname, 'federation', 'federation-relation.resolver.graphql'), ); diff --git a/packages/query-graphql/__tests__/resolvers/federation/federation.resolver.spec.ts b/packages/query-graphql/__tests__/resolvers/federation/federation.resolver.spec.ts index 8c6bdba5c..1f08f4a1a 100644 --- a/packages/query-graphql/__tests__/resolvers/federation/federation.resolver.spec.ts +++ b/packages/query-graphql/__tests__/resolvers/federation/federation.resolver.spec.ts @@ -1,187 +1,105 @@ -import { Query, Resolver } from '@nestjs/graphql'; +import { Class } from '@nestjs-query/core'; +import { ObjectType, Query, Resolver, ID } from '@nestjs/graphql'; import { deepEqual, objectContaining, when } from 'ts-mockito'; -import { FederationResolver, RelationsOpts } from '../../../src/resolvers'; -import { CursorQueryArgsType, OffsetQueryArgsType, PagingStrategies } from '../../../src/types'; +import { + Connection, + CursorQueryArgsType, + FederationResolver, + FilterableField, + OffsetQueryArgsType, + PagingStrategies, + Relation, +} from '../../../src'; import { expectSDL } from '../../__fixtures__'; import { createResolverFromNest, TestResolverDTO, TestService } from '../__fixtures__'; -import { - federationRelationEmptySDL, - federationRelationManyCustomNameSDL, - federationRelationManyDisabledSDL, - federationRelationManyNullableSDL, - federationRelationManySDL, - federationRelationOneCustomNameSDL, - federationRelationOneDisabledSDL, - federationRelationOneNullableSDL, - federationRelationOneSDL, - TestRelationDTO, -} from './__fixtures__'; +import { federationRelationEmptySDL, federationRelationSDL, TestRelationDTO } from './__fixtures__'; describe('FederationResolver', () => { - const expectResolverSDL = (sdl: string, opts?: RelationsOpts) => { - @Resolver(() => TestResolverDTO) - class TestSDLResolver extends FederationResolver(TestResolverDTO, opts) { - @Query(() => TestResolverDTO) - test(): TestResolverDTO { - return { id: '1', stringField: 'foo' }; + const expectResolverSDL = (sdl: string, DTOClass: Class) => { + @Resolver(() => DTOClass) + class TestSDLResolver extends FederationResolver(DTOClass) { + @Query(() => DTOClass) + test(): DTO { + return { id: '1', stringField: 'foo' } as DTO; } } return expectSDL([TestSDLResolver], sdl); }; - it('should not add federation methods if one and many are empty', () => { - return expectResolverSDL(federationRelationEmptySDL); - }); - describe('one', () => { - @Resolver(() => TestResolverDTO) - class TestResolver extends FederationResolver(TestResolverDTO, { - one: { relation: { DTO: TestRelationDTO }, custom: { DTO: TestRelationDTO, relationName: 'other' } }, - }) { - constructor(service: TestService) { - super(service); - } + @ObjectType('TestFederated') + @Relation('relation', () => TestRelationDTO) + @Relation('custom', () => TestRelationDTO, { relationName: 'other' }) + @Relation('relations', () => [TestRelationDTO]) + @Relation('relationsNoPaging', () => [TestRelationDTO], { pagingStrategy: PagingStrategies.NONE }) + @Connection('relationConnection', () => TestRelationDTO) + class TestFederatedDTO extends TestResolverDTO { + @FilterableField(() => ID) + id!: string; + + @FilterableField() + stringField!: string; + } + + @Resolver(() => TestFederatedDTO) + class TestResolver extends FederationResolver(TestFederatedDTO) { + constructor(service: TestService) { + super(service); } - it('should use the object type name', () => { - return expectResolverSDL(federationRelationOneSDL, { one: { relation: { DTO: TestRelationDTO } } }); - }); - - it('should use the dtoName if provided', () => { - return expectResolverSDL(federationRelationOneCustomNameSDL, { - one: { relation: { DTO: TestRelationDTO, dtoName: 'Test' } }, - }); - }); - - it('should set the field to nullable if set to true', () => { - return expectResolverSDL(federationRelationOneNullableSDL, { - one: { relation: { DTO: TestRelationDTO, nullable: true } }, - }); - }); - - it('should not add federation one methods if disableRead is true', () => { - return expectResolverSDL(federationRelationOneDisabledSDL, { - one: { relation: { DTO: TestRelationDTO, disableRead: true } }, - }); - }); + } - it('should call the service findRelation with the provided dto', async () => { - const { resolver, mockService } = await createResolverFromNest(TestResolver); - const dto: TestResolverDTO = { - id: 'id-1', - stringField: 'foo', - }; - const output: TestRelationDTO = { - id: 'id-2', - testResolverId: dto.id, - }; - when(mockService.findRelation(TestRelationDTO, 'relation', deepEqual([dto]))).thenResolve( - new Map([[dto, output]]), - ); - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - const result = await resolver.findRelation(dto, {}); - return expect(result).toEqual(output); - }); - - it('should call the service findRelation with the provided dto and correct relation name', async () => { - const { resolver, mockService } = await createResolverFromNest(TestResolver); - const dto: TestResolverDTO = { - id: 'id-1', - stringField: 'foo', - }; - const output: TestRelationDTO = { - id: 'id-2', - testResolverId: dto.id, - }; - when(mockService.findRelation(TestRelationDTO, 'other', deepEqual([dto]))).thenResolve(new Map([[dto, output]])); - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - const result = await resolver.findCustom(dto, {}); - return expect(result).toEqual(output); - }); + it('should not add federation methods if one and many are empty', () => { + return expectResolverSDL(federationRelationEmptySDL, TestResolverDTO); }); - describe('many', () => { - it('should use the object type name', () => { - return expectResolverSDL(federationRelationManySDL, { many: { relations: { DTO: TestRelationDTO } } }); - }); - - it('should use the dtoName if provided', () => { - return expectResolverSDL(federationRelationManyCustomNameSDL, { - many: { relations: { DTO: TestRelationDTO, dtoName: 'Test' } }, - }); - }); - - it('should set the field to nullable if set to true', () => { - return expectResolverSDL(federationRelationManyNullableSDL, { - many: { relations: { DTO: TestRelationDTO, nullable: true } }, - }); - }); - - it('should not add federation methods if disableRead is true', () => { - return expectResolverSDL(federationRelationManyDisabledSDL, { - many: { relations: { DTO: TestRelationDTO, disableRead: true } }, - }); - }); - - describe('with cursor paging strategy', () => { - @Resolver(() => TestResolverDTO) - class TestResolver extends FederationResolver(TestResolverDTO, { - one: { relation: { DTO: TestRelationDTO }, custom: { DTO: TestRelationDTO, relationName: 'other' } }, - many: { relations: { DTO: TestRelationDTO }, customs: { DTO: TestRelationDTO, relationName: 'others' } }, - }) { - constructor(service: TestService) { - super(service); - } - } + it('use the defined relations', () => { + return expectResolverSDL(federationRelationSDL, TestFederatedDTO); + }); + describe('one', () => { + describe('one relation', () => { it('should call the service findRelation with the provided dto', async () => { const { resolver, mockService } = await createResolverFromNest(TestResolver); const dto: TestResolverDTO = { id: 'id-1', stringField: 'foo', }; - const query: CursorQueryArgsType = { - filter: { id: { eq: 'id-2' } }, - paging: { first: 1 }, + const output: TestRelationDTO = { + id: 'id-2', + testResolverId: dto.id, }; - const output: TestRelationDTO[] = [ - { - id: 'id-2', - testResolverId: dto.id, - }, - ]; - when( - mockService.queryRelations( - TestRelationDTO, - 'relations', - deepEqual([dto]), - objectContaining({ ...query, paging: { limit: 2, offset: 0 } }), - ), - ).thenResolve(new Map([[dto, output]])); + when(mockService.findRelation(TestRelationDTO, 'relation', deepEqual([dto]))).thenResolve( + new Map([[dto, output]]), + ); // @ts-ignore // eslint-disable-next-line @typescript-eslint/no-unsafe-call - const result = await resolver.queryRelations(dto, query, {}); - return expect(result).toEqual({ - edges: [ - { - cursor: 'YXJyYXljb25uZWN0aW9uOjA=', - node: { - id: output[0].id, - testResolverId: dto.id, - }, - }, - ], - pageInfo: { - endCursor: 'YXJyYXljb25uZWN0aW9uOjA=', - hasNextPage: false, - hasPreviousPage: false, - startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', - }, - totalCountFn: expect.any(Function), - }); + const result = await resolver.findRelation(dto, {}); + return expect(result).toEqual(output); }); it('should call the service findRelation with the provided dto and correct relation name', async () => { + const { resolver, mockService } = await createResolverFromNest(TestResolver); + const dto: TestResolverDTO = { + id: 'id-1', + stringField: 'foo', + }; + const output: TestRelationDTO = { + id: 'id-2', + testResolverId: dto.id, + }; + when(mockService.findRelation(TestRelationDTO, 'other', deepEqual([dto]))).thenResolve( + new Map([[dto, output]]), + ); + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + const result = await resolver.findCustom(dto, {}); + return expect(result).toEqual(output); + }); + }); + }); + + describe('many - connection', () => { + describe('with cursor paging strategy', () => { + it('should call the service findRelation with the provided dto', async () => { const { resolver, mockService } = await createResolverFromNest(TestResolver); const dto: TestResolverDTO = { id: 'id-1', @@ -200,14 +118,14 @@ describe('FederationResolver', () => { when( mockService.queryRelations( TestRelationDTO, - 'others', + 'relationConnections', deepEqual([dto]), objectContaining({ ...query, paging: { limit: 2, offset: 0 } }), ), ).thenResolve(new Map([[dto, output]])); // @ts-ignore // eslint-disable-next-line @typescript-eslint/no-unsafe-call - const result = await resolver.queryCustoms(dto, query, {}); + const result = await resolver.queryRelationConnections(dto, query, {}); return expect(result).toEqual({ edges: [ { @@ -228,69 +146,59 @@ describe('FederationResolver', () => { }); }); }); + }); - describe('with offset paging strategy', () => { - @Resolver(() => TestResolverDTO) - class TestResolver extends FederationResolver(TestResolverDTO, { - many: { - relations: { DTO: TestRelationDTO, pagingStrategy: PagingStrategies.OFFSET }, - customs: { DTO: TestRelationDTO, pagingStrategy: PagingStrategies.OFFSET, relationName: 'others' }, + describe('with offset paging strategy', () => { + it('should call the service findRelation with the provided dto', async () => { + const { resolver, mockService } = await createResolverFromNest(TestResolver); + const dto: TestResolverDTO = { + id: 'id-1', + stringField: 'foo', + }; + const query: OffsetQueryArgsType = { + filter: { id: { eq: 'id-2' } }, + paging: { limit: 1 }, + }; + const output: TestRelationDTO[] = [ + { + id: 'id-2', + testResolverId: dto.id, }, - }) { - constructor(service: TestService) { - super(service); - } - } - - it('should call the service findRelation with the provided dto', async () => { - const { resolver, mockService } = await createResolverFromNest(TestResolver); - const dto: TestResolverDTO = { - id: 'id-1', - stringField: 'foo', - }; - const query: OffsetQueryArgsType = { - filter: { id: { eq: 'id-2' } }, - paging: { limit: 1 }, - }; - const output: TestRelationDTO[] = [ - { - id: 'id-2', - testResolverId: dto.id, - }, - ]; - when( - mockService.queryRelations(TestRelationDTO, 'relations', deepEqual([dto]), objectContaining(query)), - ).thenResolve(new Map([[dto, output]])); - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - const result = await resolver.queryRelations(dto, query, {}); - return expect(result).toEqual(output); - }); + ]; + when( + mockService.queryRelations(TestRelationDTO, 'relations', deepEqual([dto]), objectContaining(query)), + ).thenResolve(new Map([[dto, output]])); + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + const result = await resolver.queryRelations(dto, query, {}); + return expect(result).toEqual(output); + }); + }); - it('should call the service findRelation with the provided dto and correct relation name', async () => { - const { resolver, mockService } = await createResolverFromNest(TestResolver); - const dto: TestResolverDTO = { - id: 'id-1', - stringField: 'foo', - }; - const query: OffsetQueryArgsType = { - filter: { id: { eq: 'id-2' } }, - paging: { limit: 1 }, - }; - const output: TestRelationDTO[] = [ - { - id: 'id-2', - testResolverId: dto.id, - }, - ]; - when( - mockService.queryRelations(TestRelationDTO, 'others', deepEqual([dto]), objectContaining(query)), - ).thenResolve(new Map([[dto, output]])); - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - const result = await resolver.queryCustoms(dto, query, {}); - return expect(result).toEqual(output); - }); + describe('with no paging strategy', () => { + it('should call the service findRelation with the provided dto', async () => { + const { resolver, mockService } = await createResolverFromNest(TestResolver); + const dto: TestResolverDTO = { + id: 'id-1', + stringField: 'foo', + }; + const query: OffsetQueryArgsType = { + filter: { id: { eq: 'id-2' } }, + paging: { limit: 1 }, + }; + const output: TestRelationDTO[] = [ + { + id: 'id-2', + testResolverId: dto.id, + }, + ]; + when( + mockService.queryRelations(TestRelationDTO, 'relationsNoPagings', deepEqual([dto]), objectContaining(query)), + ).thenResolve(new Map([[dto, output]])); + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + const result = await resolver.queryRelationsNoPagings(dto, query, {}); + return expect(result).toEqual(output); }); }); }); diff --git a/packages/query-graphql/__tests__/resolvers/relations/read-relation.resolver.spec.ts b/packages/query-graphql/__tests__/resolvers/relations/read-relation.resolver.spec.ts index 0b9b8ed82..bbc2ebc11 100644 --- a/packages/query-graphql/__tests__/resolvers/relations/read-relation.resolver.spec.ts +++ b/packages/query-graphql/__tests__/resolvers/relations/read-relation.resolver.spec.ts @@ -1,13 +1,7 @@ import { Query, Resolver } from '@nestjs/graphql'; import { deepEqual, objectContaining, when } from 'ts-mockito'; -import { - CursorQueryArgsType, - NoPagingQueryArgsType, - OffsetQueryArgsType, - PagingStrategies, - ReadRelationsResolver, - RelationsOpts, -} from '../../../src'; +import { CursorQueryArgsType, NoPagingQueryArgsType, OffsetQueryArgsType, PagingStrategies } from '../../../src'; +import { ReadRelationsResolver, RelationsOpts } from '../../../src/resolvers/relations'; import { expectSDL } from '../../__fixtures__'; import { createResolverFromNest, TestResolverDTO, TestService } from '../__fixtures__'; import { @@ -278,9 +272,11 @@ describe('ReadRelationsResolver', () => { describe('many limit offset query', () => { @Resolver(() => TestResolverDTO) class TestResolver extends ReadRelationsResolver(TestResolverDTO, { - pagingStrategy: PagingStrategies.OFFSET, one: { relation: { DTO: TestRelationDTO }, custom: { DTO: TestRelationDTO, relationName: 'other' } }, - many: { relations: { DTO: TestRelationDTO }, customs: { DTO: TestRelationDTO, relationName: 'others' } }, + many: { + relations: { DTO: TestRelationDTO, pagingStrategy: PagingStrategies.OFFSET }, + customs: { DTO: TestRelationDTO, relationName: 'others', pagingStrategy: PagingStrategies.OFFSET }, + }, }) { constructor(service: TestService) { super(service); @@ -341,9 +337,11 @@ describe('ReadRelationsResolver', () => { describe('many limit no paging', () => { @Resolver(() => TestResolverDTO) class TestResolver extends ReadRelationsResolver(TestResolverDTO, { - pagingStrategy: PagingStrategies.NONE, one: { relation: { DTO: TestRelationDTO }, custom: { DTO: TestRelationDTO, relationName: 'other' } }, - many: { relations: { DTO: TestRelationDTO }, customs: { DTO: TestRelationDTO, relationName: 'others' } }, + many: { + relations: { DTO: TestRelationDTO, pagingStrategy: PagingStrategies.NONE }, + customs: { DTO: TestRelationDTO, pagingStrategy: PagingStrategies.NONE, relationName: 'others' }, + }, }) { constructor(service: TestService) { super(service); diff --git a/packages/query-graphql/__tests__/resolvers/relations/relations.resolver.spec.ts b/packages/query-graphql/__tests__/resolvers/relations/relations.resolver.spec.ts index ecfbf58b9..0e68bbb7e 100644 --- a/packages/query-graphql/__tests__/resolvers/relations/relations.resolver.spec.ts +++ b/packages/query-graphql/__tests__/resolvers/relations/relations.resolver.spec.ts @@ -1,8 +1,7 @@ // eslint-disable-next-line max-classes-per-file import { Field, ObjectType } from '@nestjs/graphql'; -import { PagingStrategies, ReferencesOpts, Relatable } from '../../../src'; +import { PagingStrategies, Relatable, FilterableField } from '../../../src'; import { Connection, Reference, Relation } from '../../../src/decorators'; -import { FilterableField } from '../../../src/decorators/filterable-field.decorator'; import * as readRelations from '../../../src/resolvers/relations/read-relations.resolver'; import * as referenceRelation from '../../../src/resolvers/relations/references-relation.resolver'; import * as removeRelations from '../../../src/resolvers/relations/remove-relations.resolver'; @@ -29,7 +28,7 @@ describe('Relatable', () => { @Connection('testConnection', () => TestRelation) class Test {} - Relatable(Test, { relations: {}, references: {} })(BaseServiceResolver); + Relatable(Test, {})(BaseServiceResolver); const relations = { one: { testRelation: { DTO: TestRelation } }, @@ -41,78 +40,21 @@ describe('Relatable', () => { expect(referenceMixinSpy).toHaveBeenCalledWith(Test, {}); }); - it('should call the mixins with the relations that are passed in', () => { - const relations = { - one: { testRelation: { DTO: TestRelation } }, - many: { testConnection: { DTO: TestRelation } }, - }; - - @ObjectType() - class Test {} - - Relatable(Test, { relations, references: {} })(BaseServiceResolver); - - expect(readMixinSpy).toHaveBeenCalledWith(Test, relations); - expect(updateMixinSpy).toHaveBeenCalledWith(Test, relations); - expect(removeMixinSpy).toHaveBeenCalledWith(Test, relations); - expect(referenceMixinSpy).toHaveBeenCalledWith(Test, {}); - }); - - it('should call the mixins with the relations and the correct pagingStrategy', () => { - const relations = { - one: { testRelation: { DTO: TestRelation } }, - many: { testConnection: { DTO: TestRelation } }, - }; - - @ObjectType() - class Test {} - - Relatable(Test, { pagingStrategy: PagingStrategies.OFFSET, relations, references: {} })(BaseServiceResolver); - - expect(readMixinSpy).toHaveBeenCalledWith(Test, { ...relations, pagingStrategy: PagingStrategies.OFFSET }); - expect(updateMixinSpy).toHaveBeenCalledWith(Test, relations); - expect(removeMixinSpy).toHaveBeenCalledWith(Test, relations); - expect(referenceMixinSpy).toHaveBeenCalledWith(Test, {}); - }); - - it('should call the mixins with the references derived from decorators', () => { - @ObjectType() - @Reference('testRelation', () => TestRelation, { id: 'relationId' }) - @Reference('testRelation2', () => TestRelation, { id: 'relationId' }) - class Test { - @Field() - relationId!: number; - } - - Relatable(Test, { relations: {}, references: {} })(BaseServiceResolver); - - const references = { - testRelation: { DTO: TestRelation, keys: { id: 'relationId' } }, - testRelation2: { DTO: TestRelation, keys: { id: 'relationId' } }, - }; - const relations = { many: {}, one: {} }; - expect(readMixinSpy).toHaveBeenCalledWith(Test, relations); - expect(updateMixinSpy).toHaveBeenCalledWith(Test, relations); - expect(removeMixinSpy).toHaveBeenCalledWith(Test, relations); - expect(referenceMixinSpy).toHaveBeenCalledWith(Test, references); - }); - it('should call the mixins with the references passed in', () => { @ObjectType() + @Reference('testReference', () => TestRelation, { id: 'relationId' }) class Test { @Field() relationId!: number; } - const references: ReferencesOpts = { - testRelation: { DTO: TestRelation, keys: { id: 'relationId' } }, - }; - const relations = { many: {}, one: {} }; - Relatable(Test, { relations: {}, references })(BaseServiceResolver); + Relatable(Test, {})(BaseServiceResolver); - expect(readMixinSpy).toHaveBeenCalledWith(Test, relations); - expect(updateMixinSpy).toHaveBeenCalledWith(Test, relations); - expect(removeMixinSpy).toHaveBeenCalledWith(Test, relations); - expect(referenceMixinSpy).toHaveBeenCalledWith(Test, references); + expect(readMixinSpy).toHaveBeenCalledWith(Test, {}); + expect(updateMixinSpy).toHaveBeenCalledWith(Test, {}); + expect(removeMixinSpy).toHaveBeenCalledWith(Test, {}); + expect(referenceMixinSpy).toHaveBeenCalledWith(Test, { + testReference: { DTO: TestRelation, keys: { id: 'relationId' } }, + }); }); }); diff --git a/packages/query-graphql/src/metadata/metadata-storage.ts b/packages/query-graphql/src/metadata/metadata-storage.ts index d3199c3cc..df43ec5e0 100644 --- a/packages/query-graphql/src/metadata/metadata-storage.ts +++ b/packages/query-graphql/src/metadata/metadata-storage.ts @@ -4,7 +4,7 @@ import { Class, Filter, SortField } from '@nestjs-query/core'; import { ObjectTypeMetadata } from '@nestjs/graphql/dist/schema-builder/metadata/object-type.metadata'; import { ReturnTypeFunc, FieldOptions } from '@nestjs/graphql'; import { EnumMetadata } from '@nestjs/graphql/dist/schema-builder/metadata'; -import { RelationsOpts, ResolverRelation, ResolverRelationReference } from '../resolvers/relations'; +import { ReferencesOpts, RelationsOpts, ResolverRelation, ResolverRelationReference } from '../resolvers/relations'; import { ReferencesKeys } from '../resolvers/relations/relations.interface'; import { EdgeType, StaticConnectionType } from '../types/connection'; @@ -168,8 +168,15 @@ export class GraphQLQueryMetadataStorage { references.push(reference as ReferenceDescriptor); } - getReferences(type: Class): ReferenceDescriptor[] | undefined { - return this.referenceStorage.get(type); + getReferences(type: Class): ReferencesOpts { + const metaReferences = this.referenceStorage.get(type); + if (!metaReferences) { + return {}; + } + return metaReferences.reduce((references, r) => { + const opts = { ...r.relationOpts, DTO: r.relationTypeFunc(), keys: r.keys }; + return { ...references, [r.name]: opts }; + }, {} as ReferencesOpts); } getGraphqlObjectMetadata(objType: Class): ObjectTypeMetadata | undefined { diff --git a/packages/query-graphql/src/providers.ts b/packages/query-graphql/src/providers.ts index ddd98c884..2a9ff3fcb 100644 --- a/packages/query-graphql/src/providers.ts +++ b/packages/query-graphql/src/providers.ts @@ -11,7 +11,7 @@ import { Provider, Inject } from '@nestjs/common'; import { Resolver } from '@nestjs/graphql'; import { PubSub } from 'graphql-subscriptions'; import { InjectPubSub } from './decorators'; -import { CRUDResolver, CRUDResolverOpts, FederationResolver, RelationsOpts } from './resolvers'; +import { CRUDResolver, CRUDResolverOpts, FederationResolver } from './resolvers'; import { PagingStrategies } from './types/query/paging'; type CRUDAutoResolverOpts = CRUDResolverOpts & { @@ -48,7 +48,7 @@ export type ServiceCRUDAutoResolverOpts; }; -export type FederatedAutoResolverOpts = RelationsOpts & { +export type FederatedAutoResolverOpts = { type: 'federated'; DTOClass: Class; Service: Class; @@ -85,7 +85,7 @@ function createFederatedResolver(resolverOpts: FederatedAutoResolv const { DTOClass } = resolverOpts; @Resolver(() => DTOClass) - class AutoResolver extends FederationResolver(DTOClass, resolverOpts) { + class AutoResolver extends FederationResolver(DTOClass) { constructor( @Inject(resolverOpts.Service) readonly service: QueryService, @InjectPubSub() readonly pubSub: PubSub, diff --git a/packages/query-graphql/src/resolvers/crud.resolver.ts b/packages/query-graphql/src/resolvers/crud.resolver.ts index 16a71b2cc..d2e7025ae 100644 --- a/packages/query-graphql/src/resolvers/crud.resolver.ts +++ b/packages/query-graphql/src/resolvers/crud.resolver.ts @@ -1,6 +1,6 @@ import { Class, DeepPartial } from '@nestjs-query/core'; import { PagingStrategies } from '../types'; -import { ReferencesOpts, Relatable, RelationsOpts } from './relations'; +import { Relatable } from './relations'; import { Readable, ReadResolverFromOpts, ReadResolverOpts } from './read.resolver'; import { Creatable, CreateResolver, CreateResolverOpts } from './create.resolver'; import { Refereceable, ReferenceResolverOpts } from './reference.resolver'; @@ -30,9 +30,6 @@ export interface CRUDResolverOpts< read?: R; update?: UpdateResolverOpts; delete?: DeleteResolverOpts; - relations?: RelationsOpts; - references?: ReferencesOpts; - reference?: ReferenceResolverOpts; referenceBy?: ReferenceResolverOpts; } @@ -79,8 +76,6 @@ export const CRUDResolver = < enableSubscriptions, pagingStrategy, enableTotalCount, - relations = {}, - references = {}, create = {}, read = {}, update = {}, @@ -89,7 +84,7 @@ export const CRUDResolver = < } = opts; const referencable = Refereceable(DTOClass, referenceBy); - const relatable = Relatable(DTOClass, { relations, references, pagingStrategy, enableTotalCount }); + const relatable = Relatable(DTOClass, { enableTotalCount }); const creatable = Creatable(DTOClass, { CreateDTOClass, enableSubscriptions, ...create }); const readable = Readable(DTOClass, { enableTotalCount, pagingStrategy, ...read } as MergePagingStrategyOpts< DTO, diff --git a/packages/query-graphql/src/resolvers/federation/federation.resolver.ts b/packages/query-graphql/src/resolvers/federation/federation.resolver.ts index 4199aae56..2eb9403c1 100644 --- a/packages/query-graphql/src/resolvers/federation/federation.resolver.ts +++ b/packages/query-graphql/src/resolvers/federation/federation.resolver.ts @@ -1,13 +1,9 @@ import { Class } from '@nestjs-query/core'; -import { RelationsOpts, ReadRelationsResolver } from '../relations'; -import { getRelationsFromMetadata, mergeRelations } from '../relations/helpers'; +import { getMetadataStorage } from '../../metadata'; +import { ReadRelationsResolver } from '../relations'; import { ServiceResolver } from '../resolver.interface'; -export const FederationResolver = ( - DTOClass: Class, - relations: RelationsOpts = {}, -): Class> => { - const metaRelations = getRelationsFromMetadata(DTOClass); - const mergedRelations = mergeRelations(relations, metaRelations); - return ReadRelationsResolver(DTOClass, mergedRelations); +export const FederationResolver = (DTOClass: Class): Class> => { + const relations = getMetadataStorage().getRelations(DTOClass); + return ReadRelationsResolver(DTOClass, relations); }; diff --git a/packages/query-graphql/src/resolvers/index.ts b/packages/query-graphql/src/resolvers/index.ts index 909b7b248..46c0e122d 100644 --- a/packages/query-graphql/src/resolvers/index.ts +++ b/packages/query-graphql/src/resolvers/index.ts @@ -4,16 +4,6 @@ export { ReadResolver, ReadResolverOpts } from './read.resolver'; export { UpdateResolver, UpdateResolverOpts } from './update.resolver'; export { DeleteResolver, DeleteResolverOpts } from './delete.resolver'; export { ReferenceResolver, ReferenceResolverOpts } from './reference.resolver'; -export { - Relatable, - RemoveRelationsResolver, - ReadRelationsResolver, - UpdateRelationsResolver, - ResolverRelation, - RelationsOpts, - RelationTypeMap, - ReferencesOpts, - ResolverRelationReference, -} from './relations'; +export { Relatable, ResolverRelation, ResolverRelationReference } from './relations'; export { ResolverOpts } from './resolver.interface'; export { FederationResolver } from './federation'; diff --git a/packages/query-graphql/src/resolvers/relations/helpers.ts b/packages/query-graphql/src/resolvers/relations/helpers.ts index cb95434b8..c5abbdead 100644 --- a/packages/query-graphql/src/resolvers/relations/helpers.ts +++ b/packages/query-graphql/src/resolvers/relations/helpers.ts @@ -1,14 +1,6 @@ -import { Class } from '@nestjs-query/core'; import omit from 'lodash.omit'; import { ResolverMethodOpts } from '../../decorators'; -import { getMetadataStorage } from '../../metadata'; -import { - ReferencesOpts, - RelationsOpts, - RelationTypeMap, - ResolverRelation, - ResolverRelationReference, -} from './relations.interface'; +import { RelationTypeMap, ResolverRelation, ResolverRelationReference } from './relations.interface'; export const flattenRelations = | ResolverRelationReference>( relationOptions: RelationTypeMap, @@ -31,25 +23,3 @@ export const removeRelationOpts = ( 'disableRemove', ); }; - -export const getRelationsFromMetadata = (DTOClass: Class): RelationsOpts => { - return getMetadataStorage().getRelations(DTOClass); -}; - -export const mergeRelations = (into: RelationsOpts, from: RelationsOpts): RelationsOpts => { - const oneRelations = { ...into.one, ...(from.one ?? {}) }; - const manyRelations = { ...into.many, ...(from.many ?? {}) }; - return { one: oneRelations, many: manyRelations }; -}; - -export const getReferencesFromMetadata = (DTOClass: Class): ReferencesOpts => { - const metaReferences = getMetadataStorage().getReferences(DTOClass) ?? []; - return metaReferences.reduce((references, r) => { - const opts = { ...r.relationOpts, DTO: r.relationTypeFunc(), keys: r.keys }; - return { ...references, [r.name]: opts }; - }, {} as ReferencesOpts); -}; - -export const mergeReferences = (into: ReferencesOpts, from: ReferencesOpts): ReferencesOpts => { - return { ...into, ...from }; -}; diff --git a/packages/query-graphql/src/resolvers/relations/read-relations.resolver.ts b/packages/query-graphql/src/resolvers/relations/read-relations.resolver.ts index 9a2650eff..a5cf1b7cf 100644 --- a/packages/query-graphql/src/resolvers/relations/read-relations.resolver.ts +++ b/packages/query-graphql/src/resolvers/relations/read-relations.resolver.ts @@ -4,14 +4,13 @@ import { Args, ArgsType, Context, Parent, Resolver } from '@nestjs/graphql'; import { getDTONames } from '../../common'; import { ResolverField } from '../../decorators'; import { CountRelationsLoader, DataLoaderFactory, FindRelationsLoader, QueryRelationsLoader } from '../../loader'; -import { ConnectionType, PagingStrategies, QueryArgsType } from '../../types'; +import { ConnectionType, QueryArgsType } from '../../types'; import { transformAndValidate } from '../helpers'; import { BaseServiceResolver, ServiceResolver } from '../resolver.interface'; import { flattenRelations, removeRelationOpts } from './helpers'; import { RelationsOpts, ResolverRelation } from './relations.interface'; export interface ReadRelationsResolverOpts extends RelationsOpts { - pagingStrategy?: PagingStrategies; enableTotalCount?: boolean; } @@ -96,11 +95,11 @@ export const ReadRelationsMixin = (DTOClass: Class, relations: ReadRel >( Base: B, ): B => { - const { many, one, pagingStrategy, enableTotalCount } = relations; + const { many, one, enableTotalCount } = relations; const manyRelations = flattenRelations(many ?? {}); const oneRelations = flattenRelations(one ?? {}); const WithMany = manyRelations.reduce( - (RB, a) => ReadManyRelationMixin(DTOClass, { enableTotalCount, pagingStrategy, ...a })(RB), + (RB, a) => ReadManyRelationMixin(DTOClass, { enableTotalCount, ...a })(RB), Base, ); return oneRelations.reduce((RB, a) => ReadOneRelationMixin(DTOClass, a)(RB), WithMany); diff --git a/packages/query-graphql/src/resolvers/relations/relations.resolver.ts b/packages/query-graphql/src/resolvers/relations/relations.resolver.ts index d8a582c87..9e95df373 100644 --- a/packages/query-graphql/src/resolvers/relations/relations.resolver.ts +++ b/packages/query-graphql/src/resolvers/relations/relations.resolver.ts @@ -1,18 +1,13 @@ import { Class } from '@nestjs-query/core'; -import { PagingStrategies } from '../../types/query/paging'; +import { getMetadataStorage } from '../../metadata'; import { ServiceResolver } from '../resolver.interface'; -import { getReferencesFromMetadata, getRelationsFromMetadata, mergeReferences, mergeRelations } from './helpers'; import { ReadRelationsMixin } from './read-relations.resolver'; import { ReferencesRelationMixin } from './references-relation.resolver'; -import { ReferencesOpts, RelationsOpts } from './relations.interface'; import { RemoveRelationsMixin } from './remove-relations.resolver'; import { UpdateRelationsMixin } from './update-relations.resolver'; export interface RelatableOpts { - pagingStrategy?: PagingStrategies; enableTotalCount?: boolean; - relations: RelationsOpts; - references: ReferencesOpts; } export const Relatable = (DTOClass: Class, opts: RelatableOpts) => < @@ -20,18 +15,14 @@ export const Relatable = (DTOClass: Class, opts: RelatableOpts) = >( Base: B, ): B => { - const { pagingStrategy, enableTotalCount, references, relations } = opts; - const metaRelations = getRelationsFromMetadata(DTOClass); - const mergedRelations = mergeRelations(relations, metaRelations); + const metadataStorage = getMetadataStorage(); + const { enableTotalCount } = opts; + const relations = metadataStorage.getRelations(DTOClass); + const references = metadataStorage.getReferences(DTOClass); - const metaReferences = getReferencesFromMetadata(DTOClass); - const mergedReferences = mergeReferences(references, metaReferences); + const referencesMixin = ReferencesRelationMixin(DTOClass, references); + const readRelationsMixin = ReadRelationsMixin(DTOClass, { ...relations, enableTotalCount }); + const updateRelationsMixin = UpdateRelationsMixin(DTOClass, relations); - const referencesMixin = ReferencesRelationMixin(DTOClass, mergedReferences); - const readRelationsMixin = ReadRelationsMixin(DTOClass, { ...mergedRelations, enableTotalCount, pagingStrategy }); - const updateRelationsMixin = UpdateRelationsMixin(DTOClass, mergedRelations); - - return referencesMixin( - readRelationsMixin(updateRelationsMixin(RemoveRelationsMixin(DTOClass, mergedRelations)(Base))), - ); + return referencesMixin(readRelationsMixin(updateRelationsMixin(RemoveRelationsMixin(DTOClass, relations)(Base)))); }; diff --git a/packages/query-sequelize/__tests__/query/filter-query.builder.spec.ts b/packages/query-sequelize/__tests__/query/filter-query.builder.spec.ts index 26a42c1b2..38688a0a4 100644 --- a/packages/query-sequelize/__tests__/query/filter-query.builder.spec.ts +++ b/packages/query-sequelize/__tests__/query/filter-query.builder.spec.ts @@ -13,7 +13,7 @@ describe('FilterQueryBuilder', (): void => { whereBuilder: WhereBuilder, expectedFindOptions: FindOptions, ): void => { - expect(getEntityQueryBuilder(whereBuilder).findOptions(query)).toEqual(expectedFindOptions); + expect(getEntityQueryBuilder(whereBuilder).findOptions(query)).toEqual({ ...expectedFindOptions, subQuery: false }); }; const assertUpdateOptions = (