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

@volter/twin-stripe

v0.1.2

Published

Local Stripe twin — a faithful, stateful local Stripe API your real `stripe` SDK talks to unmodified. Mirror, simulate, and fork. Built on @volter/twin.

Readme

@volter/twin-stripe

The Stripe twin — a local, spec-correct replica of the Stripe REST API on the shared @volter/twin kernel. The real stripe SDK works against it unmodified; it's the QA stack's authoritative local Stripe (it replaced the old hand-made in-process mock).

Surface

  • REST API (stripe-twin.ts → handleStripeTwinRequest; HTTP wrapper stripe-server.ts → createStripeTwinServer): charges, customers, payment_intents, setup_intents, payment_methods, products, prices, invoices, invoiceitems, subscriptions, refunds, coupons, promotion_codes, identity verification sessions, ephemeral_keys, checkout sessions, billing/customer-portal sessions + configurations.
  • Writes are local transactions (action log); reads are the projection (R3/R5/R18).
  • Card declines (stripe-twin.ts): Stripe's documented test cards get vendor-faithful outcomes on charge create / PaymentIntent confirm — 4242…4242 (and pm_card_visa/tok_visa) succeed; 4000…0002, 4000…9995, 4000…0069, 4000…0127, 4000…0119 (and the matching pm_card_*/tok_* tokens) return the real card_error envelope (HTTP 402) and leave a confirmed PaymentIntent at requires_payment_method. Unknown cards succeed. See _card.declines-test-set-only in stripe-known-deviations.json.
  • Idempotency keys: the Idempotency-Key header is honored on POST — a replay with the same key returns the stored response without re-applying the write (_idempotency.stored-per-root).
  • Events (stripe-events.ts): fires Stripe event objects on write (payment_intent.succeeded, customer.subscription.created, invoice.paid, …).
  • Conformance (stripe-conformance.ts): field name + type checked vs Stripe's real OpenAPI (standing gate).
  • UI mirror (stripe-mirror-ui.ts): a Stripe-dashboard-style React app over the twin's own REST API.

CLI

world-stripe serve [--read-only] [--port N] [--root DIR]
world-stripe mirror [--port N] [--root DIR]
world-stripe conformance [--fields FILE] [--root DIR]

serve defaults to simulator (the stack uses the twin as a writable Stripe). Point the real stripe SDK at it with { host, port, protocol: 'http' }.

Interaction surfaces

  1. SDK/API — zero edits (preferred): STRIPE_TWIN_URL=http://127.0.0.1:PORT node --require @volter/twin/inject your-app redirects the real stripe SDK from api.stripe.com to the twin (cookbook/zero-edit-inject). For the browser too: volter-twin proxy --target <app> --map stripe=http://127.0.0.1:PORT (browser + backend share one twin). Or override directly: new Stripe(key, { host: '127.0.0.1', port: PORT, protocol: 'http' }).
  2. API + CLI — world-stripe serve (writable) + drive with volter-twin status|plan|refs stripe, then push.
  3. Read-only — world-stripe serve --read-only: unlimited local reads, no rate limits; writes refuse like Stripe (4xx).
  4. UI mirror — world-stripe mirror renders a Stripe-dashboard-style view of the twin's state.

(See Getting Started → "Twin interaction surfaces".)

Stable on the twin rubric: fidelity, read/write/fork, sync, observability, event emission, and conformance are tracked with explicit coverage gaps.

Coverage

Goal: honest, explicitly tracked coverage of Stripe's core feature surface. The only accepted carve-outs are the explicit out-of-scope items listed below. Anything not done or carved out is a gap to close.

Done — core resources: customers, charges, payment_intents (+ confirm), setup_intents (+ confirm), payment_methods (+ detach), subscriptions (create/ update/cancel), prices, products, invoices (+ finalize/pay/void), invoiceitems, refunds, disputes (+ update/close), payouts (+ cancel), balance_transactions, balance (synthesized from the ledger), events (Events API list/retrieve), Checkout Sessions (create/retrieve/list/line_items/expire + modeled completion that creates+links a payment_intent/subscription/setup_intent; amount_total computed from line_items), Customer Portal (billing_portal sessions + configurations create/retrieve/ list/update), Connect (connected accounts create/retrieve/list/update/delete + login_links, and transfers platform→connected-account create/retrieve/list filtered by destination; a new account starts un-onboarded with charges/payouts disabled + a requirements hash), plus ephemeral_keys, identity verification_sessions, file_links (synthesized) and coupons/promotion_codes (retrieve/list, seed-only). Cursor pagination (limit/starting_after/ending_before + has_more); per-resource list filters; expand[] on the modeled paths; vendor-faithful test-card declines (4242… succeeds; documented decline PANs + pm_card_*/tok_* tokens return the real card_error 402); idempotency keys (Idempotency-Key replay, no re-write); events/webhooks (stripe-events.ts); spec conformance gate; UI mirror (rung-5 ✅, client/stripe-mirror.tsx + structure check); connector pull (customers + subscriptions) + push (create/update/cancel/confirm/detach/ finalize/pay/void/close to the real REST surface).

