UNPKG

poe-js-sdk

Version:

TypeScript SDK for the Path of Exile API

221 lines (166 loc) 7.21 kB
# Path of Exile SDK (TypeScript) Typed client for the official Path of Exile API (PoE1 + limited PoE2) with: - OAuth 2.1 helpers (PKCE, refresh, client credentials for service scopes) - Automatic, header‑driven rate‑limit compliance - Fully typed endpoints (ladders, PvP, stashes, characters, filters, leagues) - Optional, clearly labeled Unofficial Trade API client Server: `https://api.pathofexile.com` This SDK follows the official docs found on https://www.pathofexile.com/developer/docs. > Note: This package was renamed. Former names you might see in older docs or code: > - `poe-api-sdk` > - `poe-sdk` > The current and correct name is `poe-js-sdk`. ## Install Install from GitHub (for SSR): ``` npm install github:viligante8/poe-js-sdk ``` Note: when installing from a Git repo, npm runs the `prepare` script to build `dist/`. If your CI disables lifecycle scripts (e.g. `--ignore-scripts`), SSR may fail to resolve the entry. Ensure `prepare` runs or build manually (`npm run build`). ## Exports - Runtime: `PoEApiClient`, `TradeClient`, helpers (`LadderPager`, `publicStashStream`) - OAuth: `OAuthHelper` - Types: `Profile`, `League`, `Character`, `Item`, `StashTab`, `PvpMatch`, `LeagueAccount`, `Ladder`, `LadderEntry`, `EventLadderEntry`, `PvPLadderTeamEntry`, `ItemFilter`, `PublicStashesResponse`, `CurrencyExchangeResponse`, `RateLimitInfo`, `Realm`, trade types Type definitions are included in `dist/index.d.ts` and re-exported from the entry. You can `import type { ... } from 'poe-js-sdk'` directly. ## Quick Start ```ts import { PoEApiClient } from 'poe-js-sdk'; const client = new PoEApiClient({ userAgent: 'OAuth myapp/1.0.0 (contact: dev@example.com)', accessToken: '<user-or-service-access-token>', }); const profile = await client.getProfile(); console.log(profile.name); ``` ## Authorization (OAuth 2.1) ### Grants - Authorization Code + PKCE (user consent) - Refresh Token - Client Credentials (service scopes, confidential clients only) ```ts import { OAuthHelper } from 'poe-js-sdk'; // 1) PKCE auth URL (public or confidential) const state = crypto.randomUUID(); const pkce = OAuthHelper.generatePKCE(); const url = OAuthHelper.buildAuthUrl({ clientId: process.env.OAUTH_CLIENT_ID!, redirectUri: 'http://127.0.0.1:8080/callback', scopes: ['account:profile'], }, state, pkce); // 2) Exchange code const token = await OAuthHelper.exchangeCodeForToken({ clientId: process.env.OAUTH_CLIENT_ID!, clientSecret: process.env.OAUTH_CLIENT_SECRET, // only for confidential redirectUri: 'http://127.0.0.1:8080/callback', scopes: ['account:profile'], }, '<authorization_code>', pkce.codeVerifier); // 3) Client credentials (service scopes) const svcToken = await OAuthHelper.getClientCredentialsToken({ clientId: process.env.OAUTH_CLIENT_ID!, clientSecret: process.env.OAUTH_CLIENT_SECRET!, scopes: ['service:leagues', 'service:leagues:ladder'], }); ``` Public clients cannot request `service:*` scopes. ### User‑Agent ``` User-Agent: OAuth {clientId}/{version} (contact: {email}) OptionalInfo ``` ### Third‑Party Notice ``` This product isn't affiliated with or endorsed by Grinding Gear Games in any way. ``` ## Official API Coverage ### Account - Profile: `getProfile()` - Item Filters: `getItemFilters()`, `getItemFilter(id)`, `createItemFilter()`, `updateItemFilter()` - Characters: `getCharacters(realm?)`, `getCharacter(name, realm?)` - Stashes (PoE1): `getStashes(league, realm?)`, `getStash(league, stashId, substashId?, realm?)` - League Account (PoE1): `getLeagueAccount(league, realm?)` - Account Leagues (PoE1): `getAccountLeagues(realm?)` - Guild Stashes (PoE1): `getGuildStashes(league, realm?)`, `getGuildStash(league, stashId, substashId?, realm?)` ### Public - Leagues: `getLeagues(realm?)`, `getLeague(id, realm?)` - Ladders (PoE1): - League Ladder: `getLeagueLadder(league, { realm, limit, offset, sort, class })` - Event Ladder: `getLeagueEventLadder(league, { realm, limit, offset })` - PvP Matches (PoE1): `getPvpMatches({ realm, type, season, league })`, `getPvpMatch(id, realm?)`, `getPvpMatchLadder(id, { realm, limit, offset })` - Public Stashes (PoE1): `getPublicStashes({ realm, id })` - Currency Exchange: `getCurrencyExchange(realm?, id?)` ### Typed Responses (examples) - `getLeagueLadder``{ league: League; ladder: Ladder }` - `getLeagueEventLadder``{ league: League; ladder: { total: number; entries: EventLadderEntry[] } }` - `getPvpMatchLadder``{ match: PvpMatch; ladder: { total: number; entries: PvPLadderTeamEntry[] } }` See `src/types/index.ts` for all exported types. ## Rate Limiting (Automatic) The SDK automatically respects server rate limits: - Parses `X-Rate-Limit-*` and `X-Rate-Limit-*-State` headers - If a restriction is active (`*-State` third number > 0), subsequent requests wait - On `429 Too Many Requests`, reads `Retry-After` and delays further requests You can inspect current state: ```ts const info = client.getRateLimitInfo(); // { policy, rules, account, ip, client, accountState, ipState, clientState, retryAfter? } ``` Best practices: - Avoid polling; cache where possible - Handle 429 gracefully - Keep your User-Agent clear and contactable ## Unofficial Trade API `TradeClient` uses the website endpoints and requires a `POESESSID` cookie. ```ts import { TradeClient } from 'poe-js-sdk'; const trade = new TradeClient({ poesessid: process.env.POESESSID!, userAgent: 'OAuth myapp/1.0.0 (contact: dev@example.com)', }); const { search, items } = await trade.searchAndFetch('Standard', { /* query */ } as any, 10, 'pc'); ``` This API is unofficial and may change without notice. ## Examples ```ts // League ladder sorted by class await client.getLeagueLadder('Affliction', { realm: 'pc', sort: 'class', class: 'witch', limit: 50, }); // Characters (PoE2 on console realms) await client.getCharacters('poe2'); // Guild stash (PoE1) await client.getGuildStashes('Standard'); // Ladder pagination helper import { LadderPager } from 'poe-js-sdk'; const pager = new LadderPager(client, 'Affliction', { realm: 'pc', limit: 200 }); await pager.loadFirst(); while (await pager.next()) { // process pager.entries } // Public stash streaming import { publicStashStream } from 'poe-js-sdk'; for await (const chunk of publicStashStream(client, { realm: 'pc', idleWaitMs: 2000 })) { // chunk.stashes ... break; // stop when you want } ``` ## Security - Never embed credentials/secrets in distributed binaries or client code - Keep refresh tokens and client secrets server‑side only - One product per registered application ## User‑Agent Header ``` User-Agent: OAuth {clientId}/{version} (contact: {email}) OptionalInfo ``` ## License MIT ## Testing & Coverage - Run tests: `npm test` - Watch tests: `npm run test:watch` - Coverage report: `npm run test:coverage` ## CI & Releases - GitHub Actions run tests, lint, and type checks on pushes and PRs. - Create a release by pushing a tag `vX.Y.Z` to `main`. The Release workflow will: - run tests/lint/type-check - build `dist/` - create a GitHub Release with autogenerated notes and upload `dist/**` artifacts No npm publish is performed by the release workflow.