git:20260517.ecc4d06 to git:20260908.f6b799a
10 added, 3 removed. Audit A to A.
# api-client
## Purpose
Generated TypeScript client for the canonry HTTP API. Single source of truth for request/response types across the CLI (`packages/canonry`), web SPA (`apps/web`), and MCP adapter (`packages/canonry/src/mcp/`).
The generator (`@hey-api/openapi-ts`) reads the spec emitted by `packages/api-routes` (via `buildOpenApiDocument()`) and writes typed services into `src/generated/`. Consumers import named operations from the barrel — there is no hand-written client wrapper.
## Layout
```
codegen.ts # generation script — `pnpm gen`
src/
index.ts # public barrel (re-exports generated services + types + createClient)
generated/ # hey-api output (committed, regenerated by pnpm gen)
test/
- drift.test.ts # asserts the committed output still matches the live spec
+ smoke.test.ts # SDK type and request wiring checks
```
## Commands
```bash
pnpm --filter @ainyc/canonry-api-client gen # regenerate src/generated
- pnpm --filter @ainyc/canonry-api-client gen:check # gen + git diff --exit-code (CI drift gate)
+ pnpm --filter @ainyc/canonry-api-client gen:check # compare temporary output with src/generated
pnpm --filter @ainyc/canonry-api-client typecheck
- pnpm --filter @ainyc/canonry-api-client test # drift test
+ pnpm --filter @ainyc/canonry-api-client test # SDK smoke tests
```
## How to use
```typescript
import { createClient, getApiV1Projects } from '@ainyc/canonry-api-client'
const client = createClient({
baseUrl: 'https://api.example.com',
apiKey: process.env.CANONRY_API_KEY,
})
const { data, error } = await getApiV1Projects({ client })
if (error) throw error
// data is fully typed
```
The `createClient` helper applies Bearer auth and a base URL; everything else is the underlying `@hey-api/client-fetch` instance.
## Rules
1. **Never edit `src/generated/` by hand.** Changes are wiped on the next `pnpm gen`.
2. **Spec changes flow downstream.** When `packages/api-routes` adds a route or changes a response schema, the next `pnpm gen` produces the new client. Drift is caught by `gen:check` in CI.
3. **No business logic in `src/index.ts`.** Only re-exports + the thin `createClient` helper. Domain wrappers (caching, retry, error translation) belong in the consuming package.
4. **No DB or app imports.** This package is pure HTTP client; it depends only on `@hey-api/client-fetch` at runtime.
## When to regenerate
+
+ `gen:check` never changes generated files or the Git index. Review and stage generated changes before this check.
+ Every check compares the SDK with the index, including cache hits. Unstaged or untracked generated files fail.
+ `gen:check --committed` compares with `HEAD` instead. Pre-push uses this mode to catch generated files missing from the commit.
+ The cache under `.tmp/codegen/` includes the emitted spec, generator, lockfile, Node version, and generated file contents.
+ Missing, added, or edited output files invalidate the cache. Use `gen:check --force` to run the generator again.
+ `gen` also generates into a temporary directory first. It updates only changed files after generation succeeds.
- After any change in `packages/api-routes/src/openapi.ts` (route added, schema changed, response shape updated).
- After any change in `packages/api-routes/src/openapi-schemas.ts` (schema registry edit).
- The `gen:check` script in CI catches forgotten regens — `pnpm gen` locally to fix.
## See Also
- `packages/api-routes/src/openapi.ts` — spec source
- `packages/api-routes/src/openapi-schemas.ts` — Zod schema registry
- `packages/canonry/src/client.ts` — primary consumer (CLI + MCP)
- `apps/web/src/api.ts` — web consumer