{"_id":"@agentine/yamlite","name":"@agentine/yamlite","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@agentine/yamlite","version":"0.1.0","description":"Drop-in replacement for js-yaml — TypeScript-first YAML 1.2 parser and serializer","main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"bin":{"yamlite":"dist/cli.mjs"},"scripts":{"build":"tsup","test":"vitest run","test:watch":"vitest"},"repository":{"type":"git","url":"git+https://github.com/agentine/yamlite.git"},"license":"MIT","engines":{"node":">=16"},"devDependencies":{"@types/node":"^25.5.0","tsup":"^8.0.0","typescript":"^5.0.0","vitest":"^3.0.0"},"_id":"@agentine/yamlite@0.1.0","gitHead":"21abaff7d2ceae0feaca0b06369877acf3f4d93a","bugs":{"url":"https://github.com/agentine/yamlite/issues"},"homepage":"https://github.com/agentine/yamlite#readme","_nodeVersion":"22.22.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-MUmx+aSiZyAp9WMskhbxaPOIhqojXrGzD4z6KUy7tESeGwEBBttNFba+8OsrFpy/cqVJAMZ+TmylzsFnsGbo5A==","shasum":"6e64eb83114be280e84e7e9404477beebe697f69","tarball":"https://registry.npmjs.org/@agentine/yamlite/-/yamlite-0.1.0.tgz","fileCount":11,"unpackedSize":228197,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@agentine%2fyamlite@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDgx6QSuVMZsIjwmTj4AMAi6S3ZlVCR/WQZLCkTzCVZzAiBQRFw3bswAGCk7fB+VPy8ElnuiHSILsT28r7EcLKx0tQ=="}]},"_npmUser":{"name":"mtingers","email":"matthingersoll@gmail.com"},"directories":{},"maintainers":[{"name":"mtingers","email":"matthingersoll@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/yamlite_0.1.0_1773417108732_0.1828190270193666"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-13T15:51:48.588Z","0.1.0":"2026-03-13T15:51:48.911Z","modified":"2026-03-13T15:51:49.408Z"},"maintainers":[{"name":"mtingers","email":"matthingersoll@gmail.com"}],"description":"Drop-in replacement for js-yaml — TypeScript-first YAML 1.2 parser and serializer","homepage":"https://github.com/agentine/yamlite#readme","repository":{"type":"git","url":"git+https://github.com/agentine/yamlite.git"},"bugs":{"url":"https://github.com/agentine/yamlite/issues"},"license":"MIT","readme":"# @agentine/yamlite\n\nDrop-in replacement for js-yaml — TypeScript-first YAML 1.2 parser and serializer with zero dependencies.\n\n## Why yamlite?\n\n[js-yaml](https://github.com/nodeca/js-yaml) is one of the most downloaded packages in the npm ecosystem (161 million weekly downloads), but it has accumulated significant maintenance debt:\n\n- **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)\n- **55 open issues, 15 open PRs** with no active triage\n- **Written in ES5-era JavaScript** — no native TypeScript, no ESM\n- **Types maintained separately** on DefinitelyTyped, meaning they can drift from the implementation\n- **No native ESM** — requires workarounds for modern Node.js projects\n\nyamlite fixes all of this:\n\n- Written in TypeScript with bundled declarations — no separate `@types/` package needed\n- Native ESM with a proper dual CJS/ESM package (`exports` field)\n- **Zero runtime dependencies** — nothing to audit, nothing to break\n- Node.js 16+ required\n- 100% compatible with the js-yaml v4 public API\n\n## Installation\n\n```sh\nnpm install @agentine/yamlite\n```\n\n## Importing\n\n**ESM:**\n\n```js\nimport yaml from '@agentine/yamlite';\n// or named:\nimport { load, dump, loadAll } from '@agentine/yamlite';\n```\n\n**CJS:**\n\n```js\nconst yaml = require('@agentine/yamlite');\n// or named:\nconst { load, dump, loadAll } = require('@agentine/yamlite');\n```\n\n## Quick Start\n\n```js\nimport { load, dump } from '@agentine/yamlite';\n\n// Parse YAML → JavaScript\nconst config = load(`\nname: Acme\nversion: 3\nfeatures:\n  - auth\n  - logging\n`);\n// { name: 'Acme', version: 3, features: ['auth', 'logging'] }\n\n// Serialize JavaScript → YAML\nconst yaml = dump({ name: 'Acme', version: 3, features: ['auth', 'logging'] });\n// name: Acme\n// version: 3\n// features:\n//   - auth\n//   - logging\n```\n\n## Core API\n\n### `load(input, options?)`\n\nParse a single YAML document from a string. Throws `YAMLException` if the input contains more than one document.\n\n```ts\nfunction load(input: string, options?: LoadOptions): unknown\n```\n\n```js\nconst doc = load('answer: 42'); // { answer: 42 }\n```\n\nReturns `undefined` for empty input.\n\n### `loadAll(input, iterator?, options?)`\n\nParse 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[]`.\n\n```ts\nfunction loadAll(\n  input: string,\n  iterator?: (doc: unknown) => void,\n  options?: LoadOptions,\n): unknown[] | void\n```\n\n```js\n// Collect all documents\nconst docs = loadAll('---\\na: 1\\n---\\nb: 2');\n// [{ a: 1 }, { b: 2 }]\n\n// Stream documents via iterator\nloadAll('---\\na: 1\\n---\\nb: 2', (doc) => {\n  console.log(doc);\n});\n\n// Options without an iterator\nconst docs2 = loadAll('---\\na: 1', { schema: CORE_SCHEMA });\n```\n\n### `dump(input, options?)`\n\nSerialize a JavaScript value to a YAML string. Always appends a trailing newline.\n\n```ts\nfunction dump(input: unknown, options?: DumpOptions): string\n```\n\n```js\ndump({ a: 1, b: [2, 3] });\n// a: 1\n// b:\n//   - 2\n//   - 3\n```\n\n## LoadOptions\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `filename` | `string` | — | Used in error and warning messages to identify the source |\n| `schema` | `Schema` | `DEFAULT_SCHEMA` | Schema that controls type resolution |\n| `onWarning` | `(w: YAMLException) => void` | — | Called for non-fatal warnings (e.g., duplicate keys) |\n| `json` | `boolean` | `false` | JSON compatibility mode — silences duplicate-key warnings and accepts JSON-specific values |\n| `listener` | `(event: 'open' \\| 'close', state: object) => void` | — | Called on every parsed node open/close |\n| `maxDepth` | `number` | `1000` | Maximum nesting depth before throwing |\n| `maxAliases` | `number` | `100` | Maximum number of alias dereferences before throwing |\n\n```js\nconst doc = load(yamlString, {\n  filename: 'config.yaml',\n  onWarning: (w) => console.warn(w.message),\n  maxDepth: 100,\n  maxAliases: 50,\n});\n```\n\n## DumpOptions\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `indent` | `number` | `2` | Number of spaces per indentation level (minimum 1) |\n| `noArrayIndent` | `boolean` | `false` | Do not indent array items relative to their parent key |\n| `skipInvalid` | `boolean` | `false` | Silently skip values that cannot be serialized (functions, undefined) instead of throwing |\n| `flowLevel` | `number` | `-1` | Nesting level at which to switch to flow style; `-1` means block everywhere |\n| `styles` | `Record<string, string>` | `{}` | Per-type style overrides, e.g. `{ '!!null': 'canonical', '!!int': 'hex' }` |\n| `schema` | `Schema` | `DEFAULT_SCHEMA` | Schema used for type representation |\n| `sortKeys` | `boolean \\| ((a, b) => number)` | `false` | Sort mapping keys alphabetically, or supply a comparator |\n| `lineWidth` | `number` | `80` | Target line width for wrapping scalars; `-1` disables wrapping |\n| `noRefs` | `boolean` | `false` | Disable anchor/alias generation for repeated object references |\n| `noCompatMode` | `boolean` | `false` | Do not quote YAML 1.1 boolean words (`yes`/`no`/`on`/`off`) |\n| `condenseFlow` | `boolean` | `false` | Remove spaces inside flow-style sequences and mappings |\n| `quotingType` | `\"'\" \\| '\"'` | `\"'\"` | Preferred quote character for string scalars |\n| `forceQuotes` | `boolean` | `false` | Force quoting for all string scalars |\n| `replacer` | `(key: string, value: unknown) => unknown` | — | Transform values before serialization, like `JSON.stringify`'s replacer |\n\n```js\ndump(data, {\n  indent: 4,\n  sortKeys: true,\n  lineWidth: 120,\n  quotingType: '\"',\n});\n```\n\n## Schema System\n\nyamlite ships four built-in schemas, each a superset of the previous:\n\n| Schema | Tags |\n|--------|------|\n| `FAILSAFE_SCHEMA` | `!!str`, `!!seq`, `!!map` |\n| `JSON_SCHEMA` | + `!!null`, `!!bool`, `!!int`, `!!float` |\n| `CORE_SCHEMA` | + implicit resolution (hex/octal ints, `true`/`false`/`null` aliases) |\n| `DEFAULT_SCHEMA` | + `!!binary`, `!!omap`, `!!pairs`, `!!set`, `!!timestamp`, `!!merge` |\n\nThe default for both `load` and `dump` is `DEFAULT_SCHEMA`.\n\n### Extending a Schema\n\n`Schema.extend()` creates a new schema that inherits all types from the parent and adds your custom types. The original schema is not modified.\n\n```ts\nschema.extend(type: Type): Schema\nschema.extend(types: Type[]): Schema\nschema.extend({ implicit?: Type[], explicit?: Type[] }): Schema\n```\n\n```js\nimport { DEFAULT_SCHEMA, Type } from '@agentine/yamlite';\n\nconst PointType = new Type('!point', {\n  kind: 'sequence',\n  resolve: (data) => Array.isArray(data) && data.length === 2,\n  construct: ([x, y]) => ({ x, y }),\n});\n\nconst mySchema = DEFAULT_SCHEMA.extend(PointType);\n\nload('loc: !point [10, 20]', { schema: mySchema });\n// { loc: { x: 10, y: 20 } }\n```\n\nImplicit types are tried automatically during tag resolution; explicit types require a YAML tag (`!point`) in the document.\n\n## Type System\n\n### `Type` class\n\n```ts\nclass Type {\n  constructor(tag: string, options?: TypeOptions)\n}\n```\n\n#### TypeOptions\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `kind` | `'scalar' \\| 'sequence' \\| 'mapping'` | **Required.** The YAML node kind this type handles |\n| `resolve` | `(data: unknown) => boolean` | Return `true` if this type can represent the given raw value |\n| `construct` | `(data: unknown) => unknown` | Convert the raw YAML value to a JavaScript value |\n| `instanceOf` | `Function` | JS class whose instances this type serializes |\n| `predicate` | `(data: unknown) => boolean` | Alternative to `instanceOf` for matching JS values during dump |\n| `represent` | `((data, style?) => string) \\| Record<string, (data) => string>` | Serialize a JS value to a YAML string, optionally per named style |\n| `representName` | `(data: unknown) => string` | Override the tag name used during serialization |\n| `defaultStyle` | `string` | Which style key from `represent` to use when none is specified |\n| `styleAliases` | `Record<string, string[]>` | Map alias names to canonical style names |\n| `multi` | `boolean` | Allow multiple types with the same tag in a schema |\n\n### Custom type example\n\n```js\nimport { Type, DEFAULT_SCHEMA } from '@agentine/yamlite';\n\n// Represent JS RegExp objects as !!js/regexp scalars\nconst RegExpType = new Type('tag:yaml.org,2002:js/regexp', {\n  kind: 'scalar',\n  instanceOf: RegExp,\n  predicate: (data) => data instanceof RegExp,\n  represent: (data) => data.toString(),\n  resolve: (data) => typeof data === 'string' && data.startsWith('/'),\n  construct: (data) => {\n    const m = data.match(/^\\/(.*)\\/([gimsuy]*)$/);\n    return m ? new RegExp(m[1], m[2]) : new RegExp(data);\n  },\n});\n\nconst schema = DEFAULT_SCHEMA.extend(RegExpType);\nconst doc = load('pattern: /hello/i', { schema });\n// { pattern: /hello/i }\n```\n\n## Built-in Types\n\n### `!!str` — String\n\nTag: `tag:yaml.org,2002:str` | Kind: scalar\n\nAny YAML scalar that is not resolved by another implicit type becomes a string.\n\n```yaml\ngreeting: Hello, world!\nquoted: 'must be a string'\nmultiline: |\n  line one\n  line two\n```\n\n### `!!seq` — Sequence\n\nTag: `tag:yaml.org,2002:seq` | Kind: sequence\n\nBlock or flow sequences become JavaScript arrays.\n\n```yaml\ncolors:\n  - red\n  - green\n  - blue\ninline: [a, b, c]\n```\n\n### `!!map` — Mapping\n\nTag: `tag:yaml.org,2002:map` | Kind: mapping\n\nBlock or flow mappings become plain JavaScript objects.\n\n```yaml\nperson:\n  name: Ada\n  age: 36\ninline: { x: 1, y: 2 }\n```\n\n### `!!null` — Null\n\nTag: `tag:yaml.org,2002:null` | Kind: scalar\n\n`null`, `~`, and empty scalars all resolve to JavaScript `null`.\n\n```yaml\na: null\nb: ~\nc:       # empty — also null\n```\n\nDump styles: `lowercase` (default), `uppercase`, `camelcase`, `canonical` (`~`), `empty`.\n\n### `!!bool` — Boolean\n\nTag: `tag:yaml.org,2002:bool` | Kind: scalar\n\n`true`/`false` (case-insensitive) resolve to JavaScript booleans.\n\n```yaml\nenabled: true\ndisabled: false\n```\n\nDump styles: `lowercase` (default), `uppercase`, `camelcase`.\n\n### `!!int` — Integer\n\nTag: `tag:yaml.org,2002:int` | Kind: scalar\n\nDecimal, hexadecimal (`0x`), octal (`0o`), and binary (`0b`) integer literals.\n\n```yaml\ndecimal:     42\nhexadecimal: 0xFF\noctal:       0o17\nbinary:      0b1010\n```\n\nDump styles: `decimal` (default), `hexadecimal`, `octal`, `binary`.\n\n```js\ndump({ n: 255 }, { styles: { '!!int': 'hex' } });\n// n: 0xFF\n```\n\n### `!!float` — Float\n\nTag: `tag:yaml.org,2002:float` | Kind: scalar\n\nFloating-point numbers including special values.\n\n```yaml\npi:           3.14159\nscientific:   6.022e23\ninfinity:     .inf\nneg_infinity: -.inf\nnot_a_number: .nan\n```\n\n### `!!binary` — Binary\n\nTag: `tag:yaml.org,2002:binary` | Kind: scalar\n\nBase64-encoded content decoded to a Node.js `Buffer`.\n\n```yaml\nicon: !!binary |\n  iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAA\n  DUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==\n```\n\n```js\nconst { icon } = load(yaml);\n// icon is a Buffer\n```\n\n### `!!timestamp` — Timestamp\n\nTag: `tag:yaml.org,2002:timestamp` | Kind: scalar\n\nISO 8601 date and datetime strings resolve to JavaScript `Date` objects.\n\n```yaml\ndate:     2024-01-15\ndatetime: 2024-01-15T09:30:00Z\nwith_tz:  2024-01-15 09:30:00 +05:30\n```\n\n```js\nconst { date } = load('date: 2024-01-15');\n// date instanceof Date === true\n```\n\n### `!!merge` — Merge Key\n\nTag: `tag:yaml.org,2002:merge` | Kind: scalar\n\nThe `<<` merge key copies keys from another mapping into the current one, without overwriting existing keys.\n\n```yaml\ndefaults: &defaults\n  color: blue\n  size: medium\n\nbutton:\n  <<: *defaults\n  color: red     # overrides the merged value\n# result: { color: 'red', size: 'medium' }\n```\n\nMultiple sources can be merged with a sequence:\n\n```yaml\ncombined:\n  <<: [*defaults, *extras]\n```\n\n### `!!omap` — Ordered Map\n\nTag: `tag:yaml.org,2002:omap` | Kind: sequence\n\nAn ordered sequence of single-key mappings. Useful when insertion order must be preserved and keys must be unique.\n\n```yaml\nranked: !!omap\n  - gold: 1\n  - silver: 2\n  - bronze: 3\n```\n\nResolves to the array of single-key objects as-is (insertion order is preserved by the array).\n\n### `!!pairs` — Pairs\n\nTag: `tag:yaml.org,2002:pairs` | Kind: sequence\n\nLike `!!omap` but duplicate keys are allowed. Resolves to an array of `[key, value]` tuples.\n\n```yaml\nentries: !!pairs\n  - a: 1\n  - b: 2\n  - a: 3\n```\n\n```js\n// [['a', 1], ['b', 2], ['a', 3]]\n```\n\n### `!!set` — Set\n\nTag: `tag:yaml.org,2002:set` | Kind: mapping\n\nA mapping where all values are `null`, representing a set of unique keys.\n\n```yaml\nlanguages: !!set\n  TypeScript: ~\n  Rust: ~\n  Go: ~\n```\n\n```js\n// { TypeScript: null, Rust: null, Go: null }\n```\n\n## YAMLException\n\nAll parse and serialization errors are instances of `YAMLException`.\n\n```ts\nclass YAMLException extends Error {\n  name: 'YAMLException';\n  reason: string;    // human-readable error description\n  mark: Mark | null; // source location, or null for non-parse errors\n}\n\nclass Mark {\n  name: string | null; // filename, if provided via LoadOptions.filename\n  buffer: string;      // full input string\n  position: number;    // byte offset\n  line: number;        // 0-based line number\n  column: number;      // 0-based column number\n  getSnippet(): string | null; // source excerpt with caret\n  toString(compact?: boolean): string;\n}\n```\n\n```js\nimport { load, YAMLException } from '@agentine/yamlite';\n\ntry {\n  load(': invalid');\n} catch (e) {\n  if (e instanceof YAMLException) {\n    console.error(e.reason);         // short description\n    console.error(e.mark?.line);     // 0-based line number\n    console.error(e.mark?.column);   // 0-based column number\n    console.error(e.message);        // full formatted message with snippet\n  }\n}\n```\n\nError messages include a source snippet with a caret pointing at the problematic position:\n\n```\nYAMLException: unexpected token STREAM-END in \"config.yaml\" at line 3, column 1:\n    key: [unclosed\n        ^\n```\n\n## Deprecated Functions\n\nThe js-yaml v3 safe-prefixed functions are retained as stubs that throw a migration error:\n\n```js\nsafeLoad();    // throws: Function \"safeLoad\" is removed. Use \"load\" instead — it is now safe by default.\nsafeLoadAll(); // throws: Function \"safeLoadAll\" is removed. Use \"loadAll\" instead — it is now safe by default.\nsafeDump();    // throws: Function \"safeDump\" is removed. Use \"dump\" instead — it is now safe by default.\n```\n\n## CLI Tool\n\nyamlite installs a `yamlite` binary that parses a YAML file and prints its JSON representation to stdout.\n\n```sh\nyamlite <filename> [options]\n```\n\n| Flag | Description |\n|------|-------------|\n| `-h`, `--help` | Show help message |\n| `-t`, `--trace` | Print full stack trace on error |\n\n```sh\n# Parse and pretty-print as JSON\nyamlite config.yaml\n\n# Show source location on error\nyamlite bad.yaml --trace\n```\n\nExit code is `0` on success, `1` on error.\n\n## Security\n\nyamlite includes built-in protection against denial-of-service via deeply nested or alias-heavy documents.\n\n| Option | Default | Purpose |\n|--------|---------|---------|\n| `maxDepth` | `1000` | Throws when nesting exceeds this level |\n| `maxAliases` | `100` | Throws when alias dereferences within a single document exceed this count |\n\nTune these per-call to match your threat model:\n\n```js\nload(untrustedInput, {\n  maxDepth: 20,\n  maxAliases: 10,\n});\n```\n\nCircular object references in `dump()` are detected and always throw regardless of options.\n\n## Migration Guide\n\n### From js-yaml v4\n\nyamlite's API is 100% compatible with js-yaml v4. Change the import and you are done:\n\n```js\n// Before\nimport yaml from 'js-yaml';\nconst { load, dump } = require('js-yaml');\n\n// After\nimport yaml from '@agentine/yamlite';\nconst { load, dump } = require('@agentine/yamlite');\n```\n\n### From js-yaml v3\n\nThe `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:\n\n| v3 | v4 / yamlite |\n|----|--------------|\n| `safeLoad(str)` | `load(str)` |\n| `safeLoadAll(str, fn)` | `loadAll(str, fn)` |\n| `safeDump(obj)` | `dump(obj)` |\n\nThe `load`, `loadAll`, and `dump` functions are safe by default — they do not execute arbitrary code.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-4f12589237bfea118323eb5fe1ba0fb4"}