Files
bun-src/docs/runtime/toml.mdx
T
2026-08-27 21:09:14 +00:00

297 lines
7.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 00009999 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");
```