Skip to content
AniLink

文書 · Documentation

AniLink

A typed TypeScript client for the AniList GraphQL and MyAnimeList REST APIs. One class, two isolated provider surfaces, normalized errors, retries, pacing, and a generated operation reference.

One client, two surfaces

Typed from install to response

Construct once with per-provider credentials. Each surface is fully typed — variables in, responses out — and they never share a transport credential.

typescriptexample.ts
import { AniLink } from "anilink-api-wrapper";

// One client, two isolated provider surfaces.
const aniLink = new AniLink({
    anilist: { authToken: process.env.ANILIST_TOKEN },
    mal:     { accessToken: process.env.MAL_TOKEN },
});

// AniList — typed GraphQL, no token needed for public reads.
const anime = await aniLink.anilist.query.media({
    id: 21,
    type: "ANIME",
});
console.log(anime.media?.title?.romaji); // → "One Piece"

// MyAnimeList — typed REST, public fields need no token.
const mal = await aniLink.mal.anime.get(21, {
    fields: ["id", "title", "main_picture"],
});
console.log(mal.title);

Why AniLink

The plumbing, done once

Calling AniList or MAL directly means hand-rolling HTTP, GraphQL documents, OAuth flows, retry logic, and rate-limit handling. AniLink does that once, with types.

  • Typed operations

    Every query, page query, and mutation ships with typed variables and a typed response, generated from the provider schemas. No hand-written GraphQL shapes.

  • Normalized errors

    Provider failures become AniLinkError subclasses with stable code values. Classify failures by code, not by parsing message strings.

  • Resilience built in

    Retries with jittered backoff, optional rate-limit pacing, and an optional circuit breaker — identical behavior on both providers.

  • Provider isolation

    Credentials and transport settings are scoped per provider slot. A MAL token is never sent to AniList, and vice versa.

  • Observability hooks

    onRequestStart, onSuccess, onRetry, and onError fire at every stage of the request lifecycle. Instrument calls without wrapping a single method.

  • Cancellation & timeouts

    Pass an AbortSignal or a per-request timeout and the transport cancels in flight, releases the attempt, and surfaces a typed cancellation error.

Two providers, one client

AniList & MyAnimeList

The two surfaces share a transport layer — timeouts, retries, pacing, the circuit breaker, hooks, error normalization — but never share credentials.

AniList GraphQL MyAnimeList REST
ProtocolGraphQLREST
NamespaceaniLink.anilistaniLink.mal
SurfaceQueries · Page · Mutations · custom()anime.get · user.me
AuthOAuth bearer tokenPKCE OAuth2 access token
Credential slotanilist.authTokenmal.accessToken

The documentation

Where to start reading

The docs are organized as a single reading path. Begin with the start guides, move through the core transport concepts, then branch into provider-specific guides and the generated operation reference.

Ready to build?

Install the package and make your first typed call in under a minute.

AniLink — typed AniList & MyAnimeList client for TypeScript.