Skip to content

Commit

Permalink
fix(classes): move all single functions to exported utils
Browse files Browse the repository at this point in the history
  • Loading branch information
nartc committed Mar 6, 2021
1 parent ad3e731 commit 219b917
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 98 deletions.
4 changes: 4 additions & 0 deletions packages/classes/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export * from './lib/classes';
export * from './lib/decorators';
export * from './lib/constants';
export { prePropertiesLoop } from './lib/utils';
export { isMultipartSourcePathsInSource } from './lib/utils';
export { isDestinationPathOnSource } from './lib/utils';
export { exploreMetadata } from './lib/utils';
107 changes: 9 additions & 98 deletions packages/classes/src/lib/classes.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import { createInitialMapping, isDefined } from '@automapper/core';
import type {
Dictionary,
Mapping,
MapPluginInitializer,
} from '@automapper/types';
import { createInitialMapping } from '@automapper/core';
import type { Dictionary, MapPluginInitializer } from '@automapper/types';
import { MappingClassId } from '@automapper/types';
import 'reflect-metadata';
import {
AUTOMAP_PROPERTIES_METADATA_KEY,
AUTOMAPPER_METADATA_FACTORY_KEY,
} from './constants';
import {
ClassInstanceStorage,
ClassMappingStorage,
ClassMetadataStorage,
} from './storages';
import type { Constructible } from './types';
import { instantiate, isClass } from './utils';
import {
exploreMetadata,
instantiate,
isDestinationPathOnSource,
isMultipartSourcePathsInSource,
prePropertiesLoop,
} from './utils';

