mrkeyoor.com_
Wed 23 Sept 02:54 UTC
npmUtilsupdated 22 Sept 2026

@stoplight/yaml review

@stoplight/yaml 4.3.0 parses YAML while retaining the evidence an editor or linter needs: an AST, diagnostics, line offsets, comments, and mappings between JSON paths and zero-based source positions. It also serializes data, resolves anchors, optionally applies merge keys, preserves key order through metadata, and can keep large integers as bigint. Our browser bundle attempt failed in esbuild, so the tested full-package import is a poor fit for client code despite the README's browser claim. Version 4.3.0 added parsing and stringifying of comments; it remains a CommonJS package aimed mainly at Stoplight-style document tooling.

Verdict

@stoplight/yaml 4.3.0 installed in 2.8 seconds with 8 packages and 0 audit findings in our sandbox, but its browser bundle failed in esbuild. Keep it on the Node side for editors and linters that need AST-backed JSON paths, ranges, and diagnostics; use `yaml` or `js-yaml` for ordinary configuration loading.

We installed it

Lab card: what happened when we installed @stoplight/yamlScreenshot of @stoplight/yaml documentation
Install✓ · 2.8s8 packages on disk · 2 MB
ImportESM import works · require() works · CommonJS package
Browsern/acould not be bundled for the browser (Node-only code, most likely)
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does @stoplight/yaml install cleanly?

Yes. In a fresh container with an empty cache, npm install @stoplight/yaml finished in 3 seconds, leaving 8 packages and 2 MB on disk. npm audit reported no known vulnerabilities.

Can @stoplight/yaml run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does @stoplight/yaml work with both ESM and CommonJS?

Yes. Both import '@stoplight/yaml' and require('@stoplight/yaml') worked in Node 22 in our run. The package is published as CommonJS.

Does @stoplight/yaml include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

@stoplight/yaml or yaml: which should you use?

yaml: Use it for YAML 1.2 documents, CST editing, aliases, and modern module packaging. @stoplight/yaml 4.3.0 installed in 2.8 seconds with 8 packages and 0 audit findings in our sandbox, but its browser bundle failed in esbuild.

When should you not use @stoplight/yaml?

You only read trusted config files. yaml or js-yaml gives a simpler parse and stringify surface without Stoplight's location model.

API stability4/5Version 4.3.0 keeps the established `parse`, `parseWithPointers`, path-location helpers, AST types, anchor utilities, and `safeStringify` calls. Its headline change added comment parsing and serialization without replacing the result model. Option defaults still carry risk: merge keys, bigint values, comment attachment, and key-order preservation are disabled unless callers request them explicitly.
Docs3/5The README demonstrates `parseWithPointers`, cursor-to-path lookup, and path-to-location lookup, then links generated TSDoc and GitHub releases. Type declarations expose the complete result and option shapes. Several decision-grade details require reading source or types, including bigint conversion, opt-in merge keys, attached comments, key-order metadata, duplicate-key handling, and string pass-through in `safeStringify`.
Maintenance3/5npm published 4.3.0 on March 4, 2024, and GitHub shows the last push on April 9, 2025. The repository is unarchived with 14 stars and 20 open issues and pull requests. Comment support was a real feature release, yet the CommonJS-only package shape and Node 10.8 engine floor have not been modernized since then.
Ecosystem4/5npm recorded 5,252,603 downloads in the latest completed week. The package's result types align with `@stoplight/types`, and it builds on the separately published `@stoplight/yaml-ast-parser`, which fits Stoplight's API tooling. Outside that family, its path segments, diagnostics, ordered-object metadata, and CommonJS entry are specialized compared with the more conventional `yaml` and `js-yaml` APIs.

Use it if

  • A YAML editor or linter must translate cursor positions into JSON paths and back into source ranges.
  • Syntax problems need structured diagnostics with severities and zero-based positions.
  • One parse must retain ordinary data, the AST, comments, and the line map.
  • The project already uses Stoplight diagnostics and `@stoplight/types` locations.
Skip it if

Setup reality

We installed @stoplight/yaml 4.3.0 in 2.8 seconds in a fresh Node 22 Bookworm sandbox. It left 8 packages and 2 MB on disk. The package has 4 direct dependencies, 0 peer dependencies, 220 KB unpacked, an Apache-2.0 license, and a Node 10.8 floor. npm audit found 0 known vulnerabilities. No native compilation, credential, or config file was required.

The distribution is CommonJS without an exports map. Both require() and ESM import worked on our box, and TypeScript declarations are bundled. esbuild could not create a browser bundle from the package in our test. Treat that failure as a platform warning and prove the exact client entry in your own build before shipping it.

parse() returns only the data from parseWithPointers; its generic is a TypeScript assertion, not schema validation. Editor code should retain the complete result because the AST and line map power path-location conversion. Lines and characters are zero-based. mergeKeys, bigInt, attached comments, and preserved key order are opt-in. Without bigInt: true, large integer nodes can become imprecise Numbers.

