From af20518308c068b4afd256c81da1a543cb3f1411 Mon Sep 17 00:00:00 2001 From: Hakan Aktas Date: Thu, 1 Feb 2024 19:57:16 +0200 Subject: [PATCH] apply prettier to all files --- src/EntityBuilder.ts | 149 +++++++++++--------- src/index.ts | 13 +- src/support/JsonExclude.ts | 12 +- src/support/StringHelper.ts | 64 ++++----- src/support/Type.ts | 32 +++-- src/support/isEntityType.ts | 10 +- src/support/metadata/JsonExcludeMetadata.ts | 5 +- src/support/metadata/MetadataStorage.ts | 112 ++++++++------- src/support/metadata/TypeMetadata.ts | 78 +++++----- src/support/storage.ts | 2 +- src/support/toJson.ts | 95 +++++++------ 11 files changed, 321 insertions(+), 251 deletions(-) diff --git a/src/EntityBuilder.ts b/src/EntityBuilder.ts index e76d32b..dc87420 100644 --- a/src/EntityBuilder.ts +++ b/src/EntityBuilder.ts @@ -1,80 +1,103 @@ -import { Entity, PartialPropsJson } from './Entity'; -import { Buildable, Constructor } from './support/Type'; -import { TypeMetadata } from './support/metadata/TypeMetadata'; -import { defaultMetadataStorage } from './support/storage'; -import { isEntityType } from './support/isEntityType'; -import { StringHelper } from './support/StringHelper'; +import { Entity, PartialPropsJson } from "./Entity"; +import { Buildable, Constructor } from "./support/Type"; +import { TypeMetadata } from "./support/metadata/TypeMetadata"; +import { defaultMetadataStorage } from "./support/storage"; +import { isEntityType } from "./support/isEntityType"; +import { StringHelper } from "./support/StringHelper"; export class EntityBuilder { - public static buildOne( - buildClass: Constructor, - sourceData: PartialPropsJson, - ): T { - const entity = new (buildClass)(); - return entity.fromJson(sourceData); - } + public static buildOne( + buildClass: Constructor, + sourceData: PartialPropsJson, + ): T { + const entity = new buildClass(); + return entity.fromJson(sourceData); + } - public static buildMany( - buildClass: Constructor, - sourceData: Array>, - ): Array { - return sourceData.map( - entityData => this.buildOne(buildClass, entityData), - ); - } + public static buildMany( + buildClass: Constructor, + sourceData: Array>, + ): Array { + return sourceData.map((entityData) => + this.buildOne(buildClass, entityData), + ); + } - public static fill(entity: T, data: PartialPropsJson): T { - for (let key in data) { - EntityBuilder.fillProperty(entity, key, data[key]); - } - - return entity; + public static fill( + entity: T, + data: PartialPropsJson, + ): T { + for (let key in data) { + EntityBuilder.fillProperty(entity, key, data[key]); } - private static fillProperty(entity: T, key: string, value: any): void { - // Don't even bother for undefined values. - if (typeof value === 'undefined') { - return; - } + return entity; + } - const metadata: TypeMetadata = defaultMetadataStorage.findTypeMetadata(entity.constructor, key); + private static fillProperty( + entity: T, + key: string, + value: any, + ): void { + // Don't even bother for undefined values. + if (typeof value === "undefined") { + return; + } - if (metadata) { - EntityBuilder.fillTypeDecoratedProperty(entity, metadata, value); - return; - } + const metadata: TypeMetadata = defaultMetadataStorage.findTypeMetadata( + entity.constructor, + key, + ); - // No type definition means scalar value, and we can just set that as is. - entity.setProp(StringHelper.toCamel(key), value); + if (metadata) { + EntityBuilder.fillTypeDecoratedProperty(entity, metadata, value); + return; } - private static fillTypeDecoratedProperty(entity: T, metadata: TypeMetadata, value: InstanceType) { - // We shouldn't copy objects to our entity, as the entity should be responsible for constructing these itself. - if (typeof value === 'object' && value !== null && !Array.isArray(value)) { - if (isEntityType(metadata.type)) { - entity.setProp(metadata.propertyName, EntityBuilder.buildOne(metadata.type, value)); - } else { - entity.setProp(metadata.propertyName, new metadata.type(value)) - } + // No type definition means scalar value, and we can just set that as is. + entity.setProp(StringHelper.toCamel(key), value); + } - return; - } + private static fillTypeDecoratedProperty( + entity: T, + metadata: TypeMetadata, + value: InstanceType, + ) { + // We shouldn't copy objects to our entity, as the entity should be responsible for constructing these itself. + if (typeof value === "object" && value !== null && !Array.isArray(value)) { + if (isEntityType(metadata.type)) { + entity.setProp( + metadata.propertyName, + EntityBuilder.buildOne(metadata.type, value), + ); + } else { + entity.setProp(metadata.propertyName, new metadata.type(value)); + } - // if we have an array, we check if it contains objects, in which case the entity itself should be assumed - // responsible to construct the array of entities. - if (Array.isArray(value) && value.length > 0) { - if (isEntityType(metadata.type)) { - entity.setProp(metadata.propertyName, EntityBuilder.buildMany(metadata.type, value)); - } else { - entity.setProp(metadata.propertyName, value.map(item => new metadata.type(item))); - } + return; + } - return; - } + // if we have an array, we check if it contains objects, in which case the entity itself should be assumed + // responsible to construct the array of entities. + if (Array.isArray(value) && value.length > 0) { + if (isEntityType(metadata.type)) { + entity.setProp( + metadata.propertyName, + EntityBuilder.buildMany(metadata.type, value), + ); + } else { + entity.setProp( + metadata.propertyName, + value.map((item) => new metadata.type(item)), + ); + } - // Since all other scenarios have been exhausted, we're dealing with a primitive of some form. - // This can be an empty array of objects too, but since it's empty, there's no need for us - // to build an entity. As such, we can just assign it. The same goes for all primitives. - entity.setProp(metadata.propertyName, value); + return; } + + // Since all other scenarios have been exhausted, we're dealing with a primitive of some form. + // This can be an empty array of objects too, but since it's empty, there's no need for us + // to build an entity. As such, we can just assign it. The same goes for all primitives. + entity.setProp(metadata.propertyName, value); + } } diff --git a/src/index.ts b/src/index.ts index aeaa85a..42aea51 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,9 @@ -export { Entity } from './Entity'; -export type { Props, PropsJson, PartialProps, PartialPropsJson } from './Entity'; -export { EntityBuilder } from './EntityBuilder'; -export { Type } from './support/Type'; +export { Entity } from "./Entity"; +export type { + Props, + PropsJson, + PartialProps, + PartialPropsJson, +} from "./Entity"; +export { EntityBuilder } from "./EntityBuilder"; +export { Type } from "./support/Type"; diff --git a/src/support/JsonExclude.ts b/src/support/JsonExclude.ts index 76b5c7a..c7dbbf2 100644 --- a/src/support/JsonExclude.ts +++ b/src/support/JsonExclude.ts @@ -1,9 +1,9 @@ -import { defaultMetadataStorage } from './storage'; -import {JsonExcludeMetadata} from './metadata/JsonExcludeMetadata'; +import { defaultMetadataStorage } from "./storage"; +import { JsonExcludeMetadata } from "./metadata/JsonExcludeMetadata"; export function JsonExclude() { - return function (target: any, key: string) { - const metadata = new JsonExcludeMetadata(target.constructor, key); - defaultMetadataStorage.addExcludeProperty(metadata); - }; + return function (target: any, key: string) { + const metadata = new JsonExcludeMetadata(target.constructor, key); + defaultMetadataStorage.addExcludeProperty(metadata); + }; } diff --git a/src/support/StringHelper.ts b/src/support/StringHelper.ts index 642da55..65c0b69 100644 --- a/src/support/StringHelper.ts +++ b/src/support/StringHelper.ts @@ -1,37 +1,37 @@ export class StringHelper { - /** - * Convert a string to camelCase. - * @param source - * @returns {string} - */ - public static toCamel(source: string): string { - // Inspired by http://www.devcurry.com/2011/07/javascript-convert-camelcase-to-dashes.html - // Remove underscores and turn the next character into uppercase - const str: string = source.replace(/_+(.)/g, (x, chr) => chr.toUpperCase()); + /** + * Convert a string to camelCase. + * @param source + * @returns {string} + */ + public static toCamel(source: string): string { + // Inspired by http://www.devcurry.com/2011/07/javascript-convert-camelcase-to-dashes.html + // Remove underscores and turn the next character into uppercase + const str: string = source.replace(/_+(.)/g, (x, chr) => chr.toUpperCase()); - // If we have a leading uppercase (either the source started with an - // uppercase character or with an underscore), lowercase the first. - return this.lowercaseFirst(str); - } + // If we have a leading uppercase (either the source started with an + // uppercase character or with an underscore), lowercase the first. + return this.lowercaseFirst(str); + } - /** - * Convert a string to snake_case. - * - * @param source - * @returns {any} - */ - public static toSnake(source: string): string { - const str: string = this.lowercaseFirst(source); - return str.replace(/([A-Z])/g, x => '_' + x.toLowerCase()); - } + /** + * Convert a string to snake_case. + * + * @param source + * @returns {any} + */ + public static toSnake(source: string): string { + const str: string = this.lowercaseFirst(source); + return str.replace(/([A-Z])/g, (x) => "_" + x.toLowerCase()); + } - /** - * Lowercase the first letter of a string. - * - * @param str - * @returns {string} - */ - private static lowercaseFirst(str: string) { - return str.charAt(0).toLowerCase() + str.slice(1); - } + /** + * Lowercase the first letter of a string. + * + * @param str + * @returns {string} + */ + private static lowercaseFirst(str: string) { + return str.charAt(0).toLowerCase() + str.slice(1); + } } diff --git a/src/support/Type.ts b/src/support/Type.ts index ed6f84e..ecf23b6 100644 --- a/src/support/Type.ts +++ b/src/support/Type.ts @@ -1,12 +1,17 @@ -import { defaultMetadataStorage } from './storage'; -import { StringHelper } from './StringHelper'; -import { TypeMetadata } from './metadata/TypeMetadata'; -import { Entity } from '../Entity'; +import { defaultMetadataStorage } from "./storage"; +import { StringHelper } from "./StringHelper"; +import { TypeMetadata } from "./metadata/TypeMetadata"; +import { Entity } from "../Entity"; -export type Constructor = { new(...args: any): T }; +export type Constructor = { new (...args: any): T }; // Types that can be passed as first argument to `EntityBuilder`. -export type Buildable = Constructor | typeof Object | typeof String | typeof Number | typeof Boolean; +export type Buildable = + | Constructor + | typeof Object + | typeof String + | typeof Number + | typeof Boolean; export type DefaultExportedBuildable = { default: Buildable }; export type PackedBuildable = Buildable | DefaultExportedBuildable; @@ -16,10 +21,15 @@ export type BuildableResolver = () => PackedBuildable; export type Typeable = Buildable | BuildableResolver; export function Type(type: T, jsonKey?: string) { - return function (target: Entity, key: string) { - jsonKey = jsonKey ?? StringHelper.toSnake(key); + return function (target: Entity, key: string) { + jsonKey = jsonKey ?? StringHelper.toSnake(key); - const metadata = new TypeMetadata(target.constructor as Constructor, key, jsonKey, type); - defaultMetadataStorage.addTypeMetadata(metadata); - }; + const metadata = new TypeMetadata( + target.constructor as Constructor, + key, + jsonKey, + type, + ); + defaultMetadataStorage.addTypeMetadata(metadata); + }; } diff --git a/src/support/isEntityType.ts b/src/support/isEntityType.ts index 3d5bf3d..c3ed185 100644 --- a/src/support/isEntityType.ts +++ b/src/support/isEntityType.ts @@ -1,6 +1,8 @@ -import { Buildable, Constructor } from './Type'; -import { Entity } from '../Entity'; +import { Buildable, Constructor } from "./Type"; +import { Entity } from "../Entity"; -export function isEntityType(buildable: Buildable): buildable is Constructor { - return buildable?.prototype instanceof Entity; +export function isEntityType( + buildable: Buildable, +): buildable is Constructor { + return buildable?.prototype instanceof Entity; } diff --git a/src/support/metadata/JsonExcludeMetadata.ts b/src/support/metadata/JsonExcludeMetadata.ts index bcced1a..67eee1d 100644 --- a/src/support/metadata/JsonExcludeMetadata.ts +++ b/src/support/metadata/JsonExcludeMetadata.ts @@ -1,3 +1,6 @@ export class JsonExcludeMetadata { - constructor(public target: Function, public propertyName: string) {} + constructor( + public target: Function, + public propertyName: string, + ) {} } diff --git a/src/support/metadata/MetadataStorage.ts b/src/support/metadata/MetadataStorage.ts index 10f5d47..15339eb 100644 --- a/src/support/metadata/MetadataStorage.ts +++ b/src/support/metadata/MetadataStorage.ts @@ -1,64 +1,80 @@ -import { TypeMetadata } from './TypeMetadata'; -import {JsonExcludeMetadata} from './JsonExcludeMetadata'; +import { TypeMetadata } from "./TypeMetadata"; +import { JsonExcludeMetadata } from "./JsonExcludeMetadata"; export class DefaultValueCallbackMetadata { - constructor(public target: Function, - public propertyName: string, - public callback: () => any, - public condition: (value: any) => boolean) {} + constructor( + public target: Function, + public propertyName: string, + public callback: () => any, + public condition: (value: any) => boolean, + ) {} } /** * Storage all library metadata. */ export class MetadataStorage { + /** + * All the type metadata. + * + * @type {Array} + */ + private typeMetadatas: TypeMetadata[] = []; + private excludedProperties: JsonExcludeMetadata[] = []; - /** - * All the type metadata. - * - * @type {Array} - */ - private typeMetadatas: TypeMetadata[] = []; - private excludedProperties: JsonExcludeMetadata[] = []; + /** + * Append type metadata. + * + * @param metadata + */ + addTypeMetadata(metadata: TypeMetadata) { + this.typeMetadatas.push(metadata); + } - /** - * Append type metadata. - * - * @param metadata - */ - addTypeMetadata(metadata: TypeMetadata) { - this.typeMetadatas.push(metadata); - } + addExcludeProperty(excludeMeta: JsonExcludeMetadata) { + this.excludedProperties.push(excludeMeta); + } - addExcludeProperty(excludeMeta: JsonExcludeMetadata) { - this.excludedProperties.push(excludeMeta); - } + /** + * Find a type metadata. + * + * @param target + * @param propertyName + * @returns {TypeMetadata} + */ + findTypeMetadata(target: any, propertyName: string): TypeMetadata { + const metadataFromTarget = this.typeMetadatas.find( + (meta) => + meta.target === target && meta.sourcePropertyName === propertyName, + ); - /** - * Find a type metadata. - * - * @param target - * @param propertyName - * @returns {TypeMetadata} - */ - findTypeMetadata(target: any, propertyName: string): TypeMetadata { - const metadataFromTarget = this.typeMetadatas.find(meta => - meta.target === target && meta.sourcePropertyName === propertyName, - ); + const metadataForAliasedProperty = this.typeMetadatas.find( + (meta) => meta.target === target && meta.propertyName === propertyName, + ); - const metadataForAliasedProperty = this.typeMetadatas.find(meta => - meta.target === target && meta.propertyName === propertyName, - ); + const metadataFromChildren = this.typeMetadatas.find( + (meta) => + target.prototype instanceof meta.target && + meta.sourcePropertyName === propertyName, + ); - const metadataFromChildren = this.typeMetadatas.find(meta => - target.prototype instanceof meta.target && meta.sourcePropertyName === propertyName, - ); + return ( + metadataFromTarget || metadataForAliasedProperty || metadataFromChildren + ); + } - return metadataFromTarget || metadataForAliasedProperty || metadataFromChildren; - } - - isPropertyExcluded(target: any, propertyName: string): boolean { - return this.excludedProperties.some(propertyMeta => propertyMeta.target === target && propertyMeta.propertyName === propertyName) || - this.excludedProperties.some(propertyMeta => target.prototype instanceof propertyMeta.target && propertyMeta.propertyName === propertyName); - } + isPropertyExcluded(target: any, propertyName: string): boolean { + return ( + this.excludedProperties.some( + (propertyMeta) => + propertyMeta.target === target && + propertyMeta.propertyName === propertyName, + ) || + this.excludedProperties.some( + (propertyMeta) => + target.prototype instanceof propertyMeta.target && + propertyMeta.propertyName === propertyName, + ) + ); + } } diff --git a/src/support/metadata/TypeMetadata.ts b/src/support/metadata/TypeMetadata.ts index 4e5c63f..2288bd0 100644 --- a/src/support/metadata/TypeMetadata.ts +++ b/src/support/metadata/TypeMetadata.ts @@ -1,53 +1,51 @@ import { - PackedBuildable, - Buildable, - BuildableResolver, - Typeable, - Constructor, -} from '../Type'; -import { Entity } from '../../Entity'; + PackedBuildable, + Buildable, + BuildableResolver, + Typeable, + Constructor, +} from "../Type"; +import { Entity } from "../../Entity"; function isResolverFunction(type: Typeable): type is BuildableResolver { - // If the object's name is empty, we will assume it's an anonymous function that resolves the actual type. - return type.name?.length === 0; + // If the object's name is empty, we will assume it's an anonymous function that resolves the actual type. + return type.name?.length === 0; } export class TypeMetadata { - constructor( - public target: Constructor, - public propertyName: string, - public sourcePropertyName: string, - private _type: Typeable - ) {} + constructor( + public target: Constructor, + public propertyName: string, + public sourcePropertyName: string, + private _type: Typeable, + ) {} - public get type(): Buildable - { - if (isResolverFunction(this._type)) { - // Run the function to actually import the module and assign the module - // to type prop so that the EntityBuilder will actually get an entity - // constructor, and not a resolver function. - const resolvedType = (this._type)(); + public get type(): Buildable { + if (isResolverFunction(this._type)) { + // Run the function to actually import the module and assign the module + // to type prop so that the EntityBuilder will actually get an entity + // constructor, and not a resolver function. + const resolvedType = this._type(); - return TypeMetadata.unpackType(resolvedType); - } - - return this._type; + return TypeMetadata.unpackType(resolvedType); } - private static unpackType(type: PackedBuildable): Buildable - { - // Assuming that deferred type is resolved via a 'require' function, - // if it is *not* appended by a key, like below... - // @Type( () => require('./foo') ) - // It will resolve into an object, and since we are no magicians here, - // this will simply return the default exported item. If the entity - // class is not exported as default, the 'require' must have a key - // appended to it like below: - // @Type( () => require('./foo').Foo ) - if (typeof type === 'object') { - return type.default; - } + return this._type; + } - return type; + private static unpackType(type: PackedBuildable): Buildable { + // Assuming that deferred type is resolved via a 'require' function, + // if it is *not* appended by a key, like below... + // @Type( () => require('./foo') ) + // It will resolve into an object, and since we are no magicians here, + // this will simply return the default exported item. If the entity + // class is not exported as default, the 'require' must have a key + // appended to it like below: + // @Type( () => require('./foo').Foo ) + if (typeof type === "object") { + return type.default; } + + return type; + } } diff --git a/src/support/storage.ts b/src/support/storage.ts index aa119ef..e4217db 100644 --- a/src/support/storage.ts +++ b/src/support/storage.ts @@ -1,4 +1,4 @@ -import { MetadataStorage } from './metadata/MetadataStorage'; +import { MetadataStorage } from "./metadata/MetadataStorage"; /** * Default metadata storage is used as singleton and can be used to storage all metadatas. diff --git a/src/support/toJson.ts b/src/support/toJson.ts index adaf932..3e3d1e7 100644 --- a/src/support/toJson.ts +++ b/src/support/toJson.ts @@ -1,57 +1,70 @@ -import { defaultMetadataStorage } from './storage'; -import { StringHelper } from './StringHelper'; -import { TypeMetadata } from './metadata/TypeMetadata'; -import { Entity, Props, PropsJson } from '../Entity'; +import { defaultMetadataStorage } from "./storage"; +import { StringHelper } from "./StringHelper"; +import { TypeMetadata } from "./metadata/TypeMetadata"; +import { Entity, Props, PropsJson } from "../Entity"; -export function toJson(this: T, toSnake: boolean = true, asString: boolean = false): Props | PropsJson | string { - const data: any = {}; +export function toJson( + this: T, + toSnake: boolean = true, + asString: boolean = false, +): Props | PropsJson | string { + const data: any = {}; - for (let key in this) { - if (!this.hasOwnProperty(key)) { - continue; - } - - // exclude any properties with `@JsonExclude()` - if (defaultMetadataStorage.isPropertyExcluded(this.constructor, key)) { - continue; - } - - let outputKey = toSnake ? StringHelper.toSnake(key) : key; + for (let key in this) { + if (!this.hasOwnProperty(key)) { + continue; + } - const value: any = this[key]; + // exclude any properties with `@JsonExclude()` + if (defaultMetadataStorage.isPropertyExcluded(this.constructor, key)) { + continue; + } - if (value instanceof Entity) { - data[outputKey] = value.toJson(toSnake, asString) as Props; + let outputKey = toSnake ? StringHelper.toSnake(key) : key; - continue; - } + const value: any = this[key]; - const metadata: TypeMetadata = defaultMetadataStorage.findTypeMetadata(this.constructor, key); + if (value instanceof Entity) { + data[outputKey] = value.toJson(toSnake, asString) as Props; - if (Array.isArray(value) && value.length > 0 && value[0] instanceof Object) { - if (value[0] instanceof Entity) { - data[outputKey] = value.map((entity: Entity) => entity.toJson(toSnake, asString)); - } + continue; + } - if (metadata && metadata.type === Object) { - data[outputKey] = value; - } + const metadata: TypeMetadata = defaultMetadataStorage.findTypeMetadata( + this.constructor, + key, + ); - continue; - } + if ( + Array.isArray(value) && + value.length > 0 && + value[0] instanceof Object + ) { + if (value[0] instanceof Entity) { + data[outputKey] = value.map((entity: Entity) => + entity.toJson(toSnake, asString), + ); + } - // If the key has been manually annotated as an object, - // we will simply output the object itself. - if (value !== null && typeof value === 'object' && !(Array.isArray(value))) { - if (metadata && metadata.type === Object) { - data[outputKey] = value; - } + if (metadata && metadata.type === Object) { + data[outputKey] = value; + } - continue; - } + continue; + } + // If the key has been manually annotated as an object, + // we will simply output the object itself. + if (value !== null && typeof value === "object" && !Array.isArray(value)) { + if (metadata && metadata.type === Object) { data[outputKey] = value; + } + + continue; } - return asString ? JSON.stringify(data) : data; + data[outputKey] = value; + } + + return asString ? JSON.stringify(data) : data; }