Skip to content

Repository files navigation

tape-six-invariant NPM version

tape-six-invariant lets you embed assert-style invariant checks in production or library code that materialize into real tape-six assertions when a tape-six run exercises that code — and stay inert (or do whatever you configure) otherwise.

Zero runtime dependencies. Works in Node, Deno, Bun, and browsers. ES modules, TypeScript bindings included. The library never imports tape-six — the two coordinate through a single global slot.

import check from 'tape-six-invariant';

export function transfer(from, to, amount) {
  check(amount > 0, 'amount must be positive');
  check(from.currency === to.currency, 'currencies must match');
  // …
}
  • Under a tape-six run (the code is exercised by a test): each check() becomes a counted assertion on the current test — in the plan, in TAP output, with its source location pointing at the check() call site.
  • In production (no tape-six): a configurable behavior. Default inert (does nothing). Overridable to throw, warn, defer to your own node:assert, or anything you like.

The same call site means the same thing — an invariant — and is paid for only when something is listening.

Install

npm install --save tape-six-invariant

tape-six is needed only to run the invariants as assertions (a dev/test concern), so it is not a dependency of this package.

Usage

Materialize under test

Any code reached — directly or transitively — from a tape-six test body routes its check() calls to the current test:

import test from 'tape-six';
import {transfer} from '../src/bank.js';

test('transfer enforces its invariants', t => {
  transfer({currency: 'USD'}, {currency: 'USD'}, 10); // the two checks pass as assertions
  t.pass('done');
});

Configure production behavior

By default invariants are inert in production — they cost a single global-property read. Opt into enforcement at startup:

import {setAbsentBehavior, throwOnFail} from 'tape-six-invariant';

setAbsentBehavior(throwOnFail); // a failing check now throws InvariantError

With no behavior set — the default — a failing check is a no-op. Canned behaviors (exported functions, not magic strings):

Behavior Effect on a failing check
throwOnFail throw InvariantError
warnOnFail console.warn

setAbsentBehavior(null) (or any non-function) clears a previously set behavior. Or pass your own (ok, message) => void — for instance, to defer to node:assert, bring your own import so it stays your dependency, not the package's:

import assert from 'node:assert';

setAbsentBehavior((ok, message) => assert.ok(ok, message));

Skip expensive pre-check work

hasHost is an import-time snapshot — use it to avoid computing an argument that is only worth checking under a run:

import {check, hasHost} from 'tape-six-invariant';

if (hasHost) check(expensiveToCompute(), 'invariant holds');

Correctness never depends on the snapshot — check() always reads the live slot.

Lazy messages

Pass a () => string thunk to build an expensive message only when it is needed:

check(list.every(valid), () => `invalid items: ${list.filter(x => !valid(x)).join(', ')}`);

API

Full documentation is in the wiki — browse the index, or search it by name. check is the default export (and a named export); everything else is named-only.

  • check(cond, message?) — record an invariant. message may be a string or a () => string thunk. TypeScript signature is asserts cond.
  • hasHost — import-time boolean: was a tape-six host present at load?
  • setAbsentBehavior(fn) — set the no-host failure behavior; null clears it (default: none, a no-op).
  • throwOnFail, warnOnFail — canned absent behaviors.
  • InvariantError — thrown by throwOnFail.

Related packages

Release notes

  • 1.0.0 — Initial release: check, hasHost, setAbsentBehavior, canned behaviors (throwOnFail/warnOnFail), InvariantError.

License

BSD-3-Clause © Eugene Lazutkin

About

Zero-dependency invariant checks that materialize into real tape-six assertions under test, and stay inert (or configurable) in production.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages