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

@lockerverse/sdk

v0.2.141

Published

Stateless browser clients for Lockerverse checkout, signup, public event listings, and public Event attendee APIs. Checkout and signup validate responses and return immutable snapshots. The generated public Event client supplies request and response types

Readme

Lockerverse SDK

Stateless browser clients for Lockerverse checkout, signup, public event listings, and public Event attendee APIs. Checkout and signup validate responses and return immutable snapshots. The generated public Event client supplies request and response types, but it does not validate responses at runtime or freeze them. These clients never render UI or own host application state.

This README ships with the package and describes that release. For an installed project, use its local README, package.json exports, and public .d.ts files. Online documentation can describe a newer release. Import public package entry points, not private dist files. For ready-made React UI, use the README shipped with @lockerverse/react.

Usage guide

Checkout

import { createLockerverseCheckoutClient } from "@lockerverse/sdk/checkout";

const client = createLockerverseCheckoutClient({
  communitySlug: "auburn",
  widgetSlug: "auburn-tailgate-party",
  onError(error) {
    console.error(error.code, error.operation);
  },
});

// The host owns Product selection.
const selection = [{ productSlug: "adult", quantity: 2 }];
const pricing = {
  email: "[email protected]",
  includeServiceFee: true,
  tipCents: 500,
};

// One request returns the catalog and the initial authoritative quote.
const { catalog, checkout } = await client.load({ selection });

// Render Stripe Elements with checkout.payment.publishableKey,
// checkout.payment.connectedAccountId, and checkout.totalCents. The prepared
// checkout also binds the normalized items and pricing used for this total.
// Recalculate with the final email and other customer-controlled pricing
// fields before confirmation.
const finalCheckout = await client.calculateTotal({
  catalog,
  selection,
  ...pricing,
});
const payment = await client.submitPayment({
  checkout: finalCheckout,
  submission: {
    confirmationToken: "ctoken_...",
    customFieldAnswers: [
      { fieldId: "guest-name", value: "Ada Lovelace" },
      { fieldId: "interests", value: ["meetups", "merch"] },
    ],
    email: "[email protected]",
    metadata: { source: "community-site" },
  },
});

// Safe after a refresh or an interrupted confirmation response.
const recovered = await client.getPaymentStatus(finalCheckout.paymentReference);

Load a catalog and its initial authoritative quote in one GET request:

const { catalog, checkout } = await client.load({
  selection,
});

If the encoded selection is too long for a safe URL, the client uses a catalog GET request and then a quote POST request instead.

Deploy the backend support for selected widget GET requests before publishing an SDK version that uses this flow. The selected response must include quote.

If the host already has a catalog, it can show an immediate local estimate and refresh the authoritative quote without another catalog request:

import { estimateLockerverseCheckout } from "@lockerverse/sdk/checkout";

const estimate = estimateLockerverseCheckout(catalog, {
  includeServiceFee: catalog.widget.fields.serviceFee,
  selection,
});
const checkout = await client.calculateTotal({
  catalog,
  includeServiceFee: catalog.widget.fields.serviceFee,
  selection,
});

The estimate supports catalog prices, quantities, custom amounts, tips, and the published service-fee rate. It does not apply discounts. Do not use it for payment submission. Only the authoritative quote can create a payment.

createLockerverseCheckoutClient() exposes only load, calculateTotal, submitPayment, and getPaymentStatus. The client has no selection store, lifecycle state, recurring billing lifecycle, or Stripe state. React applications can use @lockerverse/react for the complete payment UI and orchestration.

Select one fixed recurring Product without a quantity. Lockerverse returns its monthly or annual cadence in the prepared checkout:

const recurringCheckout = await client.calculateTotal({
  catalog,
  email: "[email protected]",
  items: [{ productId: monthlyProduct.id }],
});

One-time fixed Products use quantity. One-time custom Products use amountCents. A recurring checkout contains exactly one fixed Product.

Fixed prices in the catalog are display data. calculateTotal() sends Product IDs and selections to Lockerverse, which resolves the payable amount. The host returns them together as one immutable prepared checkout. Pass that prepared checkout to submitPayment() so a host cannot accidentally submit different inputs from the ones Lockerverse quoted. It owns one stable payment reference so Lockerverse can prevent duplicate checkout creation and recover ambiguous outcomes.

