npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@agentine/yamlite

v0.1.0

Published

Drop-in replacement for js-yaml — TypeScript-first YAML 1.2 parser and serializer

Downloads

19

Readme

@agentine/yamlite

Drop-in replacement for js-yaml — TypeScript-first YAML 1.2 parser and serializer with zero dependencies.

Why yamlite?

js-yaml is one of the most downloaded packages in the npm ecosystem (161 million weekly downloads), but it has accumulated significant maintenance debt:

  • Bus factor of 1 — single maintainer with a 3.5-year gap between releases (v4.1.0 in Jan 2022, v4.1.1 in Sep 2025)
  • 55 open issues, 15 open PRs with no active triage
  • Written in ES5-era JavaScript — no native TypeScript, no ESM
  • Types maintained separately on DefinitelyTyped, meaning they can drift from the implementation
  • No native ESM — requires workarounds for modern Node.js projects

yamlite fixes all of this:

  • Written in TypeScript with bundled declarations — no separate @types/ package needed
  • Native ESM with a proper dual CJS/ESM package (exports field)
  • Zero runtime dependencies — nothing to audit, nothing to break
  • Node.js 16+ required
  • 100% compatible with the js-yaml v4 public API

Installation

npm install @agentine/yamlite

Importing

ESM:

import yaml from '@agentine/yamlite';
// or named:
import { load, dump, loadAll } from '@agentine/yamlite';

CJS:

const yaml = require('@agentine/yamlite');
// or named:
const { load, dump, loadAll } = require('@agentine/yamlite');

Quick Start

import { load, dump } from '@agentine/yamlite';

// Parse YAML → JavaScript
const config = load(`
name: Acme
version: 3
features:
  - auth
  - logging
`);
// { name: 'Acme', version: 3, features: ['auth', 'logging'] }

// Serialize JavaScript → YAML
const yaml = dump({ name: 'Acme', version: 3, features: ['auth', 'logging'] });
// name: Acme
// version: 3
// features:
//   - auth
//   - logging

Core API

load(input, options?)

Parse a single YAML document from a string. Throws YAMLException if the input contains more than one document.

function load(input: string, options?: LoadOptions): unknown
const doc = load('answer: 42'); // { answer: 42 }

Returns undefined for empty input.

loadAll(input, iterator?, options?)

Parse a multi-document YAML stream. When an iterator function is provided it is called for each document and the function returns void. Without an iterator the function returns unknown[].

function loadAll(
  input: string,
  iterator?: (doc: unknown) => void,
  options?: LoadOptions,
): unknown[] | void
// Collect all documents
const docs = loadAll('---\na: 1\n---\nb: 2');
// [{ a: 1 }, { b: 2 }]

// Stream documents via iterator
loadAll('---\na: 1\n---\nb: 2', (doc) => {
  console.log(doc);
});

// Options without an iterator
const docs2 = loadAll('---\na: 1', { schema: CORE_SCHEMA });

dump(input, options?)

Serialize a JavaScript value to a YAML string. Always appends a trailing newline.

function dump(input: unknown, options?: DumpOptions): string
dump({ a: 1, b: [2, 3] });
// a: 1
// b:
//   - 2
//   - 3

LoadOptions

| Option | Type | Default | Description | |--------|------|---------|-------------| | filename | string | — | Used in error and warning messages to identify the source | | schema | Schema | DEFAULT_SCHEMA | Schema that controls type resolution | | onWarning | (w: YAMLException) => void | — | Called for non-fatal warnings (e.g., duplicate keys) | | json | boolean | false | JSON compatibility mode — silences duplicate-key warnings and accepts JSON-specific values | | listener | (event: 'open' \| 'close', state: object) => void | — | Called on every parsed node open/close | | maxDepth | number | 1000 | Maximum nesting depth before throwing | | maxAliases | number | 100 | Maximum number of alias dereferences before throwing |

