@girardmedia/bootspring 2.0.37 → 2.0.38

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/cli/visualize.js CHANGED
@@ -11,6 +11,15 @@ const path = require('path');
11
11
  const config = require('../core/config');
12
12
  const utils = require('../core/utils');
13
13
 
14
+ // Lazy load Phase 3 module
15
+ let VisualDocGenerator = null;
16
+ function getVisualDocGenerator() {
17
+ if (!VisualDocGenerator) {
18
+ VisualDocGenerator = require('../generators/visual-doc-generator').VisualDocGenerator;
19
+ }
20
+ return VisualDocGenerator;
21
+ }
22
+
14
23
  // Colors
15
24
  const c = {
16
25
  reset: '\x1b[0m',
@@ -435,16 +444,157 @@ async function watchMode(projectRoot, interval = 2000) {
435
444
  });
436
445
  }
437
446
 
447
+ /**
448
+ * Generate Mermaid diagrams
449
+ */
450
+ async function generateDiagrams(projectRoot, args) {
451
+ const Generator = getVisualDocGenerator();
452
+ const outputDir = args.output || path.join(projectRoot, 'docs', 'diagrams');
453
+
454
+ const generator = new Generator({
455
+ projectRoot,
456
+ outputDir,
457
+ theme: args.theme || 'default'
458
+ });
459
+
460
+ console.log(`\n${c.cyan}${c.bold}Diagram Generation${c.reset}\n`);
461
+
462
+ // Read analysis data if available
463
+ const analysisPath = path.join(projectRoot, '.bootspring', 'analyze', 'reports', 'analysis.json');
464
+ let analysis = {};
465
+
466
+ if (fs.existsSync(analysisPath)) {
467
+ try {
468
+ analysis = JSON.parse(fs.readFileSync(analysisPath, 'utf-8'));
469
+ } catch {
470
+ // Continue with empty analysis
471
+ }
472
+ }
473
+
474
+ // Build analysis from project structure if no analysis exists
475
+ if (!analysis.architecture) {
476
+ console.log(`${c.dim}Building analysis from project structure...${c.reset}`);
477
+
478
+ // Detect layers from common directory patterns
479
+ const layers = { presentation: [], api: [], service: [], data: [] };
480
+ const scanDirs = ['src', 'lib', 'app', 'pages', 'components', 'api', 'services', 'models'];
481
+
482
+ for (const dir of scanDirs) {
483
+ const dirPath = path.join(projectRoot, dir);
484
+ if (fs.existsSync(dirPath)) {
485
+ const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.js') || f.endsWith('.ts') || f.endsWith('.tsx'));
486
+ for (const file of files.slice(0, 5)) {
487
+ const name = file.replace(/\.(js|ts|tsx)$/, '');
488
+ if (/component|page|view|ui/i.test(dir) || /component|page|view/i.test(file)) {
489
+ layers.presentation.push({ name });
490
+ } else if (/api|route|controller/i.test(dir) || /api|route|controller/i.test(file)) {
491
+ layers.api.push({ name });
492
+ } else if (/service|handler/i.test(dir) || /service|handler/i.test(file)) {
493
+ layers.service.push({ name });
494
+ } else if (/model|schema|repo/i.test(dir) || /model|schema|repo/i.test(file)) {
495
+ layers.data.push({ name });
496
+ }
497
+ }
498
+ }
499
+ }
500
+
501
+ analysis.architecture = { layers };
502
+ }
503
+
504
+ // Generate specific diagram type or all
505
+ const diagrams = {};
506
+ const diagramType = args._[1];
507
+
508
+ if (diagramType && diagramType !== 'all') {
509
+ try {
510
+ switch (diagramType) {
511
+ case 'architecture':
512
+ diagrams.architecture = {
513
+ type: 'architecture',
514
+ title: 'System Architecture',
515
+ code: generator.generateArchitectureDiagram(analysis.architecture || { layers: {} }),
516
+ filename: 'architecture.mmd'
517
+ };
518
+ break;
519
+ case 'dependencies':
520
+ diagrams.dependencies = {
521
+ type: 'dependencies',
522
+ title: 'Module Dependencies',
523
+ code: generator.generateDependencyDiagram(analysis.dependencies || { modules: [] }),
524
+ filename: 'dependencies.mmd'
525
+ };
526
+ break;
527
+ case 'components':
528
+ diagrams.components = {
529
+ type: 'components',
530
+ title: 'Component Hierarchy',
531
+ code: generator.generateComponentDiagram(analysis.components || { categories: {} }),
532
+ filename: 'components.mmd'
533
+ };
534
+ break;
535
+ case 'dataflow':
536
+ diagrams.dataFlow = {
537
+ type: 'dataFlow',
538
+ title: 'Data Flow',
539
+ code: generator.generateDataFlowDiagram(analysis.dataFlow || { sources: [], flows: [] }),
540
+ filename: 'data-flow.mmd'
541
+ };
542
+ break;
543
+ default:
544
+ console.log(`${c.yellow}Unknown diagram type: ${diagramType}${c.reset}`);
545
+ console.log('Available types: architecture, dependencies, components, dataflow, all');
546
+ return;
547
+ }
548
+ } catch (error) {
549
+ console.log(`${c.red}Failed to generate ${diagramType} diagram: ${error.message}${c.reset}`);
550
+ return;
551
+ }
552
+ } else {
553
+ // Generate all diagrams
554
+ Object.assign(diagrams, generator.generateAllDiagrams(analysis));
555
+ }
556
+
557
+ if (Object.keys(diagrams).length === 0) {
558
+ console.log(`${c.yellow}No diagrams generated. Run 'bootspring analyze' first for better results.${c.reset}`);
559
+ return;
560
+ }
561
+
562
+ // Save diagrams
563
+ const saved = generator.saveDiagrams(diagrams);
564
+
565
+ console.log(`Generated ${saved.length} diagram(s):\n`);
566
+ for (const file of saved) {
567
+ console.log(` ${c.green}✓${c.reset} ${file.title}`);
568
+ console.log(` ${c.dim}${file.filepath}${c.reset}`);
569
+ }
570
+
571
+ // Also generate markdown doc
572
+ if (args.markdown !== false) {
573
+ const mdPath = path.join(outputDir, 'DIAGRAMS.md');
574
+ const mdContent = generator.generateMarkdownDoc(diagrams, {
575
+ title: 'Visual Documentation'
576
+ });
577
+ fs.mkdirSync(outputDir, { recursive: true });
578
+ fs.writeFileSync(mdPath, mdContent, 'utf-8');
579
+ console.log(`\n ${c.green}✓${c.reset} Markdown documentation`);
580
+ console.log(` ${c.dim}${mdPath}${c.reset}`);
581
+ }
582
+
583
+ console.log(`\n${c.dim}View diagrams in any Mermaid-compatible viewer${c.reset}`);
584
+ console.log(`${c.dim}(GitHub, VSCode, https://mermaid.live, etc.)${c.reset}\n`);
585
+ }
586
+
438
587
  /**
439
588
  * Show help
440
589
  */
