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

waarmerk

v0.1.0

Published

Tiny and spoof-proof located diagnostics for JavaScript parsers.

Readme

waarmerk

Hand a parser's error to the code that embedded it — span moved, metadata intact, and the parser still vouching for it. ~0.5KB min+gzip, zero runtime dependencies.

NPM version Build Status NPM downloads Apache-2.0 license

Any parser embedded in something larger reports faults in its own coordinates: a template engine's expression compiler counts from the start of the expression, not the file; a query engine's pattern matcher counts from the start of the pattern, not the query. The code around it has to move those numbers, and usually does it by rebuilding the error and losing half of what was on it.

waarmerk is the handover. The parser mints an error only it can vouch for, and re-issues it in the caller's coordinates on request — same class, every field, still authentic.

Waarmerk is Dutch for a hallmark — the mark that says whose something is, and that it is genuine.

Install

npm install waarmerk

Node.js 22 or newer, ESM only.

Usage

A spreadsheet embeds a formula parser. The parser sees 4 * 5 and reports column 2; the user is looking at =4 * 5 in cell C3. Someone has to move that number, and it should not be the spreadsheet guessing at the parser's internals.

// csv-math/index.js — the parser
import { mint, relocate as relocateFault, store } from "waarmerk";

const diags = store("csv-math");
export const isDiagnostic = diags.isDiagnostic;
export const relocate = (diag, opts) => relocateFault(diags, diag, opts);

export function evaluate(source) {
  const at = source.search(/[^0-9+ ]/);
  if (at !== -1) {
    mint(diags, SyntaxError, `Unexpected "${source[at]}"`, {
      code: "CSVMATH_SYNTAX",
      start: at,
      end: at + 1,
    });
  }
  return source.split("+").reduce((sum, n) => sum + Number(n), 0);
}
// your spreadsheet, which embeds it
import { evaluate, isDiagnostic, relocate } from "csv-math";

const recalc = (cells) =>
  cells.map(({ ref, formula }) => {
    try {
      // The parser never sees the leading "=", so its columns are one short.
      return evaluate(formula.slice(1));
    } catch (error) {
      if (!isDiagnostic(error)) throw error;
      throw relocate(error, { prefix: `${ref}: `, offset: 1 });
    }
  });

recalc([{ ref: "C3", formula: "=4 * 5" }]);
// SyntaxError: C3: Unexpected "*"
//   .code  "CSVMATH_SYNTAX"
//   .start 3   .end 4        <- moved from 2, now pointing at "*" in "=4 * 5"

The copy is a real SyntaxError, carries every field the parser put on it, and still passes csv-math's own isDiagnostic. The spreadsheet wrote none of that.

Why not just throw an error with a code on it?

You can, and for a parser nobody embeds you should. Three things go wrong once something does embed it:

  • Shape is not identity. error.code && error.start != null is true of any error that happens to look right, including one thrown from a callback you were handed. waarmerk authenticates against a WeakMap only the parser holds, so a look-alike fails.
  • A hand-rolled copy drops fields. The embedder copies message, code, start, end — then the parser adds a hint in a minor release and nobody downstream hears about it. waarmerk copies by descriptor, so a field added later travels for free.
  • A hand-rolled copy is a stranger. It fails the parser's own guard, so any code that catches it further out no longer recognises it. waarmerk's copy joins the same store.

Exposing it from your own package

Callers should never need to know waarmerk is involved, or hold your store. Re-export two names:

const diags = store("csv-math");

export const isDiagnostic = diags.isDiagnostic;
export const relocate = (diag, opts) => relocateFault(diags, diag, opts);

That is the whole integration. One store per package, made once at module load.

Name your store, and relocate refuses a foreign error as TypeError("Not a diagnostic from csv-math") rather than naming a dependency your caller never chose. store() without a name says waarmerk.

When the text crossed a decode

offset shifts a span, and it is right whenever the parser read a verbatim slice of your text. It is wrong when your text was decoded first — a pattern pulled out of a JSON string literal, where \\d is three characters standing for two and every later column slides. There is no offset that fixes that, so name the region instead:

throw relocate(error, { prefix: "$.a[?match(@.b, ...)]: ", span: [16, 24] });

span replaces the span outright, and wins if you pass both. Neither option ever adds a span to a diagnostic that had none.

Budgets

Parsers that accept untrusted input usually cap something. capped mints that failure with a consistent shape, so an embedder can tell "your input was malformed" from "your input was too big":

capped(diags, "maxNodes", "CSVMATH_MAX_NODES", 100, 101);
// RangeError: maxNodes limit of 100 exceeded
//   .code "CSVMATH_MAX_NODES"   .limit 100   .actual 101

These carry no span, and relocation leaves them that way.

Adding your own context

When you embed a parser and want to be an authority on its faults too, adopt takes its diagnostic into your store as well. The copy then belongs to both, and passes both guards:

