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

@shexjs/validator

v1.0.0-alpha.33

Published

Shape Expressions Validator and schema index generator.

Readme

@shexjs/validator

npm version CI

Validate nodes in an RDF graph against shapes in a ShEx schema.

The validator takes a schema (parsed ShExJ), a data interface (a @shexjs/neighborhood-api implementation over an RDF/JS store, a SPARQL endpoint, a Wikibase…) and a shape map saying which nodes to test against which shapes.

Install

npm install @shexjs/validator

Quick start

const {ShExValidator} = require("@shexjs/validator");
const {ctor: RdfJsDb} = require("@shexjs/neighborhood-rdfjs");
const {Store, Parser} = require("n3");
const base = "http://a.example/";

const schema = require("@shexjs/parser").construct(base).parse(`
<S1> { <p1> . ; <p2> . }`);
const graph = new Store(new Parser({baseIRI: base}).parse(`
<n1> <p1> 1 ; <p2> 2 .
<n2> <p1> 3 ; <p3> 4 . # p3 where <S1> wants p2
`));

const validator = new ShExValidator(schema, RdfJsDb(graph));
const results = validator.validateShapeMap([
  {node: base + "n1", shape: base + "S1"},
  {node: base + "n2", shape: base + "S1"},
]);
results.forEach(r => console.log(r.node, r.status));
http://a.example/n1 conformant
http://a.example/n2 nonconformant

To validate against the schema's start shape, pass the Start sentinel from @shexjs/term as the shape:

const {Start} = require("@shexjs/term");
validator.validateShapeMap([{node: base + "n1", shape: Start}]);

The results

validateShapeMap returns the shape map with each association's status filled in and an appinfo saying why. For the nonconformant n2 above:

{
  "node": "http://a.example/n2",
  "shape": "http://a.example/S1",
  "status": "nonconformant",
  "appinfo": {
    "type": "Failure",
    "node": "http://a.example/n2",
    "shape": "http://a.example/S1",
    "errors": [
      {
        "type": "MissingProperty",
        "property": "http://a.example/p2"
      }
    ],
    "repairs": [
      {
        "type": "NearestBag",
        "cost": 1,
        "arcs": [
          {
            "property": "http://a.example/p2",
            "delta": 1
          }
        ]
      }
    ]
  }
}

errors says what failed; repairs says the cheapest edits that would have made it pass (here: add one <p2> arc). @shexjs/util's errsToSimple renders either as sentences.

Validation proof

A conformant association's appinfo is a proof: which triples matched which constraints. For n1 above:

{
  "type": "ShapeTest",
  "node": "http://a.example/n1",
  "shape": "http://a.example/S1",
  "solution": {
    "type": "EachOfSolutions",
    "solutions": [
      {
        "type": "EachOfSolution",
        "expressions": [
          {
            "type": "TripleConstraintSolutions",
            "predicate": "http://a.example/p1",
            "solutions": [
              {
                "type": "TestedTriple",
                "subject": "http://a.example/n1",
                "predicate": "http://a.example/p1",
                "object": {
                  "value": "1",
                  "type": "http://www.w3.org/2001/XMLSchema#integer"
                }
              }
            ]
          },
          {
            "type": "TripleConstraintSolutions",
            "predicate": "http://a.example/p2",
            "solutions": [
              {
                "type": "TestedTriple",
                "subject": "http://a.example/n1",
                "predicate": "http://a.example/p2",
                "object": {
                  "value": "2",
                  "type": "http://www.w3.org/2001/XMLSchema#integer"
                }
              }
            ]
          }
        ]
      }
    ]
  }
}

See the ShEx primer for validation semantics and ShExV for the results vocabulary.

Choosing a matching engine

The triple expression in a Shape is essentially a fancy regular expression, and the engine that matches it is pluggable (@shexjs/eval-validator-api). shex.js ships two:

Select one with the options parameter to the constructor:

new ShExValidator(schema, RdfJsDb(graph), {
  regexModule: require("@shexjs/eval-simple-1err").RegexpModule
});

External shapes

One form of ShEx extensibility is the declaration of external shapes:

<S1> {
  <p1> @<S2>
}
<S2> EXTERNAL

The ShEx specification doesn't say how these are supplied; in shex.js, pass a validateExtern function in the options:

new ShExValidator(schema, RdfJsDb(g), {
  validateExtern: myValidator
});

// (RdfJs.Term, string, ShapeExprValidationContext) -> shapeExprTest
function myValidator (point, shapeLabel, ctx) {
  if (shapeLabel === "http://a.example/S2") {
    const p2z = g.getQuads(point, "http://a.example/p2", null);
    if (p2z.length === 1) {
      return {
        "type": "ShapeTest",
        "node": point.value,
        "shape": "http://a.example/S2",
        "solution": {
          "type": "TripleConstraintSolutions",
          "predicate": "http://a.example/p2",
          "solutions": [
            {
              "type": "TestedTriple",
              "subject": point.value,
              "predicate": "http://a.example/p2",
              "object": p2z[0].object.value
            }
          ]
        }
      };
    }
  }
}

Validating a schema with external shapes and no validateExtern raises:

Error: validating "http://a.example/n2" as EXTERNAL shapeExpr http://a.example/S2 requires a 'validateExtern' option

Testing

Run this package's tests from packages/:

cd .. && npx mocha -C shex-validator/test/Validation-test.js

Selecting tests

Set TESTS to a regular expression matched against test ids, schema and data file names to run a subset:

TESTS='vitals-RESTRICTS' npx mocha -C shex-validator/test/Validation-test.js

Regenerating reference results (REGEN=1)

Validation-test.js compares validation output against the reference results in test/val/ (as mapped by test/val/test-result-map.json). When an intentional change to the validator alters the ShExResults structures, set REGEN=1 to rewrite the reference file of any test whose (canonicalized) result no longer matches, instead of failing the assertion:

TESTS='(ExtendsRepeatedP-pass|2dot_fail-empty-err)' REGEN=1 npx mocha -C shex-validator/test/Validation-test.js

The run reports the regenerated tests as passing; review the rewritten files with git diff (or ediff) and commit the ones that reflect the intended change. Always scope REGEN with TESTS to the tests you mean to regenerate — an unscoped REGEN=1 run will absorb any mismatch, including real regressions. Tests without an entry in test-result-map.json only check conformance status and are unaffected.

Result names

When validating EXTENDS hierarchies, the first result for each extension/subgraph pair carries a "resultName"; identical re-examinations in later partitions emit {"type": "ResultReference", "ref": <resultName>} instead of repeating it. A result name is the focus node followed by a ShExPath expression addressing the extension: a labeled extension by its shape-declaration selector,

<http://a.example/s>@<http://a.example/#B>

an inline extension by a step into the extending shape's EXTENDS list (…@<label>/extends/*[0] — extends selects the list, which is an item of its own in ShExPath, /* steps into it and [0] picks the first out). Only when the same node and extension are validated against a different subgraph is a disambiguating #2, #3, … appended.


@shexjs/validator is one of the shex.js packages; installing shex pulls in the whole suite, and its README maps them.