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

@alexkuz/json-schema-default-instance

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@alexkuz/json-schema-default-instance - npm Package Compare versions

Comparing version 1.2.2 to 1.2.7

1

dist/instantiator.d.ts

@@ -15,3 +15,4 @@ /// <reference types="lodash" />

}
export declare function normalizeSchemaRef(schemaRef: string, options: Options): string;
declare const instantiate: _.CurriedFunction2<Options, string, InstantiateResult>;
export default instantiate;

102

dist/instantiator.js
"use strict";
var _ = require('lodash');
var url_1 = require('url');
var defaultOptions = {
resolveDefaultRefs: false
};
/** Split a `$ref` into its relevant parts */
var splitRef = /^([\w+_./:-]+)?(?:#)?\/?((?:[^/]|~0|~1)+)\/?((?:[^/]|~0|~1)+)?\/?((?:[^/]|~0|~1)+)?\/?((?:[^/]|~0|~1)+)?\/?((?:[^/]|~0|~1)+)?\/?((?:[^/]|~0|~1)+)?/;
function deepMap(obj, iterator) {

@@ -33,16 +30,11 @@ return _.transform(obj, function (result, val, key) {

var withoutRef = _.omit(schema, '$ref');
var refs = splitRef.exec(schema['$ref']);
if (!refs) {
return { hasResult: false };
}
var _a = refs[1], jsonRef = _a === void 0 ? id : _a, path = refs.slice(2);
// resolve up to three levels, e.g. `definitions.json#/section/item`, or `#/section/item`, or just `item`
jsonRef = url_1.resolve(id, jsonRef);
var validateFunction = options.ajv.getSchema(jsonRef);
var _a = parseRef(schema['$ref']), _b = _a.schemaId, schemaId = _b === void 0 ? id : _b, path = _a.path;
// schemaId = resolve(id, schemaId);
var validateFunction = options.ajv.getSchema(schemaId);
if (!validateFunction) {
return { hasResult: false };
return { hasResult: false, error: options.ajv.errors };
}
var resolved = _.get(validateFunction.schema, path.filter(function (p) { return p !== undefined; }), {});
var result = _.merge({}, resolved, withoutRef);
return recursiveInstantiate(jsonRef, result, options);
return recursiveInstantiate(schemaId, result, options);
}

@@ -79,8 +71,14 @@ function maybeResolveRefs(id, def, options) {

if (_.has(schema, 'allOf')) {
return {
hasResult: true,
result: _.assign.apply(_, [{}].concat(schema['allOf'].map(function (s) {
return recursiveInstantiate(id, s, options).result;
})))
};
return schema['allOf'].reduce(function (res, s, idx) {
if (!res.hasResult) {
return res;
}
var resolveResult = recursiveInstantiate(id, s, options);
if (!resolveResult.hasResult) {
return res;
}
return _.assign({}, res, {
result: _.assign({}, res.result, resolveResult.result)
});
}, { hasResult: true, result: {} });
}

@@ -100,6 +98,12 @@ switch (schema['type']) {

if (hasDefault || hasRequired) {
var _a = recursiveInstantiate(id, schema['properties'][property], options), hasResult = _a.hasResult, recursiveResult = _a.result;
var _a = recursiveInstantiate(id, schema['properties'][property], options), hasResult = _a.hasResult, recursiveResult = _a.result, error = _a.error;
if (hasResult) {
result[property] = recursiveResult;
}
else {
return {
hasResult: hasResult,
error: error
};
}
}

@@ -125,7 +129,53 @@ }

return {
hasResult: false
hasResult: false,
error: "Unknown type: " + schema['type']
};
}
}
var instantiate = _.curry(function (options, id) {
function buildRef(baseSchemaId, schema, path) {
var schemaId = parseRef(schema.$ref).schemaId;
var refPath = path.length ? "/" + path.join('/') : '';
return schemaId ? "" + schema.$ref + refPath : "" + baseSchemaId + schema.$ref + refPath;
}
function schemaHasProperRef(schema) {
return _.has(schema, '$ref') && Object.keys(schema).length === 1;
}
function normalizeSchemaRef(schemaRef, options) {
var _a = parseRef(schemaRef), _b = _a.schemaId, schemaId = _b === void 0 ? schemaRef : _b, path = _a.path;
var validateFunction = options.ajv.getSchema(schemaId);
if (!validateFunction) {
return schemaRef;
}
var schema = validateFunction.schema;
if (schemaHasProperRef(schema)) {
return normalizeSchemaRef(buildRef(schemaId, schema, path), options);
}
for (var i = 0; i < path.length; ++i) {
schema = schema[path[i]];
if (schemaHasProperRef(schema)) {
return normalizeSchemaRef(buildRef(schemaId, schema, path.slice(i + 1)), options);
}
}
return schemaRef;
}
exports.normalizeSchemaRef = normalizeSchemaRef;
function parsePath(refPath) {
if (refPath.indexOf('/') === 0) {
refPath = refPath.substr(1);
}
return refPath.split('/').map(function (prop) { return prop.replace('~0', '~').replace('~1', '/'); });
}
function parseRef(schemaRef) {
if (schemaRef.indexOf('#') !== -1) {
var _a = schemaRef.split('#'), schemaId = _a[0], path = _a[1];
return schemaId ? { schemaId: schemaId, path: parsePath(path) } : { path: parsePath(path) };
}
else if (schemaRef.indexOf('/') === 0) {
return { path: parsePath(schemaRef) };
}
else {
return { schemaId: schemaRef, path: [] };
}
}
var instantiate = _.curry(function (options, schemaRef) {
if (!options.ajv) {

@@ -138,10 +188,12 @@ return {

options = _.merge({}, defaultOptions, options);
var validateFunction = options.ajv.getSchema(id);
schemaRef = normalizeSchemaRef(schemaRef, options);
var validateFunction = options.ajv.getSchema(schemaRef);
if (!validateFunction) {
return {
hasResult: false,
error: "schema not found: " + id
error: "schema not found: " + schemaRef
};
}
return recursiveInstantiate(id, validateFunction.schema, options);
var schemaId = parseRef(schemaRef).schemaId;
return recursiveInstantiate(schemaId, validateFunction.schema, options);
});

@@ -148,0 +200,0 @@ Object.defineProperty(exports, "__esModule", { value: true });

@@ -64,3 +64,76 @@ "use strict";

},
someObj: {
type: 'object',
properties: {
someProp: {
type: 'string',
default: 'someProp'
},
otherProp: {
$ref: '#/otherProp'
}
},
required: ['someProp', 'otherProp']
},
otherProp: {
type: 'string',
default: 'otherProp'
},
deepSchema: {
one: {
two: {
three: {
four: {
five: {
six: {
seven: {
eight: {
nine: {
ten: {
type: 'string',
default: 'deepValue'
}
}
}
}
}
}
}
}
}
}
}
};
var externalSchema = {
$schema: 'http://json-schema.org/draft-04/schema#',
id: 'externalSchema.json',
external: {
$ref: 'definitions.json#/someObj'
},
deepSchema: {
$ref: 'definitions.json#/deepSchema'
}
};
var allOfSchema = {
$schema: 'http://json-schema.org/draft-04/schema#',
id: 'allOfSchema.json',
allOf: [{
$ref: '#/definitions/innerObj'
}, {
description: 'unknown schema, to be ignored'
}, {
$ref: 'definitions.json#/someObj'
}],
definitions: {
innerObj: {
type: 'object',
properties: {
innerProp: {
type: 'string',
default: 'innerProp'
}
}
}
}
};
var messageSchema = {

@@ -81,2 +154,3 @@ $schema: 'http://json-schema.org/draft-04/schema#',

{
type: 'object',
properties: {

@@ -146,2 +220,25 @@ type: {

};
var resolveRefSchema = {
id: 'resolveRefSchema.json',
definitions: {
first: {
$ref: '#/definitions/second'
},
second: {
title: 'second'
}
}
};
var invalidResolveRefSchema = {
id: 'invalidResolveRefSchema.json',
$ref: '#/definitions/first',
definitions: {
first: {
$ref: '#/definitions/second'
},
second: {
title: 'second'
}
}
};
var defaultAddress = {

@@ -152,7 +249,30 @@ street_address: '100 Main Street',

};
ajv.addSchema([definitionSchema, messageSchema, internalSchema, defaultRefSchema]);
ajv.addSchema([
definitionSchema,
messageSchema,
internalSchema,
defaultRefSchema,
allOfSchema,
externalSchema,
resolveRefSchema,
invalidResolveRefSchema
]);
var ins = instantiator_1.default({ ajv: ajv });
ava_1.default('Should normalize schema ref', function (t) {
t.is(instantiator_1.normalizeSchemaRef('resolveRefSchema.json#/definitions/first', { ajv: ajv }), 'resolveRefSchema.json#/definitions/second');
t.is(instantiator_1.normalizeSchemaRef('invalidResolveRefSchema.json#/definitions/first', { ajv: ajv }), 'invalidResolveRefSchema.json#/definitions/second');
});
ava_1.default('Should return no result for unknown schema', function (t) {
t.is(ins('unknown-schema.json').hasResult, false);
});
ava_1.default('Correctly resolves external ref', function (t) {
t.deepEqual(ins('externalSchema.json#/external').result, { someProp: 'someProp', otherProp: 'otherProp' });
t.is(ins('externalSchema.json#/external/properties/someProp').result, 'someProp');
});
ava_1.default('Resolve deep schema', function (t) {
t.is(ins('definitions.json#/deepSchema/one/two/three/four/five/six/seven/eight/nine/ten').result, 'deepValue');
});
ava_1.default('Resolve external deep schema', function (t) {
t.is(ins('externalSchema.json#/deepSchema/one/two/three/four/five/six/seven/eight/nine/ten').result, 'deepValue');
});
ava_1.default('Object defaults resolve correctly', function (t) {

@@ -244,4 +364,4 @@ ajv.addSchema({

ava_1.default('Instantiate correctly instantiates defaults (externally-referenced schema)', function (t) {
var extMessage = ins('message.json').result;
t.deepEqual(extMessage, {
var result = ins('message.json').result;
t.deepEqual(result, {
header: { version: 2, type: 0, length: 8, title: 'No Name', obj: { objProp: 'text' } },

@@ -251,4 +371,4 @@ });

ava_1.default('Instantiate correctly instantiates defaults (internally-referenced schema)', function (t) {
var intMessage = ins('internalSchema').result;
t.deepEqual(intMessage, { billing_address: defaultAddress, shipping_address: defaultAddress });
var result = ins('internalSchema').result;
t.deepEqual(result, { billing_address: defaultAddress, shipping_address: defaultAddress });
});

@@ -261,2 +381,10 @@ ava_1.default('Instantiate resolves refs in default', function (t) {

});
ava_1.default('Instantiate resolves allOf', function (t) {
var result = ins('allOfSchema.json').result;
t.deepEqual(result, {
innerProp: 'innerProp',
someProp: 'someProp',
otherProp: 'otherProp'
});
});
//# sourceMappingURL=test.js.map
{
"name": "@alexkuz/json-schema-default-instance",
"version": "1.2.2",
"version": "1.2.7",
"description": "Creates an object as an instance of the given schema using its default properties.",

@@ -17,3 +17,3 @@ "main": "index.js",

"dependencies": {
"ajv": "^4.2.0",
"ajv": "^4.10.3",
"lodash": "^4.13.1",

@@ -20,0 +20,0 @@ "url": "^0.11.0"

@@ -23,5 +23,2 @@ import * as _ from 'lodash';

/** Split a `$ref` into its relevant parts */
const splitRef = /^([\w+_./:-]+)?(?:#)?\/?((?:[^/]|~0|~1)+)\/?((?:[^/]|~0|~1)+)?\/?((?:[^/]|~0|~1)+)?\/?((?:[^/]|~0|~1)+)?\/?((?:[^/]|~0|~1)+)?\/?((?:[^/]|~0|~1)+)?/;
function deepMap(obj: any, iterator: Function) {

@@ -53,17 +50,13 @@ return _.transform(obj, (result, val: any, key) => {

let withoutRef = _.omit(schema, '$ref');
let refs = splitRef.exec(schema['$ref']);
if (!refs) { return { hasResult: false }; }
let { schemaId = id, path } = parseRef(schema['$ref']);
// schemaId = resolve(id, schemaId);
let validateFunction = options.ajv.getSchema(schemaId);
let [, jsonRef = id, ...path] = refs;
// resolve up to three levels, e.g. `definitions.json#/section/item`, or `#/section/item`, or just `item`
jsonRef = resolve(id, jsonRef);
let validateFunction = options.ajv.getSchema(jsonRef);
if (!validateFunction) { return { hasResult: false, error: options.ajv.errors }; }
if (!validateFunction) { return { hasResult: false }; }
let resolved = _.get(validateFunction.schema, path.filter(p => p !== undefined), {});
let result = _.merge({}, resolved, withoutRef);
return recursiveInstantiate(jsonRef, result, options);
return recursiveInstantiate(schemaId, result, options);
}

@@ -109,8 +102,17 @@

if (_.has(schema, 'allOf')) {
return {
hasResult: true,
result: _.assign({}, ...schema['allOf'].map(s =>
recursiveInstantiate(id, s, options).result
))
};
return schema['allOf'].reduce((res, s, idx) => {
if (!res.hasResult) {
return res;
}
const resolveResult = recursiveInstantiate(id, s, options);
if (!resolveResult.hasResult) {
return res;
}
return _.assign({}, res, {
result: _.assign({}, res.result, resolveResult.result)
});
}, { hasResult: true, result: {} });
}

@@ -132,5 +134,10 @@

if (hasDefault || hasRequired) {
const { hasResult, result: recursiveResult } = recursiveInstantiate(id, schema['properties'][property], options);
const { hasResult, result: recursiveResult, error } = recursiveInstantiate(id, schema['properties'][property], options);
if (hasResult) {
result[property] = recursiveResult;
} else {
return {
hasResult,
error
};
}

@@ -158,3 +165,4 @@ }

return {
hasResult: false
hasResult: false,
error: `Unknown type: ${schema['type']}`
};

@@ -164,3 +172,61 @@ }

const instantiate = _.curry(function(options: Options, id: string): InstantiateResult {
function buildRef(baseSchemaId: string, schema: any, path: string[]): string {
const { schemaId } = parseRef(schema.$ref);
const refPath = path.length ? `/${path.join('/')}` : '';
return schemaId ? `${schema.$ref}${refPath}` : `${baseSchemaId}${schema.$ref}${refPath}`;
}
function schemaHasProperRef(schema: any): boolean {
return _.has(schema, '$ref') && Object.keys(schema).length === 1;
}
export function normalizeSchemaRef(schemaRef: string, options: Options): string {
let { schemaId = schemaRef, path } = parseRef(schemaRef);
let validateFunction = options.ajv.getSchema(schemaId);
if (!validateFunction) {
return schemaRef;
}
let schema = validateFunction.schema;
if (schemaHasProperRef(schema)) {
return normalizeSchemaRef(buildRef(schemaId, schema, path), options);
}
for (let i = 0; i < path.length; ++i) {
schema = schema[path[i]];
if (schemaHasProperRef(schema)) {
return normalizeSchemaRef(buildRef(schemaId, schema, path.slice(i + 1)), options);
}
}
return schemaRef;
}
interface ParseRefResult {
schemaId?: string,
path: string[]
}
function parsePath(refPath: string): string[] {
if (refPath.indexOf('/') === 0) {
refPath = refPath.substr(1);
}
return refPath.split('/').map(prop => prop.replace('~0', '~').replace('~1', '/'));
}
function parseRef(schemaRef: string): ParseRefResult {
if (schemaRef.indexOf('#') !== -1) {
const [schemaId, path] = schemaRef.split('#');
return schemaId ? { schemaId, path: parsePath(path) } : { path: parsePath(path) };
} else if (schemaRef.indexOf('/') === 0) {
return { path: parsePath(schemaRef) }
} else {
return { schemaId: schemaRef, path: [] };
}
}
const instantiate = _.curry(function(options: Options, schemaRef: string): InstantiateResult {
if (!options.ajv) {

@@ -175,13 +241,17 @@ return {

const validateFunction = options.ajv.getSchema(id);
schemaRef = normalizeSchemaRef(schemaRef, options);
const validateFunction = options.ajv.getSchema(schemaRef);
if (!validateFunction) {
return {
hasResult: false,
error: `schema not found: ${id}`
error: `schema not found: ${schemaRef}`
};
}
return recursiveInstantiate(id, validateFunction.schema, options);
const { schemaId } = parseRef(schemaRef);
return recursiveInstantiate(schemaId, validateFunction.schema, options);
});
export default instantiate;
/* run with `npm test` */
import instantiate from './instantiator';
import instantiate, { normalizeSchemaRef } from './instantiator';
import test from 'ava';

@@ -65,4 +65,79 @@ import * as Ajv from 'ajv';

},
someObj: {
type: 'object',
properties: {
someProp: {
type: 'string',
default: 'someProp'
},
otherProp: {
$ref: '#/otherProp'
}
},
required: ['someProp', 'otherProp']
},
otherProp: {
type: 'string',
default: 'otherProp'
},
deepSchema: {
one: {
two: {
three: {
four: {
five: {
six: {
seven: {
eight: {
nine: {
ten: {
type: 'string',
default: 'deepValue'
}
}
}
}
}
}
}
}
}
}
}
};
const externalSchema = {
$schema: 'http://json-schema.org/draft-04/schema#',
id: 'externalSchema.json',
external: {
$ref: 'definitions.json#/someObj'
},
deepSchema: {
$ref: 'definitions.json#/deepSchema'
}
};
const allOfSchema = {
$schema: 'http://json-schema.org/draft-04/schema#',
id: 'allOfSchema.json',
allOf: [{
$ref: '#/definitions/innerObj'
}, {
description: 'unknown schema, to be ignored'
}, {
$ref: 'definitions.json#/someObj'
}],
definitions: {
innerObj: {
type: 'object',
properties: {
innerProp: {
type: 'string',
default: 'innerProp'
}
}
}
}
}
const messageSchema = {

@@ -83,2 +158,3 @@ $schema: 'http://json-schema.org/draft-04/schema#',

{
type: 'object',
properties: {

@@ -151,2 +227,27 @@ type: {

const resolveRefSchema = {
id: 'resolveRefSchema.json',
definitions: {
first: {
$ref: '#/definitions/second'
},
second: {
title: 'second'
}
}
}
const invalidResolveRefSchema = {
id: 'invalidResolveRefSchema.json',
$ref: '#/definitions/first',
definitions: {
first: {
$ref: '#/definitions/second'
},
second: {
title: 'second'
}
}
}
const defaultAddress = {

@@ -158,5 +259,27 @@ street_address: '100 Main Street',

ajv.addSchema([definitionSchema, messageSchema, internalSchema, defaultRefSchema]);
ajv.addSchema([
definitionSchema,
messageSchema,
internalSchema,
defaultRefSchema,
allOfSchema,
externalSchema,
resolveRefSchema,
invalidResolveRefSchema
]);
let ins = instantiate({ ajv });
test('Should normalize schema ref', t => {
t.is(
normalizeSchemaRef('resolveRefSchema.json#/definitions/first', { ajv }),
'resolveRefSchema.json#/definitions/second'
);
t.is(
normalizeSchemaRef('invalidResolveRefSchema.json#/definitions/first', { ajv }),
'invalidResolveRefSchema.json#/definitions/second'
);
});
test('Should return no result for unknown schema', t => {

@@ -166,2 +289,22 @@ t.is(ins('unknown-schema.json').hasResult, false);

test('Correctly resolves external ref', t => {
t.deepEqual(
ins('externalSchema.json#/external').result,
{ someProp: 'someProp', otherProp: 'otherProp' } as any
);
t.is(
ins('externalSchema.json#/external/properties/someProp').result,
'someProp'
);
});
test('Resolve deep schema', t => {
t.is(ins('definitions.json#/deepSchema/one/two/three/four/five/six/seven/eight/nine/ten').result, 'deepValue');
});
test('Resolve external deep schema', t => {
t.is(ins('externalSchema.json#/deepSchema/one/two/three/four/five/six/seven/eight/nine/ten').result, 'deepValue');
});
test('Object defaults resolve correctly', t => {

@@ -263,4 +406,4 @@ ajv.addSchema({

test('Instantiate correctly instantiates defaults (externally-referenced schema)', t => {
const extMessage = ins('message.json').result;
t.deepEqual(extMessage, {
const { result } = ins('message.json');
t.deepEqual(result, {
header: { version: 2, type: 0, length: 8, title: 'No Name', obj: { objProp: 'text' } },

@@ -271,4 +414,4 @@ } as any);

test('Instantiate correctly instantiates defaults (internally-referenced schema)', t => {
const intMessage = ins('internalSchema').result;
t.deepEqual(intMessage, { billing_address: defaultAddress, shipping_address: defaultAddress } as any);
const { result } = ins('internalSchema');
t.deepEqual(result, { billing_address: defaultAddress, shipping_address: defaultAddress } as any);
});

@@ -283,1 +426,11 @@

});
test('Instantiate resolves allOf', t => {
const { result } = ins('allOfSchema.json');
t.deepEqual(result, {
innerProp: 'innerProp',
someProp: 'someProp',
otherProp: 'otherProp'
} as any);
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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