From 0f7bb6ec7db28a8040783a70040cbb1376fae627 Mon Sep 17 00:00:00 2001 From: Natalie Rose Date: Mon, 17 Aug 2026 10:08:25 +1000 Subject: [PATCH] Add Claude file --- CLAUDE.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..ec8ef0a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,78 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What this repo is + +A TypeScript client library for the JSON-RPC API of *The Lacuna Expanse* (community +edition game server), published as `@tlecommunity/client` to a private Gitea npm +registry. + +The repo serves two purposes at once: +1. It's the HTTP client other projects use to talk to the TLE server. +2. Its test suite is a deliberate **integration test for the TLE backend itself** — + tests call the real, live TLE server (no mocks) to verify responses stay correct + as that backend migrates from a legacy, untyped Perl codebase to Ruby on Rails. + This is *why* tests hit a live server instead of mocking — it's the design, not + an oversight. A passing suite is evidence the backend still behaves correctly, + not just that the client code is correct. + +## Commands + +- `npm run types` — typecheck (`tsc --noEmit`) +- `npm test` — run the full suite (`jest --coverage`); makes real network calls, see caveat below +- `npx jest lib/endpoints/captcha.test.ts` — run a single test file +- `npx jest -t "drain"` — run tests matching a name +- `npm run build` — library build via `vite build` (also emits `.d.ts` via vite-plugin-dts) +- `npm run lint` / `npm run lint:fix` — Prettier check/write (there is no ESLint in this repo) +- `npm run prepare` — full pre-publish pipeline (`types` → `test` → `build`), runs automatically on `npm publish` +- Requires Node >=22, npm >=10 (`.nvmrc` pins 22) + +## Test caveat (read before touching tests) + +Tests are intentionally **not mocked**. `lib/__utils__/get-lacuna.ts` constructs a +real `Lacuna` instance and authenticates against a live server (default `serverUrl` +in `lib/core/config.ts` is a Tailscale-hosted instance). Every `*.test.ts` file +under `lib/` exercises real endpoints over the network. `lib/__utils__/` itself is +excluded from Jest's test discovery and from coverage collection (it's a helper, +not a test). + +## Architecture + +- `lib/index.ts` is the package entry point, exporting `Lacuna` (default), `util`, and `types`. +- `Lacuna` (`lib/lacuna.ts`) is the root object. Its constructor builds the core + infra — `Log`, `Config`, `Server`, `Session` — and then one instance per API + module (`body`, `empire`, `captcha`, `shipyard`, `spacePort`, `stats`, + `essentiaVein`, plus `planetaryCommand`/`university` via the generic `Building` + endpoint). Every endpoint receives the parent `Lacuna` instance in its + constructor and reaches back through it (`this.lacuna.server`, `.session`, `.log`). +- `lib/core/endpoint.ts` — abstract `Endpoint` base class every API module + extends; provides `callWithSession` / `callWithoutSession`, which delegate to `Server#call`. +- `lib/core/server.ts` — the JSON-RPC transport. Builds the request body + (`{jsonrpc: '2.0', id, method, params}`), injects the session id into + positional (array) params when `addSession: true`, POSTs via axios, and + normalizes numeric strings in the response via `fixNumbers` (the server returns numbers as strings). +- `lib/core/session.ts` — holds the session id set by `Lacuna#authenticate`. +- `lib/core/config.ts` — holds `serverUrl` / `apiKey` / `fingerprintToken`. +- `lib/endpoints/*.ts` — one file per top-level API module (`empire`, `body`, + `captcha`, `stats`, `building`). Each is a thin class extending `Endpoint` whose + methods just forward typed params to `callWithSession`/`callWithoutSession`, + in the exact positional-argument order the server RPC expects. +- `lib/endpoints/buildings/*.ts` — building-specific modules (`essentia-vein`, + `shipyard`, `space-port`) extend the generic `Building` endpoint + (`lib/endpoints/building.ts`) rather than `Endpoint` directly, inheriting + `view`/`upgrade`/`downgrade`/`demolish`. +- `lib/types/*.ts` — one file per endpoint module with `*Params`/`*Response` + interfaces, mirroring the `lib/endpoints/` structure 1:1 (imported as + `import * as B from '../types/building'`). `lib/types/index.ts` re-exports all + of them plus shared aliases (`ServerDate`, `EmpireName`, `IntBool`, + `MapLocation`, `LacunaConfig`). + +### Adding a new endpoint method + +1. Add the params/response interfaces to the matching `lib/types/.ts`. +2. Add a method to the matching `lib/endpoints/.ts` that calls + `callWithSession`/`callWithoutSession` with positional params in the + server-expected order. +3. Add a colocated `.test.ts` that exercises it against the live test + server via `getLacuna()`. -- 2.51.2