Library quickstart
@courmap/client answers three questions: which work is this ID, what is this episode in every other numbering, and which work and episode is this release name. It runs locally and gives the same answers in both of its modes. The remote client needs nothing but a network connection, so start there.
Install
Section titled “Install”npm install @courmap/clientWith pnpm, pnpm add @courmap/client may print “Ignored build scripts: better-sqlite3”. It is harmless: better-sqlite3 ships prebuilt binaries, so nothing needs building. To silence it, list better-sqlite3 under ignoredBuiltDependencies in pnpm-workspace.yaml (or under pnpm.ignoredBuiltDependencies in package.json).
Remote: nothing to download
Section titled “Remote: nothing to download”import { createRemoteClient } from '@courmap/client';
const courmap = createRemoteClient(); // https://data.courmap.com/v1/ by default
// Episode 12 of AniList 154587, in TVDB's numbering.const t = await courmap.translate('anilist:154587', 12, ['tvdb_show']);console.log(t.work.id, t.results.tvdb_show); // sousou-no-frieren { id: '424536', season: 1, episode: 12 }
// A release name to a work and episode.const r = await courmap.resolve('[SubsPlease] Spy x Family - 17 (1080p)');console.log(r.status, r.match?.work, r.match?.episode); // ok spy-x-family-part-2 5status is ok only when Courmap is sure. A name that could be several works comes back ambiguous, with match empty and every candidate and its score in candidates; a name that matches nothing comes back unmatched with no candidates. Neither throws, so check status before using match. The library guide has the shapes.
The remote client fetches only the small files a call needs and caches them by data version. In a browser, import from @courmap/client/remote, which has no Node-only code.
Offline: download the dump once
Section titled “Offline: download the dump once”Offline mode reads the weekly SQLite dump, so no call touches the network. Use it for PVRs and any tool that resolves many names. Download and unpack the dump of the latest data release. Its file name carries the version, so ask meta.json for the address (this uses curl and jq):
url=$(curl -sL https://github.com/courmap/courmap/releases/latest/download/meta.json | jq -r .dumps.sqlite.url)curl -sL "$url" | gunzip > courmap.sqliteLibrary: remote vs offline shows how to check the download against SHA256SUMS. Then open it:
import { createOfflineClient } from '@courmap/client';
const courmap = createOfflineClient('courmap.sqlite'); // the file you unpacked
// Which work is AniList 142838?const work = await courmap.lookup('anilist:142838');console.log(work.id, work.titles.romaji); // spy-x-family-part-2 Spy x Family Part 2
// Episode 5 of it, in other numberings.const t = await courmap.translate('anilist:142838', 5, ['anidb', 'tvdb_show', 'absolute']);console.log(t.results.tvdb_show); // { id: '405920', season: 1, episode: 17 }console.log(t.results.absolute); // { sequence: 'spy-x-family-absolute', episode: 17 }
courmap.close();Valid targets
Section titled “Valid targets”The third argument of translate is a list of these names (the Target type):
| Target | You get |
|---|---|
anidb, anilist, mal, kitsu |
The provider’s ID and the episode number in its own numbering. |
tvdb_show, tmdb_show |
The show’s ID, a season and an episode. |
tmdb_movie, imdb |
The ID only; these have no episode numbering. |
absolute |
The absolute sequence’s id and the episode in it, as fansubs number it. |
A target the work has no mapping for comes back under unmapped, not as an error. The library guide lists every call and error, and the API reference has the full types.
This product uses the TMDB API but is not endorsed or certified by TMDB.