npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@poe2-toolkit/ggpk

v0.3.0

Published

Access layer for Path of Exile 2's official GGPK / patch server: fetches and decodes game tables and raw files, and decodes GGPK image and stat-description formats. The shared base every PoE2 data extractor builds on.

Downloads

534

Readme

@poe2-toolkit/ggpk

npm types included ESM only license: MIT

Shared access layer for Path of Exile 2's official GGPK / patch server. It fetches and decodes game tables and raw files, decodes the GGPK image and stat-description formats, and hands the result back to you as plain data.

This is the foundation every PoE2 data extractor in this toolkit builds on. It is the only package that talks to the network, so the extractors stay agnostic to where their bytes come from.

Code only. This package ships no game data and no art. It reads from the official patch server (or your own game files) at run time and returns the decoded result; it never bundles or redistributes anything from the game.

Install

npm install @poe2-toolkit/ggpk

Node 18+. ESM only. TypeScript types are included.

The contract

Everything is built around one small interface, the boundary an extractor depends on and the only thing that knows where bytes come from:

interface GgpkSource {
  /** Decoded rows of a GGPK data table, e.g. "PassiveSkills", in table order. */
  table(name: string): Promise<TableRow[]>;
  /** Raw bytes of a GGPK file by logical path, or null if it cannot be served. */
  file(path: string): Promise<Uint8Array | null>;
}

An extractor asks a GgpkSource for tables and files. Whether those come from the patch CDN, a local game install, or a pre-extracted cache is the source's concern, never the extractor's. The interface is dependency-free on purpose: an extractor that imports only the type pulls in none of the acquisition stack.

The default source: the patch CDN

createCdnSource is the batteries-included GgpkSource. It serves tables from a directory of pathofexile-dat-decoded JSON files and pulls raw files and sprites from the patch CDN on demand, caching them on disk.

import { createCdnSource } from '@poe2-toolkit/ggpk';

const source = await createCdnSource({
  patch: '4.5.3.1.7',          // GGPK patch version
  tablesDir: './tables/English', // pathofexile-dat's decoded <Name>.json output
  cacheDir: './.cache',          // where downloaded bundles are cached
});

const characters = await source.table('Characters');
const psg = await source.file('metadata/passiveskillgraph.psg');

Producing the decoded tables is a one-time step with pathofexile-dat's own CLI; point tablesDir at its output. Connecting to the network is deferred to the first file or sprite request, so table reads only touch local disk.

cdnHost is optional and defaults to the PoE2 patch server (https://patch-poe2.poecdn.com); override it to point at a mirror. The bundle cache lives in a <patch>/ subdirectory of cacheDir.

On top of GgpkSource, the CDN source adds image fetching for art-heavy extraction:

interface GgpkImageSource {
  /** Decode a DDS by its GGPK path (BC1/BC2/BC3/BC7), cached. */
  dds(path: string): Promise<RgbaImage | null>;
  /** Resolve a UIImages logical name to its backing DDS and rect. */
  resolveSprite(name: string): Promise<SpriteRef | null>;
  /** A UIImages sprite decoded and cropped to its rect. */
  uiSprite(name: string): Promise<RgbaImage | null>;
}

Shared decoders

The package also exports the format decoders every domain reuses, so they live in one place rather than being reimplemented per extractor:

| Export | What it does | | --- | --- | | decodeDds(bytes) | Decode a DDS buffer (BC1/BC2/BC3/BC7) to straight RGBA8. | | encodePng(width, height, rgba) | Encode RGBA8 to a PNG buffer (Node zlib, no native deps). | | decodePng(bytes) | Decode an 8-bit RGBA/RGB PNG to RGBA8. | | buildStatIndex(csd) | Parse a stat_descriptions.csd (UTF-16 text) into a per-stat index. | | renderBlock(index, statIds, values) | Render numeric (stat, value) pairs into human-readable lines. |

buildStatIndex returns a StatIndex; pass it to renderBlock along with parallel statIds/values arrays. renderBlock returns a RenderedBlock with lines (the rendered text) and unresolved (any stat ids with no matching block). RgbaImage ({ width, height, rgba }) is the shape returned by every image decoder. All of these types are exported.

All of it is pure TypeScript with no native dependencies, which keeps extraction portable across machines and CI.

A note on pathofexile-dat

The bundle loader and sprite-layout parser this package relies on live in pathofexile-dat's internal dist/ paths. The exact internal layout can change between major versions, so pathofexile-dat is pinned as a dependency. See NOTICE for attribution.

License

MIT. See LICENSE. Not affiliated with Grinding Gear Games; see NOTICE.