@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
@@ -0,0 +1,606 @@
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 { unified } from 'unified';
10
+ import remarkParse from 'remark-parse';
11
+ import remarkFrontmatter from 'remark-frontmatter';
12
+ import remarkGfm from 'remark-gfm';
13
+ import { parse as parseYaml } from 'yaml';
14
+ // ---------------------------------------------------------------------------
15
+ // Constants
16
+ // ---------------------------------------------------------------------------
17
+ const REQUIREMENT_KEYWORDS = [
18
+ 'requirements',
19
+ 'features',
20
+ 'functional requirements',
21
+ 'user stories',
22
+ ];
23
+ const ENTITY_KEYWORDS = [
24
+ 'entities',
25
+ 'data model',
26
+ 'schema',
27
+ 'models',
28
+ 'database',
29
+ ];
30
+ const WORKFLOW_KEYWORDS = [
31
+ 'workflows',
32
+ 'flows',
33
+ 'use cases',
34
+ 'user flows',
35
+ 'processes',
36
+ ];
37
+ /** Values that indicate a field is required (case-insensitive). */
38
+ const REQUIRED_VALUES = new Set(['yes', 'true', 'required', '✓', 'x']);
39
+ // ---------------------------------------------------------------------------
40
+ // Helper Functions
41
+ // ---------------------------------------------------------------------------
42
+ /** Extract plain text from an array of phrasing content nodes. */
43
+ function phrasingToText(nodes) {
44
+ return nodes
45
+ .map((node) => {
46
+ switch (node.type) {
47
+ case 'text':
48
+ case 'inlineCode':
49
+ case 'html':
50
+ return node.value;
51
+ case 'break':
52
+ return '\n';
53
+ case 'image':
54
+ case 'imageReference':
55
+ return node.alt ?? '';
56
+ case 'footnoteReference':
57
+ return '';
58
+ default:
59
+ // emphasis, strong, delete, link, linkReference — recurse
60
+ if ('children' in node) {
61
+ return phrasingToText(node.children);
62
+ }
63
+ return '';
64
+ }
65
+ })
66
+ .join('');
67
+ }
68
+ /**
69
+ * Extract plain text from block-level content nodes.
70
+ *
71
+ * Accepts `RootContent[]` or structurally-compatible arrays (e.g.
72
+ * `(BlockContent | DefinitionContent)[]`). The union types overlap
73
+ * extensively so a single cast at the call-site is safe and avoids
74
+ * verbose per-node narrowing across the mdast hierarchy.
75
+ */
76
+ function contentNodesToText(nodes) {
77
+ return nodes
78
+ .map((node) => {
79
+ switch (node.type) {
80
+ case 'paragraph':
81
+ return phrasingToText(node.children);
82
+ case 'heading':
83
+ return phrasingToText(node.children);
84
+ case 'code':
85
+ return node.value;
86
+ case 'blockquote':
87
+ // BlockContent[] is a subset of RootContent[]
88
+ return contentNodesToText(node.children);
89
+ case 'list':
90
+ return node.children
91
+ .map((item) => contentNodesToText(item.children))
92
+ .join('\n');
93
+ case 'html':
94
+ return node.value;
95
+ case 'yaml':
96
+ case 'thematicBreak':
97
+ return '';
98
+ default:
99
+ return '';
100
+ }
101
+ })
102
+ .filter(Boolean)
103
+ .join('\n');
104
+ }
105
+ /** Convert text to a URL-friendly slug. */
106
+ function slugify(text) {
107
+ return text
108
+ .toLowerCase()
109
+ .replace(/[^a-z0-9]+/g, '-')
110
+ .replace(/^-|-$/g, '');
111
+ }
112
+ /** Detect MoSCoW priority from text. */
113
+ function detectMoscow(text) {
114
+ const lower = text.toLowerCase();
115
+ if (/\bmust\b/.test(lower))
116
+ return 'must';
117
+ if (/\bshould\b/.test(lower))
118
+ return 'should';
119
+ if (/\bcould\b/.test(lower))
120
+ return 'could';
121
+ if (/\bwon'?t\b/.test(lower))
122
+ return 'wont';
123
+ return undefined;
124
+ }
125
+ /** Check whether a heading title matches any of the given keywords. */
126
+ function matchesKeywords(title, keywords) {
127
+ const lower = title.toLowerCase();
128
+ return keywords.some((kw) => lower.includes(kw));
129
+ }
130
+ /** Extract the first sentence or line from text. */
131
+ function firstSentence(text) {
132
+ const match = text.match(/^(.+?[.!?])(?:\s|$)/);
133
+ if (match?.[1])
134
+ return match[1].trim();
135
+ const firstLine = text.split('\n')[0];
136
+ return firstLine ? firstLine.trim() : text.trim();
137
+ }
138
+ /** Get the cell text content from a table row at a specific column index. */
139
+ function tableCellText(row, index) {
140
+ const cell = row.children[index];
141
+ return cell ? phrasingToText(cell.children) : '';
142
+ }
143
+ /**
144
+ * Find sections in the AST whose headings match the given keywords.
145
+ * Collects all nodes belonging to each matched section (until the next
146
+ * heading at the same or higher level).
147
+ */
148
+ function findKeywordSections(tree, keywords) {
149
+ const results = [];
150
+ let current = null;
151
+ for (const node of tree.children) {
152
+ if (node.type === 'heading') {
153
+ const title = phrasingToText(node.children);
154
+ if (matchesKeywords(title, keywords)) {
155
+ if (current)
156
+ results.push(current);
157
+ current = { heading: title, level: node.depth, nodes: [] };
158
+ }
159
+ else if (current && node.depth <= current.level) {
160
+ results.push(current);
161
+ current = null;
162
+ }
163
+ else if (current) {
164
+ current.nodes.push(node);
165
+ }
166
+ }
167
+ else if (current && node.type !== 'yaml') {
168
+ current.nodes.push(node);
169
+ }
170
+ }
171
+ if (current)
172
+ results.push(current);
173
+ return results;
174
+ }
175
+ // ---------------------------------------------------------------------------
176
+ // Relationship Extraction
177
+ // ---------------------------------------------------------------------------
178
+ const RELATIONSHIP_PATTERNS = [
179
+ { pattern: /has\s+many\s+(\w+)/gi, type: 'one-to-many' },
180
+ { pattern: /has\s+one\s+(\w+)/gi, type: 'one-to-one' },
181
+ { pattern: /belongs\s+to\s+(\w+)/gi, type: 'one-to-many' },
182
+ {
183
+ pattern: /many\s+to\s+many\s+(?:with\s+)?(\w+)/gi,
184
+ type: 'many-to-many',
185
+ },
186
+ ];
187
+ function extractRelationshipsFromText(text) {
188
+ const relationships = [];
189
+ for (const { pattern, type } of RELATIONSHIP_PATTERNS) {
190
+ // Reset lastIndex for each exec loop on global regex
191
+ pattern.lastIndex = 0;
192
+ let match;
193
+ while ((match = pattern.exec(text)) !== null) {
194
+ const target = match[1];
195
+ if (target) {
196
+ relationships.push({ target, type });
197
+ }
198
+ }
199
+ }
200
+ return relationships;
201
+ }
202
+ // ---------------------------------------------------------------------------
203
+ // MarkdownParserPlugin
204
+ // ---------------------------------------------------------------------------
205
+ /**
206
+ * Parser plugin for Markdown specification files.
207
+ *
208
+ * Implements the two-phase Markdown → AST → ParsedSpecification pipeline.
209
+ * Supports YAML frontmatter, GFM tables, task lists, and ordered lists.
210
+ */
211
+ export class MarkdownParserPlugin {
212
+ format = 'markdown';
213
+ extensions = ['.md'];
214
+ /**
215
+ * Parse a Markdown specification into the canonical model.
216
+ *
217
+ * @param content - Raw Markdown content
218
+ * @param sourcePath - Original file path
219
+ * @returns Parsed specification
220
+ */
221
+ parse(content, sourcePath) {
222
+ // Phase 1: Markdown → AST
223
+ const tree = unified()
224
+ .use(remarkParse)
225
+ .use(remarkFrontmatter, ['yaml'])
226
+ .use(remarkGfm)
227
+ .parse(content);
228
+ // Phase 2: AST → ParsedSpecification
229
+ const metadata = this.extractMetadata(tree, sourcePath);
230
+ const sections = this.extractSections(tree);
231
+ const requirements = this.extractRequirements(tree);
232
+ const entities = this.extractEntities(tree);
233
+ const workflows = this.extractWorkflows(tree);
234
+ const apiStyle = this.detectApiStyle(content);
235
+ const result = {
236
+ metadata,
237
+ sections,
238
+ requirements,
239
+ entities,
240
+ workflows,
241
+ };
242
+ if (apiStyle !== undefined) {
243
+ result.apiStyle = apiStyle;
244
+ }
245
+ return result;
246
+ }
247
+ // -----------------------------------------------------------------------
248
+ // Metadata Extraction
249
+ // -----------------------------------------------------------------------
250
+ extractMetadata(tree, sourcePath) {
251
+ let title = '';
252
+ let version;
253
+ let description;
254
+ let authors;
255
+ // Try YAML frontmatter first
256
+ const yamlNode = tree.children.find((n) => n.type === 'yaml');
257
+ if (yamlNode && 'value' in yamlNode) {
258
+ try {
259
+ const fm = parseYaml(yamlNode.value);
260
+ if (typeof fm === 'object' && fm !== null) {
261
+ if (typeof fm['title'] === 'string')
262
+ title = fm['title'];
263
+ if (typeof fm['version'] === 'string')
264
+ version = fm['version'];
265
+ if (typeof fm['description'] === 'string')
266
+ description = fm['description'];
267
+ if (Array.isArray(fm['authors'])) {
268
+ authors = fm['authors'].filter((a) => typeof a === 'string');
269
+ }
270
+ }
271
+ }
272
+ catch {
273
+ // Malformed YAML — fall through to heading fallback
274
+ }
275
+ }
276
+ // Fallback: use first h1 heading as title
277
+ if (!title) {
278
+ const firstH1 = tree.children.find((n) => n.type === 'heading' && n.depth === 1);
279
+ if (firstH1) {
280
+ title = phrasingToText(firstH1.children);
281
+ }
282
+ }
283
+ const metadata = {
284
+ title: title || 'Untitled',
285
+ sourcePath,
286
+ format: 'markdown',
287
+ };
288
+ if (version !== undefined)
289
+ metadata.version = version;
290
+ if (description !== undefined)
291
+ metadata.description = description;
292
+ if (authors !== undefined && authors.length > 0)
293
+ metadata.authors = authors;
294
+ return metadata;
295
+ }
296
+ // -----------------------------------------------------------------------
297
+ // Section Extraction
298
+ // -----------------------------------------------------------------------
299
+ extractSections(tree) {
300
+ const rootSections = [];
301
+ const stack = [];
302
+ let contentBuffer = [];
303
+ let currentSection = null;
304
+ for (const node of tree.children) {
305
+ if (node.type === 'heading') {
306
+ // Finalize previous section content
307
+ if (currentSection) {
308
+ currentSection.content = contentNodesToText(contentBuffer).trim();
309
+ }
310
+ contentBuffer = [];
311
+ const title = phrasingToText(node.children);
312
+ const newSection = {
313
+ id: slugify(title),
314
+ title,
315
+ level: node.depth,
316
+ content: '',
317
+ subsections: [],
318
+ };
319
+ // Pop stack until parent with lower level is found
320
+ while (stack.length > 0 &&
321
+ stack[stack.length - 1].level >= node.depth) {
322
+ stack.pop();
323
+ }
324
+ if (stack.length === 0) {
325
+ rootSections.push(newSection);
326
+ }
327
+ else {
328
+ stack[stack.length - 1].subsections.push(newSection);
329
+ }
330
+ stack.push(newSection);
331
+ currentSection = newSection;
332
+ }
333
+ else if (node.type !== 'yaml') {
334
+ contentBuffer.push(node);
335
+ }
336
+ }
337
+ // Finalize last section
338
+ if (currentSection) {
339
+ currentSection.content = contentNodesToText(contentBuffer).trim();
340
+ }
341
+ return rootSections;
342
+ }
343
+ // -----------------------------------------------------------------------
344
+ // Requirement Extraction
345
+ // -----------------------------------------------------------------------
346
+ extractRequirements(tree) {
347
+ const sections = findKeywordSections(tree, REQUIREMENT_KEYWORDS);
348
+ const requirements = [];
349
+ let counter = 0;
350
+ for (const section of sections) {
351
+ const lists = section.nodes.filter((n) => n.type === 'list');
352
+ for (const list of lists) {
353
+ for (const item of list.children) {
354
+ counter++;
355
+ requirements.push(this.listItemToRequirement(item, counter));
356
+ }
357
+ }
358
+ }
359
+ return requirements;
360
+ }
361
+ listItemToRequirement(item, index) {
362
+ const id = `REQ-${String(index).padStart(3, '0')}`;
363
+ // Get text from the item's direct paragraph children
364
+ const paragraphs = item.children.filter((n) => n.type === 'paragraph');
365
+ const fullText = paragraphs
366
+ .map((p) => phrasingToText(p.children))
367
+ .join(' ');
368
+ const title = firstSentence(fullText);
369
+ const priority = detectMoscow(fullText);
370
+ // Extract acceptance criteria from nested task-list items
371
+ const acceptanceCriteria = [];
372
+ const nestedLists = item.children.filter((n) => n.type === 'list');
373
+ for (const nestedList of nestedLists) {
374
+ for (const nestedItem of nestedList.children) {
375
+ if (typeof nestedItem.checked === 'boolean') {
376
+ const criteriaText = contentNodesToText(nestedItem.children).trim();
377
+ if (criteriaText) {
378
+ acceptanceCriteria.push(criteriaText);
379
+ }
380
+ }
381
+ }
382
+ }
383
+ const req = {
384
+ id,
385
+ title,
386
+ description: fullText,
387
+ acceptanceCriteria,
388
+ };
389
+ if (priority !== undefined)
390
+ req.priority = priority;
391
+ return req;
392
+ }
393
+ // -----------------------------------------------------------------------
394
+ // Entity Extraction
395
+ // -----------------------------------------------------------------------
396
+ extractEntities(tree) {
397
+ const sections = findKeywordSections(tree, ENTITY_KEYWORDS);
398
+ const entities = [];
399
+ for (const section of sections) {
400
+ entities.push(...this.extractEntitiesFromNodes(section.nodes, section.heading));
401
+ }
402
+ return entities;
403
+ }
404
+ extractEntitiesFromNodes(nodes, defaultName) {
405
+ const entities = [];
406
+ let currentName = defaultName;
407
+ let currentDescription;
408
+ let currentFields = [];
409
+ let currentRelationships = [];
410
+ let hasSubEntities = false;
411
+ for (const node of nodes) {
412
+ if (node.type === 'heading') {
413
+ // Flush previous entity if it has fields
414
+ if (hasSubEntities && currentFields.length > 0) {
415
+ entities.push(this.buildEntity(currentName, currentDescription, currentFields, currentRelationships));
416
+ }
417
+ hasSubEntities = true;
418
+ currentName = phrasingToText(node.children);
419
+ currentDescription = undefined;
420
+ currentFields = [];
421
+ currentRelationships = [];
422
+ }
423
+ else if (node.type === 'table') {
424
+ currentFields.push(...this.parseTableFields(node));
425
+ }
426
+ else if (node.type === 'list' &&
427
+ !node.ordered) {
428
+ currentFields.push(...this.parseListFields(node));
429
+ }
430
+ else if (node.type === 'paragraph') {
431
+ const text = phrasingToText(node.children);
432
+ currentRelationships.push(...extractRelationshipsFromText(text));
433
+ if (currentDescription === undefined) {
434
+ currentDescription = text;
435
+ }
436
+ }
437
+ }
438
+ // Flush last entity
439
+ if (currentFields.length > 0) {
440
+ entities.push(this.buildEntity(currentName, currentDescription, currentFields, currentRelationships));
441
+ }
442
+ return entities;
443
+ }
444
+ buildEntity(name, description, fields, relationships) {
445
+ const entity = {
446
+ name,
447
+ fields,
448
+ relationships,
449
+ };
450
+ if (description !== undefined)
451
+ entity.description = description;
452
+ return entity;
453
+ }
454
+ parseTableFields(table) {
455
+ const rows = table.children;
456
+ if (rows.length < 2)
457
+ return [];
458
+ const headerRow = rows[0];
459
+ const headers = headerRow.children.map((cell) => phrasingToText(cell.children).toLowerCase().trim());
460
+ // Find column indices
461
+ const nameIdx = headers.findIndex((h) => h === 'name' || h === 'field' || h === 'column');
462
+ const typeIdx = headers.findIndex((h) => h === 'type' || h === 'data type' || h === 'datatype');
463
+ const reqIdx = headers.findIndex((h) => h === 'required' ||
464
+ h === 'req' ||
465
+ h === 'nullable' ||
466
+ h === 'null');
467
+ const descIdx = headers.findIndex((h) => h === 'description' || h === 'desc' || h === 'notes');
468
+ if (nameIdx === -1)
469
+ return [];
470
+ const fields = [];
471
+ for (let i = 1; i < rows.length; i++) {
472
+ const row = rows[i];
473
+ const name = tableCellText(row, nameIdx).trim();
474
+ if (!name)
475
+ continue;
476
+ const type = typeIdx >= 0 ? tableCellText(row, typeIdx).trim() : 'string';
477
+ const reqValue = reqIdx >= 0
478
+ ? tableCellText(row, reqIdx).trim().toLowerCase()
479
+ : '';
480
+ const desc = descIdx >= 0 ? tableCellText(row, descIdx).trim() : undefined;
481
+ const required = REQUIRED_VALUES.has(reqValue);
482
+ const field = { name, type, required };
483
+ if (desc !== undefined && desc !== '')
484
+ field.description = desc;
485
+ fields.push(field);
486
+ }
487
+ return fields;
488
+ }
489
+ parseListFields(list) {
490
+ const fields = [];
491
+ for (const item of list.children) {
492
+ const text = contentNodesToText(item.children).trim();
493
+ if (!text)
494
+ continue;
495
+ // Try "name: type" or "name: type (required)" patterns
496
+ const colonMatch = text.match(/^(\w+)\s*:\s*(\w+)(?:\s*\(([^)]+)\))?/);
497
+ if (colonMatch?.[1] && colonMatch[2]) {
498
+ const meta = colonMatch[3]?.toLowerCase() ?? '';
499
+ fields.push({
500
+ name: colonMatch[1],
501
+ type: colonMatch[2],
502
+ required: meta.includes('required'),
503
+ });
504
+ continue;
505
+ }
506
+ // Try "name - type" pattern
507
+ const dashMatch = text.match(/^(\w+)\s+-\s+(\w+)/);
508
+ if (dashMatch?.[1] && dashMatch[2]) {
509
+ fields.push({
510
+ name: dashMatch[1],
511
+ type: dashMatch[2],
512
+ required: text.toLowerCase().includes('required'),
513
+ });
514
+ }
515
+ }
516
+ return fields;
517
+ }
518
+ // -----------------------------------------------------------------------
519
+ // Workflow Extraction
520
+ // -----------------------------------------------------------------------
521
+ extractWorkflows(tree) {
522
+ const sections = findKeywordSections(tree, WORKFLOW_KEYWORDS);
523
+ const workflows = [];
524
+ let counter = 0;
525
+ for (const section of sections) {
526
+ let currentName = section.heading;
527
+ let currentNodes = [];
528
+ let hasSubWorkflows = false;
529
+ for (const node of section.nodes) {
530
+ if (node.type === 'heading') {
531
+ if (currentNodes.length > 0) {
532
+ const wf = this.buildWorkflow(currentName, currentNodes, ++counter);
533
+ if (wf)
534
+ workflows.push(wf);
535
+ }
536
+ hasSubWorkflows = true;
537
+ currentName = phrasingToText(node.children);
538
+ currentNodes = [];
539
+ }
540
+ else {
541
+ currentNodes.push(node);
542
+ }
543
+ }
544
+ // Flush: if no sub-headings, use the entire section
545
+ if (!hasSubWorkflows) {
546
+ currentNodes = section.nodes;
547
+ }
548
+ if (currentNodes.length > 0) {
549
+ const wf = this.buildWorkflow(currentName, currentNodes, ++counter);
550
+ if (wf)
551
+ workflows.push(wf);
552
+ }
553
+ }
554
+ return workflows;
555
+ }
556
+ buildWorkflow(name, nodes, index) {
557
+ const orderedLists = nodes.filter((n) => n.type === 'list' && n.ordered === true);
558
+ if (orderedLists.length === 0)
559
+ return null;
560
+ const steps = [];
561
+ for (const list of orderedLists) {
562
+ let order = list.start ?? 1;
563
+ for (const item of list.children) {
564
+ const action = contentNodesToText(item.children).trim();
565
+ if (action) {
566
+ steps.push({ order, action });
567
+ order++;
568
+ }
569
+ }
570
+ }
571
+ if (steps.length === 0)
572
+ return null;
573
+ // Detect actors from step text
574
+ const fullText = steps.map((s) => s.action).join(' ');
575
+ const actorPattern = /\b(User|Admin|System|Customer|Manager|Client|Server|Developer|Operator)\b/gi;
576
+ const actorMatches = fullText.match(actorPattern);
577
+ const actors = actorMatches
578
+ ? [
579
+ ...new Set(actorMatches.map((a) => a.charAt(0).toUpperCase() + a.slice(1).toLowerCase())),
580
+ ]
581
+ : undefined;
582
+ const id = `WF-${String(index).padStart(3, '0')}`;
583
+ const workflow = {
584
+ id,
585
+ name,
586
+ steps,
587
+ };
588
+ if (actors !== undefined && actors.length > 0)
589
+ workflow.actors = actors;
590
+ return workflow;
591
+ }
592
+ // -----------------------------------------------------------------------
593
+ // API Style Detection
594
+ // -----------------------------------------------------------------------
595
+ detectApiStyle(content) {
596
+ const lower = content.toLowerCase();
597
+ if (lower.includes('rest api') || lower.includes('restful api'))
598
+ return 'rest';
599
+ if (lower.includes('graphql'))
600
+ return 'graphql';
601
+ if (lower.includes('grpc'))
602
+ return 'grpc';
603
+ return undefined;
604
+ }
605
+ }
606
+ //# sourceMappingURL=markdown-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-parser.js","sourceRoot":"","sources":["../../src/parsers/markdown-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,iBAAiB,MAAM,oBAAoB,CAAC;AACnD,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AA0B1C,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,MAAM,oBAAoB,GAAG;IAC3B,cAAc;IACd,UAAU;IACV,yBAAyB;IACzB,cAAc;CACf,CAAC;AAEF,MAAM,eAAe,GAAG;IACtB,UAAU;IACV,YAAY;IACZ,QAAQ;IACR,QAAQ;IACR,UAAU;CACX,CAAC;AAEF,MAAM,iBAAiB,GAAG;IACxB,WAAW;IACX,OAAO;IACP,WAAW;IACX,YAAY;IACZ,WAAW;CACZ,CAAC;AAEF,mEAAmE;AACnE,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAEvE,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,kEAAkE;AAClE,SAAS,cAAc,CAAC,KAAiC;IACvD,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,MAAM,CAAC;YACZ,KAAK,YAAY,CAAC;YAClB,KAAK,MAAM;gBACT,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC;YACd,KAAK,OAAO,CAAC;YACb,KAAK,gBAAgB;gBACnB,OAAO,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;YACxB,KAAK,mBAAmB;gBACtB,OAAO,EAAE,CAAC;YACZ;gBACE,0DAA0D;gBAC1D,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;oBACvB,OAAO,cAAc,CACnB,IAAI,CAAC,QAAsC,CAC5C,CAAC;gBACJ,CAAC;gBACD,OAAO,EAAE,CAAC;QACd,CAAC;IACH,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,kBAAkB,CAAC,KAA6B;IACvD,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,WAAW;gBACd,OAAO,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvC,KAAK,SAAS;gBACZ,OAAO,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvC,KAAK,MAAM;gBACT,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,KAAK,YAAY;gBACf,8CAA8C;gBAC9C,OAAO,kBAAkB,CACvB,IAAI,CAAC,QAAoC,CAC1C,CAAC;YACJ,KAAK,MAAM;gBACT,OAAO,IAAI,CAAC,QAAQ;qBACjB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACZ,kBAAkB,CAChB,IAAI,CAAC,QAAoC,CAC1C,CACF;qBACA,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,KAAK,MAAM;gBACT,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,KAAK,MAAM,CAAC;YACZ,KAAK,eAAe;gBAClB,OAAO,EAAE,CAAC;YACZ;gBACE,OAAO,EAAE,CAAC;QACd,CAAC;IACH,CAAC,CAAC;SACD,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,2CAA2C;AAC3C,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,IAAI;SACR,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAC3B,CAAC;AAED,wCAAwC;AACxC,SAAS,YAAY,CACnB,IAAY;IAEZ,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAC1C,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9C,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IAC5C,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAC5C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,uEAAuE;AACvE,SAAS,eAAe,CACtB,KAAa,EACb,QAA2B;IAE3B,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,oDAAoD;AACpD,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAChD,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AACpD,CAAC;AAED,6EAA6E;AAC7E,SAAS,aAAa,CAAC,GAAa,EAAE,KAAa;IACjD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACnD,CAAC;AAYD;;;;GAIG;AACH,SAAS,mBAAmB,CAC1B,IAAU,EACV,QAA2B;IAE3B,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,IAAI,OAAO,GAAwB,IAAI,CAAC;IAExC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAE5C,IAAI,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACrC,IAAI,OAAO;oBAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACnC,OAAO,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;YAC7D,CAAC;iBAAM,IAAI,OAAO,IAAI,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClD,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACtB,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;iBAAM,IAAI,OAAO,EAAE,CAAC;gBACnB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3C,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,IAAI,OAAO;QAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACnC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,8EAA8E;AAC9E,0BAA0B;AAC1B,8EAA8E;AAE9E,MAAM,qBAAqB,GAGrB;IACJ,EAAE,OAAO,EAAE,sBAAsB,EAAE,IAAI,EAAE,aAAa,EAAE;IACxD,EAAE,OAAO,EAAE,qBAAqB,EAAE,IAAI,EAAE,YAAY,EAAE;IACtD,EAAE,OAAO,EAAE,wBAAwB,EAAE,IAAI,EAAE,aAAa,EAAE;IAC1D;QACE,OAAO,EAAE,wCAAwC;QACjD,IAAI,EAAE,cAAc;KACrB;CACF,CAAC;AAEF,SAAS,4BAA4B,CACnC,IAAY;IAEZ,MAAM,aAAa,GAAyB,EAAE,CAAC;IAE/C,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,qBAAqB,EAAE,CAAC;QACtD,qDAAqD;QACrD,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QACtB,IAAI,KAA6B,CAAC;QAClC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,MAAM,EAAE,CAAC;gBACX,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,OAAO,oBAAoB;IACtB,MAAM,GAAe,UAAU,CAAC;IAChC,UAAU,GAAa,CAAC,KAAK,CAAC,CAAC;IAExC;;;;;;OAMG;IACH,KAAK,CAAC,OAAe,EAAE,UAAkB;QACvC,0BAA0B;QAC1B,MAAM,IAAI,GAAG,OAAO,EAAE;aACnB,GAAG,CAAC,WAAW,CAAC;aAChB,GAAG,CAAC,iBAAiB,EAAE,CAAC,MAAM,CAAC,CAAC;aAChC,GAAG,CAAC,SAAS,CAAC;aACd,KAAK,CAAC,OAAO,CAAS,CAAC;QAE1B,qCAAqC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAE9C,MAAM,MAAM,GAAwB;YAClC,QAAQ;YACR,QAAQ;YACR,YAAY;YACZ,QAAQ;YACR,SAAS;SACV,CAAC;QAEF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC7B,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,0EAA0E;IAC1E,sBAAsB;IACtB,0EAA0E;IAElE,eAAe,CAAC,IAAU,EAAE,UAAkB;QACpD,IAAI,KAAK,GAAG,EAAE,CAAC;QACf,IAAI,OAA2B,CAAC;QAChC,IAAI,WAA+B,CAAC;QACpC,IAAI,OAA6B,CAAC;QAElC,6BAA6B;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAC9D,IAAI,QAAQ,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;YACpC,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,SAAS,CAClB,QAAQ,CAAC,KAAe,CACS,CAAC;gBAEpC,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;oBAC1C,IAAI,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ;wBAAE,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC;oBACzD,IAAI,OAAO,EAAE,CAAC,SAAS,CAAC,KAAK,QAAQ;wBAAE,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;oBAC/D,IAAI,OAAO,EAAE,CAAC,aAAa,CAAC,KAAK,QAAQ;wBACvC,WAAW,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC;oBAClC,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;wBACjC,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,MAAM,CAC5B,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAC1C,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,oDAAoD;YACtD,CAAC;QACH,CAAC;QAED,0CAA0C;QAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAChC,CAAC,CAAC,EAAgB,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAC3D,CAAC;YACF,IAAI,OAAO,EAAE,CAAC;gBACZ,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QAED,MAAM,QAAQ,GAAiB;YAC7B,KAAK,EAAE,KAAK,IAAI,UAAU;YAC1B,UAAU;YACV,MAAM,EAAE,UAAU;SACnB,CAAC;QAEF,IAAI,OAAO,KAAK,SAAS;YAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;QACtD,IAAI,WAAW,KAAK,SAAS;YAAE,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAC;QAClE,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAC7C,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;QAE7B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,0EAA0E;IAC1E,qBAAqB;IACrB,0EAA0E;IAElE,eAAe,CAAC,IAAU;QAChC,MAAM,YAAY,GAAkB,EAAE,CAAC;QACvC,MAAM,KAAK,GAAkB,EAAE,CAAC;QAChC,IAAI,aAAa,GAAkB,EAAE,CAAC;QACtC,IAAI,cAAc,GAAuB,IAAI,CAAC;QAE9C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5B,oCAAoC;gBACpC,IAAI,cAAc,EAAE,CAAC;oBACnB,cAAc,CAAC,OAAO,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC,IAAI,EAAE,CAAC;gBACpE,CAAC;gBACD,aAAa,GAAG,EAAE,CAAC;gBAEnB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC5C,MAAM,UAAU,GAAgB;oBAC9B,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC;oBAClB,KAAK;oBACL,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,OAAO,EAAE,EAAE;oBACX,WAAW,EAAE,EAAE;iBAChB,CAAC;gBAEF,mDAAmD;gBACnD,OACE,KAAK,CAAC,MAAM,GAAG,CAAC;oBAChB,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAC5C,CAAC;oBACD,KAAK,CAAC,GAAG,EAAE,CAAC;gBACd,CAAC;gBAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAChC,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACxD,CAAC;gBAED,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACvB,cAAc,GAAG,UAAU,CAAC;YAC9B,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAChC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,wBAAwB;QACxB,IAAI,cAAc,EAAE,CAAC;YACnB,cAAc,CAAC,OAAO,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC,IAAI,EAAE,CAAC;QACpE,CAAC;QAED,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,0EAA0E;IAC1E,yBAAyB;IACzB,0EAA0E;IAElE,mBAAmB,CAAC,IAAU;QACpC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;QACjE,MAAM,YAAY,GAAsB,EAAE,CAAC;QAC3C,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAChC,CAAC,CAAC,EAAa,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CACpC,CAAC;YAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACjC,OAAO,EAAE,CAAC;oBACV,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,YAAY,CAAC;IACtB,CAAC;IAEO,qBAAqB,CAC3B,IAAc,EACd,KAAa;QAEb,MAAM,EAAE,GAAG,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QAEnD,qDAAqD;QACrD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CACrC,CAAC,CAAC,EAAkB,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAC9C,CAAC;QACF,MAAM,QAAQ,GAAG,UAAU;aACxB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;aACtC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEb,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QAExC,0DAA0D;QAC1D,MAAM,kBAAkB,GAAa,EAAE,CAAC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CACtC,CAAC,CAAC,EAAa,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CACpC,CAAC;QACF,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,KAAK,MAAM,UAAU,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;gBAC7C,IAAI,OAAO,UAAU,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;oBAC5C,MAAM,YAAY,GAAG,kBAAkB,CACrC,UAAU,CAAC,QAAoC,CAChD,CAAC,IAAI,EAAE,CAAC;oBACT,IAAI,YAAY,EAAE,CAAC;wBACjB,kBAAkB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;oBACxC,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,GAAG,GAAoB;YAC3B,EAAE;YACF,KAAK;YACL,WAAW,EAAE,QAAQ;YACrB,kBAAkB;SACnB,CAAC;QAEF,IAAI,QAAQ,KAAK,SAAS;YAAE,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEpD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,0EAA0E;IAC1E,oBAAoB;IACpB,0EAA0E;IAElE,eAAe,CAAC,IAAU;QAChC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAiB,EAAE,CAAC;QAElC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,QAAQ,CAAC,IAAI,CACX,GAAG,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CACjE,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEO,wBAAwB,CAC9B,KAA6B,EAC7B,WAAmB;QAEnB,MAAM,QAAQ,GAAiB,EAAE,CAAC;QAClC,IAAI,WAAW,GAAG,WAAW,CAAC;QAC9B,IAAI,kBAAsC,CAAC;QAC3C,IAAI,aAAa,GAAkB,EAAE,CAAC;QACtC,IAAI,oBAAoB,GAAyB,EAAE,CAAC;QACpD,IAAI,cAAc,GAAG,KAAK,CAAC;QAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5B,yCAAyC;gBACzC,IAAI,cAAc,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC/C,QAAQ,CAAC,IAAI,CACX,IAAI,CAAC,WAAW,CACd,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,oBAAoB,CACrB,CACF,CAAC;gBACJ,CAAC;gBACD,cAAc,GAAG,IAAI,CAAC;gBACtB,WAAW,GAAG,cAAc,CACzB,IAAgB,CAAC,QAAQ,CAC3B,CAAC;gBACF,kBAAkB,GAAG,SAAS,CAAC;gBAC/B,aAAa,GAAG,EAAE,CAAC;gBACnB,oBAAoB,GAAG,EAAE,CAAC;YAC5B,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACjC,aAAa,CAAC,IAAI,CAChB,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAa,CAAC,CACxC,CAAC;YACJ,CAAC;iBAAM,IACL,IAAI,CAAC,IAAI,KAAK,MAAM;gBACpB,CAAE,IAAa,CAAC,OAAO,EACvB,CAAC;gBACD,aAAa,CAAC,IAAI,CAChB,GAAG,IAAI,CAAC,eAAe,CAAC,IAAY,CAAC,CACtC,CAAC;YACJ,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACrC,MAAM,IAAI,GAAG,cAAc,CACxB,IAAkB,CAAC,QAAQ,CAC7B,CAAC;gBACF,oBAAoB,CAAC,IAAI,CACvB,GAAG,4BAA4B,CAAC,IAAI,CAAC,CACtC,CAAC;gBACF,IAAI,kBAAkB,KAAK,SAAS,EAAE,CAAC;oBACrC,kBAAkB,GAAG,IAAI,CAAC;gBAC5B,CAAC;YACH,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,QAAQ,CAAC,IAAI,CACX,IAAI,CAAC,WAAW,CACd,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,oBAAoB,CACrB,CACF,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEO,WAAW,CACjB,IAAY,EACZ,WAA+B,EAC/B,MAAqB,EACrB,aAAmC;QAEnC,MAAM,MAAM,GAAe;YACzB,IAAI;YACJ,MAAM;YACN,aAAa;SACd,CAAC;QACF,IAAI,WAAW,KAAK,SAAS;YAAE,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC;QAChE,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,gBAAgB,CAAC,KAAY;QACnC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC5B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,EAAE,CAAC;QAE/B,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC9C,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CACnD,CAAC;QAEF,sBAAsB;QACtB,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,QAAQ,CACvD,CAAC;QACF,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,UAAU,CAC7D,CAAC;QACF,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAC9B,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,KAAK,UAAU;YAChB,CAAC,KAAK,KAAK;YACX,CAAC,KAAK,UAAU;YAChB,CAAC,KAAK,MAAM,CACf,CAAC;QACF,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,aAAa,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,OAAO,CAC5D,CAAC;QAEF,IAAI,OAAO,KAAK,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAE9B,MAAM,MAAM,GAAkB,EAAE,CAAC;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;YACrB,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YAChD,IAAI,CAAC,IAAI;gBAAE,SAAS;YAEpB,MAAM,IAAI,GACR,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/D,MAAM,QAAQ,GACZ,MAAM,IAAI,CAAC;gBACT,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;gBACjD,CAAC,CAAC,EAAE,CAAC;YACT,MAAM,IAAI,GACR,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;YAEhE,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAE/C,MAAM,KAAK,GAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;YACpD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE;gBAAE,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;YAChE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,eAAe,CAAC,IAAU;QAChC,MAAM,MAAM,GAAkB,EAAE,CAAC;QAEjC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,kBAAkB,CAC7B,IAAI,CAAC,QAAoC,CAC1C,CAAC,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,IAAI;gBAAE,SAAS;YAEpB,uDAAuD;YACvD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAC3B,uCAAuC,CACxC,CAAC;YACF,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrC,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;gBAChD,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;oBACnB,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;oBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;iBACpC,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YAED,4BAA4B;YAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;YACnD,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnC,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;oBAClB,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;oBAClB,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC;iBAClD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,0EAA0E;IAC1E,sBAAsB;IACtB,0EAA0E;IAElE,gBAAgB,CAAC,IAAU;QACjC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC9D,MAAM,SAAS,GAAmB,EAAE,CAAC;QACrC,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;YAClC,IAAI,YAAY,GAAkB,EAAE,CAAC;YACrC,IAAI,eAAe,GAAG,KAAK,CAAC;YAE5B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBACjC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBAC5B,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC5B,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAC3B,WAAW,EACX,YAAY,EACZ,EAAE,OAAO,CACV,CAAC;wBACF,IAAI,EAAE;4BAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBAC7B,CAAC;oBACD,eAAe,GAAG,IAAI,CAAC;oBACvB,WAAW,GAAG,cAAc,CAAE,IAAgB,CAAC,QAAQ,CAAC,CAAC;oBACzD,YAAY,GAAG,EAAE,CAAC;gBACpB,CAAC;qBAAM,CAAC;oBACN,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;YAED,oDAAoD;YACpD,IAAI,CAAC,eAAe,EAAE,CAAC;gBACrB,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC;YAC/B,CAAC;YACD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAC3B,WAAW,EACX,YAAY,EACZ,EAAE,OAAO,CACV,CAAC;gBACF,IAAI,EAAE;oBAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,aAAa,CACnB,IAAY,EACZ,KAA6B,EAC7B,KAAa;QAEb,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAC/B,CAAC,CAAC,EAAa,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,CAC1D,CAAC;QACF,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAE3C,MAAM,KAAK,GAAmB,EAAE,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;YAC5B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACjC,MAAM,MAAM,GAAG,kBAAkB,CAC/B,IAAI,CAAC,QAAoC,CAC1C,CAAC,IAAI,EAAE,CAAC;gBACT,IAAI,MAAM,EAAE,CAAC;oBACX,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;oBAC9B,KAAK,EAAE,CAAC;gBACV,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEpC,+BAA+B;QAC/B,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtD,MAAM,YAAY,GAChB,6EAA6E,CAAC;QAChF,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,YAAY;YACzB,CAAC,CAAC;gBACE,GAAG,IAAI,GAAG,CACR,YAAY,CAAC,GAAG,CACd,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CACvD,CACF;aACF;YACH,CAAC,CAAC,SAAS,CAAC;QAEd,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QAClD,MAAM,QAAQ,GAAiB;YAC7B,EAAE;YACF,IAAI;YACJ,KAAK;SACN,CAAC;QAEF,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAC3C,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC;QAE3B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,0EAA0E;IAC1E,sBAAsB;IACtB,0EAA0E;IAElE,cAAc,CACpB,OAAe;QAEf,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC;YAC7D,OAAO,MAAM,CAAC;QAChB,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAChD,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QAC1C,OAAO,SAAS,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,22 @@
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 type { ParsedSpecification, SpecFormat } from '../types.js';
9
+ /**
10
+ * Map a parsed structured object into the canonical specification model.
11
+ *
12
+ * Validates the data structure (title required, arrays are arrays, etc.)
13
+ * and maps to canonical types with safe defaults.
14
+ *
15
+ * @param data - Raw parsed data (from YAML or JSON)
16
+ * @param sourcePath - Original file path
17
+ * @param format - Specification format (`'yaml'` or `'json'`)
18
+ * @returns Parsed specification
19
+ * @throws {@link ForgeError} with code `FORGE-SPEC-001` if `title` is missing or data is not an object
20
+ */
21
+ export declare function mapStructuredSpec(data: unknown, sourcePath: string, format: SpecFormat): ParsedSpecification;
22
+ //# sourceMappingURL=structured-mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured-mapper.d.ts","sourceRoot":"","sources":["../../src/parsers/structured-mapper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,mBAAmB,EASnB,UAAU,EACX,MAAM,aAAa,CAAC;AAiDrB;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,OAAO,EACb,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,UAAU,GACjB,mBAAmB,CAsCrB"}