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

@act-spec/runtime-fetch

v0.2.0-rc.1

Published

PRD-505 generic WHATWG-fetch handler for the ACT (Agent Content Tree) v0.1 reference implementation. Single-function adapter — `createActFetchHandler(opts) => (req: Request) => Promise<Response | null>` — portable across Cloudflare Workers, Deno Deploy, B

Readme

@act-spec/runtime-fetch

Generic WHATWG-fetch handler for ACT (Agent Content Tree).

This package is the leanest possible leaf over @act-spec/runtime-core. The whole adapter is one closure exposing one function:

(request: Request) => Promise<Response | null>

Because the input is already a WHATWG Request and the output is a WHATWG Response, this handler runs unchanged on every fetch-native runtime: Cloudflare Workers, Deno Deploy, Bun's Bun.serve, Vercel Edge Functions, Hono, Service Workers, and Node.js 20+ (where Request / Response are global). No Node-only API dependencies; no framework SDK.

Status

ACT v0.1 internal hand-test candidate. Public release lands at v0.2.

Install

Unpublished in v0.1. Consume via the workspace:

// package.json
{ "dependencies": { "@act-spec/runtime-fetch": "workspace:*" } }

This package has zero peer dependencies. It depends only on @act-spec/runtime-core (which depends on @act-spec/core + @act-spec/validator); the dispatch pipeline, ETag computation, conditional GET, content negotiation, identity / tenant resolution, and discovery Link header all live in runtime-core.

Quick start (Cloudflare Worker)

import { createActFetchHandler } from '@act-spec/runtime-fetch';

const actHandler = createActFetchHandler({
  manifest: {
    act_version: '0.1',
    site: { name: 'Acme Workspace' },
    delivery: 'runtime',
    conformance: { level: 'core' },
    auth: { schemes: ['bearer'] },
    index_url: '/act/index.json',
    node_url_template: '/act/n/{id}',
  },
  runtime: {
    async resolveManifest(req, ctx) { /* ... */ },
    async resolveIndex(req, ctx) { /* ... */ },
    async resolveNode(req, ctx, { id }) { /* ... */ },
  },
  identityResolver: async (actReq) => {
    const auth = actReq.headers.get('authorization');
    if (!auth?.startsWith('Bearer ')) return { kind: 'auth_required', reason: 'missing' };
    const claims = await verifyJwt(auth.slice(7));
    return claims ? { kind: 'principal', key: claims.sub } : { kind: 'auth_required', reason: 'invalid' };
  },
});

export default {
  fetch: async (req: Request): Promise<Response> => {
    const actResponse = await actHandler(req);
    if (actResponse) return actResponse;
    // Fall through to other handlers (HTML pages, app API, etc.)
    return new Response('Not Found', { status: 404 });
  },
};

Routing

The manifest is the routing source of truth. The handler reads the manifest's URL templates at construction time and routes incoming requests against them:

| Path | Endpoint | Level | |---|---|---| | manifestPath (default /.well-known/act.json) | manifest | Core | | index_url | index | Core | | node_url_template (with {id} capture) | node — IDs MAY contain / | Core | | subtree_url_template | subtree | Standard / Plus | | index_ndjson_url | NDJSON-streamed index | Plus | | search_url_template | search | Plus |

The manifestPath is the only URL not declared inside the manifest itself. Override via options.manifestPath for deployments where /.well-known/ is reserved by another protocol or rewritten by the host.

Passthrough vs strict mode

  • passthrough (default) — non-matching requests resolve to null. The host chains its own router: actHandler(req) ?? hostHandler(req). This is the common pattern in Workers / Deno / Hono / Bun.
  • strict — non-matching requests resolve to a 404 with the ACT error envelope (byte-identical to the in-band 404). Use when the deployment is ACT-only and the host wants no fall-through.
const handler = createActFetchHandler({
  /* ... */,
  mode: 'strict', // 404 instead of null for non-ACT paths
});

Hybrid mounts (basePath)

Set basePath to mount the handler under a sub-path; advertised URLs in the served manifest are prefixed automatically:

const handler = createActFetchHandler({
  manifest: { /* ... */ },
  basePath: '/app',
  runtime: { /* ... */ },
  identityResolver: /* ... */,
});

// Effective served URLs:
//   /app/.well-known/act.json
//   /app/act/index.json
//   /app/act/n/{id}

A parent manifest at the root /.well-known/act.json (typically served by a sibling static-export build) declares the mount.

Hono integration

import { Hono } from 'hono';
import { createActFetchHandler } from '@act-spec/runtime-fetch';

const actHandler = createActFetchHandler({ /* ... */ });

const app = new Hono();
app.use('*', async (c, next) => {
  const r = await actHandler(c.req.raw);
  if (r) return r;
  await next();
});
app.get('/', (c) => c.html('<h1>Acme</h1>'));

export default app;

The handler chains naturally — null falls through, a Response short-circuits.

Deno Deploy

import { createActFetchHandler } from '@act-spec/runtime-fetch';

const actHandler = createActFetchHandler({
  manifest: { /* ... */ },
  runtime: { /* ... */ },
  identityResolver: async (actReq) => {
    const serviceId = actReq.headers.get('x-service-account');
    if (!serviceId) return { kind: 'anonymous' }; // public access
    const allowed = (Deno.env.get('ALLOWED_SERVICES') ?? '').split(',');
    if (!allowed.includes(serviceId)) return { kind: 'auth_required', reason: 'invalid' };
    return { kind: 'principal', key: serviceId };
  },
});

Deno.serve(async (request) => {
  const actResponse = await actHandler(request);
  return actResponse ?? new Response('Not Found', { status: 404 });
});

Two-principal probe (cross-tenant non-disclosure)

This package wires the mandatory two-principal probe from @act-spec/runtime-core/test-utils against an in-process synthetic resolver. The probe verifies that:

  1. Each principal can resolve their own visible nodes (sanity baseline).
  2. Cross-tenant requests (principal A asks for principal B's node, and vice versa) return 404.
  3. The cross-tenant 404 is byte-equivalent to an absent-node 404 (status, body, every header — Content-Type, Cache-Control, Link).
  4. The discovery Link header is present and identical across both 404 paths (does not leak tenant identity in error cases).

The probe is in src/probe.test.ts and runs as part of pnpm test. It is a CI-mandatory test; do not skip and do not weaken.

NDJSON streaming portability

The handler streams NDJSON via the manual new ReadableStream({ start(controller) { … } }) form. We deliberately do not use ReadableStream.from(asyncIterable) because it is not yet uniformly available across v0.1 target runtimes (Node.js < 22, some Bun versions). The manual form runs on every WHATWG-fetch host.

Reverse proxies in front of fetch-native deployments (nginx, Caddy) MUST be configured to disable buffering on /act/index.ndjson so clients see lines incrementally.

Web Crypto availability

The default ETag computer uses crypto.subtle.digest('SHA-256', ...) via @act-spec/runtime-core. All v0.1 target runtimes (Cloudflare Workers, Deno Deploy, Bun, Vercel Edge, Hono on Workers, Service Workers, Node.js 20+) provide crypto.subtle. Hosts deploying on older Node.js (< 18) must use --experimental-global-webcrypto or fall back to @act-spec/runtime-express.

Conformance

pnpm -F @act-spec/runtime-fetch conformance runs @act-spec/validator in validateSite runtime-walk mode against an in-process Standard handler via a synthetic fetcher (no real HTTP server). Pass criterion: 0 gaps; achieved level == declared level.

License

Apache-2.0. See LICENSE.