const doc = load(yamlString, {
  filename: 'config.yaml',
  onWarning: (w) => console.warn(w.message),
  maxDepth: 100,
  maxAliases: 50,
});

DumpOptions

| Option | Type | Default | Description | |--------|------|---------|-------------| | indent | number | 2 | Number of spaces per indentation level (minimum 1) | | noArrayIndent | boolean | false | Do not indent array items relative to their parent key | | skipInvalid | boolean | false | Silently skip values that cannot be serialized (functions, undefined) instead of throwing | | flowLevel | number | -1 | Nesting level at which to switch to flow style; -1 means block everywhere | | styles | Record<string, string> | {} | Per-type style overrides, e.g. { '!!null': 'canonical', '!!int': 'hex' } | | schema | Schema | DEFAULT_SCHEMA | Schema used for type representation | | sortKeys | boolean \| ((a, b) => number) | false | Sort mapping keys alphabetically, or supply a comparator | | lineWidth | number | 80 | Target line width for wrapping scalars; -1 disables wrapping | | noRefs | boolean | false | Disable anchor/alias generation for repeated object references | | noCompatMode | boolean | false | Do not quote YAML 1.1 boolean words (yes/no/on/off) | | condenseFlow | boolean | false | Remove spaces inside flow-style sequences and mappings | | quotingType | "'" \| '"' | "'" | Preferred quote character for string scalars | | forceQuotes | boolean | false | Force quoting for all string scalars | | replacer | (key: string, value: unknown) => unknown | — | Transform values before serialization, like JSON.stringify's replacer |

dump(data, {
  indent: 4,
  sortKeys: true,
  lineWidth: 120,
  quotingType: '"',
});

Schema System

yamlite ships four built-in schemas, each a superset of the previous:

| Schema | Tags | |--------|------| | FAILSAFE_SCHEMA | !!str, !!seq, !!map | | JSON_SCHEMA | + !!null, !!bool, !!int, !!float | | CORE_SCHEMA | + implicit resolution (hex/octal ints, true/false/null aliases) | | DEFAULT_SCHEMA | + !!binary, !!omap, !!pairs, !!set, !!timestamp, !!merge |

The default for both load and dump is DEFAULT_SCHEMA.

Extending a Schema

Schema.extend() creates a new schema that inherits all types from the parent and adds your custom types. The original schema is not modified.

schema.extend(type: Type): Schema
schema.extend(types: Type[]): Schema
schema.extend({ implicit?: Type[], explicit?: Type[] }): Schema
import { DEFAULT_SCHEMA, Type } from '@agentine/yamlite';

const PointType = new Type('!point', {
  kind: 'sequence',
  resolve: (data) => Array.isArray(data) && data.length === 2,
  construct: ([x, y]) => ({ x, y }),
});

const mySchema = DEFAULT_SCHEMA.extend(PointType);

load('loc: !point [10, 20]', { schema: mySchema });
// { loc: { x: 10, y: 20 } }

Implicit types are tried automatically during tag resolution; explicit types require a YAML tag (!point) in the document.

Type System

Type class

class Type {
  constructor(tag: string, options?: TypeOptions)
}

TypeOptions

| Option | Type | Description | |--------|------|-------------| | kind | 'scalar' \| 'sequence' \| 'mapping' | Required. The YAML node kind this type handles | | resolve | (data: unknown) => boolean | Return true if this type can represent the given raw value | | construct | (data: unknown) => unknown | Convert the raw YAML value to a JavaScript value | | instanceOf | Function | JS class whose instances this type serializes | | predicate | (data: unknown) => boolean | Alternative to instanceOf for matching JS values during dump | | represent | ((data, style?) => string) \| Record<string, (data) => string> | Serialize a JS value to a YAML string, optionally per named style | | representName | (data: unknown) => string | Override the tag name used during serialization | | defaultStyle | string | Which style key from represent to use when none is specified | | styleAliases | Record<string, string[]> | Map alias names to canonical style names | | multi | boolean | Allow multiple types with the same tag in a schema |

Custom type example

import { Type, DEFAULT_SCHEMA } from '@agentine/yamlite';

// Represent JS RegExp objects as !!js/regexp scalars
const RegExpType = new Type('tag:yaml.org,2002:js/regexp', {
  kind: 'scalar',
  instanceOf: RegExp,
  predicate: (data) => data instanceof RegExp,
  represent: (data) => data.toString(),
  resolve: (data) => typeof data === 'string' && data.startsWith('/'),
  construct: (data) => {
    const m = data.match(/^\/(.*)\/([gimsuy]*)$/);
    return m ? new RegExp(m[1], m[2]) : new RegExp(data);
  },
});

const schema = DEFAULT_SCHEMA.extend(RegExpType);
const doc = load('pattern: /hello/i', { schema });
// { pattern: /hello/i }

Built-in Types

!!str — String

Tag: tag:yaml.org,2002:str | Kind: scalar

Any YAML scalar that is not resolved by another implicit type becomes a string.

greeting: Hello, world!
quoted: 'must be a string'
multiline: |
  line one
  line two

!!seq — Sequence

Tag: tag:yaml.org,2002:seq | Kind: sequence

Block or flow sequences become JavaScript arrays.

colors:
  - red
  - green
  - blue
inline: [a, b, c]

!!map — Mapping

Tag: tag:yaml.org,2002:map | Kind: mapping

Block or flow mappings become plain JavaScript objects.

person:
  name: Ada
  age: 36
inline: { x: 1, y: 2 }

!!null — Null

Tag: tag:yaml.org,2002:null | Kind: scalar

null, ~, and empty scalars all resolve to JavaScript null.

a: null
b: ~
c:       # empty — also null

Dump styles: lowercase (default), uppercase, camelcase, canonical (~), empty.

!!bool — Boolean

Tag: tag:yaml.org,2002:bool | Kind: scalar

true/false (case-insensitive) resolve to JavaScript booleans.

enabled: true
disabled: false

Dump styles: lowercase (default), uppercase, camelcase.

!!int — Integer

Tag: tag:yaml.org,2002:int | Kind: scalar

Decimal, hexadecimal (0x), octal (0o), and binary (0b) integer literals.

decimal:     42
hexadecimal: 0xFF
octal:       0o17
binary:      0b1010

Dump styles: decimal (default), hexadecimal, octal, binary.

dump({ n: 255 }, { styles: { '!!int': 'hex' } });
// n: 0xFF

!!float — Float

Tag: tag:yaml.org,2002:float | Kind: scalar

Floating-point numbers including special values.

pi:           3.14159
scientific:   6.022e23
infinity:     .inf
neg_infinity: -.inf
not_a_number: .nan

!!binary — Binary

Tag: tag:yaml.org,2002:binary | Kind: scalar

Base64-encoded content decoded to a Node.js Buffer.

icon: !!binary |
  iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAA
  DUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==
const { icon } = load(yaml);
// icon is a Buffer

!!timestamp — Timestamp

Tag: tag:yaml.org,2002:timestamp | Kind: scalar

ISO 8601 date and datetime strings resolve to JavaScript Date objects.

date:     2024-01-15
datetime: 2024-01-15T09:30:00Z
with_tz:  2024-01-15 09:30:00 +05:30
const { date } = load('date: 2024-01-15');
// date instanceof Date === true

!!merge — Merge Key

Tag: tag:yaml.org,2002:merge | Kind: scalar

The << merge key copies keys from another mapping into the current one, without overwriting existing keys.

defaults: &defaults
  color: blue
  size: medium

button:
  <<: *defaults
  color: red     # overrides the merged value
# result: { color: 'red', size: 'medium' }

Multiple sources can be merged with a sequence:

combined:
  <<: [*defaults, *extras]

!!omap — Ordered Map

Tag: tag:yaml.org,2002:omap | Kind: sequence

An ordered sequence of single-key mappings. Useful when insertion order must be preserved and keys must be unique.

