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

@manacost-labs/deckstrings

v1.0.0

Published

Production-ready Hearthstone deckstring codec for Node.js and browsers

Readme

Manacost Labs Hearthstone Deckstrings

CI CodeQL npm PyPI NuGet Packagist License: ISC

A dependency-free Hearthstone deckstring backend library for JavaScript, TypeScript, PHP, Python, and .NET. All four implementations share one public contract and the same golden fixtures, including sideboards and full clipboard exports.

Release status: 1.0.0 is a verified release candidate. The synchronized stable packages are not public in all four registries yet, so the install commands below become the supported production path only after the public v1.0.0 release is published.

Install

| Ecosystem | Package | Supported runtime | | --- | --- | --- | | npm | npm install @manacost-labs/deckstrings | Node.js 22 or 24+, modern browsers | | Composer | composer require manacost-labs/hearthstone-deckstrings | PHP 8.2–8.5 | | PyPI | python -m pip install manacost-deckstrings | Python 3.10–3.14 | | NuGet | dotnet add package ManacostLabs.Deckstrings | netstandard2.0, .NET 8, .NET 10 |

Package versions advance together. Version 1.0.0 defines the first stable cross-language API.

What the library owns

  • version 1 deckstring encoding and decoding;
  • Wild, Standard, Classic, and Twist formats;
  • heroes, cards, and sideboards;
  • deterministic canonical ordering;
  • structured validation and stable error codes;
  • parsing and formatting complete Hearthstone clipboard exports;
  • defensive limits for untrusted input.

The core does not download card data, make network requests, or decide whether a deck is legal for a patch. Card names and costs can be added at the edge with an optional resolver callback.

Shared model

{
  "format": 1,
  "heroes": [7],
  "cards": [[1, 2], [2, 2], [3, 2], [4, 1]],
  "sideboardCards": [[5, 1, 90749]]
}
  • cards entries are [dbfId, count];
  • sideboardCards entries are [dbfId, count, ownerDbfId];
  • heroes and cards are sorted by DBF ID;
  • sideboard cards are sorted by owner and then DBF ID;
  • duplicate heroes, cards, and sideboard (ownerDbfId, dbfId) pairs are invalid.

The normative model is spec/deck.schema.json, and the wire/error/export contract is documented in spec/README.md.

JavaScript / TypeScript

import {
  FormatType,
  canonicalize,
  decode,
  encode,
  formatExport,
  parseExport,
  validate,
} from "@manacost-labs/deckstrings";

const deck = decode("AAEBAQcBBAMBAgMAAA==");
const result = validate(deck); // { valid, errors }
const canonical = canonicalize(deck);
const deckstring = encode(canonical);
const parsed = parseExport(`### Example\n${deckstring}`);
const text = formatExport(parsed.deck, parsed.metadata);

The npm package includes ESM, CommonJS, browser ESM, UMD, and bundled TypeScript declarations.

PHP

use ManacostLabs\Deckstrings\Deckstrings;

$deck = Deckstrings::decode('AAEBAQcBBAMBAgMAAA==');
$result = Deckstrings::validate($deck);
$deckstring = Deckstrings::encode(Deckstrings::canonicalize($deck));
$parsed = Deckstrings::parseExport("### Example\n{$deckstring}");
$text = Deckstrings::formatExport($parsed['deck'], $parsed['metadata']);

Python

from manacost_deckstrings import (
    canonicalize,
    decode,
    encode,
    format_export,
    parse_export,
    validate,
)

deck = decode("AAEBAQcBBAMBAgMAAA==")
result = validate(deck)
deckstring = encode(canonicalize(deck))
parsed = parse_export(f"### Example\n{deckstring}")
text = format_export(parsed["deck"], parsed["metadata"])

The Python distribution is typed and ships a py.typed marker.

C# / .NET

using ManacostLabs.Deckstrings;

var deck = Deckstrings.Decode("AAEBAQcBBAMBAgMAAA==");
var result = Deckstrings.Validate(deck);
var deckstring = Deckstrings.Encode(Deckstrings.Canonicalize(deck));
var parsed = Deckstrings.ParseExport($"### Example\n{deckstring}");
var text = Deckstrings.FormatExport(parsed.Deck, parsed.Metadata);

NuGet releases include XML documentation, portable PDBs, Source Link metadata, and a separate .snupkg symbol package.

Validation and errors

validate/Validate returns ordinary user-input failures and does not throw:

{
  "valid": false,
  "errors": [
    {
      "code": "invalid_count",
      "path": "cards[0][1]",
      "message": "card count must be a positive integer"
    }
  ]
}

Encoding, decoding, canonicalization, and export parsing raise an idiomatic language exception. Match its stable machine-readable code, not the human-readable message. See docs/API.md for language-specific names and the complete code list.

Card display resolver

formatExport/format_export accepts an optional callback from DBF ID to { name, cost? } (or the native equivalent). The callback may return null for an unknown card. Names must be non-blank single-line strings, and costs must be non-negative integers no larger than 2,147,483,647. The resolver is presentation-only and never changes the encoded deckstring.

Compatibility promise

Every implementation reads fixtures/deckstrings.json, fixtures/api.json, and fixtures/exports.json directly. A behavior change is not accepted until the shared contract and all language jobs agree. Legacy deckstrings without a sideboard marker remain supported; encoders always produce canonical output.

Development

# JavaScript / TypeScript
yarn install --frozen-lockfile --ignore-scripts
npx playwright install chromium
npm run verify

# Shared schemas
uv sync --project packages/python --locked --all-extras
uv run --project packages/python --locked python scripts/validate_fixtures.py
uv run --project packages/python --locked python scripts/check_versions.py

# PHP
composer install --no-scripts --no-plugins
composer check

# Python
uv run --project packages/python --locked pytest packages/python/tests
uv run --project packages/python --locked ruff check packages/python
uv run --project packages/python --locked mypy packages/python/src

# .NET
dotnet test packages/dotnet/tests/ManacostLabs.Deckstrings.Tests/ManacostLabs.Deckstrings.Tests.csproj -c Release

See CONTRIBUTING.md, the release process, the migration guide, and the roadmap.

Credits and license

This is an independent Manacost Labs repository whose complete Git history is derived from and preserves attribution to HearthSim/hearthstone-deckstrings. Manacost Labs maintains the multi-language contract, native backend implementations, packaging, and release automation. Repository migration details are recorded in docs/REPOSITORY_MIGRATION.md.

Licensed under the ISC License.