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

@hyperjump/json-schema

Package Overview
Dependencies
Maintainers
1
Versions
96
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@hyperjump/json-schema - npm Package Compare versions

Comparing version 1.3.1 to 1.4.0

annotations/annotated-instance.d.ts

5

bundle/index.js

@@ -73,4 +73,3 @@ import { v4 as uuid } from "uuid";

Validation.collectExternalIds = (schemaUri, externalIds, ast, dynamicAnchors) => {
const nodes = ast[schemaUri][2];
if (externalIds.has(schemaUri) || typeof nodes === "boolean") {
if (externalIds.has(schemaUri) || typeof ast[schemaUri] === "boolean") {
return;

@@ -81,3 +80,3 @@ }

const id = toAbsoluteUri(schemaUri);
for (const [keywordId, , keywordValue] of nodes) {
for (const [keywordId, , keywordValue] of ast[schemaUri]) {
const keyword = getKeyword(keywordId);

@@ -84,0 +83,0 @@

23

lib/keywords/additionalProperties.js

@@ -21,3 +21,3 @@ import * as Schema from "../schema.js";

const interpret = ([propertyNames, propertyNamePatterns, additionalProperties], instance, ast, dynamicAnchors) => {
const interpret = ([propertyNames, propertyNamePatterns, additionalProperties], instance, ast, dynamicAnchors, quiet) => {
if (!Instance.typeOf(instance, "object")) {

@@ -29,9 +29,24 @@ return true;

.filter(([propertyName]) => !propertyNames.includes(propertyName) && !propertyNamePatterns.some((pattern) => pattern.test(propertyName)))
.every(([, property]) => Validation.interpret(additionalProperties, property, ast, dynamicAnchors));
.every(([, property]) => Validation.interpret(additionalProperties, property, ast, dynamicAnchors, quiet));
};
const collectEvaluatedProperties = (keywordValue, instance, ast, dynamicAnchors) => {
return interpret(keywordValue, instance, ast, dynamicAnchors) && [new RegExp("")];
const collectEvaluatedProperties = ([propertyNames, propertyNamePatterns, additionalProperties], instance, ast, dynamicAnchors) => {
if (!Instance.typeOf(instance, "object")) {
return true;
}
const evaluatedPropertyNames = new Set();
for (const [propertyName, property] of Instance.entries(instance)) {
if (!propertyNames.includes(propertyName) && !propertyNamePatterns.some((pattern) => pattern.test(propertyName))) {
if (!Validation.interpret(additionalProperties, property, ast, dynamicAnchors, true)) {
return false;
}
evaluatedPropertyNames.add(propertyName);
}
}
return evaluatedPropertyNames;
};
export default { id, compile, interpret, collectEvaluatedProperties };

@@ -13,4 +13,4 @@ import * as Pact from "@hyperjump/pact";

const interpret = (allOf, instance, ast, dynamicAnchors) => {
return allOf.every((schemaUrl) => Validation.interpret(schemaUrl, instance, ast, dynamicAnchors));
const interpret = (allOf, instance, ast, dynamicAnchors, quiet) => {
return allOf.every((schemaUrl) => Validation.interpret(schemaUrl, instance, ast, dynamicAnchors, quiet));
};

@@ -17,0 +17,0 @@

@@ -13,4 +13,4 @@ import * as Pact from "@hyperjump/pact";

const interpret = (anyOf, instance, ast, dynamicAnchors) => {
const matches = anyOf.filter((schemaUrl) => Validation.interpret(schemaUrl, instance, ast, dynamicAnchors));
const interpret = (anyOf, instance, ast, dynamicAnchors, quiet) => {
const matches = anyOf.filter((schemaUrl) => Validation.interpret(schemaUrl, instance, ast, dynamicAnchors, quiet));
return matches.length > 0;

@@ -17,0 +17,0 @@ };

@@ -23,3 +23,3 @@ import * as Schema from "../schema.js";

const interpret = ({ contains, minContains, maxContains }, instance, ast, dynamicAnchors) => {
const interpret = ({ contains, minContains, maxContains }, instance, ast, dynamicAnchors, quiet) => {
if (!Instance.typeOf(instance, "array") && !Instance.typeOf(instance, "object")) {

@@ -30,3 +30,3 @@ return true;

const matches = Instance.entries(instance).reduce((matches, [, item]) => {
return Validation.interpret(contains, item, ast, dynamicAnchors) ? matches + 1 : matches;
return Validation.interpret(contains, item, ast, dynamicAnchors, quiet) ? matches + 1 : matches;
}, 0);

@@ -36,21 +36,21 @@ return matches >= minContains && matches <= maxContains;

const collectEvaluatedItems = (keywordValue, instance, ast, dynamicAnchors) => {
return interpret(keywordValue, instance, ast, dynamicAnchors)
&& Instance.typeOf(instance, "array")
&& Instance.reduce((matchedIndexes, item, itemIndex) => {
return Validation.interpret(keywordValue.contains, item, ast, dynamicAnchors) ? matchedIndexes.add(itemIndex) : matchedIndexes;
}, new Set(), instance);
};
const collectEvaluatedProperties = (keywordValue, instance, ast, dynamicAnchors) => {
return interpret(keywordValue, instance, ast, dynamicAnchors)
return interpret(keywordValue, instance, ast, dynamicAnchors, true)
&& Instance.typeOf(instance, "object")
&& Instance.entries(instance).reduce((matchedPropertyNames, [propertyName, item]) => {
if (Validation.interpret(keywordValue.contains, item, ast, dynamicAnchors)) {
matchedPropertyNames.push(propertyName);
if (Validation.interpret(keywordValue.contains, item, ast, dynamicAnchors, true)) {
matchedPropertyNames.add(propertyName);
}
return matchedPropertyNames;
}, [], instance);
}, new Set(), instance);
};
const collectEvaluatedItems = (keywordValue, instance, ast, dynamicAnchors) => {
return interpret(keywordValue, instance, ast, dynamicAnchors, true)
&& Instance.typeOf(instance, "array")
&& Instance.reduce((matchedIndexes, item, itemIndex) => {
return Validation.interpret(keywordValue.contains, item, ast, dynamicAnchors, true) ? matchedIndexes.add(itemIndex) : matchedIndexes;
}, new Set(), instance);
};
export default { id, compile, interpret, collectEvaluatedItems, collectEvaluatedProperties };

@@ -1,4 +0,9 @@

import metaData from "./meta-data.js";
import * as Schema from "../schema.js";
export default { id: "https://json-schema.org/keyword/contentSchema", ...metaData };
const id = "https://json-schema.org/keyword/contentSchema";
const compile = (contentSchema) => Schema.uri(contentSchema);
const interpret = () => true;
export default { id, compile, interpret };

@@ -15,7 +15,7 @@ import * as Pact from "@hyperjump/pact";

const interpret = (dependentSchemas, instance, ast, dynamicAnchors) => {
const interpret = (dependentSchemas, instance, ast, dynamicAnchors, quiet) => {
const value = Instance.value(instance);
return !Instance.typeOf(instance, "object") || dependentSchemas.every(([propertyName, dependentSchema]) => {
return !(propertyName in value) || Validation.interpret(dependentSchema, instance, ast, dynamicAnchors);
return !(propertyName in value) || Validation.interpret(dependentSchema, instance, ast, dynamicAnchors, quiet);
});

@@ -25,12 +25,22 @@ };

const collectEvaluatedProperties = (dependentSchemas, instance, ast, dynamicAnchors) => {
return dependentSchemas.reduce((acc, [propertyName, dependentSchema]) => {
if (!acc || !Instance.has(propertyName, instance)) {
return acc;
const value = Instance.value(instance);
if (!Instance.typeOf(instance, "object")) {
return false;
}
const evaluatedPropertyNames = new Set();
for (const [propertyName, dependentSchema] of dependentSchemas) {
if (propertyName in value) {
const propertyNames = Validation.collectEvaluatedProperties(dependentSchema, instance, ast, dynamicAnchors);
if (propertyNames === false) {
return false;
}
propertyNames.forEach(Set.prototype.add.bind(evaluatedPropertyNames));
}
}
const propertyNames = Validation.collectEvaluatedProperties(dependentSchema, instance, ast, dynamicAnchors);
return propertyNames !== false && acc.concat(propertyNames);
}, []);
return evaluatedPropertyNames;
};
export default { id, compile, interpret, collectEvaluatedProperties };

@@ -10,7 +10,7 @@ import * as Schema from "../schema.js";

const interpret = (fragment, instance, ast, dynamicAnchors) => {
const interpret = (fragment, instance, ast, dynamicAnchors, quiet) => {
if (!(fragment in dynamicAnchors)) {
throw Error(`No dynamic anchor found for "${fragment}"`);
}
return Validation.interpret(dynamicAnchors[fragment], instance, ast, dynamicAnchors);
return Validation.interpret(dynamicAnchors[fragment], instance, ast, dynamicAnchors, quiet);
};

@@ -17,0 +17,0 @@

import * as Schema from "../schema.js";
import { getKeywordName, getKeyword } from "../keywords.js";
import { getKeywordName } from "../keywords.js";
import Validation from "./validation.js";

@@ -18,31 +18,24 @@

const interpret = ([guard, block], instance, ast, dynamicAnchors) => {
return guard === undefined || quietInterpretSchema(guard, instance, ast, dynamicAnchors) || Validation.interpret(block, instance, ast, dynamicAnchors);
const interpret = ([ifSchema, elseSchema], instance, ast, dynamicAnchors, quiet) => {
return ifSchema === undefined
|| Validation.interpret(ifSchema, instance, ast, dynamicAnchors, true)
|| Validation.interpret(elseSchema, instance, ast, dynamicAnchors, quiet);
};
// Interpret a schema without events being emitted
const quietInterpretSchema = (url, instance, ast, dynamicAnchors) => {
const nodes = ast[url][2];
return typeof nodes === "boolean" ? nodes : nodes.every(([keywordId, , keywordValue]) => {
return getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors);
});
};
const collectEvaluatedProperties = ([guard, block], instance, ast, dynamicAnchors) => {
if (guard === undefined || quietInterpretSchema(guard, instance, ast, dynamicAnchors)) {
return [];
const collectEvaluatedProperties = ([ifSchema, elseSchema], instance, ast, dynamicAnchors) => {
if (ifSchema === undefined || Validation.interpret(ifSchema, instance, ast, dynamicAnchors, true)) {
return new Set();
}
return Validation.collectEvaluatedProperties(block, instance, ast, dynamicAnchors);
return Validation.collectEvaluatedProperties(elseSchema, instance, ast, dynamicAnchors);
};
const collectEvaluatedItems = ([guard, block], instance, ast, dynamicAnchors) => {
if (guard === undefined || quietInterpretSchema(guard, instance, ast, dynamicAnchors)) {
const collectEvaluatedItems = ([ifSchema, elseSchema], instance, ast, dynamicAnchors) => {
if (ifSchema === undefined || Validation.interpret(ifSchema, instance, ast, dynamicAnchors, true)) {
return new Set();
}
return Validation.collectEvaluatedItems(block, instance, ast, dynamicAnchors);
return Validation.collectEvaluatedItems(elseSchema, instance, ast, dynamicAnchors);
};
export default { id, compile, interpret, collectEvaluatedProperties, collectEvaluatedItems };

@@ -8,4 +8,4 @@ import Validation from "./validation.js";

const interpret = (ifSchema, instance, ast, dynamicAnchors) => {
Validation.interpret(ifSchema, instance, ast, dynamicAnchors);
const interpret = (ifSchema, instance, ast, dynamicAnchors, quiet) => {
Validation.interpret(ifSchema, instance, ast, dynamicAnchors, quiet);
return true;

@@ -12,0 +12,0 @@ };

@@ -17,3 +17,3 @@ import * as Schema from "../schema.js";

const interpret = ([numberOfPrefixItems, items], instance, ast, dynamicAnchors) => {
const interpret = ([numberOfPrefixItems, items], instance, ast, dynamicAnchors, quiet) => {
if (!Instance.typeOf(instance, "array")) {

@@ -23,7 +23,7 @@ return true;

return Instance.every((item, ndx) => ndx < numberOfPrefixItems || Validation.interpret(items, item, ast, dynamicAnchors), instance);
return Instance.every((item, ndx) => ndx < numberOfPrefixItems || Validation.interpret(items, item, ast, dynamicAnchors, quiet), instance);
};
const collectEvaluatedItems = (keywordValue, instance, ast, dynamicAnchors) => {
if (!interpret(keywordValue, instance, ast, dynamicAnchors)) {
if (!interpret(keywordValue, instance, ast, dynamicAnchors, true)) {
return false;

@@ -30,0 +30,0 @@ }

@@ -7,4 +7,4 @@ import Validation from "./validation.js";

const compile = Validation.compile;
const interpret = (not, instance, ast, dynamicAnchors) => !Validation.interpret(not, instance, ast, dynamicAnchors);
const interpret = (not, instance, ast, dynamicAnchors, quiet) => !Validation.interpret(not, instance, ast, dynamicAnchors, quiet);
export default { id, compile, interpret };

@@ -12,6 +12,6 @@ import * as Schema from "../schema.js";

const interpret = (oneOf, instance, ast, dynamicAnchors) => {
const interpret = (oneOf, instance, ast, dynamicAnchors, quiet) => {
let validCount = 0;
for (const schemaUrl of oneOf) {
if (Validation.interpret(schemaUrl, instance, ast, dynamicAnchors)) {
if (Validation.interpret(schemaUrl, instance, ast, dynamicAnchors, quiet)) {
validCount++;

@@ -18,0 +18,0 @@ }

@@ -15,7 +15,7 @@ import * as Pact from "@hyperjump/pact";

const interpret = (patternProperties, instance, ast, dynamicAnchors) => {
const interpret = (patternProperties, instance, ast, dynamicAnchors, quiet) => {
return !Instance.typeOf(instance, "object") || patternProperties.every(([pattern, schemaUrl]) => {
return Instance.entries(instance)
.filter(([propertyName]) => pattern.test(propertyName))
.every(([, propertyValue]) => Validation.interpret(schemaUrl, propertyValue, ast, dynamicAnchors));
.every(([, propertyValue]) => Validation.interpret(schemaUrl, propertyValue, ast, dynamicAnchors, quiet));
});

@@ -25,5 +25,22 @@ };

const collectEvaluatedProperties = (patternProperties, instance, ast, dynamicAnchors) => {
return interpret(patternProperties, instance, ast, dynamicAnchors) && patternProperties.map(([pattern]) => pattern);
if (!Instance.typeOf(instance, "object")) {
return false;
}
const evaluatedPropertyNames = new Set();
for (const [pattern, propertySchema] of patternProperties) {
for (const [propertyName, property] of Instance.entries(instance)) {
if (pattern.test(propertyName)) {
if (!Validation.interpret(propertySchema, property, ast, dynamicAnchors, true)) {
return false;
}
evaluatedPropertyNames.add(propertyName);
}
}
}
return evaluatedPropertyNames;
};
export default { id, compile, interpret, collectEvaluatedProperties };

@@ -16,3 +16,3 @@ import * as Pact from "@hyperjump/pact";

const interpret = (items, instance, ast, dynamicAnchors) => {
const interpret = (items, instance, ast, dynamicAnchors, quiet) => {
if (!Instance.typeOf(instance, "array")) {

@@ -22,9 +22,9 @@ return true;

return Instance.every((item, ndx) => !(ndx in items) || Validation.interpret(items[ndx], item, ast, dynamicAnchors), instance);
return Instance.every((item, ndx) => !(ndx in items) || Validation.interpret(items[ndx], item, ast, dynamicAnchors, quiet), instance);
};
const collectEvaluatedItems = (items, instance, ast, dynamicAnchors) => {
return interpret(items, instance, ast, dynamicAnchors) && new Set(items.map((item, ndx) => ndx));
return interpret(items, instance, ast, dynamicAnchors, true) && new Set(items.map((item, ndx) => ndx));
};
export default { id, compile, interpret, collectEvaluatedItems };

@@ -17,15 +17,27 @@ import * as Pact from "@hyperjump/pact";

const interpret = (properties, instance, ast, dynamicAnchors) => {
const interpret = (properties, instance, ast, dynamicAnchors, quiet) => {
return !Instance.typeOf(instance, "object") || Instance.entries(instance)
.filter(([propertyName]) => propertyName in properties)
.every(([propertyName, schemaUrl]) => Validation.interpret(properties[propertyName], schemaUrl, ast, dynamicAnchors));
.every(([propertyName, schemaUrl]) => Validation.interpret(properties[propertyName], schemaUrl, ast, dynamicAnchors, quiet));
};
const collectEvaluatedProperties = (properties, instance, ast, dynamicAnchors) => {
return interpret(properties, instance, ast, dynamicAnchors) && Object.keys(properties)
.map((propertyName) => new RegExp(`^${escapeRegExp(propertyName)}$`));
if (!Instance.typeOf(instance, "object")) {
return false;
}
const evaluatedPropertyNames = new Set();
for (const [propertyName, property] of Instance.entries(instance)) {
if (propertyName in properties) {
if (!Validation.interpret(properties[propertyName], property, ast, dynamicAnchors, true)) {
return false;
}
evaluatedPropertyNames.add(propertyName);
}
}
return evaluatedPropertyNames;
};
const escapeRegExp = (string) => string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&");
export default { id, compile, interpret, collectEvaluatedProperties };

@@ -26,3 +26,3 @@ import * as Pact from "@hyperjump/pact";

const interpret = (propertyDependencies, instance, ast, dynamicAnchors) => {
const interpret = (propertyDependencies, instance, ast, dynamicAnchors, quiet) => {
return !Instance.typeOf(instance, "object") || Object.entries(propertyDependencies).every(([propertyName, valueMappings]) => {

@@ -32,3 +32,3 @@ const propertyValue = Instance.value(instance)[propertyName];

|| !(propertyValue in valueMappings)
|| Validation.interpret(valueMappings[propertyValue], instance, ast, dynamicAnchors);
|| Validation.interpret(valueMappings[propertyValue], instance, ast, dynamicAnchors, quiet);
});

@@ -35,0 +35,0 @@ };

@@ -11,5 +11,5 @@ import * as Instance from "../instance.js";

return !Instance.typeOf(instance, "object") || Instance.keys(instance)
.every((key) => Validation.interpret(propertyNames, Instance.cons(key), ast, dynamicAnchors));
.every((key) => Validation.interpret(propertyNames, Instance.cons(key), ast, dynamicAnchors, true));
};
export default { id, compile, interpret };
import * as Schema from "../schema.js";
import { getKeywordName, getKeyword } from "../keywords.js";
import { getKeywordName } from "../keywords.js";
import Validation from "./validation.js";

@@ -18,31 +18,24 @@

const interpret = ([guard, block], instance, ast, dynamicAnchors) => {
return guard === undefined || !quietInterpretSchema(guard, instance, ast, dynamicAnchors) || Validation.interpret(block, instance, ast, dynamicAnchors);
const interpret = ([ifSchema, thenSchema], instance, ast, dynamicAnchors, quiet) => {
return ifSchema === undefined
|| !Validation.interpret(ifSchema, instance, ast, dynamicAnchors, true)
|| Validation.interpret(thenSchema, instance, ast, dynamicAnchors, quiet);
};
// Interpret a schema without events being emitted
const quietInterpretSchema = (url, instance, ast, dynamicAnchors) => {
const nodes = ast[url][2];
return typeof nodes === "boolean" ? nodes : nodes.every(([keywordId, , keywordValue]) => {
return getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors);
});
};
const collectEvaluatedProperties = ([guard, block], instance, ast, dynamicAnchors) => {
if (guard === undefined || !quietInterpretSchema(guard, instance, ast, dynamicAnchors)) {
return [];
const collectEvaluatedProperties = ([ifSchema, thenSchema], instance, ast, dynamicAnchors) => {
if (ifSchema === undefined || !Validation.interpret(ifSchema, instance, ast, dynamicAnchors, true)) {
return new Set();
}
return Validation.collectEvaluatedProperties(block, instance, ast, dynamicAnchors);
return Validation.collectEvaluatedProperties(thenSchema, instance, ast, dynamicAnchors);
};
const collectEvaluatedItems = ([guard, block], instance, ast, dynamicAnchors) => {
if (guard === undefined || !quietInterpretSchema(guard, instance, ast, dynamicAnchors)) {
const collectEvaluatedItems = ([ifSchema, thenSchema], instance, ast, dynamicAnchors) => {
if (ifSchema === undefined || !Validation.interpret(ifSchema, instance, ast, dynamicAnchors, true)) {
return new Set();
}
return Validation.collectEvaluatedItems(block, instance, ast, dynamicAnchors);
return Validation.collectEvaluatedItems(thenSchema, instance, ast, dynamicAnchors);
};
export default { id, compile, interpret, collectEvaluatedProperties, collectEvaluatedItems };

@@ -12,3 +12,3 @@ import * as Schema from "../schema.js";

const interpret = ([schemaUrl, unevaluatedItems], instance, ast, dynamicAnchors) => {
const interpret = ([schemaUrl, unevaluatedItems], instance, ast, dynamicAnchors, quiet) => {
if (!Instance.typeOf(instance, "array")) {

@@ -20,3 +20,3 @@ return true;

return itemIndexes === false || Instance.every((item, itemIndex) => {
return itemIndexes.has(itemIndex) || Validation.interpret(unevaluatedItems, Instance.step(itemIndex, instance), ast, dynamicAnchors);
return itemIndexes.has(itemIndex) || Validation.interpret(unevaluatedItems, Instance.step(itemIndex, instance), ast, dynamicAnchors, quiet);
}, instance);

@@ -23,0 +23,0 @@ };

@@ -12,3 +12,3 @@ import * as Schema from "../schema.js";

const interpret = ([schemaUrl, unevaluatedProperties], instance, ast, dynamicAnchors) => {
const interpret = ([schemaUrl, unevaluatedProperties], instance, ast, dynamicAnchors, quiet) => {
if (!Instance.typeOf(instance, "object")) {

@@ -21,10 +21,30 @@ return true;

return !evaluatedPropertyNames || Instance.entries(instance)
.filter(([propertyName]) => !evaluatedPropertyNames.some((pattern) => propertyName.match(pattern)))
.every(([, property]) => Validation.interpret(unevaluatedProperties, property, ast, dynamicAnchors));
.filter(([propertyName]) => !evaluatedPropertyNames.has(propertyName))
.every(([, property]) => Validation.interpret(unevaluatedProperties, property, ast, dynamicAnchors, quiet));
};
const collectEvaluatedProperties = (keywordValue, instance, ast, dynamicAnchors) => {
return interpret(keywordValue, instance, ast, dynamicAnchors) && [new RegExp("")];
const collectEvaluatedProperties = ([schemaUrl, unevaluatedProperties], instance, ast, dynamicAnchors) => {
if (!Instance.typeOf(instance, "object")) {
return true;
}
const evaluatedPropertyNames = Validation.collectEvaluatedProperties(schemaUrl, instance, ast, dynamicAnchors, true);
if (!evaluatedPropertyNames) {
return false;
}
for (const [propertyName, property] of Instance.entries(instance)) {
if (!evaluatedPropertyNames.has(propertyName)) {
if (!Validation.interpret(unevaluatedProperties, property, ast, dynamicAnchors, true)) {
return false;
}
evaluatedPropertyNames.add(propertyName);
}
}
return evaluatedPropertyNames;
};
export default { id, compile, interpret, collectEvaluatedProperties };

@@ -33,27 +33,23 @@ import * as Pact from "@hyperjump/pact";

ast[url] = [
id,
Schema.uri(schema),
typeof schemaValue === "boolean" ? schemaValue : await Pact.pipeline([
Schema.entries,
Pact.map(async ([keyword, keywordSchema]) => {
const keywordId = getKeywordId(schema.dialectId, keyword);
if (!keywordId) {
throw Error(`Encountered unknown keyword '${keyword}' at ${url}`);
}
ast[url] = typeof schemaValue === "boolean" ? schemaValue : await Pact.pipeline([
Schema.entries,
Pact.map(async ([keyword, keywordSchema]) => {
const keywordId = getKeywordId(schema.dialectId, keyword);
if (!keywordId) {
throw Error(`Encountered unknown keyword '${keyword}' at ${url}`);
}
const keywordHandler = getKeyword(keywordId);
if (!keywordHandler) {
throw Error(`Encountered unsupported keyword ${keyword} at '${url}'. You can provide an implementation for the '${keywordId}' keyword using the 'addKeyword' function.`);
}
if (keywordHandler.experimental && !isExperimentalKeywordEnabled(keywordId)) {
throw Error(`Encountered experimental keyword ${keyword} at '${url}'. You can enable this keyword with: setExperimentalKeywordEnabled('${keywordId}', true)`);
}
const keywordHandler = getKeyword(keywordId);
if (!keywordHandler) {
throw Error(`Encountered unsupported keyword ${keyword} at '${url}'. You can provide an implementation for the '${keywordId}' keyword using the 'addKeyword' function.`);
}
if (keywordHandler.experimental && !isExperimentalKeywordEnabled(keywordId)) {
throw Error(`Encountered experimental keyword ${keyword} at '${url}'. You can enable this keyword with: setExperimentalKeywordEnabled('${keywordId}', true)`);
}
const keywordAst = await keywordHandler.compile(keywordSchema, ast, schema);
return [keywordId, Schema.uri(keywordSchema), keywordAst];
}),
Pact.all
], schema)
];
const keywordAst = await keywordHandler.compile(keywordSchema, ast, schema);
return [keywordId, Schema.uri(keywordSchema), keywordAst];
}),
Pact.all
], schema);
}

@@ -64,13 +60,11 @@

const interpret = (url, instance, ast, dynamicAnchors) => {
const [keywordId, schemaUrl, nodes] = ast[url];
const interpret = (url, instance, ast, dynamicAnchors, quiet = false) => {
dynamicAnchors = { ...ast.metaData[toAbsoluteUri(url)].dynamicAnchors, ...dynamicAnchors };
publish("result.start");
const isValid = typeof nodes === "boolean" ? nodes : nodes.every(([keywordId, schemaUrl, keywordValue]) => {
publish("result.start");
const isValid = getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors);
!quiet && publish("result.start");
const isValid = typeof ast[url] === "boolean" ? ast[url] : ast[url].every(([keywordId, schemaUrl, keywordValue]) => {
!quiet && publish("result.start");
const isValid = getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors, quiet);
publish("result", {
!quiet && publish("result", {
keyword: keywordId,

@@ -82,9 +76,9 @@ absoluteKeywordLocation: schemaUrl,

});
publish("result.end");
!quiet && publish("result.end");
return isValid;
});
publish("result", {
keyword: keywordId,
absoluteKeywordLocation: schemaUrl,
!quiet && publish("result", {
keyword: id,
absoluteKeywordLocation: url,
instanceLocation: Instance.uri(instance),

@@ -94,16 +88,14 @@ valid: isValid,

});
publish("result.end");
!quiet && publish("result.end");
return isValid;
};
const emptyPropertyNames = [];
const emptyPropertyNames = new Set();
const collectEvaluatedProperties = (url, instance, ast, dynamicAnchors, isTop = false) => {
const nodes = ast[url][2];
if (typeof nodes === "boolean") {
return nodes ? [] : false;
if (typeof ast[url] === "boolean") {
return ast[url] ? [] : false;
}
const accumulatedPropertyNames = [];
for (const [keywordId, , keywordValue] of nodes) {
const accumulatedPropertyNames = new Set();
for (const [keywordId, , keywordValue] of ast[url]) {
if (isTop && keywordId === "https://json-schema.org/keyword/unevaluatedProperties") {

@@ -116,3 +108,3 @@ continue;

? keywordHandler.collectEvaluatedProperties(keywordValue, instance, ast, dynamicAnchors, isTop)
: keywordHandler.interpret(keywordValue, instance, ast, dynamicAnchors, isTop) && emptyPropertyNames;
: keywordHandler.interpret(keywordValue, instance, ast, dynamicAnchors, true) && emptyPropertyNames;

@@ -123,3 +115,3 @@ if (propertyNames === false) {

Array.prototype.push.apply(accumulatedPropertyNames, propertyNames);
propertyNames.forEach(Set.prototype.add.bind(accumulatedPropertyNames));
}

@@ -132,10 +124,8 @@

const collectEvaluatedItems = (url, instance, ast, dynamicAnchors, isTop = false) => {
const nodes = ast[url][2];
if (typeof nodes === "boolean") {
return nodes ? new Set() : false;
if (typeof ast[url] === "boolean") {
return ast[url] ? new Set() : false;
}
const accumulatedItemIndexes = new Set();
for (const [keywordId, , keywordValue] of nodes) {
for (const [keywordId, , keywordValue] of ast[url]) {
if (isTop && keywordId === "https://json-schema.org/keyword/unevaluatedItems") {

@@ -148,3 +138,3 @@ continue;

? keywordHandler.collectEvaluatedItems(keywordValue, instance, ast, dynamicAnchors, isTop)
: keywordHandler.interpret(keywordValue, instance, ast, dynamicAnchors, isTop) && emptyItemIndexes;
: keywordHandler.interpret(keywordValue, instance, ast, dynamicAnchors, true) && emptyItemIndexes;

@@ -151,0 +141,0 @@ if (itemIndexes === false) {

{
"name": "@hyperjump/json-schema",
"version": "1.3.1",
"version": "1.4.0",
"description": "A JSON Schema validator with support for custom keywords, vocabularies, and dialects",

@@ -19,2 +19,4 @@ "type": "module",

"./instance/experimental": "./lib/instance.js",
"./annotations/experimental": "./annotations/index.js",
"./annotated-instance/experimental": "./annotations/annotated-instance.js",
"./bundle": "./bundle/index.js"

@@ -28,3 +30,3 @@ },

"lint": "eslint lib stable draft-* openapi-*",
"test": "mocha 'lib/**/*.spec.ts' 'stable/**/*.spec.ts' 'draft-*/**/*.spec.ts' 'openapi-*/**/*.spec.ts' 'bundle/**/*.spec.ts'"
"test": "mocha 'lib/**/*.spec.ts' 'stable/**/*.spec.ts' 'draft-*/**/*.spec.ts' 'openapi-*/**/*.spec.ts' 'bundle/**/*.spec.ts' 'annotations/**/*.spec.ts'"
},

@@ -31,0 +33,0 @@ "repository": "github:hyperjump-io/json-schema",

@@ -18,2 +18,3 @@ # Hyperjump - JSON Schema

* Provides utilities for building non-validation JSON Schema tooling
* Provides utilities for working with annotations

@@ -242,7 +243,7 @@ ## Install

### Usage
You can bundle schemas with external references into single deliverable using
You can bundle schemas with external references into a single deliverable using
the official JSON Schema bundling process introduced in the 2020-12
specification. Given a schema with external references, any external schemas
will be embedded in the schema resulting in a Compound Schema Document with all
the schemas necessary to evaluate the given schema in one document.
the schemas necessary to evaluate the given schema in a single JSON document.

@@ -379,5 +380,5 @@ The bundling process allows schemas to be embedded without needing to modify any

interpret: (implies, instance, ast, dynamicAnchors) => {
interpret: (implies, instance, ast, dynamicAnchors, quiet) => {
return implies.reduce((acc, schema) => {
return !acc || Validation.interpret(schema, instance, ast, dynamicAnchors);
return !acc || Validation.interpret(schema, instance, ast, dynamicAnchors, quiet);
}, true);

@@ -524,3 +525,3 @@ }

might effect this one.
* interpret: (compiledKeywordValue: A, instance: JsonDocument, ast: AST, dynamicAnchors: Anchors) => boolean
* interpret: (compiledKeywordValue: A, instance: JsonDocument, ast: AST, dynamicAnchors: Anchors, quiet: boolean) => boolean

@@ -650,2 +651,112 @@ This function takes the value returned by the `compile` function and the

## Annotations (Experimental)
JSON Schema is for annotating JSON instances as well as validating them. This
module provides utilities for working with JSON documents annotated with JSON
Schema.
### Usage
An annotated JSON document is represented as an AnnotatedInstance object. This
object is a wrapper around your JSON document with functions that allow you to
traverse the data structure and get annotations for the values within.
```javascript
import { annotate, annotatedWith, addSchema } from "@hyperjump/json-schema/annotations/experimental";
import * as AnnotatedInstance from "@hyperjump/json-schema/annotated-instance/experimental";
const schemaId = "https://example.com/foo";
const dialectId = "https://json-schema.org/draft/2020-12/schema";
addSchema({
"$schema": dialectId,
"title": "Person",
"unknown": "foo",
"type": "object",
"properties": {
"name": {
"$ref": "#/$defs/name",
"deprecated": true
},
"givenName": {
"$ref": "#/$defs/name",
"title": "Given Name"
},
"familyName": {
"$ref": "#/$defs/name",
"title": "Family Name"
}
},
"$defs": {
"name": {
"type": "string",
"title": "Name"
}
}
}, schemaId);
const instance = await annotate(schemaId, {
name: "Jason Desrosiers",
givenName: "Jason",
familyName: "Desrosiers"
});
// Get the title of the instance
const titles = AnnotatedInstance.annotation(instance, "title", dialectId); // => ["Person"]
// Unknown keywords are collected as annotations
const unknowns = AnnotatedInstance.annotation(instance, "unknown", dialectId); // => ["foo"]
// The type keyword doesn't produce annotations
const types = AnnotatedInstance.annotation(instance, "type", dialectId); // => []
// Get the title of each of the properties in the object
AnnotatedInstance.entries(instance)
.map(([propertyName, propertyInstance]) => {
return { propertyName, titles: Instance.annotation(propertyInstance, "title", dialectId) }; // => (Example) { propertyName: "givenName", titles: ["Given Name", "Name"] });
// List all locations in the instance that are deprecated
for (const deprecated of AnnotatedInstance.annotatedWith(instance, "deprecated", dialectId)) {
if (AnnotatedInstance.annotation(instance, "deprecated", dialectId)[0]) {
logger.warn(`The value at '${deprecated.pointer}' has been deprecated.`); // => (Example) "WARN: The value at '/name' has been deprecated."
}
}
```
### API
These are available from the `@hyperjump/json-schema/annotations/experimental`
export.
* **annotate**: (schemaUri: string, instance: any, outputFormat: OutputFormat = FLAG) => Promise<AnnotatedInstance>
Annotate an instance using the given schema. The function is curried to
allow compiling the schema once and applying it to multiple instances. This
may throw an [InvalidSchemaError](#api) if there is a problem with the
schema or a ValidationError if the instance doesn't validate against the
schema.
* **ValidationError**:
output: OutputUnit -- The errors that were found while validating the
instance.
### AnnotatedInstance API
These are available from the
`@hyperjump/json-schema/annotated-instance/experimental` export. The
following functions are available in addition to the functions available in the
[Instance API](#instance-api).
* **annotation**: (instance: AnnotatedInstance, keyword: string, dialectId?: string) => [any]
Get the annotations for a given keyword at the location represented by the
instance object.
* **annotatedWith**: (instance: AnnotatedInstance, keyword: string, dialectId?: string) => [AnnotatedInstance]
Get an array of instances for all the locations that are annotated with the
given keyword.
* **annotate**: (instance: AnnotatedInstance, keywordId: string, value: any) => AnnotatedInstance
Add an annotation to an instance. This is used internally, you probably
don't need it.
## Low-level Utilities (Experimental)

@@ -652,0 +763,0 @@ ### API

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