@@ -212,11 +212,11 @@ Schema, such as `@hyperjump/json-schema/draft-2020-12`.
212212 Load a schema manually rather than fetching it from the filesystem or over
213213 the network. Any schema already registered with the same identifier will be
214214 replaced with no warning.
215- * **validate**: (schemaURI: string, instance: any, outputFormat: OutputFormat = FLAG) => Promise\< OutputUnit>
215+ * **validate**: (schemaURI: string, instance: any, outputFormat: ValidationOptions | OutputFormat = FLAG) => Promise\< OutputUnit>
216216
217217 Validate an instance against a schema. This function is curried to allow
218218 compiling the schema once and applying it to multiple instances.
219- * **validate**: (schemaURI: string) => Promise\< (instance: any, outputFormat: OutputFormat = FLAG) => OutputUnit>
219+ * **validate**: (schemaURI: string) => Promise\< (instance: any, outputFormat: ValidationOptions | OutputFormat = FLAG) => OutputUnit>
220220
221221 Compiling a schema to a validation function.
222222* **FLAG**: "FLAG"
@@ -255,6 +255,10 @@ The following types are used in the above definitions
255255 Output is an experimental feature of the JSON Schema specification. There
256256 may be additional fields present in the OutputUnit, but only the ` valid`
257257 property should be considered part of the Stable API.
258+ * **ValidationOptions**:
259+
260+ * outputFormat?: OutputFormat
261+ * plugins?: EvaluationPlugin[]
258262
259263## Bundling
260264
@@ -504,6 +508,57 @@ registerSchema({
504508const output = await validate (" https://example.com/schema1" , 42 ); // Expect InvalidSchemaError
505509` ` `
506510
511+ ### EvaluationPlugins
512+
513+ EvaluationPlugins allow you to hook into the validation process for various
514+ purposes. There are hooks for before an after schema evaluation and before and
515+ after keyword evaluation. (See the API section for the full interface) The
516+ following is a simple example to record all the schema locations that were
517+ evaluated. This could be used as part of a solution for determining test
518+ coverage for a schema.
519+
520+ ` ` ` JavaScript
521+ import { registerSchema , validate } from " @hyperjump/json-schema/draft-2020-12" ;
522+ import { BASIC } from " @hyperjump/json-schema/experimental.js" ;
523+
524+ class EvaluatedKeywordsPlugin {
525+ constructor () {
526+ this .schemaLocations = new Set ();
527+ }
528+
529+ beforeKeyword ([, schemaUri ]) {
530+ this .schemaLocations .add (schemaUri);
531+ }
532+ }
533+
534+ registerSchema ({
535+ $schema: " https://json-schema.org/draft/2020-12/schema" ,
536+ type: " object" ,
537+ properties: {
538+ foo: { type: " number" },
539+ bar: { type: " boolean" }
540+ },
541+ required: [" foo" ]
542+ }, " https://schemas.hyperjump.io/main" );
543+
544+ const evaluatedKeywordPlugin = new EvaluatedKeywordsPlugin ();
545+
546+ await validate (" https://schemas.hyperjump.io/main" , { foo: 42 }, {
547+ outputFormat: BASIC ,
548+ plugins: [evaluatedKeywordPlugin]
549+ });
550+
551+ console .log (evaluatedKeywordPlugin .schemaLocations );
552+ // Set(4) {
553+ // 'https://schemas.hyperjump.io/main#/type',
554+ // 'https://schemas.hyperjump.io/main#/properties',
555+ // 'https://schemas.hyperjump.io/main#/properties/foo/type',
556+ // 'https://schemas.hyperjump.io/main#/required'
557+ // }
558+
559+ // NOTE: #/properties/bar is not in the list because the instance doesn't include that property.
560+ ` ` `
561+
507562### API
508563
509564These are available from the ` @hyperjump/ json- schema/ experimental` export.
@@ -543,15 +598,13 @@ These are available from the `@hyperjump/json-schema/experimental` export.
543598 function to return the annotation.
544599 * plugin?: EvaluationPlugin
545600
601+ If the keyword needs to track state during the evaluation process, you
602+ can include an EvaluationPlugin that will get added only when this
603+ keyword is present in the schema.
604+
546605 * **ValidationContext**: object
547606 * ast: AST
548607 * plugins: EvaluationPlugins[]
549-
550- * **EvaluationPlugin**: object
551- * beforeSchema(url: string, instance: JsonNode, context: Context): void
552- * beforeKeyword(keywordNode: Node<any>, instance: JsonNode, context: Context, schemaContext: Context, keyword: Keyword): void
553- * afterKeyword(keywordNode: Node<any>, instance: JsonNode, context: Context, valid: boolean, schemaContext: Context, keyword: Keyword): void
554- * afterSchema(url: string, instance: JsonNode, context: Context, valid: boolean): void
555608* **defineVocabulary**: (id: string, keywords: { [keyword: string]: string }) => void
556609
557610 Define a vocabulary that maps keyword name to keyword URIs defined using
@@ -630,6 +683,12 @@ These are available from the `@hyperjump/json-schema/experimental` export.
630683 include annotations or human readable error messages. The output can be
631684 processed to create human readable error messages as needed.
632685
686+ * **EvaluationPlugin**: object
687+ * beforeSchema?(url: string, instance: JsonNode, context: Context): void
688+ * beforeKeyword?(keywordNode: CompiledSchemaNode, instance: JsonNode, context: Context, schemaContext: Context, keyword: Keyword): void
689+ * afterKeyword?(keywordNode: CompiledSchemaNode, instance: JsonNode, context: Context, valid: boolean, schemaContext: Context, keyword: Keyword): void
690+ * afterSchema?(url: string, instance: JsonNode, context: Context, valid: boolean): void
691+
633692## Instance API (experimental)
634693
635694These functions are available from the
0 commit comments