UNPKG

@graphity/mapper

Version:

Decorator-based transformer of plain object to class constructors for Javascript(& Typescript).

90 lines (81 loc) 3.07 kB
import { MapperOptions, ValueTransformer } from '../interfaces/mapper' import { MaybeArray } from '../interfaces/utils' function applyTransformTo(value: any, transformers: ValueTransformer<any>[]) { const dupTransformers = transformers.slice() let result = value while (dupTransformers.length) { const transformer = dupTransformers.shift() if (transformer && transformer.to) { result = transformer.to(result) } } return result } function applyTransformFrom(value: any, transformers: ValueTransformer<any>[]) { const dupTransformers = transformers.slice().reverse() let result = value while (dupTransformers.length) { const transformer = dupTransformers.shift() if (transformer && transformer.from) { result = transformer.from(result) } } return result } export class Mapper<TEntity, TSource = any> { public constructor(public readonly options: MapperOptions<TEntity>) { } public toEntity(rows: TSource[]): TEntity[] public toEntity(rows: TSource): TEntity public toEntity(rows: MaybeArray<TSource>): MaybeArray<TEntity> { if (!Array.isArray(rows)) { return this.toEntity([rows])[0] } return rows.map((row: any) => { const entity: Partial<TEntity> = {} for (const column of this.options.columns) { const defaultValue = typeof column.default === 'function' ? column.default() : column.default const value = typeof row[column.sourceKey] !== 'undefined' ? applyTransformTo(row[column.sourceKey], column.transformers) : defaultValue const isNull = value === null || typeof value === 'undefined' if (!column.nullable && isNull) { throw new Error(`column(${column.property}) is not nullable.`) } if (column.nullable) { entity[column.property] = !isNull ? value : null } else { entity[column.property] = value } } Object.setPrototypeOf(entity, this.options.ctor.prototype) return entity as TEntity }) } public assign(entity: Partial<TEntity>[]): TEntity[] public assign(entity: Partial<TEntity>): TEntity public assign(entity: MaybeArray<Partial<TEntity>>): MaybeArray<TEntity> { if (!Array.isArray(entity)) { return Object.setPrototypeOf(entity, this.options.ctor.prototype) } return entity.map((row) => this.assign(row)) } public toPlain(entities: TEntity[]): TSource[] public toPlain(entities: TEntity): TSource public toPlain(entities: Partial<TEntity>[]): TSource[] public toPlain(entities: Partial<TEntity>): TSource public toPlain(entities: any): MaybeArray<TSource> { if (!Array.isArray(entities)) { return this.toPlain([entities] as TEntity[])[0] } return entities.map((entity) => { const row: any = {} for (const column of this.options.columns) { if (typeof entity[column.property] !== 'undefined') { row[column.sourceKey] = applyTransformFrom(entity[column.property], column.transformers) } } return row }) } }