Skip to content

Commit

Permalink
feat(core): Add new setRelations to set oneToMany/manyToMany relations
Browse files Browse the repository at this point in the history
  • Loading branch information
doug-martin committed Apr 13, 2021
1 parent c19ed78 commit 4c73591
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 0 deletions.
27 changes: 27 additions & 0 deletions packages/core/__tests__/services/assembler-query.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,33 @@ describe('AssemblerQueryService', () => {
});
});

describe('setRelations', () => {
it('should transform the results for a single entity', () => {
const mockQueryService = mock<QueryService<TestEntity>>();
const assemblerService = new AssemblerQueryService(new TestAssembler(), instance(mockQueryService));
when(mockQueryService.setRelations('test', 1, deepEqual([2]), undefined)).thenResolve({
bar: 'baz',
});

return expect(assemblerService.setRelations('test', 1, [2])).resolves.toEqual({ foo: 'baz' });
});
it('should transform the options and results for a single entity', () => {
const mockQueryService = mock<QueryService<TestEntity>>();
const assemblerService = new AssemblerQueryService(new TestAssembler(), instance(mockQueryService));
when(
mockQueryService.setRelations('test', 1, deepEqual([2]), objectContaining({ filter: { bar: { eq: 'bar' } } })),
).thenResolve({
bar: 'baz',
});

return expect(
assemblerService.setRelations('test', 1, [2], {
filter: { foo: { eq: 'bar' } },
}),
).resolves.toEqual({ foo: 'baz' });
});
});

