@hyperjump/json-schema
Advanced tools
Comparing version 1.1.0 to 1.1.1
@@ -10,3 +10,2 @@ import * as Instance from "../lib/instance.js"; | ||
const exclusiveMaximumKeyword = getKeywordName(schema.dialectId, "https://json-schema.org/keyword/draft-04/exclusiveMaximum"); | ||
console.log(exclusiveMaximumKeyword); | ||
const exclusiveMaximum = await Schema.step(exclusiveMaximumKeyword, parentSchema); | ||
@@ -13,0 +12,0 @@ const isExclusive = Schema.value(exclusiveMaximum); |
@@ -6,3 +6,3 @@ import Validation from "../lib/keywords/validation.js"; | ||
const compile = async (schema) => schema.id; | ||
const compile = (schema) => schema.id; | ||
@@ -9,0 +9,0 @@ const interpret = (id, instance, ast, dynamicAnchors) => { |
import Validation from "../lib/keywords/validation.js"; | ||
import * as Schema from "../lib/schema.js"; | ||
import { uriFragment } from "../lib/common.js"; | ||
@@ -8,7 +9,6 @@ | ||
const compile = async (dynamicRef, ast) => { | ||
const [, fragment] = splitUrl(Schema.value(dynamicRef)); | ||
const fragment = uriFragment(Schema.value(dynamicRef)); | ||
const referencedSchema = await Schema.get(Schema.value(dynamicRef), dynamicRef); | ||
await Validation.compile(referencedSchema, ast); | ||
return [referencedSchema.id, fragment, Schema.uri(referencedSchema)]; | ||
}; | ||
@@ -27,11 +27,2 @@ | ||
const splitUrl = (url) => { | ||
const indexOfHash = url.indexOf("#"); | ||
const ndx = indexOfHash === -1 ? url.length : indexOfHash; | ||
const urlReference = url.slice(0, ndx); | ||
const urlFragment = url.slice(ndx + 1); | ||
return [decodeURI(urlReference), decodeURI(urlFragment)]; | ||
}; | ||
export default { id, compile, interpret, collectEvaluatedProperties, collectEvaluatedItems }; |
@@ -0,1 +1,4 @@ | ||
import { resolveIri, toAbsoluteIri, parseIriReference } from "@hyperjump/uri"; | ||
const isObject = (value) => typeof value === "object" && !Array.isArray(value) && value !== null; | ||
@@ -13,11 +16,12 @@ const isType = { | ||
export const resolveUrl = (url, baseUri = undefined) => { | ||
const resolved = new URL(url, baseUri); | ||
if (baseUri && new URL("", baseUri).protocol !== "file:" && resolved.protocol === "file:") { | ||
throw Error(`Can't access file '${resolved.href}' resource from network context '${baseUri}'`); | ||
export const resolveUri = (uri, baseUri) => { | ||
const resolved = resolveIri(uri, baseUri); | ||
if (resolved.startsWith("file:") && baseUri && !baseUri.startsWith("file:")) { | ||
throw Error(`Can't access file '${resolved}' resource from network context '${baseUri}'`); | ||
} | ||
return resolved.href; | ||
return resolved; | ||
}; | ||
export const urlFragment = (url) => decodeURIComponent(new URL(url).hash.slice(1)); | ||
export const toAbsoluteUri = (uri) => toAbsoluteIri(uri); | ||
export const uriFragment = (uri) => decodeURIComponent(parseIriReference(uri).fragment || ""); | ||
@@ -24,0 +28,0 @@ const CHAR_BACKWARD_SLASH = 47; |
let metaSchemaOutputFormat; | ||
let shouldValidateSchema = true; | ||
let enabledExperimentalKeywords = {}; | ||
const enabledExperimentalKeywords = {}; | ||
@@ -5,0 +5,0 @@ export const getMetaSchemaOutputFormat = () => metaSchemaOutputFormat; |
export { addSchema, validate, FLAG } from "./core.js"; | ||
export type { Validator, OutputFormat, CompiledSchema, Result } from "./core.js"; | ||
export type { Validator, OutputFormat, CompiledSchema, OutputUnit } from "./core.js"; | ||
export { | ||
@@ -4,0 +4,0 @@ getMetaSchemaOutputFormat, |
import * as JsonPointer from "@hyperjump/json-pointer"; | ||
import curry from "just-curry-it"; | ||
import { resolveUrl, jsonTypeOf } from "./common.js"; | ||
import { toAbsoluteUri, jsonTypeOf } from "./common.js"; | ||
import * as Reference from "./reference.js"; | ||
export const nil = Object.freeze({ id: undefined, pointer: "", instance: undefined, value: undefined }); | ||
export const cons = (instance, id = undefined) => Object.freeze({ | ||
export const nil = { id: undefined, pointer: "", instance: undefined, value: undefined }; | ||
export const cons = (instance, id = undefined) => ({ | ||
...nil, | ||
id: id ? resolveUrl("", id) : "", | ||
id: id ? toAbsoluteUri(id) : "", | ||
instance, | ||
@@ -20,3 +20,3 @@ value: instance | ||
return Object.freeze({ ...instance, pointer: url.substr(1) }); | ||
return { ...instance, pointer: url.substr(1) }; | ||
}; | ||
@@ -29,3 +29,3 @@ | ||
export const step = (key, doc) => Object.freeze({ | ||
export const step = (key, doc) => ({ | ||
...doc, | ||
@@ -32,0 +32,0 @@ pointer: JsonPointer.append(key, doc.pointer), |
@@ -9,4 +9,8 @@ import metaData from "./keywords/meta-data.js"; | ||
_keywords[keywordHandler.id] = { | ||
collectEvaluatedItems: (keywordValue, instance, ast, dynamicAnchors, isTop) => keywordHandler.interpret(keywordValue, instance, ast, dynamicAnchors, isTop) && new Set(), | ||
collectEvaluatedProperties: (keywordValue, instance, ast, dynamicAnchors, isTop) => keywordHandler.interpret(keywordValue, instance, ast, dynamicAnchors, isTop) && [], | ||
collectEvaluatedItems: (keywordValue, instance, ast, dynamicAnchors, isTop) => { | ||
return keywordHandler.interpret(keywordValue, instance, ast, dynamicAnchors, isTop) && new Set(); | ||
}, | ||
collectEvaluatedProperties: (keywordValue, instance, ast, dynamicAnchors, isTop) => { | ||
return keywordHandler.interpret(keywordValue, instance, ast, dynamicAnchors, isTop) && []; | ||
}, | ||
...keywordHandler | ||
@@ -13,0 +17,0 @@ }; |
@@ -21,3 +21,3 @@ import * as Pact from "@hyperjump/pact"; | ||
const propertyNames = Validation.collectEvaluatedProperties(schemaUrl, instance, ast, dynamicAnchors); | ||
return propertyNames !== false ? [...acc || [], ...propertyNames] : acc; | ||
return propertyNames === false ? acc : [...acc || [], ...propertyNames]; | ||
}, false); | ||
@@ -29,3 +29,3 @@ }; | ||
const itemIndexes = Validation.collectEvaluatedItems(schemaUrl, instance, ast, dynamicAnchors); | ||
return itemIndexes !== false ? new Set([...acc || [], ...itemIndexes]) : acc; | ||
return itemIndexes === false ? acc : new Set([...acc || [], ...itemIndexes]); | ||
}, false); | ||
@@ -32,0 +32,0 @@ }; |
@@ -35,5 +35,5 @@ import * as Schema from "../schema.js"; | ||
const collectEvaluatedItems = (keywordValue, instance, ast, dynamicAnchors) => { | ||
return interpret(keywordValue, instance, ast, dynamicAnchors) && | ||
Instance.typeOf(instance, "array") && | ||
Instance.reduce((matchedIndexes, item, itemIndex) => { | ||
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; | ||
@@ -44,5 +44,5 @@ }, new Set(), instance); | ||
const collectEvaluatedProperties = (keywordValue, instance, ast, dynamicAnchors) => { | ||
return interpret(keywordValue, instance, ast, dynamicAnchors) && | ||
Instance.typeOf(instance, "object") && | ||
Instance.entries(instance).reduce((matchedPropertyNames, [propertyName, item]) => { | ||
return interpret(keywordValue, instance, ast, dynamicAnchors) | ||
&& Instance.typeOf(instance, "object") | ||
&& Instance.entries(instance).reduce((matchedPropertyNames, [propertyName, item]) => { | ||
if (Validation.interpret(keywordValue.contains, item, ast, dynamicAnchors)) { | ||
@@ -49,0 +49,0 @@ matchedPropertyNames.push(propertyName); |
@@ -26,6 +26,5 @@ import * as Schema from "../schema.js"; | ||
return typeof nodes === "boolean" ? nodes : nodes | ||
.every(([keywordId, , keywordValue]) => { | ||
return getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors); | ||
}); | ||
return typeof nodes === "boolean" ? nodes : nodes.every(([keywordId, , keywordValue]) => { | ||
return getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors); | ||
}); | ||
}; | ||
@@ -32,0 +31,0 @@ |
@@ -7,5 +7,5 @@ import * as Schema from "../schema.js"; | ||
const compile = async (schema) => Schema.value(schema); | ||
const compile = (schema) => Schema.value(schema); | ||
const interpret = (exclusiveMaximum, instance) => !Instance.typeOf(instance, "number") || Instance.value(instance) < exclusiveMaximum; | ||
export default { id, compile, interpret }; |
@@ -7,5 +7,5 @@ import * as Schema from "../schema.js"; | ||
const compile = async (schema) => Schema.value(schema); | ||
const compile = (schema) => Schema.value(schema); | ||
const interpret = (exclusiveMinimum, instance) => !Instance.typeOf(instance, "number") || Instance.value(instance) > exclusiveMinimum; | ||
export default { id, compile, interpret }; |
@@ -7,5 +7,5 @@ import * as Schema from "../schema.js"; | ||
const compile = async (schema) => Schema.value(schema); | ||
const compile = (schema) => Schema.value(schema); | ||
const interpret = (maximum, instance) => !Instance.typeOf(instance, "number") || Instance.value(instance) <= maximum; | ||
export default { id, compile, interpret }; |
@@ -7,5 +7,5 @@ import * as Schema from "../schema.js"; | ||
const compile = async (schema) => Schema.value(schema); | ||
const compile = (schema) => Schema.value(schema); | ||
const interpret = (minimum, instance) => !Instance.typeOf(instance, "number") || Instance.value(instance) >= minimum; | ||
export default { id, compile, interpret }; |
@@ -10,3 +10,3 @@ import * as Pact from "@hyperjump/pact"; | ||
const compile = async (schema, ast) => { | ||
const compile = (schema, ast) => { | ||
return Pact.pipeline([ | ||
@@ -13,0 +13,0 @@ Schema.entries, |
@@ -21,5 +21,5 @@ import * as Instance from "../instance.js"; | ||
const interpret = (required, instance) => { | ||
return !Instance.typeOf(instance, "object") || required.every((propertyName) => Instance.value(instance).hasOwnProperty(propertyName)); | ||
return !Instance.typeOf(instance, "object") || required.every((propertyName) => Object.hasOwn(Instance.value(instance), propertyName)); | ||
}; | ||
export default { id, experimental, compile, interpret }; |
@@ -10,5 +10,5 @@ import * as Schema from "../schema.js"; | ||
const interpret = (required, instance) => { | ||
return !Instance.typeOf(instance, "object") || required.every((propertyName) => Object.prototype.hasOwnProperty.call(Instance.value(instance), propertyName)); | ||
return !Instance.typeOf(instance, "object") || required.every((propertyName) => Object.hasOwn(Instance.value(instance), propertyName)); | ||
}; | ||
export default { id, compile, interpret }; |
@@ -26,6 +26,5 @@ import * as Schema from "../schema.js"; | ||
return typeof nodes === "boolean" ? nodes : nodes | ||
.every(([keywordId, , keywordValue]) => { | ||
return getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors); | ||
}); | ||
return typeof nodes === "boolean" ? nodes : nodes.every(([keywordId, , keywordValue]) => { | ||
return getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors); | ||
}); | ||
}; | ||
@@ -32,0 +31,0 @@ |
@@ -24,3 +24,3 @@ import * as Schema from "../schema.js"; | ||
const collectEvaluatedProperties = (keywordValue, instance, ast, dynamicAnchors) =>{ | ||
const collectEvaluatedProperties = (keywordValue, instance, ast, dynamicAnchors) => { | ||
return interpret(keywordValue, instance, ast, dynamicAnchors) && [new RegExp("")]; | ||
@@ -27,0 +27,0 @@ }; |
@@ -6,3 +6,3 @@ import * as Pact from "@hyperjump/pact"; | ||
import { getKeywordId, getKeyword } from "../keywords.js"; | ||
import { resolveUrl } from "../common.js"; | ||
import { toAbsoluteUri } from "../common.js"; | ||
import * as Schema from "../schema.js"; | ||
@@ -64,20 +64,19 @@ | ||
dynamicAnchors = { ...ast.metaData[resolveUrl("", url)].dynamicAnchors, ...dynamicAnchors }; | ||
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); | ||
const isValid = typeof nodes === "boolean" ? nodes : nodes.every(([keywordId, schemaUrl, keywordValue]) => { | ||
publish("result.start"); | ||
const isValid = getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors); | ||
publish("result", { | ||
keyword: keywordId, | ||
absoluteKeywordLocation: schemaUrl, | ||
instanceLocation: Instance.uri(instance), | ||
valid: isValid, | ||
ast: keywordValue | ||
}); | ||
publish("result.end"); | ||
return isValid; | ||
publish("result", { | ||
keyword: keywordId, | ||
absoluteKeywordLocation: schemaUrl, | ||
instanceLocation: Instance.uri(instance), | ||
valid: isValid, | ||
ast: keywordValue | ||
}); | ||
publish("result.end"); | ||
return isValid; | ||
}); | ||
@@ -84,0 +83,0 @@ publish("result", { |
@@ -40,4 +40,2 @@ const subscriptions = {}; | ||
await Promise.all(promises); | ||
return; | ||
}; |
const $__value = Symbol("$__value"); | ||
const $__href = Symbol("$__href"); | ||
export const cons = (href, value) => Object.freeze({ | ||
export const cons = (href, value) => ({ | ||
[$__href]: href, | ||
@@ -6,0 +6,0 @@ [$__value]: value |
import type { JsonType } from "./common.js"; | ||
export const add: <A extends SchemaObject | boolean>(schema: A, url?: string, defaultSchemaVersion?: string) => string; | ||
export const add: <A extends SchemaObject | boolean>(schema: A, retrievalUri?: string, defaultSchemaVersion?: string) => string; | ||
export const get: (url: string, context?: SchemaDocument) => Promise<SchemaDocument>; | ||
@@ -6,0 +6,0 @@ export const markValidated: (id: string) => void; |
@@ -5,3 +5,3 @@ import curry from "just-curry-it"; | ||
import * as JsonPointer from "@hyperjump/json-pointer"; | ||
import { jsonTypeOf, resolveUrl, urlFragment, pathRelative } from "./common.js"; | ||
import { jsonTypeOf, resolveUri, toAbsoluteUri, uriFragment, pathRelative } from "./common.js"; | ||
import fetch from "./fetch.js"; | ||
@@ -19,7 +19,7 @@ import * as Keywords from "./keywords.js"; | ||
export const add = (schema, url = undefined, contextDialectId = undefined) => { | ||
export const add = (schema, retrievalUri = undefined, contextDialectId = undefined) => { | ||
schema = JSON.parse(JSON.stringify(schema)); | ||
// Dialect / JSON Schema Version | ||
const dialectId = resolveUrl("", schema.$schema || contextDialectId || defaultDialectId); | ||
const dialectId = toAbsoluteUri(schema.$schema || contextDialectId || defaultDialectId); | ||
delete schema.$schema; | ||
@@ -34,7 +34,10 @@ | ||
|| Keywords.getKeywordName(dialectId, "https://json-schema.org/keyword/draft-04/id"); | ||
const internalUrl = resolveUrl(schema[idToken] || url, url); | ||
const id = resolveUrl("", internalUrl); | ||
if (retrievalUri === undefined && !(idToken in schema)) { | ||
throw Error(`Unable to determine an identifier for the schema. Use the '${idToken}' keyword or pass a retrievalUri when loading the schema.`); | ||
} | ||
const internalUrl = resolveUri(schema[idToken] || retrievalUri, retrievalUri); | ||
const id = toAbsoluteUri(internalUrl); | ||
delete schema[idToken]; | ||
if (url) { | ||
const externalId = resolveUrl("", url); | ||
if (retrievalUri) { | ||
const externalId = toAbsoluteUri(retrievalUri); | ||
schemaStoreAlias[externalId] = id; | ||
@@ -86,3 +89,3 @@ } | ||
delete subject[legacyIdToken].$schema; | ||
subject[legacyIdToken] = resolveUrl(subject[legacyIdToken], id); | ||
subject[legacyIdToken] = resolveUri(subject[legacyIdToken], id); | ||
add(subject, undefined, dialectId); | ||
@@ -95,6 +98,6 @@ return Reference.cons(subject[legacyIdToken], subject); | ||
// Embedded Schema | ||
const embeddedDialectId = typeof subject.$schema === "string" ? resolveUrl("", subject.$schema) : dialectId; | ||
const embeddedDialectId = typeof subject.$schema === "string" ? toAbsoluteUri(subject.$schema) : dialectId; | ||
const idToken = Keywords.getKeywordName(embeddedDialectId, "https://json-schema.org/keyword/id"); | ||
if (typeof subject[idToken] === "string") { | ||
subject[idToken] = resolveUrl(subject[idToken], id); | ||
subject[idToken] = resolveUri(subject[idToken], id); | ||
add(subject, undefined, dialectId); | ||
@@ -150,3 +153,3 @@ return Reference.cons(subject[idToken], subject); | ||
// Schema Retrieval | ||
const nil = Object.freeze({ | ||
const nil = { | ||
id: undefined, | ||
@@ -160,8 +163,8 @@ dialectId: undefined, | ||
validated: true | ||
}); | ||
}; | ||
export const get = async (url, contextDoc = nil) => { | ||
const resolvedUrl = resolveUrl(url, uri(contextDoc)); | ||
const id = resolveUrl("", resolvedUrl); | ||
const fragment = urlFragment(resolvedUrl); | ||
const resolvedUrl = resolveUri(url, contextDoc.id); | ||
const id = toAbsoluteUri(resolvedUrl); | ||
const fragment = uriFragment(resolvedUrl); | ||
@@ -178,3 +181,3 @@ if (!hasStoredSchema(id)) { | ||
// Try to determine the dialect from the meta-schema if it isn't already known | ||
const dialectId = resolveUrl("", schema.$schema || contextDialectId || defaultDialectId); | ||
const dialectId = toAbsoluteUri(schema.$schema || contextDialectId || defaultDialectId); | ||
if (!Keywords.hasDialect(dialectId) && !hasStoredSchema(dialectId)) { | ||
@@ -188,8 +191,8 @@ await get(dialectId); | ||
const storedSchema = getStoredSchema(id); | ||
const pointer = fragment[0] !== "/" ? getAnchorPointer(storedSchema, fragment) : fragment; | ||
const doc = Object.freeze({ | ||
const pointer = fragment[0] === "/" ? fragment : getAnchorPointer(storedSchema, fragment); | ||
const doc = { | ||
...storedSchema, | ||
pointer: pointer, | ||
value: JsonPointer.get(pointer, storedSchema.schema) | ||
}); | ||
}; | ||
@@ -217,3 +220,3 @@ return followReferences(doc); | ||
const storedSchema = getStoredSchema(doc.id); | ||
const nextDoc = Object.freeze({ | ||
return followReferences({ | ||
...doc, | ||
@@ -224,3 +227,2 @@ pointer: JsonPointer.append(`${key}`, doc.pointer), | ||
}); | ||
return followReferences(nextDoc); | ||
}; | ||
@@ -268,3 +270,3 @@ | ||
for (const anchor in schemaDoc.dynamicAnchors) { | ||
const pointer = urlFragment(schemaDoc.dynamicAnchors[anchor]); | ||
const pointer = uriFragment(schemaDoc.dynamicAnchors[anchor]); | ||
dynamicAnchors[pointer] = anchor; | ||
@@ -276,5 +278,3 @@ } | ||
const refValue = Reference.value(value); | ||
if (!fullOptions.includeEmbedded && idToken in refValue) { | ||
return; | ||
} else { | ||
if (fullOptions.includeEmbedded || !(idToken in refValue)) { | ||
return Reference.value(value); | ||
@@ -308,4 +308,4 @@ } | ||
return { | ||
...(id && { [idToken]: id }), | ||
...(dialect && { $schema: dialect }), | ||
...id && { [idToken]: id }, | ||
...dialect && { $schema: dialect }, | ||
...schema | ||
@@ -312,0 +312,0 @@ }; |
{ | ||
"name": "@hyperjump/json-schema", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"description": "A JSON Schema validator with support for custom keywords, vocabularies, and dialects", | ||
@@ -25,4 +25,4 @@ "type": "module", | ||
"clean": "xargs -a .gitignore rm -rf", | ||
"lint": "eslint lib", | ||
"test": "mocha 'lib/**/*.spec.ts' 'stable/**/*.spec.ts' 'draft-*/**/*.spec.ts' 'oas-*/**/*.spec.ts'" | ||
"lint": "eslint lib stable draft-* openapi-*", | ||
"test": "mocha 'lib/**/*.spec.ts' 'stable/**/*.spec.ts' 'draft-*/**/*.spec.ts' 'openapi-*/**/*.spec.ts'" | ||
}, | ||
@@ -68,2 +68,3 @@ "repository": "github:hyperjump-io/json-schema", | ||
"@hyperjump/pact": "^0.2.4", | ||
"@hyperjump/uri": "^1.0.0", | ||
"content-type": "^1.0.4", | ||
@@ -70,0 +71,0 @@ "fastest-stable-stringify": "^2.0.2", |
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
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
272430
7
7518
+ Added@hyperjump/uri@^1.0.0
+ Added@hyperjump/uri@1.2.2(transitive)