@toist/spec 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/src/yaml.ts ADDED
@@ -0,0 +1,61 @@
1
+ // 2121
2
+ // Strict YAML loader for pipeline files.
3
+ //
4
+ // Per pipeline-spec.md §1: anchors, aliases, merge keys, and multi-document
5
+ // files are rejected at spec-load. Reuse is a spec-level concern (kinds, refs)
6
+ // not a YAML-syntax concern, and round-trip isomorphism with the UI editor
7
+ // requires this discipline.
8
+
9
+ import YAML from "yaml"
10
+
11
+ export class YamlError extends Error {
12
+ constructor(message: string) {
13
+ super(message)
14
+ this.name = "YamlError"
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Parse a YAML pipeline source. Returns a plain JS object on success;
20
+ * throws YamlError on syntax error, multi-document files, anchors, aliases,
21
+ * or merge keys.
22
+ */
23
+ export function parse(src: string): unknown {
24
+ const docs = YAML.parseAllDocuments(src, { strict: true })
25
+ if (docs.length === 0) throw new YamlError("empty YAML document")
26
+ if (docs.length > 1) {
27
+ throw new YamlError(
28
+ "multi-document YAML files (--- separator) are not allowed; one file = one pipeline",
29
+ )
30
+ }
31
+
32
+ const doc = docs[0]
33
+ if (doc.errors.length > 0) {
34
+ throw new YamlError(`YAML parse error: ${doc.errors[0].message}`)
35
+ }
36
+
37
+ // Walk the document AST checking for anchors, aliases, and merge keys.
38
+ YAML.visit(doc, {
39
+ Alias() {
40
+ throw new YamlError(
41
+ "YAML aliases (*name) are not allowed; reuse via spec-level kinds or `$ref` instead",
42
+ )
43
+ },
44
+ Pair(_, pair) {
45
+ // Merge keys are pairs whose key is the special "<<" tag.
46
+ const key = pair.key
47
+ if (key && typeof key === "object" && "value" in key && key.value === "<<") {
48
+ throw new YamlError("YAML merge keys (<<:) are not allowed")
49
+ }
50
+ },
51
+ Node(_, node) {
52
+ if (node && typeof node === "object" && "anchor" in node && node.anchor) {
53
+ throw new YamlError(
54
+ `YAML anchors (&${node.anchor}) are not allowed; reuse via spec-level kinds or \`$ref\` instead`,
55
+ )
56
+ }
57
+ },
58
+ })
59
+
60
+ return doc.toJSON()
61
+ }