Skip to content

Changelog

All notable changes to @hosaka-fm/crate are documented here. The format follows Keep a Changelog, and this project adheres to Semantic Versioning.

  • Re-vendored the live spec: /api/v2 2.34.0 → 2.47.0 (thirteen contract versions). Regenerated types now cover: the structured track resolver (POST /tracks/resolve, GET /track), semantics/dictionary.json, the market_vs_flow_divergence + artist_press_mentions registry surfaces (44 rows; the latter with a mixed-order keyset), and the artist dossier’s season of cluster-native facets — authorship, lineage, one-call profile (listen_flow/arrival/aura/ dj_champion/radio_play), facts names+portrait, visibility corrected badge cut, web_presence DSP links, cluster-native rights/credits entries, and journalism.signals.citedMentions[] (cited articles). See the crate CHANGELOG 2.35.0–2.47.0 for contract details.

Stable from 1.0.0. The typed surface is regenerated from spec/openapi.json, so type changes track the live crate API contract. Breaking API changes bump the major.

  • Regenerated types against /api/v2 2.34.0 — a catch-up across sixteen spec minors (2.18.0 → 2.34.0). New typed surface:
    • GET /api/v2/tracks — title-first track discovery, with ?fuzzy=true (substring), ?source=mb|bandcamp|all (the new Bandcamp track corpus reaches underground/self-released titles the MB-linked catalogue can’t), and a per-result sources provenance array.
    • GET /api/v2/resolve gains ?isrc=<code> and ?artist=&track= locator arms (recording → primary-artist cluster), plus the name-mint fallback so off-master artists resolve to a cluster instead of null (typed via the existing resolve response).
    • GET /api/v2/semantics/dictionary — the fleet substrate dictionary.
    • Artist-dossier facets authorship, lineage, facts + visibility, debut, and marketplace.
    • GET /api/v2/aura gains the about legibility block.
    • Surface registry 35 → 42 (tranches 7–10): the GET /api/v2/surface/{name} enum + response union gain the new surfaces.
  • Operation set grows accordingly (now 26 paths). Additive — no breaking changes to existing types.
  • Regenerated types against /api/v2 2.18.0 — registry tranche-6: sync.placement_claim_by_cluster_v1 (claim-grain screen-placement drill-in; first sync surface). Registry now 35 surfaces; the GET /api/v2/surface/{name} enum + response union gain the surface. Operation set unchanged.
  • Regenerated types against /api/v2 2.17.0 — the artist rights facet gains a cluster-anchored ledger rights-registration dimension (registeredWorks / worksWithRegisteredIswc / distinctCowriters / cowritersWithMbid + a SoundCloud leg; counts only). Additive on ArtistDossierContract.rights; operation set unchanged.
  • Regenerated types against /api/v2 2.16.0 — registry tranche-5 adds mirror.cluster_authority_ids_v1 (ISNI/VIAF/GND/LC/Discogs authority-ID crosswalk); 34 surfaces. First text[]-typed response fields.
  • Regenerated types against /api/v2 2.15.0 — registry tranche-4 adds public.spine_artist_name_published_view (ridden) and seen.artist_signal_known_since (the detection-time ledger); 33 surfaces total. Accessor API unchanged.
  • Regenerated types against crate /api/v2 2.14.0 — registry tranche-3 adds archive_api_v1.artist_mention_daily (ridden per-source dated mention aggregate), bringing the generic surface registry to 31 surfaces. Accessor API unchanged (crate.surface(name, …)).
  • Regenerated types against /api/v2 2.13.0 — registry tranche-2 adds 24 seen surfaces (30 total), the pe-norm-v1-label keyspace, and numeric/uuid field types. SurfaceRows_* response unions now cover every accepted surface.
  • crate.surfaces()GET /api/v2/surface (the registry index) and crate.surface(name, { cluster, after, limit })GET /api/v2/surface/{name} — one generic accessor for the whole cluster-keyed read layer, keyset-paginated via the opaque after cursor.
  • Regenerated against /api/v2 2.12.0 (registry go-live).
  • Regenerated against /api/v2 2.11.0 — MB Phase-3 scarcity + credits + placements facets.
  • Corrected the VERSION constant, which 1.7.0 had shipped as 1.6.0 (an unprotected red merge). The contract.test.ts VERSION === package.json gate (ADX-7) now guards this.
  • Regenerated against /api/v2 2.9.0 — typed connections.related[] with clusterId, plus the geography facet.
  • crate.artistMaster() — the master grain, cluster-attached.
  • Regenerated against /api/v2 2.8.0.
  • crate.artists() — the genre-browse discovery grid.
  • Regenerated against /api/v2 2.7.0.
  • Regenerated against /api/v2 2.6.0 — rights-readiness facet + keyless education-preview types.
  • crate.aura() — per-artist convergence aura.
  • Regenerated against /api/v2 2.4.1 (required-field tightening, artwork dimensions). Migration guide corrected.
  • crate.artistBandcampRelease() — the cluster-attached Bandcamp release grain.
  • Regenerated against /api/v2 2.3.0.
  • Regenerated against /api/v2 2.2.0search gains artist_cluster_id, resolve gains candidates[], and _links are declared across dossiers.

