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

@movmo_app/payments

v0.3.0

Published

Movmo Spreedly Hosted Fields shared package: PCI-safe card capture for Movmo UIs and airline partner integrations.

Downloads

543

Readme

@movmo_app/payments

PCI-safe card capture for Movmo UIs (accounts-ui, flights-ui) and airline partner embeds. The package is intentionally vault-neutral on its public surface — the underlying PCI vault (currently Spreedly Hosted Fields) is an implementation detail that consumers do not depend on.

What's in the box

  • <MovmoCardForm /> — drop-in card-capture form (PCI-safe number + CVV iframes, single cardholder-name input, combined MM / YY expiry). The Save button is gated on Spreedly field validity; opt into auto-save via the autoSave prop. Tokenizes the card, then calls the Movmo API to save the vaulted card to the user's profile. Renders the detected card brand inline (Visa / MC / Amex / Discover) as the user types.
  • <PaymentMethodsManager /> — full saved-cards UI: lists existing cards, lets the user set default / remove, and embeds <MovmoCardForm /> for adding a new one. Renders a payment-type selector (Credit card + disabled "Coming soon" rows for PayPal / GooglePay / Klarna / ACH) by default; pass paymentTypeSelector={false} to hide it. Auto-saves the first card by default (autoSaveFirstCard={true} — matches flights-ui UX). Optional selection mode (selectedId + onSelect) for checkout flows.
  • useMovmoCardFields() — lower-level hook for partners composing their own form layout. Exposes per-field validity + detected brand so the consumer can gate its own submit button and render its own brand icon.
  • useUserPaymentMethods(userId) — fetches the saved-cards list with { items, status, error, refetch }. Useful standalone (e.g., showing the selected card's last4 in a checkout summary).
  • useDeletePaymentMethod(userId) — exposes { deletePaymentMethod, status, error }. Resolves on success, rejects on failure so callers can roll back optimistic updates.
  • useSetDefaultPaymentMethod(userId) — exposes { setDefault, status, error }. Same shape as delete.
  • PaymentMethodSummary — vault-neutral type returned to consumers (no vault tokens, no customer/vault IDs leak through).

Backend contract

Consumes existing monolith-api endpoints (no backend changes required):

| Method | Path | Purpose | | -------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | | GET | /v1/payments/tokenization-session | Fetch RSA-signed Spreedly session params (environmentKey, certificateToken, nonce, timestamp, signature). | | GET | /v1/users/:userid/payment-methods | List the user's saved cards. | | POST | /v1/users/:userid/payment-methods/from-token | Save the vaulted card; server derives last4/brand/expMonth/expYear from the Spreedly vault, never trusting the client. | | PUT | /v1/users/:userid/payment-methods/:methodid | Update the saved card. The manager only sends { isDefault: true } to flip the default. | | DELETE | /v1/users/:userid/payment-methods/:methodid | Delete a saved card. |

All endpoints sit behind the standard RBAC/session-cookie auth.

Usage

Just adding a card

import { MovmoCardForm } from '@movmo_app/payments';

<MovmoCardForm
  userId={user.id}
  isDefault
  defaultCardholderName={`${user.firstName} ${user.lastName}`}
  onSuccess={(pm) => console.log('saved', pm)}
  onError={(msg) => console.error(msg)}
/>;

The cardholder name is a single editable field — users can save a card that isn't in their own name (spouse card, corporate card). Pass autoSave to submit automatically once the form is valid (no Save button rendered).

Full saved-cards management (account-page style)

import { PaymentMethodsManager } from '@movmo_app/payments';

<Card>
  <PageHeader title="Payment methods" />
  <PaymentMethodsManager
    userId={user.id}
    paymentTypeSelector={false}
    autoSaveFirstCard={false}
    onChange={(items) => refreshGlobalState(items)}
  />
</Card>;

The manager renders only its list + add-card affordance — consumers own the outer chrome (page, drawer, modal, etc.). accounts-ui typically hides the payment-type selector and opts out of auto-save so the user clicks Save explicitly.

Checkout flow with payment-type selector + auto-save (flights-ui style)

import { PaymentMethodsManager } from '@movmo_app/payments';

<Drawer open={open} onClose={onClose}>
  <PaymentMethodsManager
    userId={user.id}
    selectedId={selected?.id}
    onSelect={(method) => setSelected(method)}
    // paymentTypeSelector and autoSaveFirstCard default to true.
  />
</Drawer>;

When onSelect is provided, each row renders a radio and the whole row is clickable to select. The default behavior matches the existing flights-ui add-payment UX: Credit card / PayPal / GooglePay / Klarna / ACH radios at the top (only Credit card is functional today; the others render as "Coming soon"); auto-save fires when the form is valid AND the user has zero saved cards.

Standalone hook usage

import { useUserPaymentMethods } from '@movmo_app/payments';

const { items, status } = useUserPaymentMethods(user.id);
const defaultCard = items.find((m) => m.isDefault);

Configuration

Set the API base URL once at app boot (mirrors @movmo_app/api):

import { setPaymentsConfig } from '@movmo_app/payments';

setPaymentsConfig({ baseUrl: import.meta.env.VITE_MOVMO_API_URL });

Local development

pnpm install               # from monorepo root
pnpm --filter @movmo_app/payments build
pnpm --filter @movmo_app/payments test
pnpm --filter @movmo_app/payments storybook   # → http://localhost:6007

Storybook is the primary way to exercise the components on a laptop: it mocks both the underlying vault SDK and the monolith-api calls, so no vault credentials, no live backend, and no real card data are required. See src/MovmoCardForm/__docs__/MovmoCardForm.stories.tsx and src/PaymentMethodsManager/__docs__/PaymentMethodsManager.stories.tsx for the full state matrices.