# xyaml

> A secure, extensible YAML compiler for TypeScript, Bun, Node.js, and browsers

Latest version **1.0.0** (published 2026-08-23) · MIT license · 0 weekly downloads

## Install

```sh
npm install xyaml
pnpm add xyaml
yarn add xyaml
bun add xyaml
```

Provides the command `xyaml`.

## Health

**Score 65/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 1.0.0 |
| Published | 2026-08-23 |
| First published | 2017-09-23 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=22.0.0 |
| Dependencies | 1 |
| Unpacked size | 277.9 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | teniryte |
| Maintainers | teniryte |
| Keywords | yaml, configuration, compiler, typescript, bun, node, browser |

## Links

- npm: https://www.npmjs.com/package/xyaml
- Repository: https://github.com/teniryte/xyaml
- Homepage: https://github.com/teniryte/xyaml#readme
- Issues: https://github.com/teniryte/xyaml/issues
- npm.io page: https://npm.io/package/xyaml

## Dependencies (1)

- [yaml](https://npm.io/package/yaml.md) ^2.9.0

## Alternatives

- [monaco-yaml](https://npm.io/package/monaco-yaml.md) — 420.1K weekly downloads
- [@crewx/workflow](https://npm.io/package/@crewx/workflow.md) — 3.1K weekly downloads
- [yaml-cat](https://npm.io/package/yaml-cat.md) — 38 weekly downloads
- [nunjucks-in-yaml](https://npm.io/package/nunjucks-in-yaml.md) — 9 weekly downloads
- [shopify-symlinks](https://npm.io/package/shopify-symlinks.md) — 3 weekly downloads

## Recent versions

- 1.0.0 (latest) — 2026-08-23
- 0.1.15 — 2022-07-25
- 0.1.13 — 2022-07-25
- 0.1.12 — 2022-07-25
- 0.1.11 — 2022-07-25
- 0.1.10 — 2022-07-25
- 0.1.9 — 2022-07-25
- 0.1.8 — 2021-05-16
- 0.1.7 — 2021-05-16
- 0.1.6 — 2021-05-16
- 0.1.4 — 2021-05-15
- 0.1.3 — 2021-05-15
- 0.1.2 — 2021-05-15
- 0.1.0 — 2021-01-15
- 0.0.28 — 2021-01-11
- … 20 more at https://npm.io/package/xyaml/versions

## README

[![CI](https://github.com/teniryte/xyaml/actions/workflows/ci.yml/badge.svg)](https://github.com/teniryte/xyaml/actions/workflows/ci.yml)
[![npm version](https://img.shields.io/npm/v/xyaml.svg)](https://www.npmjs.com/package/xyaml)
[![npm downloads](https://img.shields.io/npm/dm/xyaml.svg)](https://www.npmjs.com/package/xyaml)
[![minzipped size](https://img.shields.io/bundlephobia/minzip/xyaml)](https://bundlephobia.com/package/xyaml)
[![license](https://img.shields.io/npm/l/xyaml.svg)](https://github.com/teniryte/xyaml/blob/main/LICENSE)
[![TypeScript](https://img.shields.io/badge/TypeScript-7-3178c6.svg)](https://www.typescriptlang.org/)

# xyaml

A secure, extensible YAML compiler for TypeScript, Bun, Node.js, and modern browsers.

xyaml adds deterministic references, composition, resource imports, typed results, and opt-in
JavaScript evaluation to standard YAML. The default mode does not execute code or access the
network.

## Features

- Explicit `self`, `parent`, `root`, and `context` references
- Deterministic `$include` merging and typed `!import` values
- Local files, HTTP resources, raw text, JSON, and JavaScript modules
- Safe-by-default parsing with a clearly separated trusted mode
- Async and sync Node.js APIs, plus a browser-safe core
- First-class TypeScript declarations, ESM, CommonJS, and a CLI
- Structured errors, source metadata, cycle detection, caching, and cancellation
- YAML 1.2 support powered by [`yaml`](https://github.com/eemeli/yaml)

## Installation

```sh
bun add xyaml
```

```sh
npm install xyaml
```

xyaml requires Bun 1.3+ or Node.js 22+.

## Quick start

```yaml
# config.xyaml
$include:
  - ./defaults.xyaml

app:
  host: localhost
  port: 8000
  url: http://${self.host}:${self.port}

features: !import ./features.json
license: !text ./LICENSE
```

```ts
import { loadFile } from 'xyaml/node';

interface Config {
  app: {
    host: string;
    port: number;
    url: string;
  };
  features: Record<string, boolean>;
  license: string;
}

const config = await loadFile<Config>('./config.xyaml');
```

The generic type describes the expected result; it is not runtime validation. Validate untrusted
data with the schema library used by your application.

## References

References are intentionally explicit:

```yaml
name: xyaml
port: 8000
portCopy: ${self.port}

server:
  host: localhost
  url: http://${self.host}:${parent.port}
  packageName: ${root.name}
  environment: ${context.environment}
```

- `self` is the mapping or sequence containing the current value.
- `parent` is the parent of `self`.
- `root` is the compiled root document.
- `context` is supplied by the caller.

An exact reference preserves its type. Embedded references accept scalar values and produce a
string. Use `$${self.value}` to emit the literal text `${self.value}`. Missing references,
ambiguous short names, object interpolation, and cycles are errors.

```ts
import { parse } from 'xyaml';

const config = parse(source, {
  context: { environment: 'production' },
});
```

## Composition

### `$include`

`$include` merges mappings into the current mapping:

```yaml
$include:
  - ./defaults.xyaml
  - source: ./environments.xyaml
    select: production

port: 9000
```

Includes are applied from left to right. Later includes override earlier includes, and local keys
override every included key. Included values must be mappings.

### `!import`

`!import` inserts a YAML, XYAML, or JSON resource as a value:

```yaml
database: !import ./database.xyaml

enabledFeatures: !import
  source: ./features.json
  select: production
```

Local Node.js resolution checks the exact path, then `.xyaml`, `.yaml`, `.yml`, `.json`, and
matching `index.*` files.

### `!text` and `!resolve`

```yaml
license: !text ./LICENSE
absoluteConfigPath: !resolve ./config.xyaml
```

`!text` returns the resource without parsing it. `!resolve` resolves a specifier without reading
it; the Node loader returns a native absolute path for `file:` URLs.

YAML's standard explicit tags replace the coercion commands from xyaml 0.x:

```yaml
portAsString: !!str 8000
portAsInteger: !!int "8000"
ratio: !!float "0.75"
```

## Trusted mode

Trusted mode enables arbitrary JavaScript. It is intended only for configuration files controlled
by the application owner.

```yaml
math:
  base: 2
  add: !fn |
    (a, b) => a + b + self.base
  result: !expr self.add(3, 4)

$eval:
  - document.delete("math.add")
```

```ts
const config = await loadFile('./config.xyaml', { trusted: true });
```

- `!expr` evaluates a synchronous JavaScript expression.
- `!fn` evaluates a function expression and captures its `self`, `parent`, `root`, and `context`.
- `$eval` executes synchronous statements after the complete document has been resolved.
- `$eval` also receives `document.get`, `document.has`, `document.set`, and `document.delete`.

Trusted mode uses the JavaScript runtime itself. It is not a sandbox and does not protect against
filesystem access, process access, infinite loops, or global mutation.

### JavaScript modules

The built-in Node loader supports local JavaScript modules in trusted mode:

```yaml
generated: !module
  source: ./generate.mjs
  args: [production]
```

```js
export default ({ args, context, source }) => ({
  environment: args[0],
  region: context.region,
  loadedFrom: source.href,
});
```

Async loading supports `.mjs`, `.cjs`, and `.js`. `loadFileSync` only supports `.cjs`. Remote
JavaScript modules are not supported by the built-in loader.

Values containing functions cannot be serialized. Remove build-time helper functions with `$eval`
before passing the result to the CLI or `stringify`.

## HTTP resources

HTTP access is disabled by default:

```ts
const config = await loadFile('https://example.com/config.xyaml', {
  allowHttp: true,
});
```

The browser-safe core uses a fetch loader:

```ts
import { compile, createFetchLoader } from 'xyaml';

const baseUrl = new URL('/config/app.xyaml', window.location.href);
const loader = createFetchLoader({ baseUrl });
const source = await fetch(baseUrl).then(response => response.text());

const config = await compile(source, {
  allowHttp: true,
  baseUrl,
  loader,
});
```

Pass an `AbortSignal` as `signal` to cancel asynchronous resource loading. A compiler caches each
canonical resource for the duration of one compilation.

## API

### Universal core

```ts
import {
  compile,
  compileDocument,
  createCompiler,
  parse,
  parseDocument,
  stringify,
} from 'xyaml';
```

- `parse<T>(source, options?)` synchronously compiles a string. External resources require a
  loader with synchronous support.
- `compile<T>(source, options?)` asynchronously compiles a string with full resource support.
- `parseDocument<T>` and `compileDocument<T>` return an `XyamlDocument<T>`.
- `createCompiler(options?)` creates a reusable compiler configuration. Caches remain isolated to
  each compilation.
- `stringify(value, options?)` serializes a non-cyclic value to YAML and rejects functions and
  symbols.

### Node.js and Bun

```ts
import {
  loadFile,
  loadFileDocument,
  loadFileDocumentSync,
  loadFileSync,
} from 'xyaml/node';
```

- `loadFile<T>(pathOrUrl, options?)` is the recommended complete API.
- `loadFileSync<T>` supports local YAML, JSON, text, and CommonJS modules.
- Document variants return metadata and navigation methods.

### Document API

```ts
const document = await loadFileDocument('./config.xyaml');

document.get('server.port');
document.has(['server', 'host']);
document.set('server.port', 9000);
document.delete('internal');
document.toJS();
document.toJSON();
document.toString();
```

`toJS()` and `toJSON()` return independent snapshots. Parse and resource errors throw
`XyamlError`, which includes a stable `code` and optional `source`, `path`, and `cause`.

### Custom resource loaders

Implement `ResourceLoader` to integrate virtual filesystems, application caches, authenticated
HTTP clients, or browser storage:

```ts
import type { ResourceLoader, ResourceSource } from 'xyaml';

class VirtualLoader implements ResourceLoader {
  resolve(specifier: string, importer?: URL): URL {
    return new URL(specifier, importer);
  }

  async load(url: URL): Promise<ResourceSource> {
    return { url, content: await readFromApplicationStorage(url) };
  }
}
```

`loadSync`, `loadModule`, `loadModuleSync`, and `display` are optional capabilities.

## CLI

```sh
xyaml compile config.xyaml
xyaml compile config.xyaml --output config.json
xyaml compile config.xyaml --format yaml --output compiled.yaml
xyaml compile - --base ./config --context context.yaml
```

Options:

- `-o, --output <file>` writes to a file instead of stdout.
- `-f, --format json|yaml` selects the output format.
- `--context <file>` loads a YAML or JSON mapping as `context`.
- `--base <path|url>` sets the base for stdin imports.
- `--trusted` enables executable features.
- `--allow-http` enables HTTP(S) resources.

JSON is the default stdout format. A `.yaml`, `.yml`, or `.xyaml` output filename selects YAML when
`--format` is omitted. Diagnostics are written to stderr and failures use a non-zero exit code.

## Migration from 0.x

Version 1.0 intentionally replaces the historical string-command grammar:

| xyaml 0.x | xyaml 1.0 |
| --- | --- |
| `${host}` | `${self.host}` |
| `~include` | `$include` |
| `~import` | `!import` |
| `~read`, `~download` | `!text` |
| `~path`, `~resolve` | `!resolve` |
| `~str`, `~num` | `!!str`, `!!int`, `!!float` |
| `~ex` or JavaScript interpolation | `!expr` with `trusted: true` |
| Inline `fn` or arrow functions | `!fn` with `trusted: true` |
| `eval` | `$eval` with `trusted: true` |
| JS modules mutating `process.argv` | `!module` with `{ args, context, source }` |
| `dump` | `stringify` |

The old releases remain useful as historical references, but 1.0 does not include a compatibility
parser.

## Development

```sh
bun install
bun run check
```

The complete check runs formatting, linting, strict TypeScript, Bun tests with coverage, the
library build, Node ESM/CommonJS tests, a browser-target bundle smoke test, `publint`, and Are The
Types Wrong.

## License

[MIT](./LICENSE)

---
_Source: https://npm.io/package/xyaml · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
