@facet-coverage/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +422 -0
  3. package/bin/facet-coverage.js +3 -0
  4. package/dist/cli/commands/analyze.d.ts +13 -0
  5. package/dist/cli/commands/analyze.d.ts.map +1 -0
  6. package/dist/cli/commands/analyze.js +161 -0
  7. package/dist/cli/commands/analyze.js.map +1 -0
  8. package/dist/cli/commands/generate.d.ts +10 -0
  9. package/dist/cli/commands/generate.d.ts.map +1 -0
  10. package/dist/cli/commands/generate.js +67 -0
  11. package/dist/cli/commands/generate.js.map +1 -0
  12. package/dist/cli/commands/validate.d.ts +11 -0
  13. package/dist/cli/commands/validate.d.ts.map +1 -0
  14. package/dist/cli/commands/validate.js +120 -0
  15. package/dist/cli/commands/validate.js.map +1 -0
  16. package/dist/cli/commands/watch.d.ts +10 -0
  17. package/dist/cli/commands/watch.d.ts.map +1 -0
  18. package/dist/cli/commands/watch.js +151 -0
  19. package/dist/cli/commands/watch.js.map +1 -0
  20. package/dist/cli/index.d.ts +2 -0
  21. package/dist/cli/index.d.ts.map +1 -0
  22. package/dist/cli/index.js +47 -0
  23. package/dist/cli/index.js.map +1 -0
  24. package/dist/core/CoverageCalculator.d.ts +34 -0
  25. package/dist/core/CoverageCalculator.d.ts.map +1 -0
  26. package/dist/core/CoverageCalculator.js +167 -0
  27. package/dist/core/CoverageCalculator.js.map +1 -0
  28. package/dist/core/FacetParser.d.ts +39 -0
  29. package/dist/core/FacetParser.d.ts.map +1 -0
  30. package/dist/core/FacetParser.js +114 -0
  31. package/dist/core/FacetParser.js.map +1 -0
  32. package/dist/core/StructureReader.d.ts +37 -0
  33. package/dist/core/StructureReader.d.ts.map +1 -0
  34. package/dist/core/StructureReader.js +126 -0
  35. package/dist/core/StructureReader.js.map +1 -0
  36. package/dist/core/TestScanner.d.ts +36 -0
  37. package/dist/core/TestScanner.d.ts.map +1 -0
  38. package/dist/core/TestScanner.js +192 -0
  39. package/dist/core/TestScanner.js.map +1 -0
  40. package/dist/core/Validator.d.ts +33 -0
  41. package/dist/core/Validator.d.ts.map +1 -0
  42. package/dist/core/Validator.js +183 -0
  43. package/dist/core/Validator.js.map +1 -0
  44. package/dist/core/index.d.ts +6 -0
  45. package/dist/core/index.d.ts.map +1 -0
  46. package/dist/core/index.js +14 -0
  47. package/dist/core/index.js.map +1 -0
  48. package/dist/index.d.ts +6 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +23 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/integrations/playwright.d.ts +95 -0
  53. package/dist/integrations/playwright.d.ts.map +1 -0
  54. package/dist/integrations/playwright.js +168 -0
  55. package/dist/integrations/playwright.js.map +1 -0
  56. package/dist/reporters/HtmlReporter.d.ts +53 -0
  57. package/dist/reporters/HtmlReporter.d.ts.map +1 -0
  58. package/dist/reporters/HtmlReporter.js +484 -0
  59. package/dist/reporters/HtmlReporter.js.map +1 -0
  60. package/dist/reporters/JsonReporter.d.ts +21 -0
  61. package/dist/reporters/JsonReporter.d.ts.map +1 -0
  62. package/dist/reporters/JsonReporter.js +58 -0
  63. package/dist/reporters/JsonReporter.js.map +1 -0
  64. package/dist/reporters/MarkdownReporter.d.ts +25 -0
  65. package/dist/reporters/MarkdownReporter.d.ts.map +1 -0
  66. package/dist/reporters/MarkdownReporter.js +141 -0
  67. package/dist/reporters/MarkdownReporter.js.map +1 -0
  68. package/dist/reporters/index.d.ts +4 -0
  69. package/dist/reporters/index.d.ts.map +1 -0
  70. package/dist/reporters/index.js +10 -0
  71. package/dist/reporters/index.js.map +1 -0
  72. package/dist/types.d.ts +205 -0
  73. package/dist/types.d.ts.map +1 -0
  74. package/dist/types.js +28 -0
  75. package/dist/types.js.map +1 -0
  76. package/package.json +88 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,422 @@
