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

@prosewire/sdk

v0.4.0

Published

Typed client for the Prosewire content API.

Readme

@prosewire/sdk

Typed clients for Prosewire's authenticated management API and public content API.

The package is pre-1.0. Pin a compatible version and review the changelog before upgrading.

Full guide: Build a native reader with TypeScript

Install

pnpm add @prosewire/sdk

Node.js 24 or newer is supported.

Read published content

import { createPublicClient } from "@prosewire/sdk";

const publicContent = createPublicClient({
  baseUrl: "https://your-prosewire-deployment",
  blog: "fieldnotes",
});

const page = await publicContent.listPosts({ page: 1, pageSize: 20 });
console.log(page.posts.map((post) => post.title));

Filter lists and retrieve JSON or rendered HTML:

const page = await publicContent.listPosts({
  search: "portable",
  category: "engineering",
  page: 1,
  pageSize: 20,
});

console.log(page.posts.map((post) => post.title));
const article = await publicContent.getPost("welcome");
const resolution = await publicContent.resolvePost("old-welcome-slug");
const redirects = await publicContent.listRedirects();
const html = await publicContent.getRendered("welcome");

Public clients need no key and only return published content whose publication time has arrived. pageSize is capped at 100. listAllPosts follows every page for static builds, while resolvePost preserves the difference between a canonical post, redirect, and 404. The deprecated limit option remains an alias for pageSize.

Manage a publication

Create a publication-scoped API key in Integrate → Scoped API keys and keep it on a trusted server:

import { createClient } from "@prosewire/sdk";

const management = createClient({
  baseUrl: process.env.PROSEWIRE_API_URL!,
  apiKey: process.env.PROSEWIRE_API_KEY!,
});

const drafts = await management.posts.list({ status: "draft" });

Available Promise operations are:

  • imports.run() (streamed portable import, content:write)
  • health()
  • blogs.list()
  • posts.list(), posts.get(), and posts.create()
  • posts.update() and posts.archive()
  • posts.revisions() and posts.restore()
  • media.list(), media.get(), and media.startUpload()
  • media.completeUpload() and media.delete()

Management keys are publication-scoped. Post, revision, and media reads require content:read. Create, update, archive, revision restore, and media mutations require content:write. A restore saves the current post as a new revision before replacing it. Media deletion fails while a current post references the asset. Never expose a management key or signed upload reservation in untrusted code.

Start a managed upload with the publication UUID, filename, MIME type, and exact byte count. Send the bytes to the returned signed URL using its method and headers, then call media.completeUpload() with the reserved asset ID. Completion returns the sanitized variants and CDN URL.

The optional blog value on posts.list() is a safety assertion. It must match the API key's publication slug or UUID; it cannot select another publication.

For Effect applications, createEffectClient exposes the same operations as typed Effects. createClient is the Promise-compatible facade for existing callers; both share the Effect HttpApi contract; portable import uses its own streaming adapter and shared report/error schemas.

Non-success responses reject. Public-client errors include the HTTP status; management errors retain the typed Effect HTTP API failure when using createEffectClient.

Portable import

import { openPortableImportFile } from "@prosewire/sdk/import-node";

const preview = await management.imports.run({
  ...openPortableImportFile("export.json", "media.zip"),
  mode: "preview",
});

The main entrypoint accepts a ReadableStream<Uint8Array> and application/json or application/zip; the Node-only helper streams local export artifacts. Explicit mode: "apply" creates content, with posts defaulting to drafts unless preserveStates: true is supplied. Failures retain status, item, and reason in ProsewireImportError. See portable import for supported formats, limits, and exact-artifact retry policy.