Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

typedconverter

Package Overview
Dependencies
Maintainers
1
Versions
193
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

typedconverter - npm Package Compare versions

Comparing version 1.0.0-alpha.3 to 1.0.0-alpha.4

lib/generator.d.ts

40

lib/index.d.ts

@@ -1,24 +0,26 @@

interface ConverterMap {
key: Function;
converter: Converter;
declare type ConverterMap = [Function | string, Converter];
interface ConversionIssue {
path: string[];
messages: string[];
}
declare type Converter = (value: any, path: string[], expectedType: Function | Function[], converters: Map<Function | string, Converter>) => any;
declare type ConversionResult = [any, ConversionIssue[] | undefined];
declare type ConverterStore = Map<Function | string, Converter>;
interface ObjectInfo<T> {
path: string[];
expectedType: T;
converters: ConverterStore;
}
declare type Converter = (value: any, info: ObjectInfo<Function | Function[]>) => ConversionResult;
declare class ConversionError extends Error {
issues: {
path: string[];
messages: string[];
};
issues: ConversionIssue[];
status: number;
constructor(issues: {
path: string[];
messages: string[];
}, status?: number);
constructor(issues: ConversionIssue[], status?: number);
}
declare namespace DefaultConverters {
function booleanConverter(rawValue: {}, path: string[]): boolean;
function numberConverter(rawValue: {}, path: string[]): number;
function dateConverter(rawValue: {}, path: string[]): Date;
function modelConverter(value: {}, path: string[], expectedType: Function | Function[], converters: Map<Function | string, Converter>): any;
function arrayConverter(value: {}, path: string[], expectedType: Function[], converters: Map<Function | string, Converter>): any;
function friendlyArrayConverter(value: {}, path: string[], expectedType: Function[], converters: Map<Function | string, Converter>): any;
function booleanConverter(rawValue: {}, info: ObjectInfo<Function | Function[]>): ConversionResult;
function numberConverter(rawValue: {}, info: ObjectInfo<Function | Function[]>): ConversionResult;
function dateConverter(rawValue: {}, info: ObjectInfo<Function | Function[]>): ConversionResult;
function modelConverter(value: {}, info: ObjectInfo<Function | Function[]>): ConversionResult;
function strictArrayConverter(value: {}, info: ObjectInfo<Function[]>): ConversionResult;
function friendlyArrayConverter(value: {}, info: ObjectInfo<Function[]>): ConversionResult;
}

@@ -30,3 +32,3 @@ declare function converter(option?: {

}): (value: any, type?: Function | Function[] | undefined, path?: string[]) => any;
export { Converter, DefaultConverters, ConverterMap, ConversionError };
export { Converter, DefaultConverters, ConverterMap, ConversionResult, ConversionError, ObjectInfo, ConversionIssue, ConverterStore };
export default converter;

@@ -7,3 +7,3 @@ "use strict";

constructor(issues, status = 400) {
super();
super("Conversion error");
this.issues = issues;

@@ -20,3 +20,3 @@ this.status = status;

const typeName = Array.isArray(typ) ? `Array<${typ[0].name}>` : typ.name;
return new ConversionError({ path: path, messages: [`Unable to convert "${value}" into ${typeName}`] });
return [{ path: path, messages: [`Unable to convert "${value}" into ${typeName}`] }];
}

@@ -51,3 +51,3 @@ //some object can't simply convertible to string https://github.com/emberjs/ember.js/issues/14922#issuecomment-278986178

(function (DefaultConverters) {
function booleanConverter(rawValue, path) {
function booleanConverter(rawValue, info) {
const value = safeToString(rawValue);

@@ -60,23 +60,24 @@ const list = {

if (result === undefined)
throw createConversionError(value, Boolean, path);
return result;
return [undefined, createConversionError(value, Boolean, info.path)];
return [result, undefined];
}
DefaultConverters.booleanConverter = booleanConverter;
function numberConverter(rawValue, path) {
function numberConverter(rawValue, info) {
const value = safeToString(rawValue);
const result = Number(value);
if (isNaN(result) || value === "")
throw createConversionError(value, Number, path);
return result;
return [undefined, createConversionError(value, Number, info.path)];
return [result, undefined];
}
DefaultConverters.numberConverter = numberConverter;
function dateConverter(rawValue, path) {
function dateConverter(rawValue, info) {
const value = safeToString(rawValue);
const result = new Date(value);
if (isNaN(result.getTime()) || value === "")
throw createConversionError(value, Date, path);
return result;
return [undefined, createConversionError(value, Date, info.path)];
return [result, undefined];
}
DefaultConverters.dateConverter = dateConverter;
function modelConverter(value, path, expectedType, converters) {
function modelConverter(value, info) {
const { converters } = info;
//--- helper functions

@@ -87,3 +88,3 @@ const isConvertibleToObject = (value) => typeof value !== "boolean"

//---
const TheType = expectedType;
const TheType = info.expectedType;
//get reflection metadata of the class

@@ -93,8 +94,15 @@ const reflection = tinspector_1.default(TheType);

if (!isConvertibleToObject(value))
throw createConversionError(value, TheType, path);
return [undefined, createConversionError(value, TheType, info.path)];
const instance = createInstance(value, TheType);
//traverse through the object properties and convert to appropriate property's type
//sanitize excess property to prevent object having properties that doesn't match with declaration
const issues = [];
for (let x of reflection.properties) {
const val = convert(value[x.name], path.concat(x.name), x.type, converters);
const [val, err] = convert(value[x.name], {
path: info.path.concat(x.name),
expectedType: x.type,
converters
});
if (err)
issues.push(...err);
//remove undefined properties

@@ -106,14 +114,34 @@ if (val === undefined)

}
return instance;
if (issues.length > 0)
return [undefined, issues];
else
return [instance, undefined];
}
DefaultConverters.modelConverter = modelConverter;
function arrayConverter(value, path, expectedType, converters) {
function arrayConverter(value, info) {
const result = value.map((x, i) => convert(x, {
path: info.path.concat(i.toString()),
expectedType: info.expectedType && info.expectedType[0],
converters: info.converters
}));
if (result.some(x => !!x[1])) {
const issue = [];
for (const [, err] of result) {
if (err)
issue.push(...err);
}
return [undefined, issue];
}
else
return [result.map(x => x[0]), undefined];
}
function strictArrayConverter(value, info) {
if (!Array.isArray(value))
throw createConversionError(value, expectedType, path);
return value.map((x, i) => convert(x, path.concat(i.toString()), expectedType[0], converters));
return [undefined, createConversionError(value, info.expectedType, info.path)];
return arrayConverter(value, info);
}
DefaultConverters.arrayConverter = arrayConverter;
function friendlyArrayConverter(value, path, expectedType, converters) {
DefaultConverters.strictArrayConverter = strictArrayConverter;
function friendlyArrayConverter(value, info) {
const cleanValue = Array.isArray(value) ? value : [value];
return cleanValue.map((x, i) => convert(x, path.concat(i.toString()), expectedType[0], converters));
return arrayConverter(cleanValue, info);
}

@@ -126,34 +154,40 @@ DefaultConverters.friendlyArrayConverter = friendlyArrayConverter;

// --------------------------------------------------------------------- //
function convert(value, path, expectedType, converters) {
function convert(value, info) {
const { expectedType, converters, path } = info;
if (value === null || value === undefined)
return undefined;
return [undefined, undefined];
if (!expectedType)
return value;
return [value, undefined];
if (expectedType === Object)
return value;
return [value, undefined];
if (value.constructor === expectedType)
return value;
return [value, undefined];
//check if the parameter contains @array()
if (Array.isArray(expectedType))
return converters.get("Array")(value, path, expectedType, converters);
return converters.get("Array")(value, { expectedType, converters, path });
//check if parameter is native value that has default converter (Number, Date, Boolean) or if user provided converter
else if (converters.has(expectedType))
return converters.get(expectedType)(value, path, expectedType, converters);
return converters.get(expectedType)(value, { expectedType, converters, path });
//if type of model and has no converter, use DefaultObject converter
else
return converters.get("Model")(value, path, expectedType, converters);
return converters.get("Model")(value, { expectedType, converters, path });
}
function converter(option = {}) {
return (value, type, path = []) => {
const mergedConverters = new Map();
mergedConverters.set(Number, DefaultConverters.numberConverter);
mergedConverters.set(Boolean, DefaultConverters.booleanConverter);
mergedConverters.set(Date, DefaultConverters.dateConverter);
const arrayConverter = (option.guessArrayElement ? DefaultConverters.friendlyArrayConverter : DefaultConverters.arrayConverter);
mergedConverters.set("Array", arrayConverter);
mergedConverters.set("Model", DefaultConverters.modelConverter);
(option.converters || []).forEach(x => mergedConverters.set(x.key, x.converter));
return convert(value, path, type || option.type, mergedConverters);
const arrayConverter = (option.guessArrayElement ? DefaultConverters.friendlyArrayConverter : DefaultConverters.strictArrayConverter);
const mergedConverters = new Map([
[Number, DefaultConverters.numberConverter],
[Boolean, DefaultConverters.booleanConverter],
[Date, DefaultConverters.dateConverter],
["Array", arrayConverter],
["Model", DefaultConverters.modelConverter],
...option.converters || []
]);
const [val, err] = convert(value, { path, expectedType: type || option.type, converters: mergedConverters });
if (err)
throw new ConversionError(err);
else
return val;
};
}
exports.default = converter;
{
"name": "typedconverter",
"version": "1.0.0-alpha.3",
"version": "1.0.0-alpha.4",
"description": "Convert object into classes match with TypeScript type annotation",

@@ -13,3 +13,5 @@ "main": "lib/index.js",

"test": "jest",
"prepublish": "tsc -p tsconfig.build.json"
"prepublish": "tsc -p tsconfig.build.json",
"gen": "ts-node src/generator.ts",
"clean": "rm -rf src/*.js && rm -rf test/*.js"
},

@@ -19,9 +21,15 @@ "author": "Ketut Sandiarsa",

"dependencies": {
"tinspector": "^2.2.0",
"tslib": "^1.9.3"
"@types/validator": "^10.11.0",
"tinspector": "^2.2.1",
"tslib": "^1.9.3",
"validator": "^10.11.0"
},
"devDependencies": {
"@types/ejs": "^2.6.3",
"@types/jest": "^24.0.11",
"@types/joi": "^14.3.2",
"coveralls": "^3.0.3",
"ejs": "^2.6.1",
"jest": "^24.5.0",
"joi": "^14.3.1",
"ts-jest": "^24.0.0",

@@ -28,0 +36,0 @@ "typescript": "^3.3.4000"

@@ -5,3 +5,3 @@ # TypedConverter

[![Build Status](https://travis-ci.org/plumier/typedconverter.svg?branch=master)](https://travis-ci.org/plumier/typedconverter)
[![Coverage Status](https://coveralls.io/repos/github/plumier/typedconverter/badge.svg?branch=master)](https://coveralls.io/github/plumier/typedconverter?branch=master)
[![Coverage Status](https://coveralls.io/repos/github/plumier/typedconverter/badge.svg?branch=master)](https://coveralls.io/github/plumier/typedconverter?branch=master) [![Greenkeeper badge](https://badges.greenkeeper.io/plumier/typedconverter.svg)](https://greenkeeper.io/)

@@ -41,3 +41,3 @@

reflect.parameterProperties()
@reflect.parameterProperties()
class AnimalClass {

@@ -70,2 +70,29 @@ constructor(

## Convert Child Array
Nested child array need to be decorate for TypeScript added design data type
```typescript
import createConverter from "typedconverter";
@reflect.parameterProperties()
class Tag {
constructor(
public name: string,
) { }
}
@reflect.parameterProperties()
class Animal {
constructor(
public name: string,
@reflect.array(Tag)
public tags: Tags
) { }
}
const convert = createConverter()
//tags is instance of Tag class
const numb = convert({name: "Mimi", tags: [{name: "Susi"}, {name: "Lorem"}]}, Animal)
```
## Custom Converter

@@ -83,1 +110,10 @@ Provided custom converter on the configuration

```
## Guess Array Element
Useful when converting data from url encoded, where single value could be a single array.
```typescript
const convert = createConverter({ guessArrayElement: true })
const b = convert("1", [Number]) //ok
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc