@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.
- package/README.md +53 -0
- package/dist/default-registry.d.ts +19 -0
- package/dist/default-registry.d.ts.map +1 -0
- package/dist/default-registry.js +28 -0
- package/dist/default-registry.js.map +1 -0
- package/dist/detect.d.ts +16 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +32 -0
- package/dist/detect.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +31 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +45 -0
- package/dist/loader.js.map +1 -0
- package/dist/parser-plugin.d.ts +23 -0
- package/dist/parser-plugin.d.ts.map +1 -0
- package/dist/parser-plugin.js +8 -0
- package/dist/parser-plugin.js.map +1 -0
- package/dist/parsers/json-parser.d.ts +35 -0
- package/dist/parsers/json-parser.d.ts.map +1 -0
- package/dist/parsers/json-parser.js +46 -0
- package/dist/parsers/json-parser.js.map +1 -0
- package/dist/parsers/markdown-parser.d.ts +41 -0
- package/dist/parsers/markdown-parser.d.ts.map +1 -0
- package/dist/parsers/markdown-parser.js +606 -0
- package/dist/parsers/markdown-parser.js.map +1 -0
- package/dist/parsers/structured-mapper.d.ts +22 -0
- package/dist/parsers/structured-mapper.d.ts.map +1 -0
- package/dist/parsers/structured-mapper.js +214 -0
- package/dist/parsers/structured-mapper.js.map +1 -0
- package/dist/parsers/yaml-parser.d.ts +35 -0
- package/dist/parsers/yaml-parser.d.ts.map +1 -0
- package/dist/parsers/yaml-parser.js +47 -0
- package/dist/parsers/yaml-parser.js.map +1 -0
- package/dist/registry.d.ts +57 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +80 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/validate-stage.d.ts +18 -0
- package/dist/validate-stage.d.ts.map +1 -0
- package/dist/validate-stage.js +24 -0
- package/dist/validate-stage.js.map +1 -0
- package/dist/validation-types.d.ts +46 -0
- package/dist/validation-types.d.ts.map +1 -0
- package/dist/validation-types.js +9 -0
- package/dist/validation-types.js.map +1 -0
- package/dist/validators/completeness-checker.d.ts +29 -0
- package/dist/validators/completeness-checker.d.ts.map +1 -0
- package/dist/validators/completeness-checker.js +127 -0
- package/dist/validators/completeness-checker.js.map +1 -0
- package/dist/validators/cross-reference-validator.d.ts +17 -0
- package/dist/validators/cross-reference-validator.d.ts.map +1 -0
- package/dist/validators/cross-reference-validator.js +150 -0
- package/dist/validators/cross-reference-validator.js.map +1 -0
- package/dist/validators/schema-validator.d.ts +16 -0
- package/dist/validators/schema-validator.d.ts.map +1 -0
- package/dist/validators/schema-validator.js +146 -0
- package/dist/validators/schema-validator.js.map +1 -0
- package/dist/validators/spec-validator.d.ts +15 -0
- package/dist/validators/spec-validator.d.ts.map +1 -0
- package/dist/validators/spec-validator.js +52 -0
- package/dist/validators/spec-validator.js.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared mapping logic for structured (YAML / JSON) specification files.
|
|
3
|
+
*
|
|
4
|
+
* Both the YAML and JSON parsers produce a raw `unknown` object after parsing
|
|
5
|
+
* their respective formats. This module validates the structure and maps it
|
|
6
|
+
* into the canonical {@link ParsedSpecification} model.
|
|
7
|
+
*/
|
|
8
|
+
import { ForgeError, ErrorCodes } from '@hstm-labs/forge-common';
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Type Guards / Helpers
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/** Narrow `unknown` to a non-null record. */
|
|
13
|
+
function isRecord(val) {
|
|
14
|
+
return typeof val === 'object' && val !== null && !Array.isArray(val);
|
|
15
|
+
}
|
|
16
|
+
/** Safely extract a string value, returning `undefined` if not a string. */
|
|
17
|
+
function asString(val) {
|
|
18
|
+
return typeof val === 'string' ? val : undefined;
|
|
19
|
+
}
|
|
20
|
+
/** Safely extract an array, returning `[]` if not an array. */
|
|
21
|
+
function asArray(val) {
|
|
22
|
+
return Array.isArray(val) ? val : [];
|
|
23
|
+
}
|
|
24
|
+
/** Safely extract a string array, filtering non-string elements. */
|
|
25
|
+
function asStringArray(val) {
|
|
26
|
+
return asArray(val).filter((v) => typeof v === 'string');
|
|
27
|
+
}
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Validation Constants
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
const VALID_PRIORITIES = new Set([
|
|
32
|
+
'must',
|
|
33
|
+
'should',
|
|
34
|
+
'could',
|
|
35
|
+
'wont',
|
|
36
|
+
]);
|
|
37
|
+
const VALID_RELATIONSHIP_TYPES = new Set([
|
|
38
|
+
'one-to-one',
|
|
39
|
+
'one-to-many',
|
|
40
|
+
'many-to-many',
|
|
41
|
+
]);
|
|
42
|
+
const VALID_API_STYLES = new Set(['rest', 'graphql', 'grpc']);
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Public Mapper
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
/**
|
|
47
|
+
* Map a parsed structured object into the canonical specification model.
|
|
48
|
+
*
|
|
49
|
+
* Validates the data structure (title required, arrays are arrays, etc.)
|
|
50
|
+
* and maps to canonical types with safe defaults.
|
|
51
|
+
*
|
|
52
|
+
* @param data - Raw parsed data (from YAML or JSON)
|
|
53
|
+
* @param sourcePath - Original file path
|
|
54
|
+
* @param format - Specification format (`'yaml'` or `'json'`)
|
|
55
|
+
* @returns Parsed specification
|
|
56
|
+
* @throws {@link ForgeError} with code `FORGE-SPEC-001` if `title` is missing or data is not an object
|
|
57
|
+
*/
|
|
58
|
+
export function mapStructuredSpec(data, sourcePath, format) {
|
|
59
|
+
if (!isRecord(data)) {
|
|
60
|
+
throw new ForgeError(ErrorCodes.SPEC.PARSE_FAILURE, `Specification file '${sourcePath}' must contain a top-level object. ` +
|
|
61
|
+
`Ensure the file has a valid ${format.toUpperCase()} object structure.`);
|
|
62
|
+
}
|
|
63
|
+
const title = asString(data['title']);
|
|
64
|
+
if (!title) {
|
|
65
|
+
throw new ForgeError(ErrorCodes.SPEC.PARSE_FAILURE, `Specification file '${sourcePath}' is missing required field 'title'. ` +
|
|
66
|
+
`Add a 'title' string field at the top level of the specification.`);
|
|
67
|
+
}
|
|
68
|
+
const metadata = mapMetadata(data, title, sourcePath, format);
|
|
69
|
+
const sections = asArray(data['sections']).map(mapSection);
|
|
70
|
+
const requirements = asArray(data['requirements']).map(mapRequirement);
|
|
71
|
+
const entities = asArray(data['entities']).map(mapEntity);
|
|
72
|
+
const workflows = asArray(data['workflows']).map(mapWorkflow);
|
|
73
|
+
const result = {
|
|
74
|
+
metadata,
|
|
75
|
+
sections,
|
|
76
|
+
requirements,
|
|
77
|
+
entities,
|
|
78
|
+
workflows,
|
|
79
|
+
};
|
|
80
|
+
const apiStyleRaw = asString(data['apiStyle']);
|
|
81
|
+
if (apiStyleRaw && VALID_API_STYLES.has(apiStyleRaw)) {
|
|
82
|
+
result.apiStyle = apiStyleRaw;
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Individual Mappers
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
function mapMetadata(data, title, sourcePath, format) {
|
|
90
|
+
const metadata = {
|
|
91
|
+
title,
|
|
92
|
+
sourcePath,
|
|
93
|
+
format,
|
|
94
|
+
};
|
|
95
|
+
const version = asString(data['version']);
|
|
96
|
+
if (version !== undefined)
|
|
97
|
+
metadata.version = version;
|
|
98
|
+
const description = asString(data['description']);
|
|
99
|
+
if (description !== undefined)
|
|
100
|
+
metadata.description = description;
|
|
101
|
+
const authors = asStringArray(data['authors']);
|
|
102
|
+
if (authors.length > 0)
|
|
103
|
+
metadata.authors = authors;
|
|
104
|
+
return metadata;
|
|
105
|
+
}
|
|
106
|
+
function mapSection(raw) {
|
|
107
|
+
if (!isRecord(raw)) {
|
|
108
|
+
return { id: '', title: '', level: 1, content: '', subsections: [] };
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
id: asString(raw['id']) ?? '',
|
|
112
|
+
title: asString(raw['title']) ?? '',
|
|
113
|
+
level: typeof raw['level'] === 'number' ? raw['level'] : 1,
|
|
114
|
+
content: asString(raw['content']) ?? '',
|
|
115
|
+
subsections: asArray(raw['subsections']).map(mapSection),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function mapRequirement(raw) {
|
|
119
|
+
if (!isRecord(raw)) {
|
|
120
|
+
return {
|
|
121
|
+
id: '',
|
|
122
|
+
title: '',
|
|
123
|
+
description: '',
|
|
124
|
+
acceptanceCriteria: [],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const req = {
|
|
128
|
+
id: asString(raw['id']) ?? '',
|
|
129
|
+
title: asString(raw['title']) ?? '',
|
|
130
|
+
description: asString(raw['description']) ?? '',
|
|
131
|
+
acceptanceCriteria: asStringArray(raw['acceptanceCriteria']),
|
|
132
|
+
};
|
|
133
|
+
const priority = asString(raw['priority']);
|
|
134
|
+
if (priority && VALID_PRIORITIES.has(priority)) {
|
|
135
|
+
req.priority = priority;
|
|
136
|
+
}
|
|
137
|
+
return req;
|
|
138
|
+
}
|
|
139
|
+
function mapEntity(raw) {
|
|
140
|
+
if (!isRecord(raw)) {
|
|
141
|
+
return { name: '', fields: [], relationships: [] };
|
|
142
|
+
}
|
|
143
|
+
const entity = {
|
|
144
|
+
name: asString(raw['name']) ?? '',
|
|
145
|
+
fields: asArray(raw['fields']).map(mapEntityField),
|
|
146
|
+
relationships: asArray(raw['relationships']).map(mapEntityRelationship),
|
|
147
|
+
};
|
|
148
|
+
const description = asString(raw['description']);
|
|
149
|
+
if (description !== undefined)
|
|
150
|
+
entity.description = description;
|
|
151
|
+
return entity;
|
|
152
|
+
}
|
|
153
|
+
function mapEntityField(raw) {
|
|
154
|
+
if (!isRecord(raw)) {
|
|
155
|
+
return { name: '', type: 'string', required: false };
|
|
156
|
+
}
|
|
157
|
+
const field = {
|
|
158
|
+
name: asString(raw['name']) ?? '',
|
|
159
|
+
type: asString(raw['type']) ?? 'string',
|
|
160
|
+
required: typeof raw['required'] === 'boolean' ? raw['required'] : false,
|
|
161
|
+
};
|
|
162
|
+
const description = asString(raw['description']);
|
|
163
|
+
if (description !== undefined)
|
|
164
|
+
field.description = description;
|
|
165
|
+
return field;
|
|
166
|
+
}
|
|
167
|
+
function mapEntityRelationship(raw) {
|
|
168
|
+
if (!isRecord(raw)) {
|
|
169
|
+
return { target: '', type: 'one-to-many' };
|
|
170
|
+
}
|
|
171
|
+
const rel = {
|
|
172
|
+
target: asString(raw['target']) ?? '',
|
|
173
|
+
type: 'one-to-many',
|
|
174
|
+
};
|
|
175
|
+
const typeRaw = asString(raw['type']);
|
|
176
|
+
if (typeRaw && VALID_RELATIONSHIP_TYPES.has(typeRaw)) {
|
|
177
|
+
rel.type = typeRaw;
|
|
178
|
+
}
|
|
179
|
+
const description = asString(raw['description']);
|
|
180
|
+
if (description !== undefined)
|
|
181
|
+
rel.description = description;
|
|
182
|
+
return rel;
|
|
183
|
+
}
|
|
184
|
+
function mapWorkflow(raw) {
|
|
185
|
+
if (!isRecord(raw)) {
|
|
186
|
+
return { id: '', name: '', steps: [] };
|
|
187
|
+
}
|
|
188
|
+
const workflow = {
|
|
189
|
+
id: asString(raw['id']) ?? '',
|
|
190
|
+
name: asString(raw['name']) ?? '',
|
|
191
|
+
steps: asArray(raw['steps']).map(mapWorkflowStep),
|
|
192
|
+
};
|
|
193
|
+
const description = asString(raw['description']);
|
|
194
|
+
if (description !== undefined)
|
|
195
|
+
workflow.description = description;
|
|
196
|
+
const actors = asStringArray(raw['actors']);
|
|
197
|
+
if (actors.length > 0)
|
|
198
|
+
workflow.actors = actors;
|
|
199
|
+
return workflow;
|
|
200
|
+
}
|
|
201
|
+
function mapWorkflowStep(raw) {
|
|
202
|
+
if (!isRecord(raw)) {
|
|
203
|
+
return { order: 0, action: '' };
|
|
204
|
+
}
|
|
205
|
+
const step = {
|
|
206
|
+
order: typeof raw['order'] === 'number' ? raw['order'] : 0,
|
|
207
|
+
action: asString(raw['action']) ?? '',
|
|
208
|
+
};
|
|
209
|
+
const expectedResult = asString(raw['expectedResult']);
|
|
210
|
+
if (expectedResult !== undefined)
|
|
211
|
+
step.expectedResult = expectedResult;
|
|
212
|
+
return step;
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=structured-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-mapper.js","sourceRoot":"","sources":["../../src/parsers/structured-mapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YAML specification parser plugin.
|
|
3
|
+
*
|
|
4
|
+
* Parses structured YAML specification files into the canonical
|
|
5
|
+
* {@link ParsedSpecification} model by delegating to the shared
|
|
6
|
+
* structured mapper after YAML parsing.
|
|
7
|
+
*/
|
|
8
|
+
import type { SpecParserPlugin } from '../parser-plugin.js';
|
|
9
|
+
import type { ParsedSpecification, SpecFormat } from '../types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Parser plugin for YAML specification files (`.yaml`, `.yml`).
|
|
12
|
+
*
|
|
13
|
+
* Expects a structured YAML document with top-level fields matching
|
|
14
|
+
* the {@link ParsedSpecification} shape (title, requirements, entities, etc.).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const plugin = new YamlParserPlugin();
|
|
19
|
+
* const spec = plugin.parse(yamlContent, '/path/to/spec.yaml');
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare class YamlParserPlugin implements SpecParserPlugin {
|
|
23
|
+
readonly format: SpecFormat;
|
|
24
|
+
readonly extensions: string[];
|
|
25
|
+
/**
|
|
26
|
+
* Parse YAML specification content into the canonical model.
|
|
27
|
+
*
|
|
28
|
+
* @param content - Raw YAML content
|
|
29
|
+
* @param sourcePath - Original file path
|
|
30
|
+
* @returns Parsed specification
|
|
31
|
+
* @throws {@link ForgeError} with code `FORGE-SPEC-001` if YAML parsing fails or title is missing
|
|
32
|
+
*/
|
|
33
|
+
parse(content: string, sourcePath: string): ParsedSpecification;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=yaml-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/yaml-parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,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,CAAqB;IAElD;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB;CAgBhE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YAML specification parser plugin.
|
|
3
|
+
*
|
|
4
|
+
* Parses structured YAML specification files into the canonical
|
|
5
|
+
* {@link ParsedSpecification} model by delegating to the shared
|
|
6
|
+
* structured mapper after YAML parsing.
|
|
7
|
+
*/
|
|
8
|
+
import { parse as parseYaml } from 'yaml';
|
|
9
|
+
import { ForgeError, ErrorCodes } from '@hstm-labs/forge-common';
|
|
10
|
+
import { mapStructuredSpec } from './structured-mapper.js';
|
|
11
|
+
/**
|
|
12
|
+
* Parser plugin for YAML specification files (`.yaml`, `.yml`).
|
|
13
|
+
*
|
|
14
|
+
* Expects a structured YAML document with top-level fields matching
|
|
15
|
+
* the {@link ParsedSpecification} shape (title, requirements, entities, etc.).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const plugin = new YamlParserPlugin();
|
|
20
|
+
* const spec = plugin.parse(yamlContent, '/path/to/spec.yaml');
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export class YamlParserPlugin {
|
|
24
|
+
format = 'yaml';
|
|
25
|
+
extensions = ['.yaml', '.yml'];
|
|
26
|
+
/**
|
|
27
|
+
* Parse YAML specification content into the canonical model.
|
|
28
|
+
*
|
|
29
|
+
* @param content - Raw YAML content
|
|
30
|
+
* @param sourcePath - Original file path
|
|
31
|
+
* @returns Parsed specification
|
|
32
|
+
* @throws {@link ForgeError} with code `FORGE-SPEC-001` if YAML parsing fails or title is missing
|
|
33
|
+
*/
|
|
34
|
+
parse(content, sourcePath) {
|
|
35
|
+
let data;
|
|
36
|
+
try {
|
|
37
|
+
data = parseYaml(content);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw new ForgeError(ErrorCodes.SPEC.PARSE_FAILURE, `Invalid YAML in specification file '${sourcePath}': ` +
|
|
41
|
+
`${error instanceof Error ? error.message : String(error)}. ` +
|
|
42
|
+
`Verify the file contains valid YAML.`, error instanceof Error ? { cause: error } : {});
|
|
43
|
+
}
|
|
44
|
+
return mapStructuredSpec(data, sourcePath, 'yaml');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=yaml-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml-parser.js","sourceRoot":"","sources":["../../src/parsers/yaml-parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,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,EAAE,MAAM,CAAC,CAAC;IAElD;;;;;;;OAOG;IACH,KAAK,CAAC,OAAe,EAAE,UAAkB;QACvC,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAC5B,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,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser registry — manages format-specific parser plugins.
|
|
3
|
+
*
|
|
4
|
+
* Plugins are registered at startup and looked up by format or file extension
|
|
5
|
+
* when parsing specification files.
|
|
6
|
+
*/
|
|
7
|
+
import type { SpecFormat } from './types.js';
|
|
8
|
+
import type { SpecParserPlugin } from './parser-plugin.js';
|
|
9
|
+
/**
|
|
10
|
+
* Registry of {@link SpecParserPlugin} instances keyed by format and extension.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const registry = new ParserRegistry();
|
|
15
|
+
* registry.register(myMarkdownPlugin);
|
|
16
|
+
* const plugin = registry.getParser('markdown');
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare class ParserRegistry {
|
|
20
|
+
private readonly byFormat;
|
|
21
|
+
private readonly byExtension;
|
|
22
|
+
/**
|
|
23
|
+
* Register a parser plugin for its declared format and extensions.
|
|
24
|
+
*
|
|
25
|
+
* @param plugin - The parser plugin to register
|
|
26
|
+
*/
|
|
27
|
+
register(plugin: SpecParserPlugin): void;
|
|
28
|
+
/**
|
|
29
|
+
* Retrieve a parser plugin by specification format.
|
|
30
|
+
*
|
|
31
|
+
* @param format - The specification format to look up
|
|
32
|
+
* @returns The registered parser plugin
|
|
33
|
+
* @throws {@link ForgeError} with code `FORGE-SPEC-001` if no plugin is registered for the format
|
|
34
|
+
*/
|
|
35
|
+
getParser(format: SpecFormat): SpecParserPlugin;
|
|
36
|
+
/**
|
|
37
|
+
* Retrieve a parser plugin by file extension.
|
|
38
|
+
*
|
|
39
|
+
* @param extension - The file extension to look up (e.g. `'.md'`)
|
|
40
|
+
* @returns The registered parser plugin
|
|
41
|
+
* @throws {@link ForgeError} with code `FORGE-SPEC-001` if no plugin handles the extension
|
|
42
|
+
*/
|
|
43
|
+
getParserForExtension(extension: string): SpecParserPlugin;
|
|
44
|
+
/**
|
|
45
|
+
* List all registered specification formats.
|
|
46
|
+
*
|
|
47
|
+
* @returns Array of registered format identifiers
|
|
48
|
+
*/
|
|
49
|
+
getSupportedFormats(): SpecFormat[];
|
|
50
|
+
/**
|
|
51
|
+
* List all registered file extensions.
|
|
52
|
+
*
|
|
53
|
+
* @returns Array of registered file extensions
|
|
54
|
+
*/
|
|
55
|
+
getSupportedExtensions(): string[];
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;;;;;;;GASG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;IACpE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuC;IAEnE;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAOxC;;;;;;OAMG;IACH,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB;IAY/C;;;;;;OAMG;IACH,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB;IAa1D;;;;OAIG;IACH,mBAAmB,IAAI,UAAU,EAAE;IAInC;;;;OAIG;IACH,sBAAsB,IAAI,MAAM,EAAE;CAGnC"}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser registry — manages format-specific parser plugins.
|
|
3
|
+
*
|
|
4
|
+
* Plugins are registered at startup and looked up by format or file extension
|
|
5
|
+
* when parsing specification files.
|
|
6
|
+
*/
|
|
7
|
+
import { ForgeError, ErrorCodes } from '@hstm-labs/forge-common';
|
|
8
|
+
/**
|
|
9
|
+
* Registry of {@link SpecParserPlugin} instances keyed by format and extension.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const registry = new ParserRegistry();
|
|
14
|
+
* registry.register(myMarkdownPlugin);
|
|
15
|
+
* const plugin = registry.getParser('markdown');
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export class ParserRegistry {
|
|
19
|
+
byFormat = new Map();
|
|
20
|
+
byExtension = new Map();
|
|
21
|
+
/**
|
|
22
|
+
* Register a parser plugin for its declared format and extensions.
|
|
23
|
+
*
|
|
24
|
+
* @param plugin - The parser plugin to register
|
|
25
|
+
*/
|
|
26
|
+
register(plugin) {
|
|
27
|
+
this.byFormat.set(plugin.format, plugin);
|
|
28
|
+
for (const ext of plugin.extensions) {
|
|
29
|
+
this.byExtension.set(ext.toLowerCase(), plugin);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Retrieve a parser plugin by specification format.
|
|
34
|
+
*
|
|
35
|
+
* @param format - The specification format to look up
|
|
36
|
+
* @returns The registered parser plugin
|
|
37
|
+
* @throws {@link ForgeError} with code `FORGE-SPEC-001` if no plugin is registered for the format
|
|
38
|
+
*/
|
|
39
|
+
getParser(format) {
|
|
40
|
+
const plugin = this.byFormat.get(format);
|
|
41
|
+
if (!plugin) {
|
|
42
|
+
throw new ForgeError(ErrorCodes.SPEC.PARSE_FAILURE, `No parser registered for format '${format}'. ` +
|
|
43
|
+
`Register a SpecParserPlugin for this format before parsing.`);
|
|
44
|
+
}
|
|
45
|
+
return plugin;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Retrieve a parser plugin by file extension.
|
|
49
|
+
*
|
|
50
|
+
* @param extension - The file extension to look up (e.g. `'.md'`)
|
|
51
|
+
* @returns The registered parser plugin
|
|
52
|
+
* @throws {@link ForgeError} with code `FORGE-SPEC-001` if no plugin handles the extension
|
|
53
|
+
*/
|
|
54
|
+
getParserForExtension(extension) {
|
|
55
|
+
const plugin = this.byExtension.get(extension.toLowerCase());
|
|
56
|
+
if (!plugin) {
|
|
57
|
+
const supported = this.getSupportedExtensions().join(', ');
|
|
58
|
+
throw new ForgeError(ErrorCodes.SPEC.PARSE_FAILURE, `No parser registered for extension '${extension}'. ` +
|
|
59
|
+
`Supported extensions: ${supported || '(none)'}.`);
|
|
60
|
+
}
|
|
61
|
+
return plugin;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* List all registered specification formats.
|
|
65
|
+
*
|
|
66
|
+
* @returns Array of registered format identifiers
|
|
67
|
+
*/
|
|
68
|
+
getSupportedFormats() {
|
|
69
|
+
return [...this.byFormat.keys()];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* List all registered file extensions.
|
|
73
|
+
*
|
|
74
|
+
* @returns Array of registered file extensions
|
|
75
|
+
*/
|
|
76
|
+
getSupportedExtensions() {
|
|
77
|
+
return [...this.byExtension.keys()];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAIjE;;;;;;;;;GASG;AACH,MAAM,OAAO,cAAc;IACR,QAAQ,GAAG,IAAI,GAAG,EAAgC,CAAC;IACnD,WAAW,GAAG,IAAI,GAAG,EAA4B,CAAC;IAEnE;;;;OAIG;IACH,QAAQ,CAAC,MAAwB;QAC/B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACpC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,SAAS,CAAC,MAAkB;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,UAAU,CAClB,UAAU,CAAC,IAAI,CAAC,aAAa,EAC7B,oCAAoC,MAAM,KAAK;gBAC7C,6DAA6D,CAChE,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;OAMG;IACH,qBAAqB,CAAC,SAAiB;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,SAAS,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3D,MAAM,IAAI,UAAU,CAClB,UAAU,CAAC,IAAI,CAAC,aAAa,EAC7B,uCAAuC,SAAS,KAAK;gBACnD,yBAAyB,SAAS,IAAI,QAAQ,GAAG,CACpD,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACH,mBAAmB;QACjB,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,sBAAsB;QACpB,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;CACF"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical model for parsed specifications.
|
|
3
|
+
*
|
|
4
|
+
* All format-specific parsers produce a `ParsedSpecification` instance,
|
|
5
|
+
* providing a normalized internal representation for downstream pipeline stages.
|
|
6
|
+
*/
|
|
7
|
+
/** Supported specification file formats. */
|
|
8
|
+
export type SpecFormat = 'markdown' | 'yaml' | 'json';
|
|
9
|
+
/** Normalized representation of a parsed specification. */
|
|
10
|
+
export interface ParsedSpecification {
|
|
11
|
+
/** Metadata about the specification. */
|
|
12
|
+
metadata: SpecMetadata;
|
|
13
|
+
/** Top-level sections extracted from the spec. */
|
|
14
|
+
sections: SpecSection[];
|
|
15
|
+
/** Functional requirements. */
|
|
16
|
+
requirements: SpecRequirement[];
|
|
17
|
+
/** Data entities and their relationships. */
|
|
18
|
+
entities: SpecEntity[];
|
|
19
|
+
/** User workflows / use cases. */
|
|
20
|
+
workflows: SpecWorkflow[];
|
|
21
|
+
/** Optional: API style declared in the specification. */
|
|
22
|
+
apiStyle?: 'rest' | 'graphql' | 'grpc' | undefined;
|
|
23
|
+
}
|
|
24
|
+
/** Metadata extracted from a specification file. */
|
|
25
|
+
export interface SpecMetadata {
|
|
26
|
+
title: string;
|
|
27
|
+
version?: string | undefined;
|
|
28
|
+
description?: string | undefined;
|
|
29
|
+
authors?: string[] | undefined;
|
|
30
|
+
/** Original file path. */
|
|
31
|
+
sourcePath: string;
|
|
32
|
+
/** Detected format. */
|
|
33
|
+
format: SpecFormat;
|
|
34
|
+
}
|
|
35
|
+
/** A hierarchical section within the specification. */
|
|
36
|
+
export interface SpecSection {
|
|
37
|
+
id: string;
|
|
38
|
+
title: string;
|
|
39
|
+
level: number;
|
|
40
|
+
content: string;
|
|
41
|
+
subsections: SpecSection[];
|
|
42
|
+
}
|
|
43
|
+
/** A functional requirement extracted from the specification. */
|
|
44
|
+
export interface SpecRequirement {
|
|
45
|
+
id: string;
|
|
46
|
+
title: string;
|
|
47
|
+
description: string;
|
|
48
|
+
priority?: 'must' | 'should' | 'could' | 'wont' | undefined;
|
|
49
|
+
acceptanceCriteria: string[];
|
|
50
|
+
}
|
|
51
|
+
/** A data entity described in the specification. */
|
|
52
|
+
export interface SpecEntity {
|
|
53
|
+
name: string;
|
|
54
|
+
description?: string | undefined;
|
|
55
|
+
fields: EntityField[];
|
|
56
|
+
relationships: EntityRelationship[];
|
|
57
|
+
}
|
|
58
|
+
/** A field on a data entity. */
|
|
59
|
+
export interface EntityField {
|
|
60
|
+
name: string;
|
|
61
|
+
type: string;
|
|
62
|
+
required: boolean;
|
|
63
|
+
description?: string | undefined;
|
|
64
|
+
}
|
|
65
|
+
/** A relationship between two entities. */
|
|
66
|
+
export interface EntityRelationship {
|
|
67
|
+
target: string;
|
|
68
|
+
type: 'one-to-one' | 'one-to-many' | 'many-to-many';
|
|
69
|
+
description?: string | undefined;
|
|
70
|
+
}
|
|
71
|
+
/** A user workflow or use case extracted from the specification. */
|
|
72
|
+
export interface SpecWorkflow {
|
|
73
|
+
id: string;
|
|
74
|
+
name: string;
|
|
75
|
+
description?: string | undefined;
|
|
76
|
+
steps: WorkflowStep[];
|
|
77
|
+
actors?: string[] | undefined;
|
|
78
|
+
}
|
|
79
|
+
/** A single step within a workflow. */
|
|
80
|
+
export interface WorkflowStep {
|
|
81
|
+
order: number;
|
|
82
|
+
action: string;
|
|
83
|
+
expectedResult?: string | undefined;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,4CAA4C;AAC5C,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAMtD,2DAA2D;AAC3D,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,QAAQ,EAAE,YAAY,CAAC;IAEvB,kDAAkD;IAClD,QAAQ,EAAE,WAAW,EAAE,CAAC;IAExB,+BAA+B;IAC/B,YAAY,EAAE,eAAe,EAAE,CAAC;IAEhC,6CAA6C;IAC7C,QAAQ,EAAE,UAAU,EAAE,CAAC;IAEvB,kCAAkC;IAClC,SAAS,EAAE,YAAY,EAAE,CAAC;IAE1B,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;CACpD;AAMD,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC/B,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,MAAM,EAAE,UAAU,CAAC;CACpB;AAMD,uDAAuD;AACvD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,WAAW,EAAE,CAAC;CAC5B;AAMD,iEAAiE;AACjE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAC5D,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAMD,oDAAoD;AACpD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,aAAa,EAAE,kBAAkB,EAAE,CAAC;CACrC;AAED,gCAAgC;AAChC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,2CAA2C;AAC3C,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,YAAY,GAAG,aAAa,GAAG,cAAc,CAAC;IACpD,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAMD,oEAAoE;AACpE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAC/B;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate stage integration — combines parsing and validation into a
|
|
3
|
+
* single pipeline-stage function.
|
|
4
|
+
*
|
|
5
|
+
* This function will be called by the pipeline runner when executing the
|
|
6
|
+
* `validate` stage of a generation run.
|
|
7
|
+
*/
|
|
8
|
+
import type { ValidationReport } from './validation-types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Execute the validate pipeline stage: parse a specification file and
|
|
11
|
+
* validate the result.
|
|
12
|
+
*
|
|
13
|
+
* @param specPath - Path to the specification file
|
|
14
|
+
* @returns Validation report for the parsed specification
|
|
15
|
+
* @throws {@link ForgeError} if the file cannot be read or parsed
|
|
16
|
+
*/
|
|
17
|
+
export declare function executeValidateStage(specPath: string): ValidationReport;
|
|
18
|
+
//# sourceMappingURL=validate-stage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-stage.d.ts","sourceRoot":"","sources":["../src/validate-stage.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAK9D;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,GACf,gBAAgB,CAIlB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate stage integration — combines parsing and validation into a
|
|
3
|
+
* single pipeline-stage function.
|
|
4
|
+
*
|
|
5
|
+
* This function will be called by the pipeline runner when executing the
|
|
6
|
+
* `validate` stage of a generation run.
|
|
7
|
+
*/
|
|
8
|
+
import { createDefaultRegistry } from './default-registry.js';
|
|
9
|
+
import { parseSpec } from './loader.js';
|
|
10
|
+
import { validateSpec } from './validators/spec-validator.js';
|
|
11
|
+
/**
|
|
12
|
+
* Execute the validate pipeline stage: parse a specification file and
|
|
13
|
+
* validate the result.
|
|
14
|
+
*
|
|
15
|
+
* @param specPath - Path to the specification file
|
|
16
|
+
* @returns Validation report for the parsed specification
|
|
17
|
+
* @throws {@link ForgeError} if the file cannot be read or parsed
|
|
18
|
+
*/
|
|
19
|
+
export function executeValidateStage(specPath) {
|
|
20
|
+
const registry = createDefaultRegistry();
|
|
21
|
+
const spec = parseSpec(specPath, registry);
|
|
22
|
+
return validateSpec(spec);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=validate-stage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-stage.js","sourceRoot":"","sources":["../src/validate-stage.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAE9D;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB;IAEhB,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC3C,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC"}
|