@ac-kit/format-yaml 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,69 @@
1
1
  # @ac-kit/format-yaml
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a5c4d66: - **Breaking:** `parseYaml` throws `YamlParseError` instead of a bare
8
+ `Error("parse YAML")`. The parser produces a list of diagnostics, each with a
9
+ code, a character range and a line and column, and all of it was being
10
+ collapsed into one opaque `Error` whose only useful content was its `cause` —
11
+ so a caller reporting a bad config file had to reach through an undocumented
12
+ wrapper, and only ever saw the first problem. `YamlParseError` extends
13
+ `SyntaxError` and carries `diagnostics`, one entry per problem found, with
14
+ `code`, `startOffset`, `endOffset`, `line` and `column`; its message is the
15
+ parser's own, which already names the position, suffixed with a count when
16
+ there is more than one, and `cause` stays set to the first underlying
17
+ diagnostic. Conversion to a plain value still fails as before — an alias bound
18
+ or a reviver throwing is wrapped in `Error("parse YAML", { cause })`, because
19
+ it is not a syntax fault. Code matching on the old `"parse YAML"` message for
20
+ malformed input has to catch `YamlParseError` instead.
21
+ - The alias-expansion bound is now this package's contract, as
22
+ `DEFAULT_YAML_MAX_ALIAS_COUNT`. An anchor referenced from inside another
23
+ anchor expands multiplicatively — the "billion laughs" denial of service — and
24
+ `maxAliasCount` is the only thing between untrusted YAML and an unbounded
25
+ allocation, yet the value in force was whatever `yaml` happened to default to,
26
+ undocumented here and free to change under us. `parseYaml` now passes it
27
+ explicitly and exports it, so the protection is stated rather than inherited,
28
+ and `YamlParseStream` gets the same bound. A caller-supplied `maxAliasCount`
29
+ still wins in either direction: raise it, tighten it, or set `-1` to turn the
30
+ check off. It applies where a document becomes a plain value, so
31
+ `parseYamlDocument` and `parseAllYamlDocuments` do not enforce it — they
32
+ return nodes; pass the constant to the document's own `toJS()` there.
33
+ - Custom tags are writable without depending on `yaml` directly.
34
+ `YamlParseOptions` has always accepted `customTags`, while the package
35
+ exported none of the types that option needs — so anyone defining a tag had to
36
+ add `yaml` to their own dependencies to name a `ScalarTag`, and the package
37
+ advertised a contract it did not hand over. The node, tag and visitor model is
38
+ now re-exported under `Yaml`-prefixed names: `YamlScalarTag`,
39
+ `YamlCollectionTag`, `YamlTags`, `YamlNode`, `YamlDocument`, `YamlScalar`,
40
+ `YamlMap`, `YamlSeq`, `YamlAlias`, `YamlPair`, `YamlSchema`, the `isYaml…`
41
+ guards, `visitYaml` / `visitYamlAsync`, `yamlToJs`, and the context types a
42
+ tag's own callbacks are typed against. The prefix is not decoration: the
43
+ package's entry point is a flat barrel, and bare `Node` and `Document` would
44
+ shadow the DOM globals in the browsers this portable package targets.
45
+ - New `resolveYamlAsyncTags(node)`. A tag whose `resolve` is declared `async`
46
+ hands the composer a `Promise`, which it stores as the scalar's value
47
+ verbatim, so `toJS()` serialises the promise rather than what it settles to.
48
+ Awaiting the tree once, between composing it and reading it, is what makes an
49
+ async tag usable at all.
50
+ - New `addYamlTagDirective(source, handle, prefix)`. A `%TAG` directive is
51
+ per-document and must precede that document's `---`, so a handle cannot be
52
+ injected once into a multi-document stream. Each document is inspected and
53
+ patched on its own, existing directives are joined rather than duplicated, and
54
+ the `---` and `...` markers the grammar then requires are inserted.
55
+ - Dropped the `./file` subpath from `publishConfig.exports`. It pointed at
56
+ `./dist/file.js`, which no `src/file.ts` ever produced, and the development
57
+ `exports` map never declared it, so the published package advertised an entry
58
+ point that threw `ERR_MODULE_NOT_FOUND` on import.
59
+
60
+ ### Patch Changes
61
+
62
+ - Updated dependencies [a5c4d66]
63
+ - Updated dependencies [a5c4d66]
64
+ - @ac-kit/core@0.3.0
65
+ - @ac-kit/format-core@0.1.2
66
+
3
67
  ## 0.1.1
4
68
 
5
69
  ### Patch Changes
