Pokenode-ts

website·Indexed 29 days ago

https://pokenode-ts.vercel.app/

A typed TypeScript client for the PokéAPI that provides end-to-end type safety for every endpoint and field. It includes a suite of twelve specialized clients covering Pokémon, moves, items, berries, and more, featuring built-in caching, pagination support, and custom fetch integration.

Tokens
18.2K
Snippets
121
Records
132
Agent score
72%

What's inside Pokenode-ts

  1. Retrieve Location data

    Use these methods to fetch information about specific locations on the map.
    // Get a location by its name
    const locationByName = await api.getLocationByName('viridian-forest');
    
    // Get a location by its ID
    const locationById = await api.getLocationById(1);
    
    // List locations with optional offset and limit
    const locationsList = await api.listLocations(0, 20);
  2. Handle PokéAPI response errors using PokenodeError

    The pokenode-ts client throws a PokenodeError specifically when the PokéAPI returns a non-2xx HTTP status code. This error object contains details about the failed request, including the status code, status text, the requested URL, and the parsed JSON body (if available). Because the PokéAPI does not have a consistent error schema, the body property is typed as unknown and is undefined if the response was not JSON (e.g., a plain text 'Not Found' for 404s).
    import { PokemonClient, PokenodeError } from 'pokenode-ts';
    
    try {
      await new PokemonClient().getPokemonByName('missingno');
    } catch (error) {
      if (PokenodeError.isPokenodeError(error)) {
        console.log(error.status);     // e.g., 404
        console.log(error.statusText); // e.g., "Not Found"
        console.log(error.url);        // "https://pokeapi.co/api/v2/pokemon/missingno"
        console.log(error.body);        // Parsed JSON or undefined
        console.log(error.message);     // "Request to … failed with status 404"
      }
    }
  3. Initialize and use the CurrencyClient to fetch currency data

    The CurrencyClient provides methods to retrieve details about the currencies used in the Pokémon universe (e.g., Pokémon Dollars, Battle Points). You can fetch a specific currency using its name or ID.
    import { CurrencyClient } from 'pokenode-ts';
    
    const api = new CurrencyClient();
    
    // Fetch currency by name
    const dollar = await api.getCurrencyByName('poke-dollar');
    console.log(dollar.names[0].name); // "Pokémon Dollar"
  4. Retrieve Region data

    Use these methods to fetch information about Pokémon regions.
    // Get a region by its name
    const regionByName = await api.getRegionByName('kanto');
    
    // Get a region by its ID
    const regionById = await api.getRegionById(1);
    
    // List regions with optional offset and limit
    const regionsList = await api.listRegions(0, 20);
  5. Use MainClient to bundle all PokéAPI clients

    The MainClient bundles all twelve specialized API clients behind a single object. This ensures that all sub-clients share a single transport, meaning they share one cache, one set of ETag validators, and deduplicate simultaneous requests for the same URL.
    import { MainClient } from 'pokenode-ts';
    
    const api = new MainClient();
    
    // Access specialized clients via properties
    const pikachu = await api.pokemon.getPokemonByName('pikachu');
    const cheri = await api.berry.getBerryByName('cheri');
    const surf = await api.move.getMoveByName('surf');
  6. Fetch berry data using BerryClient

    Use the BerryClient to retrieve information about berries, their firmness, and their flavors from the PokéAPI. Note that fields like firmness and item are references containing only a name and url; to retrieve the full resource, pass the url to UtilityClient.getResourceByUrl().
    import { BerryClient } from 'pokenode-ts';
    
    const api = new BerryClient();
    const cheri = await api.getBerryByName('cheri');
    
    console.log(cheri.firmness.name); // "soft"
    console.log(cheri.growth_time); // 3
  7. Initialize and use the LocationClient

    The LocationClient is used to interact with the PokéAPI's locations section, allowing developers to retrieve data about regions, locations, location areas, and Pal Park areas.
    import { LocationClient } from 'pokenode-ts';
    
    const api = new LocationClient();
    const kanto = await api.getRegionByName('kanto');
    console.log(kanto.locations.length); // returns every location in Kanto
  8. Fetch move data using MoveClient

    Use the MoveClient to retrieve detailed information about Pokémon moves. Note that power, accuracy, pp, and damage_class are nullable fields because status moves lack power and some legacy entries lack damage classes. If using strictNullChecks in TypeScript, these must be handled explicitly.
    import { MoveClient } from 'pokenode-ts';
    
    const api = new MoveClient();
    
    const surf = await api.getMoveByName('surf');
    
    console.log(surf.type.name); // "water"
    console.log(surf.power); // base power, or null for a status move
    console.log(surf.damage_class?.name); // "special"
  9. Initialize and use the ContestClient

    The ContestClient is used to interact with the PokéAPI's contests section, allowing developers to retrieve information about contest types and the effects moves have in normal and super contests.
    import { ContestClient } from 'pokenode-ts';
    
    const api = new ContestClient();
    const tough = await api.getContestTypeByName('tough');
    
    console.log(tough.berry_flavor.name); // "bitter"
  10. Find an evolution chain from a Pokémon species

    Because evolution chain IDs differ from Pokémon IDs, you must first retrieve the Pokémon species to get the evolution chain URL, then use the UtilityClient to resolve that URL into an EvolutionChain object.
    import { PokemonClient, EvolutionClient, UtilityClient, type EvolutionChain } from 'pokenode-ts';
    
    const species = await new PokemonClient().getPokemonSpeciesByName('eevee');
    
    // The species carries a URL rather than an id, so follow it directly.
    const chain = await new UtilityClient().getResourceByUrl<EvolutionChain>(
      species.evolution_chain.url,
    );
  11. Resolve resource URLs using getResourceByUrl

    The getResourceByUrl method allows you to follow a PokéAPI resource URL (often found in { name, url } pairs) without needing to know which specific client or method the resource belongs to.

    If you pass the entire resource object (the link), the return type is automatically inferred. If you pass a bare string URL, you must provide a type parameter T because the string itself carries no type information. Note that the type parameter T is unchecked at runtime.

    import { UtilityClient, PokemonClient, type EvolutionChain } from 'pokenode-ts';
    
    const utility = new UtilityClient();
    const species = await new PokemonClient().getPokemonSpeciesByName('eevee');
    
    // 1. Automatic type inference by passing the link object
    const chain = await utility.getResourceByUrl(species.evolution_chain);
    // chain is inferred as EvolutionChain
    
    // 2. Explicit type parameter when passing a bare string URL
    const chainFromUrl = await utility.getResourceByUrl<EvolutionChain>(species.evolution_chain.url);
  12. Configure a proxy agent for Node.js

    Since the global fetch in Node.js ignores dispatchers, you must pair undici's fetch with a ProxyAgent and pass it via the fetch option in PokemonClient for per-client proxy isolation.
    import { PokemonClient } from 'pokenode-ts';
    import { fetch as undiciFetch, ProxyAgent } from 'undici';
    
    const dispatcher = new ProxyAgent('http://corp-proxy:8080');
    
    const api = new PokemonClient({
      fetch: (url, init) => undiciFetch(url, { ...init, dispatcher }),
    });