From 74ca3100f7ec9d31fff5a09053e15bf213a5fc28 Mon Sep 17 00:00:00 2001 From: Mathieu Picciolli Date: Mon, 10 Aug 2026 08:17:28 -0400 Subject: [PATCH 1/3] chore: point metadata at the PCMStack/converter repository The repository moved to the PCMStack organization and was renamed to "converter". Update the repository URL, author, CI badge and sample links accordingly. Also document the CDB / database / save terminology in AGENTS.md and realign two README tables. Co-Authored-By: Claude Opus 5 --- AGENTS.md | 20 ++++++++++++++++++++ README.md | 18 +++++++++--------- package.json | 4 ++-- samples/browser/index.html | 4 ++-- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index aafe4a0..a4f55ae 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,6 +11,26 @@ This package converts Pro Cycling Manager CDB binary database files to and from - Low-level binary format handling lives in [src/reader.ts](src/reader.ts), [src/writer.ts](src/writer.ts), [src/types.ts](src/types.ts), and [src/tableMetadata.ts](src/tableMetadata.ts). - Compression helpers live in [src/compression.ts](src/compression.ts). +### Terminology + +Three words, deliberately not interchangeable: + +- **CDB** — Cyanide's binary database format, the `.cdb` file. This is what the + library reads and writes, and it is always handled as a *buffer*, never a path: + the public API takes `cdbBuffer` / returns `Uint8Array`, and only the CLI in + [src/cli.ts](src/cli.ts) ever touches the filesystem. The format internals live + in [src/reader.ts](src/reader.ts), [src/writer.ts](src/writer.ts), + [src/compression.ts](src/compression.ts) and [src/tableMetadata.ts](src/tableMetadata.ts). +- **database** — on its own, always the *SQLite* side: a `sql.js` `Database` + instance (aliased `SqlDatabase`) or the `.sqlite` file it exports to. Never use + it bare for a `.cdb`; say "CDB" or "CDB database" when that is what you mean. +- **save** — a `.cdb` the *game itself wrote* as the player played, as opposed to + an official release or a community update. Nothing in the conversion path cares + about the difference, so this word belongs only where the provenance is the + actual point: the reverse-engineering notes in + [src/keyInference.ts](src/keyInference.ts) and [src/tableMetadata.ts](src/tableMetadata.ts) + ("observed in real saves"). Do not use it as a generic name for the input file. + ## Commands - Install: `npm install` diff --git a/README.md b/README.md index 94fb2ca..4095913 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # cdb-converter [![npm version](https://img.shields.io/npm/v/cdb-converter.svg)](https://www.npmjs.com/package/cdb-converter) -[![CI](https://github.com/mpicciolli/cdb-converter/actions/workflows/ci.yml/badge.svg)](https://github.com/mpicciolli/cdb-converter/actions/workflows/ci.yml) +[![CI](https://github.com/PCMStack/converter/actions/workflows/ci.yml/badge.svg)](https://github.com/PCMStack/converter/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/npm/l/cdb-converter.svg)](./LICENSE) [![Node.js](https://img.shields.io/node/v/cdb-converter.svg)](https://nodejs.org) @@ -83,10 +83,10 @@ npx cdb-converter --version | `.cdb` | CDB → SQLite | `.sqlite` | | `.sqlite` / `.db` | SQLite → CDB | `.cdb` | -| Option | Effect | -| ------------------- | -------------------------------------------------------------------------------------------------- | +| Option | Effect | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------- | | `-n`, `--normalize` | (CDB → SQLite only) reconstruct PK/FK constraints from PCM naming conventions. See [Normalized schema](#normalized-schema). | -| `--index-fk` | Implies `--normalize`; also indexes every FK column for faster JOINs (roughly doubles output size). | +| `--index-fk` | Implies `--normalize`; also indexes every FK column for faster JOINs (roughly doubles output size). | ## Library usage @@ -269,11 +269,11 @@ A full `cdb → sqlite → cdb` round-trip on a real ~60k-row database stays wel Normalization is opt-in and costs only what you ask for (measured against the default conversion, ~60k rows): -| Mode | Conversion time | Output size | -| --------------------------------------------- | --------------- | ----------- | -| Default (flat) | baseline | baseline | -| `normalize` | +~10% | +~40% | -| `normalize` + `indexForeignKeys` | +~40% | +~130% | +| Mode | Conversion time | Output size | +| -------------------------------- | --------------- | ----------- | +| Default (flat) | baseline | baseline | +| `normalize` | +~10% | +~40% | +| `normalize` + `indexForeignKeys` | +~40% | +~130% | See **[bench/README.md](bench/README.md)** for the full per-fixture numbers, the bundle breakdown, and how to reproduce them (`npm run bench`). diff --git a/package.json b/package.json index ac7409b..3b93306 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,10 @@ "version": "0.3.0", "description": "Convert Pro Cycling Manager CDB files to/from SQLite and other formats. TypeScript library with zero configuration.", "license": "MIT", - "author": "mpicciolli", + "author": "PCMStack", "repository": { "type": "git", - "url": "https://github.com/mpicciolli/cdb-converter" + "url": "https://github.com/PCMStack/converter" }, "keywords": [ "cdb", diff --git a/samples/browser/index.html b/samples/browser/index.html index aa679a0..b201cf7 100644 --- a/samples/browser/index.html +++ b/samples/browser/index.html @@ -101,8 +101,8 @@

