JavaScript API reference
The complete JavaScript / TypeScript surface that
noyalib-wasm exposes after a wasm-pack build. Two surfaces:
the simple API (functional, parse / stringify / merge)
and the document API (WasmDocument, lossless edits with
byte-faithful round-trip).
For build tool / bundler integration see
bundling.md.
Install
npm install noyalib-wasm
The package ships ESM, CJS, and web targets in one bundle;
modern bundlers pick the right one automatically.
Simple API
parse(yaml: string): unknown
Parse YAML to a plain JS object / array / scalar. Throws on parse error.
import { parse } from "noyalib-wasm";
const cfg = parse(`
name: noyalib
port: 8080
features: [a, b, c]
`);
// cfg.name === "noyalib"
// cfg.port === 8080
// cfg.features === ["a", "b", "c"]
stringify(value: unknown): string
Serialise a JS value back to a YAML string. The output is
canonical noyalib YAML — block style for non-leaf collections,
auto-quoted scalars where ambiguity would otherwise surface.
Throws if the value contains JS-specific shapes the YAML data
model doesn’t support (functions, symbols), if it contains itself
(a cycle), if it nests arrays, objects or Maps deeper than 128
levels (the parser’s default depth limit), or if it has more than
1,000,000 elements counting shared references once per use.
import { stringify } from "noyalib-wasm";
const yaml = stringify({ name: "noyalib", port: 8080 });
// "name: noyalib\nport: 8080\n"
validateJson(yaml: string): boolean
Returns true if the YAML parses successfully and contains only
JSON-compatible values (no tags, no anchors, no non-string
mapping keys). Used for “is this YAML safe to round-trip through
JSON.stringify?” checks.
parseJson(yaml: string): unknown
Like parse, but the result is the JSON data model: every tag is
stripped recursively, so !!binary R0lG... is the string and
!local [1] is the array. This is what the YAML test suite’s expected
JSON is, and what a JSON consumer expects; parse keeps tags as
{ "!tag": value } for callers that need them. Null values are JS
null in both.
getPath(yaml: string, path: string): unknown | null
Fetch a single value from a YAML string by dotted path. Returns
null if the path doesn’t exist.
import { getPath } from "noyalib-wasm";
const host = getPath(yamlString, "server.host");
const firstItem = getPath(yamlString, "items[0].name");
merge(base: string, override: string): string
Deep-merge two YAML documents — the override values win, but both documents’ comments and structure are preserved where possible.
import { merge } from "noyalib-wasm";
const merged = merge(
"name: app\nport: 8080\n",
"port: 9090\nworkers: 4\n"
);
// "name: app\nport: 9090\nworkers: 4\n"
Document API
class WasmDocument
A YAML document with byte-faithful source preservation and
path-targeted edits. The class wraps noyalib::cst::Document
from the Rust core, so to_string() after no edits returns the
input bytes exactly. Edits rewrite only the touched span.
new WasmDocument(yaml: string): WasmDocument
Parse a YAML string into a Document. Throws on parse error.
import { WasmDocument } from "noyalib-wasm";
const doc = new WasmDocument(`
# Production config
server:
host: api.example.com # public-facing
port: 8080
`);
doc.toString(): string
Re-emit the document as a string. Byte-identical to the input if no edits were made — including comments, whitespace, and trailing newlines.
doc.get(path: string): unknown | null
Read the parsed value at a dotted path. Returns null if the
path doesn’t exist.
const port = doc.get("server.port"); // 8080
const host = doc.get("server.host"); // "api.example.com"
const missing = doc.get("server.missing"); // null
doc.getSource(path: string): string | null
Read the raw source slice for the value at a dotted path — no re-quoting, no canonicalisation. Useful when you need to know exactly what the user typed.
const raw = doc.getSource("server.host");
// "api.example.com" (the bytes from the source, including any quoting)
doc.spanAt(path: string): { start: number; end: number } | null
Return the byte range [start, end) of the value at a dotted
path within the source string. Useful for editor integrations
that need to highlight the value the cursor is over.
const span = doc.spanAt("server.host");
// { start: 38, end: 53 }
doc.set(path: string, fragment: string): void
Set the value at a dotted path using a YAML fragment string. The fragment must parse as valid YAML in the target position; the document is left unchanged on parse error. A fragment nested deeper than 128 levels is refused before it is parsed into the document.
doc.set("server.port", "9090");
doc.set("server.host", '"new-api.example.com"');
doc.set("features", "[parse, emit, validate]");
After doc.toString(), only the bytes for the changed value
have moved — comments, blank lines, indent style, sibling
entries are byte-identical.
doc.setValue(path: string, value: unknown): void
Set the value at a dotted path using a JS object. Internally
serialises the JS value through noyalib::Value and applies the
result. Equivalent to doc.set(path, stringify(value)) but
slightly more direct, with the same limits as stringify.
doc.setValue("server", {
host: "api.example.com",
port: 9090,
tls: { enabled: true }
});
doc.replaceSpan(start: number, end: number, replacement: string): void
Replace the bytes in [start, end) with replacement. The
lower-level escape hatch — used when you have a span from
spanAt and want to do something the structured API doesn’t
cover. The edited document must still parse: an edit that leaves
invalid YAML, or YAML nested deeper than 128 levels (for example a
# replaced so a commented-out run of brackets becomes structure),
throws and leaves the document unchanged.
doc.commentsAt(path: string): { before: string[]; inline: string | null }
Read the YAML comments associated with the node at path.
Returns the leading-comments array (the # ... lines
immediately above the node) and the trailing inline comment
(the # ... on the same line as the value), if any. This is
the demo that motivates the entire CST architecture — comments
survive the round-trip and are queryable.
const { before, inline } = doc.commentsAt("server.host");
// before: ["# public-facing"] (depending on layout)
// inline: " public-facing" (if there's a same-line comment)
TypeScript types
The package ships full .d.ts declarations generated from the
wasm-bindgen surface. Editor autocompletion works out of the box
in any TypeScript project.
import type { WasmDocument } from "noyalib-wasm";
function bumpVersion(yamlSource: string, newVersion: string): string {
const doc: WasmDocument = new WasmDocument(yamlSource);
doc.set("version", newVersion);
return doc.toString();
}
Errors
All functions that can fail throw a JS Error with a .message
matching the Rust error’s Display output (e.g.
"YAML parse error at line 3, column 7: …"). The
noyalib::Error variant taxonomy from
the core errors reference is
preserved in the message; structured access to the variant kind
is not currently exposed (file an issue if you need it).
When to use which API
| Use case | API |
|---|---|
| Parse YAML → JS object → done | parse() |
| JS object → YAML string | stringify() |
| Quick value lookup, no edit | getPath(yaml, path) |
| Merge two configs | merge(base, override) |
| Edit a value, preserve comments / formatting | WasmDocument.set |
| Cursor-aware editor integration | WasmDocument.spanAt + replaceSpan |
| Surface comments to the user | WasmDocument.commentsAt |
| Round-trip with byte-faithfulness | new WasmDocument(s).toString() (no edits → identity) |
Related
- Bundling — Vite, Webpack, esbuild, Next.js integration
- Crate README — install + crate-level overview
crates/noyalib-wasm/examples/— runnable JS examples (browser + Node)