fast-json-stringify
Advanced tools
Comparing version 5.5.0 to 5.6.0
@@ -218,2 +218,23 @@ 'use strict' | ||
{ | ||
name: 'simple object', | ||
schema: { | ||
title: 'Example Schema', | ||
type: 'object', | ||
properties: { | ||
firstName: { | ||
type: 'string' | ||
}, | ||
lastName: { | ||
type: ['string', 'null'] | ||
}, | ||
age: { | ||
description: 'Age in years', | ||
type: 'integer', | ||
minimum: 0 | ||
} | ||
} | ||
}, | ||
input: { firstName: 'Max', lastName: 'Power', age: 22 } | ||
}, | ||
{ | ||
name: 'object with const string property', | ||
@@ -220,0 +241,0 @@ schema: { |
253
index.js
@@ -17,2 +17,10 @@ 'use strict' | ||
let largeArrayMechanism = 'default' | ||
const validRoundingMethods = [ | ||
'floor', | ||
'ceil', | ||
'round', | ||
'trunc' | ||
] | ||
const validLargeArrayMechanisms = [ | ||
@@ -23,9 +31,3 @@ 'default', | ||
const addComma = ` | ||
if (addComma) { | ||
json += ',' | ||
} else { | ||
addComma = true | ||
} | ||
` | ||
const addComma = '!addComma && (addComma = true) || (json += \',\')' | ||
@@ -46,3 +48,3 @@ function isValidSchema (schema, name) { | ||
function resolveRef (location, ref) { | ||
function resolveRef (context, location, ref) { | ||
let hashIndex = ref.indexOf('#') | ||
@@ -56,3 +58,3 @@ if (hashIndex === -1) { | ||
const schema = refResolver.getSchema(schemaId, jsonPointer) | ||
const schema = context.refResolver.getSchema(schemaId, jsonPointer) | ||
@@ -65,3 +67,3 @@ if (schema === undefined) { | ||
if (schema.$ref !== undefined) { | ||
return resolveRef(newLocation, schema.$ref) | ||
return resolveRef(context, newLocation, schema.$ref) | ||
} | ||
@@ -72,27 +74,23 @@ | ||
const contextFunctionsNamesBySchema = new Map() | ||
let rootSchemaId = null | ||
let refResolver = null | ||
let contextFunctions = null | ||
let validatorSchemasIds = null | ||
function build (schema, options) { | ||
contextFunctionsNamesBySchema.clear() | ||
isValidSchema(schema) | ||
contextFunctions = [] | ||
validatorSchemasIds = new Set() | ||
options = options || {} | ||
refResolver = new RefResolver() | ||
const context = { | ||
functions: [], | ||
functionsCounter: 0, | ||
functionsNamesBySchema: new Map(), | ||
options, | ||
refResolver: new RefResolver(), | ||
rootSchemaId: schema.$id || randomUUID(), | ||
validatorSchemasIds: new Set() | ||
} | ||
rootSchemaId = schema.$id || randomUUID() | ||
context.refResolver.addSchema(schema, context.rootSchemaId) | ||
isValidSchema(schema) | ||
refResolver.addSchema(schema, rootSchemaId) | ||
if (options.schema) { | ||
for (const key of Object.keys(options.schema)) { | ||
isValidSchema(options.schema[key], key) | ||
refResolver.addSchema(options.schema[key], key) | ||
context.refResolver.addSchema(options.schema[key], key) | ||
} | ||
@@ -102,3 +100,3 @@ } | ||
if (options.rounding) { | ||
if (!['floor', 'ceil', 'round'].includes(options.rounding)) { | ||
if (!validRoundingMethods.includes(options.rounding)) { | ||
throw new Error(`Unsupported integer rounding method ${options.rounding}`) | ||
@@ -117,13 +115,31 @@ } | ||
if (options.largeArraySize) { | ||
if (!Number.isNaN(Number.parseInt(options.largeArraySize, 10))) { | ||
if (typeof options.largeArraySize === 'string' && Number.isFinite(Number.parseInt(options.largeArraySize, 10))) { | ||
largeArraySize = Number.parseInt(options.largeArraySize, 10) | ||
} else if (typeof options.largeArraySize === 'number' && Number.isInteger(options.largeArraySize)) { | ||
largeArraySize = options.largeArraySize | ||
} else if (typeof options.largeArraySize === 'bigint') { | ||
largeArraySize = Number(options.largeArraySize) | ||
} else { | ||
throw new Error(`Unsupported large array size. Expected integer-like, got ${options.largeArraySize}`) | ||
throw new Error(`Unsupported large array size. Expected integer-like, got ${typeof options.largeArraySize} with value ${options.largeArraySize}`) | ||
} | ||
} | ||
const location = new Location(schema, rootSchemaId) | ||
const code = buildValue(location, 'input') | ||
const location = new Location(schema, context.rootSchemaId) | ||
const code = buildValue(context, location, 'input') | ||
const contextFunctionCode = ` | ||
let contextFunctionCode | ||
// If we have only the invocation of the 'anonymous0' function, we would | ||
// basically just wrap the 'anonymous0' function in the 'main' function and | ||
// and the overhead of the intermediate variabe 'json'. We can avoid the | ||
// wrapping and the unnecessary memory allocation by aliasing 'anonymous0' to | ||
// 'main' | ||
if (code === 'json += anonymous0(input)') { | ||
contextFunctionCode = ` | ||
${context.functions.join('\n')} | ||
const main = anonymous0 | ||
return main | ||
` | ||
} else { | ||
contextFunctionCode = ` | ||
function main (input) { | ||
@@ -134,5 +150,6 @@ let json = '' | ||
} | ||
${contextFunctions.join('\n')} | ||
${context.functions.join('\n')} | ||
return main | ||
` | ||
` | ||
} | ||
@@ -142,7 +159,7 @@ const serializer = new Serializer(options) | ||
for (const schemaId of validatorSchemasIds) { | ||
const schema = refResolver.getSchema(schemaId) | ||
for (const schemaId of context.validatorSchemasIds) { | ||
const schema = context.refResolver.getSchema(schemaId) | ||
validator.addSchema(schema, schemaId) | ||
const dependencies = refResolver.getSchemaDependencies(schemaId) | ||
const dependencies = context.refResolver.getSchemaDependencies(schemaId) | ||
for (const [schemaId, schema] of Object.entries(dependencies)) { | ||
@@ -153,4 +170,2 @@ validator.addSchema(schema, schemaId) | ||
const dependenciesName = ['validator', 'serializer', contextFunctionCode] | ||
if (options.debugMode) { | ||
@@ -164,3 +179,3 @@ options.mode = 'debug' | ||
serializer, | ||
code: dependenciesName.join('\n'), | ||
code: `validator\nserializer\n${contextFunctionCode}`, | ||
ajv: validator.ajv | ||
@@ -172,3 +187,3 @@ } | ||
// lazy load | ||
const isValidatorUsed = validatorSchemasIds.size > 0 | ||
const isValidatorUsed = context.validatorSchemasIds.size > 0 | ||
const buildStandaloneCode = require('./lib/standalone') | ||
@@ -182,8 +197,2 @@ return buildStandaloneCode(options, validator, isValidatorUsed, contextFunctionCode) | ||
refResolver = null | ||
rootSchemaId = null | ||
contextFunctions = null | ||
validatorSchemasIds = null | ||
contextFunctionsNamesBySchema.clear() | ||
return stringifyFunc | ||
@@ -193,8 +202,8 @@ } | ||
const objectKeywords = [ | ||
'properties', | ||
'required', | ||
'additionalProperties', | ||
'patternProperties', | ||
'maxProperties', | ||
'minProperties', | ||
'required', | ||
'properties', | ||
'patternProperties', | ||
'additionalProperties', | ||
'dependencies' | ||
@@ -250,3 +259,3 @@ ] | ||
function buildExtraObjectPropertiesSerializer (location) { | ||
function buildExtraObjectPropertiesSerializer (context, location) { | ||
const schema = location.schema | ||
@@ -273,9 +282,2 @@ const propertiesKeys = Object.keys(schema.properties || {}) | ||
try { | ||
RegExp(propertyKey) | ||
} catch (err) { | ||
const jsonPointer = propertyLocation.getSchemaRef() | ||
throw new Error(`${err.message}. Invalid pattern property regexp key ${propertyKey} at ${jsonPointer}`) | ||
} | ||
code += ` | ||
@@ -285,3 +287,3 @@ if (/${propertyKey.replace(/\\*\//g, '\\/')}/.test(key)) { | ||
json += serializer.asString(key) + ':' | ||
${buildValue(propertyLocation, 'value')} | ||
${buildValue(context, propertyLocation, 'value')} | ||
continue | ||
@@ -307,3 +309,3 @@ } | ||
json += serializer.asString(key) + ':' | ||
${buildValue(propertyLocation, 'value')} | ||
${buildValue(context, propertyLocation, 'value')} | ||
` | ||
@@ -319,3 +321,3 @@ } | ||
function buildInnerObject (location) { | ||
function buildInnerObject (context, location) { | ||
const schema = location.schema | ||
@@ -330,7 +332,6 @@ const required = schema.required || [] | ||
if (propertyLocation.schema.$ref) { | ||
propertyLocation = resolveRef(location, propertyLocation.schema.$ref) | ||
propertyLocation = resolveRef(context, location, propertyLocation.schema.$ref) | ||
} | ||
const sanitized = JSON.stringify(key) | ||
const asString = JSON.stringify(sanitized) | ||
@@ -343,6 +344,6 @@ // Using obj['key'] !== undefined instead of obj.hasOwnProperty(prop) for perf reasons, | ||
${addComma} | ||
json += ${asString} + ':' | ||
json += ${JSON.stringify(sanitized + ':')} | ||
` | ||
code += buildValue(propertyLocation, `obj[${JSON.stringify(key)}]`) | ||
code += buildValue(context, propertyLocation, `obj[${sanitized}]`) | ||
@@ -354,3 +355,3 @@ const defaultValue = propertyLocation.schema.default | ||
${addComma} | ||
json += ${asString} + ':' + ${JSON.stringify(JSON.stringify(defaultValue))} | ||
json += ${JSON.stringify(sanitized + ':' + JSON.stringify(defaultValue))} | ||
` | ||
@@ -375,3 +376,3 @@ } else if (required.includes(key)) { | ||
if (schema.patternProperties || schema.additionalProperties) { | ||
code += buildExtraObjectPropertiesSerializer(location) | ||
code += buildExtraObjectPropertiesSerializer(context, location) | ||
} | ||
@@ -382,3 +383,3 @@ | ||
function mergeAllOfSchema (location, schema, mergedSchema) { | ||
function mergeAllOfSchema (context, location, schema, mergedSchema) { | ||
const allOfLocation = location.getPropertyLocation('allOf') | ||
@@ -391,3 +392,3 @@ | ||
const allOfSchemaLocation = allOfLocation.getPropertyLocation(i) | ||
allOfSchema = resolveRef(allOfSchemaLocation, allOfSchema.$ref).schema | ||
allOfSchema = resolveRef(context, allOfSchemaLocation, allOfSchema.$ref).schema | ||
} | ||
@@ -473,3 +474,3 @@ | ||
if (allOfSchema.allOf !== undefined) { | ||
mergeAllOfSchema(location, allOfSchema, mergedSchema) | ||
mergeAllOfSchema(context, location, allOfSchema, mergedSchema) | ||
} | ||
@@ -480,8 +481,8 @@ } | ||
mergedSchema.$id = `merged_${randomUUID()}` | ||
refResolver.addSchema(mergedSchema) | ||
context.refResolver.addSchema(mergedSchema) | ||
location.addMergedSchema(mergedSchema, mergedSchema.$id) | ||
} | ||
function addIfThenElse (location, input) { | ||
validatorSchemasIds.add(location.getSchemaId()) | ||
function addIfThenElse (context, location, input) { | ||
context.validatorSchemasIds.add(location.getSchemaId()) | ||
@@ -507,5 +508,5 @@ const schema = merge({}, location.schema) | ||
if (validator.validate("${ifSchemaRef}", ${input})) { | ||
${buildValue(thenLocation, input)} | ||
${buildValue(context, thenLocation, input)} | ||
} else { | ||
${buildValue(elseLocation, input)} | ||
${buildValue(context, elseLocation, input)} | ||
} | ||
@@ -522,15 +523,15 @@ ` | ||
function buildObject (location) { | ||
function buildObject (context, location) { | ||
const schema = location.schema | ||
if (contextFunctionsNamesBySchema.has(schema)) { | ||
return contextFunctionsNamesBySchema.get(schema) | ||
if (context.functionsNamesBySchema.has(schema)) { | ||
return context.functionsNamesBySchema.get(schema) | ||
} | ||
const functionName = generateFuncName() | ||
contextFunctionsNamesBySchema.set(schema, functionName) | ||
const functionName = generateFuncName(context) | ||
context.functionsNamesBySchema.set(schema, functionName) | ||
let schemaRef = location.getSchemaRef() | ||
if (schemaRef.startsWith(rootSchemaId)) { | ||
schemaRef = schemaRef.replace(rootSchemaId, '') | ||
if (schemaRef.startsWith(context.rootSchemaId)) { | ||
schemaRef = schemaRef.replace(context.rootSchemaId, '') | ||
} | ||
@@ -544,19 +545,18 @@ | ||
functionCode += ` | ||
var obj = ${toJSON('input')} | ||
var json = '{' | ||
var addComma = false | ||
const obj = ${toJSON('input')} | ||
let json = '{' | ||
let addComma = false | ||
` | ||
functionCode += buildInnerObject(location) | ||
functionCode += buildInnerObject(context, location) | ||
functionCode += ` | ||
json += '}' | ||
return json | ||
return json + '}' | ||
} | ||
` | ||
contextFunctions.push(functionCode) | ||
context.functions.push(functionCode) | ||
return functionName | ||
} | ||
function buildArray (location) { | ||
function buildArray (context, location) { | ||
const schema = location.schema | ||
@@ -568,3 +568,3 @@ | ||
if (itemsLocation.schema.$ref) { | ||
itemsLocation = resolveRef(itemsLocation, itemsLocation.schema.$ref) | ||
itemsLocation = resolveRef(context, itemsLocation, itemsLocation.schema.$ref) | ||
} | ||
@@ -574,12 +574,12 @@ | ||
if (contextFunctionsNamesBySchema.has(schema)) { | ||
return contextFunctionsNamesBySchema.get(schema) | ||
if (context.functionsNamesBySchema.has(schema)) { | ||
return context.functionsNamesBySchema.get(schema) | ||
} | ||
const functionName = generateFuncName() | ||
contextFunctionsNamesBySchema.set(schema, functionName) | ||
const functionName = generateFuncName(context) | ||
context.functionsNamesBySchema.set(schema, functionName) | ||
let schemaRef = location.getSchemaRef() | ||
if (schemaRef.startsWith(rootSchemaId)) { | ||
schemaRef = schemaRef.replace(rootSchemaId, '') | ||
if (schemaRef.startsWith(context.rootSchemaId)) { | ||
schemaRef = schemaRef.replace(context.rootSchemaId, '') | ||
} | ||
@@ -594,3 +594,3 @@ | ||
if (!Array.isArray(obj)) { | ||
throw new TypeError(\`The value '$\{obj}' does not match schema definition.\`) | ||
throw new TypeError(\`The value of '${schemaRef}' does not match schema definition.\`) | ||
} | ||
@@ -600,3 +600,3 @@ const arrayLength = obj.length | ||
if (!schema.additionalItems) { | ||
if (!schema.additionalItems && Array.isArray(itemsSchema)) { | ||
functionCode += ` | ||
@@ -624,3 +624,3 @@ if (arrayLength > ${itemsSchema.length}) { | ||
const item = itemsSchema[i] | ||
const tmpRes = buildValue(itemsLocation.getPropertyLocation(i), `obj[${i}]`) | ||
const tmpRes = buildValue(context, itemsLocation.getPropertyLocation(i), `obj[${i}]`) | ||
functionCode += ` | ||
@@ -645,4 +645,3 @@ if (${i} < arrayLength) { | ||
for (let i = ${itemsSchema.length}; i < arrayLength; i++) { | ||
let json = JSON.stringify(obj[i]) | ||
jsonOutput += json | ||
jsonOutput += JSON.stringify(obj[i]) | ||
if (i < arrayLength - 1) { | ||
@@ -654,3 +653,3 @@ jsonOutput += ',' | ||
} else { | ||
const code = buildValue(itemsLocation, 'obj[i]') | ||
const code = buildValue(context, itemsLocation, 'obj[i]') | ||
functionCode += ` | ||
@@ -671,3 +670,3 @@ for (let i = 0; i < arrayLength; i++) { | ||
contextFunctions.push(functionCode) | ||
context.functions.push(functionCode) | ||
return functionName | ||
@@ -713,8 +712,7 @@ } | ||
let genFuncNameCounter = 0 | ||
function generateFuncName () { | ||
return 'anonymous' + genFuncNameCounter++ | ||
function generateFuncName (context) { | ||
return 'anonymous' + context.functionsCounter++ | ||
} | ||
function buildMultiTypeSerializer (location, input) { | ||
function buildMultiTypeSerializer (context, location, input) { | ||
const schema = location.schema | ||
@@ -727,3 +725,3 @@ const types = schema.type.sort(t1 => t1 === 'null' ? -1 : 1) | ||
location.schema = { ...location.schema, type } | ||
const nestedResult = buildSingleTypeSerializer(location, input) | ||
const nestedResult = buildSingleTypeSerializer(context, location, input) | ||
@@ -779,4 +777,8 @@ const statement = index === 0 ? 'if' : 'else if' | ||
}) | ||
let schemaRef = location.getSchemaRef() | ||
if (schemaRef.startsWith(context.rootSchemaId)) { | ||
schemaRef = schemaRef.replace(context.rootSchemaId, '') | ||
} | ||
code += ` | ||
else throw new Error(\`The value $\{JSON.stringify(${input})} does not match schema definition.\`) | ||
else throw new TypeError(\`The value of '${schemaRef}' does not match schema definition.\`) | ||
` | ||
@@ -787,3 +789,3 @@ | ||
function buildSingleTypeSerializer (location, input) { | ||
function buildSingleTypeSerializer (context, location, input) { | ||
const schema = location.schema | ||
@@ -812,7 +814,7 @@ | ||
case 'object': { | ||
const funcName = buildObject(location) | ||
const funcName = buildObject(context, location) | ||
return `json += ${funcName}(${input})` | ||
} | ||
case 'array': { | ||
const funcName = buildArray(location) | ||
const funcName = buildArray(context, location) | ||
return `json += ${funcName}(${input})` | ||
@@ -854,3 +856,3 @@ } | ||
function buildValue (location, input) { | ||
function buildValue (context, location, input) { | ||
let schema = location.schema | ||
@@ -863,3 +865,3 @@ | ||
if (schema.$ref) { | ||
location = resolveRef(location, schema.$ref) | ||
location = resolveRef(context, location, schema.$ref) | ||
schema = location.schema | ||
@@ -876,7 +878,7 @@ } | ||
if (schema.if && schema.then) { | ||
return addIfThenElse(location, input) | ||
return addIfThenElse(context, location, input) | ||
} | ||
if (schema.allOf) { | ||
mergeAllOfSchema(location, schema, clone(schema)) | ||
mergeAllOfSchema(context, location, schema, clone(schema)) | ||
schema = location.schema | ||
@@ -890,3 +892,3 @@ } | ||
if (type === undefined && (schema.anyOf || schema.oneOf)) { | ||
validatorSchemasIds.add(location.getSchemaId()) | ||
context.validatorSchemasIds.add(location.getSchemaId()) | ||
@@ -899,3 +901,3 @@ const type = schema.anyOf ? 'anyOf' : 'oneOf' | ||
const schemaRef = optionLocation.getSchemaRef() | ||
const nestedResult = buildValue(optionLocation, input) | ||
const nestedResult = buildValue(context, optionLocation, input) | ||
code += ` | ||
@@ -907,4 +909,9 @@ ${index === 0 ? 'if' : 'else if'}(validator.validate("${schemaRef}", ${input})) | ||
let schemaRef = location.getSchemaRef() | ||
if (schemaRef.startsWith(context.rootSchemaId)) { | ||
schemaRef = schemaRef.replace(context.rootSchemaId, '') | ||
} | ||
code += ` | ||
else throw new Error(\`The value $\{JSON.stringify(${input})} does not match schema definition.\`) | ||
else throw new TypeError(\`The value of '${schemaRef}' does not match schema definition.\`) | ||
` | ||
@@ -926,5 +933,5 @@ return code | ||
} else if (Array.isArray(type)) { | ||
code += buildMultiTypeSerializer(location, input) | ||
code += buildMultiTypeSerializer(context, location, input) | ||
} else { | ||
code += buildSingleTypeSerializer(location, input) | ||
code += buildSingleTypeSerializer(context, location, input) | ||
} | ||
@@ -931,0 +938,0 @@ |
@@ -7,4 +7,4 @@ 'use strict' | ||
module.exports = class Serializer { | ||
constructor (options = {}) { | ||
switch (options.rounding) { | ||
constructor (options) { | ||
switch (options && options.rounding) { | ||
case 'floor': | ||
@@ -19,2 +19,3 @@ this.parseInteger = Math.floor | ||
break | ||
case 'trunc': | ||
default: | ||
@@ -27,13 +28,24 @@ this.parseInteger = Math.trunc | ||
asInteger (i) { | ||
if (typeof i === 'bigint') { | ||
if (typeof i === 'number') { | ||
if (i === Infinity || i === -Infinity) { | ||
throw new Error(`The value "${i}" cannot be converted to an integer.`) | ||
} | ||
if ((i | 0) === i) { | ||
return '' + i | ||
} | ||
if (Number.isNaN(i)) { | ||
throw new Error(`The value "${i}" cannot be converted to an integer.`) | ||
} | ||
return this.parseInteger(i) | ||
} else if (i === null) { | ||
return '0' | ||
} else if (typeof i === 'bigint') { | ||
return i.toString() | ||
} else if (Number.isInteger(i)) { | ||
return '' + i | ||
} else { | ||
/* eslint no-undef: "off" */ | ||
const integer = this.parseInteger(i) | ||
if (Number.isNaN(integer) || !Number.isFinite(integer)) { | ||
if (Number.isFinite(integer)) { | ||
return '' + integer | ||
} else { | ||
throw new Error(`The value "${i}" cannot be converted to an integer.`) | ||
} else { | ||
return '' + integer | ||
} | ||
@@ -44,10 +56,13 @@ } | ||
asNumber (i) { | ||
const num = Number(i) | ||
if (Number.isNaN(num)) { | ||
if (typeof i !== 'number') { | ||
i = Number(i) | ||
} | ||
// NaN !== NaN | ||
if (i !== i) { // eslint-disable-line no-self-compare | ||
throw new Error(`The value "${i}" cannot be converted to a number.`) | ||
} else if (!Number.isFinite(num)) { | ||
return null | ||
} else { | ||
return '' + num | ||
} | ||
if (i === Infinity || i === -Infinity) { | ||
return 'null' | ||
} | ||
return '' + i | ||
} | ||
@@ -93,11 +108,14 @@ | ||
asString (str) { | ||
const quotes = '"' | ||
if (str instanceof Date) { | ||
return quotes + str.toISOString() + quotes | ||
} else if (str === null) { | ||
return quotes + quotes | ||
} else if (str instanceof RegExp) { | ||
str = str.source | ||
} else if (typeof str !== 'string') { | ||
str = str.toString() | ||
if (typeof str !== 'string') { | ||
if (str === null) { | ||
return '""' | ||
} | ||
if (str instanceof Date) { | ||
return '"' + str.toISOString() + '"' | ||
} | ||
if (str instanceof RegExp) { | ||
str = str.source | ||
} else { | ||
str = str.toString() | ||
} | ||
} | ||
@@ -107,6 +125,4 @@ | ||
if (!STR_ESCAPE.test(str)) { | ||
return quotes + str + quotes | ||
} | ||
if (str.length < 42) { | ||
return '"' + str + '"' | ||
} else if (str.length < 42) { | ||
return this.asStringSmall(str) | ||
@@ -113,0 +129,0 @@ } else { |
@@ -28,9 +28,9 @@ const fs = require('fs') | ||
} | ||
const serializerOptions = options && options.rounding ? JSON.stringify({ options: options.rounding }) : '' | ||
return ` | ||
'use strict' | ||
${serializerCode.replace("'use strict'", '').replace('module.exports = ', '')} | ||
${buildAjvCode} | ||
const serializer = new Serializer(${JSON.stringify(options || {})}) | ||
const serializer = new Serializer(${serializerOptions}) | ||
${ajvSchemasCode} | ||
@@ -40,6 +40,5 @@ | ||
module.exports = main | ||
` | ||
module.exports = main` | ||
} | ||
module.exports = buildStandaloneCode |
{ | ||
"name": "fast-json-stringify", | ||
"version": "5.5.0", | ||
"version": "5.6.0", | ||
"description": "Stringify your JSON at max speed", | ||
@@ -15,3 +15,3 @@ "main": "index.js", | ||
"test:typescript": "tsd", | ||
"test:unit": "tap -J test/*.test.js test/**/*.test.js", | ||
"test:unit": "tap", | ||
"test": "npm run test:unit && npm run test:typescript" | ||
@@ -43,9 +43,6 @@ }, | ||
"is-my-json-valid": "^2.20.0", | ||
"luxon": "^3.0.1", | ||
"proxyquire": "^2.1.3", | ||
"semver": "^7.1.0", | ||
"simple-git": "^3.7.1", | ||
"standard": "^17.0.0", | ||
"tap": "^16.0.1", | ||
"tsd": "^0.24.1", | ||
"tsd": "^0.25.0", | ||
"webpack": "^5.40.0" | ||
@@ -52,0 +49,0 @@ }, |
@@ -551,3 +551,3 @@ # fast-json-stringify | ||
The `type: integer` property will be truncated if a floating point is provided. | ||
You can customize this behaviour with the `rounding` option that will accept [`round`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round), [`ceil`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil) or [`floor`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor): | ||
You can customize this behaviour with the `rounding` option that will accept [`round`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round), [`ceil`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil), [`floor`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor) or [`trunc`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc). Default is `trunc`: | ||
@@ -554,0 +554,0 @@ ```js |
'use strict' | ||
const test = require('tap').test | ||
const { DateTime } = require('luxon') | ||
const build = require('..') | ||
process.env.TZ = 'UTC' | ||
test('allOf: combine type and format ', (t) => { | ||
@@ -17,5 +18,5 @@ t.plan(1) | ||
const stringify = build(schema) | ||
const date = new Date() | ||
const date = new Date(1674263005800) | ||
const value = stringify(date) | ||
t.equal(value, `"${DateTime.fromJSDate(date).toFormat('HH:mm:ss')}"`) | ||
t.equal(value, '"01:03:25"') | ||
}) | ||
@@ -486,1 +487,49 @@ | ||
}) | ||
test('allOf: throw Error if types mismatch ', (t) => { | ||
t.plan(1) | ||
const schema = { | ||
allOf: [ | ||
{ type: 'string' }, | ||
{ type: 'number' } | ||
] | ||
} | ||
t.throws(() => build(schema), new Error('allOf schemas have different type values')) | ||
}) | ||
test('allOf: throw Error if format mismatch ', (t) => { | ||
t.plan(1) | ||
const schema = { | ||
allOf: [ | ||
{ format: 'date' }, | ||
{ format: 'time' } | ||
] | ||
} | ||
t.throws(() => build(schema), new Error('allOf schemas have different format values')) | ||
}) | ||
test('allOf: throw Error if nullable mismatch /1', (t) => { | ||
t.plan(1) | ||
const schema = { | ||
allOf: [ | ||
{ nullable: true }, | ||
{ nullable: false } | ||
] | ||
} | ||
t.throws(() => build(schema), new Error('allOf schemas have different nullable values')) | ||
}) | ||
test('allOf: throw Error if nullable mismatch /2', (t) => { | ||
t.plan(1) | ||
const schema = { | ||
allOf: [ | ||
{ nullable: false }, | ||
{ nullable: true } | ||
] | ||
} | ||
t.throws(() => build(schema), new Error('allOf schemas have different nullable values')) | ||
}) |
@@ -155,1 +155,78 @@ 'use strict' | ||
}) | ||
test('should throw a TypeError with the path to the key of the invalid value /1', (t) => { | ||
t.plan(1) | ||
// any on Foo codepath. | ||
const schema = { | ||
anyOf: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
kind: { | ||
type: 'string', | ||
enum: ['Foo'] | ||
}, | ||
value: {} | ||
} | ||
}, | ||
{ | ||
type: 'object', | ||
properties: { | ||
kind: { | ||
type: 'string', | ||
enum: ['Bar'] | ||
}, | ||
value: { | ||
type: 'number' | ||
} | ||
} | ||
} | ||
] | ||
} | ||
const stringify = build(schema) | ||
t.throws(() => stringify({ kind: 'Baz', value: 1 }), new TypeError('The value of \'#\' does not match schema definition.')) | ||
}) | ||
test('should throw a TypeError with the path to the key of the invalid value /2', (t) => { | ||
t.plan(1) | ||
// any on Foo codepath. | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
data: { | ||
anyOf: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
kind: { | ||
type: 'string', | ||
enum: ['Foo'] | ||
}, | ||
value: {} | ||
} | ||
}, | ||
{ | ||
type: 'object', | ||
properties: { | ||
kind: { | ||
type: 'string', | ||
enum: ['Bar'] | ||
}, | ||
value: { | ||
type: 'number' | ||
} | ||
} | ||
} | ||
] | ||
} | ||
} | ||
} | ||
const stringify = build(schema) | ||
t.throws(() => stringify({ data: { kind: 'Baz', value: 1 } }), new TypeError('The value of \'#/properties/data\' does not match schema definition.')) | ||
}) |
'use strict' | ||
const { DateTime } = require('luxon') | ||
const { test } = require('tap') | ||
const build = require('..') | ||
process.env.TZ = 'UTC' | ||
test('object with multiple types field', (t) => { | ||
@@ -522,6 +523,6 @@ t.plan(2) | ||
const data = { | ||
prop: { nestedProp: new Date() } | ||
prop: { nestedProp: new Date(1674263005800) } | ||
} | ||
t.equal(withOneOfStringify(data), `{"prop":{"nestedProp":"${DateTime.fromJSDate(data.prop.nestedProp).toISODate()}"}}`) | ||
t.equal(withOneOfStringify(data), '{"prop":{"nestedProp":"2023-01-21"}}') | ||
}) | ||
@@ -551,6 +552,5 @@ | ||
const data = { | ||
prop: { nestedProp: new Date() } | ||
prop: { nestedProp: new Date(1674263005800) } | ||
} | ||
t.equal(withOneOfStringify(data), `{"prop":{"nestedProp":"${DateTime.fromJSDate(data.prop.nestedProp).toFormat('HH:mm:ss')}"}}`) | ||
t.equal(withOneOfStringify(data), '{"prop":{"nestedProp":"01:03:25"}}') | ||
}) | ||
@@ -557,0 +557,0 @@ |
@@ -6,2 +6,3 @@ 'use strict' | ||
const build = require('..') | ||
const Ajv = require('ajv') | ||
@@ -269,3 +270,3 @@ test('error on invalid largeArrayMechanism', (t) => { | ||
test('array items is a list of schema and additionalItems is false', (t) => { | ||
test('array items is a list of schema and additionalItems is false /1', (t) => { | ||
t.plan(1) | ||
@@ -279,5 +280,3 @@ | ||
items: [ | ||
{ | ||
type: 'string' | ||
} | ||
{ type: 'string' } | ||
], | ||
@@ -290,16 +289,53 @@ additionalItems: false | ||
const stringify = build(schema) | ||
t.throws(() => stringify({ foo: ['foo', 'bar'] }), new Error('Item at 1 does not match schema definition.')) | ||
}) | ||
try { | ||
stringify({ | ||
foo: [ | ||
'foo', | ||
'bar' | ||
] | ||
}) | ||
t.fail() | ||
} catch (error) { | ||
t.ok(/does not match schema definition./.test(error.message)) | ||
test('array items is a list of schema and additionalItems is false /2', (t) => { | ||
t.plan(3) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { | ||
type: 'array', | ||
items: [ | ||
{ type: 'string' }, | ||
{ type: 'string' } | ||
], | ||
additionalItems: false | ||
} | ||
} | ||
} | ||
const stringify = build(schema) | ||
t.throws(() => stringify({ foo: [1, 'bar'] }), new Error('Item at 0 does not match schema definition.')) | ||
t.throws(() => stringify({ foo: ['foo', 1] }), new Error('Item at 1 does not match schema definition.')) | ||
t.throws(() => stringify({ foo: ['foo', 'bar', 'baz'] }), new Error('Item at 2 does not match schema definition.')) | ||
}) | ||
test('array items is a schema and additionalItems is false', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
foo: { | ||
type: 'array', | ||
items: { type: 'string' }, | ||
additionalItems: false | ||
} | ||
} | ||
} | ||
const stringify = build(schema) | ||
// ajv ignores additionalItems if items is not an Array | ||
const ajv = new Ajv({ allErrors: true, strict: false }) | ||
const validate = ajv.compile(schema) | ||
t.same(stringify({ foo: ['foo', 'bar'] }), '{"foo":["foo","bar"]}') | ||
t.equal(validate({ foo: ['foo', 'bar'] }), true) | ||
}) | ||
// https://github.com/fastify/fast-json-stringify/issues/279 | ||
@@ -500,1 +536,84 @@ test('object array with anyOf and symbol', (t) => { | ||
}) | ||
test('error on invalid value for largeArraySize /1', (t) => { | ||
t.plan(1) | ||
t.throws(() => build({ | ||
title: 'large array of null values with default mechanism', | ||
type: 'object', | ||
properties: { | ||
ids: { | ||
type: 'array', | ||
items: { type: 'null' } | ||
} | ||
} | ||
}, { | ||
largeArraySize: 'invalid' | ||
}), Error('Unsupported large array size. Expected integer-like, got string with value invalid')) | ||
}) | ||
test('error on invalid value for largeArraySize /2', (t) => { | ||
t.plan(1) | ||
t.throws(() => build({ | ||
title: 'large array of null values with default mechanism', | ||
type: 'object', | ||
properties: { | ||
ids: { | ||
type: 'array', | ||
items: { type: 'null' } | ||
} | ||
} | ||
}, { | ||
largeArraySize: Infinity | ||
}), Error('Unsupported large array size. Expected integer-like, got number with value Infinity')) | ||
}) | ||
test('error on invalid value for largeArraySize /3', (t) => { | ||
t.plan(1) | ||
t.throws(() => build({ | ||
title: 'large array of null values with default mechanism', | ||
type: 'object', | ||
properties: { | ||
ids: { | ||
type: 'array', | ||
items: { type: 'null' } | ||
} | ||
} | ||
}, { | ||
largeArraySize: [200] | ||
}), Error('Unsupported large array size. Expected integer-like, got object with value 200')) | ||
}) | ||
buildTest({ | ||
title: 'large array of integers with largeArraySize is bigint', | ||
type: 'object', | ||
properties: { | ||
ids: { | ||
type: 'array', | ||
items: { type: 'integer' } | ||
} | ||
} | ||
}, { | ||
ids: new Array(2e4).fill(42) | ||
}, { | ||
largeArraySize: 20000n, | ||
largeArrayMechanism: 'default' | ||
}) | ||
buildTest({ | ||
title: 'large array of integers with largeArraySize is valid string', | ||
type: 'object', | ||
properties: { | ||
ids: { | ||
type: 'array', | ||
items: { type: 'integer' } | ||
} | ||
} | ||
}, { | ||
ids: new Array(1e4).fill(42) | ||
}, { | ||
largeArraySize: '10000', | ||
largeArrayMechanism: 'default' | ||
}) |
'use strict' | ||
const test = require('tap').test | ||
const { DateTime } = require('luxon') | ||
const validator = require('is-my-json-valid') | ||
const build = require('..') | ||
process.env.TZ = 'UTC' | ||
test('render a date in a string as JSON', (t) => { | ||
@@ -15,3 +16,3 @@ t.plan(2) | ||
} | ||
const toStringify = new Date() | ||
const toStringify = new Date(1674263005800) | ||
@@ -34,3 +35,3 @@ const validate = validator(schema) | ||
} | ||
const toStringify = new Date() | ||
const toStringify = new Date(1674263005800) | ||
@@ -54,3 +55,3 @@ const validate = validator(schema) | ||
} | ||
const toStringify = new Date() | ||
const toStringify = new Date(1674263005800) | ||
@@ -73,3 +74,3 @@ const validate = validator(schema) | ||
} | ||
const toStringify = new Date() | ||
const toStringify = new Date(1674263005800) | ||
@@ -80,3 +81,3 @@ const validate = validator(schema) | ||
t.equal(output, `"${DateTime.fromJSDate(toStringify).toISODate()}"`) | ||
t.equal(output, '"2023-01-21"') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
@@ -94,3 +95,3 @@ }) | ||
} | ||
const toStringify = new Date() | ||
const toStringify = new Date(1674263005800) | ||
@@ -101,3 +102,3 @@ const validate = validator(schema) | ||
t.equal(output, `"${DateTime.fromJSDate(toStringify).toISODate()}"`) | ||
t.equal(output, '"2023-01-21"') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
@@ -120,3 +121,3 @@ }) | ||
t.equal(output, `"${DateTime.fromJSDate(toStringify).toISODate()}"`) | ||
t.equal(output, '"2020-01-01"') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
@@ -133,3 +134,3 @@ }) | ||
} | ||
const toStringify = new Date() | ||
const toStringify = new Date(1674263005800) | ||
@@ -143,3 +144,3 @@ const validate = validator(schema) | ||
t.equal(output, `"${DateTime.fromJSDate(toStringify).toFormat('HH:mm:ss')}"`) | ||
t.equal(output, '"01:03:25"') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
@@ -157,3 +158,3 @@ }) | ||
} | ||
const toStringify = new Date() | ||
const toStringify = new Date(1674263005800) | ||
@@ -167,3 +168,3 @@ const validate = validator(schema) | ||
t.equal(output, `"${DateTime.fromJSDate(toStringify).toFormat('HH:mm:ss')}"`) | ||
t.equal(output, '"01:03:25"') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
@@ -180,3 +181,3 @@ }) | ||
} | ||
const midnight = new Date(new Date().setHours(24)) | ||
const midnight = new Date(new Date(1674263005800).setHours(24)) | ||
@@ -190,3 +191,3 @@ const validate = validator(schema) | ||
t.equal(output, `"${DateTime.fromJSDate(midnight).toFormat('HH:mm:ss')}"`) | ||
t.equal(output, '"00:03:25"') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
@@ -212,3 +213,3 @@ }) | ||
t.equal(output, `"${DateTime.fromJSDate(toStringify).toFormat('HH:mm:ss')}"`) | ||
t.equal(output, '"01:01:01"') | ||
t.ok(validate(JSON.parse(output)), 'valid schema') | ||
@@ -230,3 +231,3 @@ }) | ||
} | ||
const toStringify = { date: new Date() } | ||
const toStringify = { date: new Date(1674263005800) } | ||
@@ -403,7 +404,7 @@ const validate = validator(schema) | ||
const date = new Date() | ||
const date = new Date(1674263005800) | ||
const input = { updatedAt: date } | ||
const { output } = serialize(schema, input) | ||
t.equal(output, JSON.stringify({ updatedAt: DateTime.fromJSDate(date).toFormat('HH:mm:ss') })) | ||
t.equal(output, JSON.stringify({ updatedAt: '01:03:25' })) | ||
}) | ||
@@ -423,6 +424,6 @@ | ||
const date = new Date() | ||
const date = new Date(1674263005800) | ||
const { output } = serialize(schema, date) | ||
t.equal(output, `"${DateTime.fromJSDate(date).toFormat('HH:mm:ss')}"`) | ||
t.equal(output, '"01:03:25"') | ||
}) | ||
@@ -518,3 +519,3 @@ | ||
} | ||
const toStringify = new Date() | ||
const toStringify = new Date(1674263005800) | ||
@@ -542,6 +543,6 @@ const stringify = build(schema) | ||
const data = new Date() | ||
const data = new Date(1674263005800) | ||
const result = stringify(data) | ||
t.same(result, `"${DateTime.fromJSDate(data).toISODate()}"`) | ||
t.same(result, '"2023-01-21"') | ||
}) | ||
@@ -567,1 +568,93 @@ | ||
}) | ||
test('should serialize also an invalid string value, even if it is not a valid date', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
title: 'a date in a string', | ||
type: 'string', | ||
format: 'date-time', | ||
nullable: true | ||
} | ||
const toStringify = 'invalid' | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify(toStringify) | ||
t.equal(output, JSON.stringify(toStringify)) | ||
t.not(validate(JSON.parse(output)), 'valid schema') | ||
}) | ||
test('should throw an error if value can not be transformed to date-time', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
title: 'a date in a string', | ||
type: 'string', | ||
format: 'date-time', | ||
nullable: true | ||
} | ||
const toStringify = true | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
t.throws(() => stringify(toStringify), new Error('The value "true" cannot be converted to a date-time.')) | ||
t.not(validate(toStringify)) | ||
}) | ||
test('should throw an error if value can not be transformed to date', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
title: 'a date in a string', | ||
type: 'string', | ||
format: 'date', | ||
nullable: true | ||
} | ||
const toStringify = true | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
t.throws(() => stringify(toStringify), new Error('The value "true" cannot be converted to a date.')) | ||
t.not(validate(toStringify)) | ||
}) | ||
test('should throw an error if value can not be transformed to time', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
title: 'a time in a string', | ||
type: 'string', | ||
format: 'time', | ||
nullable: true | ||
} | ||
const toStringify = true | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
t.throws(() => stringify(toStringify), new Error('The value "true" cannot be converted to a time.')) | ||
t.not(validate(toStringify)) | ||
}) | ||
test('should serialize also an invalid string value, even if it is not a valid time', (t) => { | ||
t.plan(2) | ||
const schema = { | ||
title: 'a time in a string', | ||
type: 'string', | ||
format: 'time', | ||
nullable: true | ||
} | ||
const toStringify = 'invalid' | ||
const validate = validator(schema) | ||
const stringify = build(schema) | ||
const output = stringify(toStringify) | ||
t.equal(output, JSON.stringify(toStringify)) | ||
t.not(validate(JSON.parse(output)), 'valid schema') | ||
}) |
'use strict' | ||
const t = require('tap') | ||
const { DateTime } = require('luxon') | ||
const build = require('..') | ||
process.env.TZ = 'UTC' | ||
const schema = { | ||
@@ -384,5 +385,5 @@ type: 'object', | ||
const date = new Date() | ||
const date = new Date(1674263005800) | ||
t.equal(stringify(date), `"${DateTime.fromJSDate(date).toISODate()}"`) | ||
t.equal(stringify(date), '"2023-01-21"') | ||
t.equal(stringify('Invalid'), '"Invalid"') | ||
@@ -389,0 +390,0 @@ }) |
@@ -48,2 +48,10 @@ 'use strict' | ||
{ input: -45.05, output: '-45' }, | ||
{ input: Math.PI, output: '3', rounding: 'trunc' }, | ||
{ input: 5.0, output: '5', rounding: 'trunc' }, | ||
{ input: null, output: '0', rounding: 'trunc' }, | ||
{ input: 0, output: '0', rounding: 'trunc' }, | ||
{ input: 0.0, output: '0', rounding: 'trunc' }, | ||
{ input: 42, output: '42', rounding: 'trunc' }, | ||
{ input: 1.99999, output: '1', rounding: 'trunc' }, | ||
{ input: -45.05, output: '-45', rounding: 'trunc' }, | ||
{ input: 0.95, output: '1', rounding: 'ceil' }, | ||
@@ -50,0 +58,0 @@ { input: 0.2, output: '1', rounding: 'ceil' }, |
@@ -151,1 +151,19 @@ 'use strict' | ||
}) | ||
test('patternProperties - fail on invalid regex, handled by ajv', (t) => { | ||
t.plan(1) | ||
t.throws(() => build({ | ||
title: 'check array coerce', | ||
type: 'object', | ||
properties: {}, | ||
patternProperties: { | ||
'foo/\\': { | ||
type: 'array', | ||
items: { | ||
type: 'string' | ||
} | ||
} | ||
} | ||
}), new Error('schema is invalid: data/patternProperties must match format "regex"')) | ||
}) |
@@ -2008,1 +2008,74 @@ 'use strict' | ||
}) | ||
test('should throw an Error if two non-identical schemas with same id are provided', (t) => { | ||
t.plan(1) | ||
const schema = { | ||
$id: 'schema', | ||
type: 'object', | ||
allOf: [ | ||
{ | ||
$id: 'base', | ||
type: 'object', | ||
properties: { | ||
name: { | ||
type: 'string' | ||
} | ||
}, | ||
required: [ | ||
'name' | ||
] | ||
}, | ||
{ | ||
$id: 'inner_schema', | ||
type: 'object', | ||
properties: { | ||
union: { | ||
$id: '#id', | ||
anyOf: [ | ||
{ | ||
$id: 'guid', | ||
type: 'string' | ||
}, | ||
{ | ||
$id: 'email', | ||
type: 'string' | ||
} | ||
] | ||
} | ||
}, | ||
required: [ | ||
'union' | ||
] | ||
}, | ||
{ | ||
$id: 'inner_schema', | ||
type: 'object', | ||
properties: { | ||
union: { | ||
$id: '#id', | ||
anyOf: [ | ||
{ | ||
$id: 'guid', | ||
type: 'string' | ||
}, | ||
{ | ||
$id: 'mail', | ||
type: 'string' | ||
} | ||
] | ||
} | ||
}, | ||
required: [ | ||
'union' | ||
] | ||
} | ||
] | ||
} | ||
t.throws(() => build(schema), new Error('There is already another schema with id inner_schema')) | ||
}) |
@@ -485,5 +485,51 @@ 'use strict' | ||
const stringify = build(schema) | ||
t.throws(() => stringify({ arr: null }), new TypeError('The value \'null\' does not match schema definition.')) | ||
t.throws(() => stringify({ arr: null }), new TypeError('The value of \'#/properties/arr\' does not match schema definition.')) | ||
}) | ||
test('should throw an error when type is array and object is not an array', (t) => { | ||
t.plan(1) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
arr: { | ||
type: 'array', | ||
items: { | ||
type: 'number' | ||
} | ||
} | ||
} | ||
} | ||
const stringify = build(schema) | ||
t.throws(() => stringify({ arr: { foo: 'hello' } }), new TypeError('The value of \'#/properties/arr\' does not match schema definition.')) | ||
}) | ||
test('should throw an error when type is array and object is not an array with external schema', (t) => { | ||
t.plan(1) | ||
const schema = { | ||
type: 'object', | ||
properties: { | ||
arr: { | ||
$ref: 'arrayOfNumbers#/definitions/arr' | ||
} | ||
} | ||
} | ||
const externalSchema = { | ||
arrayOfNumbers: { | ||
definitions: { | ||
arr: { | ||
type: 'array', | ||
items: { | ||
type: 'number' | ||
} | ||
} | ||
} | ||
} | ||
} | ||
const stringify = build(schema, { schema: externalSchema }) | ||
t.throws(() => stringify({ arr: { foo: 'hello' } }), new TypeError('The value of \'arrayOfNumbers#/definitions/arr\' does not match schema definition.')) | ||
}) | ||
test('throw an error if none of types matches', (t) => { | ||
@@ -490,0 +536,0 @@ t.plan(1) |
@@ -161,4 +161,6 @@ import Ajv, { Options as AjvOptions } from "ajv" | ||
* Optionally configure how the integer will be rounded | ||
* | ||
* @default 'trunc' | ||
*/ | ||
rounding?: 'ceil' | 'floor' | 'round' | ||
rounding?: 'ceil' | 'floor' | 'round' | 'trunc' | ||
/** | ||
@@ -173,2 +175,18 @@ * @deprecated | ||
mode?: 'debug' | 'standalone' | ||
/** | ||
* Large arrays are defined as arrays containing, by default, `20000` | ||
* elements or more. That value can be adjusted via the option parameter | ||
* `largeArraySize`. | ||
* | ||
* @default 20000 | ||
*/ | ||
largeArraySize?: number | string | BigInt | ||
/** | ||
* Specify the function on how large Arrays should be stringified. | ||
* | ||
* @default 'default' | ||
*/ | ||
largeArrayMechanism?: 'default' | 'json-stringify' | ||
} | ||
@@ -175,0 +193,0 @@ |
@@ -16,2 +16,8 @@ import Ajv from 'ajv' | ||
build(schema2, { rounding: 'ceil' }) | ||
build(schema2, { rounding: 'floor' }) | ||
build(schema2, { rounding: 'round' }) | ||
build(schema2, { rounding: 'trunc' }) | ||
expectError(build(schema2, { rounding: 'invalid' })) | ||
// String schema | ||
@@ -221,1 +227,12 @@ const schema3: Schema = { | ||
expectError(stringify7("a string")); | ||
// largeArrayMechanism | ||
build({}, { largeArrayMechanism: 'json-stringify'} ) | ||
build({}, { largeArrayMechanism: 'default'} ) | ||
expectError(build({} as Schema, { largeArrayMechanism: 'invalid'} )) | ||
build({}, { largeArraySize: 2000 } ) | ||
build({}, { largeArraySize: '2e4' } ) | ||
build({}, { largeArraySize: 2n } ) | ||
expectError(build({} as Schema, { largeArraySize: ['asdf']} )) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
351136
11
79
13029
10