fast-json-stringify
Advanced tools
Comparing version 5.1.0 to 5.2.0
@@ -216,2 +216,56 @@ 'use strict' | ||
} | ||
}, | ||
{ | ||
name: 'object with const string property', | ||
schema: { | ||
type: 'object', | ||
properties: { | ||
a: { const: 'const string' } | ||
} | ||
}, | ||
input: { a: 'const string' } | ||
}, | ||
{ | ||
name: 'object with const number property', | ||
schema: { | ||
type: 'object', | ||
properties: { | ||
a: { const: 1 } | ||
} | ||
}, | ||
input: { a: 1 } | ||
}, | ||
{ | ||
name: 'object with const bool property', | ||
schema: { | ||
type: 'object', | ||
properties: { | ||
a: { const: true } | ||
} | ||
}, | ||
input: { a: true } | ||
}, | ||
{ | ||
name: 'object with const object property', | ||
schema: { | ||
type: 'object', | ||
properties: { | ||
foo: { const: { bar: 'baz' } } | ||
} | ||
}, | ||
input: { | ||
foo: { bar: 'baz' } | ||
} | ||
}, | ||
{ | ||
name: 'object with const null property', | ||
schema: { | ||
type: 'object', | ||
properties: { | ||
foo: { const: null } | ||
} | ||
}, | ||
input: { | ||
foo: null | ||
} | ||
} | ||
@@ -218,0 +272,0 @@ ] |
196
index.js
@@ -12,3 +12,4 @@ 'use strict' | ||
const Serializer = require('./serializer') | ||
const buildAjv = require('./ajv') | ||
const Validator = require('./validator') | ||
const RefResolver = require('./ref-resolver') | ||
@@ -61,16 +62,8 @@ let largeArraySize = 2e4 | ||
const schemaRef = schemaId + jsonPointer | ||
const schema = refResolver.getSchema(schemaId, jsonPointer) | ||
let ajvSchema | ||
try { | ||
ajvSchema = ajvInstance.getSchema(schemaRef) | ||
} catch (error) { | ||
if (schema === undefined) { | ||
throw new Error(`Cannot find reference "${ref}"`) | ||
} | ||
if (ajvSchema === undefined) { | ||
throw new Error(`Cannot find reference "${ref}"`) | ||
} | ||
const schema = ajvSchema.schema | ||
if (schema.$ref !== undefined) { | ||
@@ -87,8 +80,7 @@ return resolveRef({ schema, schemaId, jsonPointer }, schema.$ref) | ||
let rootSchemaId = null | ||
let ajvInstance = null | ||
let refResolver = null | ||
let validator = null | ||
let contextFunctions = null | ||
function build (schema, options) { | ||
schema = clone(schema) | ||
arrayItemsReferenceSerializersMap.clear() | ||
@@ -100,25 +92,16 @@ objectReferenceSerializersMap.clear() | ||
ajvInstance = buildAjv(options.ajv) | ||
refResolver = new RefResolver() | ||
validator = new Validator(options.ajv) | ||
rootSchemaId = schema.$id || randomUUID() | ||
isValidSchema(schema) | ||
extendDateTimeType(schema) | ||
ajvInstance.addSchema(schema, rootSchemaId) | ||
validator.addSchema(schema, rootSchemaId) | ||
refResolver.addSchema(schema, rootSchemaId) | ||
if (options.schema) { | ||
const externalSchemas = clone(options.schema) | ||
for (const key of Object.keys(externalSchemas)) { | ||
const externalSchema = externalSchemas[key] | ||
isValidSchema(externalSchema, key) | ||
extendDateTimeType(externalSchema) | ||
let schemaKey = externalSchema.$id || key | ||
if (externalSchema.$id !== undefined && externalSchema.$id[0] === '#') { | ||
schemaKey = key + externalSchema.$id // relative URI | ||
} | ||
if (ajvInstance.getSchema(schemaKey) === undefined) { | ||
ajvInstance.addSchema(externalSchema, schemaKey) | ||
} | ||
for (const key of Object.keys(options.schema)) { | ||
isValidSchema(options.schema[key], key) | ||
validator.addSchema(options.schema[key], key) | ||
refResolver.addSchema(options.schema[key], key) | ||
} | ||
@@ -164,3 +147,3 @@ } | ||
const dependenciesName = ['ajv', 'serializer', contextFunctionCode] | ||
const dependenciesName = ['validator', 'serializer', contextFunctionCode] | ||
@@ -172,3 +155,3 @@ if (options.debugMode) { | ||
if (options.mode === 'debug') { | ||
return { code: dependenciesName.join('\n'), ajv: ajvInstance } | ||
return { code: dependenciesName.join('\n'), validator, ajv: validator.ajv } | ||
} | ||
@@ -179,10 +162,11 @@ | ||
const buildStandaloneCode = require('./standalone') | ||
return buildStandaloneCode(options, ajvInstance, contextFunctionCode) | ||
return buildStandaloneCode(options, validator, contextFunctionCode) | ||
} | ||
/* eslint no-new-func: "off" */ | ||
const contextFunc = new Function('ajv', 'serializer', contextFunctionCode) | ||
const stringifyFunc = contextFunc(ajvInstance, serializer) | ||
const contextFunc = new Function('validator', 'serializer', contextFunctionCode) | ||
const stringifyFunc = contextFunc(validator, serializer) | ||
ajvInstance = null | ||
refResolver = null | ||
validator = null | ||
rootSchemaId = null | ||
@@ -351,13 +335,12 @@ contextFunctions = null | ||
let propertyLocation = mergeLocation(propertiesLocation, key) | ||
if (schema.properties[key].$ref) { | ||
propertyLocation = resolveRef(location, schema.properties[key].$ref) | ||
schema.properties[key] = propertyLocation.schema | ||
if (propertyLocation.$ref) { | ||
propertyLocation = resolveRef(location, propertyLocation.$ref) | ||
} | ||
const sanitized = JSON.stringify(key) | ||
const asString = JSON.stringify(sanitized) | ||
// Using obj['key'] !== undefined instead of obj.hasOwnProperty(prop) for perf reasons, | ||
// see https://github.com/mcollina/fast-json-stringify/pull/3 for discussion. | ||
const sanitized = JSON.stringify(key) | ||
const asString = JSON.stringify(sanitized) | ||
code += ` | ||
@@ -371,3 +354,3 @@ if (obj[${sanitized}] !== undefined) { | ||
const defaultValue = schema.properties[key].default | ||
const defaultValue = propertyLocation.schema.default | ||
if (defaultValue !== undefined) { | ||
@@ -487,12 +470,2 @@ code += ` | ||
if (allOfSchema.fjs_type !== undefined) { | ||
if ( | ||
mergedSchema.fjs_type !== undefined && | ||
mergedSchema.fjs_type !== allOfSchema.fjs_type | ||
) { | ||
throw new Error('allOf schemas have different fjs_type values') | ||
} | ||
mergedSchema.fjs_type = allOfSchema.fjs_type | ||
} | ||
if (allOfSchema.allOf !== undefined) { | ||
@@ -505,3 +478,4 @@ mergeAllOfSchema(location, allOfSchema, mergedSchema) | ||
mergedSchema.$id = `merged_${randomUUID()}` | ||
ajvInstance.addSchema(mergedSchema) | ||
validator.addSchema(mergedSchema) | ||
refResolver.addSchema(mergedSchema) | ||
location.schemaId = mergedSchema.$id | ||
@@ -535,3 +509,3 @@ location.jsonPointer = '#' | ||
let code = ` | ||
if (ajv.validate("${ifSchemaRef}", obj)) { | ||
if (validator.validate("${ifSchemaRef}", obj)) { | ||
` | ||
@@ -810,4 +784,4 @@ | ||
let type = schema.type | ||
const nullable = schema.nullable === true | ||
const type = schema.type | ||
const nullable = schema.nullable === true || (Array.isArray(type) && type.includes('null')) | ||
@@ -817,4 +791,11 @@ let code = '' | ||
if (schema.fjs_type === 'string' && schema.format === undefined && Array.isArray(schema.type) && schema.type.length === 2) { | ||
type = 'string' | ||
if ('const' in schema) { | ||
if (nullable) { | ||
code += ` | ||
json += ${input} === null ? 'null' : '${JSON.stringify(schema.const)}' | ||
` | ||
return code | ||
} | ||
code += `json += '${JSON.stringify(schema.const)}'` | ||
return code | ||
} | ||
@@ -827,3 +808,11 @@ | ||
case 'string': { | ||
funcName = nullable ? 'serializer.asStringNullable.bind(serializer)' : 'serializer.asString.bind(serializer)' | ||
if (schema.format === 'date-time') { | ||
funcName = nullable ? 'serializer.asDateTimeNullable.bind(serializer)' : 'serializer.asDateTime.bind(serializer)' | ||
} else if (schema.format === 'date') { | ||
funcName = nullable ? 'serializer.asDateNullable.bind(serializer)' : 'serializer.asDate.bind(serializer)' | ||
} else if (schema.format === 'time') { | ||
funcName = nullable ? 'serializer.asTimeNullable.bind(serializer)' : 'serializer.asTime.bind(serializer)' | ||
} else { | ||
funcName = nullable ? 'serializer.asStringNullable.bind(serializer)' : 'serializer.asString.bind(serializer)' | ||
} | ||
code += `json += ${funcName}(${input})` | ||
@@ -845,11 +834,3 @@ break | ||
case 'object': | ||
if (schema.format === 'date-time') { | ||
funcName = nullable ? 'serializer.asDateTimeNullable.bind(serializer)' : 'serializer.asDateTime.bind(serializer)' | ||
} else if (schema.format === 'date') { | ||
funcName = nullable ? 'serializer.asDateNullable.bind(serializer)' : 'serializer.asDate.bind(serializer)' | ||
} else if (schema.format === 'time') { | ||
funcName = nullable ? 'serializer.asTimeNullable.bind(serializer)' : 'serializer.asTime.bind(serializer)' | ||
} else { | ||
funcName = buildObject(location) | ||
} | ||
funcName = buildObject(location) | ||
code += `json += ${funcName}(${input})` | ||
@@ -872,3 +853,3 @@ break | ||
code += ` | ||
${index === 0 ? 'if' : 'else if'}(ajv.validate("${schemaRef}", ${input})) | ||
${index === 0 ? 'if' : 'else if'}(validator.validate("${schemaRef}", ${input})) | ||
${nestedResult} | ||
@@ -885,15 +866,6 @@ ` | ||
` | ||
} else if ('const' in schema) { | ||
} else { | ||
code += ` | ||
if(ajv.validate(${JSON.stringify(schema)}, ${input})) | ||
json += '${JSON.stringify(schema.const)}' | ||
else | ||
throw new Error(\`Item $\{JSON.stringify(${input})} does not match schema definition.\`) | ||
` | ||
} else if (schema.type === undefined) { | ||
code += ` | ||
json += JSON.stringify(${input}) | ||
` | ||
} else { | ||
throw new Error(`${schema.type} unsupported`) | ||
} | ||
@@ -922,3 +894,14 @@ break | ||
code += ` | ||
${statement}(${input} === null || typeof ${input} === "${type}" || ${input} instanceof RegExp || (typeof ${input} === "object" && Object.hasOwnProperty.call(${input}, "toString"))) | ||
${statement}( | ||
typeof ${input} === "string" || | ||
${input} === null || | ||
${input} instanceof Date || | ||
${input} instanceof RegExp || | ||
( | ||
typeof ${input} === "object" && | ||
typeof ${input}.toString === "function" && | ||
${input}.toString !== Object.prototype.toString && | ||
!(${input} instanceof Date) | ||
) | ||
) | ||
${nestedResult} | ||
@@ -943,13 +926,6 @@ ` | ||
case 'object': { | ||
if (schema.fjs_type) { | ||
code += ` | ||
${statement}(${input} instanceof Date || ${input} === null) | ||
${nestedResult} | ||
` | ||
} else { | ||
code += ` | ||
${statement}(typeof ${input} === "object" || ${input} === null) | ||
${nestedResult} | ||
` | ||
} | ||
code += ` | ||
${statement}(typeof ${input} === "object" || ${input} === null) | ||
${nestedResult} | ||
` | ||
break | ||
@@ -983,30 +959,6 @@ } | ||
// Ajv does not support js date format. In order to properly validate objects containing a date, | ||
// it needs to replace all occurrences of the string date format with a custom keyword fjs_type. | ||
// (see https://github.com/fastify/fast-json-stringify/pull/441) | ||
function extendDateTimeType (schema) { | ||
if (schema === null) return | ||
if (schema.type === 'string') { | ||
schema.fjs_type = 'string' | ||
schema.type = ['string', 'object'] | ||
} else if ( | ||
Array.isArray(schema.type) && | ||
schema.type.includes('string') && | ||
!schema.type.includes('object') | ||
) { | ||
schema.fjs_type = 'string' | ||
schema.type.push('object') | ||
} | ||
for (const property in schema) { | ||
if (typeof schema[property] === 'object') { | ||
extendDateTimeType(schema[property]) | ||
} | ||
} | ||
} | ||
function isEmpty (schema) { | ||
// eslint-disable-next-line | ||
for (var key in schema) { | ||
if (schema.hasOwnProperty(key) && schema[key] !== undefined) { | ||
if (Object.prototype.hasOwnProperty.call(schema, key) && schema[key] !== undefined) { | ||
return false | ||
@@ -1022,7 +974,7 @@ } | ||
module.exports.restore = function ({ code, ajv }) { | ||
module.exports.restore = function ({ code, validator }) { | ||
const serializer = new Serializer() | ||
// eslint-disable-next-line | ||
return (Function.apply(null, ['ajv', 'serializer', code]) | ||
.apply(null, [ajv, serializer])) | ||
return (Function.apply(null, ['validator', 'serializer', code]) | ||
.apply(null, [validator, serializer])) | ||
} |
{ | ||
"name": "fast-json-stringify", | ||
"version": "5.1.0", | ||
"version": "5.2.0", | ||
"description": "Stringify your JSON at max speed", | ||
@@ -36,2 +36,3 @@ "main": "index.js", | ||
"devDependencies": { | ||
"@fastify/pre-commit": "^2.0.2", | ||
"@sinclair/typebox": "^0.24.9", | ||
@@ -42,4 +43,3 @@ "benchmark": "^2.1.4", | ||
"is-my-json-valid": "^2.20.0", | ||
"luxon": "^2.4.0", | ||
"pre-commit": "^1.2.2", | ||
"luxon": "^3.0.1", | ||
"proxyquire": "^2.1.3", | ||
@@ -57,2 +57,3 @@ "semver": "^7.1.0", | ||
"ajv-formats": "^2.1.1", | ||
"fast-deep-equal": "^3.1.3", | ||
"fast-uri": "^2.1.0", | ||
@@ -59,0 +60,0 @@ "rfdc": "^1.2.0" |
@@ -77,2 +77,5 @@ 'use strict' | ||
} | ||
if (typeof date === 'string') { | ||
return '"' + date + '"' | ||
} | ||
throw new Error(`The value "${date}" cannot be converted to a date-time.`) | ||
@@ -90,2 +93,5 @@ } | ||
} | ||
if (typeof date === 'string') { | ||
return '"' + date + '"' | ||
} | ||
throw new Error(`The value "${date}" cannot be converted to a date.`) | ||
@@ -103,2 +109,5 @@ } | ||
} | ||
if (typeof date === 'string') { | ||
return '"' + date + '"' | ||
} | ||
throw new Error(`The value "${date}" cannot be converted to a time.`) | ||
@@ -105,0 +114,0 @@ } |
const fs = require('fs') | ||
const path = require('path') | ||
function buildStandaloneCode (options, ajvInstance, contextFunctionCode) { | ||
function buildStandaloneCode (options, validator, contextFunctionCode) { | ||
const serializerCode = fs.readFileSync(path.join(__dirname, 'serializer.js')).toString() | ||
let buildAjvCode = '' | ||
let defaultAjvSchema = '' | ||
const defaultMeta = ajvInstance.defaultMeta() | ||
const defaultMeta = validator.ajv.defaultMeta() | ||
if (typeof defaultMeta === 'string') { | ||
@@ -14,14 +14,14 @@ defaultAjvSchema = defaultMeta | ||
} | ||
const shouldUseAjv = contextFunctionCode.indexOf('ajv') !== -1 | ||
const shouldUseAjv = contextFunctionCode.indexOf('validator') !== -1 | ||
// we need to export the custom json schema | ||
let ajvSchemasCode = '' | ||
if (shouldUseAjv) { | ||
ajvSchemasCode += `const ajv = buildAjv(${JSON.stringify(options.ajv || {})})\n` | ||
for (const [id, schema] of Object.entries(ajvInstance.schemas)) { | ||
ajvSchemasCode += `const validator = new Validator(${JSON.stringify(options.ajv || {})})\n` | ||
for (const [id, schema] of Object.entries(validator.ajv.schemas)) { | ||
// should skip ajv default schema | ||
if (id === defaultAjvSchema) continue | ||
ajvSchemasCode += `ajv.addSchema(${JSON.stringify(schema.schema)}, "${id}")\n` | ||
ajvSchemasCode += `validator.ajv.addSchema(${JSON.stringify(schema.schema)}, "${id}")\n` | ||
} | ||
buildAjvCode = fs.readFileSync(path.join(__dirname, 'ajv.js')).toString() | ||
buildAjvCode = buildAjvCode.replace("'use strict'", '').replace('module.exports = buildAjv', '') | ||
buildAjvCode = fs.readFileSync(path.join(__dirname, 'validator.js')).toString() | ||
buildAjvCode = buildAjvCode.replace("'use strict'", '').replace('module.exports = SchemaValidator', '') | ||
} | ||
@@ -28,0 +28,0 @@ return ` |
@@ -27,2 +27,180 @@ 'use strict' | ||
test('schema with const string and different input', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { const: 'bar' } | ||
} | ||
} | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify({ | ||
foo: 'baz' | ||
}) | ||
t.equal(output, '{"foo":"bar"}') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
}) | ||
test('schema with const string and different type input', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { const: 'bar' } | ||
} | ||
} | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify({ | ||
foo: 1 | ||
}) | ||
t.equal(output, '{"foo":"bar"}') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
}) | ||
test('schema with const string and no input', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { const: 'bar' } | ||
} | ||
} | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify({}) | ||
t.equal(output, '{}') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
}) | ||
test('schema with const number', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { const: 1 } | ||
} | ||
} | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify({ | ||
foo: 1 | ||
}) | ||
t.equal(output, '{"foo":1}') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
}) | ||
test('schema with const number and different input', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { const: 1 } | ||
} | ||
} | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify({ | ||
foo: 2 | ||
}) | ||
t.equal(output, '{"foo":1}') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
}) | ||
test('schema with const bool', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { const: true } | ||
} | ||
} | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify({ | ||
foo: true | ||
}) | ||
t.equal(output, '{"foo":true}') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
}) | ||
test('schema with const number', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { const: 1 } | ||
} | ||
} | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify({ | ||
foo: 1 | ||
}) | ||
t.equal(output, '{"foo":1}') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
}) | ||
test('schema with const null', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { const: null } | ||
} | ||
} | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify({ | ||
foo: null | ||
}) | ||
t.equal(output, '{"foo":null}') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
}) | ||
test('schema with const array', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { const: [1, 2, 3] } | ||
} | ||
} | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify({ | ||
foo: [1, 2, 3] | ||
}) | ||
t.equal(output, '{"foo":[1,2,3]}') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
}) | ||
test('schema with const object', (t) => { | ||
@@ -48,2 +226,52 @@ t.plan(2) | ||
test('schema with const and null as type', (t) => { | ||
t.plan(4) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { type: ['string', 'null'], const: 'baz' } | ||
} | ||
} | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify({ | ||
foo: null | ||
}) | ||
t.equal(output, '{"foo":null}') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
const output2 = stringify({ foo: 'baz' }) | ||
t.equal(output2, '{"foo":"baz"}') | ||
t.ok(validate(JSON.parse(output2)), 'valid schema') | ||
}) | ||
test('schema with const as nullable', (t) => { | ||
t.plan(4) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { nullable: true, const: 'baz' } | ||
} | ||
} | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify({ | ||
foo: null | ||
}) | ||
t.equal(output, '{"foo":null}') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
const output2 = stringify({ | ||
foo: 'baz' | ||
}) | ||
t.equal(output2, '{"foo":"baz"}') | ||
t.ok(validate(JSON.parse(output2)), 'valid schema') | ||
}) | ||
test('schema with const and invalid object', (t) => { | ||
@@ -60,11 +288,10 @@ t.plan(2) | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
try { | ||
stringify({ | ||
foo: { foo: 'baz' } | ||
}) | ||
} catch (err) { | ||
t.match(err.message, /^Item .* does not match schema definition/, 'Given object has invalid const value') | ||
t.ok(err) | ||
} | ||
const result = stringify({ | ||
foo: { foo: 'baz' } | ||
}) | ||
t.equal(result, '{"foo":{"foo":"bar"}}') | ||
t.ok(validate(JSON.parse(result)), 'valid schema') | ||
}) |
@@ -5,3 +5,5 @@ 'use strict' | ||
const fjs = require('..') | ||
const Ajv = require('ajv').default | ||
const Validator = require('../validator') | ||
@@ -22,3 +24,3 @@ function build (opts) { | ||
test('activate debug mode', t => { | ||
t.plan(3) | ||
t.plan(4) | ||
const debugMode = build({ debugMode: true }) | ||
@@ -28,2 +30,3 @@ | ||
t.ok(debugMode.ajv instanceof Ajv) | ||
t.ok(debugMode.validator instanceof Validator) | ||
t.type(debugMode.code, 'string') | ||
@@ -33,3 +36,3 @@ }) | ||
test('activate debug mode truthy', t => { | ||
t.plan(3) | ||
t.plan(4) | ||
@@ -41,6 +44,7 @@ const debugMode = build({ debugMode: 'yes' }) | ||
t.ok(debugMode.ajv instanceof Ajv) | ||
t.ok(debugMode.validator instanceof Validator) | ||
}) | ||
test('to string auto-consistent', t => { | ||
t.plan(4) | ||
t.plan(5) | ||
const debugMode = build({ debugMode: 1 }) | ||
@@ -51,2 +55,3 @@ | ||
t.ok(debugMode.ajv instanceof Ajv) | ||
t.ok(debugMode.validator instanceof Validator) | ||
@@ -59,3 +64,3 @@ const compiled = fjs.restore(debugMode) | ||
test('to string auto-consistent with ajv', t => { | ||
t.plan(4) | ||
t.plan(5) | ||
@@ -79,2 +84,3 @@ const debugMode = fjs({ | ||
t.ok(debugMode.ajv instanceof Ajv) | ||
t.ok(debugMode.validator instanceof Validator) | ||
@@ -81,0 +87,0 @@ const compiled = fjs.restore(debugMode) |
@@ -447,1 +447,98 @@ 'use strict' | ||
}) | ||
test('nullable type in the schema', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: ['object', 'null'], | ||
properties: { | ||
foo: { | ||
type: 'string' | ||
} | ||
} | ||
} | ||
const stringify = build(schema) | ||
const data = { foo: 'bar' } | ||
t.same(stringify(data), JSON.stringify(data)) | ||
t.same(stringify(null), JSON.stringify(null)) | ||
}) | ||
test('throw an error if the value doesn\'t match the type', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
additionalProperties: false, | ||
required: ['data'], | ||
properties: { | ||
data: { | ||
type: 'array', | ||
minItems: 1, | ||
items: { | ||
oneOf: [ | ||
{ | ||
type: 'string' | ||
}, | ||
{ | ||
type: 'number' | ||
} | ||
] | ||
} | ||
} | ||
} | ||
} | ||
const stringify = build(schema) | ||
const validData = { data: [1, 'testing'] } | ||
t.equal(stringify(validData), JSON.stringify(validData)) | ||
const invalidData = { data: [false, 'testing'] } | ||
t.throws(() => stringify(invalidData)) | ||
}) | ||
test('nullable value in oneOf', (t) => { | ||
t.plan(1) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
data: { | ||
oneOf: [ | ||
{ | ||
type: 'array', | ||
items: { | ||
type: 'object', | ||
properties: { | ||
id: { type: 'integer', minimum: 1 } | ||
}, | ||
additionalProperties: false, | ||
required: ['id'] | ||
} | ||
}, | ||
{ | ||
type: 'array', | ||
items: { | ||
type: 'object', | ||
properties: { | ||
job: { type: 'string', nullable: true } | ||
}, | ||
additionalProperties: false, | ||
required: ['job'] | ||
} | ||
} | ||
] | ||
} | ||
}, | ||
required: ['data'], | ||
additionalProperties: false | ||
} | ||
const stringify = build(schema) | ||
const data = { data: [{ job: null }] } | ||
t.equal(stringify(data), JSON.stringify(data)) | ||
}) |
@@ -1956,1 +1956,29 @@ 'use strict' | ||
}) | ||
test('nested schema should overwrite anchor scope', (t) => { | ||
t.plan(2) | ||
const externalSchema = { | ||
root: { | ||
$id: 'root', | ||
definitions: { | ||
subschema: { | ||
$id: 'subschema', | ||
definitions: { | ||
anchorSchema: { | ||
$id: '#anchor', | ||
type: 'string' | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
const data = 'test' | ||
const stringify = build({ $ref: 'subschema#anchor' }, { schema: externalSchema }) | ||
const output = stringify(data) | ||
t.equal(output, JSON.stringify(data)) | ||
t.throws(() => build({ $ref: 'root#anchor' }, { schema: externalSchema })) | ||
}) |
@@ -441,2 +441,31 @@ 'use strict' | ||
test('class instance that is simultaneously a string and a json', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
simultaneously: { | ||
type: ['string', 'object'], | ||
properties: { | ||
foo: { type: 'string' } | ||
} | ||
} | ||
} | ||
} | ||
class Test { | ||
toString () { return 'hello' } | ||
} | ||
const likeObjectId = new Test() | ||
const stringify = build(schema) | ||
const valueStr = stringify({ simultaneously: likeObjectId }) | ||
t.equal(valueStr, '{"simultaneously":"hello"}') | ||
const valueObj = stringify({ simultaneously: { foo: likeObjectId } }) | ||
t.equal(valueObj, '{"simultaneously":{"foo":"hello"}}') | ||
}) | ||
test('should throw an error when type is array and object is null', (t) => { | ||
@@ -443,0 +472,0 @@ t.plan(1) |
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
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
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
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
328413
77
12261
6
+ Addedfast-deep-equal@^3.1.3