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

@openexercise/open-workout-client

v0.4.0

Published

A thin TypeScript client for any Open Workout server, generated from the Open Workout API core, with Lifterclub's full API as a subpath.

Readme

@openexercise/open-workout-client

A thin TypeScript client for any Open Workout server. It's an openapi-fetch client typed from the Open Workout API core (api/core.yaml), which sends your token and an Idempotency-Key on every POST, plus a few helpers. Workouts are Open Workout Schema documents, and exercises are Open Exercise IDs.

npm install @openexercise/open-workout-client

Two entry points:

  • @openexercise/open-workout-client: the core, for any server. createOpenWorkoutClient takes the server's address.
  • @openexercise/open-workout-client/lifterclub: Lifterclub, the reference implementation. createLifterclubClient is typed from Lifterclub's full API (the core plus sentence parsing, records and progress, the profile, routines, programs, imports and partners), and defaults to https://api.lifterclub.com.

Published from openexercise/open-workout, where a tag clients-ts-v<version> releases it with npm provenance.

Use

import { changes, createOpenWorkoutClient, signatureHeader, unwrap, verifySignature } from '@openexercise/open-workout-client'

const api = createOpenWorkoutClient({ baseUrl: 'https://api.lifterclub.com', token: () => tokens.access })

// Every route in the core, typed from the document.
const logged = unwrap(
  await api.POST('/v1/workouts', {
    body: { external_id: 'my-42', exercises: [{ name: 'bench press', sets: [{ reps: 5, load: 185, unit: 'lb' }] }] },
  }),
)
console.log(logged.summary)

// Mirror a log: every change since the last time, oldest first, deleted ones as tombstones.
for await (const change of changes(api, { updatedSince: lastSeen, includeDeleted: true })) {
  if (change.kind === 'workout') store(change.workout)
  else remove(change.tombstone.id)
}

// A webhook delivery, signed in OWS-Signature.
const ok = await verifySignature(subscription.secret, request.headers.get(signatureHeader), rawBody)

For Lifterclub's routes beyond the core:

import { createLifterclubClient, unwrap } from '@openexercise/open-workout-client/lifterclub'

const lc = createLifterclubClient({ token: () => tokens.access })
const draft = unwrap(await lc.POST('/v1/parse', { body: { text: 'bench 3x8 at 185' } }))

api.GET, POST, PATCH, PUT and DELETE return { data, error, response }. unwrap returns data, or throws an ApiError. Its code is the error code (rate_limited, not_found, invalid_token…), with status, detail, the full problem, and retryAfter in seconds when the status is 429.

A POST retried with the same Idempotency-Key returns the first result instead of writing twice. The client makes a key per call; pass your own in headers to retry across restarts.

Lifterclub also signs webhooks as Lifterclub-Signature (lifterclubSignatureHeader) until OWS v1, for receivers written before.

Moving from @openexercise/lifterclub-client

That package was this one under its earlier name, up to 0.3.0. Install this one instead, and import from @openexercise/open-workout-client/lifterclub to keep createLifterclubClient and every type as they were. Read OWS-Signature (signatureHeader) on new webhook receivers.

Develop

  • npm run gen regenerates src/core.d.ts and src/lifterclub-api.d.ts from the OpenAPI documents: the Lifterclub repository's docs/openapi/ows-core.yaml and v1.yaml, or api/core.yaml and api/v1.yaml next to this package. CORE_SPEC=path and SPEC=path name other copies.
  • npm run check fails when the committed types are stale.
  • npm test, npm run typecheck, npm run build.