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

@devly-cl/billing-flow

v0.1.0

Published

Reusable native Flow billing adapter with durable host ports.

Readme

@devly-cl/billing-flow

Native Flow billing adapter for Node 24+. Depends only on the public APIs of @devly-cl/billing-core and @devly-cl/flow-client; emits CommonJS and TypeScript declarations and supports ESM and NodeNext consumers. Published releases are installed from npm; local npm pack only creates a candidate tarball.

Install

npm install @devly-cl/billing-core @devly-cl/flow-client @devly-cl/billing-flow

Integration

Construct FlowBillingClient with a wire FlowHttpClient and an optional beforeRequest(method, path) policy. It translates only FlowClientError into the shared core SubscriptionGatewayError. mutation(request, validate) marks validation failures after a successful request as uncertain. Preflight rejection remains definitive.

Construct FlowBillingProvider with FlowBillingProviderOptions: immutable environment and client; journal and authorized resource context; payment-method evidence port; reference factory; time-zone getter and optional clock; readiness/capability callbacks; callback and return-URL functions. Getters and policies are evaluated when used. The host must gate charge-producing POSTs immediately before dispatch while permitting reads, reconciliation and cancellation during a sales pause.

FlowOperationJournal owns atomic begin, get, complete, fail, and find. begin must distinguish environment/key/kind/tenant and a stable fingerprint of the full request. It returns false only for an identical existing intent; mismatches must throw. Persist the intent before the external call. The runner never repeats a POST for an existing intent: it returns the durable result or recovers from canonical provider reads. Store implementations own locks, request canonicalization, leases and timestamps. FlowResourceContext separately checks authorized checkout/subscription ownership and checkout eligibility. FlowOperationRunner receives only the journal.

Some Flow mutations have no safe automatic lookup after a lost response. A host may call resolveUncertainCustomer({tenantId,customerId}) only for the matching durable customer:{tenantId} intent; it confirms the supplied ID through /customer/get and requires the original external ID and email. A host may call resolveUncertainRegistration({tenantId,localOperationId,token,url}) only for the matching durable registration intent; it validates the Flow-hosted URL and /customer/getRegisterStatus, then uses the existing canonical card verification. Neither method issues a POST or creates a new key. The host must authorize the tenant and immutable Flow binding, show unresolved operation metadata without raw token/result data, and retain an operator audit trail.

FlowReferenceFactory supplies customer/plan IDs (including optional legacy plan IDs), fallback offer ID, registration token lookup hash and snapshot fingerprint. Preserve each historical algorithm when integrating existing data. Registration token lookup and callback receipt hashing are independent contracts. Snapshot fingerprinting must omit opaque.fingerprint itself and protect the remaining snapshot. No project name, environment variables or frontend routes are built in.

Plan economics are immutable at the adapter boundary. When a durable or recovered historical plan has matching economics but a different payment callback, the provider leaves that plan and its subscriptions intact, then creates or reuses a deterministic callback-scoped plan derived from the base ID and current callback URL. The journal makes this safe across retries and restarts. A changed amount, currency, interval, trial, or status is still a BILLING_FLOW_PLAN_MISMATCH; it is never hidden by a scoped plan. Existing subscribers retain their original callback, so hosts need a stable public callback ingress or periodic reconciliation for historical plans.

FlowPaymentMethodEvidencePort stores and reads verified card evidence without exposing persistence to the provider. A partial receipt must retain its tenant metadata even before card evidence is complete. The host owns storage JSON, authorization and the transaction used to display {brand,last4}.

Capabilities and callbacks

The provider implements checkout/registration, canonical invoice reconciliation, cancellation, recurring-term reads, and managed native plan changes. It advertises subscriptionCheckout and paymentMethodSetup, plus managedPlanChange when enabled by host policy. Generic recurring-price/interval mutation, one-off invoice, payment-method replacement and signed-body webhook capabilities are not advertised. FlowNativePlanChanges can also be composed directly with explicit journal runner, resource context, clock, timezone and snapshot fingerprint. Calendar helpers preserve Santiago DST ambiguity and leap-year handling; mapper helpers preserve recurring charges, credits and outside-payment evidence.

For recurring reconciliation and a paid plan adjustment, a Flow invoice is paid only when its invoice status, payment status, ownership and immutable dimensions all match. Flow documents error as a failed charge attempt, so error=1 does not overturn a later canonical payment.status=2; a missing, external, mismatched or unconfirmed payment remains pending or review according to the operation.

FlowCallbacks receives a durable queue, an environment-to-verifier resolver and idempotent invoice/wake effects. Receipt enqueue does no provider lookup. Each worker claim verifies canonical state before effects and completion; uncertain acknowledgement retries the same receipt. The queue owns raw-token digest, leases, retry scheduling and retention. HTTP routing, browser returns, commerce wake-up behavior and navigation belong to the host.

Public errors are the original core constructors; import them from @devly-cl/billing-core. Wire types remain available from @devly-cl/flow-client. Only the package root is exported. Legacy host paths remain compatibility facades during migration.

Integration example

The declared host ports below must be implemented by the integrating application. This is wiring, not an in-memory production journal or a charge example. Supply stable reference/fingerprint algorithms and durable storage before invoking operations.

import { FlowHttpClient, type FlowCredentials } from '@devly-cl/flow-client';
import { FlowBillingClient, FlowBillingProvider, type FlowBillingProviderOptions } from '@devly-cl/billing-flow';

declare const host: Omit<FlowBillingProviderOptions, 'environment' | 'client'>;
declare function getCredentials(): FlowCredentials;
declare function beforeRequest(method: 'GET' | 'POST', path: string): void;

const wire = new FlowHttpClient({ environment: 'test', getCredentials });
const client = new FlowBillingClient(wire, { beforeRequest });
const provider = new FlowBillingProvider({
  environment: 'test',
  client,
  journal: host.journal,
  context: host.context,
  references: host.references,
  paymentMethods: host.paymentMethods,
  getTimeZone: () => host.getTimeZone(),
  assertReady: () => host.assertReady(),
  assertPlanChangesReady: () => host.assertPlanChangesReady(),
  planChangesEnabled: () => host.planChangesEnabled(),
  callbackUrl: (kind) => host.callbackUrl(kind),
  returnUrl: () => host.returnUrl(),
  now: host.now ? () => host.now!() : undefined,
});
void provider;

beforeRequest must recheck the host's sales policy before charge-producing POSTs; account separately for preview, canonical reads and maintenance cancellation. callbackUrl supplies the integrating application's public callback endpoints, and returnUrl supplies its browser continuation. Do not embed customer tokens or secrets in those URLs. A pinned test provider must receive only test credentials.

Validation

Run npm run build:packages, npm run test:packages, npm run test:package-boundaries and npm run test:package-artifacts from this repository root. The isolated artifact consumer installs these three packages offline, intercepts signed requests, persists an uncertain operation to disk, restarts the process and recovers without another POST. It has no Nest, TypeORM or .env. Local contract tests do not demonstrate a real PSP transaction or production readiness of credentials.

After package changes, rebuild and restart Nest. Automatic package hot reload has not been validated.