If submitPayment() throws an error with recoveryRecommended: true, the request may still have reached Lockerverse. Query getPaymentStatus() with the prepared checkout's payment reference before allowing another payment. Other failures are definitive and do not require recovery.

Runtime configuration

Production is the default endpoint and environment. Checkout, signup, auctions, and public event listings share these options. A custom endpoint requires an explicit environment; development also requires an explicit apiBaseUrl. Include /api in this URL. The generated attendee client uses a separate baseUrl option with the origin only, as shown in its section below.

const client = createLockerverseCheckoutClient({
  apiBaseUrl: "https://portal-dev.lockerverse.com/api",
  communitySlug: "auburn",
  environment: "development",
  widgetSlug: "auburn-tailgate-party",
});

Custom endpoints must be HTTP(S) URLs without credentials, query strings, or fragments. HTTPS is required. Local HTTP endpoints are accepted only with environment: "development" and a host of localhost, 127.0.0.1, [::1], or a .localhost subdomain. Requests have a 20-second deadline by default; override it with a positive requestTimeoutMs value. The same deadline includes reading successful JSON responses and supported payment or signup error bodies.

Public Event attendees

Use the generated public API client. It already owns the route, parameters, response type, and production origin:

import { getPublicEventAttendees } from "@lockerverse/sdk";

try {
  const { data } = await getPublicEventAttendees({
    path: {
      communitySlug: "auburn",
      eventId: "11111111-1111-4111-8111-111111111111",
    },
    throwOnError: true,
  });
  console.log(data.registrations);
} catch (error) {
  console.error("Could not load attendees", error);
}

data.registrations contains each public name and party size. Pass data.nextCursor as query.cursor to load the next page. For development, create the same generated client with the development origin and pass it to each request:

import { createLockerversePublicApiClient } from "@lockerverse/sdk";

const client = createLockerversePublicApiClient({
  baseUrl: "https://portal-dev.lockerverse.com",
});

const firstPage = await getPublicEventAttendees({
  client,
  path: {
    communitySlug: "auburn",
    eventId: "11111111-1111-4111-8111-111111111111",
  },
  throwOnError: true,
});

if (firstPage.data.nextCursor) {
  await getPublicEventAttendees({
    client,
    path: {
      communitySlug: "auburn",
      eventId: "11111111-1111-4111-8111-111111111111",
    },
    query: { cursor: firstPage.data.nextCursor },
    throwOnError: true,
  });
}

Signup

import { createLockerverseSignupClient } from "@lockerverse/sdk/signup";

const signup = createLockerverseSignupClient({
  communitySlug: "auburn",
  signupSlug: "tailgate-guests",
});

const definition = await signup.load();
const submissionReference = crypto.randomUUID();
const submission = await signup.submit({
  answers: [{ fieldId: "guest-type", value: "student" }],
  email: "[email protected]",
  name: "Ada Lovelace",
  participantCount: 2,
}, { submissionReference });

The signup client is stateless. Calls to load and submit are independent. Signup definitions always have an enabled, required name field. For all other built-in fields, a disabled field is never required. The SDK rejects a response that breaks these rules before it reaches the UI. Create a submission reference before a request. If an error has recoveryRecommended: true, reuse that reference with the same values so Lockerverse can return the original submission.

Auctions

Use the auction client without React or Stripe UI dependencies:

import { createLockerverseAuctionClient } from "@lockerverse/sdk/auctions";

const auctions = createLockerverseAuctionClient({ communitySlug: "auburn" });
const catalog = await auctions.list();
const auction = await auctions.load("community-auction");
const item = auction.items[0];

The default environment is production. For development, set both apiBaseUrl and environment: "development", as shown in runtime configuration. load returns the auction, enabled items, bid amounts, inventory, fees, and payment configuration. The payment configuration supplies the Stripe publishable key and connected account; no secret key belongs in a browser. Older backends can omit this configuration; update the backend before using the built-in auction checkout.

The following functions show the raw mutation API. They do not run until your application calls them after the customer confirms their choice:

import type {
  LockerverseAuctionBidSubmission,
  LockerverseAuctionPurchaseSubmission,
} from "@lockerverse/sdk/auctions";

function submitBid(itemId: string, submission: LockerverseAuctionBidSubmission) {
  return auctions.createBid(auction.path, itemId, submission);
}

