@documentation-robotics/cli 0.1.0 → 0.1.5
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/LICENSE +21 -0
- package/README.md +466 -693
- package/dist/analysis/data-model-analyzer.js +189 -0
- package/dist/analysis/data-model-analyzer.js.map +7 -0
- package/dist/analysis/index.js +3 -0
- package/dist/analysis/index.js.map +7 -0
- package/dist/analysis/relationship-classifier.js +181 -0
- package/dist/analysis/relationship-classifier.js.map +7 -0
- package/dist/analyzers/base-analyzer.js +1 -0
- package/dist/analyzers/base-analyzer.js.map +7 -0
- package/dist/analyzers/call-graph-utils.js +39 -0
- package/dist/analyzers/call-graph-utils.js.map +7 -0
- package/dist/analyzers/cbm-analyzer.js +1205 -0
- package/dist/analyzers/cbm-analyzer.js.map +7 -0
- package/dist/analyzers/heuristic-utils.js +55 -0
- package/dist/analyzers/heuristic-utils.js.map +7 -0
- package/dist/analyzers/mapping-loader.js +146 -0
- package/dist/analyzers/mapping-loader.js.map +7 -0
- package/dist/analyzers/registry.js +124 -0
- package/dist/analyzers/registry.js.map +7 -0
- package/dist/analyzers/session-state.js +176 -0
- package/dist/analyzers/session-state.js.map +7 -0
- package/dist/analyzers/stdio-client.js +206 -0
- package/dist/analyzers/stdio-client.js.map +7 -0
- package/dist/analyzers/types.js +15 -0
- package/dist/analyzers/types.js.map +7 -0
- package/dist/analyzers/verify-engine.js +209 -0
- package/dist/analyzers/verify-engine.js.map +7 -0
- package/dist/analyzers/verify-ignore.js +130 -0
- package/dist/analyzers/verify-ignore.js.map +7 -0
- package/dist/analyzers/version.js +8 -0
- package/dist/analyzers/version.js.map +7 -0
- package/dist/audit/ai/runner.js +41 -0
- package/dist/audit/ai/runner.js.map +7 -0
- package/dist/audit/differential-analyzer.js +183 -0
- package/dist/audit/differential-analyzer.js.map +7 -0
- package/dist/audit/index.js +32 -0
- package/dist/audit/index.js.map +7 -0
- package/dist/audit/nodes/ai/evaluator.js +49 -0
- package/dist/audit/nodes/ai/evaluator.js.map +7 -0
- package/dist/audit/nodes/ai/parser.js +55 -0
- package/dist/audit/nodes/ai/parser.js.map +7 -0
- package/dist/audit/nodes/ai/prompts.js +103 -0
- package/dist/audit/nodes/ai/prompts.js.map +7 -0
- package/dist/audit/nodes/analysis/node-completeness-checker.js +32 -0
- package/dist/audit/nodes/analysis/node-completeness-checker.js.map +7 -0
- package/dist/audit/nodes/analysis/node-definition-analyzer.js +47 -0
- package/dist/audit/nodes/analysis/node-definition-analyzer.js.map +7 -0
- package/dist/audit/nodes/analysis/node-overlap-detector.js +79 -0
- package/dist/audit/nodes/analysis/node-overlap-detector.js.map +7 -0
- package/dist/audit/nodes/model/orchestrator.js +82 -0
- package/dist/audit/nodes/model/orchestrator.js.map +7 -0
- package/dist/audit/nodes/spec/loader.js +116 -0
- package/dist/audit/nodes/spec/loader.js.map +7 -0
- package/dist/audit/nodes/spec/orchestrator.js +68 -0
- package/dist/audit/nodes/spec/orchestrator.js.map +7 -0
- package/dist/audit/nodes/types.js +1 -0
- package/dist/audit/nodes/types.js.map +7 -0
- package/dist/audit/pipeline/index.js +5 -0
- package/dist/audit/pipeline/index.js.map +7 -0
- package/dist/audit/pipeline/pipeline-orchestrator.js +218 -0
- package/dist/audit/pipeline/pipeline-orchestrator.js.map +7 -0
- package/dist/audit/relationships/ai/evaluator.js +235 -0
- package/dist/audit/relationships/ai/evaluator.js.map +7 -0
- package/dist/audit/relationships/ai/parser.js +197 -0
- package/dist/audit/relationships/ai/parser.js.map +7 -0
- package/dist/audit/relationships/ai/prompts.js +274 -0
- package/dist/audit/relationships/ai/prompts.js.map +7 -0
- package/dist/audit/relationships/analysis/balance-assessor.js +115 -0
- package/dist/audit/relationships/analysis/balance-assessor.js.map +7 -0
- package/dist/audit/relationships/analysis/coverage-analyzer.js +99 -0
- package/dist/audit/relationships/analysis/coverage-analyzer.js.map +7 -0
- package/dist/audit/relationships/analysis/duplicate-detector.js +95 -0
- package/dist/audit/relationships/analysis/duplicate-detector.js.map +7 -0
- package/dist/audit/relationships/analysis/gap-analyzer.js +99 -0
- package/dist/audit/relationships/analysis/gap-analyzer.js.map +7 -0
- package/dist/audit/relationships/analysis/layer-templates.js +294 -0
- package/dist/audit/relationships/analysis/layer-templates.js.map +7 -0
- package/dist/audit/relationships/graph/connectivity.js +129 -0
- package/dist/audit/relationships/graph/connectivity.js.map +7 -0
- package/dist/audit/relationships/graph/relationship-graph.js +179 -0
- package/dist/audit/relationships/graph/relationship-graph.js.map +7 -0
- package/dist/audit/relationships/model/balance-assessor.js +49 -0
- package/dist/audit/relationships/model/balance-assessor.js.map +7 -0
- package/dist/audit/relationships/model/coverage-analyzer.js +34 -0
- package/dist/audit/relationships/model/coverage-analyzer.js.map +7 -0
- package/dist/audit/relationships/model/duplicate-detector.js +68 -0
- package/dist/audit/relationships/model/duplicate-detector.js.map +7 -0
- package/dist/audit/relationships/model/gap-analyzer.js +41 -0
- package/dist/audit/relationships/model/gap-analyzer.js.map +7 -0
- package/dist/audit/relationships/model/orchestrator.js +126 -0
- package/dist/audit/relationships/model/orchestrator.js.map +7 -0
- package/dist/audit/relationships/spec/orchestrator.js +157 -0
- package/dist/audit/relationships/spec/orchestrator.js.map +7 -0
- package/dist/audit/reports/index.js +5 -0
- package/dist/audit/reports/index.js.map +7 -0
- package/dist/audit/reports/report-generator.js +118 -0
- package/dist/audit/reports/report-generator.js.map +7 -0
- package/dist/audit/snapshot-storage.js +163 -0
- package/dist/audit/snapshot-storage.js.map +7 -0
- package/dist/audit/types.js +21 -0
- package/dist/audit/types.js.map +7 -0
- package/dist/cli.js +223 -92
- package/dist/cli.js.map +3 -3
- package/dist/coding-agents/agents/claude-code.js +147 -0
- package/dist/coding-agents/agents/claude-code.js.map +7 -0
- package/dist/coding-agents/agents/index.js +5 -0
- package/dist/coding-agents/agents/index.js.map +7 -0
- package/dist/coding-agents/agents/types.js +1 -0
- package/dist/coding-agents/agents/types.js.map +7 -0
- package/dist/coding-agents/base-chat-client.js +45 -0
- package/dist/coding-agents/base-chat-client.js.map +7 -0
- package/dist/coding-agents/chat-utils.js +23 -0
- package/dist/coding-agents/chat-utils.js.map +7 -0
- package/dist/coding-agents/claude-code-client.js +246 -0
- package/dist/coding-agents/claude-code-client.js.map +7 -0
- package/dist/coding-agents/copilot-client.js +209 -0
- package/dist/coding-agents/copilot-client.js.map +7 -0
- package/dist/commands/add.js +95 -33
- package/dist/commands/add.js.map +2 -2
- package/dist/commands/analyzer.js +511 -0
- package/dist/commands/analyzer.js.map +7 -0
- package/dist/commands/audit-diff.js +49 -0
- package/dist/commands/audit-diff.js.map +7 -0
- package/dist/commands/audit-snapshots.js +62 -0
- package/dist/commands/audit-snapshots.js.map +7 -0
- package/dist/commands/audit.js +81 -0
- package/dist/commands/audit.js.map +7 -0
- package/dist/commands/catalog.js +248 -0
- package/dist/commands/catalog.js.map +7 -0
- package/dist/commands/changeset.js +577 -66
- package/dist/commands/changeset.js.map +2 -2
- package/dist/commands/chat.js +106 -83
- package/dist/commands/chat.js.map +2 -2
- package/dist/commands/claude.js +74 -0
- package/dist/commands/claude.js.map +7 -0
- package/dist/commands/conformance.js +71 -68
- package/dist/commands/conformance.js.map +2 -2
- package/dist/commands/copilot.js +75 -0
- package/dist/commands/copilot.js.map +7 -0
- package/dist/commands/delete.js +125 -11
- package/dist/commands/delete.js.map +3 -3
- package/dist/commands/discover-logic.js +44 -0
- package/dist/commands/discover-logic.js.map +7 -0
- package/dist/commands/docs.js +87 -0
- package/dist/commands/docs.js.map +7 -0
- package/dist/commands/element.js +14 -20
- package/dist/commands/element.js.map +2 -2
- package/dist/commands/export.js +13 -3
- package/dist/commands/export.js.map +2 -2
- package/dist/commands/import.js +51 -0
- package/dist/commands/import.js.map +7 -0
- package/dist/commands/info.js +30 -24
- package/dist/commands/info.js.map +2 -2
- package/dist/commands/init.js +27 -11
- package/dist/commands/init.js.map +2 -2
- package/dist/commands/list.js +63 -13
- package/dist/commands/list.js.map +3 -3
- package/dist/commands/relationship.js +225 -37
- package/dist/commands/relationship.js.map +2 -2
- package/dist/commands/report.js +54 -0
- package/dist/commands/report.js.map +7 -0
- package/dist/commands/reports.js +45 -0
- package/dist/commands/reports.js.map +7 -0
- package/dist/commands/schema.js +135 -0
- package/dist/commands/schema.js.map +7 -0
- package/dist/commands/search.js +40 -12
- package/dist/commands/search.js.map +2 -2
- package/dist/commands/show.js +58 -27
- package/dist/commands/show.js.map +2 -2
- package/dist/commands/stats.js +35 -0
- package/dist/commands/stats.js.map +7 -0
- package/dist/commands/trace.js +39 -16
- package/dist/commands/trace.js.map +2 -2
- package/dist/commands/update.js +141 -14
- package/dist/commands/update.js.map +2 -2
- package/dist/commands/upgrade.js +210 -46
- package/dist/commands/upgrade.js.map +3 -3
- package/dist/commands/validate.js +142 -23
- package/dist/commands/validate.js.map +3 -3
- package/dist/commands/version.js +8 -12
- package/dist/commands/version.js.map +2 -2
- package/dist/commands/visualize.js +155 -25
- package/dist/commands/visualize.js.map +2 -2
- package/dist/core/base-snapshot-manager.js +84 -0
- package/dist/core/base-snapshot-manager.js.map +7 -0
- package/dist/core/changeset-exporter.js +305 -0
- package/dist/core/changeset-exporter.js.map +7 -0
- package/dist/core/changeset-validator.js +41 -0
- package/dist/core/changeset-validator.js.map +7 -0
- package/dist/core/changeset.js +88 -173
- package/dist/core/changeset.js.map +2 -2
- package/dist/core/dependency-tracker.js +4 -2
- package/dist/core/dependency-tracker.js.map +2 -2
- package/dist/core/element.js +98 -27
- package/dist/core/element.js.map +2 -2
- package/dist/core/golden-copy-cache.js +290 -0
- package/dist/core/golden-copy-cache.js.map +7 -0
- package/dist/core/graph-model.js +266 -0
- package/dist/core/graph-model.js.map +7 -0
- package/dist/core/layer.js +159 -16
- package/dist/core/layer.js.map +2 -2
- package/dist/core/layers.js +32 -0
- package/dist/core/layers.js.map +7 -0
- package/dist/core/manifest.js +32 -11
- package/dist/core/manifest.js.map +2 -2
- package/dist/core/migration-registry.js +56 -1
- package/dist/core/migration-registry.js.map +2 -2
- package/dist/core/model.js +424 -217
- package/dist/core/model.js.map +3 -3
- package/dist/core/mutation-handler.js +179 -0
- package/dist/core/mutation-handler.js.map +7 -0
- package/dist/core/reference-registry.js +29 -21
- package/dist/core/reference-registry.js.map +2 -2
- package/dist/core/relationship-catalog.js +189 -0
- package/dist/core/relationship-catalog.js.map +7 -0
- package/dist/core/relationship-registry.js.map +2 -2
- package/dist/core/relationships.js.map +1 -1
- package/dist/core/report-data-model.js +285 -0
- package/dist/core/report-data-model.js.map +7 -0
- package/dist/core/spec-data-service.js +185 -0
- package/dist/core/spec-data-service.js.map +7 -0
- package/dist/core/spec-loader-types.js +1 -0
- package/dist/core/spec-loader-types.js.map +7 -0
- package/dist/core/spec-loader.js +234 -0
- package/dist/core/spec-loader.js.map +7 -0
- package/dist/core/staged-changeset-storage.js +282 -0
- package/dist/core/staged-changeset-storage.js.map +7 -0
- package/dist/core/staging-area.js +1002 -0
- package/dist/core/staging-area.js.map +7 -0
- package/dist/core/stats-collector.js +169 -0
- package/dist/core/stats-collector.js.map +7 -0
- package/dist/core/virtual-projection.js +443 -0
- package/dist/core/virtual-projection.js.map +7 -0
- package/dist/export/archimate-exporter.js +99 -60
- package/dist/export/archimate-exporter.js.map +2 -2
- package/dist/export/audit-formatters.js +479 -0
- package/dist/export/audit-formatters.js.map +7 -0
- package/dist/export/diff-formatters.js +99 -0
- package/dist/export/diff-formatters.js.map +7 -0
- package/dist/export/export-manager.js.map +2 -2
- package/dist/export/graphml-exporter.js +44 -27
- package/dist/export/graphml-exporter.js.map +2 -2
- package/dist/export/index.js +4 -0
- package/dist/export/index.js.map +2 -2
- package/dist/export/json-schema-exporter.js +55 -42
- package/dist/export/json-schema-exporter.js.map +2 -2
- package/dist/export/markdown-exporter.js +92 -70
- package/dist/export/markdown-exporter.js.map +2 -2
- package/dist/export/markdown-generator.js +248 -0
- package/dist/export/markdown-generator.js.map +7 -0
- package/dist/export/markdown-utils.js +30 -0
- package/dist/export/markdown-utils.js.map +7 -0
- package/dist/export/mermaid-markdown-exporter.js +37 -0
- package/dist/export/mermaid-markdown-exporter.js.map +7 -0
- package/dist/export/openapi-exporter.js +119 -71
- package/dist/export/openapi-exporter.js.map +2 -2
- package/dist/export/plantuml-exporter.js +104 -39
- package/dist/export/plantuml-exporter.js.map +2 -2
- package/dist/export/report-formatters.js +111 -0
- package/dist/export/report-formatters.js.map +7 -0
- package/dist/export/stats-formatters.js +98 -0
- package/dist/export/stats-formatters.js.map +7 -0
- package/dist/export/types.js +2 -14
- package/dist/export/types.js.map +2 -2
- package/dist/export/verify-formatters.js +153 -0
- package/dist/export/verify-formatters.js.map +7 -0
- package/dist/generated/compiled-validators.js +17 -0
- package/dist/generated/compiled-validators.js.map +7 -0
- package/dist/generated/index.js +31 -0
- package/dist/generated/index.js.map +7 -0
- package/dist/generated/layer-registry.js +190 -0
- package/dist/generated/layer-registry.js.map +7 -0
- package/dist/generated/layer-types.js +7 -0
- package/dist/generated/layer-types.js.map +7 -0
- package/dist/generated/node-types.js +1719 -0
- package/dist/generated/node-types.js.map +7 -0
- package/dist/generated/relationship-index.js +14552 -0
- package/dist/generated/relationship-index.js.map +7 -0
- package/dist/import/archimate-importer.js +166 -0
- package/dist/import/archimate-importer.js.map +7 -0
- package/dist/import/index.js +47 -0
- package/dist/import/index.js.map +7 -0
- package/dist/import/openapi-importer.js +143 -0
- package/dist/import/openapi-importer.js.map +7 -0
- package/dist/import/types.js +1 -0
- package/dist/import/types.js.map +7 -0
- package/dist/integrations/base-manager.js +311 -0
- package/dist/integrations/base-manager.js.map +7 -0
- package/dist/integrations/claude-manager.js +360 -0
- package/dist/integrations/claude-manager.js.map +7 -0
- package/dist/integrations/claude_code/agents/dr-advisor.md +253 -0
- package/dist/integrations/claude_code/agents/dr-architect.md +278 -0
- package/dist/integrations/claude_code/agents/dr-extractor.md +286 -0
- package/dist/integrations/claude_code/commands/dr-changeset.md +657 -0
- package/dist/integrations/claude_code/commands/dr-design.md +373 -0
- package/dist/integrations/claude_code/commands/dr-info.md +132 -0
- package/dist/integrations/claude_code/commands/dr-init.md +251 -0
- package/dist/integrations/claude_code/commands/dr-map.md +936 -0
- package/dist/integrations/claude_code/commands/dr-model.md +493 -0
- package/dist/integrations/claude_code/commands/dr-relate.md +814 -0
- package/dist/integrations/claude_code/commands/dr-sync.md +279 -0
- package/dist/integrations/claude_code/commands/dr-validate.md +654 -0
- package/dist/integrations/claude_code/commands/dr-verify.md +559 -0
- package/dist/integrations/claude_code/docs/END_TO_END_WALKTHROUGH.md +903 -0
- package/dist/integrations/claude_code/docs/QUICK_START.md +271 -0
- package/dist/integrations/claude_code/docs/README.md +347 -0
- package/dist/integrations/claude_code/skills/dr_01_motivation_layer/SKILL.md +550 -0
- package/dist/integrations/claude_code/skills/dr_02_business_layer/SKILL.md +620 -0
- package/dist/integrations/claude_code/skills/dr_03_security_layer/SKILL.md +642 -0
- package/dist/integrations/claude_code/skills/dr_04_application_layer/SKILL.md +911 -0
- package/dist/integrations/claude_code/skills/dr_05_technology_layer/SKILL.md +836 -0
- package/dist/integrations/claude_code/skills/dr_06_api_layer/SKILL.md +933 -0
- package/dist/integrations/claude_code/skills/dr_07_data_model_layer/SKILL.md +210 -0
- package/dist/integrations/claude_code/skills/dr_08_dataset_layer/SKILL.md +319 -0
- package/dist/integrations/claude_code/skills/dr_09_ux_layer/SKILL.md +319 -0
- package/dist/integrations/claude_code/skills/dr_10_navigation_layer/SKILL.md +318 -0
- package/dist/integrations/claude_code/skills/dr_11_apm_layer/SKILL.md +273 -0
- package/dist/integrations/claude_code/skills/dr_12_testing_layer/SKILL.md +273 -0
- package/dist/integrations/claude_code/skills/dr_changeset_reviewer/SKILL.md +187 -0
- package/dist/integrations/claude_code/skills/dr_codebase_memory/SKILL.md +590 -0
- package/dist/integrations/claude_code/skills/dr_engineering_guide/SKILL.md +295 -0
- package/dist/integrations/copilot-manager.js +328 -0
- package/dist/integrations/copilot-manager.js.map +7 -0
- package/dist/integrations/github_copilot/agents/dr-advisor.md +243 -0
- package/dist/integrations/github_copilot/agents/dr-architect.md +1567 -0
- package/dist/integrations/github_copilot/skills/dr_01_motivation_layer/SKILL.md +491 -0
- package/dist/integrations/github_copilot/skills/dr_02_business_layer/SKILL.md +539 -0
- package/dist/integrations/github_copilot/skills/dr_03_security_layer/SKILL.md +667 -0
- package/dist/integrations/github_copilot/skills/dr_04_application_layer/SKILL.md +670 -0
- package/dist/integrations/github_copilot/skills/dr_05_technology_layer/SKILL.md +660 -0
- package/dist/integrations/github_copilot/skills/dr_06_api_layer/SKILL.md +855 -0
- package/dist/integrations/github_copilot/skills/dr_07_data_model_layer/SKILL.md +171 -0
- package/dist/integrations/github_copilot/skills/dr_08_dataset_layer/SKILL.md +216 -0
- package/dist/integrations/github_copilot/skills/dr_09_ux_layer/SKILL.md +230 -0
- package/dist/integrations/github_copilot/skills/dr_10_navigation_layer/SKILL.md +228 -0
- package/dist/integrations/github_copilot/skills/dr_11_apm_layer/SKILL.md +234 -0
- package/dist/integrations/github_copilot/skills/dr_12_testing_layer/SKILL.md +230 -0
- package/dist/integrations/github_copilot/skills/dr_changeset_reviewer/SKILL.md +187 -0
- package/dist/integrations/hash-utils.js +51 -0
- package/dist/integrations/hash-utils.js.map +7 -0
- package/dist/integrations/types.js +16 -0
- package/dist/integrations/types.js.map +7 -0
- package/dist/reports/model-layer-report-generator.js +278 -0
- package/dist/reports/model-layer-report-generator.js.map +7 -0
- package/dist/reports/model-report-data.js +57 -0
- package/dist/reports/model-report-data.js.map +7 -0
- package/dist/reports/model-report-orchestrator.js +103 -0
- package/dist/reports/model-report-orchestrator.js.map +7 -0
- package/dist/schemas/bundled/analyzers/cbm.json +595 -0
- package/dist/schemas/bundled/analyzers/manifest.json +9 -0
- package/dist/schemas/bundled/api.json +3411 -0
- package/dist/schemas/bundled/apm.json +2371 -0
- package/dist/schemas/bundled/application.json +1253 -0
- package/dist/schemas/bundled/base.json +1622 -0
- package/dist/schemas/bundled/business.json +1279 -0
- package/dist/schemas/bundled/data-model.json +1298 -0
- package/dist/schemas/bundled/data-store.json +2025 -0
- package/dist/schemas/bundled/manifest.json +93 -0
- package/dist/schemas/bundled/motivation.json +1360 -0
- package/dist/schemas/bundled/navigation.json +1874 -0
- package/dist/schemas/bundled/security.json +3488 -0
- package/dist/schemas/bundled/technology.json +2067 -0
- package/dist/schemas/bundled/testing.json +3120 -0
- package/dist/schemas/bundled/ux.json +3592 -0
- package/dist/server/schemas.js +202 -0
- package/dist/server/schemas.js.map +7 -0
- package/dist/server/server.js +1336 -252
- package/dist/server/server.js.map +3 -3
- package/dist/server/telemetry-middleware.js +22 -15
- package/dist/server/telemetry-middleware.js.map +2 -2
- package/dist/server-entry.js +65 -0
- package/dist/server-entry.js.map +7 -0
- package/dist/telemetry/config.js +89 -0
- package/dist/telemetry/config.js.map +7 -0
- package/dist/telemetry/console-interceptor.js.map +1 -1
- package/dist/telemetry/detect.js +24 -0
- package/dist/telemetry/detect.js.map +7 -0
- package/dist/telemetry/fetch-otlp-exporter.js +112 -0
- package/dist/telemetry/fetch-otlp-exporter.js.map +7 -0
- package/dist/telemetry/index.js +153 -3
- package/dist/telemetry/index.js.map +2 -2
- package/dist/telemetry/resilient-exporter.js +22 -8
- package/dist/telemetry/resilient-exporter.js.map +2 -2
- package/dist/telemetry/resilient-log-exporter.js +17 -8
- package/dist/telemetry/resilient-log-exporter.js.map +2 -2
- package/dist/telemetry/test-instrumentation.js.map +2 -2
- package/dist/types/index.js +84 -0
- package/dist/types/index.js.map +3 -3
- package/dist/types/source-reference.js +1 -0
- package/dist/types/source-reference.js.map +7 -0
- package/dist/utils/chat-logger.js +292 -0
- package/dist/utils/chat-logger.js.map +7 -0
- package/dist/utils/claude-stream.js +8 -0
- package/dist/utils/claude-stream.js.map +7 -0
- package/dist/utils/date-utils.js +7 -0
- package/dist/utils/date-utils.js.map +7 -0
- package/dist/utils/element-utils.js.map +1 -1
- package/dist/utils/errors.js +88 -15
- package/dist/utils/errors.js.map +3 -3
- package/dist/utils/export-python-annotations.js +82 -0
- package/dist/utils/export-python-annotations.js.map +7 -0
- package/dist/utils/file-io.js +7 -2
- package/dist/utils/file-io.js.map +2 -2
- package/dist/utils/file-lock.js +156 -0
- package/dist/utils/file-lock.js.map +7 -0
- package/dist/utils/id-generator.js +18 -0
- package/dist/utils/id-generator.js.map +7 -0
- package/dist/utils/layer-name-formatter.js +16 -0
- package/dist/utils/layer-name-formatter.js.map +7 -0
- package/dist/utils/markdown-anchor.js +7 -0
- package/dist/utils/markdown-anchor.js.map +7 -0
- package/dist/utils/markdown-link.js +12 -0
- package/dist/utils/markdown-link.js.map +7 -0
- package/dist/utils/markdown-table.js +17 -0
- package/dist/utils/markdown-table.js.map +7 -0
- package/dist/utils/mermaid-utils.js +11 -0
- package/dist/utils/mermaid-utils.js.map +7 -0
- package/dist/utils/project-paths.js.map +2 -2
- package/dist/utils/source-reference.js +52 -0
- package/dist/utils/source-reference.js.map +7 -0
- package/dist/utils/spec-installer.js +40 -53
- package/dist/utils/spec-installer.js.map +2 -2
- package/dist/utils/spec-version.js +5 -1
- package/dist/utils/spec-version.js.map +2 -2
- package/dist/utils/string-utils.js +12 -0
- package/dist/utils/string-utils.js.map +7 -0
- package/dist/utils/table-formatting.js +19 -0
- package/dist/utils/table-formatting.js.map +7 -0
- package/dist/validators/index.js +4 -0
- package/dist/validators/index.js.map +2 -2
- package/dist/validators/naming-validator.js +20 -23
- package/dist/validators/naming-validator.js.map +2 -2
- package/dist/validators/reference-validator.js +23 -38
- package/dist/validators/reference-validator.js.map +2 -2
- package/dist/validators/relationship-schema-validator.js +243 -0
- package/dist/validators/relationship-schema-validator.js.map +7 -0
- package/dist/validators/schema-validator.js +168 -68
- package/dist/validators/schema-validator.js.map +2 -2
- package/dist/validators/semantic-validator.js +36 -60
- package/dist/validators/semantic-validator.js.map +2 -2
- package/dist/validators/types.js.map +2 -2
- package/dist/validators/validation-formatter.js +159 -0
- package/dist/validators/validation-formatter.js.map +7 -0
- package/dist/validators/validator.js +24 -38
- package/dist/validators/validator.js.map +2 -2
- package/dist/viewer/README.md +139 -0
- package/dist/viewer/assets/main-CY0Xufuj.css +1 -0
- package/dist/viewer/assets/main-DtgErnwF.js +81 -0
- package/dist/viewer/assets/vendor-CxKvDp2x.js +17 -0
- package/dist/viewer/favicon.svg +11 -0
- package/dist/viewer/fonts/inter/Inter-Black.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-Bold.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-ExtraBold.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-Light.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-Medium.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-Regular.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-SemiBold.woff2 +0 -0
- package/dist/viewer/fonts/jetbrains-mono/JetBrainsMono-Medium.woff2 +0 -0
- package/dist/viewer/fonts/jetbrains-mono/JetBrainsMono-Regular.woff2 +0 -0
- package/dist/viewer/fonts/jetbrains-mono/JetBrainsMono-SemiBold.woff2 +0 -0
- package/dist/viewer/index.html +15 -0
- package/dist/viewer/manifest.json +99 -0
- package/dist/viewer/version.json +1 -0
- package/package.json +37 -13
- package/PYTHON_CLI_PARITY.md +0 -265
- package/PYTHON_CLI_STRUCTURE_UPDATE.md +0 -246
- package/biome.json +0 -42
- package/bunfig.toml +0 -3
- package/dist/ai/claude-client.js +0 -71
- package/dist/ai/claude-client.js.map +0 -7
- package/dist/ai/context-provider.js +0 -129
- package/dist/ai/context-provider.js.map +0 -7
- package/dist/ai/tools.js +0 -231
- package/dist/ai/tools.js.map +0 -7
- package/dist/commands/migrate.js +0 -36
- package/dist/commands/migrate.js.map +0 -7
- package/dist/commands/project.js +0 -74
- package/dist/commands/project.js.map +0 -7
- package/dist/core/active-changeset.js +0 -52
- package/dist/core/active-changeset.js.map +0 -7
- package/dist/core/projection-engine.js +0 -288
- package/dist/core/projection-engine.js.map +0 -7
- package/dist/schemas/bundled/01-motivation-layer.schema.json +0 -942
- package/dist/schemas/bundled/02-business-layer.schema.json +0 -1293
- package/dist/schemas/bundled/03-security-layer.schema.json +0 -2177
- package/dist/schemas/bundled/04-application-layer.schema.json +0 -1328
- package/dist/schemas/bundled/05-technology-layer.schema.json +0 -1465
- package/dist/schemas/bundled/06-api-layer.schema.json +0 -1743
- package/dist/schemas/bundled/07-data-model-layer.schema.json +0 -1253
- package/dist/schemas/bundled/08-datastore-layer.schema.json +0 -892
- package/dist/schemas/bundled/09-ux-layer.schema.json +0 -1506
- package/dist/schemas/bundled/10-navigation-layer.schema.json +0 -843
- package/dist/schemas/bundled/11-apm-observability-layer.schema.json +0 -1430
- package/dist/schemas/bundled/12-testing-layer.schema.json +0 -1091
- package/dist/schemas/bundled/common/layer-extensions.schema.json +0 -266
- package/dist/schemas/bundled/common/predicates.schema.json +0 -493
- package/dist/schemas/bundled/common/relationships.schema.json +0 -791
- package/dist/schemas/bundled/common/source-references.schema.json +0 -71
- package/dist/schemas/bundled/link-registry.json +0 -1839
- package/dist/schemas/bundled/link-registry.schema.json +0 -339
- package/dist/schemas/bundled/relationship-catalog.json +0 -1302
- package/dist/schemas/bundled/relationship-type.schema.json +0 -221
- package/dist/utils/model-path.js +0 -22
- package/dist/utils/model-path.js.map +0 -7
- package/docs/TEST-INSTRUMENTATION.md +0 -405
- package/docs/telemetry.md +0 -427
- package/test-debug.js +0 -33
- package/test-special.mjs +0 -46
- package/test_runner.ts +0 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/export/openapi-exporter.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Model } from \"../core/model.js\";\nimport type { Exporter, ExportOptions } from \"./types.js\";\n\ninterface OpenAPISpec {\n openapi: string;\n info: {\n title: string;\n version: string;\n description?: string;\n };\n paths: Record<string, unknown>;\n components: {\n schemas?: Record<string, unknown>;\n responses?: Record<string, unknown>;\n parameters?: Record<string, unknown>;\n requestBodies?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n securitySchemes?: Record<string, unknown>;\n };\n servers?: Array<{ url: string; description?: string }>;\n tags?: Array<{ name: string; description?: string }>;\n externalDocs?: { url: string; description?: string };\n security?: unknown[];\n}\n\n/**\n * OpenAPI 3.0 Exporter for layer 6 (API)\n */\nexport class OpenAPIExporter implements Exporter {\n name = \"OpenAPI\";\n supportedLayers = [\"api\"];\n\n async export(model: Model, _options: ExportOptions = {}): Promise<string> {\n const layer = await model.getLayer(\"api\");\n if (!layer) {\n throw new Error(\"No API layer found in model\");\n }\n\n // Note: _options is not used for OpenAPI exporter as it only supports the api layer\n // The parameter is kept for interface consistency with other exporters\n\n const spec: OpenAPISpec = {\n openapi: \"3.0.0\",\n info: {\n title: model.manifest.name,\n version: model.manifest.version || \"1.0.0\",\n },\n paths: {},\n components: {\n schemas: {},\n responses: {},\n parameters: {},\n requestBodies: {},\n headers: {},\n securitySchemes: {},\n },\n };\n\n if (model.manifest.description) {\n spec.info.description = model.manifest.description;\n }\n\n // Group endpoints by path\n const pathGroups = new Map<string, Array<{ method: string; element: any }>>();\n\n for (const element of layer.listElements()) {\n if (element.type === \"endpoint\") {\n const path = element.getProperty<string>(\"path\") || \"/\";\n const method = (element.getProperty<string>(\"method\") || \"get\").toLowerCase();\n\n if (!pathGroups.has(path)) {\n pathGroups.set(path, []);\n }\n pathGroups.get(path)!.push({ method, element });\n }\n }\n\n // Build paths section\n for (const [path, endpoints] of pathGroups) {\n const pathItem: Record<string, unknown> = {};\n\n for (const { method, element } of endpoints) {\n const operation: Record<string, unknown> = {\n summary: element.name,\n operationId: element.id,\n responses: element.getProperty(\"responses\") || {\n \"200\": {\n description: \"Successful response\",\n },\n },\n };\n\n if (element.description) {\n operation.description = element.description;\n }\n\n const tags = element.getProperty(\"tags\");\n if (tags) {\n operation.tags = tags;\n }\n\n const parameters = element.getProperty(\"parameters\");\n if (parameters) {\n operation.parameters = parameters;\n }\n\n const requestBody = element.getProperty(\"requestBody\");\n if (requestBody) {\n operation.requestBody = requestBody;\n }\n\n const security = element.getProperty(\"security\");\n if (security) {\n operation.security = security;\n }\n\n const deprecated = element.getProperty(\"deprecated\");\n if (deprecated) {\n operation.deprecated = deprecated;\n }\n\n pathItem[method] = operation;\n }\n\n (spec.paths as Record<string, unknown>)[path] = pathItem;\n }\n\n // Collect all schema definitions from elements\n for (const element of layer.listElements()) {\n if (element.type === \"schema\") {\n const schemaName = element.getProperty<string>(\"schemaName\") || element.id;\n const schema = element.getProperty(\"schema\");\n if (schema) {\n spec.components.schemas![schemaName] = schema;\n }\n }\n }\n\n // Collect security schemes if defined\n for (const element of layer.listElements()) {\n if (element.type === \"security-scheme\") {\n const schemeName = element.name;\n const schemeType = element.getProperty<string>(\"type\");\n if (schemeType) {\n const scheme: Record<string, unknown> = {\n type: schemeType,\n };\n\n const schemeProp = element.getProperty(\"scheme\");\n if (schemeProp) {\n scheme.scheme = schemeProp;\n }\n\n const bearerFormat = element.getProperty(\"bearerFormat\");\n if (bearerFormat) {\n scheme.bearerFormat = bearerFormat;\n }\n\n const flows = element.getProperty(\"flows\");\n if (flows) {\n scheme.flows = flows;\n }\n\n const openIdConnectUrl = element.getProperty(\"openIdConnectUrl\");\n if (openIdConnectUrl) {\n scheme.openIdConnectUrl = openIdConnectUrl;\n }\n\n if (element.description) {\n scheme.description = element.description;\n }\n\n spec.components.securitySchemes![schemeName] = scheme;\n }\n }\n }\n\n // Add servers if defined in manifest (would be stored separately)\n // For now, servers would need to be added via layer properties\n // This could be extended in the future\n\n // Remove empty component sections\n const components = spec.components;\n if (components.schemas && Object.keys(components.schemas).length === 0) {\n delete components.schemas;\n }\n if (components.responses && Object.keys(components.responses).length === 0) {\n delete components.responses;\n }\n if (components.parameters && Object.keys(components.parameters).length === 0) {\n delete components.parameters;\n }\n if (components.requestBodies && Object.keys(components.requestBodies).length === 0) {\n delete components.requestBodies;\n }\n if (components.headers && Object.keys(components.headers).length === 0) {\n delete components.headers;\n }\n if (components.securitySchemes && Object.keys(components.securitySchemes).length === 0) {\n delete components.securitySchemes;\n }\n if (Object.keys(components).length === 0) {\n delete (spec as Partial<OpenAPISpec>).components;\n }\n\n return JSON.stringify(spec, null, 2);\n }\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type { Model } from \"../core/model.js\";\nimport type { Exporter, ExportOptions } from \"./types.js\";\nimport { isTelemetryEnabled, startSpan, endSpan } from \"../telemetry/index.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\n\n/**\n * OpenAPI server definition\n * Specifies base URL and optional description for API access\n */\ninterface OpenAPIServer {\n url: string;\n description?: string;\n}\n\n/**\n * OpenAPI tag definition\n * Logical grouping for operations\n */\ninterface OpenAPITag {\n name: string;\n description?: string;\n}\n\n/**\n * OpenAPI external documentation link\n * Reference to external documentation\n */\ninterface OpenAPIExternalDocs {\n url: string;\n description?: string;\n}\n\n/**\n * OpenAPI info object\n * Metadata about the API\n */\ninterface OpenAPIInfo {\n title: string;\n version: string;\n description?: string;\n}\n\n/**\n * OpenAPI components section\n * Reusable schema definitions and other components\n */\ninterface OpenAPIComponents {\n schemas?: Record<string, unknown>;\n responses?: Record<string, unknown>;\n parameters?: Record<string, unknown>;\n requestBodies?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n securitySchemes?: Record<string, unknown>;\n}\n\n/**\n * OpenAPI specification root\n * Complete OpenAPI 3.0 document structure\n */\ninterface OpenAPISpec {\n openapi: string;\n info: OpenAPIInfo;\n paths: Record<string, unknown>;\n components: OpenAPIComponents;\n servers?: OpenAPIServer[];\n tags?: OpenAPITag[];\n externalDocs?: OpenAPIExternalDocs;\n security?: unknown[];\n}\n\n/**\n * Endpoint mapping entry\n * Groups endpoints by path and method for processing\n */\ninterface EndpointData {\n name: string;\n id: string;\n description?: string;\n getProperty: (key: string) => unknown;\n getSourceReference: () => unknown;\n}\n\ninterface EndpointMapping {\n method: string;\n element: EndpointData;\n}\n\n/**\n * OpenAPI 3.0 Exporter for layer 6 (API)\n */\nexport class OpenAPIExporter implements Exporter {\n name = \"OpenAPI\";\n supportedLayers = [\"api\"];\n\n async export(model: Model, _options: ExportOptions = {}): Promise<string> {\n const span = isTelemetryEnabled ? startSpan(\"export.format.openapi\") : null;\n\n try {\n // Load API layer elements\n const apiLayer = await model.getLayer(\"api\");\n if (!apiLayer) {\n throw new Error(\"No API layer found in model\");\n }\n const elements = apiLayer.listElements();\n if (elements.length === 0) {\n throw new Error(\"No API layer found in model\");\n }\n\n // Note: _options is not used for OpenAPI exporter as it only supports the api layer\n // The parameter is kept for interface consistency with other exporters\n\n const spec: OpenAPISpec = {\n openapi: \"3.0.0\",\n info: {\n title: model.manifest.name,\n version: model.manifest.version || \"1.0.0\",\n },\n paths: {},\n components: {\n schemas: {},\n responses: {},\n parameters: {},\n requestBodies: {},\n headers: {},\n securitySchemes: {},\n },\n };\n\n if (model.manifest.description) {\n spec.info.description = model.manifest.description;\n }\n\n // Group operations by operationId-derived path\n const pathGroups = new Map<string, EndpointMapping[]>();\n\n // Iterate layer elements for operation/endpoint nodes\n for (const element of elements) {\n if (element.type === \"operation\" || element.type === \"endpoint\") {\n const operationId =\n (element.attributes?.operationId as string) || element.name;\n\n // Derive URL path from element attributes (for endpoints) or slug (for operations)\n let pathKey: string;\n const attrPath = element.attributes?.path as string;\n if (attrPath) {\n // Use path from attributes (e.g., \"/api/orders\")\n pathKey = attrPath;\n } else {\n // Derive URL path from element slug (last segment of path)\n // e.g., api.operation.get-user-profile \u2192 /get-user-profile\n const slugSegment = (element as { path?: string }).path?.split(\".\").pop();\n pathKey = slugSegment ? `/${slugSegment}` : `/${operationId}`;\n }\n\n // Infer HTTP method from operationId prefix keywords or use method attribute\n const method = ((element.attributes?.method as string) || (() => {\n const opIdLower = operationId.toLowerCase();\n if (/^(create|post|add|insert|register|submit|send)/.test(opIdLower)) {\n return \"post\";\n } else if (/^(update|put|edit|modify|replace|set|save)/.test(opIdLower)) {\n return \"put\";\n } else if (/^(patch|partial)/.test(opIdLower)) {\n return \"patch\";\n } else if (/^(delete|remove|destroy|purge|clear|unregister)/.test(opIdLower)) {\n return \"delete\";\n }\n return \"get\";\n })()).toLowerCase();\n\n if (!pathGroups.has(pathKey)) {\n pathGroups.set(pathKey, []);\n }\n\n const endpointData: EndpointData = {\n name: (element.attributes?.summary as string) || element.name,\n id: element.id,\n description: element.description,\n getProperty: (key: string) => element.attributes?.[key],\n getSourceReference: () => element.getSourceReference(),\n };\n\n pathGroups.get(pathKey)!.push({ method, element: endpointData });\n }\n }\n\n // Build paths section\n for (const [path, endpoints] of pathGroups) {\n const pathItem: Record<string, unknown> = {};\n\n for (const { method, element } of endpoints) {\n const operation: Record<string, unknown> = {\n summary: element.name,\n operationId: (element.getProperty(\"operationId\") as string) || element.id,\n responses: element.getProperty(\"responses\") || {\n \"200\": {\n description: \"Successful response\",\n },\n },\n };\n\n if (element.description) {\n operation.description = element.description;\n }\n\n const tags = element.getProperty(\"tags\");\n if (tags) {\n operation.tags = Array.isArray(tags) ? tags : [tags];\n }\n\n const parameters = element.getProperty(\"parameters\");\n if (parameters) {\n operation.parameters = parameters;\n }\n\n const requestBody = element.getProperty(\"requestBody\");\n if (requestBody) {\n operation.requestBody = requestBody;\n }\n\n const security = element.getProperty(\"security\");\n if (security) {\n operation.security = security;\n }\n\n const deprecated = element.getProperty(\"deprecated\");\n if (deprecated) {\n operation.deprecated = deprecated;\n }\n\n // Add source reference if present\n const sourceRef = element.getSourceReference();\n if (sourceRef) {\n operation[\"x-source-reference\"] = sourceRef;\n }\n\n pathItem[method] = operation;\n }\n\n // Add source reference to PathItem if any endpoint has one\n // (Use first endpoint's source reference for the path)\n if (endpoints.length > 0) {\n const firstSourceRef = endpoints[0].element.getSourceReference();\n if (firstSourceRef) {\n pathItem[\"x-source-reference\"] = firstSourceRef;\n }\n }\n\n (spec.paths as Record<string, unknown>)[path] = pathItem;\n }\n\n // Collect all schema definitions from elements\n for (const element of elements) {\n if (element.type === \"schema\") {\n const schemaName = (element.attributes?.schemaName as string) || element.id;\n const schema = element.attributes?.schema;\n if (schema) {\n spec.components.schemas![schemaName] = schema;\n }\n }\n }\n\n // Collect security schemes if defined\n for (const element of elements) {\n if (element.type === \"security-scheme\") {\n const schemeName = element.name;\n const schemeType = element.attributes?.type as string;\n if (schemeType) {\n const scheme: Record<string, unknown> = {\n type: schemeType,\n };\n\n const schemeProp = element.attributes?.scheme;\n if (schemeProp) {\n scheme.scheme = schemeProp;\n }\n\n const bearerFormat = element.attributes?.bearerFormat;\n if (bearerFormat) {\n scheme.bearerFormat = bearerFormat;\n }\n\n const flows = element.attributes?.flows;\n if (flows) {\n scheme.flows = flows;\n }\n\n const openIdConnectUrl = element.attributes?.openIdConnectUrl;\n if (openIdConnectUrl) {\n scheme.openIdConnectUrl = openIdConnectUrl;\n }\n\n if (element.description) {\n scheme.description = element.description;\n }\n\n spec.components.securitySchemes![schemeName] = scheme;\n }\n }\n }\n\n // Add servers if defined in manifest (would be stored separately)\n // For now, servers would need to be added via layer properties\n // This could be extended in the future\n\n // Remove empty component sections\n const components = spec.components;\n if (components.schemas && Object.keys(components.schemas).length === 0) {\n delete components.schemas;\n }\n if (components.responses && Object.keys(components.responses).length === 0) {\n delete components.responses;\n }\n if (components.parameters && Object.keys(components.parameters).length === 0) {\n delete components.parameters;\n }\n if (components.requestBodies && Object.keys(components.requestBodies).length === 0) {\n delete components.requestBodies;\n }\n if (components.headers && Object.keys(components.headers).length === 0) {\n delete components.headers;\n }\n if (components.securitySchemes && Object.keys(components.securitySchemes).length === 0) {\n delete components.securitySchemes;\n }\n if (Object.keys(components).length === 0) {\n delete (spec as Partial<OpenAPISpec>).components;\n }\n\n const result = JSON.stringify(spec, null, 2) + \"\\n\";\n\n if (isTelemetryEnabled && span) {\n const endpointCount = Array.from(pathGroups.values()).reduce(\n (sum, endpoints) => sum + endpoints.length,\n 0\n );\n (span as any).setAttribute(\"export.endpointCount\", endpointCount);\n (span as any).setAttribute(\"export.pathCount\", pathGroups.size);\n (span as any).setAttribute(\n \"export.schemaCount\",\n Object.keys(spec.components?.schemas || {}).length\n );\n (span as any).setAttribute(\"export.size\", result.length);\n (span as any).setStatus({ code: 0 });\n }\n\n return result;\n } catch (error) {\n if (isTelemetryEnabled && span) {\n (span as any).recordException(error as Error);\n (span as any).setStatus({\n code: 2,\n message: getErrorMessage(error),\n });\n }\n throw error;\n } finally {\n endSpan(span);\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,51 +1,109 @@
|
|
|
1
1
|
import { ALL_LAYERS, LAYER_COLORS } from "./types.js";
|
|
2
|
+
import { isTelemetryEnabled, startSpan, endSpan } from "../telemetry/index.js";
|
|
3
|
+
import { getErrorMessage } from "../utils/errors.js";
|
|
2
4
|
class PlantUMLExporter {
|
|
3
5
|
name = "PlantUML";
|
|
4
6
|
supportedLayers = ALL_LAYERS;
|
|
5
7
|
async export(model, options = {}) {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
for (const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
lines.push(
|
|
8
|
+
const span = isTelemetryEnabled ? startSpan("export.format.plantuml", {
|
|
9
|
+
"export.layerCount": options.layers?.length || this.supportedLayers.length,
|
|
10
|
+
"export.includeSources": options.includeSources === !0
|
|
11
|
+
}) : null;
|
|
12
|
+
try {
|
|
13
|
+
const lines = [];
|
|
14
|
+
lines.push("@startuml"), lines.push(`title "${this.escapeQuotes(model.manifest.name)}"`), lines.push(""), model.manifest.description && (lines.push(`note top : "${this.escapeQuotes(model.manifest.description)}"`), lines.push(""));
|
|
15
|
+
const layersToExport = options.layers || this.supportedLayers, elementsByLayer = /* @__PURE__ */ new Map(), nodesByLayer = /* @__PURE__ */ new Map(), rawToPlantUMLId = /* @__PURE__ */ new Map();
|
|
16
|
+
for (const layerName of layersToExport) {
|
|
17
|
+
const nodes = model.graph.getNodesByLayer(layerName);
|
|
18
|
+
if (nodes.length === 0)
|
|
19
|
+
continue;
|
|
20
|
+
const layerElements = [];
|
|
21
|
+
nodesByLayer.set(layerName, nodes);
|
|
22
|
+
for (const node of nodes) {
|
|
23
|
+
const pumlId = this.toPlantUMLId(node.id);
|
|
24
|
+
rawToPlantUMLId.set(node.id, pumlId), layerElements.push({
|
|
25
|
+
id: pumlId,
|
|
26
|
+
name: node.name,
|
|
27
|
+
type: node.type,
|
|
28
|
+
description: node.description
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
elementsByLayer.set(layerName, layerElements);
|
|
32
|
+
}
|
|
33
|
+
for (const layerName of layersToExport) {
|
|
34
|
+
const elements = elementsByLayer.get(layerName);
|
|
35
|
+
if (!elements || elements.length === 0)
|
|
36
|
+
continue;
|
|
37
|
+
const color = LAYER_COLORS[layerName] || "FFFFFF";
|
|
38
|
+
lines.push(`package "${layerName}" #${color} {`);
|
|
39
|
+
const nodes = nodesByLayer.get(layerName) || [];
|
|
40
|
+
for (let i = 0; i < elements.length; i++) {
|
|
41
|
+
const element = elements[i];
|
|
42
|
+
if (lines.push(` component "${this.escapeQuotes(element.name)}" as ${element.id}`), options.includeSources) {
|
|
43
|
+
const node = nodes[i], sourceRef = this.extractSourceReference(node);
|
|
44
|
+
sourceRef && (lines.push(` note right of ${element.id}`), lines.push(` ${this.escapeQuotes(sourceRef)}`), lines.push(" end note"));
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
lines.push("}"), lines.push("");
|
|
48
|
+
}
|
|
49
|
+
const edges = model.graph.getAllEdges();
|
|
50
|
+
for (const edge of edges) {
|
|
51
|
+
const srcPuml = rawToPlantUMLId.get(edge.source), dstPuml = rawToPlantUMLId.get(edge.destination);
|
|
52
|
+
if (srcPuml && dstPuml) {
|
|
53
|
+
const arrow = this.getArrowType(edge.predicate);
|
|
54
|
+
lines.push(`${srcPuml} ${arrow} ${dstPuml} : ${this.escapeQuotes(edge.predicate)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
lines.push(""), lines.push("@enduml");
|
|
58
|
+
const result = lines.join(`
|
|
47
59
|
`) + `
|
|
48
60
|
`;
|
|
61
|
+
if (isTelemetryEnabled && span) {
|
|
62
|
+
let totalElements = 0, totalEdges = 0;
|
|
63
|
+
for (const elements of elementsByLayer.values())
|
|
64
|
+
totalElements += elements.length;
|
|
65
|
+
for (const edge of edges)
|
|
66
|
+
rawToPlantUMLId.has(edge.source) && rawToPlantUMLId.has(edge.destination) && totalEdges++;
|
|
67
|
+
span.setAttribute("export.elementCount", totalElements), span.setAttribute("export.relationshipCount", totalEdges), span.setAttribute("export.size", result.length), span.setStatus({ code: 0 });
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
} catch (error) {
|
|
71
|
+
throw isTelemetryEnabled && span && (span.recordException(error), span.setStatus({
|
|
72
|
+
code: 2,
|
|
73
|
+
message: getErrorMessage(error)
|
|
74
|
+
})), error;
|
|
75
|
+
} finally {
|
|
76
|
+
endSpan(span);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get PlantUML arrow type based on predicate
|
|
81
|
+
*/
|
|
82
|
+
getArrowType(predicate) {
|
|
83
|
+
return {
|
|
84
|
+
composes: "*--",
|
|
85
|
+
aggregates: "o--",
|
|
86
|
+
supports: "-->",
|
|
87
|
+
realizes: "..|>",
|
|
88
|
+
"flows-to": "-->",
|
|
89
|
+
"refers-to": "..>"
|
|
90
|
+
}[predicate] || "-->";
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Extract and format source reference from node properties
|
|
94
|
+
*/
|
|
95
|
+
extractSourceReference(node) {
|
|
96
|
+
if (!node)
|
|
97
|
+
return null;
|
|
98
|
+
let sourceRef = node.source_reference;
|
|
99
|
+
if (sourceRef || (sourceRef = node.properties?.["x-source-reference"]), !sourceRef && node.properties?.source?.reference && (sourceRef = node.properties.source.reference), !sourceRef)
|
|
100
|
+
return null;
|
|
101
|
+
const parts = [];
|
|
102
|
+
if (Array.isArray(sourceRef.locations) && sourceRef.locations.length > 0) {
|
|
103
|
+
const location = sourceRef.locations[0];
|
|
104
|
+
location.file && parts.push(`Source: ${location.file}`), location.symbol && parts.push(`Symbol: ${location.symbol}`);
|
|
105
|
+
}
|
|
106
|
+
return sourceRef.repository?.url && (parts.push(`Repo: ${sourceRef.repository.url}`), sourceRef.repository.commit && parts.push(`Commit: ${sourceRef.repository.commit.substring(0, 8)}`)), parts.length > 0 ? parts.join("\\n") : null;
|
|
49
107
|
}
|
|
50
108
|
/**
|
|
51
109
|
* Escape quotes for PlantUML syntax
|
|
@@ -53,6 +111,13 @@ class PlantUMLExporter {
|
|
|
53
111
|
escapeQuotes(str) {
|
|
54
112
|
return str.replace(/"/g, '\\"');
|
|
55
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Convert a raw element ID (path or UUID) to a valid PlantUML identifier.
|
|
116
|
+
* PlantUML identifiers cannot contain dots or hyphens, so replace with underscores.
|
|
117
|
+
*/
|
|
118
|
+
toPlantUMLId(id) {
|
|
119
|
+
return id.replace(/[.\-]/g, "_");
|
|
120
|
+
}
|
|
56
121
|
}
|
|
57
122
|
export {
|
|
58
123
|
PlantUMLExporter
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/export/plantuml-exporter.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Model } from \"../core/model.js\";\nimport type { Exporter, ExportOptions } from \"./types.js\";\nimport { ALL_LAYERS, LAYER_COLORS } from \"./types.js\";\n\n/**\n * PlantUML Exporter - generates PlantUML syntax for diagram visualization\n * Supports all 12 layers\n */\nexport class PlantUMLExporter implements Exporter {\n name = \"PlantUML\";\n supportedLayers = ALL_LAYERS;\n\n async export(model: Model, options: ExportOptions = {}): Promise<string> {\n const lines: string[] = [];\n\n
|
|
5
|
-
"mappings": "AAEA,SAAS,YAAY,oBAAoB;
|
|
4
|
+
"sourcesContent": ["import type { Model } from \"../core/model.js\";\nimport type { Exporter, ExportOptions } from \"./types.js\";\nimport { ALL_LAYERS, LAYER_COLORS } from \"./types.js\";\nimport { isTelemetryEnabled, startSpan, endSpan } from \"../telemetry/index.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\n\n/**\n * PlantUML element entry for diagram generation\n * Contains element metadata for rendering from graph nodes\n */\ninterface PlantUMLElementEntry {\n id: string;\n name: string;\n type: string;\n description?: string;\n}\n\n/**\n * PlantUML Exporter - generates PlantUML syntax for diagram visualization\n * Supports all 12 layers\n *\n * Exports the model as PlantUML component diagram syntax with layers,\n * elements, relationships, and optional source references.\n */\nexport class PlantUMLExporter implements Exporter {\n name = \"PlantUML\";\n supportedLayers = ALL_LAYERS;\n\n async export(model: Model, options: ExportOptions = {}): Promise<string> {\n const span = isTelemetryEnabled\n ? startSpan(\"export.format.plantuml\", {\n \"export.layerCount\": options.layers?.length || this.supportedLayers.length,\n \"export.includeSources\": options.includeSources === true,\n })\n : null;\n\n try {\n const lines: string[] = [];\n\n lines.push(\"@startuml\");\n lines.push(`title \"${this.escapeQuotes(model.manifest.name)}\"`);\n lines.push(\"\");\n\n if (model.manifest.description) {\n lines.push(`note top : \"${this.escapeQuotes(model.manifest.description)}\"`);\n lines.push(\"\");\n }\n\n const layersToExport = options.layers || this.supportedLayers;\n const elementsByLayer = new Map<string, PlantUMLElementEntry[]>();\n const nodesByLayer = new Map<string, any[]>();\n // Map from raw graph node ID \u2192 sanitized PlantUML ID for edge rendering\n const rawToPlantUMLId = new Map<string, string>();\n\n // Collect nodes by layer from graph model\n for (const layerName of layersToExport) {\n const nodes = model.graph.getNodesByLayer(layerName);\n if (nodes.length === 0) continue;\n\n const layerElements: PlantUMLElementEntry[] = [];\n nodesByLayer.set(layerName, nodes);\n\n for (const node of nodes) {\n const pumlId = this.toPlantUMLId(node.id);\n rawToPlantUMLId.set(node.id, pumlId);\n layerElements.push({\n id: pumlId,\n name: node.name,\n type: node.type,\n description: node.description,\n });\n }\n elementsByLayer.set(layerName, layerElements);\n }\n\n // Create packages for each layer\n for (const layerName of layersToExport) {\n const elements = elementsByLayer.get(layerName);\n if (!elements || elements.length === 0) continue;\n\n const color = LAYER_COLORS[layerName] || \"FFFFFF\";\n lines.push(`package \"${layerName}\" #${color} {`);\n\n const nodes = nodesByLayer.get(layerName) || [];\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n lines.push(` component \"${this.escapeQuotes(element.name)}\" as ${element.id}`);\n\n // Add source reference as note if includeSources option is enabled\n if (options.includeSources) {\n const node = nodes[i];\n const sourceRef = this.extractSourceReference(node);\n if (sourceRef) {\n lines.push(` note right of ${element.id}`);\n lines.push(` ${this.escapeQuotes(sourceRef)}`);\n lines.push(` end note`);\n }\n }\n }\n\n lines.push(\"}\");\n lines.push(\"\");\n }\n\n // Add relationships from graph edges\n const edges = model.graph.getAllEdges();\n\n for (const edge of edges) {\n // Only include edges between exported nodes (check raw IDs)\n const srcPuml = rawToPlantUMLId.get(edge.source);\n const dstPuml = rawToPlantUMLId.get(edge.destination);\n if (srcPuml && dstPuml) {\n const arrow = this.getArrowType(edge.predicate);\n lines.push(\n `${srcPuml} ${arrow} ${dstPuml} : ${this.escapeQuotes(edge.predicate)}`\n );\n }\n }\n\n lines.push(\"\");\n lines.push(\"@enduml\");\n\n const result = lines.join(\"\\n\") + \"\\n\";\n\n if (isTelemetryEnabled && span) {\n // Count total elements and relationships\n let totalElements = 0;\n let totalEdges = 0;\n\n for (const elements of elementsByLayer.values()) {\n totalElements += elements.length;\n }\n\n for (const edge of edges) {\n if (rawToPlantUMLId.has(edge.source) && rawToPlantUMLId.has(edge.destination)) {\n totalEdges++;\n }\n }\n\n (span as any).setAttribute(\"export.elementCount\", totalElements);\n (span as any).setAttribute(\"export.relationshipCount\", totalEdges);\n (span as any).setAttribute(\"export.size\", result.length);\n (span as any).setStatus({ code: 0 });\n }\n\n return result;\n } catch (error) {\n if (isTelemetryEnabled && span) {\n (span as any).recordException(error as Error);\n (span as any).setStatus({\n code: 2,\n message: getErrorMessage(error),\n });\n }\n throw error;\n } finally {\n endSpan(span);\n }\n }\n\n /**\n * Get PlantUML arrow type based on predicate\n */\n private getArrowType(predicate: string): string {\n const arrowMap: Record<string, string> = {\n composes: \"*--\",\n aggregates: \"o--\",\n supports: \"-->\",\n realizes: \"..|>\",\n \"flows-to\": \"-->\",\n \"refers-to\": \"..>\",\n };\n return arrowMap[predicate] || \"-->\";\n }\n\n /**\n * Extract and format source reference from node properties\n */\n private extractSourceReference(node: any): string | null {\n if (!node) return null;\n\n // Try node.source_reference first (primary field on GraphNode)\n let sourceRef = node.source_reference;\n\n // Fall back to x-source-reference in properties\n if (!sourceRef) {\n sourceRef = node.properties?.[\"x-source-reference\"];\n }\n\n // Fall back to nested source.reference format\n if (!sourceRef && node.properties?.source?.reference) {\n sourceRef = node.properties.source.reference;\n }\n\n if (!sourceRef) return null;\n\n // Format source reference for display\n const parts: string[] = [];\n\n if (Array.isArray(sourceRef.locations) && sourceRef.locations.length > 0) {\n const location = sourceRef.locations[0];\n if (location.file) {\n parts.push(`Source: ${location.file}`);\n }\n if (location.symbol) {\n parts.push(`Symbol: ${location.symbol}`);\n }\n }\n\n if (sourceRef.repository?.url) {\n parts.push(`Repo: ${sourceRef.repository.url}`);\n if (sourceRef.repository.commit) {\n parts.push(`Commit: ${sourceRef.repository.commit.substring(0, 8)}`);\n }\n }\n\n return parts.length > 0 ? parts.join(\"\\\\n\") : null;\n }\n\n /**\n * Escape quotes for PlantUML syntax\n */\n private escapeQuotes(str: string): string {\n // Escape double quotes within strings for PlantUML\n return str.replace(/\"/g, '\\\\\"');\n }\n\n /**\n * Convert a raw element ID (path or UUID) to a valid PlantUML identifier.\n * PlantUML identifiers cannot contain dots or hyphens, so replace with underscores.\n */\n private toPlantUMLId(id: string): string {\n return id.replace(/[.\\-]/g, \"_\");\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import ansis from "ansis";
|
|
2
|
+
import { formatDate } from "../utils/date-utils.js";
|
|
3
|
+
function formatReport(report, options) {
|
|
4
|
+
switch (options.format) {
|
|
5
|
+
case "json":
|
|
6
|
+
return formatJSON(report);
|
|
7
|
+
case "markdown":
|
|
8
|
+
return formatMarkdown(report, options);
|
|
9
|
+
case "compact":
|
|
10
|
+
return formatCompact(report);
|
|
11
|
+
case "text":
|
|
12
|
+
default:
|
|
13
|
+
return formatText(report, options);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function formatText(report, options) {
|
|
17
|
+
const lines = [];
|
|
18
|
+
return lines.push(""), lines.push(ansis.bold(`\u{1F4CA} Architecture Report: ${ansis.cyan(report.statistics.project.name)}`)), lines.push(ansis.dim("=".repeat(80))), lines.push(""), lines.push(`Generated: ${formatDate(report.timestamp)}`), lines.push(`Version: ${report.statistics.project.version}`), lines.push(""), options.includeQuality && (formatQualitySection(lines, report.quality), lines.push("")), formatStatisticsSection(lines, report), lines.push(""), formatRelationshipsSection(lines, report), lines.push(""), options.includeDataModel && (formatDataModelSection(lines, report), lines.push("")), lines.join(`
|
|
19
|
+
`);
|
|
20
|
+
}
|
|
21
|
+
function formatJSON(report) {
|
|
22
|
+
return JSON.stringify(report, null, 2) + `
|
|
23
|
+
`;
|
|
24
|
+
}
|
|
25
|
+
function formatMarkdown(report, options) {
|
|
26
|
+
const lines = [];
|
|
27
|
+
return lines.push(`# Architecture Report: ${report.statistics.project.name}`), lines.push(""), lines.push(`**Generated:** ${formatDate(report.timestamp)}`), lines.push(`**Version:** ${report.statistics.project.version}`), lines.push(""), lines.push("## Contents"), lines.push("- [Quality Metrics](#quality-metrics)"), lines.push("- [Statistics](#statistics)"), lines.push("- [Relationships](#relationships)"), options.includeDataModel && lines.push("- [Data Model](#data-model)"), lines.push(""), options.includeQuality && (formatQualityMarkdown(lines, report.quality), lines.push("")), formatStatisticsMarkdown(lines, report), lines.push(""), formatRelationshipsMarkdown(lines, report), lines.push(""), options.includeDataModel && (formatDataModelMarkdown(lines, report), lines.push("")), lines.join(`
|
|
28
|
+
`);
|
|
29
|
+
}
|
|
30
|
+
function formatCompact(report) {
|
|
31
|
+
const stats = report.statistics.statistics, quality = report.quality;
|
|
32
|
+
return `${report.statistics.project.name} v${report.statistics.project.version}: ${stats.totalElements} elements, ${stats.totalRelationships} relationships, ${report.relationships.circularDependencies.length} circular deps, ${Math.round(quality.elementCoverage)}% coverage`;
|
|
33
|
+
}
|
|
34
|
+
function formatQualitySection(lines, quality) {
|
|
35
|
+
lines.push(ansis.bold("Quality Metrics:")), lines.push(` ${ansis.gray("Element Coverage:")} ${qualityBar(quality.elementCoverage)} ${quality.elementCoverage.toFixed(0)}%`), lines.push(` ${ansis.gray("Relationship Coverage:")} ${qualityBar(quality.relationshipCoverage)} ${quality.relationshipCoverage.toFixed(0)}%`), lines.push(` ${ansis.gray("Documentation Coverage:")} ${qualityBar(quality.documentationCoverage)} ${quality.documentationCoverage.toFixed(0)}%`), lines.push(` ${ansis.gray("Layer Coverage:")} ${qualityBar(quality.layerCoverage)} ${quality.layerCoverage.toFixed(0)}%`), lines.push(""), lines.push(` ${ansis.gray("ArchiMate Compliance:")} ${quality.archimateCompliance.toFixed(0)}%`), lines.push(` ${ansis.gray("Spec Compliance:")} ${quality.specCompliance.toFixed(0)}%`), lines.push(` ${ansis.gray("Semantic Consistency:")} ${quality.semanticConsistency.toFixed(0)}%`), lines.push(""), lines.push(` ${ansis.gray("Orphaned Elements:")} ${quality.orphanedElements > 0 ? ansis.yellow(quality.orphanedElements) : ansis.green("0")}`), lines.push(` ${ansis.gray("Circular Dependencies:")} ${quality.circularDependencies > 0 ? ansis.red(quality.circularDependencies) : ansis.green("0")}`);
|
|
36
|
+
}
|
|
37
|
+
function formatStatisticsSection(lines, report) {
|
|
38
|
+
const stats = report.statistics;
|
|
39
|
+
lines.push(ansis.bold("Statistics:")), lines.push(` ${ansis.gray("Total Elements:")} ${stats.statistics.totalElements}`), lines.push(` ${ansis.gray("Total Relationships:")} ${stats.statistics.totalRelationships}`), lines.push(` ${ansis.gray("Populated Layers:")} ${stats.statistics.populatedLayers}/${stats.statistics.totalLayers}`), lines.push(""), lines.push(ansis.bold("Top Element Types:"));
|
|
40
|
+
for (const layer of stats.layers.slice(0, 5))
|
|
41
|
+
if (layer.totalElements > 0) {
|
|
42
|
+
const types = Object.entries(layer.elementsByType).sort(([, a], [, b]) => b - a).slice(0, 3).map(([type, count]) => `${count} ${type}`).join(", ");
|
|
43
|
+
lines.push(` ${layer.name}: ${types}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function formatRelationshipsSection(lines, report) {
|
|
47
|
+
const relationships = report.relationships;
|
|
48
|
+
lines.push(ansis.bold("Relationships:")), lines.push(` ${ansis.gray("Cross-Layer:")} ${relationships.crossLayerCount}`), lines.push(` ${ansis.gray("Intra-Layer:")} ${relationships.intraLayerCount}`), lines.push(""), lines.push(ansis.bold("By Category:"));
|
|
49
|
+
const categoryEntries = Object.entries(relationships.byCategory).sort(([, a], [, b]) => b - a).slice(0, 5);
|
|
50
|
+
for (const [category, count] of categoryEntries) {
|
|
51
|
+
const percentage = relationships.totalRelationships > 0 ? count / relationships.totalRelationships * 100 : 0;
|
|
52
|
+
lines.push(` ${category.padEnd(20)} ${String(count).padEnd(3)} (${percentage.toFixed(0)}%)`);
|
|
53
|
+
}
|
|
54
|
+
if (relationships.circularDependencies.length > 0) {
|
|
55
|
+
lines.push(""), lines.push(ansis.bold(ansis.red("\u26A0\uFE0F Circular Dependencies:")));
|
|
56
|
+
for (const circular of relationships.circularDependencies.slice(0, 5))
|
|
57
|
+
lines.push(` ${circular.elements.join(" \u2192 ")} \u2192 ${circular.elements[0]}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function formatDataModelSection(lines, report) {
|
|
61
|
+
const dataModel = report.dataModel;
|
|
62
|
+
if (lines.push(ansis.bold("Data Model (Layer 7):")), lines.push(` ${ansis.gray("Total Entities:")} ${dataModel.entityCount}`), lines.push(` ${ansis.gray("Total Attributes:")} ${dataModel.attributeCount}`), lines.push(` ${ansis.gray("Entity Relationships:")} ${dataModel.relationshipCount}`), lines.push(` ${ansis.gray("Referenced Entities:")} ${dataModel.referencedEntities}`), lines.push(""), dataModel.orphanedEntities.length > 0) {
|
|
63
|
+
lines.push(ansis.bold(ansis.yellow("\u26A0\uFE0F Orphaned Entities:")));
|
|
64
|
+
for (const entity of dataModel.orphanedEntities.slice(0, 5))
|
|
65
|
+
lines.push(` - ${entity}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function formatQualityMarkdown(lines, quality) {
|
|
69
|
+
lines.push("## Quality Metrics"), lines.push(""), lines.push("### Coverage"), lines.push("| Metric | Value |"), lines.push("|--------|-------|"), lines.push(`| Element Coverage | ${quality.elementCoverage.toFixed(0)}% |`), lines.push(`| Relationship Coverage | ${quality.relationshipCoverage.toFixed(0)}% |`), lines.push(`| Documentation Coverage | ${quality.documentationCoverage.toFixed(0)}% |`), lines.push(`| Layer Coverage | ${quality.layerCoverage.toFixed(0)}% |`), lines.push(""), lines.push("### Compliance"), lines.push("| Metric | Score |"), lines.push("|--------|-------|"), lines.push(`| ArchiMate Compliance | ${quality.archimateCompliance.toFixed(0)}% |`), lines.push(`| Spec Compliance | ${quality.specCompliance.toFixed(0)}% |`), lines.push(`| Semantic Consistency | ${quality.semanticConsistency.toFixed(0)}% |`), lines.push(""), lines.push("### Issues"), lines.push(`- Orphaned Elements: ${quality.orphanedElements}`), lines.push(`- Circular Dependencies: ${quality.circularDependencies}`), lines.push("");
|
|
70
|
+
}
|
|
71
|
+
function formatStatisticsMarkdown(lines, report) {
|
|
72
|
+
const stats = report.statistics;
|
|
73
|
+
lines.push("## Statistics"), lines.push(""), lines.push("### Overview"), lines.push("| Metric | Value |"), lines.push("|--------|-------|"), lines.push(`| Total Elements | ${stats.statistics.totalElements} |`), lines.push(`| Total Relationships | ${stats.statistics.totalRelationships} |`), lines.push(`| Populated Layers | ${stats.statistics.populatedLayers}/${stats.statistics.totalLayers} |`), lines.push(""), lines.push("### Elements by Layer"), lines.push("| Layer | Count | Types |"), lines.push("|-------|-------|-------|");
|
|
74
|
+
for (const layer of stats.layers)
|
|
75
|
+
if (layer.totalElements > 0) {
|
|
76
|
+
const types = Object.keys(layer.elementsByType).join(", ");
|
|
77
|
+
lines.push(`| ${layer.name} | ${layer.totalElements} | ${types} |`);
|
|
78
|
+
}
|
|
79
|
+
lines.push("");
|
|
80
|
+
}
|
|
81
|
+
function formatRelationshipsMarkdown(lines, report) {
|
|
82
|
+
const relationships = report.relationships;
|
|
83
|
+
lines.push("## Relationships"), lines.push(""), lines.push("### Overview"), lines.push("| Type | Count |"), lines.push("|------|-------|"), lines.push(`| Total | ${relationships.totalRelationships} |`), lines.push(`| Cross-Layer | ${relationships.crossLayerCount} |`), lines.push(`| Intra-Layer | ${relationships.intraLayerCount} |`), lines.push(""), lines.push("### By Category"), lines.push("| Category | Count | Percentage |"), lines.push("|----------|-------|-----------|");
|
|
84
|
+
for (const [category, count] of Object.entries(relationships.byCategory).sort(([, a], [, b]) => b - a)) {
|
|
85
|
+
const percentage = (count / relationships.totalRelationships * 100).toFixed(1);
|
|
86
|
+
lines.push(`| ${category} | ${count} | ${percentage}% |`);
|
|
87
|
+
}
|
|
88
|
+
if (lines.push(""), relationships.circularDependencies.length > 0) {
|
|
89
|
+
lines.push("### Circular Dependencies");
|
|
90
|
+
for (const circular of relationships.circularDependencies)
|
|
91
|
+
lines.push(`- ${circular.elements.join(" \u2192 ")} \u2192 ${circular.elements[0]}`);
|
|
92
|
+
lines.push("");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function formatDataModelMarkdown(lines, report) {
|
|
96
|
+
const dataModel = report.dataModel;
|
|
97
|
+
if (lines.push("## Data Model (Layer 7)"), lines.push(""), lines.push("### Overview"), lines.push("| Metric | Value |"), lines.push("|--------|-------|"), lines.push(`| Total Entities | ${dataModel.entityCount} |`), lines.push(`| Total Attributes | ${dataModel.attributeCount} |`), lines.push(`| Entity Relationships | ${dataModel.relationshipCount} |`), lines.push(`| Referenced Entities | ${dataModel.referencedEntities} |`), lines.push(""), dataModel.orphanedEntities.length > 0) {
|
|
98
|
+
lines.push("### Orphaned Entities");
|
|
99
|
+
for (const entity of dataModel.orphanedEntities)
|
|
100
|
+
lines.push(`- ${entity}`);
|
|
101
|
+
lines.push("");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function qualityBar(percentage) {
|
|
105
|
+
const filled = Math.round(percentage / 100 * 20), empty = 20 - filled, bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
106
|
+
return percentage >= 80 ? ansis.green(bar) : percentage >= 60 ? ansis.yellow(bar) : ansis.red(bar);
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
formatReport
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=report-formatters.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/export/report-formatters.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Report formatters for comprehensive architecture reports\n * Supports text, JSON, and markdown output formats\n */\n\nimport ansis from \"ansis\";\nimport { ReportData, QualityMetrics } from \"../core/report-data-model.js\";\nimport { formatDate } from \"../utils/date-utils.js\";\n\nexport type ReportFormat = \"text\" | \"json\" | \"markdown\" | \"compact\";\n\nexport interface ReportFormatterOptions {\n format: ReportFormat;\n compact?: boolean;\n verbose?: boolean;\n includeDataModel?: boolean;\n includeQuality?: boolean;\n}\n\n/**\n * Format report for output\n */\nexport function formatReport(report: ReportData, options: ReportFormatterOptions): string {\n switch (options.format) {\n case \"json\":\n return formatJSON(report);\n case \"markdown\":\n return formatMarkdown(report, options);\n case \"compact\":\n return formatCompact(report);\n case \"text\":\n default:\n return formatText(report, options);\n }\n}\n\n/**\n * Format as plain text (default)\n */\nfunction formatText(report: ReportData, options: ReportFormatterOptions): string {\n const lines: string[] = [];\n\n // Header\n lines.push(\"\");\n lines.push(ansis.bold(`\uD83D\uDCCA Architecture Report: ${ansis.cyan(report.statistics.project.name)}`));\n lines.push(ansis.dim(\"=\".repeat(80)));\n lines.push(\"\");\n lines.push(`Generated: ${formatDate(report.timestamp)}`);\n lines.push(`Version: ${report.statistics.project.version}`);\n lines.push(\"\");\n\n // Quality Overview\n if (options.includeQuality) {\n formatQualitySection(lines, report.quality);\n lines.push(\"\");\n }\n\n // Statistics\n formatStatisticsSection(lines, report);\n lines.push(\"\");\n\n // Relationships\n formatRelationshipsSection(lines, report);\n lines.push(\"\");\n\n // Data Model\n if (options.includeDataModel) {\n formatDataModelSection(lines, report);\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format as JSON\n */\nfunction formatJSON(report: ReportData): string {\n return JSON.stringify(report, null, 2) + \"\\n\";\n}\n\n/**\n * Format as Markdown\n */\nfunction formatMarkdown(report: ReportData, options: ReportFormatterOptions): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`# Architecture Report: ${report.statistics.project.name}`);\n lines.push(\"\");\n lines.push(`**Generated:** ${formatDate(report.timestamp)}`);\n lines.push(`**Version:** ${report.statistics.project.version}`);\n lines.push(\"\");\n\n // Table of Contents\n lines.push(\"## Contents\");\n lines.push(\"- [Quality Metrics](#quality-metrics)\");\n lines.push(\"- [Statistics](#statistics)\");\n lines.push(\"- [Relationships](#relationships)\");\n if (options.includeDataModel) {\n lines.push(\"- [Data Model](#data-model)\");\n }\n lines.push(\"\");\n\n // Quality Metrics\n if (options.includeQuality) {\n formatQualityMarkdown(lines, report.quality);\n lines.push(\"\");\n }\n\n // Statistics\n formatStatisticsMarkdown(lines, report);\n lines.push(\"\");\n\n // Relationships\n formatRelationshipsMarkdown(lines, report);\n lines.push(\"\");\n\n // Data Model\n if (options.includeDataModel) {\n formatDataModelMarkdown(lines, report);\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format as compact single line\n */\nfunction formatCompact(report: ReportData): string {\n const stats = report.statistics.statistics;\n const quality = report.quality;\n\n return (\n `${report.statistics.project.name} v${report.statistics.project.version}: ` +\n `${stats.totalElements} elements, ` +\n `${stats.totalRelationships} relationships, ` +\n `${report.relationships.circularDependencies.length} circular deps, ` +\n `${Math.round(quality.elementCoverage)}% coverage`\n );\n}\n\n/**\n * Format quality section for text output\n */\nfunction formatQualitySection(lines: string[], quality: QualityMetrics): void {\n lines.push(ansis.bold(\"Quality Metrics:\"));\n lines.push(\n ` ${ansis.gray(\"Element Coverage:\")} ${qualityBar(quality.elementCoverage)} ${quality.elementCoverage.toFixed(0)}%`\n );\n lines.push(\n ` ${ansis.gray(\"Relationship Coverage:\")} ${qualityBar(quality.relationshipCoverage)} ${quality.relationshipCoverage.toFixed(0)}%`\n );\n lines.push(\n ` ${ansis.gray(\"Documentation Coverage:\")} ${qualityBar(quality.documentationCoverage)} ${quality.documentationCoverage.toFixed(0)}%`\n );\n lines.push(\n ` ${ansis.gray(\"Layer Coverage:\")} ${qualityBar(quality.layerCoverage)} ${quality.layerCoverage.toFixed(0)}%`\n );\n lines.push(\"\");\n lines.push(\n ` ${ansis.gray(\"ArchiMate Compliance:\")} ${quality.archimateCompliance.toFixed(0)}%`\n );\n lines.push(\n ` ${ansis.gray(\"Spec Compliance:\")} ${quality.specCompliance.toFixed(0)}%`\n );\n lines.push(\n ` ${ansis.gray(\"Semantic Consistency:\")} ${quality.semanticConsistency.toFixed(0)}%`\n );\n lines.push(\"\");\n lines.push(\n ` ${ansis.gray(\"Orphaned Elements:\")} ${quality.orphanedElements > 0 ? ansis.yellow(quality.orphanedElements) : ansis.green(\"0\")}`\n );\n lines.push(\n ` ${ansis.gray(\"Circular Dependencies:\")} ${quality.circularDependencies > 0 ? ansis.red(quality.circularDependencies) : ansis.green(\"0\")}`\n );\n}\n\n/**\n * Format statistics section for text output\n */\nfunction formatStatisticsSection(lines: string[], report: ReportData): void {\n const stats = report.statistics;\n\n lines.push(ansis.bold(\"Statistics:\"));\n lines.push(\n ` ${ansis.gray(\"Total Elements:\")} ${stats.statistics.totalElements}`\n );\n lines.push(\n ` ${ansis.gray(\"Total Relationships:\")} ${stats.statistics.totalRelationships}`\n );\n lines.push(\n ` ${ansis.gray(\"Populated Layers:\")} ${stats.statistics.populatedLayers}/${stats.statistics.totalLayers}`\n );\n lines.push(\"\");\n\n lines.push(ansis.bold(\"Top Element Types:\"));\n for (const layer of stats.layers.slice(0, 5)) {\n if (layer.totalElements > 0) {\n const types = Object.entries(layer.elementsByType)\n .sort(([, a], [, b]) => b - a)\n .slice(0, 3)\n .map(([type, count]) => `${count} ${type}`)\n .join(\", \");\n lines.push(` ${layer.name}: ${types}`);\n }\n }\n}\n\n/**\n * Format relationships section for text output\n */\nfunction formatRelationshipsSection(lines: string[], report: ReportData): void {\n const relationships = report.relationships;\n\n lines.push(ansis.bold(\"Relationships:\"));\n lines.push(\n ` ${ansis.gray(\"Cross-Layer:\")} ${relationships.crossLayerCount}`\n );\n lines.push(\n ` ${ansis.gray(\"Intra-Layer:\")} ${relationships.intraLayerCount}`\n );\n lines.push(\"\");\n\n lines.push(ansis.bold(\"By Category:\"));\n const categoryEntries = Object.entries(relationships.byCategory)\n .sort(([, a], [, b]) => b - a)\n .slice(0, 5);\n\n for (const [category, count] of categoryEntries) {\n const percentage = relationships.totalRelationships > 0 ? (count / relationships.totalRelationships) * 100 : 0;\n lines.push(` ${category.padEnd(20)} ${String(count).padEnd(3)} (${percentage.toFixed(0)}%)`);\n }\n\n if (relationships.circularDependencies.length > 0) {\n lines.push(\"\");\n lines.push(ansis.bold(ansis.red(\"\u26A0\uFE0F Circular Dependencies:\")));\n for (const circular of relationships.circularDependencies.slice(0, 5)) {\n lines.push(` ${circular.elements.join(\" \u2192 \")} \u2192 ${circular.elements[0]}`);\n }\n }\n}\n\n/**\n * Format data model section for text output\n */\nfunction formatDataModelSection(lines: string[], report: ReportData): void {\n const dataModel = report.dataModel;\n\n lines.push(ansis.bold(\"Data Model (Layer 7):\"));\n lines.push(\n ` ${ansis.gray(\"Total Entities:\")} ${dataModel.entityCount}`\n );\n lines.push(\n ` ${ansis.gray(\"Total Attributes:\")} ${dataModel.attributeCount}`\n );\n lines.push(\n ` ${ansis.gray(\"Entity Relationships:\")} ${dataModel.relationshipCount}`\n );\n lines.push(\n ` ${ansis.gray(\"Referenced Entities:\")} ${dataModel.referencedEntities}`\n );\n lines.push(\"\");\n\n if (dataModel.orphanedEntities.length > 0) {\n lines.push(ansis.bold(ansis.yellow(\"\u26A0\uFE0F Orphaned Entities:\")));\n for (const entity of dataModel.orphanedEntities.slice(0, 5)) {\n lines.push(` - ${entity}`);\n }\n }\n}\n\n/**\n * Format quality section for markdown\n */\nfunction formatQualityMarkdown(lines: string[], quality: QualityMetrics): void {\n lines.push(\"## Quality Metrics\");\n lines.push(\"\");\n lines.push(\"### Coverage\");\n lines.push(\"| Metric | Value |\");\n lines.push(\"|--------|-------|\");\n lines.push(`| Element Coverage | ${quality.elementCoverage.toFixed(0)}% |`);\n lines.push(`| Relationship Coverage | ${quality.relationshipCoverage.toFixed(0)}% |`);\n lines.push(`| Documentation Coverage | ${quality.documentationCoverage.toFixed(0)}% |`);\n lines.push(`| Layer Coverage | ${quality.layerCoverage.toFixed(0)}% |`);\n lines.push(\"\");\n\n lines.push(\"### Compliance\");\n lines.push(\"| Metric | Score |\");\n lines.push(\"|--------|-------|\");\n lines.push(`| ArchiMate Compliance | ${quality.archimateCompliance.toFixed(0)}% |`);\n lines.push(`| Spec Compliance | ${quality.specCompliance.toFixed(0)}% |`);\n lines.push(`| Semantic Consistency | ${quality.semanticConsistency.toFixed(0)}% |`);\n lines.push(\"\");\n\n lines.push(\"### Issues\");\n lines.push(`- Orphaned Elements: ${quality.orphanedElements}`);\n lines.push(`- Circular Dependencies: ${quality.circularDependencies}`);\n lines.push(\"\");\n}\n\n/**\n * Format statistics section for markdown\n */\nfunction formatStatisticsMarkdown(lines: string[], report: ReportData): void {\n const stats = report.statistics;\n\n lines.push(\"## Statistics\");\n lines.push(\"\");\n lines.push(\"### Overview\");\n lines.push(\"| Metric | Value |\");\n lines.push(\"|--------|-------|\");\n lines.push(`| Total Elements | ${stats.statistics.totalElements} |`);\n lines.push(`| Total Relationships | ${stats.statistics.totalRelationships} |`);\n lines.push(`| Populated Layers | ${stats.statistics.populatedLayers}/${stats.statistics.totalLayers} |`);\n lines.push(\"\");\n\n lines.push(\"### Elements by Layer\");\n lines.push(\"| Layer | Count | Types |\");\n lines.push(\"|-------|-------|-------|\");\n for (const layer of stats.layers) {\n if (layer.totalElements > 0) {\n const types = Object.keys(layer.elementsByType).join(\", \");\n lines.push(`| ${layer.name} | ${layer.totalElements} | ${types} |`);\n }\n }\n lines.push(\"\");\n}\n\n/**\n * Format relationships section for markdown\n */\nfunction formatRelationshipsMarkdown(lines: string[], report: ReportData): void {\n const relationships = report.relationships;\n\n lines.push(\"## Relationships\");\n lines.push(\"\");\n lines.push(\"### Overview\");\n lines.push(\"| Type | Count |\");\n lines.push(\"|------|-------|\");\n lines.push(`| Total | ${relationships.totalRelationships} |`);\n lines.push(`| Cross-Layer | ${relationships.crossLayerCount} |`);\n lines.push(`| Intra-Layer | ${relationships.intraLayerCount} |`);\n lines.push(\"\");\n\n lines.push(\"### By Category\");\n lines.push(\"| Category | Count | Percentage |\");\n lines.push(\"|----------|-------|-----------|\");\n for (const [category, count] of Object.entries(relationships.byCategory)\n .sort(([, a], [, b]) => b - a)) {\n const percentage = ((count / relationships.totalRelationships) * 100).toFixed(1);\n lines.push(`| ${category} | ${count} | ${percentage}% |`);\n }\n lines.push(\"\");\n\n if (relationships.circularDependencies.length > 0) {\n lines.push(\"### Circular Dependencies\");\n for (const circular of relationships.circularDependencies) {\n lines.push(`- ${circular.elements.join(\" \u2192 \")} \u2192 ${circular.elements[0]}`);\n }\n lines.push(\"\");\n }\n}\n\n/**\n * Format data model section for markdown\n */\nfunction formatDataModelMarkdown(lines: string[], report: ReportData): void {\n const dataModel = report.dataModel;\n\n lines.push(\"## Data Model (Layer 7)\");\n lines.push(\"\");\n lines.push(\"### Overview\");\n lines.push(\"| Metric | Value |\");\n lines.push(\"|--------|-------|\");\n lines.push(`| Total Entities | ${dataModel.entityCount} |`);\n lines.push(`| Total Attributes | ${dataModel.attributeCount} |`);\n lines.push(`| Entity Relationships | ${dataModel.relationshipCount} |`);\n lines.push(`| Referenced Entities | ${dataModel.referencedEntities} |`);\n lines.push(\"\");\n\n if (dataModel.orphanedEntities.length > 0) {\n lines.push(\"### Orphaned Entities\");\n for (const entity of dataModel.orphanedEntities) {\n lines.push(`- ${entity}`);\n }\n lines.push(\"\");\n }\n}\n\n/**\n * Create quality progress bar\n */\nfunction qualityBar(percentage: number): string {\n const width = 20;\n const filled = Math.round((percentage / 100) * width);\n const empty = width - filled;\n\n const bar = \"\u2588\".repeat(filled) + \"\u2591\".repeat(empty);\n\n if (percentage >= 80) return ansis.green(bar);\n if (percentage >= 60) return ansis.yellow(bar);\n return ansis.red(bar);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import ansis from "ansis";
|
|
2
|
+
import { getLayerById } from "../generated/layer-registry.js";
|
|
3
|
+
function formatStats(stats, options) {
|
|
4
|
+
switch (options.format) {
|
|
5
|
+
case "json":
|
|
6
|
+
return formatJSON(stats);
|
|
7
|
+
case "markdown":
|
|
8
|
+
return formatMarkdown(stats);
|
|
9
|
+
case "compact":
|
|
10
|
+
return formatCompact(stats);
|
|
11
|
+
case "text":
|
|
12
|
+
default:
|
|
13
|
+
return formatText(stats, options.verbose);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function formatText(stats, verbose) {
|
|
17
|
+
const lines = [];
|
|
18
|
+
lines.push(""), lines.push(ansis.bold(`${ansis.cyan(stats.project.name)}`)), lines.push(ansis.dim("=".repeat(80))), lines.push(""), lines.push(ansis.bold("Overview:")), lines.push(` ${ansis.gray("Version:")} ${stats.project.version}`), lines.push(` ${ansis.gray("Created:")} ${formatDate(stats.project.created)}`), lines.push(` ${ansis.gray("Updated:")} ${formatDate(stats.project.updated)}`);
|
|
19
|
+
const statusIcon = stats.validation.isValid ? ansis.green("\u2713") : ansis.red("\u2717"), statusText = stats.validation.isValid ? "Valid" : "Invalid";
|
|
20
|
+
lines.push(` ${ansis.gray("Status:")} ${statusIcon} ${statusText}`), stats.validation.errors > 0 && lines.push(` ${ansis.gray("Errors:")} ${ansis.red(stats.validation.errors)}`), stats.validation.warnings > 0 && lines.push(` ${ansis.gray("Warnings:")} ${ansis.yellow(stats.validation.warnings)}`), lines.push(""), lines.push(ansis.bold("Elements by Layer:"));
|
|
21
|
+
for (const layer of stats.layers) {
|
|
22
|
+
const layerNum = getLayerById(layer.name)?.number ?? 0, typeDetails = Object.entries(layer.elementsByType).map(([type, count]) => `${count} ${type}${count > 1 ? "s" : ""}`).join(", "), typeSummary = typeDetails ? ` (${typeDetails})` : "";
|
|
23
|
+
lines.push(` ${String(layerNum).padEnd(2)}. ${ansis.cyan(layer.name.padEnd(20))} ${String(layer.totalElements).padEnd(3)} elements${typeSummary}`);
|
|
24
|
+
}
|
|
25
|
+
if (lines.push(""), lines.push(ansis.bold(`Total: ${ansis.cyan(`${stats.statistics.totalElements} elements`)} across ${ansis.cyan(`${stats.statistics.totalLayers} layers`)}`)), stats.statistics.totalRelationships > 0) {
|
|
26
|
+
lines.push(""), lines.push(ansis.bold("Cross-Layer Relationships:"));
|
|
27
|
+
const byPair = stats.relationships.byPair, sortedPairs = Object.entries(byPair).sort(([, a], [, b]) => b - a).slice(0, 10);
|
|
28
|
+
for (const [pair, count] of sortedPairs)
|
|
29
|
+
lines.push(` ${pair.padEnd(20)} ${String(count).padEnd(3)} relationships`);
|
|
30
|
+
lines.push(""), lines.push(ansis.bold(`Total Relationships: ${ansis.cyan(stats.statistics.totalRelationships)}`)), lines.push(` ${ansis.gray("Cross-layer:")} ${stats.relationships.crossLayerCount}`), lines.push(` ${ansis.gray("Intra-layer:")} ${stats.relationships.intraLayerCount}`);
|
|
31
|
+
}
|
|
32
|
+
lines.push(""), lines.push(ansis.bold("Model Completeness:"));
|
|
33
|
+
const completenessBar = createCompletionBar(stats.completeness.overall);
|
|
34
|
+
lines.push(` ${completenessBar} ${stats.completeness.overall}%`), lines.push(""), lines.push(ansis.bold("Layer Coverage:"));
|
|
35
|
+
for (const layer of stats.layers) {
|
|
36
|
+
const icon = layer.coverage >= 75 ? ansis.green("\u2713") : layer.coverage >= 50 ? ansis.yellow("\u25D0") : ansis.red("\u2717");
|
|
37
|
+
lines.push(` ${icon} ${ansis.cyan(layer.name.padEnd(18))} ${String(layer.coverage).padEnd(3)}% (${layer.totalElements} elements)`);
|
|
38
|
+
}
|
|
39
|
+
if (verbose || stats.orphanedElements.length > 0) {
|
|
40
|
+
if (lines.push(""), lines.push(ansis.bold("Quality Metrics:")), stats.orphanedElements.length === 0)
|
|
41
|
+
lines.push(` ${ansis.green("\u2713")} No orphaned elements`);
|
|
42
|
+
else if (lines.push(` ${ansis.yellow("\u26A0")} ${stats.orphanedElements.length} orphaned element${stats.orphanedElements.length > 1 ? "s" : ""}`), verbose) {
|
|
43
|
+
for (const orphan of stats.orphanedElements.slice(0, 5))
|
|
44
|
+
lines.push(` - ${orphan}`);
|
|
45
|
+
stats.orphanedElements.length > 5 && lines.push(` ... and ${stats.orphanedElements.length - 5} more`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return lines.push(""), lines.join(`
|
|
49
|
+
`);
|
|
50
|
+
}
|
|
51
|
+
function formatJSON(stats) {
|
|
52
|
+
return JSON.stringify(stats, null, 2) + `
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
function formatMarkdown(stats) {
|
|
56
|
+
const lines = [];
|
|
57
|
+
lines.push(`# ${stats.project.name} - Architecture Statistics`), lines.push(""), lines.push("## Overview"), lines.push(""), lines.push("| Metric | Value |"), lines.push("|--------|-------|"), lines.push(`| Version | ${stats.project.version} |`), lines.push(`| Created | ${formatDate(stats.project.created)} |`), lines.push(`| Updated | ${formatDate(stats.project.updated)} |`), lines.push(`| Status | ${stats.validation.isValid ? "\u2713 Valid" : "\u2717 Invalid"} |`), lines.push(`| Total Elements | ${stats.statistics.totalElements} |`), lines.push(`| Total Relationships | ${stats.statistics.totalRelationships} |`), lines.push(`| Completeness | ${stats.completeness.overall}% |`), lines.push(""), lines.push("## Elements by Layer"), lines.push(""), lines.push("| Layer | Elements | Types |"), lines.push("|-------|----------|-------|");
|
|
58
|
+
for (const layer of stats.layers) {
|
|
59
|
+
const typeList = Object.entries(layer.elementsByType).map(([type, count]) => `${type}: ${count}`).join(", ");
|
|
60
|
+
lines.push(`| ${layer.name} | ${layer.totalElements} | ${typeList} |`);
|
|
61
|
+
}
|
|
62
|
+
if (lines.push(""), stats.statistics.totalRelationships > 0) {
|
|
63
|
+
lines.push("## Relationships"), lines.push(""), lines.push("| Type | Count |"), lines.push("|------|-------|"), lines.push(`| Total | ${stats.statistics.totalRelationships} |`), lines.push(`| Cross-layer | ${stats.relationships.crossLayerCount} |`), lines.push(`| Intra-layer | ${stats.relationships.intraLayerCount} |`), lines.push(""), lines.push("### By Predicate"), lines.push(""), lines.push("| Predicate | Count |"), lines.push("|-----------|-------|");
|
|
64
|
+
for (const [predicate, count] of Object.entries(stats.relationships.byPredicate))
|
|
65
|
+
lines.push(`| ${predicate} | ${count} |`);
|
|
66
|
+
lines.push("");
|
|
67
|
+
}
|
|
68
|
+
lines.push("## Completeness"), lines.push(""), lines.push(`Overall: **${stats.completeness.overall}%**`), lines.push(""), lines.push("### By Layer"), lines.push(""), lines.push("| Layer | Coverage |"), lines.push("|-------|----------|");
|
|
69
|
+
for (const [layer, coverage] of Object.entries(stats.completeness.byLayer))
|
|
70
|
+
lines.push(`| ${layer} | ${coverage}% |`);
|
|
71
|
+
return lines.push(""), lines.push("## Quality"), lines.push(""), stats.orphanedElements.length === 0 ? lines.push("- \u2713 No orphaned elements") : lines.push(`- \u26A0 ${stats.orphanedElements.length} orphaned element${stats.orphanedElements.length > 1 ? "s" : ""}`), lines.push(""), lines.join(`
|
|
72
|
+
`);
|
|
73
|
+
}
|
|
74
|
+
function formatCompact(stats) {
|
|
75
|
+
const statusIcon = stats.validation.isValid ? "\u2713" : "\u2717";
|
|
76
|
+
return `${stats.project.name}: ${stats.statistics.totalElements} elements, ${stats.statistics.totalRelationships} relationships, ${stats.statistics.totalLayers} layers | Status: ${statusIcon} ${stats.validation.isValid ? "Valid" : "Invalid"} | Completeness: ${stats.completeness.overall}% | Updated: ${formatDate(stats.project.updated)}`;
|
|
77
|
+
}
|
|
78
|
+
function createCompletionBar(percentage, width = 40) {
|
|
79
|
+
const filled = Math.round(percentage / 100 * width), empty = width - filled, bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
80
|
+
return percentage >= 75 ? ansis.green(bar) : percentage >= 50 ? ansis.yellow(bar) : ansis.red(bar);
|
|
81
|
+
}
|
|
82
|
+
function formatDate(dateString) {
|
|
83
|
+
try {
|
|
84
|
+
return new Date(dateString).toLocaleDateString("en-US", {
|
|
85
|
+
year: "numeric",
|
|
86
|
+
month: "short",
|
|
87
|
+
day: "numeric",
|
|
88
|
+
hour: "2-digit",
|
|
89
|
+
minute: "2-digit"
|
|
90
|
+
});
|
|
91
|
+
} catch {
|
|
92
|
+
return dateString;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
formatStats
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=stats-formatters.js.map
|