class-transformer
Advanced tools
Comparing version 0.1.0-beta.4 to 0.1.0-beta.5
@@ -8,23 +8,23 @@ "use strict"; | ||
var executor = new TransformOperationExecutor_1.TransformOperationExecutor("classToPlain", options || {}); | ||
return executor.transform(undefined, object, undefined, undefined); | ||
return executor.transform(undefined, object, undefined, undefined, undefined); | ||
}; | ||
ClassTransformer.prototype.classToPlainFromExist = function (object, plainObject, options) { | ||
var executor = new TransformOperationExecutor_1.TransformOperationExecutor("classToPlain", options || {}); | ||
return executor.transform(plainObject, object, undefined, undefined); | ||
return executor.transform(plainObject, object, undefined, undefined, undefined); | ||
}; | ||
ClassTransformer.prototype.plainToClass = function (cls, plain, options) { | ||
var executor = new TransformOperationExecutor_1.TransformOperationExecutor("plainToClass", options || {}); | ||
return executor.transform(undefined, plain, cls, undefined); | ||
return executor.transform(undefined, plain, cls, undefined, undefined); | ||
}; | ||
ClassTransformer.prototype.plainToClassFromExist = function (clsObject, plain, options) { | ||
var executor = new TransformOperationExecutor_1.TransformOperationExecutor("plainToClass", options || {}); | ||
return executor.transform(clsObject, plain, undefined, undefined); | ||
return executor.transform(clsObject, plain, undefined, undefined, undefined); | ||
}; | ||
ClassTransformer.prototype.classToClass = function (object, options) { | ||
var executor = new TransformOperationExecutor_1.TransformOperationExecutor("classToClass", options || {}); | ||
return executor.transform(undefined, object, undefined, undefined); | ||
return executor.transform(undefined, object, undefined, undefined, undefined); | ||
}; | ||
ClassTransformer.prototype.classToClassFromExist = function (object, fromObject, options) { | ||
var executor = new TransformOperationExecutor_1.TransformOperationExecutor("classToClass", options || {}); | ||
return executor.transform(fromObject, object, undefined, undefined); | ||
return executor.transform(fromObject, object, undefined, undefined, undefined); | ||
}; | ||
@@ -31,0 +31,0 @@ ClassTransformer.prototype.serialize = function (object, options) { |
@@ -1,11 +0,10 @@ | ||
import { ExposeOptions, ExcludeOptions } from "./metadata/ExposeExcludeOptions"; | ||
export interface TypeTransformOptions { | ||
newObject: any; | ||
object: Object; | ||
property: string; | ||
} | ||
import { ExposeOptions, ExcludeOptions, TypeOptions, TransformOptions } from "./metadata/ExposeExcludeOptions"; | ||
/** | ||
* Defines a custom logic for value transformation. | ||
*/ | ||
export declare function Transform(transformFn: (value: any) => any, options?: TransformOptions): (target: any, key: string) => void; | ||
/** | ||
* Specifies a type of the property. | ||
*/ | ||
export declare function Type(typeFunction?: (type?: TypeTransformOptions) => Function): (target: any, key: string) => void; | ||
export declare function Type(typeFunction?: (type?: TypeOptions) => Function): (target: any, key: string) => void; | ||
/** | ||
@@ -12,0 +11,0 @@ * Marks property as included in the process of transformation. By default it includes the property for both |
@@ -6,3 +6,14 @@ "use strict"; | ||
var ExcludeMetadata_1 = require("./metadata/ExcludeMetadata"); | ||
var TransformMetadata_1 = require("./metadata/TransformMetadata"); | ||
/** | ||
* Defines a custom logic for value transformation. | ||
*/ | ||
function Transform(transformFn, options) { | ||
return function (target, key) { | ||
var metadata = new TransformMetadata_1.TransformMetadata(target.constructor, key, transformFn, options); | ||
index_1.defaultMetadataStorage.addTransformMetadata(metadata); | ||
}; | ||
} | ||
exports.Transform = Transform; | ||
/** | ||
* Specifies a type of the property. | ||
@@ -13,4 +24,3 @@ */ | ||
var type = Reflect.getMetadata("design:type", target, key); | ||
var isArray = type && typeof type === "string" ? type.toLowerCase() === "array" : false; | ||
var metadata = new TypeMetadata_1.TypeMetadata(target.constructor, key, type, typeFunction, isArray); | ||
var metadata = new TypeMetadata_1.TypeMetadata(target.constructor, key, type, typeFunction); | ||
index_1.defaultMetadataStorage.addTypeMetadata(metadata); | ||
@@ -17,0 +27,0 @@ }; |
@@ -6,2 +6,3 @@ import { ClassType } from "./ClassTransformer"; | ||
export { ClassTransformOptions } from "./ClassTransformOptions"; | ||
export * from "./metadata/ExposeExcludeOptions"; | ||
export * from "./decorators"; | ||
@@ -8,0 +9,0 @@ /** |
@@ -0,1 +1,13 @@ | ||
export interface TransformOptions { | ||
since?: number; | ||
until?: number; | ||
groups?: string[]; | ||
toClassOnly?: boolean; | ||
toPlainOnly?: boolean; | ||
} | ||
export interface TypeOptions { | ||
newObject: any; | ||
object: Object; | ||
property: string; | ||
} | ||
export interface ExposeOptions { | ||
@@ -2,0 +14,0 @@ name?: string; |
@@ -5,2 +5,3 @@ import { TypeMetadata } from "./TypeMetadata"; | ||
import { TransformationType } from "../TransformOperationExecutor"; | ||
import { TransformMetadata } from "./TransformMetadata"; | ||
/** | ||
@@ -11,7 +12,10 @@ * Storage all library metadata. | ||
private _typeMetadatas; | ||
private _transformMetadatas; | ||
private _exposeMetadatas; | ||
private _excludeMetadatas; | ||
addTypeMetadata(metadata: TypeMetadata): void; | ||
addTransformMetadata(metadata: TransformMetadata): void; | ||
addExposeMetadata(metadata: ExposeMetadata): void; | ||
addExcludeMetadata(metadata: ExcludeMetadata): void; | ||
findTransformMetadatas(target: Function, propertyName: string, transformationType: TransformationType): TransformMetadata[]; | ||
findExcludeMetadata(target: Function, propertyName: string): ExcludeMetadata; | ||
@@ -29,2 +33,3 @@ findExposeMetadata(target: Function, propertyName: string): ExposeMetadata; | ||
private findMetadata<T>(metadatas, target, propertyName); | ||
private findMetadatas<T>(metadatas, target, propertyName); | ||
} |
@@ -11,2 +11,3 @@ "use strict"; | ||
this._typeMetadatas = []; | ||
this._transformMetadatas = []; | ||
this._exposeMetadatas = []; | ||
@@ -21,2 +22,5 @@ this._excludeMetadatas = []; | ||
}; | ||
MetadataStorage.prototype.addTransformMetadata = function (metadata) { | ||
this._transformMetadatas.push(metadata); | ||
}; | ||
MetadataStorage.prototype.addExposeMetadata = function (metadata) { | ||
@@ -31,2 +35,18 @@ this._exposeMetadatas.push(metadata); | ||
// ------------------------------------------------------------------------- | ||
MetadataStorage.prototype.findTransformMetadatas = function (target, propertyName, transformationType) { | ||
return this.findMetadatas(this._transformMetadatas, target, propertyName) | ||
.filter(function (metadata) { | ||
if (!metadata.options) | ||
return true; | ||
if (metadata.options.toClassOnly === true && metadata.options.toPlainOnly === true) | ||
return true; | ||
if (metadata.options.toClassOnly === true) { | ||
return transformationType === "classToClass" || transformationType === "plainToClass"; | ||
} | ||
if (metadata.options.toPlainOnly === true) { | ||
return transformationType === "classToPlain"; | ||
} | ||
return true; | ||
}); | ||
}; | ||
MetadataStorage.prototype.findExcludeMetadata = function (target, propertyName) { | ||
@@ -111,2 +131,7 @@ return this.findMetadata(this._excludeMetadatas, target, propertyName); | ||
}; | ||
MetadataStorage.prototype.findMetadatas = function (metadatas, target, propertyName) { | ||
var metadataFromTarget = metadatas.filter(function (meta) { return meta.target === target && meta.propertyName === propertyName; }); | ||
var metadataFromChildren = metadatas.filter(function (meta) { return target.prototype instanceof meta.target && meta.propertyName === propertyName; }); | ||
return metadataFromChildren.reverse().concat(metadataFromTarget.reverse()); | ||
}; | ||
return MetadataStorage; | ||
@@ -113,0 +138,0 @@ }()); |
@@ -0,1 +1,2 @@ | ||
import { TypeOptions } from "./ExposeExcludeOptions"; | ||
export declare class TypeMetadata { | ||
@@ -5,5 +6,4 @@ target: Function; | ||
reflectedType: any; | ||
typeFunction: (object?: Object) => Function; | ||
isArray: boolean; | ||
constructor(target: Function, propertyName: string, reflectedType: any, typeFunction: (object?: Object) => Function, isArray: boolean); | ||
typeFunction: (options?: TypeOptions) => Function; | ||
constructor(target: Function, propertyName: string, reflectedType: any, typeFunction: (options?: TypeOptions) => Function); | ||
} |
"use strict"; | ||
var TypeMetadata = (function () { | ||
function TypeMetadata(target, propertyName, reflectedType, typeFunction, isArray) { | ||
function TypeMetadata(target, propertyName, reflectedType, typeFunction) { | ||
this.target = target; | ||
@@ -8,3 +8,2 @@ this.propertyName = propertyName; | ||
this.typeFunction = typeFunction; | ||
this.isArray = isArray; | ||
} | ||
@@ -11,0 +10,0 @@ return TypeMetadata; |
{ | ||
"name": "class-transformer", | ||
"version": "0.1.0-beta.4", | ||
"version": "0.1.0-beta.5", | ||
"description": "Proper decorator-based transformation / serialization / deserialization of plain javascript objects to class constructors", | ||
@@ -43,2 +43,3 @@ "license": "MIT", | ||
"mocha": "^2.5.3", | ||
"moment": "^2.14.1", | ||
"reflect-metadata": "^0.1.3", | ||
@@ -45,0 +46,0 @@ "remap-istanbul": "^0.6.4", |
@@ -517,2 +517,33 @@ # class-transformer | ||
### Additional data transformation | ||
You can perform additional data transformation using `@Transform` decorator. | ||
For example, you want to make your `Date` object to be a `moment` object when you are | ||
transforming object from plain to class: | ||
```javascript | ||
import {Transform} from "class-transformer"; | ||
import * as moment from "moment"; | ||
import {Moment} from "moment"; | ||
export class Photo { | ||
id: number; | ||
@Transform(value => moment(value), { toClassOnly: true }) | ||
date: Moment; | ||
} | ||
``` | ||
Now when you call `plainToClass` and send a plain representation of the Photo object, | ||
it will convert a date value in your photo object to moment date. | ||
`@Transform` decorator also supports groups and versioning. | ||
### Working with generics | ||
Generics are not supported because TypeScript does not have good reflection abilities. | ||
Once TypeScript team provide us better runtime type reelection tools, generics will be implemented. | ||
There are some tweaks however you can use, that maybe can solve your problem. | ||
[Checkout this example.](https://github.com/pleerock/class-transformer/tree/master/sample/sample4-generics) | ||
### How does it handle circular references? | ||
@@ -519,0 +550,0 @@ |
@@ -8,3 +8,4 @@ import { ClassTransformOptions } from "./ClassTransformOptions"; | ||
constructor(transformationType: TransformationType, options: ClassTransformOptions); | ||
transform(source: Object | Object[] | any, value: Object | Object[] | any, targetType: Function, arrayType: Function, level?: number): any; | ||
transform(source: Object | Object[] | any, value: Object | Object[] | any, targetType: Function, arrayType: Function, fromProperty: string, level?: number): any; | ||
private applyCustomTransformations(value, target, key); | ||
private isCircular(object, level); | ||
@@ -14,2 +15,4 @@ private getKeyType(newObject, object, target, key); | ||
private getKeys(target, object); | ||
private checkVersion(since, until); | ||
private checkGroups(groups); | ||
} |
@@ -18,3 +18,3 @@ "use strict"; | ||
// ------------------------------------------------------------------------- | ||
TransformOperationExecutor.prototype.transform = function (source, value, targetType, arrayType, level) { | ||
TransformOperationExecutor.prototype.transform = function (source, value, targetType, arrayType, fromProperty, level) { | ||
var _this = this; | ||
@@ -27,3 +27,3 @@ if (level === void 0) { level = 0; } | ||
if (!_this.isCircular(subValue, level)) { | ||
newValue_1.push(_this.transform(subSource, subValue, targetType, undefined, level + 1)); | ||
newValue_1.push(_this.transform(subSource, subValue, targetType, undefined, String(index), level + 1)); | ||
} | ||
@@ -62,2 +62,4 @@ else if (_this.transformationType === "classToClass") { | ||
if (!source && (this.transformationType === "plainToClass" || this.transformationType === "classToClass")) { | ||
if (!targetType) | ||
throw new Error("Cannot determine type for " + targetType.name + "." + fromProperty + ", did you forget to specify a @Type?"); | ||
newValue = new targetType(); | ||
@@ -102,6 +104,8 @@ } | ||
if (!this.isCircular(subValue, level)) { | ||
newValue[newValueKey] = this.transform(subSource, subValue, type, arrayType_1, level + 1); | ||
newValue[newValueKey] = this.transform(subSource, subValue, type, arrayType_1, propertyName, level + 1); | ||
newValue[newValueKey] = this.applyCustomTransformations(newValue[newValueKey], targetType, key); | ||
} | ||
else if (this.transformationType === "classToClass") { | ||
newValue[newValueKey] = subValue; | ||
newValue[newValueKey] = this.applyCustomTransformations(newValue[newValueKey], targetType, key); | ||
} | ||
@@ -115,2 +119,33 @@ } | ||
}; | ||
TransformOperationExecutor.prototype.applyCustomTransformations = function (value, target, key) { | ||
var _this = this; | ||
var metadatas = index_1.defaultMetadataStorage.findTransformMetadatas(target, key, this.transformationType); | ||
// apply versioning options | ||
if (this.options.version !== undefined) { | ||
metadatas = metadatas.filter(function (metadata) { | ||
if (!metadata.options) | ||
return true; | ||
return _this.checkVersion(metadata.options.since, metadata.options.until); | ||
}); | ||
} | ||
// apply grouping options | ||
if (this.options.groups && this.options.groups.length) { | ||
metadatas = metadatas.filter(function (metadata) { | ||
if (!metadata.options) | ||
return true; | ||
return _this.checkGroups(metadata.options.groups); | ||
}); | ||
} | ||
else { | ||
metadatas = metadatas.filter(function (metadata) { | ||
return !metadata.options || | ||
!metadata.options.groups || | ||
!metadata.options.groups.length; | ||
}); | ||
} | ||
metadatas.forEach(function (metadata) { | ||
value = metadata.transformFn(value); | ||
}); | ||
return value; | ||
}; | ||
// preventing circular references | ||
@@ -124,3 +159,4 @@ TransformOperationExecutor.prototype.isCircular = function (object, level) { | ||
var metadata = index_1.defaultMetadataStorage.findTypeMetadata(target, key); | ||
return metadata ? metadata.typeFunction({ newObject: newObject, transformingObject: object, property: key }) : undefined; | ||
var options = { newObject: newObject, object: object, property: key }; | ||
return metadata ? metadata.typeFunction(options) : undefined; | ||
}; | ||
@@ -167,8 +203,3 @@ TransformOperationExecutor.prototype.getReflectedType = function (target, propertyName) { | ||
return true; | ||
var decision = true; | ||
if (decision && exposeMetadata.options.since) | ||
decision = _this.options.version >= exposeMetadata.options.since; | ||
if (decision && exposeMetadata.options.until) | ||
decision = _this.options.version < exposeMetadata.options.until; | ||
return decision; | ||
return _this.checkVersion(exposeMetadata.options.since, exposeMetadata.options.until); | ||
}); | ||
@@ -180,5 +211,5 @@ } | ||
var exposeMetadata = index_1.defaultMetadataStorage.findExposeMetadata(target, key); | ||
if (!exposeMetadata || !exposeMetadata.options || !exposeMetadata.options.groups) | ||
if (!exposeMetadata || !exposeMetadata.options) | ||
return true; | ||
return _this.options.groups.some(function (optionGroup) { return exposeMetadata.options.groups.indexOf(optionGroup) !== -1; }); | ||
return _this.checkGroups(exposeMetadata.options.groups); | ||
}); | ||
@@ -208,2 +239,15 @@ } | ||
}; | ||
TransformOperationExecutor.prototype.checkVersion = function (since, until) { | ||
var decision = true; | ||
if (decision && since) | ||
decision = this.options.version >= since; | ||
if (decision && until) | ||
decision = this.options.version < until; | ||
return decision; | ||
}; | ||
TransformOperationExecutor.prototype.checkGroups = function (groups) { | ||
if (!groups) | ||
return true; | ||
return this.options.groups.some(function (optionGroup) { return groups.indexOf(optionGroup) !== -1; }); | ||
}; | ||
return TransformOperationExecutor; | ||
@@ -210,0 +254,0 @@ }()); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
118337
36
871
582
23