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

@activityplug/server

v1.0.2

Published

GraphQL and HTTP server surfaces for ActivityPlug.

Readme

@activityplug/server

@activityplug/server exposes ActivityPlug through a versioned HTTP API, GraphQL, WebSocket streams, and an optional browser backend-for-frontend (BFF). Applications that own their configuration and storage construct it through the createActivityPlugServer() API. The activityplug-server command lives in @activityplug/cli.

Node.js 26 or newer is required. The package uses ECMAScript modules.

Command-line server

@activityplug/cli provides the activityplug-server command. It bundles the Mastodon, Misskey, Pleroma, Hollo, and HackersPub adapters and uses process-local stores:

npx @activityplug/cli \
  --allow-origin https://social.example

See the @activityplug/cli README for its options. Applications that need durable stores should construct the server through this package instead.

Installation

Install the server and its peer dependencies:

pnpm add @activityplug/server @activityplug/core @hono/node-server @logtape/logtape graphql hono

Install each adapter that your program imports directly. For example:

pnpm add @activityplug/mastodon

The package root contains the supported public API:

import * as activityplug from "@activityplug/server";

The examples below use named imports so their required configuration is visible.

Programmatic server

Applications should construct the adapters, origin policy, stores, and listener explicitly:

import { createMastodonAdapter } from "@activityplug/mastodon";
import {
  createActivityPlugServer,
  createNodePinnedWebSocketFactory,
  createOriginPolicy,
  nodeLookupAddresses,
} from "@activityplug/server";

const originPolicy = createOriginPolicy(["https://social.example"]);
const webSocket = createNodePinnedWebSocketFactory({
  originPolicy,
  lookup: nodeLookupAddresses,
});

const server = createActivityPlugServer({
  adapters: [createMastodonAdapter({ webSocket })],
  originPolicy,
  tokenImport: { enabled: false },
});

await server.ready;
try {
  server.start({ hostname: "127.0.0.1", port: 4000 });
  await new Promise<void>((resolve) => {
    process.once("SIGINT", () => resolve());
    process.once("SIGTERM", () => resolve());
  });
} finally {
  await server.close();
}

Without an explicit originPolicy, the constructed server rejects every remote request. allowPrivateNetworks changes address filtering only; it does not allow an origin that the policy rejects.

ready resolves after the owned security-state lifecycle starts. Requests also wait for it. close() is idempotent and closes listeners created by this server. Injected store clients, database pools, and other dependencies remain caller-owned and must be closed after the server.

Choose an API surface

  • Use server.service for calls inside the same Node.js process.
  • Use /api/v1 for the versioned HTTP API and /api/v1/openapi.json for its OpenAPI document.
  • Use /graphql for GraphQL queries and mutations.
  • Use /api/v1/streams/* for the HTTP API's WebSocket streams.
  • Configure browser and use /v1/browser/* when an application needs an HttpOnly cookie BFF instead of exposing ActivityPlug session IDs to browser JavaScript.

Public HTTP and GraphQL clients send ActivityPlug session IDs in Authorization: Bearer. Browser routes reject that header and bind authentication to the __Host-activityplug cookie.

Browser configuration

Browser mode requires a public HTTPS origin, a 32-byte or longer signing key, and browser and stream-ticket stores:

import {
  createActivityPlugServer,
  InMemoryBrowserSessionStore,
  InMemoryStreamTicketStore,
} from "@activityplug/server";

const server = createActivityPlugServer({
  adapters,
  originPolicy,
  browser: {
    publicOrigin: "https://app.example",
    cookieSigningKey,
    browserSessions: new InMemoryBrowserSessionStore(),
    streamTickets: new InMemoryStreamTicketStore(),
  },
});

The server supplies in-memory OAuth state, authentication challenge, and authentication-start limiter stores when they are omitted. These defaults, the stores shown above, and the default authentication session store lose state on restart. Production deployments should inject durable implementations for every lifecycle store they use.

Anonymous browser sessions are stateless by default. Set anonymousSessionMode: "stored" only when server-side allocation is required; stored mode applies global, per-client, and creation-rate admission limits. A direct deployment can use the verified transport peer as the client identity. A deployment behind a proxy should provide a resolver that trusts forwarding headers only from known proxy addresses.

Routes

The principal entry points are:

| Route | Purpose | | --------------------------------- | --------------------------------------- | | GET /health | Process and dependency readiness | | GET /api/v1 | HTTP API version and discovery links | | GET /api/v1/openapi.json | HTTP API contract | | POST /graphql | GraphQL API | | GET /api/v1/streams | Public stream protocol metadata | | GET /api/v1/streams/* | Public WebSocket streams | | GET /v1/browser/session | Browser session and CSRF bootstrap | | /v1/browser/auth/* | Browser authentication flows | | /v1/browser/api/* | Cookie-authenticated browser operations | | POST /v1/browser/stream-tickets | Single-use browser stream ticket | | GET /v1/browser/stream | Ticket-authenticated browser stream |

The complete HTTP operation list is published by the running server's OpenAPI document. Browser routes intentionally expose a smaller product-facing surface.

Storage and security choices

The default stores are suitable for tests, examples, and single-process development. Durable deployments must keep related records in compatible stores. In particular, a durable authentication session store requires a matching oauthClientSecrets store.

Configure the following according to the surfaces you enable:

  • sessions and oauthClientSecrets for authentication sessions and OAuth client secrets;
  • browserSessions, oauthStates, streamTickets, authStartLimiter, and authChallenges for browser mode;
  • readiness to include durable dependencies in GET /health;
  • requestLimits for transport bodies, remote structured responses, and WebSocket buffering;
  • graphqlLimits for GraphQL document shape and resolver concurrency;
  • createBudgetScope for per-operation remote request, byte, node, concurrency, and deadline budgets;
  • remoteCredentialGrants when a credential may be sent to an origin other than its issuer;
  • clientIp when rate limits run behind a trusted reverse proxy.

See server usage, browser integration, session storage, security model, and errors and troubleshooting.

License

Licensed under Apache-2.0 OR MIT. See LICENSE-APACHE and LICENSE-MIT.