@hstm-labs/forge-spec-parser 0.1.2

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.
Files changed (70) hide show
  1. package/README.md +53 -0
  2. package/dist/default-registry.d.ts +19 -0
  3. package/dist/default-registry.d.ts.map +1 -0
  4. package/dist/default-registry.js +28 -0
  5. package/dist/default-registry.js.map +1 -0
  6. package/dist/detect.d.ts +16 -0
  7. package/dist/detect.d.ts.map +1 -0
  8. package/dist/detect.js +32 -0
  9. package/dist/detect.js.map +1 -0
  10. package/dist/index.d.ts +18 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +23 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/loader.d.ts +31 -0
  15. package/dist/loader.d.ts.map +1 -0
  16. package/dist/loader.js +45 -0
  17. package/dist/loader.js.map +1 -0
  18. package/dist/parser-plugin.d.ts +23 -0
  19. package/dist/parser-plugin.d.ts.map +1 -0
  20. package/dist/parser-plugin.js +8 -0
  21. package/dist/parser-plugin.js.map +1 -0
  22. package/dist/parsers/json-parser.d.ts +35 -0
  23. package/dist/parsers/json-parser.d.ts.map +1 -0
  24. package/dist/parsers/json-parser.js +46 -0
  25. package/dist/parsers/json-parser.js.map +1 -0
  26. package/dist/parsers/markdown-parser.d.ts +41 -0
  27. package/dist/parsers/markdown-parser.d.ts.map +1 -0
  28. package/dist/parsers/markdown-parser.js +606 -0
  29. package/dist/parsers/markdown-parser.js.map +1 -0
  30. package/dist/parsers/structured-mapper.d.ts +22 -0
  31. package/dist/parsers/structured-mapper.d.ts.map +1 -0
  32. package/dist/parsers/structured-mapper.js +214 -0
  33. package/dist/parsers/structured-mapper.js.map +1 -0
  34. package/dist/parsers/yaml-parser.d.ts +35 -0
  35. package/dist/parsers/yaml-parser.d.ts.map +1 -0
  36. package/dist/parsers/yaml-parser.js +47 -0
  37. package/dist/parsers/yaml-parser.js.map +1 -0
  38. package/dist/registry.d.ts +57 -0
  39. package/dist/registry.d.ts.map +1 -0
  40. package/dist/registry.js +80 -0
  41. package/dist/registry.js.map +1 -0
  42. package/dist/types.d.ts +85 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +8 -0
  45. package/dist/types.js.map +1 -0
  46. package/dist/validate-stage.d.ts +18 -0
  47. package/dist/validate-stage.d.ts.map +1 -0
  48. package/dist/validate-stage.js +24 -0
  49. package/dist/validate-stage.js.map +1 -0
  50. package/dist/validation-types.d.ts +46 -0
  51. package/dist/validation-types.d.ts.map +1 -0
  52. package/dist/validation-types.js +9 -0
  53. package/dist/validation-types.js.map +1 -0
  54. package/dist/validators/completeness-checker.d.ts +29 -0
  55. package/dist/validators/completeness-checker.d.ts.map +1 -0
  56. package/dist/validators/completeness-checker.js +127 -0
  57. package/dist/validators/completeness-checker.js.map +1 -0
  58. package/dist/validators/cross-reference-validator.d.ts +17 -0
  59. package/dist/validators/cross-reference-validator.d.ts.map +1 -0
  60. package/dist/validators/cross-reference-validator.js +150 -0
  61. package/dist/validators/cross-reference-validator.js.map +1 -0
  62. package/dist/validators/schema-validator.d.ts +16 -0
  63. package/dist/validators/schema-validator.d.ts.map +1 -0
  64. package/dist/validators/schema-validator.js +146 -0
  65. package/dist/validators/schema-validator.js.map +1 -0
  66. package/dist/validators/spec-validator.d.ts +15 -0
  67. package/dist/validators/spec-validator.d.ts.map +1 -0
  68. package/dist/validators/spec-validator.js +52 -0
  69. package/dist/validators/spec-validator.js.map +1 -0
  70. package/package.json +29 -0
