npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jarenjs/validate

v0.9.2

Published

Jaren is a JavaScript JSON Schema Validator

Downloads

178

Readme

@jarenjs/validate

The JSON Schema validating compiler at the heart of Jaren. It compiles JSON Schemas into optimized validation functions and fully supports draft-06, draft-07, draft 2019-09 and draft 2020-12 — passing 100% of the official JSON-Schema-Test-Suite for draft-07, 2019-09 and 2020-12.

Usage

import { JarenValidator } from '@jarenjs/validate';

const jaren = new JarenValidator();

const validate = jaren.compile({
  type: 'object',
  properties: {
    name: { type: 'string' },
    age: { type: 'integer', minimum: 0 }
  },
  required: ['name']
});

validate({ name: 'John', age: 30 }); // true

Key entry points:

  • new JarenValidator(options) — create a validator instance
  • .addSchema(schema, key) — register schemas for $ref resolution
  • .addMetaSchema(schemas, key) — register (custom) meta-schemas, honoring $vocabulary
  • .addFormats(formats) — register format validators (see @jarenjs/formats)
  • .compile(schema) — compile a schema into a validation function

Highlights:

  • Annotation-based unevaluatedProperties/unevaluatedItems
  • Spec-compliant dynamic scope for $dynamicRef/$dynamicAnchor and $recursiveRef/$recursiveAnchor
  • Per-document draft handling for cross-draft references
  • $vocabulary-aware keyword selection and per-draft format/content assertion defaults
  • Instance-data references via the data keyword (json-everything data-ref) and Ajv-style $data
  • Cross-field assertions via the $query extension keyword (a Jaren JSON Query inside the schema)

🔑 JSON Schema validation keywords

