typedconverter
Advanced tools
Comparing version 2.2.1 to 2.3.0
import { Class } from "./types"; | ||
declare type Converter = (value: {}) => {} | undefined; | ||
declare function safeToString(value: any): any; | ||
declare const defaultConverters: Map<Class, Converter>; | ||
declare const defaultConverters: Map<Class<any>, Converter>; | ||
export { defaultConverters, Converter, safeToString }; |
@@ -6,7 +6,7 @@ import { Opt, val } from "./decorators"; | ||
import { Result, ResultMessages } from "./visitor"; | ||
interface Option { | ||
interface Option<T = any> { | ||
/** | ||
* Expected type | ||
*/ | ||
type: Class | Class[]; | ||
type: T; | ||
/** | ||
@@ -34,3 +34,3 @@ * List of visitor extension to extend TypedConverter internal process | ||
*/ | ||
declare function convert(value: any, opt: Option): Result; | ||
declare function convert<T = any>(value: any, option: Option<T> | T): T extends Class<infer R>[] ? Result<R[]> : T extends Class<infer R> ? Result<R> : Result<any>; | ||
/** | ||
@@ -40,4 +40,5 @@ * Create type converter with specific configuration | ||
*/ | ||
export default function createConverter(option: Option): (value: any) => Result; | ||
declare function validate(value: any, opt: Option): Result; | ||
export { convert, Option, VisitorExtension, VisitorInvocation, Result, ResultMessages, partial, validatorVisitor, Validator, PartialValidator, val, Opt, validate, ValidatorDecorator }; | ||
export default function createConverter<T = any>(option: Option<T> | T): (value: any) => T extends Class<infer R>[] ? Result<R[]> : T extends Class<infer R_1> ? Result<R_1> : Result<any>; | ||
declare function createValidator<T>(option: T | Option<T>): (value: any) => T extends Class<infer R>[] ? Result<R[]> : T extends Class<infer R_1> ? Result<R_1> : Result<any>; | ||
declare function validate<T>(value: any, option: Option<T> | T): T extends Class<infer R>[] ? Result<R[]> : T extends Class<infer R_1> ? Result<R_1> : Result<any>; | ||
export { convert, Option, VisitorExtension, VisitorInvocation, Result, ResultMessages, partial, validatorVisitor, Validator, PartialValidator, val, Opt, validate, createValidator, ValidatorDecorator }; |
@@ -17,3 +17,4 @@ "use strict"; | ||
*/ | ||
function convert(value, opt) { | ||
function convert(value, option) { | ||
const opt = "type" in option ? option : { type: option }; | ||
return visitor_1.pipeline(value, transformer_1.transform(opt.type), { | ||
@@ -34,3 +35,8 @@ path: opt.path || "", extension: opt.visitors || [], | ||
exports.default = createConverter; | ||
function validate(value, opt) { | ||
function createValidator(option) { | ||
return (value) => validate(value, option); | ||
} | ||
exports.createValidator = createValidator; | ||
function validate(value, option) { | ||
const opt = "type" in option ? option : { type: option }; | ||
const visitors = [validation_1.validatorVisitor]; | ||
@@ -37,0 +43,0 @@ for (const visitor of (opt.visitors || [])) { |
@@ -1,1 +0,1 @@ | ||
export declare type Class = new (...args: any[]) => any; | ||
export declare type Class<T = any> = new (...args: any[]) => T; |
@@ -8,4 +8,4 @@ import { VisitorExtension } from "./invocation"; | ||
} | ||
interface Result { | ||
value: any; | ||
interface Result<T = any> { | ||
value: T; | ||
issues?: ResultMessages[]; | ||
@@ -12,0 +12,0 @@ } |
{ | ||
"name": "typedconverter", | ||
"version": "2.2.1", | ||
"version": "2.3.0", | ||
"description": "Convert object into classes match with TypeScript type annotation", | ||
@@ -16,3 +16,3 @@ "main": "lib/index.js", | ||
"clean": "rm -rf src/*.js && rm -rf test/*.js && rm -rf lib", | ||
"benchmark": "ts-node test/benchmark.ts" | ||
"benchmark": "ts-node benchmark/index.ts" | ||
}, | ||
@@ -25,14 +25,16 @@ "author": "Ketut Sandiarsa", | ||
"tslib": "^1.11.1", | ||
"validator": "^12.2.0" | ||
"validator": "^13.0.0" | ||
}, | ||
"devDependencies": { | ||
"@hapi/joi": "^17.1.1", | ||
"@types/ejs": "^3.0.1", | ||
"@types/hapi__joi": "^16.0.12", | ||
"@types/jest": "^25.1.4", | ||
"@types/joi": "^14.3.4", | ||
"coveralls": "^3.0.9", | ||
"@types/lodash": "^4.14.149", | ||
"coveralls": "^3.0.11", | ||
"ejs": "^3.0.1", | ||
"jest": "^25.1.0", | ||
"joi": "^14.3.1", | ||
"lodash": "^4.17.15", | ||
"ts-jest": "^25.2.1", | ||
"ts-node": "^8.6.2", | ||
"ts-node": "^8.8.1", | ||
"typescript": "^3.8.3" | ||
@@ -39,0 +41,0 @@ }, |
138
readme.md
@@ -8,83 +8,88 @@ # TypedConverter | ||
## Convert Primitive Type | ||
## Performance | ||
TypedConverter uses several performance optimization, first it traverse Type properties using efficient properties traversal then compiles TypeScript types into optimized object graph contains functions for conversion. | ||
```typescript | ||
import { convert } from "typedconverter"; | ||
const numb = await convert("12345", { type: Number }) //return number 12345 | ||
const numb = await convert("YES", { type: Boolean }) //return true | ||
const numb = await convert("2019-2-2", { type: Date }) //return date 1/1/2019 | ||
Performance compared to Joi | ||
``` | ||
Test Type Sec | ||
Joi - Type conversion 17.62 | ||
Joi - Validation 61.67 | ||
TypedConverter - Type conversion 7.29 | ||
TypedConverter - Validation 23.51 | ||
``` | ||
## Specify type on configuration | ||
Expected type can be specified in the configuration, than you can omit expected type on the second parameter of the `convert` function. Useful when you want to covert several times without specifying expected type. | ||
To run benchmark: | ||
* Clone this repo | ||
* `yarn install` | ||
* `yarn benchmark` | ||
```typescript | ||
import createConverter from "typedconverter"; | ||
## Usage | ||
const convert = createConverter({type: Number}) | ||
const numb = await convert("12345") | ||
const numb1 = await convert("-12345") | ||
const numb2 = await convert("12345.123") | ||
``` | ||
## Convert custom class | ||
TypedConvert uses tinspector to get type metadata, so it aware about TypeScript type annotation. | ||
```typescript | ||
import {convert} from "typedconverter"; | ||
import reflect from "tinspector" | ||
import { createValidator, val } from "typedconverter" | ||
@reflect.parameterProperties() | ||
class AnimalClass { | ||
class User { | ||
constructor( | ||
public id: number, | ||
public name: string, | ||
public deceased: boolean, | ||
public birthday: Date | ||
) { } | ||
@val.email() | ||
public email:string, | ||
public name:string, | ||
@val.before() | ||
public dateOfBirth:Date, | ||
public isActive:boolean | ||
){} | ||
} | ||
//return instance of AnimalClass with appropriate properties type | ||
const data = await convert({ | ||
id: "200", | ||
name: "Mimi", | ||
deceased: "ON", | ||
birthday: "2018-2-2" }, | ||
{ type: AnimalClass }) | ||
``` | ||
## Convert Array | ||
Convert into array by providing array of type in the expected type. | ||
// create validation function | ||
const validate = createValidator(User) | ||
// this configuration will result the same | ||
// const validate = createValidator({ type: User }) | ||
// validate raw value | ||
const user = validate({ | ||
email: "john.doe@gmail.com", name: "John Doe", | ||
dateOfBirth: "1991-1-2", isActive: "true" | ||
}) | ||
```typescript | ||
import {convert} from "typedconverter"; | ||
// create validation function for array | ||
const validate = createValidator([User]) | ||
// validate raw value | ||
const user = validate([{ | ||
email: "john.doe@gmail.com", name: "John Doe", | ||
dateOfBirth: "1991-1-2", isActive: "true" | ||
}, { | ||
email: "jane.deane@gmail.com", name: "Jane Deane", | ||
dateOfBirth: "1994-1-2", isActive: "false" | ||
}, | ||
]) | ||
const numb = await convert(["1", "2", "-3"], { type: [Number] }) | ||
``` | ||
## Convert Child Array | ||
Nested child array need to be decorate for TypeScript added design data type | ||
## Without Factory | ||
`createValidator` good to have a shared validator configuration, but for single usage its better to use the `validate` function. | ||
```typescript | ||
import {convert} from "typedconverter"; | ||
import reflect from "tinspector" | ||
import { validate, val } from "typedconverter" | ||
@reflect.parameterProperties() | ||
class Tag { | ||
class User { | ||
constructor( | ||
public name: string, | ||
) { } | ||
@val.email() | ||
public email:string, | ||
public name:string, | ||
@val.before() | ||
public dateOfBirth:Date, | ||
public isActive:boolean | ||
){} | ||
} | ||
@reflect.parameterProperties() | ||
class Animal { | ||
constructor( | ||
public name: string, | ||
@reflect.array(Tag) | ||
public tags: Tags | ||
) { } | ||
} | ||
//tags is instance of Tag class | ||
const numb = await convert({name: "Mimi", tags: [{name: "Susi"}, {name: "Lorem"}]}, { type: Animal }) | ||
// pass the Type as the second parameter | ||
const user = validate({ | ||
email: "john.doe@gmail.com", name: "John Doe", | ||
dateOfBirth: "1991-1-2", isActive: "true" | ||
}, User) | ||
// can be passed as option too | ||
// const user = validate(<raw value>, { type: User }) | ||
``` | ||
@@ -96,7 +101,8 @@ | ||
```typescript | ||
const b = await convert("1", { type: [Number], guessArrayElement: true }) //ok [1] | ||
const b = await convert("1", { type: [Number], guessArrayElement: true }) // -> result = [1] | ||
``` | ||
Note that, when the type passed to the configuration is of type Array, providing single value will guessed as Array. | ||
## Visitors | ||
## Extending with Visitors | ||
Visitors executed after conversion process traverse through properties / array element. Invocation can be multiple and run in sequence the last sequence will execute the converter. Visitors work like [Plumier middleware](https://plumierjs.com/docs/middleware) | ||
@@ -117,3 +123,3 @@ | ||
```typescript | ||
import createConverter, { Result, VisitorInvocation } from "typedconverter" | ||
import { createValidation, Result, VisitorInvocation } from "typedconverter" | ||
@@ -127,7 +133,5 @@ const olderThanEightTeen = (i: VisitorInvocation) => { | ||
const convert = createConverter({ type: Number, visitors: [olderThanEightTeen] }) | ||
const result = convert("40") // { value: 40 } | ||
const other = convert("12") // { issues: [{path: "", messages: ["Must be older than 18"]}] } | ||
``` | ||
const validate = createValidation({ type: Number, visitors: [olderThanEightTeen] }) | ||
const result = validate("40") // { value: 40 } | ||
const other = validate("12") // { issues: [{path: "", messages: ["Must be older than 18"]}] } | ||
``` |
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
46984
31
1019
133
12
+ Addedvalidator@13.12.0(transitive)
- Removedvalidator@12.2.0(transitive)
Updatedvalidator@^13.0.0