/**
*
Expand Down Expand Up @@ -154,90 +152,3 @@ export const classes: MapPluginInitializer<Constructible> = (errorHandler) => {
},
};
};

function exploreMetadata(
metadataStorage: ClassMetadataStorage,
instanceStorage: ClassInstanceStorage,
...models: Constructible[]
) {
// Loop through each models passed in
for (const model of models) {
// if metadataStorage hasn't had metadata of the model
if (!metadataStorage.has(model)) {
// get the metadata from Reflection and AUTOMAPPER_METADATA_FACTORY then populate metadataStorage and instanceStorage
let metadataList =
Reflect.getMetadata(AUTOMAP_PROPERTIES_METADATA_KEY, model) || [];

if ((model as any)[AUTOMAPPER_METADATA_FACTORY_KEY]) {
metadataList = metadataList.concat(
(model as any)[AUTOMAPPER_METADATA_FACTORY_KEY]() || []
);
}

// if no metadata, skip
if (!isDefined(metadataList)) continue;
// loop through metadata list
for (const [propertyKey, { typeFn, depth }] of metadataList) {
metadataStorage.addMetadata(model, [propertyKey, typeFn]);
if (depth != null) {
instanceStorage.setDepth(model, propertyKey, depth);
}
}
}
}
}

function prePropertiesLoop(
source: Constructible,
metadataStorage: ClassMetadataStorage,
instanceStorage: ClassInstanceStorage,
sourceInstance: unknown,
sourceNestedConstructible: unknown[]
) {
return (mapping: Mapping) => {
// get prototype of the constructor
const sourceProtoConstructor = Object.getPrototypeOf(source.constructor);
// if it has name, then it's not anonymous Function
if (sourceProtoConstructor.name) {
// try to instantiate the proto constructor
const [sourceProtoInstance, sourceProtoNestedConstructible] = instantiate(
instanceStorage,
metadataStorage,
sourceProtoConstructor
);
// merge the instance of the proto with the sourceInstance
sourceInstance = Object.assign(sourceInstance, sourceProtoInstance);
// update the sourceInstance on the mapping
mapping[MappingClassId.mappings][0] = sourceInstance;
if ((sourceProtoNestedConstructible as unknown[]).length) {
// update the nested constructible
sourceNestedConstructible = sourceNestedConstructible.concat(
sourceProtoNestedConstructible
);
}
}
};
}

function isMultipartSourcePathsInSource(
dottedSourcePaths: string[],
sourceInstance: Record<string, unknown>
) {
return !(
dottedSourcePaths.length > 1 &&
(!sourceInstance.hasOwnProperty(dottedSourcePaths[0]) ||
(sourceInstance[dottedSourcePaths[0]] &&
// eslint-disable-next-line @typescript-eslint/ban-types
isClass((sourceInstance[dottedSourcePaths[0]] as unknown) as Function)))
);
}

function isDestinationPathOnSource(sourceProto: Record<string, unknown>) {
return (sourceObj: any, sourcePath: string) => {
return !(
!sourceObj.hasOwnProperty(sourcePath) &&
!sourceProto.hasOwnProperty(sourcePath) &&
!Object.getPrototypeOf(sourceObj).hasOwnProperty(sourcePath)
);
};
}
39 changes: 39 additions & 0 deletions packages/classes/src/lib/utils/explore-metadata.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { isDefined } from '@automapper/core';
import {
AUTOMAP_PROPERTIES_METADATA_KEY,
AUTOMAPPER_METADATA_FACTORY_KEY,
} from '../constants';
import type { ClassInstanceStorage, ClassMetadataStorage } from '../storages';
import type { Constructible } from '../types';

export function exploreMetadata(
metadataStorage: ClassMetadataStorage,
instanceStorage: ClassInstanceStorage,
...models: Constructible[]
) {
// Loop through each models passed in
for (const model of models) {
// if metadataStorage hasn't had metadata of the model
if (!metadataStorage.has(model)) {
// get the metadata from Reflection and AUTOMAPPER_METADATA_FACTORY then populate metadataStorage and instanceStorage
let metadataList =
Reflect.getMetadata(AUTOMAP_PROPERTIES_METADATA_KEY, model) || [];

if ((model as any)[AUTOMAPPER_METADATA_FACTORY_KEY]) {
metadataList = metadataList.concat(
(model as any)[AUTOMAPPER_METADATA_FACTORY_KEY]() || []
);
}

// if no metadata, skip
if (!isDefined(metadataList)) continue;
// loop through metadata list
for (const [propertyKey, { typeFn, depth }] of metadataList) {
metadataStorage.addMetadata(model, [propertyKey, typeFn]);
if (depth != null) {
instanceStorage.setDepth(model, propertyKey, depth);
}
}
}
}
}
4 changes: 4 additions & 0 deletions packages/classes/src/lib/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
export * from './instantiate.util';
export * from './is-class.util';
export * from './pre-properties-loop.util';
export * from './is-multipart-source-paths-in-source.util';
export * from './is-destination-path-on-source.util';
export * from './explore-metadata.util';
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function isDestinationPathOnSource(
sourceProto: Record<string, unknown>
) {
return (sourceObj: any, sourcePath: string) => {
return !(
!sourceObj.hasOwnProperty(sourcePath) &&
!sourceProto.hasOwnProperty(sourcePath) &&
!Object.getPrototypeOf(sourceObj).hasOwnProperty(sourcePath)
);
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { isClass } from './is-class.util';

export function isMultipartSourcePathsInSource(
dottedSourcePaths: string[],
sourceInstance: Record<string, unknown>
) {
return !(
dottedSourcePaths.length > 1 &&
(!sourceInstance.hasOwnProperty(dottedSourcePaths[0]) ||
(sourceInstance[dottedSourcePaths[0]] &&
// eslint-disable-next-line @typescript-eslint/ban-types
isClass((sourceInstance[dottedSourcePaths[0]] as unknown) as Function)))
);
}
37 changes: 37 additions & 0 deletions packages/classes/src/lib/utils/pre-properties-loop.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { Mapping } from '@automapper/types';
import { MappingClassId } from '@automapper/types';
import type { ClassInstanceStorage, ClassMetadataStorage } from '../storages';
import type { Constructible } from '../types';
import { instantiate } from './instantiate.util';

export function prePropertiesLoop(
source: Constructible,
metadataStorage: ClassMetadataStorage,
instanceStorage: ClassInstanceStorage,
sourceInstance: unknown,
sourceNestedConstructible: unknown[]
) {
return (mapping: Mapping) => {
// get prototype of the constructor
const sourceProtoConstructor = Object.getPrototypeOf(source.constructor);
// if it has name, then it's not anonymous Function
if (sourceProtoConstructor.name) {
// try to instantiate the proto constructor
const [sourceProtoInstance, sourceProtoNestedConstructible] = instantiate(
instanceStorage,
metadataStorage,
sourceProtoConstructor
);
// merge the instance of the proto with the sourceInstance
sourceInstance = Object.assign(sourceInstance, sourceProtoInstance);
// update the sourceInstance on the mapping
mapping[MappingClassId.mappings][0] = sourceInstance;
if ((sourceProtoNestedConstructible as unknown[]).length) {
// update the nested constructible
sourceNestedConstructible = sourceNestedConstructible.concat(
sourceProtoNestedConstructible
);
}
}
};
}

0 comments on commit 219b917

Please sign in to comment.