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

@withmarfa/sdk

v1.6.0

Published

TypeScript HTTP client for the [Marfa](https://marfa.so) API.

Readme

@withmarfa/sdk

TypeScript HTTP client for the Marfa API.

pnpm add @withmarfa/sdk
import { MarfaClient } from "@withmarfa/sdk";

const client = new MarfaClient({
  url: "https://staging.marfa.so",
  apiKey: process.env.MARFA_API_KEY,
});

const note = await client.items.create({
  type: "core.note",
  properties: { title: "Hello", body: "World" },
});

Surface

client.{items,types,keys,edges,search,metadata,tenants,webhooks,connections,auth} — one nested namespace per API surface. Methods return the unwrapped resource (e.g. client.items.get returns Item, not { item }); errors throw typed MarfaError subclasses (NotFoundError, ValidationError, UnauthorizedError, ForbiddenError, ConflictError).

The OAuth helpers (PKCE, device flow, token storages, MarfaAuth) ship under the @withmarfa/sdk/auth subpath.

Testing

The SDK ships two in-process test fixtures so consumers can exercise the client against a real Hono server without a network. Both are in packages/sdk/src/test-harness.ts.

Keys-mode fixture (createKeysModeFixture)

For SDK surfaces that don't depend on auth_user resolution. Bootstraps a platform-admin API key over POST /keys and returns a client wired to it.

import { createKeysModeFixture } from "./test-harness.js";

const { client, adminKey, cleanup } = await createKeysModeFixture();
try {
  const note = await client.items.create({
    type: "core.note",
    properties: { body: "Hello" },
  });
  expect(note.id).toBeTruthy();
} finally {
  cleanup();
}

Hosted-mode fixture (createHostedModeFixture)

For SDK surfaces that resolve an auth_user from the bearer (account lifecycle, future passkey shims, anything that needs client.auth.account.*). Boots the server in authMode: 'hosted', signs up a fresh user via the wrapped form endpoint (which provisions tenants + users bridge atomically), marks email-verified directly, and mints a tenant_admin API key bound to the new user's tenant. The returned client uses that key as bearer; account-lifecycle routes resolve through the bridge.

import {
  createHostedModeFixture,
  readLatestAccountVerification,
} from "./test-harness.js";

const fixture = await createHostedModeFixture();
try {
  await fixture.client.auth.account.requestDelete();

  // The harness leaves emailTransport undefined; routes silently skip
  // send. The confirm token still lands in auth_verification.
  const token = await readLatestAccountVerification(
    fixture.storage,
    "account-delete:",
  );
  await fixture.client.auth.account.confirmDelete(token ?? "");

  await fixture.client.auth.account.cancel();
} finally {
  fixture.cleanup();
}

The fixture exposes email, authUserId, tenantId, and bearerKey for tests that need to assert on or interact with the underlying user — e.g. minting additional clients against the same tenant, or correlating audit rows.

When to use which

| Surface under test | Fixture | | ------------------------------------------------------------------------------------- | ------------------------- | | items / edges / search / types / metadata / tenants / webhooks / keys | createKeysModeFixture | | auth.account.{requestDelete,confirmDelete,cancel} | createHostedModeFixture | | Any future SDK surface that resolves auth_user.id from the bearer | createHostedModeFixture |

Both fixtures share the same SQLite-backed in-process server. PG matrix coverage of the SDK lives off this scope — it runs through the server's test:pg matrix on every PR, not the SDK's pnpm test.

Build

tsup produces dist/index.js (ESM) and dist/index.d.ts. @withmarfa/types declarations are inlined into the shared .d.ts so consumers only need @withmarfa/sdk and @withmarfa/shared.

Versioning

Major bumps when @withmarfa/shared major-bumps (every wire-shape change cascades). Minor bumps for additive SDK features. Patch for bug fixes. Tag pushes (v*) trigger the OIDC-published release workflow; the workflow skips packages whose version is already on npm so unbumped packages are no-ops.