Gathering detailed insights and metrics for @hyperjump/json-schema
Gathering detailed insights and metrics for @hyperjump/json-schema
Gathering detailed insights and metrics for @hyperjump/json-schema
Gathering detailed insights and metrics for @hyperjump/json-schema
JSON Schema Validation, Annotation, and Bundling. Supports Draft 04, 06, 07, 2019-09, 2020-12, OpenAPI 3.0, and OpenAPI 3.1
npm install @hyperjump/json-schema
98.9
Supply Chain
99.6
Quality
88
Maintenance
100
Vulnerability
100
License
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
223 Stars
187 Commits
21 Forks
8 Watching
2 Branches
4 Contributors
Updated on 19 Nov 2024
Minified
Minified + Gzipped
JavaScript (75.91%)
TypeScript (24.09%)
Cumulative downloads
Total Downloads
Last day
-42.2%
6,956
Compared to previous day
Last week
11.4%
56,137
Compared to previous week
Last month
-6.1%
239,356
Compared to previous month
Last year
229.4%
1,404,435
Compared to previous year
7
1
A collection of modules for working with JSON Schemas.
Includes support for node.js/bun.js (ES Modules, TypeScript) and browsers (works
with CSP
unsafe-eval
).
1npm install @hyperjump/json-schema
This package uses the package.json "exports" field. TypeScript understands
"exports",
but you need to change a couple settings in your tsconfig.json
for it to work.
1 "module": "Node16", // or "NodeNext" 2 "moduleResolution": "Node16", // or "NodeNext"
The API for this library is divided into two categories: Stable and Experimental. The Stable API follows semantic versioning, but the Experimental API may have backward-incompatible changes between minor versions.
All experimental features are segregated into exports that include the word "experimental" so you never accidentally depend on something that could change or be removed in future releases.
This library supports many versions of JSON Schema. Use the pattern
@hyperjump/json-schema/*
to import the version you need.
1import { registerSchema, validate } from "@hyperjump/json-schema/draft-2020-12";
You can import support for additional versions as needed.
1import { registerSchema, validate } from "@hyperjump/json-schema/draft-2020-12"; 2import "@hyperjump/json-schema/draft-07";
Note: The default export (@hyperjump/json-schema
) is reserved for the
stable version of JSON Schema that will hopefully be released in near future.
Validate schema from JavaScript
1registerSchema({ 2 $schema: "https://json-schema.org/draft/2020-12/schema", 3 type: "string" 4}, "http://example.com/schemas/string"); 5 6const output = await validate("http://example.com/schemas/string", "foo"); 7if (output.valid) { 8 console.log("Instance is valid :-)"); 9} else { 10 console.log("Instance is invalid :-("); 11}
Compile schema
If you need to validate multiple instances against the same schema, you can compile the schema into a reusable validation function.
1const isString = await validate("http://example.com/schemas/string"); 2const output1 = isString("foo"); 3const output2 = isString(42);
Fetching schemas
Schemas that are available on the web can be loaded automatically without needing to load them manually.
1const output = await validate("http://example.com/schemas/string", "foo");
When running on the server, you can also load schemas directly from the
filesystem. When fetching from the file system, there are limitations for
security reasons. You can only reference a schema identified by a file URI
scheme (file:///path/to/my/schemas) from another schema identified by a file
URI scheme. Also, a schema is not allowed to self-identify ($id
) with a
file:
URI scheme.
1const output = await validate(`file://${__dirname}/string.schema.json`, "foo");
If the schema URI is relative, the base URI in the browser is the browser location and the base URI on the server is the current working directory. This is the preferred way to work with file-based schemas on the server.
1const output = await validate(`./string.schema.json`, "foo");
You can add/modify/remove support for any URI scheme using the plugin
system provided by
@hyperjump/browser
.
OpenAPI
The OpenAPI 3.0 and 3.1 meta-schemas are pre-loaded and the OpenAPI JSON Schema
dialects for each of those versions is supported. A document with a Content-Type
of application/openapi+json
(web) or a file extension of openapi.json
(filesystem) is understood as an OpenAPI document.
Use the pattern @hyperjump/json-schema/*
to import the version you need. The
available versions are openapi-3-0
for 3.0 and openapi-3-1
for 3.1.
1import { validate } from "@hyperjump/json-schema/openapi-3-1"; 2 3 4// Validate an OpenAPI document 5const output = await validate("https://spec.openapis.org/oas/3.1/schema-base", openapi); 6 7// Validate an instance against a schema in an OpenAPI document 8const output = await validate("./example.openapi.json#/components/schemas/foo", 42);
YAML support isn't built in, but you can add it by writing a
MediaTypePlugin. You can
use the one at lib/openapi.js
as an example and replace the JSON parts with
YAML.
Media types
This library uses media types to determine how to parse a retrieved document. It
will never assume the retrieved document is a schema. By default it's configured
to accept documents with a application/schema+json
Content-Type header (web)
or a .schema.json
file extension (filesystem).
You can add/modify/remove support for any media-type using the plugin
system provided by
@hyperjump/browser
. The following example shows how to add support for JSON
Schemas written in YAML.
1import YAML from "yaml"; 2import contentTypeParser from "content-type"; 3import { addMediaTypePlugin } from "@hyperjump/browser"; 4import { buildSchemaDocument } from "@hyperjump/json-schema/experimental"; 5 6 7addMediaTypePlugin("application/schema+yaml", { 8 parse: async (response) => { 9 const contentType = contentTypeParser.parse(response.headers.get("content-type") ?? ""); 10 const contextDialectId = contentType.parameters.schema ?? contentType.parameters.profile; 11 12 const foo = YAML.parse(await response.text()); 13 return buildSchemaDocument(foo, response.url, contextDialectId); 14 }, 15 fileMatcher: (path) => path.endsWith(".schema.yml") 16});
These are available from any of the exports that refer to a version of JSON
Schema, such as @hyperjump/json-schema/draft-2020-12
.
registerSchema: (schema: object, retrievalUri?: string, defaultDialectId?: string) => void
Add a schema the local schema registry. When this schema is needed, it will be loaded from the register rather than the filesystem or network. If a schema with the same identifier is already registered, an exception will be throw.
unregisterSchema: (uri: string) => void
Remove a schema from the local schema registry.
(deprecated) addSchema: (schema: object, retrievalUri?: string, defaultDialectId?: string) => void
Load a schema manually rather than fetching it from the filesystem or over the network. Any schema already registered with the same identifier will be replaced with no warning.
validate: (schemaURI: string, instance: any, outputFormat: OutputFormat = FLAG) => Promise<OutputUnit>
Validate an instance against a schema. This function is curried to allow compiling the schema once and applying it to multiple instances.
validate: (schemaURI: string) => Promise<(instance: any, outputFormat: OutputFormat = FLAG) => OutputUnit>
Compiling a schema to a validation function.
FLAG: "FLAG"
An identifier for the FLAG
output format as defined by the 2019-09 and
2020-12 specifications.
InvalidSchemaError: Error & { output: OutputUnit }
This error is thrown if the schema being compiled is found to be invalid.
The output
field contains an OutputUnit
with information about the
error. You can use the setMetaSchemaOutputFormat
configuration to set the
output format that is returned in output
.
setMetaSchemaOutputFormat: (outputFormat: OutputFormat) => void
Set the output format used for validating schemas.
getMetaSchemaOutputFormat: () => OutputFormat
Get the output format used for validating schemas.
setShouldMetaValidate: (isEnabled: boolean) => void
Enable or disable validating schemas.
getShouldMetaValidate: (isEnabled: boolean) => void
Determine if validating schemas is enabled.
Type Definitions
The following types are used in the above definitions
OutputFormat: FLAG
Only the FLAG
output format is part of the Stable API. Additional output
formats are included as part of the Experimental API.
OutputUnit: { valid: boolean }
Output is an experimental feature of the JSON Schema specification. There
may be additional fields present in the OutputUnit, but only the valid
property should be considered part of the Stable API.
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 a single JSON document.
The bundling process allows schemas to be embedded without needing to modify any references which means you get the same output details whether you validate the bundle or the original unbundled schemas.
1import { registerSchema } from "@hyperjump/json-schema/draft-2020-12"; 2import { bundle } from "@hyperjump/json-schema/bundle"; 3 4 5registerSchema({ 6 "$schema": "https://json-schema.org/draft/2020-12/schema", 7 8 "type": "object", 9 "properties": { 10 "foo": { "$ref": "/string" } 11 } 12}, "https://example.com/main"); 13 14registerSchema({ 15 "$schema": "https://json-schema.org/draft/2020-12/schema", 16 17 "type": "string" 18}, "https://example.com/string"); 19 20const bundledSchema = await bundle("https://example.com/main"); // { 21// "$schema": "https://json-schema.org/draft/2020-12/schema", 22// 23// "type": "object", 24// "properties": { 25// "foo": { "$ref": "/string" } 26// }, 27// 28// "$defs": { 29// "string": { 30// "$id": "https://example.com/string", 31// "type": "string" 32// } 33// } 34// }
These are available from the @hyperjump/json-schema/bundle
export.
bundle: (uri: string, options: Options) => Promise<SchemaObject>
Create a bundled schema starting with the given schema. External schemas will be fetched from the filesystem, the network, or the local schema registry as needed.
Options:
Change the validation output format
The FLAG
output format isn't very informative. You can change the output
format used for validation to get more information about failures. The official
output format is still evolving, so these may change or be replaced in the
future.
1import { BASIC } from "@hyperjump/json-schema/experimental"; 2 3 4const output = await validate("https://example.com/schema1", 42, BASIC);
Change the schema validation output format
The output format used for validating schemas can be changed as well.
1import { validate, setMetaSchemaOutputFormat } from "@hyperjump/json-schema/draft-2020-12"; 2import { BASIC } from "@hyperjump/json-schema/experimental"; 3 4 5setMetaSchemaOutputFormat(BASIC); 6try { 7 const output = await validate("https://example.com/invalid-schema"); 8} catch (error) { 9 console.log(error.output); 10}
In order to create and use a custom keyword, you need to define your keyword's behavior, create a vocabulary that includes that keyword, and then create a dialect that includes your vocabulary.
Schemas are represented using the
@hyperjump/browser
package. You'll
use that API to traverse schemas. @hyperjump/browser
uses async generators to
iterate over arrays and objects. If you like using higher order functions like
map
/filter
/reduce
, see
@hyperjump/pact
for utilities for
working with generators and async generators.
1import { registerSchema, validate } from "@hyperjump/json-schema/draft-2020-12"; 2import { addKeyword, defineVocabulary, Validation } from "@hyperjump/json-schema/experimental"; 3import * as Browser from "@hyperjump/browser"; 4 5 6// Define a keyword that's an array of schemas that are applied sequentially 7// using implication: A -> B -> C -> D 8addKeyword({ 9 id: "https://example.com/keyword/implication", 10 11 compile: async (schema, ast) => { 12 const subSchemas = []; 13 for await (const subSchema of Browser.iter(schema)) { 14 subSchemas.push(Validation.compile(subSchema, ast)); 15 } 16 return subSchemas; 17 18 // Alternative using @hyperjump/pact 19 // return pipe( 20 // Browser.iter(schema), 21 // asyncMap((subSchema) => Validation.compile(subSchema, ast)), 22 // asyncCollectArray 23 // ); 24 }, 25 26 interpret: (implies, instance, ast, dynamicAnchors, quiet) => { 27 return implies.reduce((valid, schema) => { 28 return !valid || Validation.interpret(schema, instance, ast, dynamicAnchors, quiet); 29 }, true); 30 } 31}); 32 33// Create a vocabulary with this keyword and call it "implies" 34defineVocabulary("https://example.com/vocab/logic", { 35 "implies": "https://example.com/keyword/implication" 36}); 37 38// Create a vocabulary schema for this vocabulary 39registerSchema({ 40 "$id": "https://example.com/meta/logic", 41 "$schema": "https://json-schema.org/draft/2020-12/schema", 42 43 "$dynamicAnchor": "meta", 44 "properties": { 45 "implies": { 46 "type": "array", 47 "items": { "$dynamicRef": "meta" }, 48 "minItems": 2 49 } 50 } 51}); 52 53// Create a dialect schema adding this vocabulary to the standard JSON Schema 54// vocabularies 55registerSchema({ 56 "$id": "https://example.com/dialect/logic", 57 "$schema": "https://json-schema.org/draft/2020-12/schema", 58 59 "$vocabulary": { 60 "https://json-schema.org/draft/2020-12/vocab/core": true, 61 "https://json-schema.org/draft/2020-12/vocab/applicator": true, 62 "https://json-schema.org/draft/2020-12/vocab/unevaluated": true, 63 "https://json-schema.org/draft/2020-12/vocab/validation": true, 64 "https://json-schema.org/draft/2020-12/vocab/meta-data": true, 65 "https://json-schema.org/draft/2020-12/vocab/format-annotation": true, 66 "https://json-schema.org/draft/2020-12/vocab/content": true 67 "https://example.com/vocab/logic": true 68 }, 69 70 "$dynamicAnchor": "meta", 71 72 "allOf": [ 73 { "$ref": "https://json-schema.org/draft/2020-12/schema" }, 74 { "$ref": "/meta/logic" } 75 ] 76}); 77 78// Use your dialect to validate a JSON instance 79registerSchema({ 80 "$schema": "https://example.com/dialect/logic", 81 82 "type": "number", 83 "implies": [ 84 { "minimum": 10 }, 85 { "multipleOf": 2 } 86 ] 87}, "https://example.com/schema1"); 88const output = await validate("https://example.com/schema1", 42);
You can use a custom meta-schema to restrict users to a subset of JSON Schema functionality. This example requires that no unknown keywords are used in the schema.
1registerSchema({ 2 "$id": "https://example.com/meta-schema1", 3 "$schema": "https://json-schema.org/draft/2020-12/schema", 4 5 "$vocabulary": { 6 "https://json-schema.org/draft/2020-12/vocab/core": true, 7 "https://json-schema.org/draft/2020-12/vocab/applicator": true, 8 "https://json-schema.org/draft/2020-12/vocab/unevaluated": true, 9 "https://json-schema.org/draft/2020-12/vocab/validation": true, 10 "https://json-schema.org/draft/2020-12/vocab/meta-data": true, 11 "https://json-schema.org/draft/2020-12/vocab/format-annotation": true, 12 "https://json-schema.org/draft/2020-12/vocab/content": true 13 }, 14 15 "$dynamicAnchor": "meta", 16 17 "$ref": "https://json-schema.org/draft/2020-12/schema", 18 "unevaluatedProperties": false 19}); 20 21registerSchema({ 22 $schema: "https://example.com/meta-schema1", 23 type: "number", 24 foo: 42 25}, "https://example.com/schema1"); 26 27const output = await validate("https://example.com/schema1", 42); // Expect InvalidSchemaError
These are available from the @hyperjump/json-schema/experimental
export.
addKeyword: (keywordHandler: Keyword) => void
Define a keyword for use in a vocabulary.
id: string
A URI that uniquely identifies the keyword. It should use a domain you own to avoid conflict with keywords defined by others.
compile: (schema: Browser, ast: AST, parentSchema: Browser) => Promise<any>
This function takes the keyword value, does whatever preprocessing it
can on it without an instance, and returns the result. The returned
value will be passed to the interpret
function. The ast
parameter
is needed for compiling sub-schemas. The parentSchema
parameter is
primarily useful for looking up the value of an adjacent keyword that
might effect this one.
interpret: (compiledKeywordValue: any, instance: JsonNode, ast: AST, dynamicAnchors: object, quiet: boolean, schemaLocation: string) => boolean
This function takes the value returned by the compile
function and
the instance value that is being validated and returns whether the
value is valid or not. The other parameters are only needed for
validating sub-schemas.
collectEvaluatedProperties?: (compiledKeywordValue: any, instance: JsonNode, ast: AST, dynamicAnchors: object) => Set<string> | false
If the keyword is an applicator, it will need to implement this
function for unevaluatedProperties
to work as expected.
collectEvaluatedItems?: (compiledKeywordValue: A, instance: JsonNode, ast: AST, dynamicAnchors: object) => Set<number> | false
If the keyword is an applicator, it will need to implement this
function for unevaluatedItems
to work as expected.
collectExternalIds?: (visited: Set<string>, parentSchema: Browser, schema: Browser) => Set<string> If the keyword is an applicator, it will need to implement this function to work properly with the bundle feature.
defineVocabulary: (id: string, keywords: { [keyword: string]: string }) => void
Define a vocabulary that maps keyword name to keyword URIs defined using
addKeyword
.
getKeywordId: (keywordName: string, dialectId: string) => string
Get the identifier for a keyword by its name.
getKeyword: (keywordId: string) => Keyword
Get a keyword object by its URI. This is useful for building non-validation tooling.
getKeywordByName: (keywordName: string, dialectId: string) => Keyword
Get a keyword object by its name. This is useful for building non-validation tooling.
getKeywordName: (dialectId: string, keywordId: string) => string
Determine a keyword's name given its URI a dialect URI. This is useful when
defining a keyword that depends on the value of another keyword (such as how
contains
depends on minContains
and maxContains
).
loadDialect: (dialectId: string, dialect: { [vocabularyId: string] }, allowUnknownKeywords: boolean = false) => void
Define a dialect. In most cases, dialects are loaded automatically from the
$vocabulary
keyword in the meta-schema. The only time you would need to
load a dialect manually is if you're creating a distinct version of JSON
Schema rather than creating a dialect of an existing version of JSON Schema.
unloadDialect: (dialectId: string) => void
Remove a dialect. You shouldn't need to use this function. It's called for
you when you call unregisterSchema
.
Validation: Keyword
A Keyword object that represents a "validate" operation. You would use this for compiling and evaluating sub-schemas when defining a custom keyword.
getSchema: (uri: string, browser?: Browser) => Promise<Browser>
Get a schema by it's URI taking the local schema registry into account.
buildSchemaDocument: (schema: SchemaObject | boolean, retrievalUri?: string, contextDialectId?: string) => SchemaDocument
Build a SchemaDocument from a JSON-compatible value. You might use this if you're creating a custom media type plugin, such as supporting JSON Schemas in YAML.
canonicalUri: (schema: Browser) => string
Returns a URI for the schema.
toSchema: (schema: Browser, options: ToSchemaOptions) => object
Get a raw schema from a Schema Document.
ToSchemaOptions: object
$schema
keyword will be omitted.$schema
will only be included if it differs from
contextDialectId
.$id
s will be relative to this
URI.compile: (schema: Browser) => Promise<CompiledSchema>
Return a compiled schema. This is useful if you're creating tooling for something other than validation.
interpret: (schema: CompiledSchema, instance: JsonNode, outputFormat: OutputFormat = BASIC) => OutputUnit
A curried function for validating an instance against a compiled schema. This can be useful for creating custom output formats.
OutputFormat: FLAG | BASIC
In addition to the FLAG
output format in the Stable API, the Experimental
API includes support for the BASIC
format as specified in the 2019-09
specification (with some minor customizations). This implementation doesn't
include annotations or human readable error messages. The output can be
processed to create human readable error messages as needed.
These functions are available from the
@hyperjump/json-schema/instance/experimental
export.
This library uses JsonNode objects to represent instances. You'll work with these objects if you create a custom keyword.
This API uses generators to iterate over arrays and objects. If you like using
higher order functions like map
/filter
/reduce
, see
@hyperjump/pact
for utilities for
working with generators and async generators.
fromJs: (value: any, uri?: string) => JsonNode
Construct a JsonNode from a JavaScript value.
cons: (baseUri: string, pointer: string, value: any, type: string, children: JsonNode[], parent?: JsonNode) => JsonNode
Construct a JsonNode. This is used internally. You probably want fromJs
instead.
get: (url: string, instance: JsonNode) => JsonNode
Apply a same-resource reference to a JsonNode.
uri: (instance: JsonNode) => string
Returns a URI for the value the JsonNode represents.
value: (instance: JsonNode) => any
Returns the value the JsonNode represents.
has: (key: string, instance: JsonNode) => boolean
Returns whether or not "key" is a property name in a JsonNode that represents an object.
typeOf: (instance: JsonNode) => string
The JSON type of the JsonNode. In addition to the standard JSON types,
there's also the property
type that indicates a property name/value pair
in an object.
step: (key: string, instance: JsonNode) => JsonType
Similar to indexing into a object or array using the []
operator.
iter: (instance: JsonNode) => Generator<JsonNode>
Iterate over the items in the array that the JsonNode represents.
entries: (instance: JsonNode) => Generator<[JsonNode, JsonNode]>
Similar to Object.entries
, but yields JsonNodes for keys and values.
values: (instance: JsonNode) => Generator<JsonNode>
Similar to Object.values
, but yields JsonNodes for values.
keys: (instance: JsonNode) => Generator<JsonNode>
Similar to Object.keys
, but yields JsonNodes for keys.
length: (instance: JsonNode) => number
Similar to Array.prototype.length
.
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.
An annotated JSON document is represented as a (JsonNode)[#/instance-api-experimental] AST. You can use this AST to traverse the data structure and get annotations for the values it represents.
1import { registerSchema } from "@hyperjump/json-schema/draft/2020-12"; 2import { annotate } from "@hyperjump/json-schema/annotations/experimental"; 3import * as AnnotatedInstance from "@hyperjump/json-schema/annotated-instance/experimental"; 4 5 6const schemaId = "https://example.com/foo"; 7const dialectId = "https://json-schema.org/draft/2020-12/schema"; 8 9registerSchema({ 10 "$schema": dialectId, 11 12 "title": "Person", 13 "unknown": "foo", 14 15 "type": "object", 16 "properties": { 17 "name": { 18 "$ref": "#/$defs/name", 19 "deprecated": true 20 }, 21 "givenName": { 22 "$ref": "#/$defs/name", 23 "title": "Given Name" 24 }, 25 "familyName": { 26 "$ref": "#/$defs/name", 27 "title": "Family Name" 28 } 29 }, 30 31 "$defs": { 32 "name": { 33 "type": "string", 34 "title": "Name" 35 } 36 } 37}, schemaId); 38 39const instance = await annotate(schemaId, { 40 name: "Jason Desrosiers", 41 givenName: "Jason", 42 familyName: "Desrosiers" 43}); 44 45// Get the title of the instance 46const titles = AnnotatedInstance.annotation(instance, "title", dialectId); // => ["Person"] 47 48// Unknown keywords are collected as annotations 49const unknowns = AnnotatedInstance.annotation(instance, "unknown", dialectId); // => ["foo"] 50 51// The type keyword doesn't produce annotations 52const types = AnnotatedInstance.annotation(instance, "type", dialectId); // => [] 53 54// Get the title of each of the properties in the object 55for (const [propertyNameNode, propertyInstance] of AnnotatedInstance.entries(instance)) { 56 const propertyName = AnnotatedInstance.value(propertyName); 57 console.log(propertyName, AnnotatedInstance.annotation(propertyInstance, "title", dialectId)); 58} 59 60// List all locations in the instance that are deprecated 61for (const deprecated of AnnotatedInstance.annotatedWith(instance, "deprecated", dialectId)) { 62 if (AnnotatedInstance.annotation(deprecated, "deprecated", dialectId)[0]) { 63 logger.warn(`The value at '${deprecated.pointer}' has been deprecated.`); // => (Example) "WARN: The value at '/name' has been deprecated." 64 } 65}
These are available from the @hyperjump/json-schema/annotations/experimental
export.
annotate: (schemaUri: string, instance: any, outputFormat: OutputFormat = BASIC) => Promise<JsonNode>
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 if there is a problem with the schema or a ValidationError if the instance doesn't validate against the schema.
interpret: (compiledSchema: CompiledSchema, instance: JsonNode, outputFormat: OutputFormat = BASIC) => JsonNode
Annotate a JsonNode object rather than a plain JavaScript value. This might be useful when building tools on top of the annotation functionality, but you probably don't need it.
ValidationError: Error & { output: OutputUnit }
The output
field contains an OutputUnit
with information about the
error.
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.
annotation: (instance: JsonNode, keyword: string, dialect?: string): any[];
Get the annotations for a keyword for the value represented by the JsonNode.
annotatedWith: (instance: JsonNode, keyword: string, dialect?: string): JsonNode[];
Get all JsonNodes that are annotated with the given keyword.
setAnnotation: (instance: JsonNode, keywordId: string, value: any) => JsonNode
Add an annotation to an instance. This is used internally, you probably don't need it.
Run the tests
1npm test
Run the tests with a continuous test runner
1npm test -- --watch
No vulnerabilities found.
No security vulnerabilities found.