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

eyeling

v1.7.1

Published

A minimal Notation3 (N3) reasoner in JavaScript.

Downloads

7,156

Readme

eyeling

A Notation3 (N3) reasoner in JavaScript.

eyeling is:

  • a single self-contained file (eyeling.js, no external deps)
  • a practical N3/Turtle superset (enough for lots of real rulesets)
  • supports forward (=>) + backward (<=) chaining over Horn-style rules
  • prints only newly derived forward facts, optionally preceded by compact proof comments
  • “pass-only-new” style output (we never want to leak raw input data; backward rules can act like “functions” over raw data)
  • works fully client-side (browser) and in Node.js

Playground

Try it here:

The playground runs eyeling client-side. You can:

  • edit an N3 program directly
  • load an N3 program from a URL (in the "Load N3 from URL" box or as ?url=...)
  • share a link with the program encoded in the URL fragment (#...)

Quick start

Requirements

  • Node.js >= 18 (anything modern with BigInt support is fine)

Install

npm i eyeling

CLI

Run on a file:

npx eyeling examples/socrates.n3

(Or install globally: npm i -g eyeling and run eyeling ....)

JavaScript API

const { reason } = require("eyeling");

const input = `
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix : <http://example.org/socrates#>.

:Socrates a :Human.
:Human rdfs:subClassOf :Mortal.

{ ?S a ?A. ?A rdfs:subClassOf ?B } => { ?S a ?B }.
`;

const output = reason({ proofComments: false }, input);
console.log(output);

ESM:

import eyeling from "eyeling";
const output = eyeling.reason({ proofComments: false }, input);
console.log(output);

Note: the API currently shells out to the bundled eyeling.js CLI under the hood (simple + robust).

Testing

From a repo checkout:

npm test

Or run individual suites:

npm run test:api
npm run test:examples
npm run test:package
npm run test:packlist
  • test:api runs an independent JS API test suite (does not rely on examples/).
  • test:examples runs the examples in the examples directory and compares against the golden outputs in examples/output.
  • test:package does a “real consumer” smoke test: npm pack → install tarball into a temp project → run API + CLI + examples.
  • test:packlist sanity-checks what will be published in the npm tarball (and the CLI shebang/bin wiring).

Usage

Usage: eyeling [options] <file.n3>

Options:
  -h, --help              Show this help and exit.
  -v, --version           Print version and exit.
  -p, --proof-comments    Enable proof explanations.
  -n, --no-proof-comments Disable proof explanations (default).
  -s, --super-restricted  Disable all builtins except => and <=.
  -a, --ast               Print parsed AST as JSON and exit.

By default, eyeling:

  1. parses the input (facts + rules)
  2. runs forward chaining to a fixpoint
  3. prints only newly derived forward facts (not the original input facts)
  4. prints a compact per-triple explanation as # comments (can be disabled)

What output do I get?

For each newly derived triple, eyeling prints:

  1. a proof-style comment block explaining why the triple holds (unless -n), and then
  2. the triple itself in N3/Turtle syntax.

The proof comments are compact “local justifications” per derived triple (not a single exported global proof tree).

Reasoning model

Forward + backward chaining

  • Forward chaining to fixpoint for forward rules written as { P } => { C } .
  • Backward chaining (SLD-style) for backward rules written as { H } <= { B } . and for built-ins.

Forward rule premises are proved using:

  • ground facts (input + derived)
  • backward rules
  • built-ins

The CLI prints only newly derived forward facts.

Performance notes

eyeling includes a few key performance mechanisms:

  • facts are indexed for matching:
    • by predicate, and (when possible) by (predicate, object) (important for type-heavy workloads)
  • IRIs/literals are interned to reduce allocations and speed up comparisons/lookups
  • parsed numeric literals are cached, and rule standardization reuses unchanged subterms to cut repeated parsing/allocation
  • duplicate detection uses a fast key path when a triple is fully IRI/Literal-shaped
  • backward rules are indexed by head predicate
  • the backward prover is iterative (explicit stack), so deep chains won’t blow the JS call stack
  • for very deep backward chains, substitutions may be compactified (semantics-preserving) to avoid quadratic “copy a growing substitution object” behavior

Blank nodes and quantification

eyeling follows the usual N3 intuition:

  1. blank nodes in facts are normal RDF blanks (_:b1, _:b2, … within a run)
  2. blank nodes in rule premises behave like rule-scoped universals (similar to variables)
  3. blank nodes only in rule conclusions behave like existentials: each rule firing generates fresh Skolem blanks (_:sk_0, _:sk_1, …)

Equal facts up to renaming of Skolem IDs are treated as duplicates and are not re-added.

Rule-producing rules aka meta-rules

eyeling understands the log:implies / log:impliedBy idiom.

Top level:

  • { P } log:implies { C } . becomes a forward rule { P } => { C } .
  • { H } log:impliedBy { B } . becomes a backward rule { H } <= { B } .

During reasoning:

  • any derived log:implies / log:impliedBy triple with formula subject/object is turned into a new live forward/backward rule.

Inference fuse

Rules whose conclusion is false are treated as hard failures:

:stone :color :black .
:stone :color :white .

{ ?X :color :black . ?X :color :white . } => false.

As soon as the premise is provable, eyeling exits with status code 2.

Syntax + built-ins

eyeling’s parser targets (nearly) the full Notation3 Language grammar from the W3C N3 Community Group spec.

In practice this means: it’s a Turtle superset that also accepts quoted formulas, rules, paths, and the N3 “syntax shorthand” operators (=, =>, <=) described in the spec.

Commonly used N3/Turtle features:

  • Prefix/base directives (@prefix / @base, and SPARQL-style PREFIX / BASE)
  • Triples with ; and ,
  • Variables (?x)
  • Blank nodes ([], and [ :p :o; :q :r ])
  • Collections ( ... )
  • Quoted formulas { ... }
  • Implications (=>, <=)
  • Datatyped literals (^^) and language tags ("..."@en)
  • Inverse predicate sugar (<- and keyword forms like is ... of)
  • Resource paths (! and ^)
  • # line comments

eyeling implements a pragmatic subset of common N3 builtin families and evaluates them during backward goal proving:

  • crypto: crypto:md5 crypto:sha crypto:sha256 crypto:sha512
  • list: list:append list:first list:firstRest list:in list:iterate list:last list:length list:map list:member list:memberAt list:notMember list:remove list:rest list:reverse list:sort
  • log: log:collectAllIn log:equalTo log:forAllIn log:impliedBy log:implies log:notEqualTo log:notIncludes log:skolem log:uri
  • math: math:absoluteValue math:acos math:asin math:atan math:cos math:cosh math:degrees math:difference math:equalTo math:exponentiation math:greaterThan math:integerQuotient math:lessThan math:negation math:notEqualTo math:notGreaterThan math:notLessThan math:product math:quotient math:remainder math:rounded math:sin math:sinh math:sum math:tan math:tanh
  • string: string:concatenation string:contains string:containsIgnoringCase string:endsWith string:equalIgnoringCase string:format string:greaterThan string:jsonPointer string:lessThan string:matches string:notEqualIgnoringCase string:notGreaterThan string:notLessThan string:notMatches string:replace string:scrape string:startsWith
  • time: time:localTime

License

MIT (see LICENSE).