package/README.md CHANGED
@@ -23,9 +23,64 @@ for (const document of parseAllYamlDocuments(manifestSource)) {
23
23
  - `parseAllYamlDocuments` — every document in a multi-document stream.
24
24
  - `editYaml` / `createYamlEdits` — change one value, leaving the rest of the
25
25
  source as it was.
26
+ - `addYamlTagDirective` — inject a `%TAG` handle into source text, once per
27
+ document, leaving existing directives and boundaries alone.
28
+ - `resolveYamlAsyncTags` — settle the promises an async custom tag leaves in the
29
+ node tree.
30
+ - `YamlParseError` — malformed input, carrying every diagnostic with its line
31
+ and column.
32
+ - The `yaml` node and tag model under `Yaml`-prefixed names — `YamlScalarTag`,
33
+ `YamlCollectionTag`, `YamlNode`, `YamlDocument`, `YamlScalar`, the
34
+ `isYaml…` guards, `visitYaml` / `visitYamlAsync`, `yamlToJs` — so a custom tag
35
+ needs no direct dependency on `yaml`.
26
36
  - `YamlParseStream`, `YamlPrintStream`, and the document-oriented stream
27
37
  variants — `TransformStream`s over `@ac-kit/format-core`.
28
38
 
39
+ ## Custom tags
40
+
41
+ A tag resolves a value of its own; declaring `resolve` `async` leaves a
42
+ `Promise` sitting in the node tree, which `toJS()` would serialise as-is.
43
+ `resolveYamlAsyncTags` awaits the tree once, between composing it and reading
44
+ it:
45
+
46
+ ```ts
47
+ import {
48
+ parseYamlDocument,
49
+ resolveYamlAsyncTags,
50
+ type YamlScalarTag,
51
+ } from "@ac-kit/format-yaml";
52
+
53
+ const includeTag: YamlScalarTag = {
54
+ tag: "!include",
55
+ resolve: async (path) => await readConfig(path),
56
+ };
57
+
58
+ const document = parseYamlDocument(source, { customTags: [includeTag] });
59
+ await resolveYamlAsyncTags(document);
60
+ document.toJS();
61
+ ```
62
+
63
+ A tag handle has to be declared by a `%TAG` directive before the document that
64
+ uses it, so it cannot be added once to a multi-document file.
65
+ `addYamlTagDirective` patches each document that lacks the handle, inserting the
66
+ `---` and `...` markers the grammar then requires:
67
+
68
+ ```ts
69
+ addYamlTagDirective(source, "!inv!", "tag:example.com,2024:");
70
+ ```
71
+
72
+ ## Alias bounds
73
+
74
+ `parseYaml` caps alias expansion at `DEFAULT_YAML_MAX_ALIAS_COUNT` (100). An
75
+ anchor referenced from inside another anchor expands multiplicatively — the
76
+ "billion laughs" denial of service — and this bound is what keeps untrusted YAML
77
+ from allocating without limit. Pass your own `maxAliasCount` to raise it, lower
78
+ it, or disable the check with `-1`.
79
+
80
+ The bound applies when a document is converted to a plain value, so
81
+ `parseYamlDocument` and `parseAllYamlDocuments` do not enforce it: they hand
82
+ back nodes. Pass `maxAliasCount` to the document's own `toJS()` there.
83
+
29
84
  Portable: no Node.js built-ins, so it runs unchanged in browsers, Deno, Bun and
30
85
  edge runtimes.
31
86
 
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Ensures every document in `source` declares `handle` as a `%TAG` prefix,
3
+ * returning the updated source.
4
+ *
5
+ * A `%TAG` directive is per-document and must precede that document's `---`, so
6
+ * a handle cannot be injected once for a multi-document stream: each document
7
+ * is inspected and patched on its own. A document already declaring the same
8
+ * handle, or the same prefix under a different handle, is left alone.
9
+ *
10
+ * Existing document boundaries, directives and comments are preserved; a `...`
11
+ * end marker is inserted where the YAML grammar requires one before a directive
12
+ * that follows another document. An empty `source` yields a single empty
13
+ * document carrying the directive.
14
+ *
15
+ * Linear in the token count of `source`, over one `yaml.Parser` pass.
16
+ *
17
+ * @param source YAML source text.
18
+ * @param handle Tag handle to ensure, e.g. `"!inv!"`.
19
+ * @param prefix Tag prefix the handle expands to, e.g.
20
+ * `"tag:example.com,2024:"`.
21
+ */
22
+ export declare function addYamlTagDirective(source: string, handle: string, prefix: string): string;
23
+ //# sourceMappingURL=add-tag-directive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-tag-directive.d.ts","sourceRoot":"","sources":["../src/add-tag-directive.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACZ,MAAM,CA4HR"}
@@ -0,0 +1,127 @@
1
+ import * as yaml from "yaml";
2
+ /**
3
+ * Ensures every document in `source` declares `handle` as a `%TAG` prefix,
4
+ * returning the updated source.
5
+ *
6
+ * A `%TAG` directive is per-document and must precede that document's `---`, so
7
+ * a handle cannot be injected once for a multi-document stream: each document
8
+ * is inspected and patched on its own. A document already declaring the same
9
+ * handle, or the same prefix under a different handle, is left alone.
10
+ *
11
+ * Existing document boundaries, directives and comments are preserved; a `...`
12
+ * end marker is inserted where the YAML grammar requires one before a directive
13
+ * that follows another document. An empty `source` yields a single empty
14
+ * document carrying the directive.
15
+ *
16
+ * Linear in the token count of `source`, over one `yaml.Parser` pass.
17
+ *
18
+ * @param source YAML source text.
19
+ * @param handle Tag handle to ensure, e.g. `"!inv!"`.
20
+ * @param prefix Tag prefix the handle expands to, e.g.
21
+ * `"tag:example.com,2024:"`.
22
+ */
23
+ export function addYamlTagDirective(source, handle, prefix) {
24
+ if (source.trim() === "") {
25
+ return `%TAG ${handle} ${prefix}\n---\n`;
26
+ }
27
+ const directiveLine = `%TAG ${handle} ${prefix}\n`;
28
+ const tokens = Array.from(new yaml.Parser().parse(source));
29
+ // Applied in reverse so an earlier insertion cannot shift a later offset.
30
+ const insertions = [];
31
+ for (const [index, token] of tokens.entries()) {
32
+ if (token.type !== "document") {
33
+ continue;
34
+ }
35
+ const docStartToken = token.start.find((item) => item.type === "doc-start");
36
+ const docStartOffset = docStartToken?.offset ?? token.offset;
37
+ let hasHandle = false;
38
+ let hasPrefix = false;
39
+ let lastDirectiveEndOffset = null;
40
+ let foundExplicitDocEnd = false;
41
+ let foundDocBoundary = false;
42
+ let isPreviousDocStartMarkerOnly = false;
43
+ // Walk back to this document's own directives, stopping at its predecessor.
44
+ for (let j = index - 1; j >= 0; j--) {
45
+ const previous = tokens[j];
46
+ if (previous === undefined) {
47
+ break;
48
+ }
49
+ if (previous.type === "doc-end") {
50
+ foundExplicitDocEnd = true;
51
+ foundDocBoundary = true;
52
+ break;
53
+ }
54
+ if (previous.type === "document") {
55
+ foundDocBoundary = true;
56
+ const previousDocStart = previous.start.find((item) => item.type === "doc-start");
57
+ if (previousDocStart !== undefined && !previous.value) {
58
+ isPreviousDocStartMarkerOnly = true;
59
+ }
60
+ break;
61
+ }
62
+ if (previous.type !== "directive" ||
63
+ !previous.source.startsWith("%TAG ")) {
64
+ continue;
65
+ }
66
+ if (previous.source.startsWith(`%TAG ${handle} `)) {
67
+ hasHandle = true;
68
+ }
69
+ if (/^%TAG\s+\S+\s+(.+)$/.exec(previous.source)?.[1] === prefix) {
70
+ hasPrefix = true;
71
+ }
72
+ const directiveEnd = previous.offset + previous.source.length;
73
+ if (lastDirectiveEndOffset === null ||
74
+ directiveEnd > lastDirectiveEndOffset) {
75
+ lastDirectiveEndOffset = directiveEnd;
76
+ }
77
+ }
78
+ if (hasHandle || hasPrefix) {
79
+ continue;
80
+ }
81
+ if (lastDirectiveEndOffset !== null) {
82
+ // Join the existing directive block rather than opening a second one.
83
+ const directiveEnd = lastDirectiveEndOffset;
84
+ const newlinesAfterDirective = token.start.filter((item) => item.type === "newline" &&
85
+ item.offset > directiveEnd &&
86
+ item.offset < docStartOffset);
87
+ let insertOffset = directiveEnd;
88
+ if (source[insertOffset] === "\n") {
89
+ insertOffset++;
90
+ }
91
+ for (const _ of newlinesAfterDirective) {
92
+ if (source[insertOffset] === "\n") {
93
+ insertOffset++;
94
+ }
95
+ }
96
+ insertions.push({ offset: insertOffset, text: directiveLine });
97
+ }
98
+ else if (foundDocBoundary &&
99
+ !foundExplicitDocEnd &&
100
+ !isPreviousDocStartMarkerOnly) {
101
+ // A directive after another document needs an explicit end marker first.
102
+ insertions.push({
103
+ offset: docStartOffset,
104
+ text: `...\n${directiveLine}`,
105
+ });
106
+ }
107
+ else {
108
+ insertions.push({ offset: docStartOffset, text: directiveLine });
109
+ }
110
+ if (docStartToken === undefined) {
111
+ // Directives oblige the document to open with an explicit `---`.
112
+ insertions.push({
113
+ offset: docStartOffset,
114
+ text: docStartOffset >= source.length ? "\n---\n" : "---\n",
115
+ });
116
+ }
117
+ }
118
+ let result = source;
119
+ for (const insertion of insertions.reverse()) {
120
+ result =
121
+ result.slice(0, insertion.offset) +
122
+ insertion.text +
123
+ result.slice(insertion.offset);
124
+ }
125
+ return result;
126
+ }
127
+ //# sourceMappingURL=add-tag-directive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-tag-directive.js","sourceRoot":"","sources":["../src/add-tag-directive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type * as yaml from "yaml";
2
+ /** One parser diagnostic, with where in the source it applies. */
3
+ export type YamlDiagnostic = {
4
+ /** The `yaml` error code, e.g. `BAD_INDENT` or `MISSING_CHAR`. */
5
+ readonly code: string;
6
+ readonly message: string;
7
+ /** Character offsets into the source the diagnostic covers. */
8
+ readonly startOffset: number;
9
+ readonly endOffset: number;
10
+ /** 1-based line, absent when `prettyErrors: false` suppressed line counting. */
11
+ readonly line?: number;
12
+ /** 1-based column, absent under the same condition as {@link line}. */
13
+ readonly column?: number;
14
+ };
15
+ /**
16
+ * Input that is not well-formed YAML, carrying every diagnostic the parser
17
+ * produced rather than only the first.
18
+ */
19
+ export declare class YamlParseError extends SyntaxError {
20
+ readonly diagnostics: readonly YamlDiagnostic[];
21
+ constructor(errors: readonly yaml.YAMLError[]);
22
+ }
23
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,IAAI,MAAM,MAAM,CAAC;AAElC,kEAAkE;AAClE,MAAM,MAAM,cAAc,GAAG;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,gFAAgF;IAChF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;;GAGG;AACH,qBAAa,cAAe,SAAQ,WAAW;IAC9C,QAAQ,CAAC,WAAW,EAAE,SAAS,cAAc,EAAE,CAAC;IAEhD,YAAY,MAAM,EAAE,SAAS,IAAI,CAAC,SAAS,EAAE,EAY5C;CACD"}
package/dist/errors.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Input that is not well-formed YAML, carrying every diagnostic the parser
3
+ * produced rather than only the first.
4
+ */
5
+ export class YamlParseError extends SyntaxError {
6
+ diagnostics;
7
+ constructor(errors) {
8
+ const [first, ...rest] = errors;
9
+ super(first === undefined
10
+ ? "Invalid YAML"
11
+ : rest.length === 0
12
+ ? first.message
13
+ : `${first.message} (and ${rest.length} further error${rest.length === 1 ? "" : "s"})`, { cause: first });
14
+ this.name = "YamlParseError";
15
+ this.diagnostics = errors.map(toDiagnostic_);
16
+ }
17
+ }
18
+ function toDiagnostic_(error) {
19
+ const [startOffset, endOffset] = error.pos;
20
+ const start = error.linePos?.[0];
21
+ return {
22
+ code: error.code,
23
+ message: error.message,
24
+ startOffset,
25
+ endOffset,
26
+ ...(start === undefined ? {} : { line: start.line, column: start.col }),
27
+ };
28
+ }
29
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,MAAM,OAAO,cAAe,SAAQ,WAAW;IACrC,WAAW,CAA4B;IAEhD,YAAY,MAAiC;QAC5C,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC;QAChC,KAAK,CACJ,KAAK,KAAK,SAAS;YAClB,CAAC,CAAC,cAAc;YAChB,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;gBAClB,CAAC,CAAC,KAAK,CAAC,OAAO;gBACf,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,SAAS,IAAI,CAAC,MAAM,iBAAiB,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,EACxF,EAAE,KAAK,EAAE,KAAK,EAAE,CAChB,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC9C,CAAC;CACD;AAED,SAAS,aAAa,CAAC,KAAqB;IAC3C,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC;IAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IACjC,OAAO;QACN,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,WAAW;QACX,SAAS;QACT,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;KACvE,CAAC;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,25 @@
1
+ export * from "./add-tag-directive.js";
1
2
  export * from "./document-parse-stream.js";
2
3
  export * from "./document-print-stream.js";
3
4
  export * from "./documents-parse-stream.js";
4
5
  export * from "./documents-print-stream.js";
5
6
  export * from "./edit.js";
7
+ export * from "./errors.js";
6
8
  export * from "./parse-stream.js";
7
9
  export * from "./parse.js";
8
10
  export * from "./print-stream.js";
9
11
  export * from "./print.js";
12
+ export * from "./resolve-async-tags.js";
13
+ /**
14
+ * The `yaml` node, tag and visitor model, re-exported so a caller can write a
15
+ * custom tag without taking its own dependency on `yaml`.
16
+ *
17
+ * Names are `Yaml`-prefixed rather than kept as upstream. This package's index
18
+ * is a flat `export *`, so a bare `Node`, `Document`, `Scalar` or `Schema`
19
+ * would sit beside `YamlParseStream` and `parseYaml` under names that say
20
+ * nothing about YAML — and `Node` and `Document` are DOM globals, which this
21
+ * package, being portable, is expected to be imported alongside.
22
+ */
23
+ export { isAlias as isYamlAlias, isCollection as isYamlCollection, isDocument as isYamlDocument, isMap as isYamlMap, isNode as isYamlNode, isPair as isYamlPair, isScalar as isYamlScalar, isSeq as isYamlSeq, visit as visitYaml, visitAsync as visitYamlAsync, Alias as YamlAlias, Document as YamlDocument, YAMLMap as YamlMap, Pair as YamlPair, Scalar as YamlScalar, Schema as YamlSchema, YAMLSeq as YamlSeq, type asyncVisitor as YamlAsyncVisitor, type CollectionTag as YamlCollectionTag, type Node as YamlNode, type ParsedNode as YamlParsedNode, type Range as YamlRange, type ScalarTag as YamlScalarTag, type TagId as YamlTagId, type Tags as YamlTags, type visitor as YamlVisitor, } from "yaml";
24
+ export { toJS as yamlToJs, type CreateNodeContext as YamlCreateNodeContext, type StringifyContext as YamlStringifyContext, type ToJSContext as YamlToJsContext, } from "yaml/util";
10
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,yBAAyB,CAAC;AAExC;;;;;;;;;GASG;AAEH,OAAO,EACN,OAAO,IAAI,WAAW,EACtB,YAAY,IAAI,gBAAgB,EAChC,UAAU,IAAI,cAAc,EAC5B,KAAK,IAAI,SAAS,EAClB,MAAM,IAAI,UAAU,EACpB,MAAM,IAAI,UAAU,EACpB,QAAQ,IAAI,YAAY,EACxB,KAAK,IAAI,SAAS,EAClB,KAAK,IAAI,SAAS,EAClB,UAAU,IAAI,cAAc,EAC5B,KAAK,IAAI,SAAS,EAClB,QAAQ,IAAI,YAAY,EACxB,OAAO,IAAI,OAAO,EAClB,IAAI,IAAI,QAAQ,EAChB,MAAM,IAAI,UAAU,EACpB,MAAM,IAAI,UAAU,EACpB,OAAO,IAAI,OAAO,EAClB,KAAK,YAAY,IAAI,gBAAgB,EACrC,KAAK,aAAa,IAAI,iBAAiB,EACvC,KAAK,IAAI,IAAI,QAAQ,EACrB,KAAK,UAAU,IAAI,cAAc,EACjC,KAAK,KAAK,IAAI,SAAS,EACvB,KAAK,SAAS,IAAI,aAAa,EAC/B,KAAK,KAAK,IAAI,SAAS,EACvB,KAAK,IAAI,IAAI,QAAQ,EACrB,KAAK,OAAO,IAAI,WAAW,GAC3B,MAAM,MAAM,CAAC;AACd,OAAO,EACN,IAAI,IAAI,QAAQ,EAChB,KAAK,iBAAiB,IAAI,qBAAqB,EAC/C,KAAK,gBAAgB,IAAI,oBAAoB,EAC7C,KAAK,WAAW,IAAI,eAAe,GACnC,MAAM,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,25 @@
1
+ export * from "./add-tag-directive.js";
1
2
  export * from "./document-parse-stream.js";
2
3
  export * from "./document-print-stream.js";
3
4
  export * from "./documents-parse-stream.js";
4
5
  export * from "./documents-print-stream.js";
5
6
  export * from "./edit.js";
7
+ export * from "./errors.js";
6
8
  export * from "./parse-stream.js";
7
9
  export * from "./parse.js";
8
10
  export * from "./print-stream.js";
9
11
  export * from "./print.js";
12
+ export * from "./resolve-async-tags.js";
13
+ /**
14
+ * The `yaml` node, tag and visitor model, re-exported so a caller can write a
15
+ * custom tag without taking its own dependency on `yaml`.
16
+ *
17
+ * Names are `Yaml`-prefixed rather than kept as upstream. This package's index
18
+ * is a flat `export *`, so a bare `Node`, `Document`, `Scalar` or `Schema`
19
+ * would sit beside `YamlParseStream` and `parseYaml` under names that say
20
+ * nothing about YAML — and `Node` and `Document` are DOM globals, which this
21
+ * package, being portable, is expected to be imported alongside.
22
+ */
23
+ export { isAlias as isYamlAlias, isCollection as isYamlCollection, isDocument as isYamlDocument, isMap as isYamlMap, isNode as isYamlNode, isPair as isYamlPair, isScalar as isYamlScalar, isSeq as isYamlSeq, visit as visitYaml, visitAsync as visitYamlAsync, Alias as YamlAlias, Document as YamlDocument, YAMLMap as YamlMap, Pair as YamlPair, Scalar as YamlScalar, Schema as YamlSchema, YAMLSeq as YamlSeq, } from "yaml";
24
+ export { toJS as yamlToJs, } from "yaml/util";
10
25
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,yBAAyB,CAAC;AAExC;;;;;;;;;GASG;AAEH,OAAO,EACN,OAAO,IAAI,WAAW,EACtB,YAAY,IAAI,gBAAgB,EAChC,UAAU,IAAI,cAAc,EAC5B,KAAK,IAAI,SAAS,EAClB,MAAM,IAAI,UAAU,EACpB,MAAM,IAAI,UAAU,EACpB,QAAQ,IAAI,YAAY,EACxB,KAAK,IAAI,SAAS,EAClB,KAAK,IAAI,SAAS,EAClB,UAAU,IAAI,cAAc,EAC5B,KAAK,IAAI,SAAS,EAClB,QAAQ,IAAI,YAAY,EACxB,OAAO,IAAI,OAAO,EAClB,IAAI,IAAI,QAAQ,EAChB,MAAM,IAAI,UAAU,EACpB,MAAM,IAAI,UAAU,EACpB,OAAO,IAAI,OAAO,GAUlB,MAAM,MAAM,CAAC;AACd,OAAO,EACN,IAAI,IAAI,QAAQ,GAIhB,MAAM,WAAW,CAAC"}
@@ -1,4 +1,4 @@
1
- import * as yaml from "yaml";
1
+ import type * as yaml from "yaml";
2
2
  export type YamlParseStreamOptions = yaml.ParseOptions & yaml.DocumentOptions & yaml.SchemaOptions;
3
3
  /** Buffers a byte stream and emits one parsed YAML value on flush. */
4
4
  export declare class YamlParseStream extends TransformStream<Uint8Array, unknown> {
@@ -1 +1 @@
1
- {"version":3,"file":"parse-stream.d.ts","sourceRoot":"","sources":["../src/parse-stream.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,YAAY,GACrD,IAAI,CAAC,eAAe,GACpB,IAAI,CAAC,aAAa,CAAC;AAEpB,sEAAsE;AACtE,qBAAa,eAAgB,SAAQ,eAAe,CAAC,UAAU,EAAE,OAAO,CAAC;IACxE,YAAY,OAAO,GAAE,sBAA2B,EAO/C;CACD"}
1
+ {"version":3,"file":"parse-stream.d.ts","sourceRoot":"","sources":["../src/parse-stream.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,IAAI,MAAM,MAAM,CAAC;AAIlC,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,YAAY,GACrD,IAAI,CAAC,eAAe,GACpB,IAAI,CAAC,aAAa,CAAC;AAEpB,sEAAsE;AACtE,qBAAa,eAAgB,SAAQ,eAAe,CAAC,UAAU,EAAE,OAAO,CAAC;IACxE,YAAY,OAAO,GAAE,sBAA2B,EAI/C;CACD"}
@@ -1,9 +1,9 @@
1
1
  import { wholeTextParseTransformer } from "@ac-kit/format-core";
2
- import * as yaml from "yaml";
2
+ import { parseYaml } from "./parse.js";
3
3
  /** Buffers a byte stream and emits one parsed YAML value on flush. */
4
4
  export class YamlParseStream extends TransformStream {
5
5
  constructor(options = {}) {
6
- super(wholeTextParseTransformer((source) => yaml.parse(source, options), "YAML"));
6
+ super(wholeTextParseTransformer((source) => parseYaml(source, options), "YAML"));
7
7
  }
8
8
  }
9
9
  //# sourceMappingURL=parse-stream.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-stream.js","sourceRoot":"","sources":["../src/parse-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAM7B,sEAAsE;AACtE,MAAM,OAAO,eAAgB,SAAQ,eAAoC;IACxE,YAAY,OAAO,GAA2B,EAAE;QAC/C,KAAK,CACJ,yBAAyB,CACxB,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAY,EAClD,MAAM,CACN,CACD,CAAC;IACH,CAAC;CACD"}
1
+ {"version":3,"file":"parse-stream.js","sourceRoot":"","sources":["../src/parse-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAGhE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAMvC,sEAAsE;AACtE,MAAM,OAAO,eAAgB,SAAQ,eAAoC;IACxE,YAAY,OAAO,GAA2B,EAAE;QAC/C,KAAK,CACJ,yBAAyB,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,CACzE,CAAC;IACH,CAAC;CACD"}
package/dist/parse.d.ts CHANGED
@@ -1,9 +1,36 @@
1
1
  import * as yaml from "yaml";
2
2
  export type YamlParseOptions = yaml.ParseOptions & yaml.DocumentOptions & yaml.SchemaOptions & yaml.ToJSOptions;
3
- /** Parses a YAML string into a plain JS value. */
3
+ /**
4
+ * Alias expansions allowed while converting a document to a plain value, unless
5
+ * the caller passes its own `maxAliasCount`.
6
+ *
7
+ * An anchor referenced from inside another anchor expands multiplicatively —
8
+ * the "billion laughs" denial of service — and this bound is the only thing
9
+ * between untrusted YAML and an unbounded allocation. `-1` disables the check,
10
+ * `0` rejects every alias.
11
+ */
12
+ export declare const DEFAULT_YAML_MAX_ALIAS_COUNT = 100;
13
+ /**
14
+ * Parses a YAML string into a plain JS value.
15
+ *
16
+ * Throws {@link YamlParseError} for malformed input, carrying every diagnostic
17
+ * with its position. Alias expansion is bounded by
18
+ * {@link DEFAULT_YAML_MAX_ALIAS_COUNT}.
19
+ */
4
20
  export declare function parseYaml(source: string, options?: YamlParseOptions): unknown;
5
- /** Parses a YAML string into a {@link yaml.Document} (CST-level). */
21
+ /**
22
+ * Parses a YAML string into a {@link yaml.Document} (CST-level).
23
+ *
24
+ * Error-tolerant, as `yaml`'s own `parseDocument` is: diagnostics stay on the
25
+ * returned document's `errors`, so partially valid source is still inspectable.
26
+ * Hand them to {@link YamlParseError} to turn them into a throw. `maxAliasCount`
27
+ * bounds `toJS()`, not this call.
28
+ */
6
29
  export declare function parseYamlDocument(source: string, options?: yaml.ParseOptions & yaml.DocumentOptions & yaml.SchemaOptions): yaml.Document;
7
- /** Parses all YAML documents from a multi-document string. */
30
+ /**
31
+ * Parses all YAML documents from a multi-document string.
32
+ *
33
+ * Error-tolerant in the same way as {@link parseYamlDocument}.
34
+ */
8
35
  export declare function parseAllYamlDocuments(source: string, options?: yaml.ParseOptions & yaml.DocumentOptions & yaml.SchemaOptions): yaml.Document[];
9
36
  //# sourceMappingURL=parse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,GAC/C,IAAI,CAAC,eAAe,GACpB,IAAI,CAAC,aAAa,GAClB,IAAI,CAAC,WAAW,CAAC;AAElB,kDAAkD;AAClD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAM7E;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,aAAa,GACrE,IAAI,CAAC,QAAQ,CAEf;AAED,8DAA8D;AAC9D,wBAAgB,qBAAqB,CACpC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,aAAa,GACrE,IAAI,CAAC,QAAQ,EAAE,CAEjB"}
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAK7B,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,GAC/C,IAAI,CAAC,eAAe,GACpB,IAAI,CAAC,aAAa,GAClB,IAAI,CAAC,WAAW,CAAC;AAElB;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAmB7E;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,aAAa,GACrE,IAAI,CAAC,QAAQ,CAEf;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACpC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,aAAa,GACrE,IAAI,CAAC,QAAQ,EAAE,CAEjB"}
package/dist/parse.js CHANGED
@@ -1,18 +1,58 @@
1
1
  import * as yaml from "yaml";
2
- /** Parses a YAML string into a plain JS value. */
2
+ import { warn } from "yaml/util";
3
+ import { YamlParseError } from "./errors.js";
4
+ /**
5
+ * Alias expansions allowed while converting a document to a plain value, unless
6
+ * the caller passes its own `maxAliasCount`.
7
+ *
8
+ * An anchor referenced from inside another anchor expands multiplicatively —
9
+ * the "billion laughs" denial of service — and this bound is the only thing
10
+ * between untrusted YAML and an unbounded allocation. `-1` disables the check,
11
+ * `0` rejects every alias.
12
+ */
13
+ export const DEFAULT_YAML_MAX_ALIAS_COUNT = 100;
14
+ /**
15
+ * Parses a YAML string into a plain JS value.
16
+ *
17
+ * Throws {@link YamlParseError} for malformed input, carrying every diagnostic
18
+ * with its position. Alias expansion is bounded by
19
+ * {@link DEFAULT_YAML_MAX_ALIAS_COUNT}.
20
+ */
3
21
  export function parseYaml(source, options) {
22
+ const logLevel = options?.logLevel ?? "warn";
23
+ const document = yaml.parseDocument(source, options);
24
+ for (const warning of document.warnings) {
25
+ warn(logLevel, warning);
26
+ }
27
+ if (document.errors.length > 0 && logLevel !== "silent") {
28
+ throw new YamlParseError(document.errors);
29
+ }
4
30
  try {
5
- return yaml.parse(source, options);
31
+ return document.toJS({
32
+ maxAliasCount: DEFAULT_YAML_MAX_ALIAS_COUNT,
33
+ ...options,
34
+ });
6
35
  }
7
36
  catch (error) {
8
37
  throw new Error("parse YAML", { cause: error });
9
38
  }
10
39
  }
11
- /** Parses a YAML string into a {@link yaml.Document} (CST-level). */
40
+ /**
41
+ * Parses a YAML string into a {@link yaml.Document} (CST-level).
42
+ *
43
+ * Error-tolerant, as `yaml`'s own `parseDocument` is: diagnostics stay on the
44
+ * returned document's `errors`, so partially valid source is still inspectable.
45
+ * Hand them to {@link YamlParseError} to turn them into a throw. `maxAliasCount`
46
+ * bounds `toJS()`, not this call.
47
+ */
12
48
  export function parseYamlDocument(source, options) {
13
49
  return yaml.parseDocument(source, options);
14
50
  }
15
- /** Parses all YAML documents from a multi-document string. */
51
+ /**
52
+ * Parses all YAML documents from a multi-document string.
53
+ *
54
+ * Error-tolerant in the same way as {@link parseYamlDocument}.
55
+ */
16
56
  export function parseAllYamlDocuments(source, options) {
17
57
  return yaml.parseAllDocuments(source, options);
18
58
  }
package/dist/parse.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAO7B,kDAAkD;AAClD,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,OAA0B;IACnE,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,CAAC;AACF,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,iBAAiB,CAChC,MAAc,EACd,OAAuE;IAEvE,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,qBAAqB,CACpC,MAAc,EACd,OAAuE;IAEvE,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC"}
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAO7C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,OAA0B;IACnE,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,MAAM,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAErD,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACzC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACzD,MAAM,IAAI,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC;QACJ,OAAO,QAAQ,CAAC,IAAI,CAAC;YACpB,aAAa,EAAE,4BAA4B;YAC3C,GAAG,OAAO;SACV,CAAC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,CAAC;AACF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAChC,MAAc,EACd,OAAuE;IAEvE,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACpC,MAAc,EACd,OAAuE;IAEvE,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,14 @@
1
+ import * as yaml from "yaml";
2
+ /**
3
+ * Settles every `Promise` an async custom tag left behind in `node`.
4
+ *
5
+ * A `ScalarTag.resolve` declared `async` hands the composer a `Promise`, which
6
+ * it stores as the scalar's value verbatim — so `toJS()` would serialise the
7
+ * promise rather than what it settles to. Awaiting the tree once, between
8
+ * composing it and reading it, is what makes an async tag usable.
9
+ *
10
+ * Mutates `node` in place. Linear in the number of nodes; the awaits run in
11
+ * document order, not concurrently.
12
+ */
13
+ export declare function resolveYamlAsyncTags(node: yaml.Node | yaml.Document | null): Promise<void>;
14
+ //# sourceMappingURL=resolve-async-tags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-async-tags.d.ts","sourceRoot":"","sources":["../src/resolve-async-tags.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACzC,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,GACpC,OAAO,CAAC,IAAI,CAAC,CAQf"}
@@ -0,0 +1,23 @@
1
+ import { isPromise } from "@ac-kit/core";
2
+ import * as yaml from "yaml";
3
+ /**
4
+ * Settles every `Promise` an async custom tag left behind in `node`.
5
+ *
6
+ * A `ScalarTag.resolve` declared `async` hands the composer a `Promise`, which
7
+ * it stores as the scalar's value verbatim — so `toJS()` would serialise the
8
+ * promise rather than what it settles to. Awaiting the tree once, between
9
+ * composing it and reading it, is what makes an async tag usable.
10
+ *
11
+ * Mutates `node` in place. Linear in the number of nodes; the awaits run in
12
+ * document order, not concurrently.
13
+ */
14
+ export async function resolveYamlAsyncTags(node) {
15
+ await yaml.visitAsync(node, {
16
+ async Scalar(_key, scalar) {
17
+ if (isPromise(scalar.value)) {
18
+ scalar.value = await scalar.value;
19
+ }
20
+ },
21
+ });
22
+ }
23
+ //# sourceMappingURL=resolve-async-tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-async-tags.js","sourceRoot":"","sources":["../src/resolve-async-tags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACzC,IAAsC;IAEtC,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QAC3B,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM;YACxB,IAAI,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7B,MAAM,CAAC,KAAK,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;YACnC,CAAC;QACF,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ac-kit/format-yaml",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "YAML parse and print streams over @ac-kit/format-core.",
5
5
  "keywords": [
6
6
  "config",
@@ -26,14 +26,12 @@
26
26
  "sideEffects": false,
27
27
  "main": "./dist/index.js",
28
28
  "exports": {
29
- ".": "./dist/index.js",
30
- "./file": "./dist/file.js"
29
+ ".": "./dist/index.js"
31
30
  },
32
31
  "publishConfig": {
33
32
  "main": "./dist/index.js",
34
33
  "exports": {
35
- ".": "./dist/index.js",
36
- "./file": "./dist/file.js"
34
+ ".": "./dist/index.js"
37
35
  },
38
36
  "access": "public"
39
37
  },
@@ -46,8 +44,8 @@
46
44
  "prepack": "yarn build"
47
45
  },
48
46
  "dependencies": {
49
- "@ac-kit/core": "^0.2.0",
50
- "@ac-kit/format-core": "^0.1.1",
47
+ "@ac-kit/core": "^0.3.0",
48
+ "@ac-kit/format-core": "^0.1.2",
51
49
  "@types/node": "^26.5.1",
52
50
  "yaml": "^2.9.0"
53
51
  },