diff --git a/AGENTS.md b/AGENTS.md index aafe4a0..5bf3397 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -56,4 +56,3 @@ This package converts Pro Cycling Manager CDB binary database files to and from ## References - API usage and examples: [README.md](README.md) -- Build/export behavior note: [build-notes.md](memories/repo/build-notes.md) diff --git a/README.md b/README.md index 94fb2ca..96c3348 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,8 @@ The conversion is **lossless**: a full `cdb → sqlite → cdb` round-trip prese - **CLI included** — convert files without writing any code; direction is auto-detected. - **Lossless round-trip** — table flags, column order, and data types survive an export/reopen cycle. - **Optional relational schema** — reconstruct `PRIMARY KEY` / `FOREIGN KEY` constraints for JOINs and ER diagrams, without breaking the round-trip. -- **Isomorphic** — runs in Node.js and in the browser via [sql.js](https://github.com/sql-js/sql.js). -- **Lightweight** — the library's own code is ~28 kB, with only `pako` and `sql.js` as dependencies. +- **Node-first, browser-capable** — the CLI and default `better-sqlite3` engine target Node.js; an optional `sql.js` (WASM) engine covers the browser. +- **Lightweight** — the library's own code is ~28 kB. `better-sqlite3` is a hard dependency; the `sql.js` (WASM) engine is optional and installed separately. - **TypeScript-first** — native type definitions and full IDE support. - **Tree-shakeable** — pure functions, no side effects, ESM + CommonJS builds. @@ -48,7 +48,7 @@ npm install cdb-converter ``` > [!NOTE] -> Requires **Node.js 22 or newer**. In the browser, `sql.js` loads its WebAssembly runtime on demand. +> Requires **Node.js 22 or newer**. The CLI and the default `better-sqlite3` engine are ready to use out of the box — `better-sqlite3` is installed automatically as a dependency. For the browser, install `sql.js` instead — it loads its WebAssembly runtime on demand. The fastest way to try it is the CLI: @@ -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 @@ -94,14 +94,12 @@ npx cdb-converter --version ```typescript import fs from "node:fs"; -import initSqlJs from "sql.js"; +import { betterSqlite3Engine } from "cdb-converter/engines/better-sqlite3"; import { cdbToSql } from "cdb-converter"; -const SQL = await initSqlJs(); - // Read and convert a CDB file const cdbBuffer = fs.readFileSync("save.cdb"); -const db = cdbToSql(cdbBuffer, SQL); +const db = cdbToSql(cdbBuffer, betterSqlite3Engine); // Query it like any SQLite database const result = db.exec("SELECT * FROM Teams LIMIT 5"); @@ -112,14 +110,14 @@ fs.writeFileSync("save.sqlite", db.export()); ``` > [!IMPORTANT] -> You must pass the initialized `sql.js` module returned by `initSqlJs()`. This library does not initialize `sql.js` for you: that setup is asynchronous and environment-specific (the caller decides how the wasm file is loaded in Node.js or the browser). +> You must pass a `SqlEngine`. `cdb-converter/engines/better-sqlite3` (requires the `better-sqlite3` package) is the default for Node.js; `cdb-converter/engines/sql-js` (requires the `sql.js` package) works in the browser but needs an `await` to initialize its WASM runtime. See [Using a different SQLite engine](#using-a-different-sqlite-engine). ### Normalized schema By default the SQLite output is a flat mirror of the CDB tables, with no relational constraints. Pass `{ normalize: true }` to reconstruct `PRIMARY KEY` and `FOREIGN KEY` constraints from the PCM naming conventions (`ID{table}` identity columns and `fkID{target}` references), turning the export into a proper relational database — ready for JOINs, entity-relationship diagrams, and schema introspection tools. ```typescript -const db = cdbToSql(cdbBuffer, SQL, { normalize: true }); +const db = cdbToSql(cdbBuffer, betterSqlite3Engine, { normalize: true }); // Relationships are now navigable: db.exec(` @@ -138,24 +136,25 @@ Notes: ```typescript // Lean: constraints only (~+40% size) -cdbToSql(cdbBuffer, SQL, { normalize: true }); +cdbToSql(cdbBuffer, betterSqlite3Engine, { normalize: true }); // Heavier, faster JOINs: also index FK columns (~2x size) -cdbToSql(cdbBuffer, SQL, { normalize: true, indexForeignKeys: true }); +cdbToSql(cdbBuffer, betterSqlite3Engine, { + normalize: true, + indexForeignKeys: true, +}); ``` ### SQLite to CDB ```typescript import fs from "node:fs"; -import initSqlJs from "sql.js"; +import { betterSqlite3Engine } from "cdb-converter/engines/better-sqlite3"; 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 db = new SQL.Database(sqliteBuffer); +const db = new betterSqlite3Engine.Database(sqliteBuffer); const cdbBuffer = sqlToCdb(db); // automatically compressed fs.writeFileSync("save.cdb", Buffer.from(cdbBuffer)); @@ -178,8 +177,9 @@ const decompressed = decompressCdb(compressed); // accepts compressed or raw inp