package/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # @hstm-labs/forge-spec-parser
2
+
3
+ Specification parsing and validation for Forge — reads product specifications in Markdown, YAML, or JSON format and produces a canonical `ParsedSpecification` model with completeness scoring and cross-reference validation.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @hstm-labs/forge-spec-parser
9
+ ```
10
+
11
+ ## Public API
12
+
13
+ ### Parsing
14
+
15
+ - `parseSpec(content, format)` — parse specification content into canonical model
16
+ - `loadSpecFile(path)` — load and parse a specification file
17
+ - `detectFormat(path)` — auto-detect specification format
18
+ - `ParserRegistry` — plugin registry for format parsers
19
+ - `createDefaultRegistry()` — factory for registry with all built-in parsers
20
+
21
+ ### Parser Plugins
22
+
23
+ - `MarkdownParserPlugin` — GFM Markdown with entity/requirement extraction
24
+ - `YamlParserPlugin` — structured YAML specifications
25
+ - `JsonParserPlugin` — structured JSON specifications
26
+ - `mapStructuredSpec()` — shared mapper for YAML/JSON formats
27
+
28
+ ### Validation
29
+
30
+ - `validateSpec(spec)` — full validation (schema + completeness + cross-references)
31
+ - `validateSchema(spec)` — schema validation
32
+ - `checkCompleteness(spec)` — 6-dimension completeness scoring
33
+ - `validateCrossReferences(spec)` — entity/requirement reference integrity
34
+
35
+ ### Types
36
+
37
+ - `ParsedSpecification` — canonical specification model
38
+ - `SpecRequirement`, `SpecEntity`, `SpecWorkflow` — specification components
39
+ - `ValidationReport`, `ValidationFinding` — validation output
40
+
41
+ ## Usage
42
+
43
+ ```typescript
44
+ import { loadSpecFile, validateSpec } from '@hstm-labs/forge-spec-parser';
45
+
46
+ const spec = await loadSpecFile('specs/product-spec.md');
47
+ const report = validateSpec(spec);
48
+ console.log(`Completeness: ${report.completeness.overall}%`);
49
+ ```
50
+
51
+ ## License
52
+
53
+ [MIT](../../LICENSE)
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Factory for creating a pre-configured parser registry.
3
+ *
4
+ * Returns a {@link ParserRegistry} with all built-in parser plugins
5
+ * registered, ready for use with {@link parseSpec}.
6
+ */
7
+ import { ParserRegistry } from './registry.js';
8
+ /**
9
+ * Create a parser registry pre-loaded with all built-in parser plugins.
10
+ *
11
+ * Currently registers:
12
+ * - {@link MarkdownParserPlugin} — `.md` files
13
+ * - {@link YamlParserPlugin} — `.yaml`, `.yml` files
14
+ * - {@link JsonParserPlugin} — `.json` files
15
+ *
16
+ * @returns A fully-configured {@link ParserRegistry}
17
+ */
18
+ export declare function createDefaultRegistry(): ParserRegistry;
19
+ //# sourceMappingURL=default-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-registry.d.ts","sourceRoot":"","sources":["../src/default-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAK/C;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,IAAI,cAAc,CAMtD"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Factory for creating a pre-configured parser registry.
3
+ *
4
+ * Returns a {@link ParserRegistry} with all built-in parser plugins
5
+ * registered, ready for use with {@link parseSpec}.
6
+ */
7
+ import { ParserRegistry } from './registry.js';
8
+ import { MarkdownParserPlugin } from './parsers/markdown-parser.js';
9
+ import { YamlParserPlugin } from './parsers/yaml-parser.js';
10
+ import { JsonParserPlugin } from './parsers/json-parser.js';
11
+ /**
12
+ * Create a parser registry pre-loaded with all built-in parser plugins.
13
+ *
14
+ * Currently registers:
15
+ * - {@link MarkdownParserPlugin} — `.md` files
16
+ * - {@link YamlParserPlugin} — `.yaml`, `.yml` files
17
+ * - {@link JsonParserPlugin} — `.json` files
18
+ *
19
+ * @returns A fully-configured {@link ParserRegistry}
20
+ */
21
+ export function createDefaultRegistry() {
22
+ const registry = new ParserRegistry();
23
+ registry.register(new MarkdownParserPlugin());
24
+ registry.register(new YamlParserPlugin());
25
+ registry.register(new JsonParserPlugin());
26
+ return registry;
27
+ }
28
+ //# sourceMappingURL=default-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-registry.js","sourceRoot":"","sources":["../src/default-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;IAC9C,QAAQ,CAAC,QAAQ,CAAC,IAAI,gBAAgB,EAAE,CAAC,CAAC;IAC1C,QAAQ,CAAC,QAAQ,CAAC,IAAI,gBAAgB,EAAE,CAAC,CAAC;IAC1C,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Format auto-detection for specification files.
3
+ *
4
+ * Determines the {@link SpecFormat} of a specification file based on its
5
+ * file extension.
6
+ */
7
+ import type { SpecFormat } from './types.js';
8
+ /**
9
+ * Detect the specification format from a file's extension.
10
+ *
11
+ * @param filePath - Path to the specification file
12
+ * @returns The detected specification format
13
+ * @throws {@link ForgeError} with code `FORGE-SPEC-001` if the extension is unsupported
14
+ */
15
+ export declare function detectFormat(filePath: string): SpecFormat;
16
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAa7C;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAWzD"}
package/dist/detect.js ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Format auto-detection for specification files.
3
+ *
4
+ * Determines the {@link SpecFormat} of a specification file based on its
5
+ * file extension.
6
+ */
7
+ import path from 'node:path';
8
+ import { ForgeError, ErrorCodes } from '@hstm-labs/forge-common';
9
+ /** Map of file extensions to specification formats. */
10
+ const EXTENSION_MAP = new Map([
11
+ ['.md', 'markdown'],
12
+ ['.yaml', 'yaml'],
13
+ ['.yml', 'yaml'],
14
+ ['.json', 'json'],
15
+ ]);
16
+ /**
17
+ * Detect the specification format from a file's extension.
18
+ *
19
+ * @param filePath - Path to the specification file
20
+ * @returns The detected specification format
21
+ * @throws {@link ForgeError} with code `FORGE-SPEC-001` if the extension is unsupported
22
+ */
23
+ export function detectFormat(filePath) {
24
+ const ext = path.extname(filePath).toLowerCase();
25
+ const format = EXTENSION_MAP.get(ext);
26
+ if (!format) {
27
+ throw new ForgeError(ErrorCodes.SPEC.PARSE_FAILURE, `Unsupported specification format: '${ext || '(no extension)'}'. ` +
28
+ `Supported: .md, .yaml, .yml, .json`);
29
+ }
30
+ return format;
31
+ }
32
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGjE,uDAAuD;AACvD,MAAM,aAAa,GAAoC,IAAI,GAAG,CAG5D;IACA,CAAC,KAAK,EAAE,UAAU,CAAC;IACnB,CAAC,OAAO,EAAE,MAAM,CAAC;IACjB,CAAC,MAAM,EAAE,MAAM,CAAC;IAChB,CAAC,OAAO,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACjD,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,UAAU,CAClB,UAAU,CAAC,IAAI,CAAC,aAAa,EAC7B,sCAAsC,GAAG,IAAI,gBAAgB,KAAK;YAChE,oCAAoC,CACvC,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,18 @@
1
+ export type { SpecFormat, ParsedSpecification, SpecMetadata, SpecSection, SpecRequirement, SpecEntity, EntityField, EntityRelationship, SpecWorkflow, WorkflowStep, } from './types.js';
2
+ export type { SpecParserPlugin } from './parser-plugin.js';
3
+ export { ParserRegistry } from './registry.js';
4
+ export { detectFormat } from './detect.js';
5
+ export { loadSpecFile, parseSpec } from './loader.js';
6
+ export { MarkdownParserPlugin } from './parsers/markdown-parser.js';
7
+ export { YamlParserPlugin } from './parsers/yaml-parser.js';
8
+ export { JsonParserPlugin } from './parsers/json-parser.js';
9
+ export { mapStructuredSpec } from './parsers/structured-mapper.js';
10
+ export { createDefaultRegistry } from './default-registry.js';
11
+ export type { ValidationSeverity, ValidationCategory, ValidationFinding, ValidationReport, } from './validation-types.js';
12
+ export { validateSchema } from './validators/schema-validator.js';
13
+ export { checkCompleteness } from './validators/completeness-checker.js';
14
+ export type { CompletenessResult } from './validators/completeness-checker.js';
15
+ export { validateCrossReferences } from './validators/cross-reference-validator.js';
16
+ export { validateSpec } from './validators/spec-validator.js';
17
+ export { executeValidateStage } from './validate-stage.js';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,YAAY,EACZ,WAAW,EACX,eAAe,EACf,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AACzE,YAAY,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAG9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ // @hstm-labs/forge-spec-parser public API
2
+ // Parser registry
3
+ export { ParserRegistry } from './registry.js';
4
+ // Format detection
5
+ export { detectFormat } from './detect.js';
6
+ // File loading and parse entry point
7
+ export { loadSpecFile, parseSpec } from './loader.js';
8
+ // Parser plugins
9
+ export { MarkdownParserPlugin } from './parsers/markdown-parser.js';
10
+ export { YamlParserPlugin } from './parsers/yaml-parser.js';
11
+ export { JsonParserPlugin } from './parsers/json-parser.js';
12
+ // Shared structured mapper
13
+ export { mapStructuredSpec } from './parsers/structured-mapper.js';
14
+ // Default registry factory
15
+ export { createDefaultRegistry } from './default-registry.js';
16
+ // Validators
17
+ export { validateSchema } from './validators/schema-validator.js';
18
+ export { checkCompleteness } from './validators/completeness-checker.js';
19
+ export { validateCrossReferences } from './validators/cross-reference-validator.js';
20
+ export { validateSpec } from './validators/spec-validator.js';
21
+ // Validate stage integration
22
+ export { executeValidateStage } from './validate-stage.js';
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAmB1C,kBAAkB;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,qCAAqC;AACrC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEtD,iBAAiB;AACjB,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,2BAA2B;AAC3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,2BAA2B;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAU9D,aAAa;AACb,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAEzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAE9D,6BAA6B;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Specification file loader and primary parse entry point.
3
+ *
4
+ * Provides {@link loadSpecFile} for reading raw file content and
5
+ * {@link parseSpec} as the main public API for parsing a specification
6
+ * file into the canonical {@link ParsedSpecification} model.
7
+ */
8
+ import type { ParsedSpecification } from './types.js';
9
+ import type { ParserRegistry } from './registry.js';
10
+ /**
11
+ * Read the content of a specification file from disk.
12
+ *
13
+ * @param filePath - Absolute or relative path to the specification file
14
+ * @returns The file content as a UTF-8 string
15
+ * @throws {@link ForgeError} with code `FORGE-SPEC-001` if the file cannot be read
16
+ */
17
+ export declare function loadSpecFile(filePath: string): string;
18
+ /**
19
+ * Parse a specification file into the canonical model.
20
+ *
21
+ * Detects the file format, selects the appropriate parser plugin from the
22
+ * registry, reads the file content, and delegates to the plugin's `parse`
23
+ * method.
24
+ *
25
+ * @param filePath - Path to the specification file
26
+ * @param registry - Parser registry with registered format plugins
27
+ * @returns Parsed specification
28
+ * @throws {@link ForgeError} with code `FORGE-SPEC-001` if format detection, file reading, or parsing fails
29
+ */
30
+ export declare function parseSpec(filePath: string, registry: ParserRegistry): ParsedSpecification;
31
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,GACvB,mBAAmB,CAKrB"}
package/dist/loader.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Specification file loader and primary parse entry point.
3
+ *
4
+ * Provides {@link loadSpecFile} for reading raw file content and
5
+ * {@link parseSpec} as the main public API for parsing a specification
6
+ * file into the canonical {@link ParsedSpecification} model.
7
+ */
8
+ import fs from 'node:fs';
9
+ import { ForgeError, ErrorCodes } from '@hstm-labs/forge-common';
10
+ import { detectFormat } from './detect.js';
11
+ /**
12
+ * Read the content of a specification file from disk.
13
+ *
14
+ * @param filePath - Absolute or relative path to the specification file
15
+ * @returns The file content as a UTF-8 string
16
+ * @throws {@link ForgeError} with code `FORGE-SPEC-001` if the file cannot be read
17
+ */
18
+ export function loadSpecFile(filePath) {
19
+ try {
20
+ return fs.readFileSync(filePath, 'utf-8');
21
+ }
22
+ catch (error) {
23
+ throw new ForgeError(ErrorCodes.SPEC.PARSE_FAILURE, `Failed to read specification file '${filePath}'. ` +
24
+ `Ensure the file exists and is readable, then retry.`, error instanceof Error ? { cause: error } : {});
25
+ }
26
+ }
27
+ /**
28
+ * Parse a specification file into the canonical model.
29
+ *
30
+ * Detects the file format, selects the appropriate parser plugin from the
31
+ * registry, reads the file content, and delegates to the plugin's `parse`
32
+ * method.
33
+ *
34
+ * @param filePath - Path to the specification file
35
+ * @param registry - Parser registry with registered format plugins
36
+ * @returns Parsed specification
37
+ * @throws {@link ForgeError} with code `FORGE-SPEC-001` if format detection, file reading, or parsing fails
38
+ */
39
+ export function parseSpec(filePath, registry) {
40
+ const format = detectFormat(filePath);
41
+ const plugin = registry.getParser(format);
42
+ const content = loadSpecFile(filePath);
43
+ return plugin.parse(content, filePath);
44
+ }
45
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,UAAU,CAClB,UAAU,CAAC,IAAI,CAAC,aAAa,EAC7B,sCAAsC,QAAQ,KAAK;YACjD,qDAAqD,EACvD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAC/C,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CACvB,QAAgB,EAChB,QAAwB;IAExB,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvC,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Plugin interface for format-specific specification parsers.
3
+ *
4
+ * Each plugin handles a single {@link SpecFormat} and converts raw file
5
+ * content into the canonical {@link ParsedSpecification} model.
6
+ */
7
+ import type { ParsedSpecification, SpecFormat } from './types.js';
8
+ /** Contract that all format-specific parsers must implement. */
9
+ export interface SpecParserPlugin {
10
+ /** Format this plugin handles. */
11
+ readonly format: SpecFormat;
12
+ /** File extensions this plugin handles (e.g. `['.md']`). */
13
+ readonly extensions: string[];
14
+ /**
15
+ * Parse raw content into the canonical specification model.
16
+ *
17
+ * @param content - Raw file content as a string
18
+ * @param sourcePath - Original file path (used for metadata)
19
+ * @returns Parsed specification
20
+ */
21
+ parse(content: string, sourcePath: string): ParsedSpecification;
22
+ }
23
+ //# sourceMappingURL=parser-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser-plugin.d.ts","sourceRoot":"","sources":["../src/parser-plugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAElE,gEAAgE;AAChE,MAAM,WAAW,gBAAgB;IAC/B,kCAAkC;IAClC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAE5B,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAE9B;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB,CAAC;CACjE"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Plugin interface for format-specific specification parsers.
3
+ *
4
+ * Each plugin handles a single {@link SpecFormat} and converts raw file
5
+ * content into the canonical {@link ParsedSpecification} model.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=parser-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser-plugin.js","sourceRoot":"","sources":["../src/parser-plugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * JSON specification parser plugin.
3
+ *
4
+ * Parses structured JSON specification files into the canonical
5
+ * {@link ParsedSpecification} model by delegating to the shared
6
+ * structured mapper after JSON parsing.
7
+ */
8
+ import type { SpecParserPlugin } from '../parser-plugin.js';
9
+ import type { ParsedSpecification, SpecFormat } from '../types.js';
10
+ /**
11
+ * Parser plugin for JSON specification files (`.json`).
12
+ *
13
+ * Expects a structured JSON object with top-level fields matching
14
+ * the {@link ParsedSpecification} shape (title, requirements, entities, etc.).
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const plugin = new JsonParserPlugin();
19
+ * const spec = plugin.parse(jsonContent, '/path/to/spec.json');
20
+ * ```
21
+ */
22
+ export declare class JsonParserPlugin implements SpecParserPlugin {
23
+ readonly format: SpecFormat;
24
+ readonly extensions: string[];
25
+ /**
26
+ * Parse JSON specification content into the canonical model.
27
+ *
28
+ * @param content - Raw JSON content
29
+ * @param sourcePath - Original file path
30
+ * @returns Parsed specification
31
+ * @throws {@link ForgeError} with code `FORGE-SPEC-001` if JSON parsing fails or title is missing
32
+ */
33
+ parse(content: string, sourcePath: string): ParsedSpecification;
34
+ }
35
+ //# sourceMappingURL=json-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/json-parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGnE;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAiB,YAAW,gBAAgB;IACvD,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAU;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAa;IAE1C;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB;CAgBhE"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * JSON specification parser plugin.
3
+ *
4
+ * Parses structured JSON specification files into the canonical
5
+ * {@link ParsedSpecification} model by delegating to the shared
6
+ * structured mapper after JSON parsing.
7
+ */
8
+ import { ForgeError, ErrorCodes } from '@hstm-labs/forge-common';
9
+ import { mapStructuredSpec } from './structured-mapper.js';
10
+ /**
11
+ * Parser plugin for JSON specification files (`.json`).
12
+ *
13
+ * Expects a structured JSON object with top-level fields matching
14
+ * the {@link ParsedSpecification} shape (title, requirements, entities, etc.).
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const plugin = new JsonParserPlugin();
19
+ * const spec = plugin.parse(jsonContent, '/path/to/spec.json');
20
+ * ```
21
+ */
22
+ export class JsonParserPlugin {
23
+ format = 'json';
24
+ extensions = ['.json'];
25
+ /**
26
+ * Parse JSON specification content into the canonical model.
27
+ *
28
+ * @param content - Raw JSON content
29
+ * @param sourcePath - Original file path
30
+ * @returns Parsed specification
31
+ * @throws {@link ForgeError} with code `FORGE-SPEC-001` if JSON parsing fails or title is missing
32
+ */
33
+ parse(content, sourcePath) {
34
+ let data;
35
+ try {
36
+ data = JSON.parse(content);
37
+ }
38
+ catch (error) {
39
+ throw new ForgeError(ErrorCodes.SPEC.PARSE_FAILURE, `Invalid JSON in specification file '${sourcePath}': ` +
40
+ `${error instanceof Error ? error.message : String(error)}. ` +
41
+ `Verify the file contains valid JSON.`, error instanceof Error ? { cause: error } : {});
42
+ }
43
+ return mapStructuredSpec(data, sourcePath, 'json');
44
+ }
45
+ }
46
+ //# sourceMappingURL=json-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-parser.js","sourceRoot":"","sources":["../../src/parsers/json-parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,gBAAgB;IAClB,MAAM,GAAe,MAAM,CAAC;IAC5B,UAAU,GAAa,CAAC,OAAO,CAAC,CAAC;IAE1C;;;;;;;OAOG;IACH,KAAK,CAAC,OAAe,EAAE,UAAkB;QACvC,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAY,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,UAAU,CAClB,UAAU,CAAC,IAAI,CAAC,aAAa,EAC7B,uCAAuC,UAAU,KAAK;gBACpD,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI;gBAC7D,sCAAsC,EACxC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAC/C,CAAC;QACJ,CAAC;QAED,OAAO,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC;CACF"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Markdown specification parser plugin.
3
+ *
4
+ * Converts rich Markdown specification documents into the canonical
5
+ * {@link ParsedSpecification} model using a two-phase pipeline:
6
+ * 1. Markdown → mdast (Abstract Syntax Tree) via unified/remark
7
+ * 2. mdast → ParsedSpecification via AST walking and extraction
8
+ */
9
+ import type { SpecParserPlugin } from '../parser-plugin.js';
10
+ import type { ParsedSpecification, SpecFormat } from '../types.js';
11
+ /**
12
+ * Parser plugin for Markdown specification files.
13
+ *
14
+ * Implements the two-phase Markdown → AST → ParsedSpecification pipeline.
15
+ * Supports YAML frontmatter, GFM tables, task lists, and ordered lists.
16
+ */
17
+ export declare class MarkdownParserPlugin implements SpecParserPlugin {
18
+ readonly format: SpecFormat;
19
+ readonly extensions: string[];
20
+ /**
21
+ * Parse a Markdown specification into the canonical model.
22
+ *
23
+ * @param content - Raw Markdown content
24
+ * @param sourcePath - Original file path
25
+ * @returns Parsed specification
26
+ */
27
+ parse(content: string, sourcePath: string): ParsedSpecification;
28
+ private extractMetadata;
29
+ private extractSections;
30
+ private extractRequirements;
31
+ private listItemToRequirement;
32
+ private extractEntities;
33
+ private extractEntitiesFromNodes;
34
+ private buildEntity;
35
+ private parseTableFields;
36
+ private parseListFields;
37
+ private extractWorkflows;
38
+ private buildWorkflow;
39
+ private detectApiStyle;
40
+ }
41
+ //# sourceMappingURL=markdown-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/markdown-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EACV,mBAAmB,EASnB,UAAU,EACX,MAAM,aAAa,CAAC;AA6OrB;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,gBAAgB;IAC3D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAc;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAW;IAExC;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB;IAmC/D,OAAO,CAAC,eAAe;IA0DvB,OAAO,CAAC,eAAe;IAwDvB,OAAO,CAAC,mBAAmB;IAqB3B,OAAO,CAAC,qBAAqB;IAmD7B,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,wBAAwB;IAsEhC,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,gBAAgB;IAsDxB,OAAO,CAAC,eAAe;IAyCvB,OAAO,CAAC,gBAAgB;IA6CxB,OAAO,CAAC,aAAa;IA2DrB,OAAO,CAAC,cAAc;CAUvB"}