cdb-converter

From 41487bdb329b898812fb9deb927b880df6f91d70 Mon Sep 17 00:00:00 2001 From: Mathieu Picciolli Date: Mon, 10 Aug 2026 08:19:33 -0400 Subject: [PATCH 2/3] docs(demo): say database, not save, and name PCMStack A .cdb is a database whatever its provenance: career save, official Cyanide release or community update. "Save" only describes a .cdb the game itself wrote into an edition's Cloud/ folder, so it never belongs in copy about the converter, which accepts any .cdb. Also states explicitly that the conversion runs client-side. Co-Authored-By: Claude Opus 5 --- README.md | 24 ++++++++++++------------ samples/browser/index.html | 9 +++++++-- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 4095913..584af51 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Convert **Pro Cycling Manager CDB** database files to and from SQLite, straight from the command line or your own code. Lightweight, isomorphic (Node.js **and** the browser), and zero-configuration. -The conversion is **lossless**: a full `cdb → sqlite → cdb` round-trip preserves every table, column, data type, and flag — so you can edit a save in any SQLite tool and load it back into the game. Optionally, it can reconstruct the save's relationships as real `PRIMARY KEY` / `FOREIGN KEY` constraints, turning the export into a normalized database you can explore with JOINs and ER-diagram tools. +The conversion is **lossless**: a full `cdb → sqlite → cdb` round-trip preserves every table, column, data type, and flag — so you can edit a database in any SQLite tool and load it back into the game. Optionally, it can reconstruct the database relationships as real `PRIMARY KEY` / `FOREIGN KEY` constraints, turning the export into a normalized database you can explore with JOINs and ER-diagram tools. > [!NOTE] > Based on [agfor/pcmdbedit](https://github.com/agfor/pcmdbedit/) — many thanks to agfor for the foundational work. @@ -53,7 +53,7 @@ npm install cdb-converter The fastest way to try it is the CLI: ```bash -npx cdb-converter save.cdb +npx cdb-converter database.cdb ``` ## Command line @@ -61,17 +61,17 @@ npx cdb-converter save.cdb The package ships a `cdb-converter` command. The conversion direction is auto-detected from the input file extension. ```bash -# CDB → SQLite (default output: save.sqlite) -npx cdb-converter save.cdb +# CDB → SQLite (default output: database.sqlite) +npx cdb-converter database.cdb -# SQLite → CDB (default output: save.cdb) -npx cdb-converter save.sqlite +# SQLite → CDB (default output: database.cdb) +npx cdb-converter database.sqlite # Provide an explicit output path (directories are created as needed) -npx cdb-converter save.cdb data/save.sqlite +npx cdb-converter database.cdb data/database.sqlite # Reconstruct PRIMARY KEY / FOREIGN KEY constraints (CDB → SQLite only) -npx cdb-converter save.cdb save.sqlite --normalize +npx cdb-converter database.cdb database.sqlite --normalize # Help / version npx cdb-converter --help @@ -100,7 +100,7 @@ import { cdbToSql } from "cdb-converter"; const SQL = await initSqlJs(); // Read and convert a CDB file -const cdbBuffer = fs.readFileSync("save.cdb"); +const cdbBuffer = fs.readFileSync("database.cdb"); const db = cdbToSql(cdbBuffer, SQL); // Query it like any SQLite database @@ -108,7 +108,7 @@ const result = db.exec("SELECT * FROM Teams LIMIT 5"); console.log(result[0].values); // Export to a .sqlite file -fs.writeFileSync("save.sqlite", db.export()); +fs.writeFileSync("database.sqlite", db.export()); ``` > [!IMPORTANT] @@ -154,11 +154,11 @@ import { sqlToCdb } from "cdb-converter"; const SQL = await initSqlJs(); // Load a SQLite database and convert back to CDB -const sqliteBuffer = fs.readFileSync("save.sqlite"); +const sqliteBuffer = fs.readFileSync("database.sqlite"); const db = new SQL.Database(sqliteBuffer); const cdbBuffer = sqlToCdb(db); // automatically compressed -fs.writeFileSync("save.cdb", Buffer.from(cdbBuffer)); +fs.writeFileSync("database.cdb", Buffer.from(cdbBuffer)); ``` ### Compression diff --git a/samples/browser/index.html b/samples/browser/index.html index b201cf7..0e8fd38 100644 --- a/samples/browser/index.html +++ b/samples/browser/index.html @@ -3,7 +3,7 @@ - cdb-converter + cdb-converter: PCMStack