@sjsf-lab/hyperjump-validator
Advanced tools
+1
-1
@@ -0,4 +1,4 @@ | ||
| import type * as H from "@hyperjump/json-schema-errors"; | ||
| import type { FormValue, ValidationResult } from "@sjsf/form"; | ||
| import type * as H from "@hyperjump/json-schema-errors"; | ||
| export declare function transformFormErrors<T>(out: H.ValidationResult, data: FormValue): ValidationResult<T>; | ||
| export declare function transformFieldErrors(out: H.ValidationResult): string[]; |
+25
-18
@@ -0,24 +1,31 @@ | ||
| import type { Json as HyperjumpJson, ValidationOptions } from "@hyperjump/json-schema-errors"; | ||
| import { type AST, type CompiledSchema } from "@hyperjump/json-schema/experimental"; | ||
| import type { FormValue, Schema, SchemaValue } from "@sjsf/form"; | ||
| import { type AST } from "@hyperjump/json-schema/experimental"; | ||
| import { type JsonNode } from "@hyperjump/json-schema/instance/experimental"; | ||
| import { type Localization } from "@hyperjump/json-schema-errors"; | ||
| export interface ValidatorOptions { | ||
| import { type ValidatorRetrieverOptions } from "@sjsf/form/validators/precompile"; | ||
| interface LegacyValidatorOptions { | ||
| /** @deprecated use `validatorRetriever` instead */ | ||
| ast: AST; | ||
| localization: Localization; | ||
| /** @deprecated use `validatorRetriever` instead */ | ||
| augmentSuffix?: string; | ||
| valueToJSON?: (value: FormValue) => SchemaValue; | ||
| validatorRetriever?: (schema: Schema) => CompiledSchema; | ||
| } | ||
| interface ModernValidatorOptions { | ||
| validatorRetriever: (schema: Schema) => CompiledSchema; | ||
| } | ||
| export type CoreValidatorOptions = (LegacyValidatorOptions | ModernValidatorOptions) & Partial<ValidationOptions>; | ||
| export declare function createRetriever(options: CoreValidatorOptions): (schema: Schema) => CompiledSchema; | ||
| export interface ValueToJSON { | ||
| valueToJSON: (value: FormValue) => SchemaValue; | ||
| } | ||
| export type ValidatorOptions = CoreValidatorOptions & ValueToJSON; | ||
| export declare function fromAst(ast: AST, options?: Partial<Omit<ValidatorRetrieverOptions<any>, "registry">>): ({ $id: id, allOf }: Schema) => { | ||
| schemaUri: string; | ||
| ast: AST; | ||
| }; | ||
| export interface Context { | ||
| ast: AST; | ||
| schemaUri: string; | ||
| value: JsonNode; | ||
| compiledSchema: CompiledSchema; | ||
| value: HyperjumpJson; | ||
| } | ||
| export declare function createContext({ ast, augmentSuffix, valueToJSON, }: ValidatorOptions, { $id: id, allOf }: Schema, value: FormValue): Context; | ||
| export declare function validate(ctx: Context): boolean; | ||
| export declare function evaluateCompiledSchema(ctx: Context, localization: Localization): { | ||
| valid: true; | ||
| errors?: undefined; | ||
| } | { | ||
| valid: false; | ||
| errors: import("@hyperjump/json-schema-errors").ErrorObject[]; | ||
| }; | ||
| export declare function createContext(options: ValidatorOptions, schema: Schema, value: FormValue): Context; | ||
| export declare function validate({ compiledSchema, value }: Context): boolean; | ||
| export {}; |
+51
-42
@@ -1,47 +0,56 @@ | ||
| import { DEFAULT_AUGMENT_SUFFIX } from "@sjsf/form/validators/precompile"; | ||
| import { Validation } from "@hyperjump/json-schema/experimental"; | ||
| import { fromJs, } from "@hyperjump/json-schema/instance/experimental"; | ||
| import { getErrors, } from "@hyperjump/json-schema-errors"; | ||
| import { JsonSchemaErrorsOutputPlugin } from "./output-plugin.js"; | ||
| const defaultValueToJson = (v) => v === undefined || v === null | ||
| ? null | ||
| : typeof v === "object" | ||
| ? JSON.parse(JSON.stringify(v)) | ||
| : v; | ||
| export function createContext({ ast, augmentSuffix = DEFAULT_AUGMENT_SUFFIX, valueToJSON = defaultValueToJson, }, { $id: id, allOf }, value) { | ||
| if (id === undefined) { | ||
| const firstAllOfItem = allOf?.[0]; | ||
| if (typeof firstAllOfItem === "object" && | ||
| firstAllOfItem.$id !== undefined) { | ||
| id = firstAllOfItem.$id + augmentSuffix; | ||
| } | ||
| else { | ||
| throw new Error("Schema id not found"); | ||
| } | ||
| } | ||
| import { Validation, } from "@hyperjump/json-schema/experimental"; | ||
| import { fromJs } from "@hyperjump/json-schema/instance/experimental"; | ||
| import { createValidatorRetriever, } from "@sjsf/form/validators/precompile"; | ||
| // TODO: Remove in v4 | ||
| export function createRetriever(options) { | ||
| return "ast" in options | ||
| ? (options.validatorRetriever ?? | ||
| createValidatorRetriever({ | ||
| registry: { | ||
| get: (id) => { | ||
| const schemaUri = `${id}#`; | ||
| return schemaUri in options.ast | ||
| ? { | ||
| schemaUri, | ||
| ast: options.ast, | ||
| } | ||
| : undefined; | ||
| }, | ||
| }, | ||
| idAugmentations: options.augmentSuffix | ||
| ? { | ||
| combination: (id) => id + options.augmentSuffix, | ||
| } | ||
| : undefined, | ||
| })) | ||
| : options.validatorRetriever; | ||
| } | ||
| export function fromAst(ast, options) { | ||
| return createValidatorRetriever({ | ||
| registry: { | ||
| get(id) { | ||
| const schemaUri = `${id}#`; | ||
| return schemaUri in ast | ||
| ? { | ||
| schemaUri, | ||
| ast, | ||
| } | ||
| : undefined; | ||
| }, | ||
| }, | ||
| ...options, | ||
| }); | ||
| } | ||
| export function createContext(options, schema, value) { | ||
| const getCompiledSchema = createRetriever(options); | ||
| return { | ||
| ast, | ||
| schemaUri: `${id}#`, | ||
| value: fromJs(valueToJSON(value)), | ||
| compiledSchema: getCompiledSchema(schema), | ||
| value: options.valueToJSON(value), | ||
| }; | ||
| } | ||
| export function validate(ctx) { | ||
| return Validation.interpret(ctx.schemaUri, ctx.value, { | ||
| ast: ctx.ast, | ||
| plugins: [...ctx.ast.plugins], | ||
| export function validate({ compiledSchema, value }) { | ||
| return Validation.interpret(compiledSchema.schemaUri, fromJs(value), { | ||
| ast: compiledSchema.ast, | ||
| plugins: [...compiledSchema.ast.plugins], | ||
| }); | ||
| } | ||
| export function evaluateCompiledSchema(ctx, localization) { | ||
| const outputPlugin = new JsonSchemaErrorsOutputPlugin(); | ||
| const context = { | ||
| ast: ctx.ast, | ||
| plugins: [...ctx.ast.plugins, outputPlugin], | ||
| }; | ||
| const valid = Validation.interpret(ctx.schemaUri, ctx.value, context); | ||
| return valid | ||
| ? { valid } | ||
| : { | ||
| valid, | ||
| errors: getErrors(outputPlugin.output, ctx.value, localization, ctx.ast), | ||
| }; | ||
| } |
@@ -1,2 +0,2 @@ | ||
| export { type ValidatorOptions } from "./model.js"; | ||
| export { type ValidatorOptions, fromAst } from "./model.js"; | ||
| export * from "./validator.js"; |
@@ -1,2 +0,2 @@ | ||
| export {} from "./model.js"; | ||
| export { fromAst } from "./model.js"; | ||
| export * from "./validator.js"; |
| import type { FieldValueValidator, FormValueValidator, Validator } from "@sjsf/form"; | ||
| import { type ValidatorOptions } from "./model.js"; | ||
| import { type CoreValidatorOptions, type ValidatorOptions, type ValueToJSON } from "./model.js"; | ||
| export declare function createValidator(options: ValidatorOptions): Validator; | ||
| export interface FormValueValidatorOptions extends ValidatorOptions { | ||
| } | ||
| export type FormValueValidatorOptions = ValidatorOptions; | ||
| export declare function createFormValueValidator<T>(options: FormValueValidatorOptions): FormValueValidator<T>; | ||
| export declare function createFieldValueValidator(options: FormValidatorOptions): FieldValueValidator; | ||
| export interface FormValidatorOptions extends FormValueValidatorOptions { | ||
| } | ||
| export declare function createFormValidatorFactory<T>(vOptions: ValidatorOptions): (options: Omit<FormValidatorOptions, keyof ValidatorOptions>) => Validator & FormValueValidator<T> & FieldValueValidator; | ||
| export type FieldValueValidatorOptions = ValidatorOptions; | ||
| export declare function createFieldValueValidator(options: FieldValueValidatorOptions): FieldValueValidator; | ||
| export type FormValidatorOptions = ValidatorOptions & FormValueValidatorOptions & FieldValueValidatorOptions; | ||
| export declare function createFormValidatorFactory<T>(vOptions: CoreValidatorOptions & Partial<ValueToJSON>): (options: Omit<FormValidatorOptions, keyof ValidatorOptions>) => Validator & FormValueValidator<T> & FieldValueValidator; |
+14
-6
@@ -0,3 +1,4 @@ | ||
| import { evaluateCompiledSchema } from "@hyperjump/json-schema-errors"; | ||
| import { transformFormErrors, transformFieldErrors } from "./errors.js"; | ||
| import { createContext, evaluateCompiledSchema, validate, } from "./model.js"; | ||
| import { createContext, createRetriever, validate, } from "./model.js"; | ||
| export function createValidator(options) { | ||
@@ -17,4 +18,4 @@ return { | ||
| validateFormValue(rootSchema, formValue) { | ||
| const ctx = createContext(options, rootSchema, formValue); | ||
| const out = evaluateCompiledSchema(ctx, options.localization); | ||
| const { compiledSchema, value } = createContext(options, rootSchema, formValue); | ||
| const out = evaluateCompiledSchema(compiledSchema, value, options); | ||
| return transformFormErrors(out, formValue); | ||
@@ -27,4 +28,4 @@ }, | ||
| validateFieldValue(field, fieldValue) { | ||
| const ctx = createContext(options, field.schema, fieldValue); | ||
| const out = evaluateCompiledSchema(ctx, options.localization); | ||
| const { compiledSchema, value } = createContext(options, field.schema, fieldValue); | ||
| const out = evaluateCompiledSchema(compiledSchema, value, options); | ||
| return transformFieldErrors(out); | ||
@@ -37,4 +38,11 @@ }, | ||
| const full = { | ||
| ...options, | ||
| ...vOptions, | ||
| ...options, | ||
| validatorRetriever: vOptions.validatorRetriever ?? createRetriever(vOptions), | ||
| valueToJSON: vOptions.valueToJSON ?? | ||
| ((v) => v === undefined || v === null | ||
| ? null | ||
| : typeof v === "object" | ||
| ? JSON.parse(JSON.stringify(v)) | ||
| : v), | ||
| }; | ||
@@ -41,0 +49,0 @@ return Object.assign(createValidator(full), createFormValueValidator(full), createFieldValueValidator(full)); |
+27
-31
| { | ||
| "name": "@sjsf-lab/hyperjump-validator", | ||
| "version": "3.0.0", | ||
| "version": "3.1.0", | ||
| "description": "The @hyperjump/json-schema based validator for svelte-jsonschema-form", | ||
| "license": "MIT", | ||
| "keywords": [ | ||
| "validator", | ||
| "hyperjump", | ||
| "jsonschema", | ||
| "hyperjump" | ||
| "validator" | ||
| ], | ||
| "type": "module", | ||
| "homepage": "https://x0k.github.io/svelte-jsonschema-form/", | ||
| "bugs": "https://github.com/x0k/svelte-jsonschema-form/issues", | ||
| "license": "MIT", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/x0k/svelte-jsonschema-form.git", | ||
| "directory": "lab/hyperjump-validator" | ||
| }, | ||
| "files": [ | ||
@@ -17,14 +23,5 @@ "dist", | ||
| ], | ||
| "publishConfig": { | ||
| "provenance": true | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/x0k/svelte-jsonschema-form.git", | ||
| "directory": "lab/hyperjump-validator" | ||
| }, | ||
| "bugs": "https://github.com/x0k/svelte-jsonschema-form/issues", | ||
| "homepage": "https://x0k.github.io/svelte-jsonschema-form/", | ||
| "type": "module", | ||
| "main": "dist/index.js", | ||
| "types": "dist/index.d.ts", | ||
| "main": "dist/index.js", | ||
| "exports": { | ||
@@ -41,22 +38,19 @@ "./package.json": "./package.json", | ||
| "default": "./dist/precompile.js" | ||
| }, | ||
| "./localizations/*": { | ||
| "types": "./dist/localizations/*.d.ts", | ||
| "default": "./dist/localizations/*.js" | ||
| } | ||
| }, | ||
| "peerDependencies": { | ||
| "@fluent/bundle": "^0.19.0", | ||
| "@hyperjump/json-schema": "^1.17.0", | ||
| "@sjsf/form": "^3.5.0" | ||
| "publishConfig": { | ||
| "provenance": true | ||
| }, | ||
| "dependencies": { | ||
| "@hyperjump/json-schema-errors": "github:hyperjump-io/json-schema-errors#21ec0ab303b986e052e5ff255bf41d01c54e886b" | ||
| }, | ||
| "devDependencies": { | ||
| "@fluent/bundle": "^0.19.1", | ||
| "@hyperjump/json-schema": "^1.17.6", | ||
| "svelte": "^5.55.5", | ||
| "@sjsf/form": "3.6.0", | ||
| "validator-testing": "1.0.27" | ||
| "svelte": "^5.56.4", | ||
| "validator-testing": "1.0.28", | ||
| "@sjsf/form": "3.7.0" | ||
| }, | ||
| "dependencies": { | ||
| "@hyperjump/json-schema-errors": "github:hyperjump-io/json-schema-errors#8bda546feeca780ae02c1ebd7247291424ea4a98" | ||
| "peerDependencies": { | ||
| "@hyperjump/json-schema": "^1.17.0", | ||
| "@sjsf/form": "^3.5.0" | ||
| }, | ||
@@ -66,4 +60,6 @@ "scripts": { | ||
| "build": "tsc && publint", | ||
| "dev": "tsc --watch" | ||
| "dev": "tsc --watch", | ||
| "format": "oxfmt .", | ||
| "format:check": "oxfmt --check ." | ||
| } | ||
| } |
+7
-3
@@ -17,8 +17,12 @@ # @sjsf-lab/hyperjump-validator | ||
| ```typescript | ||
| import { createFormValidatorFactory } from "@sjsf-lab/hyperjump-validator"; | ||
| import { localization } from "@sjsf-lab/hyperjump-validator/localizations/en-us"; | ||
| import { | ||
| createFormValidatorFactory, | ||
| fromAst, | ||
| } from "@sjsf-lab/hyperjump-validator/precompile"; | ||
| import { ast } from "./ast"; | ||
| const factory = createFormValidatorFactory({ ast, localization }); | ||
| const factory = createFormValidatorFactory({ | ||
| validatorRetriever: fromAst(ast), | ||
| }); | ||
| ``` | ||
@@ -25,0 +29,0 @@ |
| import type { FluentBundle } from "@fluent/bundle"; | ||
| import type { Json as HyperjumpJson, ContainsRange } from "@hyperjump/json-schema-errors"; | ||
| export declare class Localization { | ||
| #private; | ||
| private readonly bundle; | ||
| private disjunction; | ||
| private conjunction; | ||
| constructor(bundle: FluentBundle); | ||
| getBooleanSchemaErrorMessage(): string; | ||
| getTypeErrorMessage(expectedTypes: string[]): string; | ||
| getEnumErrorMessage(expected: HyperjumpJson[]): string; | ||
| getFormatErrorMessage(format: string): string; | ||
| getExclusiveMaximumErrorMessage(exclusiveMaximum: number): string; | ||
| getMaximumErrorMessage(maximum: number): string; | ||
| getExclusiveMinimumErrorMessage(exclusiveMinimum: number): string; | ||
| getMinimumErrorMessage(minimum: number): string; | ||
| getMultipleOfErrorMessage(multipleOf: number): string; | ||
| getMaxLengthErrorMessage(maxLength: number): string; | ||
| getMinLengthErrorMessage(minLength: number): string; | ||
| getPatternErrorMessage(pattern: number): string; | ||
| getMaxItemsErrorMessage(maxItems: number): string; | ||
| getMinItemsErrorMessage(minItems: number): string; | ||
| getContainsErrorMessage(range: ContainsRange): string; | ||
| getUniqueItemsErrorMessage(): string; | ||
| getMaxPropertiesErrorMessage(maxProperties: number): string; | ||
| getMinPropertiesErrorMessage(minProperties: number): string; | ||
| getRequiredErrorMessage(required: string[]): string; | ||
| getAnyOfErrorMessage(): string; | ||
| getOneOfErrorMessage(matchCount: number): string; | ||
| getNotErrorMessage(): string; | ||
| getUnknownErrorMessage(keyword: string): string; | ||
| } |
| // This file is derived from: | ||
| // https://github.com/hyperjump-io/json-schema-errors/blob/8bda546feeca780ae02c1ebd7247291424ea4a98/src/localization.js | ||
| // Copyright (c) 2026 Hyperjump Software, LLC | ||
| // Licensed under the MIT License | ||
| // Modifications made by Roman Krasilnikov. | ||
| export class Localization { | ||
| bundle; | ||
| disjunction; | ||
| conjunction; | ||
| constructor(bundle) { | ||
| this.bundle = bundle; | ||
| const locale = bundle.locales[0]; | ||
| this.disjunction = new Intl.ListFormat(locale, { type: "disjunction" }); | ||
| this.conjunction = new Intl.ListFormat(locale, { type: "conjunction" }); | ||
| } | ||
| #formatMessage(messageId, args) { | ||
| const message = this.bundle.getMessage(messageId); | ||
| if (!message?.value) { | ||
| throw Error(`Message '${messageId}' not found.`); | ||
| } | ||
| return this.bundle.formatPattern(message.value, args); | ||
| } | ||
| getBooleanSchemaErrorMessage() { | ||
| return this.#formatMessage("boolean-schema-message", {}); | ||
| } | ||
| getTypeErrorMessage(expectedTypes) { | ||
| return this.#formatMessage("type-message", { | ||
| expectedTypes: this.disjunction.format(expectedTypes), | ||
| }); | ||
| } | ||
| getEnumErrorMessage(expected) { | ||
| if (expected.length === 1) { | ||
| return this.#formatMessage("const-message", { | ||
| expected: JSON.stringify(expected[0], null, " "), | ||
| }); | ||
| } | ||
| else { | ||
| const expectedJson = expected.map((value) => JSON.stringify(value)); | ||
| return this.#formatMessage("enum-message", { | ||
| expected: this.disjunction.format(expectedJson), | ||
| }); | ||
| } | ||
| } | ||
| getFormatErrorMessage(format) { | ||
| return this.#formatMessage("format-message", { format }); | ||
| } | ||
| getExclusiveMaximumErrorMessage(exclusiveMaximum) { | ||
| return this.#formatMessage("exclusiveMaximum-message", { | ||
| exclusiveMaximum, | ||
| }); | ||
| } | ||
| getMaximumErrorMessage(maximum) { | ||
| return this.#formatMessage("maximum-message", { maximum }); | ||
| } | ||
| getExclusiveMinimumErrorMessage(exclusiveMinimum) { | ||
| return this.#formatMessage("exclusiveMinimum-message", { | ||
| exclusiveMinimum, | ||
| }); | ||
| } | ||
| getMinimumErrorMessage(minimum) { | ||
| return this.#formatMessage("minimum-message", { minimum }); | ||
| } | ||
| getMultipleOfErrorMessage(multipleOf) { | ||
| return this.#formatMessage("multipleOf-message", { multipleOf }); | ||
| } | ||
| getMaxLengthErrorMessage(maxLength) { | ||
| return this.#formatMessage("maxLength-message", { maxLength }); | ||
| } | ||
| getMinLengthErrorMessage(minLength) { | ||
| return this.#formatMessage("minLength-message", { minLength }); | ||
| } | ||
| getPatternErrorMessage(pattern) { | ||
| return this.#formatMessage("pattern-message", { pattern }); | ||
| } | ||
| getMaxItemsErrorMessage(maxItems) { | ||
| return this.#formatMessage("maxItems-message", { maxItems }); | ||
| } | ||
| getMinItemsErrorMessage(minItems) { | ||
| return this.#formatMessage("minItems-message", { minItems }); | ||
| } | ||
| getContainsErrorMessage(range) { | ||
| range.minContains ??= 1; | ||
| if (range.minContains === range.maxContains) { | ||
| return this.#formatMessage("contains-exact-message", range); | ||
| } | ||
| else if (range.maxContains) { | ||
| return this.#formatMessage("contains-range-message", range); | ||
| } | ||
| else { | ||
| return this.#formatMessage("contains-message", range); | ||
| } | ||
| } | ||
| getUniqueItemsErrorMessage() { | ||
| return this.#formatMessage("uniqueItems-message", {}); | ||
| } | ||
| getMaxPropertiesErrorMessage(maxProperties) { | ||
| return this.#formatMessage("maxProperties-message", { maxProperties }); | ||
| } | ||
| getMinPropertiesErrorMessage(minProperties) { | ||
| return this.#formatMessage("minProperties-message", { minProperties }); | ||
| } | ||
| getRequiredErrorMessage(required) { | ||
| return this.#formatMessage("required-message", { | ||
| required: this.conjunction.format(required), | ||
| count: required.length, | ||
| }); | ||
| } | ||
| getAnyOfErrorMessage() { | ||
| return this.#formatMessage("anyOf-message", {}); | ||
| } | ||
| getOneOfErrorMessage(matchCount) { | ||
| return this.#formatMessage("oneOf-message", { matchCount }); | ||
| } | ||
| getNotErrorMessage() { | ||
| return this.#formatMessage("not-message", {}); | ||
| } | ||
| getUnknownErrorMessage(keyword) { | ||
| return this.#formatMessage("unknown-message", { keyword }); | ||
| } | ||
| } |
| import { Localization } from "../localization.js"; | ||
| export declare const localization: Localization; |
| // This file is derived from: | ||
| // https://github.com/hyperjump-io/json-schema-errors/blob/8bda546feeca780ae02c1ebd7247291424ea4a98/src/translations/en-US.ftl | ||
| // Copyright (c) 2026 Hyperjump Software, LLC | ||
| // Licensed under the MIT License | ||
| // Modifications made by Roman Krasilnikov. | ||
| import { FluentBundle, FluentResource } from "@fluent/bundle"; | ||
| import { Localization } from "../localization.js"; | ||
| const source = `// Any type keywords | ||
| boolean-schema-message = A value is not allowed here | ||
| type-message = Expected a {$expectedTypes} | ||
| const-message = Expected exactly {$expected} | ||
| enum-message = Expected one of {$expected} | ||
| format-message = Expected a value matching the '{$format}' format | ||
| unknown-message = Validation failed for '{$keyword}' | ||
| // Number keywords | ||
| exclusiveMaximum-message = Expected a number less than {$exclusiveMaximum} | ||
| exclusiveMinimum-message = Expected a number greater than {$exclusiveMinimum} | ||
| maximum-message = Expected a number less than or equal to {$maximum} | ||
| minimum-message = Expected a number greater than or equal to {$minimum} | ||
| multipleOf-message = Expected a number that is a multiple of {$multipleOf} | ||
| // String keywords | ||
| maxLength-message = Expected a string with no more than {$maxLength} characters | ||
| minLength-message = Expected a string with at least {$minLength} characters | ||
| pattern-message = Expected a string matching the regular expression /{$pattern}/ | ||
| // Array keywords | ||
| maxItems-message = Expected an array with no more than {$maxItems} items | ||
| minItems-message = Expected an array with at least {$minItems} items | ||
| contains-message = Expected an array that contains {$minContains -> | ||
| [1] at least one item matching | ||
| *[other] at least {$minContains} items matching | ||
| } the 'contains' schema | ||
| contains-range-message = Expected an array containing between {$minContains} and {$maxContains} items matching the 'contains' schema | ||
| contains-exact-message = Expected an array containing {$minContains -> | ||
| [1] exactly one item matching | ||
| *[other] exactly {$minContains} items matching | ||
| } the 'contains' schema | ||
| uniqueItems-message = Array items must be unique | ||
| // Object keywords | ||
| maxProperties-message = Expected an object with no more than {$maxProperties} properties | ||
| minProperties-message = Expected an object with at least {$minProperties} properties | ||
| required-message = Missing required {$count -> | ||
| [one] property: {$required} | ||
| *[other] properties: {$required} | ||
| } | ||
| // Applicators | ||
| anyOf-message = Expected the value to match at least one alternative | ||
| oneOf-message = Expected the value to match exactly one alternative, {$matchCount -> | ||
| [0] but none | ||
| *[other] but more than one | ||
| } matched | ||
| not-message = Expected a value that doesn't match the 'not' schema | ||
| `; | ||
| const resource = new FluentResource(source); | ||
| const bundle = new FluentBundle("en-US"); | ||
| bundle.addResource(resource); | ||
| export const localization = new Localization(bundle); |
| import type { NormalizedOutput } from "@hyperjump/json-schema-errors"; | ||
| import type { EvaluationPlugin, Keyword, Node, ValidationContext } from "@hyperjump/json-schema/experimental"; | ||
| import * as Instance from "@hyperjump/json-schema/instance/experimental"; | ||
| type ErrorsContext = ValidationContext & { | ||
| output: NormalizedOutput; | ||
| subSchemaOutput?: NormalizedOutput[]; | ||
| }; | ||
| export declare class JsonSchemaErrorsOutputPlugin implements EvaluationPlugin<ErrorsContext> { | ||
| output: NormalizedOutput; | ||
| constructor(); | ||
| beforeSchema(_url: string, _instance: Instance.JsonNode, context: ErrorsContext): void; | ||
| beforeKeyword(_keywordNode: Node<unknown>, _instance: Instance.JsonNode, context: ErrorsContext, schemaContext: ErrorsContext, _keyword: Keyword<unknown>): void; | ||
| afterKeyword(keywordNode: Node<unknown>, instance: Instance.JsonNode, context: ErrorsContext, valid: boolean, schemaContext: ErrorsContext, keyword: Keyword<unknown>): void; | ||
| afterSchema(url: string, instance: Instance.JsonNode, context: ErrorsContext, valid: boolean): void; | ||
| } | ||
| export {}; |
| // This file is derived from: | ||
| // https://github.com/hyperjump-io/json-schema-errors/blob/8bda546feeca780ae02c1ebd7247291424ea4a98/src/output-plugin.js | ||
| // Copyright (c) 2026 Hyperjump Software, LLC | ||
| // Licensed under the MIT License | ||
| // Modifications made by Roman Krasilnikov. | ||
| import * as Instance from "@hyperjump/json-schema/instance/experimental"; | ||
| export class JsonSchemaErrorsOutputPlugin { | ||
| output; | ||
| constructor() { | ||
| this.output = {}; | ||
| } | ||
| beforeSchema(_url, _instance, context) { | ||
| context.output = {}; | ||
| } | ||
| beforeKeyword(_keywordNode, _instance, context, schemaContext, _keyword) { | ||
| context.output = schemaContext.output; | ||
| } | ||
| afterKeyword(keywordNode, instance, context, valid, schemaContext, keyword) { | ||
| const [keywordUri, schemaLocation] = keywordNode; | ||
| if (keyword.simpleApplicator) { | ||
| for (const subSchemaOutput of context.subSchemaOutput ?? []) { | ||
| mergeOutput(schemaContext.output, subSchemaOutput); | ||
| } | ||
| } | ||
| else { | ||
| schemaContext.output[Instance.uri(instance)] ??= {}; | ||
| schemaContext.output[Instance.uri(instance)][keywordUri] ??= {}; | ||
| schemaContext.output[Instance.uri(instance)][keywordUri][schemaLocation] = valid || (context.subSchemaOutput ?? valid); | ||
| } | ||
| } | ||
| afterSchema(url, instance, context, valid) { | ||
| if (typeof context.ast[url] === "boolean" && !valid) { | ||
| context.output[Instance.uri(instance)] ??= {}; | ||
| context.output[Instance.uri(instance)]["https://json-schema.org/validation"] ??= {}; | ||
| context.output[Instance.uri(instance)]["https://json-schema.org/validation"][url] = valid; | ||
| } | ||
| context.subSchemaOutput ??= []; | ||
| context.subSchemaOutput.push(context.output); | ||
| this.output = context.output; | ||
| } | ||
| } | ||
| const mergeOutput = (a, b) => { | ||
| for (const instanceLocation in b) { | ||
| a[instanceLocation] ??= {}; | ||
| for (const keywordUri in b[instanceLocation]) { | ||
| a[instanceLocation][keywordUri] ??= {}; | ||
| Object.assign(a[instanceLocation][keywordUri], b[instanceLocation][keywordUri]); | ||
| } | ||
| } | ||
| }; |
GitHub dependency
Supply chain riskContains a dependency which resolves to a GitHub URL. Dependencies fetched from GitHub specifiers are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
GitHub dependency
Supply chain riskContains a dependency which resolves to a GitHub URL. Dependencies fetched from GitHub specifiers are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
3
-25%4
-20%32
14.29%0
-100%10696
-50.55%13
-31.58%171
-59.67%1
Infinity%