Skip to content
4 changes: 2 additions & 2 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"typescript": "^6.0.3"
},
"dependencies": {
"js-yaml": "^4.1.1",
"js-yaml": "^5.2.0",
"proper-lockfile": "^4.1.2",
"yargs": "^18.0.0"
}
Expand Down
21 changes: 13 additions & 8 deletions src/yaml/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* - one import site to update if we ever want to swap the library.
*/

import { dump, load } from "js-yaml";
import { dump, load, YAMLException } from "js-yaml";

/** The value kinds we accept. */
export type YamlValue = string | number | boolean | null | YamlValue[] | YamlMap;
Expand All @@ -20,14 +20,19 @@ export type YamlMap = { [key: string]: YamlValue };
/** Parse a YAML document. Throws on malformed input. */
export function parseYaml(source: string): YamlValue {
// `load` already rejects multi-document input (use `loadAll` for that) and
// in js-yaml v4 it uses the DEFAULT_SCHEMA which is safe (no !!js/function,
// uses the DEFAULT_SCHEMA, which is safe (no !!js/function,
// no !!js/regexp, no !!js/undefined).
const value = load(source);
// js-yaml returns `undefined` for an empty document; we normalize to `null`
// so callers never have to branch between the two (YAML itself treats them
// the same — `~`, `null`, and an empty document all mean "no value").
if (value === undefined) {
return null;
let value: unknown;
try {
value = load(source);
} catch (err) {
if (
err instanceof YAMLException &&
err.reason === "expected a document, but the input is empty"
) {
return null;
}
throw err;
}
return value as YamlValue;
}
Expand Down