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

@visionary_software/contrax-annotations

v2026.5.10

Published

Contrax SPI vocabulary types — Enforcement, CallSite, Check, Details — for the TypeScript port.

Readme

contrax-annotations — Design by Contract SPI vocabulary (TypeScript line)

The vocabulary layer of the Contrax Design by Contract framework, ported to TypeScript: discriminated-union types (CallSite, Check), the Enforcement strategy, the Details substrate bundle, and the standalone violate / withDetail / formatCallSite / siteFor functions every other contrax-typescript module builds on.

This is the TypeScript line. The Java line lives on java; the Kotlin K2/FIR port on kotlin.

Install

bun  add @visionary_software/contrax-annotations
npm  i   @visionary_software/contrax-annotations
pnpm add @visionary_software/contrax-annotations
yarn add @visionary_software/contrax-annotations

Peer dependency: typescript. Direct dependency: @visionary_software/apt (TS-AST navigation toolkit).

Conceptual model

Design by Contract — formalised by Bertrand Meyer in Object-Oriented Software Construction — divides responsibility between a routine and its caller into three obligations: the caller must satisfy a precondition, the routine must satisfy a postcondition, and every class must maintain its invariants across visible states.

TypeScript has no built-in support. The usual fallback is defensive runtime if-and-throw, scattered across method bodies, indistinguishable from business logic, detecting violations late. Contrax instead lets library authors declare their preconditions and postconditions as JSDoc tags, and a transformer plugin (in the processor module, ported separately) turns violations into build-failing tsc diagnostics at the offending call site or returned expression.

This module is the SPI vocabulary every part of that pipeline shares.

Type catalogue (so far)

| Export | Shape | Role | |---|---|---| | CallSite | discriminated union of AtParameter \| InReturn \| WithDetail | Single parameter object handed to an Enforcement. AtParameter for pre-condition seams; InReturn for post-condition seams; WithDetail decorates either with a clarifying message suffix. | | Check | discriminated union of Pre \| Post | Strategy describing WHAT seam to look at. The dispatch primitive (details.check(check), introduced in a later feature) is the Context that knows HOW to look. | | Enforcement | (site: CallSite) => void | Compile-time DbC enforcement. Inspects site and calls violate(site) (optionally wrapped via withDetail first) when the contract isn't met. | | Details | record { executable, sourceFile, program, checker, addDiagnostic } | The substrate bundle a CallSite carries — mirror of Java's record Details(ExecutableElement, CompilationUnitTree, ProcessingEnvironment). | | formatCallSite(site) | (site) => string | Canonical diagnostic message frame: "@<UserTag> violated at parameter #N ('name' of type T) of Class.method" (AtParameter) / "@<UserTag> violated in return from Class.method" (InReturn) / "<delegate's frame>: <detail>" (WithDetail; stacks). | | withDetail(site, detail) | (CallSite, string) => WithDetail | Wrap with a clarifying suffix; stacks. | | violate(site) | (CallSite) => void | Unwraps WithDetail to the leaf for positioning, pushes a ts.Diagnostic (Error severity, fixed CONTRAX_VIOLATION_CODE) on the leaf's expression range with the wrapped site's formatted message. | | siteFor(check, useSiteTag, details) | (Check, ts.JSDocTag, Details) => CallSite | Build the CallSite flavor matching check. | | contractTagName(check) | (Check) => "precondition" \| "postcondition" | The JSDoc tag name a Check looks for on candidate declarations. | | CONTRAX_VIOLATION_CODE | 6_000_001 | Numeric code on every contrax-emitted diagnostic. Sits in the 6_000_000+ range reserved for third-party transformer codes so it cannot collide with TypeScript's own. | | check(details, strategy) | (Details, Check) => void | The dispatch primitive — mirror of Java's Details.check(Check). Walks getOverrideHierarchy(details.executable), scans tags per candidate (parameter at index for Pre, method tags for Post), finds the contract tag (direct match on the use-site OR indirect via tagsOnRegistrationSite), reads the enforcement name from the contract tag's comment, looks it up in details.enforcements, dispatches enforcement(siteFor(strategy, useSiteTag, details)). First-match-wins; closest-override-wins implicit. | | Details.enforcements | ReadonlyMap<string, Enforcement> | The Enforcement registry (mirror of Java's static ServiceLoader.load(...).toList()). Keyed by export name (e.g. "IsNotBlank") — the convention contrax-transformer uses when scanning node_modules for packages whose package.json declares a contrax.enforcements field (cross-link: see processor's discovery section). |

Dispatch is silent on missing pieces

check() is permissive on three boundaries that look like they should be loud but aren't:

  • No tag at the seam — a parameter with no @precondition and no registered custom tag dispatches nothing. There is no contract here to verify.
  • A tag whose Enforcement isn't in the registry — the use site references @precondition Foo but no Foo was discovered in node_modules. Build passes silently. Surfacing this as a build failure would couple every consumer's build to the exact set of installed enforcement packages, which is operationally fragile (CI agents that haven't pulled an enforcement plugin would fail builds on otherwise-correct code).
  • A registered Enforcement that decides the use site doesn't violate — the silent-pass case for built-ins on identifier references / computed values that contrax can't read at compile time.

A separate XMOD-3 meta-diagnostic in processor catches the closely-related "upstream package shipped with removeComments: true" case so it doesn't masquerade as silent dispatch.

Why a separate module?

To keep the contrax SPI clean. contrax-annotations defines the vocabulary types every other contrax module shares, with no transformer / engine / enforcement code. AST navigation belongs in apt; the engine that walks call sites and dispatches details.check(check) belongs in processor; the built-in enforcements belong in enforcements.

TypeScript peculiarities

  • Every CallSite and Check carries a kind discriminant. TypeScript interfaces are erased at runtime — there is no instanceof AtParameter because AtParameter is not a runtime entity. To distinguish union members at runtime (in formatCallSite, in siteFor, in every Enforcement that needs to skip the withDetail wrapper), an explicit string tag is the idiomatic solution. The compiler then narrows the union inside case "atParameter": branches automatically. The Java/Kotlin lines lean on sealed-hierarchy pattern matching for the same flow; TS uses string-discriminated unions.

  • Cross-package consumption ships both ESM and CJS. Downstream packages (contrax-enforcements, contrax-range-check, the transformer's runtime users) import this package as ESM. The transformer itself runs on Node via tspc and discovers Enforcement bundles via require(), so every Enforcement-shipping consumer of this package must publish a CJS sibling alongside its ESM. This package's own package.json uses the standard exports.import / exports.require conditions so both consumption paths resolve to the right artifact; downstream packages follow the same pattern. See the processor README's "TypeScript peculiarities" section for the full discovery walk.

License

GPL-3.0-or-later. See COPYING. Contact Visionary Software Solutions for commercial licensing.