@iarna/toml

A fast, spec-compliant TOML parser and stringifier for Node.js with a familiar JSON-style interface.

Library
npm
v2.2.5
341stars
ISC

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
35/100Needs Attention
Development Activity0
Maintenance0
Community60
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
71/100Good
Architecture78
Code Quality82
Innovation55
Learning Curve70

@iarna/toml is a Node.js library for reading and writing TOML documents, exposing an interface deliberately shaped like JSON.parse/JSON.stringify so it drops into existing config-loading code with minimal friction. It targets the TOML 1.0.0-rc.1 specification with careful, test-suite-verified adherence, and produces detailed, human-readable parser errors that point at the exact row, column, and byte offset of a problem.

Beyond the basic synchronous parse/stringify pair, the library ships async and Node stream interfaces for working with very large TOML documents without blocking the event loop, plus a low-level state-machine parser API for callers who want to feed it data incrementally. It has zero runtime dependencies, native BigInt support for large integers, and a stringifier that round-trips dates, times, and nested tables/arrays back into TOML that re-parses to the same structure.

What You Get

  • A synchronous TOML.parse(str) that returns a plain object, matching the ergonomics of JSON.parse
  • A synchronous TOML.stringify(obj) that serializes objects to TOML, matching JSON.stringify ergonomics including toJSON() support
  • Async (TOML.parse.async) and streaming (TOML.parse.stream) parse interfaces for large documents that shouldn’t block the event loop
  • A low-level, incrementally-feedable parser class (lib/toml-parser.js) for callers building their own I/O around it
  • Parser errors carrying line, col, and pos, plus an optional pretty-printed error view showing the offending source line
  • Bundled TypeScript type definitions (index.d.ts) covering the parse/stringify surface

Common Use Cases

  • Reading and writing TOML configuration files (e.g. pyproject.toml-style or Cargo-style config) from Node.js tooling
  • Powering CLI tools and build tools that accept TOML as a config format alternative to JSON/YAML
  • Converting between TOML and JSON in migration scripts or interop layers
  • Streaming-parsing very large TOML documents without loading the full string into a blocking synchronous call
  • Generating TOML output programmatically for other tools/ecosystems to consume (e.g. Rust/Cargo-adjacent tooling)

Under The Hood

Architecture The library is organized around a small state-machine parser: lib/parser.js defines a generic Parser base class with next/call/return/goto primitives for a stack-based state machine driven one character at a time, and lib/toml-parser.js subclasses it with TOML-specific grammar states (tables, arrays, inline tables, strings, datetimes) built as chained method-per-state handlers. The public entry points (parse.js, parse-async.js, parse-stream.js) are thin wrappers that drive this same parser instance synchronously, in timed chunks via setImmediate, or fed from a Node Transform stream, so all three modes share one parsing core rather than three separate implementations. stringify.js is a fully separate, independent module (object-walking, recursive by key/table type) with no shared code with the parser, and toml.js just re-exports both halves. This gives a clear separation of concerns between the parsing engine, its I/O wrappers, and the reverse (stringify) direction, though it means bug fixes to core grammar rules touch a large single file (lib/toml-parser.js, ~1400 lines).

Tech Stack Plain JavaScript (CommonJS, no build step, no transpilation) with zero runtime dependencies declared in package.json. Small helper modules (lib/create-date.js, create-time.js, create-datetime.js, create-datetime-float.js) wrap native Date objects with TOML-specific isFloating/isDate/isTime markers, and lib/format-num.js handles numeric padding. Bundled index.d.ts provides TypeScript types for consumers without the package itself being written in TypeScript. Devtooling uses tap for the test runner and the author’s own @iarna/standard lint config; benchmarking uses the benchmark package plus comparison against several competing TOML libraries.

Code Quality The project maintains a dedicated 100%-coverage test suite (test/) combining hand-written unit tests, an official TOML-spec-derived assertion suite (toml-spec-tests, TOML/YAML pairs), the third-party BurntSushi TOML compliance suite, and round-trip tests asserting parse(stringify(parse(x))) stability. Coverage-only edge-case files (coverage.js, coverage-error.js) exist specifically to close gaps the functional tests don’t hit, and istanbul ignore annotations mark intentionally-unreachable defensive branches rather than leaving them silently untested. Errors are typed (ParserError, TomlError) with structured line/col/pos fields rather than opaque strings. The codebase predates strict TypeScript adoption and has no static type-checking on the implementation itself, only on its public .d.ts surface.

What Makes It Unique Its distinguishing choice is deliberately mirroring the native JSON.parse/JSON.stringify API shape and semantics (including toJSON() hook support) so that TOML becomes a near drop-in replacement for JSON in existing Node code, while still exposing lower-level async, streaming, and incremental parser APIs for callers with large-document or non-blocking requirements that most competing TOML libraries don’t offer. Combined with an unusually rigorous, spec-conformance-first test strategy (three independent compliance suites plus round-trip verification) for a library of its size, it favors correctness and ergonomic familiarity over minimal implementation footprint.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search