~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
145 lines · 4.6 KB Raw History

Contributing

Setup

git clone https://tangled.org/chadtmiller.com/pds.js
cd pds.js && pnpm install
npm run build:ui

Install with pnpm. The workspace dependencies use the workspace:* protocol, and npm install fails on it with EUNSUPPORTEDPROTOCOL. The npm run scripts work normally once pnpm has installed the tree.

Run npm run build:ui first on a fresh clone. @pdsjs/account-ui exports a gitignored bundle, and without it the node and cloudflare entrypoints do not resolve.

Local development

With just and Docker installed, one command starts the whole stack:

just dev        # infra, PDS, and a seeded account
just dev-down   # stop the PDS and remove the docker infra

just dev starts the docker infra (local PLC, relay, Caddy) and runs the PDS on port 2471. It then registers a mock account with a few records. Open http://localhost:2471/account and sign in with the printed credentials.

just dev serves a prebuilt account interface. There is no hot reload. After you change interface code, run npm run build:ui and refresh the page.

For live interface work, run just dev-live. It starts the same stack plus a Vite dev server with hot module reload on port 5173. Sign in at http://localhost:5173/account, and your edits reload in the browser. The PDS also restarts on backend edits. Port 2471 and port 5173 are different origins, so you sign in separately on each.

Run just to see all recipes. just logs tails the PDS log.

Setup without <code>just</code>
# Start the local PLC and relay (needs Docker)
docker compose up -d

# Start the PDS
npm run dev:node

# Register with the local PLC, in another terminal
npm run setup -- --pds https://localhost:3443 --plc-url http://localhost:2582 --relay-url http://localhost:2470

The commit gate

npm run ci

That runs build:ui, biome, tsc --noEmit, and test:coverage. CI runs the same command. Run it before you commit.

The full gate is heavy: the git integration tests spawn the real git binary against an in-process PDS, and the coverage floors across 195 test files take a few minutes. You do not need it for every local edit. CI enforces it on every push, so iterate with the targeted commands below and run the full gate only before you commit.

The individual steps:

npm run check       # biome lint + format check
npm run format      # auto-format
npm run lint        # lint only
npm run typecheck   # tsc --noEmit
npm test            # unit tests
npm run test:watch  # unit tests, watching

Coverage floors are in vitest.config.js, per area rather than global. A glob key aggregates every file it matches, so give each module its own entry.

End-to-end tests

The e2e suite is not part of the gate. It needs docker compose.

docker compose up -d
npm run test:e2e:node
npm run test:e2e:deno
npm run test:e2e:cloudflare

The suite binds port 2471, so a just dev stack blocks it.

npm run test:reference tests permissioned data against the reference implementation. See docs/permissioned-data.md.

Conventions

CLAUDE.md holds the conventions this repository enforces by review rather than by tooling: what earns a comment, how to phrase one, no any in library type annotations, and no em dashes in user-facing copy.

docs/architecture.md explains the ports and the packages. docs/pds-decomposition.md tracks the handler module work in core/src/pds.js. Read it before you take the next cluster.

Changesets

npm run changeset

Describe the change relative to the previous release. That is where "what changed" belongs, rather than in a code comment.

Project structure

packages/
  core/               # platform-agnostic core
  spaces/             # permissioned data (optional)
  lexicon-resolver/   # lexicon resolution and record validation
  account-ui/         # account interface
  node/               # Node.js adapter
  deno/               # Deno adapter
  cloudflare/         # Cloudflare adapter
  readonly/           # read-only server for CAR-backed repositories
  storage-sqlite/     # SQLite storage adapter
  blobs-*/            # blob storage adapters
examples/
  node/               # Node.js example
  deno/               # Deno example
  cloudflare/         # Cloudflare example
  runclub/            # permissioned data demo, two PDSes and a syncing app
docker/               # container entrypoint and the local dev stack
scripts/              # setup, seeding, and reference tests