dyslibria-converter
dyslibria-converter
Install `dyslibria-converter`, run it from Node.js or the CLI, and understand the runtime expectations before you wire it into your own tools.
What you'll cover
- Published as `dyslibria-converter`
- CLI binary: `dyslibria-convert`
- Targets Node.js 20 or newer
- The same package powers the self-hosted library
Chapter 1 · 5 min read
Package quick start
Install
The package ships a Node.js API together with a small CLI. Install it into any Node 20+ project that needs EPUB inspection or Dyslibria conversion without the rest of the application stack.
Install from npm
terminal · bash
npm install dyslibria-converterYour first conversion
If you do not provide a preset or custom profile, the converter falls back to Dyslibria Default. By default it also returns an in-memory `outputBuffer` as well as the inspection and stats object. If you only want a file written to disk, pass `returnBuffer: false` to skip holding the output in memory.
Minimal Node example
convert-book.ts · ts
import { convertBook } from 'dyslibria-converter';
const result = await convertBook('./books/input.epub', {
outputPath: './books/input.dyslibria.epub',
presetId: 'intense-scaffolding',
});
console.log(result.outputPath);
console.log(result.stats.processedFiles);
console.log(result.inspection.title);What `convertBook` returns
- `inspection`: title, author, warnings, HTML entry list, and cover metadata
- `stats`: processed file count, skipped file count, duration, input bytes, and output bytes
- `outputPath`: present when you provide `outputPath`
- `outputBuffer`: present by default unless `returnBuffer` is set to `false`
Chapter 2 · 8 min read
Node.js API reference
Use file paths, buffers, streams, or custom converter instances depending on the shape of your own application.
- Supports path, buffer, and stream inputs
- `createConverter()` for reusable instances
- Deterministic output is enabled by default
- Safety limits protect archive extraction
Accepted input types
The converter API accepts more than a plain file path. You can pass a string path, a `Buffer`, a `Uint8Array`, a readable stream, or an object wrapper containing a path, buffer, or stream with an optional filename.
That flexibility makes it easy to use in web workers, message consumers, or custom upload flows where the EPUB is already in memory.
Buffer and stream inputs
inputs.ts · ts
import fs from 'node:fs';
import { convertBook } from 'dyslibria-converter';
const bufferResult = await convertBook({
buffer: await fs.promises.readFile('./books/source.epub'),
filename: 'source.epub',
});
const streamResult = await convertBook({
stream: fs.createReadStream('./books/source.epub'),
filename: 'source.epub',
}, {
outputPath: './books/source.dyslibria.epub',
returnBuffer: false,
});Important options
- `outputPath`: copy the finished EPUB to a stable path you choose
- `returnBuffer`: keep or skip the in-memory output buffer
- `presetId`: select a built-in preset such as `intense-scaffolding` (Dyslibria Default) or `dyslibria-balanced`
- `profile` or `profilePath`: pass a full custom profile JSON or a reader-configuration export from the typography lab
- `deterministic`: keep reproducible output packaging enabled
- `dictionary` or `dictionaryPath`: override the word list used by the transform
- `tempRootDir`: choose where temporary workspaces are created
- `maxArchiveEntries` and `maxExtractBytes`: adjust archive-safety limits
Reusable converter instances
If you prefer to hide the static functions behind a reusable object, `createConverter()` exposes the same conversion capability through an instance-style interface. That can be convenient in dependency-injected services or background worker classes.
Using createConverter
converter-service.ts · ts
import { createConverter } from 'dyslibria-converter';
const converter = createConverter();
export async function convertFromQueue(inputPath: string, outputPath: string) {
return converter.convertBook(inputPath, {
outputPath,
returnBuffer: false,
});
}Chapter 3 · 7 min read
Inspection, logging, and error handling
Inspect EPUBs before conversion, stream structured log events into your own observability tooling, and respond to package-specific error classes.
- `inspectBook()` reads metadata without converting
- Structured logger callback with step and level
- Typed error classes for invalid EPUBs and safety failures
- Cover entry information is surfaced during inspection
Use `inspectBook()` when you want metadata first
Inspection is useful when you want to show a title, author, warnings list, or cover entry before deciding whether to run a full conversion. It is also a good fit for validation endpoints and content triage tools.
Inspect an EPUB
inspect-book.ts · ts
import { inspectBook } from 'dyslibria-converter';
const inspection = await inspectBook('./books/source.epub');
console.log(inspection.title);
console.log(inspection.author);
console.log(inspection.coverEntryName);
console.log(inspection.warnings);Structured logging
Pass a `logger` callback to receive structured events for each stage of the pipeline. Each event includes a log level, a step name, a message, and optional details.
This is the easiest way to wire the converter into your own app logs without parsing arbitrary console output.
Conversion logger
logger.ts · ts
import { convertBook } from 'dyslibria-converter';
await convertBook('./books/source.epub', {
outputPath: './books/source.dyslibria.epub',
logger(event) {
if (event.level === 'debug') return;
console.log(`[${event.level}] [${event.step}] ${event.message}`, event.details ?? {});
},
});Error classes worth catching
- `InvalidEpubError` for archives that are not valid EPUBs
- `ArchiveSafetyError` for extraction hazards such as zip-slip style paths or over-large archives
- `NoContentFilesError` when no HTML or XHTML content was found to process
- `ConversionStepError` when a specific pipeline stage fails and you want step context
A practical catch block
Typed error handling
error-handling.ts · ts
import {
ArchiveSafetyError,
ConversionStepError,
InvalidEpubError,
convertBook,
} from 'dyslibria-converter';
try {
await convertBook('./books/source.epub');
} catch (error) {
if (error instanceof InvalidEpubError) {
console.error('The upload is not a valid EPUB.');
} else if (error instanceof ArchiveSafetyError) {
console.error('The EPUB failed safety checks.');
} else if (error instanceof ConversionStepError) {
console.error('Conversion failed during step:', error.context?.step);
} else {
console.error('Unexpected converter error:', error);
}
}Chapter 4 · 4 min read
CLI usage
Use the CLI for quick local conversions, inspection runs, and simple shell-driven workflows without writing any Node code.
- Binary name: `dyslibria-convert`
- `convert` and `inspect` subcommands
- Optional `--output`, `--preset`, and `--profile` flags
- Default output naming appends `.dyslibria.epub`
CLI commands
Usage
terminal · bash
dyslibria-convert convert <input.epub> [--output <output.epub>] [--preset <preset-id>] [--profile <profile.json>]
dyslibria-convert inspect <input.epub>Convert a book from the command line
If you do not pass `--output`, the CLI writes the result beside the input file using the pattern `name.dyslibria.epub`. If you do not pass `--preset` or `--profile`, the CLI uses Dyslibria Default.
Convert
terminal · bash
npx dyslibria-convert convert ./books/input.epub
npx dyslibria-convert convert ./books/input.epub --preset intense-scaffolding
npx dyslibria-convert convert ./books/input.epub --profile ./profiles/custom-profile.json --output ./books/output.epubInspect without converting
The inspect command prints a formatted JSON object with title, author, warnings, and other metadata fields, which makes it handy inside shell scripts and CI checks.
Inspect
terminal · bash
npx dyslibria-convert inspect ./books/input.epubChapter 5 · 6 min read
Release and regression workflow
Use the package like a real maintainer would: build it, run tests, dry-run the published tarball, and validate it against a trusted private EPUB corpus.
- `npm run release:check` before publishing
- `npm pack --dry-run` included
- Real-world regression script supported
- Private manifests can target hand-picked regression books
Release check
Before publishing a new version, run the built-in release check. It covers unit and parity tests, the package build, and a dry-run pack step so you can confirm the published tarball shape before npm sees it.
Release check
terminal · bash
npm test
npm run build
npm run release:checkReal-world regression runs
Synthetic fixtures are essential, but real EPUB corpora catch the awkward edge cases that only appear in the wild. The package includes a regression runner so you can point the current build at a trusted local corpus before a release.
Batch regression run
terminal · bash
npm run build
npm run qa:real-world -- \
--input-dir /path/to/raw-epubs \
--output-dir ./reports/real-world-output \
--report ./reports/real-world-regression.jsonTarget a smaller release-candidate subset
If you keep a hand-picked private manifest for especially valuable books, the real-world regression runner can process just that shortlist. This is a good habit when you have a known set of titles that historically reveal regressions.
Manifest-driven run
terminal · bash
npm run qa:real-world -- \
--input-dir /path/to/raw-epubs \
--manifest ./fixtures/local/release-candidate.json \
--output-dir ./reports/regression-output \
--report ./reports/regression-report.json