Version 4.3.0 can parse and stringify comments, but comments must be attached explicitly during parsing. Ordered keys use symbol-backed metadata, and trapAccess() alters reflective key access. safeStringify() returns a string input unchanged instead of quoting it as one YAML scalar. Add input-size limits and runtime schema checks around untrusted documents.

Patterns

Read a small YAML config parse-yaml-data

import { parse } from '@stoplight/yaml';

const config = parse<{ port: number; debug: boolean }>(`
port: 8080
debug: false
`);
console.log(config.port);

The type argument changes TypeScript's view of the value only; it does not validate `port` or `debug` at runtime.

Inspect a broken document parse-with-diagnostics

import { parseWithPointers } from '@stoplight/yaml';

const result = parseWithPointers('server:
  port: [8080');
for (const diagnostic of result.diagnostics) {
  console.error(diagnostic.message, diagnostic.range.start);
}
console.log(result.data, result.ast, result.lineMap);

Syntax failures commonly appear in `diagnostics`; callers should still catch exceptions around duplicate-key and parser edge cases.

Map a cursor to a JSON path map-position-to-path

const source = 'server:
  port: 8080
';
const result = parseWithPointers(source);
const path = getJsonPathForPosition(result, { line: 1, character: 8 });
console.log(path); // ['server', 'port']

Line 1 here means the second source line because both position fields are zero-based.

Locate a JSON path in source map-path-to-location

const location = getLocationForJsonPath(result, ['server', 'port']);
if (location) {
  console.log(location.range.start, location.range.end);
}

The returned range comes from this result's AST and line map, so do not reuse it after editing the source string.

Preserve an integer beyond Number range preserve-big-integers

const result = parseWithPointers<{ id: bigint }>(
  'id: 9007199254740993',
  { bigInt: true },
);
console.log(result.data?.id === 9007199254740993n);

`bigInt` is off by default; the value 9007199254740993 cannot be represented exactly as a JavaScript Number.

Resolve an anchored defaults mapping resolve-merge-keys

const source = `
defaults: &defaults
  retries: 3
service:
  <<: *defaults
  name: api
`;
const result = parseWithPointers<{ service: { retries: number } }>(
  source,
  { mergeKeys: true },
);
console.log(result.data?.service.retries);

Without `mergeKeys: true`, the parser keeps `<<` as a property rather than copying `retries` into `service`.

Attach comments during parsing attach-comments

const result = parseWithPointers(
  '# service settings
name: api # public name
',
  { attachComments: true },
);
console.log(result.comments);

The comment map is separate from `data` and records placement around the pointed YAML node.

Reflect keys in document order preserve-key-order

import { parseWithPointers, trapAccess } from '@stoplight/yaml';

const result = parseWithPointers<Record<string, number>>(
  'third: 3
first: 1
second: 2',
  { preserveKeyOrder: true },
);
if (result.data) {
  const ordered = trapAccess(result.data);
  console.log(Reflect.ownKeys(ordered));
}

Order lives in symbol metadata. `trapAccess()` affects reflection for this object and does not recursively wrap nested mappings.

Flag a non-string mapping key enforce-json-compatible-yaml

const result = parseWithPointers('1: one
name: api', {
  json: true,
  ignoreDuplicateKeys: false,
});
console.log(result.diagnostics.map(item => item.message));

JSON mode expects string scalar keys. Pass `ignoreDuplicateKeys` explicitly when duplicate behavior matters.

Dump an object without aliases stringify-object

import { safeStringify } from '@stoplight/yaml';

const output = safeStringify(
  { server: { port: 8080 }, features: ['search', 'billing'] },
  { indent: 2, noRefs: true },
);
console.log(output);

`noRefs: true` tells the underlying dumper not to emit aliases for repeated object references.

Pass through YAML text unchanged stringify-string-input

const source = 'name: api
';
const output = safeStringify(source);
console.log(output === source); // true

For a string input, `safeStringify` returns the same bytes instead of emitting a quoted scalar.

Derive a path from one AST node build-node-path

import { buildJsonPath, Kind, parseWithPointers } from '@stoplight/yaml';

const result = parseWithPointers('items:
  - name: first');
if (result.ast?.kind === Kind.MAP) {
  const value = result.ast.mappings[0].value;
  if (value) console.log(buildJsonPath(value));
}

Check the node's `Kind` before reading mapping-only fields such as `mappings` and `value`.

Alternatives

PackageRegistryPick it when
yamlnpmUse it for YAML 1.2 documents, CST editing, aliases, and modern module packaging.
js-yamlnpmUse it for ordinary load and dump work that does not need source-to-path mapping.
@stoplight/yaml-ast-parsernpmUse it when direct AST access is enough and you can build diagnostics and path mapping yourself.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.