@hosaka-fm/crate v0.3.0
Official TypeScript client

The crate catalogue, typed end‑to‑end.

A medium-thickness client for crate's cluster-first public music-catalogue API (/api/v2) — artist / label / festival dossiers keyed on the canonical cluster_id, where master and bandcamp are dimensions of the artist dossier. Typed methods, automatic retries, sparse ?fields=, and errors that teach. Built so a human reaches a green result in 60 seconds — and an AI agent recovers from failures using the error object alone.

Key concepts — the catalogue's vocabulary

crate isn't a CRUD API — it's an intelligence layer over the world's music metadata. A few ideas unlock everything else, so learn these first.

Why crate

Typed off the live spec

Every parameter and response is generated from crate's OpenAPI contract — full autocomplete, no any, no hand-written drift.

Resilient by default

Auto-retry on 429/5xx with full-jitter backoff that honours Retry-After, a per-attempt timeout, and a whole-call deadline.

Default-rich, opt-out

One call returns the full dossier; pass { fields } to trim it. Deprecation/Sunset headers are surfaced and 308 redirects are followed for you.

Errors that teach

Typed exceptions carry .kind / .code, a human .hint, and a copy-pasteable .next — and they're JSON-safe.

Agent-native

Forgiving inputs, branch-on-code handling, and a runtime-discoverable surface via index(), CRATE_RESOURCES, CRATE_ERROR_REGISTRY.

Lean

Dual ESM + CJS, zero runtime dependencies, tree-shakeable, types bundled. Node 18+.

Quick start

    

Methods

The full client surface. Filter by namespace or auth tier, search, then select a method for its signature, endpoint, return type, and a copy-paste example.

namespace
auth

Errors

Every failure throws a CrateError subclass. Branch on err.kind (the discriminant) and err.code — never the message. Select a kind for its fields and codes.

HTTP status → kind
StatusBecomesNotes
The canonical catch


      
Type guards
GuardNarrows to

Configuration

Pass options to new Crate(opts); override any retry/timeout knob per call via the final RequestOptions argument (which also accepts an AbortSignal).

Constructor options — CrateOptions
OptionTypeDefaultMeaning
Per-call overrides — RequestOptions

signal?: AbortSignal plus timeout, maxRetries, maxBackoffMs, maxRetryAfterMs, totalDeadlineMs, headers.

The reliability model

Retries fire only on 429 / 500 / 503 / 504 and transport faults, with full-jitter exponential backoff capped at maxBackoffMs, honouring a server Retry-After (clamped by maxRetryAfterMs), and the whole call is bounded by totalDeadlineMs. All read methods are idempotent. Drag the controls to see the worst-case backoff envelope:

Auth tiers

3

crate is key-first. The SDK enforces tiers locally, so a missing credential fails fast with a typed error instead of a confusing runtime 401.

Fail-fast guard

    

Types

The exported types that shape requests and responses. Every one is generated from the OpenAPI spec and bundled with the package (no @types/… needed). Expand for the field shape.

Agent guide

AI agents are a first-class consumer. The SDK is built so an agent succeeds first-try and recovers from any failure using the error object alone — no external docs, no message parsing.

Forgiving inputs

resolve() / artist() take a bare string and infer it: URL → url, discogs:/mbid: → locator, 64-hex → cluster, else → name.

Branch on code, not message

Switch on err.kind then err.code. err.hint says what's wrong; err.next is a corrected call you can run.

Lossless handoff

JSON.stringify(err) preserves the teaching payload (a plain Error{}). It omits .raw and reduces .cause to {name,message}.

Don't double-retry

The SDK already retries 429/5xx with backoff. On a 429 read err.retryAfter / err.rateLimit — don't wrap calls in your own loop.

null is an honest gap

artistOrNull() returns null, and resolve() a null cluster_id (HTTP 200, present:false) when data is absent. Only 4xx/5xx throw.

Opaque ids

cluster_id and discogs_master_id are strings — pass them through verbatim, never numericize.

Discover the surface at runtime

      

// mirrored by examples/agent.ts + AGENTS.md + llms.txt — all type-checked in CI so they can't rot.

Copied