This cycle added: ACH/SEPA micro-deposit verification (payment_intents/setup_intents /verify_microdeposits — confirm with pm_us_bank_account → requires_action with a verify_with_microdeposits next_action, then the 32/45 amounts or SM11AA descriptor → succeeded), Customer.list_payment_methods (/v1/customers/:id/payment_methods), subscription items CRUD (create/retrieve/list/update/delete, kept in sync with the parent sub's items list), subscriptions/invoices search, invoice line items (/lines + add_lines/update_lines/remove_lines with recomputed totals), invoice edge-action gating (finalize/pay/mark_uncollectible/void state machine), Tax transactions (create_from_calculation + create_reversal with negated lines), quote cancel-from-draft/ open lifecycle gates, customer + subscription discount delete, promotion-code update (active toggle), charge fraud-marking (fraud_details[user_report]), and the Radar family — Reviews (/approve), Value Lists (+ items), Rules — plus a Radar dashboard screen in the UI mirror.

Issuing (modeled) — cardholders/cards/authorizations/transactions/disputes + test helpers (present authorization, capture, force capture, fund_balance), including the real-time authorization leg: an endpoint enrolled for issuing_authorization.request receives the signed request event synchronously at present time and its JSON response ({approved, amount?}) decides the authorization within Stripe's 2-second window (timeout → declined webhook_timeout, invalid response → webhook_error); spending_controls (category/country allow+block lists, per_authorization/all_time/calendar-window spending limits) are enforced ahead of the webhook with the vendor's spending_controls decline reason; and captures debit the issuing balance (balance_transaction type issuing_transaction, balance_type: 'issuing', served in GET /v1/balance's issuing section). Remaining issuing gaps (authorization holds, expire/increment/reverse test helpers) are tracked todos in stripe-capabilities.ts. Terminal (locations/readers/connection tokens + process_payment_intent) is likewise modeled — the old "Planned" listing for both families was stale.

Planned (known-missing, will do) — Treasury (financial accounts), Climate, Financial Connections, Entitlements, Billing credit grants + usage alerts, Connect remaining surfaces (account sessions, connected-account payouts, top-ups, payout reverse), Reporting/Sigma, the legacy Sources API, and additional list endpoints/filters as needed. (See stripe-capabilities.ts for the full honest todo list — every entry not explicitly out-of-scope is a tracked gap.)

Out of scope (deliberately not modeled, with reason) —

  • Pixel-rendering Stripe-hosted Checkout / Customer Portal pages: the hosted HTML is Stripe's, not an API object — the twin models the Session/API object + redirect url instead (now Done; the page pixels stay out of scope). See _checkout.hosted-page-pixels in stripe-known-deviations.json.
  • Real money settlement / bank movement (proposed — pending owner approval): actually moving funds is real-world infra, not the API — the payout/balance_transaction/balance objects and their lifecycle are modeled.

Rate budget — the fail-closed backstop on live calls

liveStripeExecute is the one place this pack issues a live request, so every call it makes is charged against a persistent, fail-closed spend ledger before the request goes out. Past the ceiling, or while a Retry-After/429 cooldown is armed, it throws instead of calling. The ledger is keyed by vendor and a hash of the credential (limits are per credential, so it is deliberately not cwd-scoped) and persists across processes, so a fresh process does not get a fresh allowance; a corrupt ledger counts as a full window rather than zero spend. There is no option to disable it, and no value you can pass for budget that yields an unguarded client — an injected budget is validated by method identity, so a subclass or a Proxy that replaces checkBudget is refused.

The declared numbers: 120 weighted units / 60s = 2 requests/second — 2% of Stripe's documented 100/s live mode and 8% of the 25/s a sandbox key or any single endpoint gets. POST/DELETE cost 2 (not a published ratio — a judgement call about blast radius: a write creates a charge, refund or receipt e-mail and cannot be taken back) and POST /v1/payouts costs 5 (documented at 15 creates/second). Stripe's own window is a second while this one is a minute, so an intra-second burst reaches Stripe's limiter first; the 429 cooldown is the backstop for that shape.

The mechanism is shared and vendor-agnostic — it lives in the kernel (@volter/twin → control-plane/src/rateBudget.ts); what lives here in src/stripe-budget.ts is this vendor's declaration (window, ceiling, per-endpoint weights, and a reason citing the limits above) plus the vendor-bound StripeBudget. The rule is ratified as ARCHITECTURE.md D8, and the kernel module's header documents what the guard does not guarantee — read that before trusting it.