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

viberail

v0.1.1

Published

Typed behavioral specifications — the blueprint for your functions

Readme

viberail

Typed behavioral specifications — the blueprint for your functions.

Describe function behavior as typed data (Spec<Fn>), and everything else derives mechanically: tests, decision tables, dependency graphs, documentation.

Install

npm install viberail

Core idea

A spec is a typed object that declares what a function should do — its failure modes, success paths, examples, and assertions. No test framework DSL, no decorators, no magic strings. Just data.

import { Spec, SpecFn, Result } from 'viberail'

// 1. Define the function's type signature
type ParseEmail = SpecFn<
  string,                          // input
  { user: string; domain: string },// output
  'empty' | 'invalid-format',     // failure types
  'parsed'                         // success types
>

// 2. Write the spec
export const parseEmailSpec: Spec<ParseEmail> = {
  shouldFailWith: {
    'empty': {
      description: 'Rejects empty strings',
      examples: [
        { description: 'empty string', whenInput: '' },
      ],
    },
    'invalid-format': {
      description: 'Rejects strings without @',
      examples: [
        { description: 'no at sign', whenInput: 'foo' },
      ],
    },
  },
  shouldSucceedWith: {
    parsed: {
      description: 'Splits email into user and domain',
      examples: [
        {
          description: 'simple email',
          whenInput: '[email protected]',
          then: { user: 'alice', domain: 'example.com' },
        },
      ],
    },
  },
  shouldAssert: {
    parsed: {
      noEmptyParts: {
        description: 'Neither user nor domain is empty',
        assert: (_input, output) => output.user.length > 0 && output.domain.length > 0,
      },
    },
  },
}

Testing

testSpec generates Jest tests from your spec — one test per example, plus assertion checks on every success example.

import { testSpec } from 'viberail'
import { parseEmailSpec } from './parse-email.spec'
import { parseEmail } from './parse-email'

testSpec('parseEmail', parseEmailSpec, parseEmail)

This generates a full test suite:

parseEmail
  failures
    empty — Rejects empty strings
      ✓ empty string
    invalid-format — Rejects strings without @
      ✓ no at sign
  successes
    parsed — Splits email into user and domain
      ✓ simple email
      ✓ simple email — Neither user nor domain is empty

Inherited failures from steps are auto-skipped with coveredBy attribution. Failures without examples show as test.todo.

Canonical implementation

For flat functions (no decomposition into steps), CanonicalFn + execCanonical gives a standardized structure: constraints → conditions → transform.

import { CanonicalFn, execCanonical } from 'viberail'

const def: CanonicalFn<ParseEmail> = {
  constraints: {
    'empty': (input) => input.length > 0,           // true = valid
    'invalid-format': (input) => input.includes('@'),
  },
  conditions: {
    parsed: (_input) => true,  // only one success path
  },
  transform: {
    parsed: (input) => {
      const [user, domain] = input.split('@')
      return { user, domain }
    },
  },
}

export const parseEmail = execCanonical<ParseEmail>(def)

The executor checks all constraints (accumulating failures), finds the first matching condition, and runs its transform. Returns a Result<O, F, S>.

Algorithm steps

Specs can declare an algorithm as a sequence of typed steps. This enables failure inheritance — child step failures automatically propagate to the parent spec.

import { Spec, StepInfo, asStepSpec } from 'viberail'

const steps: StepInfo[] = [
  { name: 'validateInput', type: 'step', description: 'Validate raw input', spec: asStepSpec(validateInputSpec) },
  { name: 'fetchUser', type: 'dep', description: 'Load user from database' },
  { name: 'normalize', type: 'safe-dep', description: 'Parse and normalize data', spec: asStepSpec(normalizeSpec) },
  { name: 'route', type: 'strategy', description: 'Route by account type', handlers: {
    free: freeHandlerSpec,
    paid: paidHandlerSpec,
  }},
]

export const processOrderSpec: Spec<ProcessOrder> = {
  steps,
  shouldFailWith: {
    // Only declare failures unique to this level.
    // Failures from validateInput, normalize, and strategy handlers
    // are inherited automatically via inheritFromSteps().
  },
  shouldSucceedWith: { /* ... */ },
  shouldAssert: { /* ... */ },
}

Step types:

| Type | Has spec? | Purpose | |------|-----------|---------| | step | optional | Composable domain logic | | safe-dep | optional | Wraps external dependency with parsing/validation | | dep | no | Infrastructure dependency (tested separately) | | strategy | handlers | Conditional dispatch — one spec per case |

Result type

All functions return Result<T, F, S>:

// Success
{ ok: true, value: T, successType: S[] }

// Failure
{ ok: false, errors: F[], details?: string[] }

CLI

viberail gen

Generates .spec.md documentation files and a Mermaid dependency graph from your specs.

npx viberail gen

For each .spec.ts file with document: true, generates a markdown file containing:

  • Pipeline table (step sequence with types and failure modes)
  • Decision table (all failure/success paths as a truth table)
  • Strategy handler sub-tables

Also generates docs/dependency-graph.md with a Mermaid flowchart showing spec dependencies grouped by domain.

viberail check

Validates your specs across 6 dimensions:

npx viberail check

| Check | Severity | What it catches | |-------|----------|-----------------| | Example completeness | warning | Failure/success groups with no examples | | Assertion strength | warning | Success types with no assertions | | Orphan detection | warning | Steps referencing specs not in the graph | | Failure union drift | error | Dead failures — no examples and no coveredBy | | Step-impl sync | warning | .spec.ts has steps but no sibling .ts implementation | | Inheritance completeness | error | Inherited failure with no coveredBy chain |

Exits with code 1 if any errors are found.

JSON test reporter

A custom Jest reporter that outputs structured test results:

// jest.config.js
{
  "reporters": ["default", "viberail/dist/reporters/json-reporter.js"]
}

Outputs a JSON file with per-spec results, pass/fail/skip/todo counts, assertion breakdowns, and timing.

Programmatic API

Everything is exported from the main entry point:

import {
  // Core types
  type Spec, type SpecFn, type Result, type Cmd,
  type StepInfo, type FailGroup, type SuccessGroup,

  // Test runner
  testSpec,

  // Failure inheritance
  inheritFromSteps,

  // Canonical pattern
  type CanonicalFn, execCanonical,

  // Spec loading & analysis
  loadSpecs,

  // Checks
  runChecks, analyzeSpecs,

  // Generation
  generateSpecs,
} from 'viberail'

License

MIT