Jaren supports the full set of JSON Schema validation keywords. Here's a quick overview:

  • JSON data type: type, nullable, required
  • Numbers: maximum, minimum, multipleOf
  • Strings: maxLength, minLength, pattern
  • Content: contentEncoding, contentMediaType
  • Arrays: maxItems, minItems, uniqueItems, items, prefixItems, contains, unevaluatedItems
  • Objects: maxProperties, minProperties, required, properties, patternProperties, unevaluatedProperties
  • All types: enum, const
  • Compound: not, oneOf, anyOf, allOf, if/then/else
  • Meta: $schema, $id, $ref, $anchor, $dynamicRef/$dynamicAnchor, $recursiveRef/$recursiveAnchor, $vocabulary
  • Non-standard: data (json-everything's data-ref proposal), Ajv-style $data references, and the $query keyword below

🔑 JSON data type

  • type
  • nullable | (OpenAPI)
  • required | as boolean (OpenAPI)

🔑 Keywords for numbers

  • maximum / minimumor exclusiveMaximum / exclusiveMinimum
  • multipleOf

BigInt instance values are supported too: maximum/minimum/exclusiveMaximum/exclusiveMinimum and multipleOf compile dedicated BigInt comparators when the data is a bigint.

🔑 Keywords for strings

  • maxLength / minLength
  • pattern

🔑 Keywords for content

  • contentEncoding | asserts in draft7, annotation-only from draft2019 on (spec default), controlled by the contentValidation option
  • contentMediaType | same assertion defaults; application/json content is parse-checked
  • ❌ contentSchema | annotation only (never asserted)

🔑 Keywords for format

  • format
  • formatMinimum / formatMaximumor formatExclusiveMinimum / formatExclusiveMaximum

🔑 Keywords for array

  • maxItems / minItems
  • uniqueItems
  • items
    • items | as schema or tuple deprecated in draft2020
    • items | as schema only new draft2020
  • prefixItems | as tuple new draft2020
  • additionalItems | as schema deprecated in draft2020
  • contains
  • maxContains / minContains | new draft2019
  • unevaluatedItems | new draft2019

🔑 Keywords for object

  • maxProperties / minProperties
  • required | as array!
  • properties
  • patternProperties
  • additionalProperties
  • dependencies | deprecated in draft2019
  • dependentRequired | new draft2019
  • dependentSchemas | new draft2019
  • propertyNames
  • unevaluatedProperties | new draft2019
  • propertyDependencies

🔑 Keywords for all types

  • enum
  • const

🔑 Compound keywords

  • not
  • oneOf
  • anyOf
  • allOf
  • if / then / else

See also:

🔑 Meta keywords

  • $schema | used for draft detection, vocabulary selection and cross-draft references
  • $id
  • $ref
  • $anchor
  • $recursiveRef | new draft2019 & deprecated in draft2020
  • $recursiveAnchor | new draft2019 & deprecated in draft2020
  • $dynamicRef | new draft2020
  • $dynamicAnchor | new draft2020
  • $data | (Ajv specific)
  • $vocabulary | new draft2019 - a custom metaschema that omits the validation vocabulary turns keywords like type and minimum into annotations; a metaschema that declares the format-assertion vocabulary turns format assertion on

🔑 Non-standard keywords

  • data | json-everything's data-ref proposal

    The data keyword allows you to reference values from the instance being validated, enabling dynamic constraints based on other parts of the data.

    Example - Requiring B >= A:

    {
      "type": "object",
      "properties": {
        "A": { "type": "number" },
        "B": {
          "type": "number",
          "data": {
            "minimum": "/A"
          }
        }
      }
    }
    • Passes: { "A": 5, "B": 10 } (10 >= 5)
    • Fails: { "A": 15, "B": 10 } (10 < 15)

    Example - Enum from instance array:

    {
      "type": "object",
      "properties": {
        "color": {
          "data": {
            "enum": "/validColors"
          }
        },
        "validColors": {
          "type": "array",
          "items": { "type": "string" }
        }
      }
    }

    Supported keywords within data:

    • Number constraints: minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf
    • String constraints: minLength, maxLength, pattern, format
    • Array constraints: minItems, maxItems
    • Object constraints: minProperties, maxProperties
    • Value constraints: enum, const

    Both absolute JSON Pointers (e.g., /A, /limits/min) and relative JSON Pointers (e.g., 0/parent, 1/sibling) are supported.

  • $data | Ajv-style instance references ({ "minimum": { "$data": "1/limit" } }) — supports every keyword the data list above supports, plus uniqueItems and required. Refs compile once at schema compile time through the compiled pointer engine of @jarenjs/json.

  • $query | Jaren's cross-field assertion keyword — see below

🔑 Miscellaneous keywords

  • ❌ strict
  • ❌ strictFormat
  • ❌ strictTuple
  • ❌ errorMessage
  • definitions | used by initial schema traversal deprecated in draft2019
  • $defs | used by initial schema traversal new draft2019
  • components | (OpenAPI)

🛠️ Notable capabilities

👉 Modelling Inheritance with JSON Schema

Jaren fully supports unevaluatedProperties, so the inheritance patterns from the Modelling Inheritance blog post work out of the box. Annotations flow from properties, patternProperties, additionalProperties and every in-place applicator (allOf/anyOf/oneOf/if-then-else/$ref/dependentSchemas), with annotations from failed branches correctly discarded.

See also:

👉 Express array constraints more cleanly

Jaren fully supports unevaluatedItems, covering the array patterns from the 2020-12 release notes: items evaluated by items, prefixItems, additionalItems and (in 2020-12) contains are tracked, and everything left over is validated by the unevaluatedItems schema.

👉 Using Dynamic References to Support Generic Types

Jaren fully supports $dynamicRef/$dynamicAnchor (2020-12) and $recursiveRef/$recursiveAnchor (2019-09), including the generic-type patterns from the dynamicRef and generics blog post. Resolution follows the specification's dynamic-scope rules: entering a schema resource brings all of its dynamic anchors into scope, and a $dynamicRef resolves to the anchor in the outermost resource of the dynamic scope.

See also:

👉 Runtime schema manipulation of constraints

Jaren supports the data-ref proposal from json-everything through the data keyword, plus Ajv-style $data references. Both allow a schema constraint to take its value from the instance being validated:

  • Absolute JSON Pointers (e.g., /A, /limits/min)
  • Relative JSON Pointers (e.g., 0/parent, 1/sibling)
  • All common constraint keywords: minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, minLength, maxLength, pattern, format, enum, const, minItems, maxItems, minProperties, maxProperties

The refs compile once at schema compile time through the compiled pointer engine of @jarenjs/json and resolve allocation-free per validation.

See also:

👉 Vocabularies and cross-draft references

A schema's $schema declaration is honored per document: referenced documents that declare a different draft are processed with that draft's keyword set (a draft-07 document ignores dependentRequired; a 2019-09 document ignores prefixItems). Custom metaschemas with $vocabulary are respected — omitting the validation vocabulary turns validation keywords into annotations, and declaring format-assertion turns format assertion on.

$query — cross-field assertions

$query is a Jaren extension keyword: its value is a Jaren JSON Query document, compiled once at schema compile time and evaluated per validation against the current instance location. The instance is valid when the query result's effective boolean value is true. This gives JSON Schema the class of constraint it is notoriously bad at — cross-field arithmetic, ordering, aggregate consistency, quantification — through the query engine that already sits underneath the stack. Other validators treat $query as an unknown-keyword annotation, so schemas using it stay portable; the constraint simply only asserts here.

An invoice whose total must equal the sum of its line amounts:

const validate = jaren.compile({
  type: 'object',
  properties: {
    lines: { type: 'array', items: { type: 'object' } },
    total: { type: 'number' }
  },
  $query: { $eq: ['$.total', { $sum: '$.lines[*].amount' }] }
});

validate({ lines: [{ amount: 12.5 }, { amount: 7.5 }], total: 20 }); // true
validate({ lines: [{ amount: 12.5 }, { amount: 7.5 }], total: 21 }); // false

Date ordering ($le compares strings by code points, QUERY-FORMAT §8.4 — exactly right for ISO dates):

jaren.compile({ $query: { $le: ['$.start', '$.end'] } });

Quantification over items:

jaren.compile({
  $query: { $every: { l: '$.lines[*]' }, $satisfies: { $gt: ['$l.qty', 0] } }
});

Two external parameters are bound on every evaluation: root — the instance root — and path — the current instance location as a JSON pointer string. (The JSLT template layer reserves the same two names with one twist: its matching language is JSONPath, so its path is an RFC 9535 normalized path, not a pointer — see JSLT-FORMAT §8.2.) So a subschema can reach across the document:

jaren.compile({
  type: 'object',
  properties: {
    lines: {
      type: 'array',
      items: {
        type: 'object',
        // every line's currency must match the document-level currency
        $query: { $eq: ['$.currency', '$root.currency'] }
      }
    }
  }
});

Semantics and composition:

  • $query works at any subschema level and composes like every other keyword: under properties/items the query's $ is that location's value, $path its pointer (/lines/0, ...), $root the whole document.
  • A bare JSONPath string is the degenerate query: { "$query": "$.approved" } asserts the EBV of that member (missing → empty sequence → false).
  • Query runtime errors (JQ2xxx — e.g. arithmetic on a non-number, the EBV of a multi-item result) are validation failures, never throws; in collectErrors mode the error params carry the code and the query docPath. Malformed query documents and free externals other than root/path fail fast at compile().
  • Schema literals inside the query ($valid/$assert/$as, QUERY-FORMAT §8.11) compile against the same validator instance, so their $refs resolve to your addSchema registrations.

Development

Unit tests live in test/validate/ at the repository root (npm run test:validate). Performance against Ajv is measured over the official test suite with the benchmark workspace (node benchmark/profiler.js --profile-all), which also houses the test-failure debugger, coverage and call-graph tools.

This package's internals — the four-phase compile pipeline, ref flattening, annotation tracking, dynamic scope — are described in its own ARCHITECTURE document. For practical usage recipes (options, lightweight setups, custom formats, pitfalls) see the repository HOWTO; for the monorepo picture see the repository README and ARCHITECTURE; for what is planned next see the ROADMAP.