function submitPurchase(itemId: string, submission: LockerverseAuctionPurchaseSubmission) {
  return auctions.createPurchase(auction.path, itemId, submission);
}

Create a Stripe confirmation token with the payment configuration from the auction. Bids use card setup for later off-session settlement. Buy-now uses immediate payment. Both submissions include the token, email, and E.164 phone. Amounts are integer USD cents. Send the expected subtotal, service fee, and total that the customer accepted. Handle requiresAction with Stripe handleNextAction and the returned clientSecret.

  • Never automatically retry a bid. The backend does not deduplicate bids and has no public bid-status recovery endpoint. An unknown result needs support follow-up; a submitted bid is not a winning bid or a payment receipt.
  • Create one clientRequestId before a buy-now request. Keep that ID and the same purchase details for recovery. Call getPurchaseStatus(auctionSlug, itemId, clientRequestId) to check the existing purchase without creating another payment. It returns a purchase result or null and can reconcile Stripe status and deliver the purchase notification. null means no purchase was found at that moment; it does not prove an original in-flight request has ended. If you retry a submission, use the same original request ID and details. Use status === "paid" to establish payment completion; a pending result is not completion.
  • getPurchaseReceipt(auctionSlug, itemSlug, purchaseId) takes the item slug, while mutations take its ID. The receipt contains amounts and quantity, not payment status. It is not proof of successful payment.

For card-only buy-now Elements configured with paymentMethodTypes: ["card"], pass the same paymentMethodTypes: ["card"] in createPurchase. Omit this field when collecting payment details with automatic payment methods. Stripe requires the client and server payment-method configuration to match. Include a return_url when creating the confirmation token.

The built-in React auction checkout accepts cards only. The core client accepts the confirmation tokens supported by the backend; a custom UI must obey its payment-method rules.

For ready-made browsing and checkout, use @lockerverse/react/auctions and @lockerverse/react/auction-item.

Public event listings

Use @lockerverse/sdk/public-events to read a community's publicly listed Events. This API is separate from the ticket attendee API at the package root. It does not require a user account or expose ticket data.

import { createLockerversePublicEventsClient } from "@lockerverse/sdk/public-events";

const client = createLockerversePublicEventsClient({ communitySlug: "auburn" });
const upcoming = await client.list();
const past = await client.listPast({ limit: 20, offset: 0 });
const selected = await client.search({
  from: "2026-09-01T00:00:00.000Z",
  to: "2026-10-01T00:00:00.000Z",
  timeScope: "all",
  sort: "startAtAsc",
  limit: 20,
  offset: 0,
});
if (past.hasMore) {
  const nextPage = await client.listPast({ limit: 20, offset: past.events.length });
}

list() returns Events that are happening now or start in the future. listPast() returns { events, hasMore } for Events that have ended; its defaults are limit: 20 and offset: 0. Increment the offset by the number of records already loaded. Each Event has id, name, description, imageUrl, location, link, startAt, and endAt. The description, image, location, and link can be null. The backend controls public visibility. The SDK validates responses and returns immutable snapshots. Use @lockerverse/react/public-events for the styled list with Upcoming and Past views.

search() returns the same page shape and defaults to timeScope: "current". The Event must overlap the window: it must end after from and start before to. timeScope can be current, past, or all. Sort with startAtAsc, startAtDesc, endAtAsc, or endAtDesc. Follow hasMore with the next offset to read the full range.

Security and observability

  • No Stripe or Lockerverse secret is accepted by the public API.
  • Successful catalog, quote, confirmation, and status responses are validated before being returned.
  • Public operation inputs are validated with private Valibot schemas.
  • Backend response bodies and validation internals never escape in SDK errors.
  • Expected input errors are reportable: false; unexpected network and server failures are reportable: true.
  • Reportable failures are sent directly to Lockerverse Sentry with allowlisted request context. sentryDsn: null disables loading and sending telemetry.
  • The Sentry runtime is an isolated failure-only chunk and does not replace or mutate the host application's Sentry client.
  • Stripe's shared publishable key is selected by environment. The authoritative quote supplies the community's connected account.
  • Analytics is intentionally out of scope.

Commands

Run these from the repository root:

pnpm dev:react
pnpm typecheck
pnpm test
pnpm build
pnpm --filter @lockerverse/sdk pack:check