describe('removeRelations', () => {
it('should transform the results for a single entity', () => {
const mockQueryService = mock<QueryService<TestEntity>>();
Expand Down
19 changes: 19 additions & 0 deletions packages/core/__tests__/services/noop-query.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,31 @@ describe('NoOpQueryService', () => {
DeepPartial<TestType>,
DeepPartial<TestType>
>();

it('should throw a NotImplementedException when calling addRelations', () =>
expect(instance.addRelations('test', 1, [1, 2, 3])).rejects.toThrow('addRelations is not implemented'));

it('should throw a NotImplementedException when calling createMany', () =>
expect(instance.createMany([{ foo: 'bar' }])).rejects.toThrow('createMany is not implemented'));

it('should throw a NotImplementedException when calling createOne', () =>
expect(instance.createOne({ foo: 'bar' })).rejects.toThrow('createOne is not implemented'));

it('should throw a NotImplementedException when calling deleteMany', () =>
expect(instance.deleteMany({ foo: { eq: 'bar' } })).rejects.toThrow('deleteMany is not implemented'));

it('should throw a NotImplementedException when calling deleteOne', () =>
expect(instance.deleteOne(1)).rejects.toThrow('deleteOne is not implemented'));

it('should throw a NotImplementedException when calling findById', () =>
expect(instance.findById(1)).rejects.toThrow('findById is not implemented'));

it('should throw a NotImplementedException when calling findRelation', () =>
expect(instance.findRelation(TestType, 'test', new TestType())).rejects.toThrow('findRelation is not implemented'));

it('should throw a NotImplementedException when calling getById', () =>
expect(instance.getById(1)).rejects.toThrow('getById is not implemented'));

it('should throw a NotImplementedException when calling query', () =>
expect(instance.query({})).rejects.toThrow('query is not implemented'));

Expand All @@ -36,22 +45,32 @@ describe('NoOpQueryService', () => {

it('should throw a NotImplementedException when calling count', () =>
expect(instance.count({})).rejects.toThrow('count is not implemented'));

it('should throw a NotImplementedException when calling queryRelations', () =>
expect(instance.queryRelations(TestType, 'test', new TestType(), {})).rejects.toThrow(
'queryRelations is not implemented',
));

it('should throw a NotImplementedException when calling countRelations', () =>
expect(instance.countRelations(TestType, 'test', new TestType(), {})).rejects.toThrow(
'countRelations is not implemented',
));

it('should throw a NotImplementedException when calling removeRelation', () =>
expect(instance.removeRelation('test', 1, 2)).rejects.toThrow('removeRelation is not implemented'));

it('should throw a NotImplementedException when calling removeRelations', () =>
expect(instance.removeRelations('test', 1, [1, 2, 3])).rejects.toThrow('removeRelations is not implemented'));

it('should throw a NotImplementedException when calling setRelation', () =>
expect(instance.setRelation('test', 1, 1)).rejects.toThrow('setRelation is not implemented'));

it('should throw a NotImplementedException when calling setRelations', () =>
expect(instance.setRelations('test', 1, [1])).rejects.toThrow('setRelations is not implemented'));

it('should throw a NotImplementedException when calling updateMany', () =>
expect(instance.updateMany({ foo: 'bar' }, {})).rejects.toThrow('updateMany is not implemented'));

it('should throw a NotImplementedException when calling updateOne', () =>
expect(instance.updateOne(1, { foo: 'bar' })).rejects.toThrow('updateOne is not implemented'));

Expand Down
8 changes: 8 additions & 0 deletions packages/core/__tests__/services/proxy-query.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ describe('ProxyQueryService', () => {
when(mockQueryService.setRelation(relationName, id, relationId, undefined)).thenResolve(result);
return expect(queryService.setRelation(relationName, id, relationId)).resolves.toBe(result);
});
it('should proxy to the underlying service when calling setRelations', () => {
const relationName = 'test';
const id = 1;
const relationIds = [2];
const result = { foo: 'bar' };
when(mockQueryService.setRelations(relationName, id, relationIds, undefined)).thenResolve(result);
return expect(queryService.setRelations(relationName, id, relationIds)).resolves.toBe(result);
});
it('should proxy to the underlying service when calling updateMany', () => {
const update = { foo: 'bar' };
const filter = {};
Expand Down
10 changes: 10 additions & 0 deletions packages/core/__tests__/services/relation-query.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,14 @@ describe('RelationQueryService', () => {
return expect(queryService.setRelation(relationName, id, relationId)).resolves.toBe(result);
});
});
describe('#setRelations', () => {
it('should proxy to the underlying service when calling setRelations', () => {
const relationName = 'test';
const id = 1;
const relationIds = [2];
const result = { foo: 'bar' };
when(mockQueryService.setRelations(relationName, id, relationIds, undefined)).thenResolve(result);
return expect(queryService.setRelations(relationName, id, relationIds)).resolves.toBe(result);
});
});
});
11 changes: 11 additions & 0 deletions packages/core/src/services/assembler-query.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,17 @@ export class AssemblerQueryService<DTO, Entity, C = DeepPartial<DTO>, CE = DeepP
);
}

setRelations<Relation>(
relationName: string,
id: string | number,
relationIds: (string | number)[],
opts?: ModifyRelationOptions<DTO, Relation>,
): Promise<DTO> {
return this.assembler.convertAsyncToDTO(
this.queryService.setRelations(relationName, id, relationIds, this.convertModifyRelationsOptions(opts)),
);
}

setRelation<Relation>(
relationName: string,
id: string | number,
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/services/noop-query.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,15 @@ export class NoOpQueryService<DTO, C = DeepPartial<DTO>, U = DeepPartial<DTO>> i
return Promise.reject(new NotImplementedException('removeRelations is not implemented'));
}

setRelations<Relation>(
relationName: string,
id: string | number,
relationId: (string | number)[],
opts?: ModifyRelationOptions<DTO, Relation>,
): Promise<DTO> {
return Promise.reject(new NotImplementedException('setRelations is not implemented'));
}

setRelation<Relation>(
relationName: string,
id: string | number,
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/services/proxy-query.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ export class ProxyQueryService<DTO, C = DeepPartial<DTO>, U = DeepPartial<DTO>>
return this.proxied.removeRelations(relationName, id, relationIds, opts);
}

setRelations<Relation>(
relationName: string,
id: string | number,
relationIds: (string | number)[],
opts?: ModifyRelationOptions<DTO, Relation>,
): Promise<DTO> {
return this.proxied.setRelations(relationName, id, relationIds, opts);
}

setRelation<Relation>(
relationName: string,
id: string | number,
Expand Down
16 changes: 16 additions & 0 deletions packages/core/src/services/query.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,22 @@ export interface QueryService<DTO, C = DeepPartial<DTO>, U = DeepPartial<DTO>> {
opts?: ModifyRelationOptions<DTO, Relation>,
): Promise<DTO>;

/**
* Set the relations on the dto.
*
* @param relationName - The name of the relation to query for.
* @param id - The id of the dto to set the relation on.
* @param relationIds - The ids of the relation to set on the dto. If the array is empty the relations will be
* removed.
* @param opts - Additional options.
*/
setRelations<Relation>(
relationName: string,
id: string | number,
relationIds: (string | number)[],
opts?: ModifyRelationOptions<DTO, Relation>,
): Promise<DTO>;

/**
* Set the relation on the dto.
*
Expand Down

0 comments on commit 4c73591

Please sign in to comment.