First stable release. Targets crate’s cluster-first /api/v2 (OpenAPI 2.0.0). The catalogue is now keyed on cluster_id — the artist is the root, and master/bandcamp are dimensions of the artist dossier rather than top-level resources. This is a breaking change from the 0.x line (which targeted /api/v1); see Migrating from v1 in the README.

  • crate.label(key, opts?)LabelDossierContract. Labels are first-class in v2.
  • ?fields= sparse fieldsets on artist() and dossier.artist() via { fields: [...] } — the response is default-rich (one round-trip); pass fields only to trim it. An unknown field name returns 400 invalid_fields (added to CRATE_ERROR_CODES).
  • RFC 8594 deprecation surfacing: Deprecation/Sunset response headers emit a one-time console.warn. The transport follows 308 redirects preserving method + body (the two POST beacon endpoints survive a redirect).
  • World-class documentation suite: README (cluster-first hero, recipes, migration table), a docs/ guide set, runnable examples/, and agent-first entrypoints (AGENTS.md, llms.txt). The README “Client surface” table + the interactive explorer are generated from method TSDoc (npm run docs:build); the explorer’s “Key concepts” come from the spec’s x-concepts — all drift-guarded in CI.
  • npm package metadata: keywords, homepage, bugs; CHANGELOG.md ships in the tarball.
  • Base path is now /api/v2 (was /api/v1). crate.index() (keyless) reports version: v2.
  • The artist dossier (ArtistDossierContract) is the cluster-first hub: it carries discography (a pointer index of masters: discogs_master_id + representative_name + _links.master), bandcamp_emergence, and bandcamp_tastemaker dimensions. LabelDossierContract is first-class.
  • Attribution is Hosaka FM; publishing target is the public npm registry under @hosaka-fm.
  • crate.master() / crate.masters() — masters have no standalone v2 resource. The artist dossier’s discography is a pointer index, not per-master detail; per-master enrichment, tracklists, and batch master lookups are genuine removals (their _links.master point back to the frozen v1 surface).
  • crate.bandcamp.* (release, releases) and the BandcampRelease* types — Bandcamp is now the bandcamp_emergence / bandcamp_tastemaker dimensions of the artist dossier.
  • crate.wayfind / crate.usage() — no v2 equivalent.
  • Pagination (crate.search().pages(), bulkAll, the pagination export, async iterators) — removed with the bulk Bandcamp surface; crate.search() returns a single page.
  • crate.bandcamp.release({ item | url })BandcampRelease | null (the honest gap, HTTP 200 present: false, returns null — not an error) and crate.bandcamp.releases({ clusterId })BandcampReleaseSummary[].
  • New exported types: BandcampRelease, BandcampReleaseSummary, BandcampReleaseResponse, ArtworkItem, and a BandcampTrack alias.
  • Regenerated types against the live spec: resolve() locators now spans eight platform arrays; dossiers carry link-only artwork (ArtworkItem[]). bandcamp_item_id / cluster_id are opaque strings — pass through, never numericize.
  • Key-first. Every data endpoint now requires an apiKey (sent as X-API-Key); only crate.index() is keyless. Data methods throw CrateValidationError('api_key_required') before any network call. Regenerated against crate API spec 1.1.0.
  • Initial release: typed client over crate’s public API with typed methods, automatic retries (full-jitter backoff honouring Retry-After), async-iterator pagination, teaching errors as typed exceptions (CrateError + subclasses, .kind/.code/.hint/.next, JSON-safe), the CRATE_RESOURCES surface map and CRATE_ERROR_REGISTRY error dictionary, dual ESM + CJS, and zero runtime dependencies.