@telorun/analyzer 0.30.1 → 0.31.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.
@@ -80,6 +80,11 @@ export interface LoadedGraph {
80
80
  * error for a major mismatch). Surfaced alongside `analyze()` diagnostics by
81
81
  * every consumer (CLI, editor, VS Code). */
82
82
  versionDiagnostics: AnalysisDiagnostic[];
83
+ /** YAML parse failures aggregated from every file's `parseErrors`. A file
84
+ * that fails to parse yields a mangled `toJSON()` projection, so these are
85
+ * fatal Error diagnostics — surfaced alongside `analyze()` output by every
86
+ * consumer (CLI, editor, VS Code) and treated as fatal by the kernel. */
87
+ parseDiagnostics: AnalysisDiagnostic[];
83
88
  /** Surface-level errors that did not abort the graph load (e.g. an import
84
89
  * whose target failed to fetch). */
85
90
  errors: GraphLoadError[];
@@ -1 +1 @@
1
- {"version":3,"file":"loaded-types.d.ts","sourceRoot":"","sources":["../src/loaded-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;4EAI4E;AAC5E,MAAM,WAAW,UAAU;IACzB;+DAC2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf;gEAC4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,6EAA6E;IAC7E,SAAS,EAAE,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,0EAA0E;IAC1E,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;mCACmC;AACnC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB;oEACgE;IAChE,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED;;;;;2EAK2E;AAC3E,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB;6EACyE;IACzE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,oEAAoE;IACpE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;0BAC0B;AAC1B,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;IACpB;;wBAEoB;IACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnC;;;;2BAIuB;IACvB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAClD;;;iFAG6E;IAC7E,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;;;iDAG6C;IAC7C,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;IACzC;yCACqC;IACrC,MAAM,EAAE,cAAc,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,KAAK,CAAC;CACd"}
1
+ {"version":3,"file":"loaded-types.d.ts","sourceRoot":"","sources":["../src/loaded-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;4EAI4E;AAC5E,MAAM,WAAW,UAAU;IACzB;+DAC2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf;gEAC4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,6EAA6E;IAC7E,SAAS,EAAE,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,0EAA0E;IAC1E,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;mCACmC;AACnC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB;oEACgE;IAChE,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED;;;;;2EAK2E;AAC3E,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB;6EACyE;IACzE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,oEAAoE;IACpE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;0BAC0B;AAC1B,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;IACpB;;wBAEoB;IACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnC;;;;2BAIuB;IACvB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAClD;;;iFAG6E;IAC7E,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;;;iDAG6C;IAC7C,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;IACzC;;;8EAG0E;IAC1E,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;IACvC;yCACqC;IACrC,MAAM,EAAE,cAAc,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,KAAK,CAAC;CACd"}
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-loader.d.ts","sourceRoot":"","sources":["../src/manifest-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,UAAU,EACV,WAAW,EACX,YAAY,EACb,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAiBpB,qBAAa,MAAM;IACjB;;;yEAGqE;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAE3D;;;;;8BAK0B;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IAEzD,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC;;;;mBAIe;gBACH,OAAO,GAAE,cAAc,EAAO,EAAE,OAAO,GAAE,iBAAsB;IAK3E,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAKtC,OAAO,CAAC,IAAI;IAMN,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUrD;;;;2CAIuC;IACvC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAM7C;;;+BAG2B;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAyCvE;;;;gEAI4D;IAC5D,OAAO,CAAC,oBAAoB;IAa5B;gFAC4E;IAC5E,OAAO,CAAC,cAAc;IAQtB;;wEAEoE;IAC9D,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAsB3E;;;qCAGiC;IAC3B,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAqH9E;;;;;;;;sBAQkB;IAClB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAOlE,OAAO,CAAC,6BAA6B;IAarC,OAAO,CAAC,mCAAmC;IAc3C,OAAO,CAAC,2BAA2B;YAkCrB,eAAe;IAmB7B;;;0CAGsC;IAChC,gBAAgB,CACpB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CA0B5D"}
1
+ {"version":3,"file":"manifest-loader.d.ts","sourceRoot":"","sources":["../src/manifest-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,UAAU,EACV,WAAW,EACX,YAAY,EACb,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAwCpB,qBAAa,MAAM;IACjB;;;yEAGqE;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAE3D;;;;;8BAK0B;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IAEzD,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC;;;;mBAIe;gBACH,OAAO,GAAE,cAAc,EAAO,EAAE,OAAO,GAAE,iBAAsB;IAK3E,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAKtC,OAAO,CAAC,IAAI;IAMN,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUrD;;;;2CAIuC;IACvC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAM7C;;;+BAG2B;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAyCvE;;;;gEAI4D;IAC5D,OAAO,CAAC,oBAAoB;IAa5B;gFAC4E;IAC5E,OAAO,CAAC,cAAc;IAQtB;;wEAEoE;IAC9D,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAsB3E;;;qCAGiC;IAC3B,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAsH9E;;;;;;;;sBAQkB;IAClB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAOlE,OAAO,CAAC,6BAA6B;IAarC,OAAO,CAAC,mCAAmC;IAc3C,OAAO,CAAC,2BAA2B;YAkCrB,eAAe;IAmB7B;;;0CAGsC;IAChC,gBAAgB,CACpB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CA0B5D"}
@@ -3,7 +3,27 @@ import { desugarLoadedFile } from "./inline-imports.js";
3
3
  import { isModuleKind } from "./module-kinds.js";
4
4
  import { parseLoadedFile } from "./parse-loaded-file.js";
5
5
  import { reconcileModuleVersions } from "./reconcile-module-versions.js";
6
- import { DEFAULT_MANIFEST_FILENAME, } from "./types.js";
6
+ import { DEFAULT_MANIFEST_FILENAME, DiagnosticSeverity, } from "./types.js";
7
+ /** Project every file's YAML `parseErrors` into fatal Error diagnostics. Each
8
+ * carries `data.filePath` so `findPositions` routes it to the failing file. */
9
+ function collectParseDiagnostics(modules) {
10
+ const diagnostics = [];
11
+ for (const mod of modules.values()) {
12
+ for (const file of [mod.owner, ...mod.partials]) {
13
+ for (const err of file.parseErrors) {
14
+ diagnostics.push({
15
+ severity: DiagnosticSeverity.Error,
16
+ code: "MANIFEST_PARSE_FAILED",
17
+ source: "telo-analyzer",
18
+ message: err.message,
19
+ range: err.range,
20
+ data: { filePath: file.source },
21
+ });
22
+ }
23
+ }
24
+ }
25
+ return diagnostics;
26
+ }
7
27
  const SYSTEM_KINDS = new Set([
8
28
  "Telo.Application",
9
29
  "Telo.Library",
@@ -268,6 +288,7 @@ export class Loader {
268
288
  importEdges,
269
289
  overrides,
270
290
  versionDiagnostics: diagnostics,
291
+ parseDiagnostics: collectParseDiagnostics(modules),
271
292
  errors,
272
293
  };
273
294
  }
@@ -1 +1 @@
1
- {"version":3,"file":"parse-loaded-file.d.ts","sourceRoot":"","sources":["../src/parse-loaded-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKxD,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,mBAAmB,CAAC;AAIhE,MAAM,WAAW,YAAY;IAC3B;4EACwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,oEAAoE;AACpE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,YAAY,GACrB,UAAU,CA8CZ"}
1
+ {"version":3,"file":"parse-loaded-file.d.ts","sourceRoot":"","sources":["../src/parse-loaded-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKxD,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,mBAAmB,CAAC;AAIhE,MAAM,WAAW,YAAY;IAC3B;4EACwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AA4BD,oEAAoE;AACpE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,YAAY,GACrB,UAAU,CA+CZ"}
@@ -3,6 +3,29 @@ import { parseAllDocuments } from "yaml";
3
3
  import { buildCelEnvironment } from "./cel-environment.js";
4
4
  import { buildDocumentPositions } from "./position-metadata.js";
5
5
  import { precompileDoc } from "./precompile.js";
6
+ /** Append an actionable hint to raw yaml-parser messages that are otherwise
7
+ * cryptic. The parser reports `BLOCK_AS_IMPLICIT_KEY` ("Nested mappings are
8
+ * not allowed in compact mappings") when a plain (unquoted) scalar contains
9
+ * `: ` (colon-space) — the parser reads the colon as a nested key. Telling the
10
+ * author to quote the value turns an opaque error into a one-step fix. */
11
+ function augmentParseMessage(err) {
12
+ if (err.code === "BLOCK_AS_IMPLICIT_KEY") {
13
+ return `${err.message}\n\nHint: a plain (unquoted) value cannot contain ': ' (colon followed by a space) — the parser reads it as a nested mapping. Wrap the value in quotes, e.g. \`description: "… \`encoding: base64\` …"\`.`;
14
+ }
15
+ return err.message;
16
+ }
17
+ /** The yaml lib reports 1-based `{line, col}` pairs; convert to a 0-based
18
+ * analyzer `Range`. Returns undefined when the error carried no position. */
19
+ function rangeFromLinePos(linePos) {
20
+ const start = linePos?.[0];
21
+ if (!start)
22
+ return undefined;
23
+ const end = linePos?.[1] ?? start;
24
+ return {
25
+ start: { line: start.line - 1, character: start.col - 1 },
26
+ end: { line: end.line - 1, character: end.col - 1 },
27
+ };
28
+ }
6
29
  /** Pure: text in, structured load result out. No I/O, no caches. */
7
30
  export function parseLoadedFile(source, requestedUrl, text, options) {
8
31
  const documents = parseAllDocuments(text, { customTags: defaultCustomTags() });
@@ -12,7 +35,8 @@ export function parseLoadedFile(source, requestedUrl, text, options) {
12
35
  for (const err of doc.errors) {
13
36
  parseErrors.push({
14
37
  documentIndex,
15
- message: err.message,
38
+ message: augmentParseMessage(err),
39
+ range: rangeFromLinePos(err.linePos),
16
40
  });
17
41
  }
18
42
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telorun/analyzer",
3
- "version": "0.30.1",
3
+ "version": "0.31.0",
4
4
  "description": "Telo Analyzer - Static manifest validator for Telo manifests.",
5
5
  "keywords": [
6
6
  "telo",
@@ -85,6 +85,11 @@ export interface LoadedGraph {
85
85
  * error for a major mismatch). Surfaced alongside `analyze()` diagnostics by
86
86
  * every consumer (CLI, editor, VS Code). */
87
87
  versionDiagnostics: AnalysisDiagnostic[];
88
+ /** YAML parse failures aggregated from every file's `parseErrors`. A file
89
+ * that fails to parse yields a mangled `toJSON()` projection, so these are
90
+ * fatal Error diagnostics — surfaced alongside `analyze()` output by every
91
+ * consumer (CLI, editor, VS Code) and treated as fatal by the kernel. */
92
+ parseDiagnostics: AnalysisDiagnostic[];
88
93
  /** Surface-level errors that did not abort the graph load (e.g. an import
89
94
  * whose target failed to fetch). */
90
95
  errors: GraphLoadError[];
@@ -13,12 +13,37 @@ import { isModuleKind } from "./module-kinds.js";
13
13
  import { parseLoadedFile } from "./parse-loaded-file.js";
14
14
  import { reconcileModuleVersions } from "./reconcile-module-versions.js";
15
15
  import {
16
+ type AnalysisDiagnostic,
16
17
  DEFAULT_MANIFEST_FILENAME,
18
+ DiagnosticSeverity,
17
19
  type LoadOptions,
18
20
  type LoaderInitOptions,
19
21
  type ManifestSource,
20
22
  } from "./types.js";
21
23
 
24
+ /** Project every file's YAML `parseErrors` into fatal Error diagnostics. Each
25
+ * carries `data.filePath` so `findPositions` routes it to the failing file. */
26
+ function collectParseDiagnostics(
27
+ modules: Map<string, LoadedModule>,
28
+ ): AnalysisDiagnostic[] {
29
+ const diagnostics: AnalysisDiagnostic[] = [];
30
+ for (const mod of modules.values()) {
31
+ for (const file of [mod.owner, ...mod.partials]) {
32
+ for (const err of file.parseErrors) {
33
+ diagnostics.push({
34
+ severity: DiagnosticSeverity.Error,
35
+ code: "MANIFEST_PARSE_FAILED",
36
+ source: "telo-analyzer",
37
+ message: err.message,
38
+ range: err.range,
39
+ data: { filePath: file.source },
40
+ });
41
+ }
42
+ }
43
+ }
44
+ return diagnostics;
45
+ }
46
+
22
47
  const SYSTEM_KINDS = new Set([
23
48
  "Telo.Application",
24
49
  "Telo.Library",
@@ -309,6 +334,7 @@ export class Loader {
309
334
  importEdges,
310
335
  overrides,
311
336
  versionDiagnostics: diagnostics,
337
+ parseDiagnostics: collectParseDiagnostics(modules),
312
338
  errors,
313
339
  };
314
340
  }
@@ -15,6 +15,32 @@ export interface ParseOptions {
15
15
  celEnv?: Environment;
16
16
  }
17
17
 
18
+ /** Append an actionable hint to raw yaml-parser messages that are otherwise
19
+ * cryptic. The parser reports `BLOCK_AS_IMPLICIT_KEY` ("Nested mappings are
20
+ * not allowed in compact mappings") when a plain (unquoted) scalar contains
21
+ * `: ` (colon-space) — the parser reads the colon as a nested key. Telling the
22
+ * author to quote the value turns an opaque error into a one-step fix. */
23
+ function augmentParseMessage(err: import("yaml").YAMLError): string {
24
+ if (err.code === "BLOCK_AS_IMPLICIT_KEY") {
25
+ return `${err.message}\n\nHint: a plain (unquoted) value cannot contain ': ' (colon followed by a space) — the parser reads it as a nested mapping. Wrap the value in quotes, e.g. \`description: "… \`encoding: base64\` …"\`.`;
26
+ }
27
+ return err.message;
28
+ }
29
+
30
+ /** The yaml lib reports 1-based `{line, col}` pairs; convert to a 0-based
31
+ * analyzer `Range`. Returns undefined when the error carried no position. */
32
+ function rangeFromLinePos(
33
+ linePos: import("yaml").YAMLError["linePos"],
34
+ ): import("./types.js").Range | undefined {
35
+ const start = linePos?.[0];
36
+ if (!start) return undefined;
37
+ const end = linePos?.[1] ?? start;
38
+ return {
39
+ start: { line: start.line - 1, character: start.col - 1 },
40
+ end: { line: end.line - 1, character: end.col - 1 },
41
+ };
42
+ }
43
+
18
44
  /** Pure: text in, structured load result out. No I/O, no caches. */
19
45
  export function parseLoadedFile(
20
46
  source: string,
@@ -30,7 +56,8 @@ export function parseLoadedFile(
30
56
  for (const err of doc.errors) {
31
57
  parseErrors.push({
32
58
  documentIndex,
33
- message: err.message,
59
+ message: augmentParseMessage(err),
60
+ range: rangeFromLinePos(err.linePos),
34
61
  });
35
62
  }
36
63
  });