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

@selectwin/sdk

v0.1.1

Published

Official Selectwin Node.js / TypeScript SDK — payments (card, PIX, boleto), subscriptions, webhooks.

Readme

@selectwin/sdk

Official Selectwin Node.js / TypeScript SDK — payments (credit card, PIX, boleto), subscriptions, wallets, webhooks and more.

Status: early / work in progress (0.1.0). Foundation, DX shell and Stripe-style namespaces in place.

npm install @selectwin/sdk

Quickstart

import { Selectwin, CardError } from '@selectwin/sdk';

const sw = new Selectwin(process.env.SELECTWIN_API_KEY!); // sk_test_… / sk_live_…

// Create a PIX transaction (amounts in cents). Stripe-style alias — pass the body directly:
const tx = await sw.transactions.create({ amount: 9990, payment: { method: 'pix', currency: 'BRL' } });

// id + body / id-only aliases:
await sw.subscriptions.pause('subs_…');
await sw.subscriptions.cancel('subs_…', { /* … */ });
const one = await sw.transactions.retrieve('tra_…');

// Typed errors — branch on the class / error.code, never the message
try {
  await sw.transactions.create({ /* … */ });
} catch (err) {
  if (err instanceof CardError) {
    console.log(err.displayMessage, err.reversible); // buyer-facing + retryable
  }
}

Every resource is a namespace with Stripe-style aliases (create, retrieve, update, list, delete, plus resource verbs like sw.subscriptions.pause('subs_…')). The full generated API (all operationId methods) is always reachable via .raw:

await sw.transactions.raw.createTransaction({ /* … */ });

Pagination

Top-level list() methods auto-paginate. The returned value is both awaitable (first page) and async-iterable (every item across pages):

// stream every transaction across all pages
for await (const tx of sw.transactions.list({ limit: 100 })) {
  // …
}

const firstPage = await sw.transactions.list({ limit: 20 }); // { data, hasMore, offset, … }
const all = await sw.customers.list().toArray();             // or .toArray(500) to cap
for await (const page of sw.transactions.list().pages()) { /* page.data */ }

For endpoints not wrapped as auto-pagers (e.g. sub-resource lists), the low-level paginate helper works over any list function:

import { paginate } from '@selectwin/sdk';
for await (const item of paginate((p) => sw.subscriptions.raw.listSubscriptionItems({ subscriptionId: 'subs_…', ...p }), { limit: 100 })) { /* … */ }

Webhooks

constructEvent verifies the signature and returns a discriminated union over the whole Event Catalog — switch (event.type) narrows event.payload.object to the matching resource shape:

// rawBody MUST be the exact bytes/string received (do not re-serialize)
const event = sw.webhooks.constructEvent(
  rawBody,
  req.headers['x-selectwin-signature'],
  process.env.SELECTWIN_WEBHOOK_SECRET!, // whsec_…
);

switch (event.type) {
  case 'transaction.approved':
    event.payload.object.id; // typed as the transaction read shape
    break;
  case 'subscription.paused':
    event.payload.object; // typed as the subscription read shape
    break;
}

event.type autocompletes every catalog value (WebhookEventType). The catalog itself is exported for validation — WEBHOOK_EVENT_TYPES (readonly tuple) and isWebhookEventType(x) — along with per-resource groups (TransactionEventType, SubscriptionEventType, …) and the WebhookEventObjectMap type → object mapping. Need to assert the object shape yourself? Pass a type argument: constructEvent<MyType>(rawBody, sig, secret).

What the SDK adds over the raw generated client

The package is a generated core (from the OpenAPI v2.0.0 spec) + a hand-written DX shell:

  • Typed clientnew Selectwin(key)sw.transactions, sw.subscriptions, sw.customers, …
  • Stripe-style aliases per resource (.create/.retrieve/.update/.list/.delete + custom verbs), delegating to the generated methods with exact types. Standard CRUD is flattenedcreate(body), retrieve(id), update(id, body) — while complex methods (multi-id sub-resources, lists) keep the object form. .raw exposes the full generated surface.
  • Typed errors by HTTP status / error.code: CardError (402, displayMessage/reversible), ValidationError (params), RateLimitError (retryAfter), AuthenticationError, PermissionError, NotFoundError, ConflictError, ApiError, ApiConnectionError.
  • Auto-retries (429/5xx/network) with exponential backoff, honouring Retry-After.
  • Idempotency — an X-Idempotency-Key is added to every mutation (override via headers).
  • Timeouts (AbortController).
  • Auto-pagination — top-level list() returns an AutoPager (await = first page, for await = all items, .toArray(), .pages()); plus a low-level paginate(listFn, params) helper.
  • Webhook verification + typed eventsconstructEvent (HMAC-SHA256 of the raw body, constant-time) returns a discriminated union over the Event Catalog, so switch (event.type) narrows event.payload.object. The catalog is generated from the spec, so it never drifts.

Auth is the SelectKey header; the environment (sandbox/production) is resolved from the key prefix (sk_test_ / sk_live_).

Architecture

src/
  generated/        # openapi-generator typescript-fetch output — DO NOT edit; synced from selectwin-sdks
  namespaces.ts     # GENERATED Stripe-style typed wrappers (gen-namespaces.mjs) — DO NOT edit
  webhook-events.ts # GENERATED typed Event Catalog + discriminated event union — DO NOT edit
  http.ts           # custom fetch (retries/timeout) + middleware (idempotency, error mapping)
  errors.ts         # typed error hierarchy
  webhooks.ts       # constructEvent (signature verification)
  pagination.ts     # paginate() + AutoPager
  client.ts         # Selectwin — wires one Configuration into all namespaces
  index.ts          # public exports

Cross-cutting concerns are injected once into the generated Configuration (fetchApi + middleware), so every endpoint inherits them and new endpoints work automatically when the core is regenerated.

Development

npm run sync:core         # copy the generated core from selectwin-sdks + regen namespaces + events
npm run gen:namespaces    # regenerate src/namespaces.ts from the generated core
npm run gen:webhook-events # regenerate src/webhook-events.ts (typed Event Catalog)
npm run typecheck         # tsc --noEmit (src + test — also verifies the type-level assertions)
npm test                  # vitest (errors, webhooks, webhook-events, pagination, http, client)
npm run test:integration  # sandbox integration suite — see below
npm run build             # tsup → dual ESM/CJS + d.ts in dist/

sync:core runs gen:namespaces and gen:webhook-events automatically. The core is regenerated from the OpenAPI spec in selectwin-sdks; the DX shell in src/ (except the generated namespaces.ts and webhook-events.ts) is hand-maintained.

Integration tests (sandbox)

test/integration/** runs against the real sandbox API and is self-gated: every suite is skipped (so npm test never touches the network) unless a sandbox key is present. Provide one and run the separate suite:

SELECTWIN_SANDBOX_KEY=sk_test_... npm run test:integration
# SELECTWIN_API_KEY is also honoured, but only if it starts with sk_test_ (never a live key).
# SELECTWIN_BASE_URL optionally overrides the host (sandbox/prod is resolved from the key prefix).

Coverage: read-only smoke (auth + list envelope + auto-pagination across resources), typed-error mapping (bogus key → AuthenticationError), and a customer create → retrieve → delete round-trip plus an idempotency replay. Writes are sandbox-only and cleaned up in afterAll.

Roadmap

  • Publish the package (npm) once the API stabilises; wire CI to run unit tests on PRs and the sandbox suite on a schedule/with a repo secret.