441
590
  function showHelp() {
442
591
  console.log(`
443
592
  ${c.cyan}${c.bold}⚡ Bootspring Visualize${c.reset}
444
- ${c.dim}Terminal-based workflow visualization${c.reset}
593
+ ${c.dim}Terminal-based workflow visualization and diagram generation${c.reset}
445
594
 
446
595
  ${c.bold}Usage:${c.reset}
447
596
  bootspring visualize [options]
597
+ bootspring visualize diagrams [type] Generate Mermaid diagrams
448
598
 
449
599
  ${c.bold}Options:${c.reset}
450
600
  --watch Live updating view
@@ -455,11 +605,25 @@ ${c.bold}Options:${c.reset}
455
605
  --tasks Show only task overview
456
606
  --json Output as JSON
457
607
 
608
+ ${c.bold}Diagram Generation:${c.reset}
609
+ diagrams Generate all diagrams
610
+ diagrams architecture Architecture diagram only
611
+ diagrams dependencies Dependency diagram only
612
+ diagrams components Component diagram only
613
+ diagrams dataflow Data flow diagram only
614
+
615
+ ${c.bold}Diagram Options:${c.reset}
616
+ --output <dir> Output directory (default: docs/diagrams)
617
+ --theme <theme> Mermaid theme (default, forest, dark, neutral)
618
+ --no-markdown Skip markdown documentation
619
+
458
620
  ${c.bold}Examples:${c.reset}
459
621
  bootspring visualize # Full visualization
460
622
  bootspring visualize --watch # Live updating view
461
623
  bootspring visualize --graph # Include dependency graph
462
624
  bootspring visualize --pipeline # Pipeline only
625
+ bootspring visualize diagrams # Generate all diagrams
626
+ bootspring visualize diagrams architecture --theme dark
463
627
  `);
464
628
  }
465
629
 
@@ -478,6 +642,12 @@ async function run(args) {
478
642
  const cfg = config.load();
479
643
  const projectRoot = cfg._projectRoot;
480
644
 
645
+ // Handle diagrams subcommand
646
+ if (subcommand === 'diagrams' || subcommand === 'diagram') {
647
+ await generateDiagrams(projectRoot, parsedArgs);
648
+ return;
649
+ }
650
+
481
651
  if (parsedArgs.json) {
482
652
  const data = {
483
653
  workflows: getWorkflowStates(projectRoot),
@@ -14,9 +14,23 @@ const {
14
14
  TERMINOLOGY_PATTERNS
15
15
  } = require('./document-coherence');
16
16
 
17
+ const {
18
+ SemanticDocumentAnalyzer,
19
+ CONCEPT_CATEGORIES,
20
+ SPECIFICITY_THRESHOLDS,
21
+ GAP_CATEGORIES
22
+ } = require('./semantic-analyzer');
23
+
17
24
  module.exports = {
25
+ // Engines
18
26
  DocumentCoherenceEngine,
27
+ SemanticDocumentAnalyzer,
28
+
29
+ // Constants
19
30
  DOCUMENT_RELATIONSHIPS,
20
31
  VALIDATION_RULES,
21
- TERMINOLOGY_PATTERNS
32
+ TERMINOLOGY_PATTERNS,
33
+ CONCEPT_CATEGORIES,
34
+ SPECIFICITY_THRESHOLDS,
35
+ GAP_CATEGORIES
22
36
  };