Skip to content
Permalink
Browse files

Initial

  • Loading branch information
Ajaxy committed Aug 25, 2018
0 parents commit 18e2d5b531698a5943b0e507eabf133bf2ee5fb0
Showing with 6,352 additions and 0 deletions.
  1. +17 −0 .eslintrc
  2. +3 −0 .gitignore
  3. +61 −0 README.md
  4. +71 −0 lib/index.js
  5. +5,996 −0 package-lock.json
  6. +44 −0 package.json
  7. +160 −0 tests/all.test.js
@@ -0,0 +1,17 @@
{
"extends": "airbnb-base",
"rules": {
"max-len": ["error", 120],
"no-param-reassign": 0,
"no-use-before-define": [
"error",
{
"functions": false,
"classes": false
}
]
},
"env": {
"jest": true
}
}
@@ -0,0 +1,3 @@
.idea
.DS_Store
node_modules
@@ -0,0 +1,61 @@
# cast-with-schema
[![NPM version](https://img.shields.io/npm/v/cast-with-schema.svg)](https://npmjs.com/package/cast-with-schema)

The way to cast data to types specified with [JSON schema](http://json-schema.org/).

May be used for query params casting:

```js
const qs = require('qs');
const castWithSchema = require('cast-with-schema');
const schema = {
type: "object",
properties: {
param1: {
type: 'string',
},
param2: {
type: 'integer',
},
param3: {
type: 'number',
},
param4: {
type: 'boolean',
},
}
};
const query = 'param1=value&param2=777&param3=7.77&param4=false';
const parsed = qs.parse(query);
const casted = castWithSchema(query, schema);
/*
`casted` is now:
{
param1: 'value',
param2: 777,
param3: 7.77,
param4: false,
}
*/
```

Supports `null` if schema is either:
```
type: ['..', 'null']
```
or
```
anyOf: [
{ type: '..' },
{ type: 'null' }
]
```

### See also

Check out [tinsypec](https://github.com/Ajaxy/tinyspec) for more smart JSON schema use cases.

@@ -0,0 +1,71 @@
function castWithSchema(query, schema) {
const casted = {};

Object.keys(query).forEach((field) => {
const value = query[field];
const propertyDef = schema.properties && schema.properties[field];

casted[field] = castProp(value, propertyDef);
});

return casted;
}

function castProp(value, propertyDef) {
if (!value || !propertyDef) {
return value;
}

if (value === 'null' && isNullAllowed(propertyDef)) {
return null;
}

switch (resolveType(propertyDef)) {
case 'integer':
return parseInt(value, 10);
case 'number':
return Number(value);
case 'boolean':
return value !== 'false';
case 'array':
return Array.isArray(value) ? value.map(member => castProp(member, propertyDef.items)) : undefined;
case 'object':
return typeof value === 'object' ? castWithSchema(value, propertyDef) : undefined;
default:
return value;
}
}

function isNullAllowed(propertyDef) {
const { type, anyOf } = propertyDef;

if (Array.isArray(type)) {
return type.includes('null');
}

if (anyOf) {
return anyOf.some(({ type: t }) => t === 'null');
}

return false;
}

function resolveType(propertyDef) {
const { type, anyOf } = propertyDef;

if (typeof type === 'string') {
return type;
}

if (Array.isArray(type)) {
return type.find(t => t !== 'null');
}

if (anyOf) {
return anyOf.find(({ type: t }) => t !== 'null').type;
}

return null;
}

module.exports = castWithSchema;

0 comments on commit 18e2d5b

Please sign in to comment.
You can’t perform that action at this time.