@cat-factory/sdk
v0.63.0
Published
TypeScript/JavaScript client for the cat-factory public API (/api/v1): typed models and resource clients generated from the published OpenAPI spec, over a hand-written fetch transport with bearer auth, bounded retries, keyset auto-pagination and an SSE re
Maintainers
Readme
@cat-factory/sdk
TypeScript / JavaScript client for the cat-factory public API (/api/v1).
npm install @cat-factory/sdkNode 20+. No dependencies: the transport is fetch.
import { CatFactoryClient, CatFactoryNotFoundError } from '@cat-factory/sdk'
const client = new CatFactoryClient({
baseUrl: 'https://cat-factory.example.com',
apiKey: process.env.CAT_FACTORY_API_KEY!,
})
const { services } = await client.services.list()
const task = await client.tasks.create(services[0].serviceId, {
title: 'Add a health check endpoint',
taskType: 'feature',
})
await client.tasks.start(task.taskId, {})Resource clients
jobs, services, tasks, pipelines, notifications, webhook, usage, decisions,
debug:
one per tag of the published OpenAPI surface. A workspace-scoped call acts on the key's only workspace, or on workspaceId for a key that reaches several.
Watching a run
const stream = await client.tasks.stream(task.taskId)
try {
for await (const event of stream) {
if (event.event === 'decision') {
// The run PARKED on a human decision and waits indefinitely. Answer it through
// `client.decisions` (needs a `decide`-scope key) or free it with `tasks.stop`.
const { decisions } = await client.decisions.list(runId)
}
if (event.event === 'done' || event.event === 'error') break
// `timeout` means the deployment's connection cap was reached, NOT that the run finished.
}
} finally {
await stream.close()
}Paging
Every bounded list has an auto-paging companion that follows nextCursor for you:
for await (const task of client.tasks.listByServiceAll(serviceId)) {
console.log(task.taskId)
}Errors
The exception CLASS comes from the HTTP status; code carries the specific cause and is a plain
string, because this surface adds new codes without a major version.
try {
await client.tasks.get(taskId)
} catch (error) {
if (error instanceof CatFactoryNotFoundError) return null
if (error instanceof CatFactoryForbiddenError && error.code === 'insufficient_scope') {
throw new Error('this key needs a higher scope')
}
throw error
}Classes: CatFactoryValidationError (400/422), …Unauthorized (401), …Forbidden (403),
…NotFound (404), …Conflict (409), …CredentialRequired (428), …RateLimited (429),
…ServerError (5xx), plus …ConnectionError, …TimeoutError and …DecodeError. All extend
CatFactoryError. Every API error carries status, code, details, issues and the
requestId to quote when reporting a fault.
A CatFactoryConnectionError states what actually failed rather than asserting the deployment was
unreachable, and says what this client had already seen from the origin:
cat-factory SDK: POST /api/v1/tasks failed: https://cat-factory.example.com reset the connection
before answering. This client had answered 9 calls against https://cat-factory.example.com, the
last 0.2s ago. (read ECONNRESET)A reset after nine answered calls is a deployment that restarted; a refusal with nothing answered
yet is an address with nothing behind it, and the two send you to completely different places. The
runtime's own cause chain is kept verbatim at the end of the message and on cause.
Options
new CatFactoryClient({
baseUrl,
apiKey,
timeoutMs: 30_000, // 0 disables
maxRetries: 2, // idempotent requests only - a POST is never auto-retried
headers: {},
userAgent: 'my-integration/1.2.3',
fetch: myFetch, // a proxy agent, or a test double
})Local development and mocks
The base URL takes any origin (http://localhost:8787, a fixture server, a mock) and no scheme
validation is applied. Each client also accepts a custom transport, so you can intercept in-process
instead. See the SDK guide.
Notes
src/*.generated.tsare generated fromdocs/openapi.json; see../README.md.- The sources are erasable-only TypeScript (no enums, namespaces or parameter properties), so
they run under Node's type stripping and
erasableSyntaxOnlybuilds. - API reference:
backend/docs/public-api.md.
