chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
# Contributing
## Setup
```bash
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`](https://github.com/casey/just) and Docker installed, one command
starts the whole stack:
```bash
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.
<details>
<summary>Setup without <code>just</code></summary>
```bash
# 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
```
</details>
## The commit gate
```bash
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:
```bash
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.
```bash
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](docs/permissioned-data.md).
## Conventions
[CLAUDE.md](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](docs/architecture.md) explains the ports and the packages.
[docs/pds-decomposition.md](docs/pds-decomposition.md) tracks the handler module
work in `core/src/pds.js`. Read it before you take the next cluster.
## Changesets
```bash
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
```