Skip to content

Commit

Permalink
feat(sequelize): Initial Sequelize support
Browse files Browse the repository at this point in the history
  • Loading branch information
doug-martin committed Apr 29, 2020
1 parent 0dae582 commit bfcf436
Show file tree
Hide file tree
Showing 30 changed files with 1,151 additions and 36 deletions.
172 changes: 172 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions packages/core/__tests__/decorators/assembler.decorator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,23 @@ describe('@Assembler', () => {

it('should register an assembler as injectable and with metadata', () => {
@Assembler(TestFrom, TestTo)
class TestAssembler extends ClassTransformerAssembler<TestFrom, TestTo> {}
class TestAssembler extends ClassTransformerAssembler<TestFrom, TestTo> {
toPlain(dtoOrEntity: TestFrom | TestTo): object {
return dtoOrEntity;
}
}
expect(injectableSpy).toBeCalledTimes(1);
expect(AssemblerFactory.getAssembler(TestFrom, TestTo)).toBeInstanceOf(TestAssembler);
expect(AssemblerFactory.getAssembler(TestTo, TestFrom)).toBeInstanceOf(DefaultAssembler);
});

it('should throw an error when registering an assembler for the same From To combo', () => {
@Assembler(TestFrom, TestTo)
class TestAssembler extends ClassTransformerAssembler<TestFrom, TestTo> {}
class TestAssembler extends ClassTransformerAssembler<TestFrom, TestTo> {
toPlain(dtoOrEntity: TestFrom | TestTo): object {
return dtoOrEntity;
}
}
expect(() => Assembler(TestFrom, TestTo)(TestAssembler)).toThrowError(
'Assembler already registered for TestFrom TestTo',
);
Expand Down
23 changes: 23 additions & 0 deletions packages/core/src/assemblers/assembler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,26 @@ export function Assembler<DTO, Entity>(DTOClass: Class<DTO>, EntityClass: Class<
return cls;
};
}

export type AssemblerSerializer<T> = (instance: T) => object;
export type AssemblerDeserializer<T> = (obj: object) => T;

export function AssemblerSerializer<T>(serializer: AssemblerSerializer<T>) {
return <Cls extends Class<T>>(cls: Cls): Cls | void => {
if (getCoreMetadataStorage().hasAssemblerSerializer(cls)) {
throw new Error(`Assembler Serializer already registered for ${cls.name}`);
}
getCoreMetadataStorage().addAssemblerSerializer(cls, serializer);
return cls;
};
}

export function AssemblerDeserializer<T>(deserializer: AssemblerDeserializer<T>) {
return <Cls extends Class<T>>(cls: Cls): Cls | void => {
if (getCoreMetadataStorage().hasAssemblerDeserializer(cls)) {
throw new Error(`Assembler Deserializer already registered for ${cls.name}`);
}
getCoreMetadataStorage().addAssemblerDeserializer(cls, deserializer);
return cls;
};
}
29 changes: 27 additions & 2 deletions packages/core/src/assemblers/class-transformer.assembler.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,45 @@
import { plainToClass } from 'class-transformer';
import { Query } from '../interfaces';
import { getCoreMetadataStorage } from '../metadata';
import { AbstractAssembler } from './abstract.assembler';
import { Class } from '../common';

/**
* Base assembler that uses class-transformer to transform to and from the DTO/Entity.
*/
export abstract class ClassTransformerAssembler<DTO, Entity> extends AbstractAssembler<DTO, Entity> {
convertToDTO(entity: Entity): DTO {
return plainToClass(this.DTOClass, entity);
return this.convert(this.DTOClass, this.toPlain(entity));
}

convertToEntity(dto: DTO): Entity {
return plainToClass(this.EntityClass, dto);
return this.convert(this.EntityClass, this.toPlain(dto));
}

convertQuery(query: Query<DTO>): Query<Entity> {
return query as Query<Entity>;
}

convert<T>(cls: Class<T>, obj: object): T {
const deserializer = getCoreMetadataStorage().getAssemblerDeserializer(cls);
if (deserializer) {
return deserializer(obj);
}
return plainToClass(cls, obj);
}

toPlain(entityOrDto: Entity | DTO): object {
if (entityOrDto instanceof this.EntityClass) {
const serializer = getCoreMetadataStorage().getAssemblerSerializer(this.EntityClass);
if (serializer) {
return serializer(entityOrDto);
}
} else if (entityOrDto instanceof this.DTOClass) {
const serializer = getCoreMetadataStorage().getAssemblerSerializer(this.DTOClass);
if (serializer) {
return serializer(entityOrDto);
}
}
return (entityOrDto as unknown) as object;
}
}
2 changes: 1 addition & 1 deletion packages/core/src/assemblers/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { ClassTransformerAssembler } from './class-transformer.assembler';
export { DefaultAssembler } from './default.assembler';
export { AbstractAssembler } from './abstract.assembler';
export { Assembler } from './assembler';
export { Assembler, AssemblerSerializer, AssemblerDeserializer } from './assembler';
export { AssemblerFactory } from './assembler.factory';
2 changes: 2 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ export {
DefaultAssembler,
AbstractAssembler,
Assembler,
AssemblerSerializer,
AssemblerDeserializer,
AssemblerFactory,
} from './assemblers';
Loading

0 comments on commit bfcf436

Please sign in to comment.