--- title: TOML description: Use Bun's built-in support for TOML files through both runtime APIs and bundler integration --- In Bun, TOML is a first-class citizen alongside JSON, JSON5, and YAML. You can: - Parse TOML strings with `Bun.TOML.parse` - `import` & `require` TOML files as modules at runtime (including hot reloading & watch mode support) - `import` & `require` TOML files in frontend apps with Bun's bundler --- ## Runtime API ### `Bun.TOML.parse()` Parse a TOML string into a JavaScript object. ```ts import { TOML } from "bun"; const text = ` name = "my-app" version = "1.0.0" debug = true [database] host = "localhost" port = 5432 [features] tags = ["web", "api"] `; const data = TOML.parse(text); console.log(data); // { // name: "my-app", // version: "1.0.0", // debug: true, // database: { host: "localhost", port: 5432 }, // features: { tags: ["web", "api"] } // } ``` #### Supported TOML Features Bun's TOML parser implements the full [TOML v1.1.0 specification](https://github.com/toml-lang/toml/releases/tag/1.1.0) and passes the complete official [toml-test](https://github.com/toml-lang/toml-test) conformance suite. - **Strings**: basic (`"..."`) and literal (`'...'`), including multi-line, with all escapes (`\uHHHH`, `\UHHHHHHHH`, and TOML 1.1's `\xHH` and `\e`) - **Integers**: decimal, hex (`0x`), octal (`0o`), and binary (`0b`). Integers outside ±(2^53 - 1) throw, because a JavaScript number cannot represent them losslessly - **Floats**: including `inf` and `nan` - **Booleans**: `true` and `false` - **Date/times**: returned as [Temporal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal) objects — offset date-time as `Temporal.Instant`, local date-time as `Temporal.PlainDateTime`, local date as `Temporal.PlainDate`, and local time as `Temporal.PlainTime` - **Arrays**: including mixed types and nested arrays - **Tables**: standard (`[table]`) and inline (`{ key = "value" }`), including TOML 1.1 multi-line inline tables - **Array of tables**: `[[array]]` - **Dotted keys**: `a.b.c = "value"` - **Comments**: using `#` ```ts const data = Bun.TOML.parse(` # Application config title = "My App" [owner] name = "John Doe" [database] enabled = true ports = [8000, 8001, 8002] connection_max = 5000 [servers.alpha] ip = "10.0.0.1" role = "frontend" [servers.beta] ip = "10.0.0.2" role = "backend" `); ``` #### Date/times Each of TOML's four date/time types maps 1:1 onto a Temporal type. Temporal carries nanosecond precision; as the TOML spec permits, fractional seconds beyond nine digits are truncated: ```ts const doc = Bun.TOML.parse(` created = 1979-05-27T00:32:00-07:00 # offset date-time meeting = 1979-05-27T07:32:00 # local date-time birthday = 1979-05-27 # local date opens = 07:32:00 # local time `); doc.created; // Temporal.Instant (an offset date-time specifies an instant; // the written offset normalizes away: 1979-05-27T07:32:00Z) doc.meeting; // Temporal.PlainDateTime doc.birthday; // Temporal.PlainDate doc.opens; // Temporal.PlainTime ``` #### Error Handling `Bun.TOML.parse()` throws a `SyntaxError` if the TOML is invalid: ```ts try { Bun.TOML.parse("invalid = = ="); } catch (error) { console.error("Failed to parse TOML:", error.message); // Failed to parse TOML: TOML Parse error: Expected a value but found '=' } ``` ### `Bun.TOML.stringify()` Serialize a JavaScript object to a TOML document. Scalar keys come first, followed by `[table]` and `[[array-of-tables]]` sections: ```ts Bun.TOML.stringify({ name: "app", server: { host: "localhost", port: 8080 }, points: [{ x: 1 }, { x: 2 }], }); // name = "app" // // [server] // host = "localhost" // port = 8080 // // [[points]] // x = 1 // // [[points]] // x = 2 ``` The top-level value must be an object — a TOML document is a table. `Temporal.Instant`, `Temporal.PlainDateTime`, `Temporal.PlainDate`, and `Temporal.PlainTime` values become the corresponding TOML date/time literals, so `stringify(parse(doc))` round-trips date/time types. `Temporal.ZonedDateTime` becomes an offset date-time and `Date` becomes an offset date-time in UTC. TOML has no syntax for time-zone or calendar annotations, so those are dropped (the ISO fields are written), and its years are four digits, so date values outside 0000–9999 and invalid `Date`s throw. Because TOML cannot represent them, `null` values, `BigInt`, circular structures, `Temporal.PlainYearMonth`, `Temporal.PlainMonthDay`, and `Temporal.Duration` also throw; `undefined`, function, and symbol properties are skipped (inside arrays they throw, since TOML arrays cannot have holes), and passing one of those as the top-level value returns `undefined`, as `JSON.stringify` does. --- ## Module Import ### ES Modules Import TOML files directly as ES modules. Bun parses the TOML and exposes it as both default and named exports: ```toml config.toml [database] host = "localhost" port = 5432 name = "myapp" [redis] host = "localhost" port = 6379 [features] auth = true rateLimit = true analytics = false ``` #### Default Import ```ts app.ts icon="/icons/typescript.svg" import config from "./config.toml"; console.log(config.database.host); // "localhost" console.log(config.redis.port); // 6379 ``` #### Named Imports You can destructure top-level TOML tables as named imports: ```ts app.ts icon="/icons/typescript.svg" import { database, redis, features } from "./config.toml"; console.log(database.host); // "localhost" console.log(redis.port); // 6379 console.log(features.auth); // true ``` Or combine both: ```ts app.ts icon="/icons/typescript.svg" import config, { database, features } from "./config.toml"; // Use the full config object console.log(config); // Or use specific parts if (features.rateLimit) { setupRateLimiting(database); } ``` #### Import Attributes Use an import attribute to load any file as TOML: ```ts app.ts icon="/icons/typescript.svg" import myConfig from "./my.config" with { type: "toml" }; ``` ### CommonJS You can also `require` TOML files in CommonJS: ```ts app.ts icon="/icons/typescript.svg" const config = require("./config.toml"); console.log(config.database.name); // "myapp" // Destructuring also works const { database, redis } = require("./config.toml"); console.log(database.port); // 5432 ``` --- ## Hot Reloading with TOML When you run your application with `bun --hot`, Bun detects changes to TOML files and reloads them without restarting: ```toml config.toml [server] port = 3000 host = "localhost" [features] debug = true verbose = false ``` ```ts server.ts icon="/icons/typescript.svg" import { server, features } from "./config.toml"; console.log(`Starting server on ${server.host}:${server.port}`); Bun.serve({ port: server.port, hostname: server.host, fetch(req) { if (features.verbose) { console.log(`${req.method} ${req.url}`); } return new Response("Hello World"); }, }); ``` Run with hot reloading: ```bash terminal icon="terminal" bun --hot server.ts ``` --- ## Bundler Integration When you bundle with Bun, the bundler parses imported TOML at build time and includes it as a JavaScript module: ```bash terminal icon="terminal" bun build app.ts --outdir=dist ``` This means: - Zero runtime TOML parsing overhead in production - Smaller bundle sizes - Tree shaking of unused properties (named imports) ### Dynamic Imports You can also dynamically import TOML files: ```ts const config = await import("./config.toml"); ```