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

@suluk/journeys

v0.5.1

Published

Intuitive, runnable BDD over a v4 'Suluk' contract. Projects a deterministic Gherkin step VOCABULARY from the contract (Given from x-suluk-access, When from each operation, Then from declared statuses + x-suluk-store + x-suluk-cost), binds authored .featu

Readme

@suluk/journeys

Intuitive, runnable BDD over a v4 "Suluk" contract — a non-technical author (PM / BA / QA) writes Gherkin user-stories and journeys against a step vocabulary generated from the contract, and a bidirectional gap report tells everyone exactly what the contract can and cannot yet back.

CANDIDATE tooling — not official OpenAPI. Suluk is a single-contributor candidate for OpenAPI v4.0 ("Moonwalk"), unaffiliated with the OpenAPI Initiative. See ADR C038.

The loop

contract ──generateVocabulary──▶ step palette ──▶ humans author .feature stories
   ▲                                                        │
   └── dev fills the gap ◀── bidirectional gap report ◀── bindFeatures
  1. generateVocabulary(doc) projects the contract into a deterministic Gherkin step palette:
    • Givenx-suluk-access (authenticated"Given I am a signed-in user")
    • When ← each operation (checkout"When I checkout", getCredits"When I view credits")
    • Then ← declared statuses ("Then it succeeds"), x-suluk-store ("Then my credits refreshes"), per-unit x-suluk-cost ("Then I am charged credits")
  2. A non-technical author writes plain .feature files against that palette (the prose lives in a sidecar, never in the contract — the D1 wall).
  3. bindFeatures(vocab, features) binds each step exact-or-UNBOUND, with outcome (Then) steps resolved relative to the scenario's When-subject, and reports the gaps both ways.

What a "gap" is — bidirectional, tri-state

  • authored → contract. An unbound step is classified deterministically:
    • PARAPHRASE — you wrote it differently; an author-owned alias resolves it, no developer needed.
    • NEEDS-DEV-GLUE — the operation exists, but no step wires it; a developer adds one.
    • NEEDS-CONTRACT — nothing backs the intent; a developer extends the contract.
  • contract → authored. A pure set-difference over the stable handle space surfaces every operation/store with no covering scenario — the "complete" guarantee — and emits a drop-in stub for each.

Binding never uses scoring, lemmatization, or embeddings — those would make the decision non-deterministic. String similarity appears only in the presentational "did you mean?" suggestion on an already-unbound step.

Runnable — and it partly tests your frontend

emitRunnableSuite(vocab, features) lowers bound scenarios to a self-contained bun:test suite driven through @suluk/sdk's generated client — the same client your frontend ships on. A green scenario exercises the real frontend data-path: typed dispatch, input validation, the auth interceptor, response decode, and the C037 store invalidation/refetch. Honest boundary: it tests client + contract + wire + the store data layer — not rendered UI, layout, or visual behavior (there is no DOM in a bun:test). That last mile is @suluk/visual + a browser.

Usage

import { generateVocabulary, parseFeature, bindFeatures, renderGapReport, renderPhrasebook } from "@suluk/journeys";
import { apiDocument } from "./contract"; // your v4 contract

const vocab = generateVocabulary(apiDocument());
console.log(renderPhrasebook(vocab)); // the palette an author picks from

const feature = parseFeature(await Bun.file("./billing.feature").text());
const report = bindFeatures(vocab, [feature], {
  aliases: { "given i am a logged in user": "given i am a signed-in user" }, // author-owned, no dev
});
console.log(renderGapReport(report));

Stable identity

Step identity is op.name@path-uri (the by-name handle), not the @suluk/sdk client accessor — resolveOps mutates the accessor in place during collision resolution, so accessor-keyed identity would churn when a sibling operation is added. (Witnessed on toolfactory's api/billing/subscription, which holds both getSubscription and cancelSubscription.)

Two-role authoring + composition (no developer)

A non-technical author can write stories in their own words and hand them to a scaffolder (a more technical author — not a developer) who maps that free prose onto the runnable vocabulary. Neither role writes code.

  • detectUndefined(vocab, features, defs) is the scaffolder's worklist (Cucumber-style undefined-step detection, resolved by mapping not coding). It splits each not-yet-runnable step into "the scaffolder can define this" (an operation/step exists → alias or decompose) vs "escalate to a developer" (NEEDS-CONTRACT — no operation backs it). renderScaffold(...) prints it with paste-ready stubs.
  • A Definitions artifact (author/scaffolder-owned data) turns prose into runnable steps three ways:
    • alias"prose": "When I checkout" (one canonical step)
    • decomposition"I sign up and buy credits": ["Given I am a signed-in user", "When I checkout", "Then it succeeds"]
    • journey — a named, reusable sequence referenced from a story with When I complete the "top up" journey
const defs = {
  steps: { "when i sign up and buy credits": ["Given I am a signed-in user", "When I checkout", "Then it succeeds"] },
  journeys: { "top up": ["Given I am a signed-in user", "When I checkout", "Then it succeeds"] },
};
const report = bindFeatures(vocab, [story], { definitions: defs });   // composed + decomposed, all bound
const todo = detectUndefined(vocab, [story], { definitions: defs });  // what still needs defining / escalation

Composition lets authors build bigger journeys out of existing ones (complete the "…" journey), and outcome steps bind to the most-recent action, so multi-step journeys bind each Then to its own When. The only thing that ever needs a developer is genuinely new backend capability (NEEDS-CONTRACT) — composition and mapping do not.

Discovery (designed, gated)

A semantic reuse search — "find an existing flow to reuse / modify / rebuild" — is designed (a deterministic faceted handle-index inside this package; the reuse verdict is set algebra over contract-handle overlap; an embedding overlay is a walled-off, gated sibling). It is deferred until a real corpus exists. See ADR C038.

Status

0.1.0, ceiling 0.45 — originated, projection-model-native, spike-witnessed on the real toolfactory contract; the open question is whether the constrained-vocabulary-plus-alias UX feels intuitive to a real non-technical author.