ranked: !!omap
  - gold: 1
  - silver: 2
  - bronze: 3

Resolves to the array of single-key objects as-is (insertion order is preserved by the array).

!!pairs — Pairs

Tag: tag:yaml.org,2002:pairs | Kind: sequence

Like !!omap but duplicate keys are allowed. Resolves to an array of [key, value] tuples.

entries: !!pairs
  - a: 1
  - b: 2
  - a: 3
// [['a', 1], ['b', 2], ['a', 3]]

!!set — Set

Tag: tag:yaml.org,2002:set | Kind: mapping

A mapping where all values are null, representing a set of unique keys.

languages: !!set
  TypeScript: ~
  Rust: ~
  Go: ~
// { TypeScript: null, Rust: null, Go: null }

YAMLException

All parse and serialization errors are instances of YAMLException.

class YAMLException extends Error {
  name: 'YAMLException';
  reason: string;    // human-readable error description
  mark: Mark | null; // source location, or null for non-parse errors
}

class Mark {
  name: string | null; // filename, if provided via LoadOptions.filename
  buffer: string;      // full input string
  position: number;    // byte offset
  line: number;        // 0-based line number
  column: number;      // 0-based column number
  getSnippet(): string | null; // source excerpt with caret
  toString(compact?: boolean): string;
}
import { load, YAMLException } from '@agentine/yamlite';

try {
  load(': invalid');
} catch (e) {
  if (e instanceof YAMLException) {
    console.error(e.reason);         // short description
    console.error(e.mark?.line);     // 0-based line number
    console.error(e.mark?.column);   // 0-based column number
    console.error(e.message);        // full formatted message with snippet
  }
}

Error messages include a source snippet with a caret pointing at the problematic position:

YAMLException: unexpected token STREAM-END in "config.yaml" at line 3, column 1:
    key: [unclosed
        ^

Deprecated Functions

The js-yaml v3 safe-prefixed functions are retained as stubs that throw a migration error:

safeLoad();    // throws: Function "safeLoad" is removed. Use "load" instead — it is now safe by default.
safeLoadAll(); // throws: Function "safeLoadAll" is removed. Use "loadAll" instead — it is now safe by default.
safeDump();    // throws: Function "safeDump" is removed. Use "dump" instead — it is now safe by default.

CLI Tool

yamlite installs a yamlite binary that parses a YAML file and prints its JSON representation to stdout.

yamlite <filename> [options]

| Flag | Description | |------|-------------| | -h, --help | Show help message | | -t, --trace | Print full stack trace on error |

# Parse and pretty-print as JSON
yamlite config.yaml

# Show source location on error
yamlite bad.yaml --trace

Exit code is 0 on success, 1 on error.

Security

yamlite includes built-in protection against denial-of-service via deeply nested or alias-heavy documents.

| Option | Default | Purpose | |--------|---------|---------| | maxDepth | 1000 | Throws when nesting exceeds this level | | maxAliases | 100 | Throws when alias dereferences within a single document exceed this count |

Tune these per-call to match your threat model:

load(untrustedInput, {
  maxDepth: 20,
  maxAliases: 10,
});

Circular object references in dump() are detected and always throw regardless of options.

Migration Guide

From js-yaml v4

yamlite's API is 100% compatible with js-yaml v4. Change the import and you are done:

// Before
import yaml from 'js-yaml';
const { load, dump } = require('js-yaml');

// After
import yaml from '@agentine/yamlite';
const { load, dump } = require('@agentine/yamlite');

From js-yaml v3

The safeLoad, safeLoadAll, and safeDump functions were removed in js-yaml v4. In yamlite they throw a descriptive error pointing you to the replacement. Replace them as follows:

| v3 | v4 / yamlite | |----|--------------| | safeLoad(str) | load(str) | | safeLoadAll(str, fn) | loadAll(str, fn) | | safeDump(obj) | dump(obj) |

The load, loadAll, and dump functions are safe by default — they do not execute arbitrary code.

License

MIT