1
+ # Facet Coverage
2
+
3
+ > **Test every facet of your features**
4
+ > Natural specifications. Multiple perspectives. Rigorous coverage.
5
+
6
+ ## What is Facet?
7
+
8
+ Facet is a modern testing framework that lets you document features from multiple stakeholder perspectives while maintaining exact traceability to your tests.
9
+
10
+ **One feature. Many facets.**
11
+ - Business requirements
12
+ - Compliance mandates
13
+ - UX standards
14
+ - Technical specs
15
+
16
+ All connected to the same tests. All tracked for coverage.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ bun add -d @facet-coverage/core
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### 1. Create Your First Facets
27
+
28
+ ```bash
29
+ mkdir -p features/checkout/facets
30
+ ```
31
+
32
+ Write in natural language:
33
+
34
+ **features/checkout/facets/business.md**
35
+ ```markdown
36
+ ## Guest Purchase Flow
37
+
38
+ A user who isn't logged in should be able to buy products. They add
39
+ items to cart, click checkout, provide email and payment details,
40
+ and get an order confirmation.
41
+
42
+ ### Edge Cases
43
+ - Empty cart at checkout
44
+ - Invalid email format
45
+ - Payment gateway timeout
46
+ ```
47
+
48
+ **features/checkout/facets/compliance.md**
49
+ ```markdown
50
+ ## PCI-DSS Payment Requirements
51
+
52
+ We handle credit card data, so PCI-DSS compliance is mandatory:
53
+
54
+ 1. **Encryption in transit** - TLS 1.2+ required
55
+ 2. **No CVV storage** - Use payment gateway, never store CVV
56
+ 3. **Card masking** - Display only last 4 digits
57
+ ```
58
+
59
+ ### 2. Generate Structure
60
+
61
+ ```bash
62
+ bunx facet generate features/checkout/facets/
63
+ ```
64
+
65
+ This creates `features/checkout/.facet/structure.json`:
66
+
67
+ ```json
68
+ {
69
+ "feature": "checkout",
70
+ "facets": [
71
+ {
72
+ "id": "business:guest-purchase-flow",
73
+ "source": {
74
+ "file": "facets/business.md",
75
+ "section": "guest-purchase-flow"
76
+ },
77
+ "type": "business"
78
+ },
79
+ {
80
+ "id": "compliance:pci-dss-payment-requirements",
81
+ "source": {
82
+ "file": "facets/compliance.md",
83
+ "section": "pci-dss-payment-requirements"
84
+ },
85
+ "type": "compliance"
86
+ }
87
+ ]
88
+ }
89
+ ```
90
+
91
+ ### 3. Link Tests
92
+
93
+ ```typescript
94
+ // features/checkout/tests/checkout.spec.ts
95
+ import { test, expect } from '@playwright/test';
96
+ import { facet } from '@facet-coverage/core/playwright';
97
+
98
+ test('guest user completes purchase', {
99
+ annotation: facet(
100
+ 'business:guest-purchase-flow',
101
+ 'compliance:pci-dss-payment-requirements'
102
+ )
103
+ }, async ({ page }) => {
104
+ await page.goto('/checkout');
105
+ // ... test code
106
+
107
+ // Verify compliance: card masking
108
+ const maskedCard = page.locator('.card-last-four');
109
+ await expect(maskedCard).toHaveText('•••• 4242');
110
+ });
111
+ ```
112
+
113
+ ### 4. Run Coverage
114
+
115
+ ```bash
116
+ bunx facet analyze
117
+ ```
118
+
119
+ **Output:**
120
+ ```
121
+ šŸ’Ž Facet Coverage Report
122
+
123
+ Overall: 100%
124
+
125
+ By Type:
126
+ āœ… business: 100% (1/1)
127
+ āœ… compliance: 100% (1/1)
128
+
129
+ Reports generated:
130
+ šŸ“„ .facet-coverage/coverage.json
131
+ šŸ“„ .facet-coverage/coverage.html
132
+ šŸ“„ .facet-coverage/coverage.md
133
+ ```
134
+
135
+ ## Project Structure
136
+
137
+ ```
138
+ project/
139
+ ā”œā”€ā”€ features/
140
+ │ ā”œā”€ā”€ checkout/
141
+ │ │ ā”œā”€ā”€ facets/
142
+ │ │ │ ā”œā”€ā”€ business.md # Product owner writes
143
+ │ │ │ ā”œā”€ā”€ compliance.md # Compliance team writes
144
+ │ │ │ └── ux.md # UX designer writes
145
+ │ │ ā”œā”€ā”€ .facet/
146
+ │ │ │ └── structure.json # Generated or manual
147
+ │ │ └── tests/
148
+ │ │ └── checkout.spec.ts
149
+ │ │
150
+ │ └── authentication/
151
+ │ ā”œā”€ā”€ facets/
152
+ │ ā”œā”€ā”€ .facet/
153
+ │ └── tests/
154
+ │
155
+ ā”œā”€ā”€ .facet-coverage/ # Coverage reports
156
+ │ ā”œā”€ā”€ coverage.json
157
+ │ ā”œā”€ā”€ coverage.html
158
+ │ └── coverage.md
159
+ │
160
+ └── facet.config.js # Configuration
161
+ ```
162
+
163
+ ## CLI Commands
164
+
165
+ ### Generate Structure
166
+
167
+ ```bash
168
+ # Generate structure from facet documents
169
+ bunx facet generate <facets-dir>
170
+
171
+ # Options
172
+ bunx facet generate features/checkout/facets/ -o ./custom-output
173
+ bunx facet generate features/checkout/facets/ -t business
174
+ ```
175
+
176
+ ### Analyze Coverage
177
+
178
+ ```bash
179
+ # Run coverage analysis
180
+ bunx facet analyze
181
+
182
+ # Options
183
+ bunx facet analyze -c facet.config.js # Custom config
184
+ bunx facet analyze -f html # Specific format
185
+ bunx facet analyze -t 80 # Set threshold
186
+ bunx facet analyze --json # JSON output for CI
187
+ bunx facet analyze --silent # No console output
188
+ ```
189
+
190
+ ### Validate
191
+
192
+ ```bash
193
+ # Validate structure and test links
194
+ bunx facet validate
195
+
196
+ # Options
197
+ bunx facet validate --strict # Require all tests linked
198
+ bunx facet validate --json # JSON output
199
+ ```
200
+
201
+ ### Watch Mode
202
+
203
+ ```bash
204
+ # Re-run on changes
205
+ bunx facet watch
206
+
207
+ # Options
208
+ bunx facet watch -v # Validate before analysis
209
+ ```
210
+
211
+ ## Playwright Integration
212
+
213
+ ### Reporter Setup
214
+
215
+ ```typescript
216
+ // playwright.config.ts
217
+ import { FacetCoverageReporter } from '@facet-coverage/core/playwright';
218
+
219
+ export default {
220
+ reporter: [
221
+ ['html'],
222
+ [FacetCoverageReporter, {
223
+ output: {
224
+ dir: '.facet-coverage',
225
+ formats: ['json', 'html', 'markdown']
226
+ },
227
+ thresholds: {
228
+ global: 80,
229
+ byType: {
230
+ compliance: 100
231
+ }
232
+ }
233
+ }]
234
+ ]
235
+ };
236
+ ```
237
+
238
+ ### Test Annotations
239
+
240
+ ```typescript
241
+ import { test } from '@playwright/test';
242
+ import { facet } from '@facet-coverage/core/playwright';
243
+
244
+ // Single facet
245
+ test('my test', {
246
+ annotation: facet('guest-checkout-flow')
247
+ }, async ({ page }) => {
248
+ // ...
249
+ });
250
+
251
+ // Multiple facets
252
+ test('comprehensive test', {
253
+ annotation: facet(
254
+ 'guest-checkout-flow',
255
+ 'pci-card-masking',
256
+ 'mobile-checkout-ux'
257
+ )
258
+ }, async ({ page }) => {
259
+ // ...
260
+ });
261
+ ```
262
+
263
+ ## Configuration
264
+
265
+ **facet.config.js:**
266
+
267
+ ```javascript
268
+ export default {
269
+ // Where structure files live
270
+ structureFiles: [
271
+ 'features/**/.facet/structure.json'
272
+ ],
273
+
274
+ // Where tests live
275
+ testDir: './features/**/tests',
276
+ testPatterns: ['**/*.spec.ts', '**/*.test.ts'],
277
+
278
+ // Validation options
279
+ validation: {
280
+ requireSourceExists: true,
281
+ requireSectionExists: true,
282
+ requireAllTestsLinked: false
283
+ },
284
+
285
+ // Output options
286
+ output: {
287
+ dir: '.facet-coverage',
288
+ formats: ['json', 'html', 'markdown']
289
+ },
290
+
291
+ // Coverage thresholds
292
+ thresholds: {
293
+ global: 75,
294
+ byType: {
295
+ compliance: 100,
296
+ business: 80,
297
+ ux: 70
298
+ }
299
+ }
300
+ };
301
+ ```
302
+
303
+ ## ID Patterns
304
+
305
+ ### Auto-Generated (Recommended)
306
+
307
+ ```
308
+ Pattern: {filename}:{section-slug}
309
+
310
+ Examples:
311
+ - business:guest-purchase-flow
312
+ - compliance:pci-dss-payment-requirements
313
+ - ux:mobile-checkout-experience
314
+ ```
315
+
316
+ ### Custom Slugs
317
+
318
+ ```json
319
+ {
320
+ "id": "guest-checkout-flow",
321
+ "source": {
322
+ "file": "facets/business.md",
323
+ "section": "guest-purchase-flow"
324
+ },
325
+ "type": "business"
326
+ }
327
+ ```
328
+
329
+ ### Flexible Linking
330
+
331
+ ```typescript
332
+ // All three formats work:
333
+ facet('guest-checkout-flow') // Custom slug
334
+ facet('business:guest-purchase-flow') // Auto-generated
335
+ facet('facets/business.md#guest-purchase-flow') // Direct path
336
+ ```
337
+
338
+ ## Programmatic API
339
+
340
+ ```typescript
341
+ import {
342
+ StructureReader,
343
+ TestScanner,
344
+ CoverageCalculator,
345
+ Validator,
346
+ JsonReporter,
347
+ HtmlReporter,
348
+ MarkdownReporter
349
+ } from '@facet-coverage/core';
350
+
351
+ // Read structures
352
+ const reader = new StructureReader();
353
+ const structures = await reader.readAllStructures();
354
+
355
+ // Scan tests
356
+ const scanner = new TestScanner();
357
+ const tests = await scanner.scanAllTests();
358
+
359
+ // Calculate coverage
360
+ const calculator = new CoverageCalculator();
361
+ const report = await calculator.calculateCoverage();
362
+
363
+ // Validate
364
+ const validator = new Validator();
365
+ const result = await validator.validate();
366
+
367
+ // Generate reports
368
+ const jsonReporter = new JsonReporter();
369
+ jsonReporter.write(report);
370
+
371
+ const htmlReporter = new HtmlReporter();
372
+ htmlReporter.write(report);
373
+
374
+ const mdReporter = new MarkdownReporter();
375
+ mdReporter.write(report);
376
+ ```
377
+
378
+ ## Benefits
379
+
380
+ ### For Product Owners
381
+ - Write in natural language
382
+ - Focus on business value
383
+ - See what's tested immediately
384
+ - Documentation evolves with product
385
+
386
+ ### For Compliance Teams
387
+ - Direct regulation mapping
388
+ - Audit-ready traceability
389
+ - 100% coverage enforcement
390
+ - Automated compliance reports
391
+
392
+ ### For UX Designers
393
+ - Document user flows naturally
394
+ - Link designs to tests
395
+ - Track accessibility coverage
396
+ - Mobile/desktop requirements clear
397
+
398
+ ### For Developers
399
+ - One test covers multiple facets
400
+ - Clear requirements from all stakeholders
401
+ - Know exactly what's covered
402
+ - Easy maintenance
403
+
404
+ ### For QA Teams
405
+ - Complete visibility
406
+ - Automated gap detection
407
+ - Multi-perspective coverage
408
+ - Progress tracking
409
+
410
+ ## Key Principles
411
+
412
+ 1. **Multi-Perspective**: Every feature has multiple facets
413
+ 2. **Natural Language**: Write like humans, not machines
414
+ 3. **Evolutionary**: Documentation grows with understanding
415
+ 4. **Traceable**: Exact test-to-facet mapping
416
+ 5. **Feature-Modular**: Self-contained, team-owned
417
+ 6. **Lightweight**: Markdown + JSON, nothing heavy
418
+ 7. **Flexible**: Adopt incrementally, customize freely
419
+
420
+ ## License
421
+
422
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import('../dist/cli/index.js');
@@ -0,0 +1,13 @@
1
+ interface AnalyzeOptions {
2
+ config?: string;
3
+ format?: string;
4
+ threshold?: string;
5
+ json?: boolean;
6
+ silent?: boolean;
7
+ }
8
+ /**
9
+ * Analyze facet coverage
10
+ */
11
+ export declare function analyzeCommand(options?: AnalyzeOptions): Promise<void>;
12
+ export {};
13
+ //# sourceMappingURL=analyze.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/analyze.ts"],"names":[],"mappings":"AASA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwEhF"}
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.analyzeCommand = analyzeCommand;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const CoverageCalculator_js_1 = require("../../core/CoverageCalculator.js");
7
+ const JsonReporter_js_1 = require("../../reporters/JsonReporter.js");
8
+ const HtmlReporter_js_1 = require("../../reporters/HtmlReporter.js");
9
+ const MarkdownReporter_js_1 = require("../../reporters/MarkdownReporter.js");
10
+ const types_js_1 = require("../../types.js");
11
+ /**
12
+ * Analyze facet coverage
13
+ */
14
+ async function analyzeCommand(options = {}) {
15
+ const cwd = process.cwd();
16
+ // Load config
17
+ const config = await loadConfig(options.config, cwd);
18
+ // Override with CLI options
19
+ if (options.threshold) {
20
+ config.thresholds.global = parseInt(options.threshold, 10);
21
+ }
22
+ if (!options.silent) {
23
+ console.log('šŸ’Ž Analyzing Facet Coverage...\n');
24
+ }
25
+ // Calculate coverage
26
+ const calculator = new CoverageCalculator_js_1.CoverageCalculator(config);
27
+ const report = await calculator.calculateCoverage(cwd);
28
+ // Check if any facets were found
29
+ if (report.summary.totalFacets === 0) {
30
+ if (!options.silent) {
31
+ console.log('āš ļø No facets found. Make sure you have:');
32
+ console.log(' 1. Structure files matching: ' + config.structureFiles.join(', '));
33
+ console.log(' 2. Test files in: ' + config.testDir);
34
+ }
35
+ process.exit(0);
36
+ }
37
+ // Generate reports
38
+ const formats = options.format
39
+ ? [options.format]
40
+ : config.output.formats;
41
+ const outputPaths = [];
42
+ if (formats.includes('json')) {
43
+ const reporter = new JsonReporter_js_1.JsonReporter(config);
44
+ outputPaths.push(reporter.write(report, cwd));
45
+ }
46
+ if (formats.includes('html')) {
47
+ const reporter = new HtmlReporter_js_1.HtmlReporter(config);
48
+ outputPaths.push(reporter.write(report, cwd));
49
+ }
50
+ if (formats.includes('markdown')) {
51
+ const reporter = new MarkdownReporter_js_1.MarkdownReporter(config);
52
+ outputPaths.push(reporter.write(report, cwd));
53
+ }
54
+ // Output results
55
+ if (options.json) {
56
+ // JSON output mode for CI
57
+ const jsonReporter = new JsonReporter_js_1.JsonReporter(config);
58
+ console.log(jsonReporter.generateSummary(report));
59
+ }
60
+ else if (!options.silent) {
61
+ printReport(report, config, outputPaths);
62
+ }
63
+ // Check thresholds
64
+ const thresholdResult = calculator.checkThresholds(report);
65
+ if (!thresholdResult.passed) {
66
+ if (!options.silent) {
67
+ console.log('\nāŒ Coverage thresholds not met:');
68
+ for (const failure of thresholdResult.failures) {
69
+ console.log(` - ${failure}`);
70
+ }
71
+ }
72
+ process.exit(1);
73
+ }
74
+ }
75
+ /**
76
+ * Load configuration from file or use defaults
77
+ */
78
+ async function loadConfig(configPath, cwd) {
79
+ const configFiles = [
80
+ configPath,
81
+ 'facet.config.js',
82
+ 'facet.config.mjs',
83
+ 'facet.config.json',
84
+ ].filter(Boolean);
85
+ for (const file of configFiles) {
86
+ const fullPath = (0, path_1.resolve)(cwd, file);
87
+ if ((0, fs_1.existsSync)(fullPath)) {
88
+ if (file.endsWith('.json')) {
89
+ const content = (0, fs_1.readFileSync)(fullPath, 'utf-8');
90
+ return { ...types_js_1.defaultConfig, ...JSON.parse(content) };
91
+ }
92
+ else {
93
+ // Dynamic import for JS config
94
+ try {
95
+ const imported = await import(fullPath);
96
+ return { ...types_js_1.defaultConfig, ...(imported.default || imported) };
97
+ }
98
+ catch (error) {
99
+ console.warn(`Warning: Could not load config from ${file}`);
100
+ }
101
+ }
102
+ }
103
+ }
104
+ return types_js_1.defaultConfig;
105
+ }
106
+ /**
107
+ * Print coverage report to console
108
+ */
109
+ function printReport(report, config, outputPaths) {
110
+ const { summary, byType, features, uncovered } = report;
111
+ // Overall summary
112
+ const overallIcon = summary.percentage >= 80 ? 'āœ…' : summary.percentage >= 50 ? '🟔' : 'āŒ';
113
+ console.log(`${overallIcon} Overall Coverage: ${summary.percentage}%\n`);
114
+ console.log('ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”');
115
+ console.log(`│ Total Facets: ${String(summary.totalFacets).padStart(6)} │`);
116
+ console.log(`│ Covered: ${String(summary.coveredFacets).padStart(6)} │`);
117
+ console.log(`│ Uncovered: ${String(summary.uncoveredFacets).padStart(6)} │`);
118
+ console.log('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜');
119
+ // By type
120
+ if (byType.length > 0) {
121
+ console.log('\nBy Type:');
122
+ for (const type of byType) {
123
+ const icon = type.percentage === 100 ? 'āœ…' : type.percentage >= 75 ? '🟔' : 'āŒ';
124
+ const bar = createProgressBar(type.percentage);
125
+ console.log(` ${icon} ${type.type.padEnd(15)} ${bar} ${type.percentage}% (${type.covered}/${type.total})`);
126
+ }
127
+ }
128
+ // Features
129
+ if (features.length > 0) {
130
+ console.log('\nFeatures:');
131
+ for (const feature of features) {
132
+ const icon = feature.percentage === 100 ? 'āœ…' : feature.percentage >= 75 ? '🟔' : 'āŒ';
133
+ console.log(` ${icon} ${feature.feature}: ${feature.percentage}% (${feature.coveredFacets}/${feature.totalFacets})`);
134
+ }
135
+ }
136
+ // Uncovered facets
137
+ if (uncovered.length > 0) {
138
+ console.log(`\nāŒ Uncovered Facets (${uncovered.length}):`);
139
+ const maxDisplay = 10;
140
+ for (const facet of uncovered.slice(0, maxDisplay)) {
141
+ console.log(` - ${facet.id} (${facet.type})`);
142
+ }
143
+ if (uncovered.length > maxDisplay) {
144
+ console.log(` ... and ${uncovered.length - maxDisplay} more`);
145
+ }
146
+ }
147
+ // Output paths
148
+ console.log('\nReports generated:');
149
+ for (const path of outputPaths) {
150
+ console.log(` šŸ“„ ${path}`);
151
+ }
152
+ }
153
+ /**
154
+ * Create a simple progress bar
155
+ */
156
+ function createProgressBar(percentage, width = 20) {
157
+ const filled = Math.round((percentage / 100) * width);
158
+ const empty = width - filled;
159
+ return `[${'ā–ˆ'.repeat(filled)}${'ā–‘'.repeat(empty)}]`;
160
+ }
161
+ //# sourceMappingURL=analyze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../../src/cli/commands/analyze.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ interface GenerateOptions {
2
+ output?: string;
3
+ type?: string;
4
+ }
5
+ /**
6
+ * Generate structure.json from facet markdown files
7
+ */
8
+ export declare function generateCommand(dir: string, options?: GenerateOptions): Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAKA,UAAU,eAAe;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyE/F"}