3.1 KiB
dispatch
Purpose
Per-file orchestration extracted from the bin entry. Reads a single input
file from disk, routes binary inputs (TTF/OTF/WOFF/WOFF2) through the
injected FontConverter to produce a TypefaceFont, routes .json inputs
through pass-through parsing (no conversion), then either serialises the
TypefaceFont back to JSON (when --format=json) or packs it via
BinaryFontPacker and writes the resulting .btf. Progress, skip, and
error events are streamed through the injected printer / logger. Lives in
its own module so the entry can stay small enough to satisfy the file-size
budget while keeping a single round-trip testable in isolation.
Features
- Discriminates input by extension:
.ttf/.otf/.woff/.woff2goes to the converter;.jsongoes to pass-through validation. - Computes destination paths honouring
--preserve-structure(mirror the input tree under the output root) vs the flat default. - Honours
--force: existing outputs are skipped silently unless--forceis set, in which case they are overwritten. - Captures any throwable from the converter or packer per file, prints a
failure line, logs through
LoggerLike, and returns{ ok: false }so the batch can continue and the entry exits1.
Usage: Basic
import { FontConverter } from "@suaveplan/font-convert";
import { BinaryFontPacker } from "../packer/binary-font-packer/binary-font-packer.js";
import { dispatchOne } from "./dispatch.js";
const outcome = await dispatchOne(
"./fonts/Inter-Regular.ttf",
new FontConverter(),
new BinaryFontPacker(),
options,
"./fonts",
"./out",
deps
);
// outcome.ok === true, outcome.compressedBytes > 0
Usage: Advanced
const failures: string[] = [];
for (const file of files) {
const r = await dispatchOne(file, converter, packer, options, root, out, deps);
if (!r.ok) failures.push(file);
}
if (failures.length > 0) {
deps.logger.error("font-compress.cli.batch_partial", { failures });
}
API Reference
| Name | Signature | Notes |
|---|---|---|
dispatchOne |
(file, converter, packer, options, inputRoot, outputRoot, deps) => Promise<FileOutcome> |
Never throws; all failures are reported via the returned outcome. |
FileOutcome |
{ ok; originalBytes; compressedBytes } |
compressedBytes === 0 means the file was skipped without overwrite. |
DispatchDeps |
{ logger; stdout; stderr } |
Injected so a test can capture stream output. |
Implementation Notes
Destination resolution intentionally does NOT call path.relative —
prefix-strip plus replace(/^[\\/]+/) is enough and lets us mirror the
upstream legacy semantics where Windows-style separators round-trip
unchanged. The dispatcher always creates the parent directory with
mkdir({ recursive: true }) before writing, so users do not need to
pre-create the output tree. JSON inputs are validated by JSON.parse only —
the typeface schema is enforced downstream by BinaryFontPacker, which
throws FontCompressError(PACK_FAILED) for malformed shapes, and the catch
arm here converts that into a clean per-file failure line.