import { adopt } from "waarmerk";
import { isDiagnostic as isExpression, relocate as relocateExpression } from "csv-math";

try {
  evaluate(body);
} catch (error) {
  if (!isExpression(error)) throw error;
  // csv-math stays the authority on the syntax; you add where it sat.
  throw adopt(diags, relocateExpression(error, { offset: at }), { blocks: open() });
}

TypeScript

Types ship with the package. Diagnostic names the fields waarmerk knows about; narrow it to your own:

import { type Diagnostic, store } from "waarmerk";

export interface CsvMathDiagnostic extends Diagnostic {
  readonly code?: "CSVMATH_SYNTAX" | "CSVMATH_MAX_NODES";
}

const diags = store();
export const isDiagnostic = diags.isDiagnostic as (error: unknown) => error is CsvMathDiagnostic;

API

| | | | ---------------------------------------------------- | -------------------------------------------------------------------------- | | store() | A frozen { isDiagnostic, origin }. One per package, made at module load. | | mint(store, Kind, message, fields?, origin?) | Throws a diagnostic of class Kind, authenticated against store. | | adopt(store, error, fields?, origin?) | Returns error, now a member of store, with fields defined on it. | | capped(store, name, code, limit, actual?, origin?) | Throws a RangeError reading <name> limit of <limit> exceeded. | | relocate(store, diag, { prefix?, offset?, span? }) | Returns the copy. Throws TypeError when diag is not from store. |

fields are defined non-writable, non-configurable and enumerable — so they show up in a spread, resist tampering, and a frozen value you attach stays frozen through any number of relocations.

origin is optional and most packages ignore it. It exists for parsers that compile once and evaluate many times: pass a per-compile token and store.origin(error) hands it back, so one compilation's runtime errors can be told from another's.

waarmerk defines no error codes and no field names beyond the five it documents. Which codes exist, and what rides with each, is yours.

Contract

Normative, for anyone implementing against this or relying on it.

A diagnostic is authenticated by identity, never by shape. The store that minted it holds the only record. An error carrying a code and a start that came from somewhere else is not a diagnostic, and its metadata may not be read as if it were.

A store belongs to the package that mints into it. waarmerk owns no identity of its own and shares none between packages, so two copies of waarmerk in one dependency tree cannot disagree about who threw what, and packages depending on it version independently.

A copy is made by the store that minted the original. It joins that store under the same origin, so it passes the guard the original passed. The original is never mutated, and every own field comes across by descriptor.

offset shifts; span replaces. span wins when both are given.

Relocation never invents a span, and never drops one. start and end travel as a pair; a diagnostic carrying one half is not a located fault and does not move, and neither does one whose span is an accessor rather than a value.

A copy joins only the store that relocated it. A diagnostic belonging to two stores — one package's fault, re-vouched for by the package that embeds it — has to be adopted again after relocation to stay in both. That is the isolation guarantee working, not a gap in it.

What waarmerk is not

It is not a shared-primitives package. Anything that would arrive only because more than one package wants it is out of scope: a module that admits a second unrelated concern stops having an interface and starts having a namespace.

It is not a formatter, an error-reporting library, or a pretty-printer. waarmerk never composes a message beyond prefix + message, with the one exception of capped. Rendering a span into a caret-and-underline snippet is a separate job and a separate package.

It is not a parser, and has no opinion about how you find the fault — only about handing it over once you have.

Content Security Policy

waarmerk contains no string-to-code path — no eval, no dynamically constructed functions — and needs no unsafe-eval. A test greps the shipped source for those spellings, the suite runs under --disallow-code-generation-from-strings, and a browser suite serves the shipped file under default-src 'none'; script-src 'self' in Chromium and fails on any policy violation.

Safety

Relocation builds its copy from a class table captured at module load, never through the original's constructor, and reads and writes descriptors through Object methods captured at the same time. The WeakMap operations every store's membership rests on are captured the same way and always called against an explicit receiver. Replacing a prototype's constructor, an Object method, or a WeakMap method after load changes nothing.

The WeakMap behind a store never leaves this module: handing out a way to add a member would make authentication forgeable. Fields are defined non-writable and non-configurable, so a frozen value attached at mint stays frozen through any number of relocations.

Environments

Node.js 22 and newer, ESM only. Browser use is supported through a standards-based ESM bundler in environments supporting ES2024. Direct <script> globals, UMD, and CommonJS builds are not provided.

Shipping CommonJS alongside ESM would put two copies of this module in any process that mixed require and import. Each copy keeps its own table of stores, so a store made through one would not be recognised by the other and every call would throw.

Minting and relocation both cost roughly what constructing an Error costs; isDiagnostic is a WeakMap lookup. Run npm run bench.

Contributing

git clone https://github.com/getquario/waarmerk.git
cd waarmerk
npm install
npm run check

npm run check is the local gate. Conventions for this repo live in AGENTS.md.

License

Copyright 2026 Robin van der Vleuten

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.