bsdata40k-to-json
v1.0.1
Published
Convert BSData BattleScribe XML files (.cat/.gst) to JSON — raw or curated
Maintainers
Readme
bsdata40k-to-json
Convert BSData BattleScribe XML for Warhammer 40,000 into JSON. Turn army list data (factions, units, weapons, abilities, points) from the community-maintained BSData repos into two output formats:
- Raw — Faithful 1:1 XML-to-JSON conversion preserving all BattleScribe elements, attributes, and list-builder logic
- Curated — Clean, game-ready JSON: datasheet stats (M, T, SV, W, LD, OC), ranged/melee weapon profiles, abilities, keywords, transport capacity, leader attachments, enhancements, and points per faction
Built for Warhammer 40,000 (40k) 10th edition data. Use the output for list-building apps, points calculators, roster viewers, or any tool that needs structured 40k game data.
Install
npm install bsdata40k-to-jsonOr install globally for CLI access:
npm install -g bsdata40k-to-jsonCLI Usage
Pass the input directory (BSData repo) and output directory as two arguments:
bsdata40k-to-json ./wh40k-10e ./outputOptions
| Argument / Flag | Description |
|---|---|
| <input-dir> | Directory containing .cat and .gst files (required) |
| <output-dir> | Directory to write JSON output (required) |
| --raw-only | Only produce raw (1:1 XML-to-JSON) output |
| --curated-only | Only produce curated game-data output |
| --help, -h | Show help message |
Development scripts
| Command | Description |
|---|---|
| npm run convert -- <input-dir> <output-dir> | Run both pipelines via tsx |
| npm run convert:raw -- <input-dir> <output-dir> | Raw XML-to-JSON only |
| npm run convert:curated -- <input-dir> <output-dir> | Curated extraction only |
| npm run build | Compile TypeScript to dist/ |
Library Usage
import { convert } from "bsdata40k-to-json";
const result = await convert({
inputDir: "./wh40k-10e",
outputDir: "./output",
curatedOnly: true,
});
console.log(`Converted ${result.factionCount} factions`);Individual extractors are also available:
import {
convertFileToRawJson,
extractGameSystem,
extractCatalogue,
discoverFiles,
} from "bsdata40k-to-json";
const { gstFiles, catFiles } = await discoverFiles("./wh40k-10e");
const rawJson = await convertFileToRawJson(gstFiles[0]);
const gameSystem = extractGameSystem(rawJson);All TypeScript types are exported:
import type {
CuratedFaction,
CuratedUnit,
WeaponProfile,
Enhancement,
CuratedGameSystem,
ConvertOptions,
ConvertResult,
} from "bsdata40k-to-json";Output Structure
<output-dir>/
raw/ # 1:1 XML-to-JSON
game-system.json # Warhammer 40,000.gst (core rules, profile types)
necrons.json # One file per faction catalogue (.cat)
imperium-space-marines.json
...
curated/ # Clean game data
game-system.json # Shared rules (e.g. Blast, Devastating Wounds), profile types, categories
factions/
necrons.json
imperium-space-marines.json
...
index.json # Faction manifest with unit countsWhat’s in the curated output (40k terms)
- Factions — One JSON file per 40k faction (e.g. Necrons, Space Marines, Tyranids), with
name,catalogueName, and all units/enhancements for that army. - Units — Full datasheet-style data: Movement (M), Toughness (T), Save (SV), Wounds (W), Leadership (LD), Objective Control (OC), plus keywords (Infantry, Character, etc.) and faction keywords.
- Weapons — Ranged and melee weapon profiles with Range, Attacks (A), Ballistic Skill (BS) or Weapon Skill (WS), Strength (S), Armour Penetration (AP), Damage (D), and weapon keywords (e.g. Devastating Wounds, Blast).
- Abilities — Named abilities and their rules text (e.g. Master Chronomancer, Oath of Moment).
- Enhancements — Detachment enhancements with name, points cost, and description; optional
detachmentwhen applicable. - Leader attachments — Which units a character can lead (e.g. Orikan the Diviner → Immortals, Necron Warriors).
Curated JSON Format (example: Necrons)
Each faction file contains units with full 40k-style datasheets:
{
"id": "b654-a18a-ea1-3bf2",
"name": "Necrons",
"catalogueName": "Xenos - Necrons",
"units": [
{
"id": "ba86-eaad-5396-fc07",
"name": "Orikan the Diviner",
"points": 80,
"keywords": ["Infantry", "Character", "Epic Hero", "Cryptek"],
"factionKeywords": ["Necrons"],
"stats": { "M": "5\"", "T": "4", "SV": "4+", "W": "4", "LD": "6+", "OC": "1" },
"rangedWeapons": [],
"meleeWeapons": [
{
"name": "Staff of Tomorrow",
"range": "Melee",
"A": "2",
"WS": "3+",
"S": "4",
"AP": "-3",
"D": "D3",
"keywords": ["Devastating Wounds"]
}
],
"abilities": [
{ "name": "Master Chronomancer", "description": "While this model is leading a unit, models in that unit have a 4+ invulnerable save." }
],
"leader": ["Immortals", "Necron Warriors"]
}
],
"enhancements": [
{
"name": "Veil of Darkness",
"points": 20,
"description": "NECRONS model only. Once per battle...",
"detachment": "Awakened Dynasty"
}
]
}Project Structure
src/
cli.ts # CLI entry point (arg parsing)
index.ts # Library entry point (programmatic API + re-exports)
raw-converter.ts # Faithful XML-to-JSON using fast-xml-parser
utils.ts # File discovery, slugification, helpers
curated/
types.ts # TypeScript interfaces for output shapes
extract-game-system.ts # .gst extractor (rules, profile types, categories)
extract-catalogue.ts # .cat extractor (units, weapons, abilities, enhancements)How It Works
- Discovery — Scans the input directory for the 40k game system (
.gst) and faction catalogues (.cat). - Raw conversion — Parses each XML file with
fast-xml-parser, preserving attributes (prefixed with@_) and forcing arrays for repeatable elements. - Curated extraction — Walks the parsed XML tree to extract 40k game data:
- Resolves
entryLinkcross-references (shared units, wargear, weapons) by building an ID lookup map - Recursively collects profiles from nested
selectionEntry,selectionEntryGroup, andentryLinkelements - Deduplicates weapons by name
- Parses leader attachment targets from ability descriptions (e.g. “This model can be attached to…”)
- Separates faction keywords (e.g.
Faction: Necrons) from unit keywords (Infantry, Character, etc.)
- Resolves
Data Source (Warhammer 40,000)
Input files come from the BSData community-maintained Warhammer 40,000 data. For 10th edition use the BSData/wh40k-10e repository:
git clone https://github.com/BSData/wh40k-10e.git
bsdata40k-to-json ./wh40k-10e ./outputThe repo contains the core game system (Warhammer 40,000.gst) and one catalogue (.cat) per faction (Space Marines, Necrons, Tyranids, etc.). Download or clone the repo and pass its path as the first argument.
License
MIT
