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

@venn-lang/assert

v0.6.0

Published

The words that follow expect: equals, contains, oneOf and closeTo.

Readme

@venn-lang/assert

The words that follow expect: equals, contains, oneOf and closeTo.

expect belongs to the kernel; the vocabulary does not. This plugin registers four matchers, each carrying its own one-line failure message and the two values it compared. A red assertion therefore prints a sentence a person can read plus a structured diff, never [object Object]. The plugin contributes no verbs, declares no types and needs no host capability.

Install

@venn-lang/assert is part of the stdlib the venn CLI and the language server load, so there is nothing to install. A file that asserts brings the namespace in:

import { assert } from "venn/assert"

A matcher used without that line is VN2007; a word no plugin registered is VN2004. Both are reported by venn check, before anything runs.

Usage

module demo.matchers

import { assert } from "venn/assert"

flow "Bareword matchers" {
  step "checks" {
    let plan = "pro"
    let total = 99.005
    expect plan oneOf ["free", "pro"]
    expect "Total: $99.00" contains "$99.00"
    expect total closeTo 99.0 { within: 0.01 }
    expect plan equals "pro"
    expect not plan oneOf ["a", "b"]
  }
}

Matchers are barewords: they resolve by name alone, not through the assert. prefix. The namespace is what use brings into the file.

Matchers

| Matcher | Written as | Passes when | | --- | --- | --- | | equals | expect res.status equals 200 | The two values are structurally the same. No coercion: "200" never equals 200. | | contains | expect body contains "$99.00" | The subject is a string holding that substring, or a list holding that item. Anything else fails. | | oneOf | expect plan oneOf ["free", "pro"] | The subject is one of the listed values. | | closeTo | expect total closeTo 99.0 { within: 0.01 } | The two numbers differ by no more than the tolerance. within defaults to 0.01. |

not negates any of them: expect not plan oneOf ["a", "b"].

How equals compares

Maps and lists compare by value, not by reference: a body built twice the same way is the same thing, and comparing it by identity would fail an assertion that reads as true on the page.

  • A field set to nothing is not a field. { id: 1, ref: absent } equals { id: 1 }, because both print and travel over the wire identically. A field holding null is still a field, so { id: 1, ref: null } does not.
  • A value that contains itself is handled rather than overflowing the stack: two containers already open on the way down are taken as equal, the way one cycle matches another.
  • Anything that is neither a map nor a list (dates, plugin objects, closures) compares by identity.

contains compares list items the same way, so expect rows contains { id: 1 } works.

What a failure looks like

The title is one line, in the values' own terms:

expected {"status":"pending"} to equal {"status":"paid"}
expected 500 to be one of [200,204]
expected 99.5 to be within 0.01 of 99

Both sides are rendered to the same level of detail. Past a line's worth, both are summarised by shape (expected a map with 3 fields to equal a map with 2 fields) rather than one being spelled out beside one that is not. Strings are quoted, so "200" never reads as 200.

The full values are not lost: each matcher hands back the two sides, and the kernel turns them into the diff carried by the VN6001 problem. Membership matchers (contains, oneOf) mark their sides unaligned, because the needle was held against every item and never stood opposite item 0. A negated expect gets no diff on purpose: under not the two sides matched, and "expected 200, actual 200" explains nothing.

API

| Export | What it is | | --- | --- | | assertPlugin (also the default export) | The PluginDefinition: namespace assert, matchers only, no actions, no typeDefs, no required capability. | | assertMatchers | The four MatcherDefinitions, in order: equals, contains, oneOf, closeTo. |

A matcher is a plain object, so it can be exercised directly:

import { assertMatchers } from "@venn-lang/assert";

const equals = assertMatchers.find((matcher) => matcher.name === "equals");

equals?.test({ subject: { id: 1 }, args: [{ id: 1 }], params: {} });
// true
equals?.message({ subject: "200", args: [200], params: {} });
// 'expected "200" to equal 200'
equals?.detail?.({ subject: { status: "pending" }, args: [{ status: "paid" }], params: {} });
// { expected: { status: "paid" }, actual: { status: "pending" } }

See also