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

@swft-checkout/js

v1.0.0

Published

JavaScript SDK for Swft Checkout — sub-200ms edge checkout for any platform

Readme

@swft-checkout/js

JavaScript/TypeScript SDK for Swft Checkout — sub-200ms edge checkout for any platform.

Installation

npm install @swft-checkout/js
# or
yarn add @swft-checkout/js
# or
pnpm add @swft-checkout/js

Quick start

import { createSession, redirectToCheckout } from '@swft-checkout/js'

const session = await createSession({ merchantApiKey: 'sk_live_...', currency: 'GBP', lineItems, shippingMethods, subtotal: 2999 })
redirectToCheckout(session.sessionUrl)

API reference

createSession(options)

Creates a Swft checkout session. Returns a SwftSession.

import { createSession } from '@swft-checkout/js'

const session = await createSession({
  merchantApiKey: process.env.SWFT_API_KEY!,
  currency: 'GBP',
  lineItems: [
    {
      name: 'Padel Racket Pro',
      quantity: 1,
      price: 8999,           // pence — £89.99
      product_id: 'sku_abc',
      image: 'https://example.com/racket.jpg',
      sku: 'PADEL-PRO-001',
    },
  ],
  shippingMethods: [
    { id: 'standard', label: 'Standard Delivery (3-5 days)', cost: 499 },
    { id: 'express',  label: 'Express Delivery (next day)',  cost: 999 },
    { id: 'free',     label: 'Free Delivery (5-7 days)',     cost: 0   },
  ],
  subtotal: 8999,
  tax: 1500,
  discount: 0,
  customer: {
    email: '[email protected]',
    first_name: 'Jamie',
    last_name: 'Smith',
  },
  extensions: {
    order_bump_ids: ['bump_helmet'],
  },
})

console.log(session.sessionId)   // swft_sess_abc123
console.log(session.sessionUrl)  // https://checkout.swft.co.uk/swft_sess_abc123
console.log(session.expiresAt)   // ISO 8601 timestamp

Options

| Field | Type | Required | Description | |-------|------|----------|-------------| | merchantApiKey | string | Yes | Your Swft merchant API key from the dashboard | | currency | string | Yes | ISO 4217 code: 'GBP', 'USD', 'EUR' | | lineItems | SwftLineItem[] | Yes | Products in the cart | | shippingMethods | SwftShippingMethod[] | Yes | Available shipping options | | subtotal | number | Yes | Cart subtotal in minor units (pence/cents) | | tax | number | No | Tax in minor units (default 0) | | discount | number | No | Discount in minor units (default 0) | | customer | SwftCustomer | No | Pre-fill customer details | | extensions | Record<string, unknown> | No | Swft module data (order bumps, funnels, etc.) | | apiUrl | string | No | Override API base URL (default https://api.swft.co.uk) | | cartHash | string | No | Deduplication hash — auto-generated from line items if omitted |


redirectToCheckout(sessionUrl)

Redirects the browser to the Swft hosted checkout. Must be called in a browser context.

import { redirectToCheckout } from '@swft-checkout/js'

redirectToCheckout(session.sessionUrl)

Throws SwftError with code 'browser_only' if called server-side.


getCheckoutUrl(sessionId)

Returns the checkout URL for a given session ID without redirecting.

import { getCheckoutUrl } from '@swft-checkout/js'

const url = getCheckoutUrl('swft_sess_abc123')
// https://checkout.swft.co.uk/swft_sess_abc123

verifySwftWebhook(rawBody, signature, secret)

Verifies a Swft webhook using the Web Crypto API. Compatible with Node 18+, browsers, Cloudflare Workers, and Deno.

import { verifySwftWebhook } from '@swft-checkout/js'

// In a Cloudflare Worker or Next.js App Router route handler:
const rawBody  = await req.text()
const signature = req.headers.get('x-swft-signature') ?? ''

const payload = await verifySwftWebhook(
  rawBody,
  signature,
  process.env.SWFT_WEBHOOK_SECRET!
)

console.log(payload.event)     // 'payment_succeeded'
console.log(payload.sessionId) // 'swft_sess_abc123'

Throws SwftError with code 'invalid_signature' and status 401 if verification fails.


verifySwftWebhookNode(rawBody, signature, secret)

Node.js-only synchronous variant using the built-in crypto module. Use this on Node < 18 or when you cannot use async/await in your webhook handler.

import { verifySwftWebhookNode } from '@swft-checkout/js'

// In an Express route:
app.post('/webhooks/swft', express.raw({ type: 'application/json' }), (req, res) => {
  const payload = verifySwftWebhookNode(
    req.body,
    req.headers['x-swft-signature'] as string,
    process.env.SWFT_WEBHOOK_SECRET!
  )

  if (payload.event === 'payment_succeeded') {
    // fulfil order
  }

  res.json({ received: true })
})

TypeScript types

interface SwftLineItem {
  name:        string
  quantity:    number
  price:       number            // minor units (pence/cents)
  product_id?: string | number
  variant_id?: string | number
  image?:      string
  sku?:        string
  attributes?: Record<string, string>
}

interface SwftShippingMethod {
  id:    string
  label: string
  cost:  number                  // minor units
}

interface SwftCustomer {
  email?:      string
  first_name?: string
  last_name?:  string
}

interface SwftCreateSessionOptions {
  merchantApiKey:  string
  currency:        string
  lineItems:       SwftLineItem[]
  shippingMethods: SwftShippingMethod[]
  subtotal:        number
  tax?:            number
  discount?:       number
  customer?:       SwftCustomer
  extensions?:     Record<string, unknown>
  apiUrl?:         string
  cartHash?:       string
}

interface SwftSession {
  sessionId:  string
  sessionUrl: string
  expiresAt:  string
}

Webhook payload

All webhook events share this shape:

interface SwftWebhookPayload {
  event:            'payment_succeeded' | 'payment_failed' | 'session_expired'
  sessionId:        string
  paymentIntentId?: string
  amount?:          number       // minor units
  currency?:        string       // ISO 4217
  customer?: {
    email?:      string
    first_name?: string
    last_name?:  string
  }
  shippingAddress?: {
    line1:    string
    line2?:   string
    city:     string
    postcode: string
    state?:   string
    country:  string
  }
  lineItems?:  SwftLineItem[]
  extensions?: Record<string, unknown>
  timestamp:   string            // ISO 8601
}

Error handling

All errors thrown by this SDK are instances of SwftError:

import { createSession, SwftError } from '@swft-checkout/js'

try {
  const session = await createSession(options)
} catch (err) {
  if (err instanceof SwftError) {
    console.error(err.message) // human-readable message
    console.error(err.code)    // machine-readable code e.g. 'session_error'
    console.error(err.status)  // HTTP status if applicable e.g. 401
  }
}

Common error codes:

| Code | Description | |------|-------------| | session_error | API returned a non-OK response during session creation | | invalid_signature | Webhook signature verification failed | | browser_only | redirectToCheckout called outside a browser |


Environment compatibility

| Environment | createSession | verifySwftWebhook | verifySwftWebhookNode | |-------------|----------------|---------------------|------------------------| | Node.js 18+ | Yes | Yes (Web Crypto) | Yes | | Node.js < 18 | Yes | No | Yes | | Browser | Yes | Yes | No | | Cloudflare Workers | Yes | Yes | No | | Deno | Yes | Yes | No | | Bun | Yes | Yes | Yes |

createSession uses the native fetch API available in all modern environments. For Node < 18, polyfill fetch with node-fetch or undici.