@empline/preflight 1.1.58 → 1.1.59

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 (32) hide show
  1. package/dist/checks/accessibility/accessibility-validation.d.ts.map +1 -1
  2. package/dist/checks/accessibility/accessibility-validation.js +131 -14
  3. package/dist/checks/accessibility/accessibility-validation.js.map +1 -1
  4. package/dist/checks/accessibility/wcag-advanced-validation.d.ts +10 -0
  5. package/dist/checks/accessibility/wcag-advanced-validation.d.ts.map +1 -0
  6. package/dist/checks/accessibility/wcag-advanced-validation.js +622 -0
  7. package/dist/checks/accessibility/wcag-advanced-validation.js.map +1 -0
  8. package/dist/checks/database/query-performance-validation.d.ts +10 -0
  9. package/dist/checks/database/query-performance-validation.d.ts.map +1 -0
  10. package/dist/checks/database/query-performance-validation.js +544 -0
  11. package/dist/checks/database/query-performance-validation.js.map +1 -0
  12. package/dist/checks/react/react-patterns-validation.d.ts +10 -0
  13. package/dist/checks/react/react-patterns-validation.d.ts.map +1 -0
  14. package/dist/checks/react/react-patterns-validation.js +559 -0
  15. package/dist/checks/react/react-patterns-validation.js.map +1 -0
  16. package/dist/checks/security/security-headers-validation.d.ts +10 -0
  17. package/dist/checks/security/security-headers-validation.d.ts.map +1 -0
  18. package/dist/checks/security/security-headers-validation.js +594 -0
  19. package/dist/checks/security/security-headers-validation.js.map +1 -0
  20. package/dist/reporters/github-reporter.d.ts +35 -0
  21. package/dist/reporters/github-reporter.d.ts.map +1 -0
  22. package/dist/reporters/github-reporter.js +397 -0
  23. package/dist/reporters/github-reporter.js.map +1 -0
  24. package/dist/reporters/html-report.d.ts +12 -0
  25. package/dist/reporters/html-report.d.ts.map +1 -0
  26. package/dist/reporters/html-report.js +469 -0
  27. package/dist/reporters/html-report.js.map +1 -0
  28. package/dist/reporters/index.d.ts +8 -0
  29. package/dist/reporters/index.d.ts.map +1 -0
  30. package/dist/reporters/index.js +18 -0
  31. package/dist/reporters/index.js.map +1 -0
  32. package/package.json +1 -1
@@ -0,0 +1,469 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.generateHtmlReport = generateHtmlReport;
38
+ exports.writeHtmlReport = writeHtmlReport;
39
+ /**
40
+ * HTML Report Generator
41
+ *
42
+ * Generates interactive HTML dashboard reports for preflight results:
43
+ *
44
+ * Features:
45
+ * - Summary dashboard with charts
46
+ * - Category breakdown
47
+ * - Severity filtering
48
+ * - Searchable findings
49
+ * - Expandable details
50
+ * - Export to JSON
51
+ * - Trend comparison (when baseline provided)
52
+ */
53
+ const fs = __importStar(require("node:fs"));
54
+ const path = __importStar(require("node:path"));
55
+ function escapeHtml(text) {
56
+ return text
57
+ .replace(/&/g, "&amp;")
58
+ .replace(/</g, "&lt;")
59
+ .replace(/>/g, "&gt;")
60
+ .replace(/"/g, "&quot;")
61
+ .replace(/'/g, "&#039;");
62
+ }
63
+ function generateSeverityBadge(severity) {
64
+ const colors = {
65
+ error: "bg-red-500",
66
+ warning: "bg-yellow-500",
67
+ info: "bg-blue-500",
68
+ };
69
+ const color = colors[severity] || "bg-gray-500";
70
+ return `<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${color} text-white">${severity}</span>`;
71
+ }
72
+ function generatePassFailBadge(passed) {
73
+ if (passed) {
74
+ return `<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-green-100 text-green-800">PASSED</span>`;
75
+ }
76
+ return `<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-red-100 text-red-800">FAILED</span>`;
77
+ }
78
+ function getRecordCategory(record) {
79
+ // Extract category from pathOrCmd if available
80
+ const match = record.pathOrCmd.match(/checks\/([^/]+)\//);
81
+ return match ? match[1] : record.group || "uncategorized";
82
+ }
83
+ function isRecordPassed(record) {
84
+ return record.kind === "passed";
85
+ }
86
+ function generateCategoryStats(records) {
87
+ const categoryMap = new Map();
88
+ for (const record of records) {
89
+ const category = getRecordCategory(record);
90
+ const current = categoryMap.get(category) || { passed: 0, failed: 0 };
91
+ if (isRecordPassed(record)) {
92
+ current.passed++;
93
+ }
94
+ else {
95
+ current.failed++;
96
+ }
97
+ categoryMap.set(category, current);
98
+ }
99
+ return Array.from(categoryMap.entries())
100
+ .map(([category, stats]) => ({
101
+ category,
102
+ passed: stats.passed,
103
+ failed: stats.failed,
104
+ total: stats.passed + stats.failed,
105
+ }))
106
+ .sort((a, b) => b.failed - a.failed);
107
+ }
108
+ function generateFindingsList(findings) {
109
+ if (!findings || findings.length === 0) {
110
+ return '<p class="text-gray-500 italic">No findings</p>';
111
+ }
112
+ return findings.map(f => `
113
+ <div class="border-l-4 ${f.level === 'error' ? 'border-red-500' : f.level === 'warning' ? 'border-yellow-500' : 'border-blue-500'} pl-4 py-2 mb-3">
114
+ <div class="flex items-center gap-2">
115
+ ${generateSeverityBadge(f.level || 'info')}
116
+ <span class="font-medium">${escapeHtml(f.message)}</span>
117
+ </div>
118
+ ${f.file ? `<p class="text-sm text-gray-600 mt-1">📄 ${escapeHtml(f.file)}${f.startLine ? `:${f.startLine}` : ''}</p>` : ''}
119
+ ${f.ruleId ? `<p class="text-sm text-gray-500 mt-1">Rule: ${escapeHtml(f.ruleId)}</p>` : ''}
120
+ ${f.suggestion ? `<p class="text-sm text-green-600 mt-1">💡 ${escapeHtml(f.suggestion)}</p>` : ''}
121
+ </div>
122
+ `).join('');
123
+ }
124
+ function generateHtmlReport(report, options = {}) {
125
+ const { title = "Preflight Report", baseline, } = options;
126
+ const totalChecks = report.records.length;
127
+ const passedChecks = report.summary.passed;
128
+ const failedChecks = report.summary.failed;
129
+ const passRate = totalChecks > 0 ? Math.round((passedChecks / totalChecks) * 100) : 0;
130
+ const overallPassed = failedChecks === 0;
131
+ const totalFindings = report.records.reduce((sum, r) => sum + (r.findings?.length || 0), 0);
132
+ const errorCount = report.records.reduce((sum, r) => sum + (r.findings?.filter(f => f.level === 'error').length || 0), 0);
133
+ const warningCount = report.records.reduce((sum, r) => sum + (r.findings?.filter(f => f.level === 'warning').length || 0), 0);
134
+ const categoryStats = generateCategoryStats(report.records);
135
+ // Calculate trends if baseline provided
136
+ let trendHtml = '';
137
+ if (baseline) {
138
+ const baselinePassRate = baseline.records.length > 0
139
+ ? Math.round((baseline.summary.passed / baseline.records.length) * 100)
140
+ : 0;
141
+ const passRateDiff = passRate - baselinePassRate;
142
+ const trendIcon = passRateDiff > 0 ? '📈' : passRateDiff < 0 ? '📉' : '➡️';
143
+ const trendColor = passRateDiff > 0 ? 'text-green-600' : passRateDiff < 0 ? 'text-red-600' : 'text-gray-600';
144
+ trendHtml = `
145
+ <div class="bg-white rounded-lg shadow p-6">
146
+ <h3 class="text-lg font-semibold mb-4">Trend vs Baseline</h3>
147
+ <div class="flex items-center gap-4">
148
+ <span class="text-3xl">${trendIcon}</span>
149
+ <div>
150
+ <p class="${trendColor} text-xl font-bold">${passRateDiff >= 0 ? '+' : ''}${passRateDiff}%</p>
151
+ <p class="text-gray-500 text-sm">Pass rate change</p>
152
+ </div>
153
+ </div>
154
+ </div>
155
+ `;
156
+ }
157
+ const html = `
158
+ <!DOCTYPE html>
159
+ <html lang="en">
160
+ <head>
161
+ <meta charset="UTF-8">
162
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
163
+ <title>${escapeHtml(title)}</title>
164
+ <script src="https://cdn.tailwindcss.com"></script>
165
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
166
+ <style>
167
+ .finding-details { display: none; }
168
+ .finding-details.open { display: block; }
169
+ .check-row:hover { background-color: #f9fafb; }
170
+ .filter-active { background-color: #3b82f6 !important; color: white !important; }
171
+ </style>
172
+ </head>
173
+ <body class="bg-gray-100 min-h-screen">
174
+ <nav class="bg-white shadow-sm border-b">
175
+ <div class="max-w-7xl mx-auto px-4 py-4">
176
+ <div class="flex justify-between items-center">
177
+ <h1 class="text-2xl font-bold text-gray-900">🛫 ${escapeHtml(title)}</h1>
178
+ <div class="flex items-center gap-4">
179
+ <span class="text-sm text-gray-500">Generated: ${new Date().toLocaleString()}</span>
180
+ <button onclick="exportJson()" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
181
+ Export JSON
182
+ </button>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ </nav>
187
+
188
+ <main class="max-w-7xl mx-auto px-4 py-8">
189
+ <!-- Summary Cards -->
190
+ <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
191
+ <div class="bg-white rounded-lg shadow p-6">
192
+ <div class="flex items-center justify-between">
193
+ <div>
194
+ <p class="text-gray-500 text-sm">Overall Status</p>
195
+ <div class="mt-2">${generatePassFailBadge(overallPassed)}</div>
196
+ </div>
197
+ <div class="text-5xl">${overallPassed ? '✅' : '❌'}</div>
198
+ </div>
199
+ </div>
200
+
201
+ <div class="bg-white rounded-lg shadow p-6">
202
+ <div class="flex items-center justify-between">
203
+ <div>
204
+ <p class="text-gray-500 text-sm">Pass Rate</p>
205
+ <p class="text-3xl font-bold ${passRate >= 80 ? 'text-green-600' : passRate >= 50 ? 'text-yellow-600' : 'text-red-600'}">${passRate}%</p>
206
+ </div>
207
+ <div class="text-4xl">📊</div>
208
+ </div>
209
+ <p class="text-sm text-gray-500 mt-2">${passedChecks} / ${totalChecks} checks passed</p>
210
+ </div>
211
+
212
+ <div class="bg-white rounded-lg shadow p-6">
213
+ <div class="flex items-center justify-between">
214
+ <div>
215
+ <p class="text-gray-500 text-sm">Findings</p>
216
+ <p class="text-3xl font-bold">${totalFindings}</p>
217
+ </div>
218
+ <div class="text-4xl">📋</div>
219
+ </div>
220
+ <div class="flex gap-4 mt-2 text-sm">
221
+ <span class="text-red-600">${errorCount} errors</span>
222
+ <span class="text-yellow-600">${warningCount} warnings</span>
223
+ </div>
224
+ </div>
225
+
226
+ <div class="bg-white rounded-lg shadow p-6">
227
+ <div class="flex items-center justify-between">
228
+ <div>
229
+ <p class="text-gray-500 text-sm">Duration</p>
230
+ <p class="text-3xl font-bold">${report.durationSec.toFixed(1)}s</p>
231
+ </div>
232
+ <div class="text-4xl">⏱️</div>
233
+ </div>
234
+ <p class="text-sm text-gray-500 mt-2">${categoryStats.length} categories</p>
235
+ </div>
236
+ </div>
237
+
238
+ ${trendHtml}
239
+
240
+ <!-- Charts -->
241
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
242
+ <div class="bg-white rounded-lg shadow p-6">
243
+ <h3 class="text-lg font-semibold mb-4">Pass/Fail Distribution</h3>
244
+ <canvas id="passFailChart" width="400" height="200"></canvas>
245
+ </div>
246
+
247
+ <div class="bg-white rounded-lg shadow p-6">
248
+ <h3 class="text-lg font-semibold mb-4">Category Breakdown</h3>
249
+ <canvas id="categoryChart" width="400" height="200"></canvas>
250
+ </div>
251
+ </div>
252
+
253
+ <!-- Filters -->
254
+ <div class="bg-white rounded-lg shadow p-4 mb-6">
255
+ <div class="flex flex-wrap gap-2 items-center">
256
+ <span class="text-gray-600 font-medium">Filter:</span>
257
+ <button onclick="filterChecks('all')" class="filter-btn filter-active px-3 py-1 rounded bg-gray-200 hover:bg-gray-300" data-filter="all">All</button>
258
+ <button onclick="filterChecks('failed')" class="filter-btn px-3 py-1 rounded bg-gray-200 hover:bg-gray-300" data-filter="failed">Failed Only</button>
259
+ <button onclick="filterChecks('passed')" class="filter-btn px-3 py-1 rounded bg-gray-200 hover:bg-gray-300" data-filter="passed">Passed Only</button>
260
+ <button onclick="filterChecks('blocking')" class="filter-btn px-3 py-1 rounded bg-gray-200 hover:bg-gray-300" data-filter="blocking">Blocking</button>
261
+ <div class="ml-auto">
262
+ <input type="text" id="searchInput" placeholder="Search checks..." class="px-3 py-1 border rounded" onkeyup="searchChecks()">
263
+ </div>
264
+ </div>
265
+ </div>
266
+
267
+ <!-- Checks Table -->
268
+ <div class="bg-white rounded-lg shadow overflow-hidden">
269
+ <table class="min-w-full divide-y divide-gray-200">
270
+ <thead class="bg-gray-50">
271
+ <tr>
272
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
273
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Check</th>
274
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Category</th>
275
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Findings</th>
276
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Duration</th>
277
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Blocking</th>
278
+ </tr>
279
+ </thead>
280
+ <tbody class="bg-white divide-y divide-gray-200" id="checksTableBody">
281
+ ${report.records.map((record, index) => {
282
+ const recordPassed = record.kind === 'passed';
283
+ const recordCategory = getRecordCategory(record);
284
+ return `
285
+ <tr class="check-row cursor-pointer" onclick="toggleDetails(${index})"
286
+ data-passed="${recordPassed}"
287
+ data-blocking="${record.blocking}"
288
+ data-category="${recordCategory}"
289
+ data-name="${escapeHtml(record.name.toLowerCase())}">
290
+ <td class="px-6 py-4 whitespace-nowrap">
291
+ <span class="text-2xl">${recordPassed ? '✅' : '❌'}</span>
292
+ </td>
293
+ <td class="px-6 py-4">
294
+ <div class="text-sm font-medium text-gray-900">${escapeHtml(record.name)}</div>
295
+ <div class="text-sm text-gray-500">${escapeHtml(record.pathOrCmd || '')}</div>
296
+ </td>
297
+ <td class="px-6 py-4 whitespace-nowrap">
298
+ <span class="px-2 py-1 text-xs rounded bg-gray-100">${escapeHtml(recordCategory)}</span>
299
+ </td>
300
+ <td class="px-6 py-4 whitespace-nowrap">
301
+ ${record.findings?.length ? `
302
+ <span class="text-red-600">${record.findings.filter(f => f.level === 'error').length}</span> /
303
+ <span class="text-yellow-600">${record.findings.filter(f => f.level === 'warning').length}</span> /
304
+ <span class="text-blue-600">${record.findings.filter(f => f.level === 'info').length}</span>
305
+ ` : '<span class="text-gray-400">-</span>'}
306
+ </td>
307
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
308
+ ${record.durationSec.toFixed(2)}s
309
+ </td>
310
+ <td class="px-6 py-4 whitespace-nowrap">
311
+ ${record.blocking ? '<span class="text-red-600 font-medium">Yes</span>' : '<span class="text-gray-400">No</span>'}
312
+ </td>
313
+ </tr>
314
+ <tr class="finding-details" id="details-${index}">
315
+ <td colspan="6" class="px-6 py-4 bg-gray-50">
316
+ <div class="max-h-96 overflow-y-auto">
317
+ ${generateFindingsList(record.findings || [])}
318
+ </div>
319
+ </td>
320
+ </tr>
321
+ `;
322
+ }).join('')}
323
+ </tbody>
324
+ </table>
325
+ </div>
326
+ </main>
327
+
328
+ <footer class="bg-white border-t mt-8 py-4">
329
+ <div class="max-w-7xl mx-auto px-4 text-center text-gray-500 text-sm">
330
+ Generated by @empline/preflight | ${new Date().toISOString()}
331
+ </div>
332
+ </footer>
333
+
334
+ <script>
335
+ // Store report data for export
336
+ const reportData = ${JSON.stringify(report)};
337
+
338
+ // Pass/Fail Chart
339
+ new Chart(document.getElementById('passFailChart'), {
340
+ type: 'doughnut',
341
+ data: {
342
+ labels: ['Passed', 'Failed'],
343
+ datasets: [{
344
+ data: [${passedChecks}, ${failedChecks}],
345
+ backgroundColor: ['#22c55e', '#ef4444'],
346
+ }]
347
+ },
348
+ options: {
349
+ responsive: true,
350
+ plugins: {
351
+ legend: { position: 'bottom' }
352
+ }
353
+ }
354
+ });
355
+
356
+ // Category Chart
357
+ new Chart(document.getElementById('categoryChart'), {
358
+ type: 'bar',
359
+ data: {
360
+ labels: ${JSON.stringify(categoryStats.map(s => s.category))},
361
+ datasets: [
362
+ {
363
+ label: 'Passed',
364
+ data: ${JSON.stringify(categoryStats.map(s => s.passed))},
365
+ backgroundColor: '#22c55e',
366
+ },
367
+ {
368
+ label: 'Failed',
369
+ data: ${JSON.stringify(categoryStats.map(s => s.failed))},
370
+ backgroundColor: '#ef4444',
371
+ }
372
+ ]
373
+ },
374
+ options: {
375
+ responsive: true,
376
+ scales: {
377
+ x: { stacked: true },
378
+ y: { stacked: true }
379
+ },
380
+ plugins: {
381
+ legend: { position: 'bottom' }
382
+ }
383
+ }
384
+ });
385
+
386
+ function toggleDetails(index) {
387
+ const details = document.getElementById('details-' + index);
388
+ details.classList.toggle('open');
389
+ }
390
+
391
+ function filterChecks(filter) {
392
+ const rows = document.querySelectorAll('.check-row');
393
+ const detailRows = document.querySelectorAll('.finding-details');
394
+ const buttons = document.querySelectorAll('.filter-btn');
395
+
396
+ buttons.forEach(btn => btn.classList.remove('filter-active'));
397
+ document.querySelector('[data-filter="' + filter + '"]').classList.add('filter-active');
398
+
399
+ rows.forEach((row, index) => {
400
+ let show = true;
401
+ if (filter === 'failed') show = row.dataset.passed === 'false';
402
+ else if (filter === 'passed') show = row.dataset.passed === 'true';
403
+ else if (filter === 'blocking') show = row.dataset.blocking === 'true';
404
+
405
+ row.style.display = show ? '' : 'none';
406
+ detailRows[index].style.display = 'none';
407
+ detailRows[index].classList.remove('open');
408
+ });
409
+ }
410
+
411
+ function searchChecks() {
412
+ const query = document.getElementById('searchInput').value.toLowerCase();
413
+ const rows = document.querySelectorAll('.check-row');
414
+ const detailRows = document.querySelectorAll('.finding-details');
415
+
416
+ rows.forEach((row, index) => {
417
+ const name = row.dataset.name;
418
+ const category = row.dataset.category;
419
+ const show = name.includes(query) || category.includes(query);
420
+ row.style.display = show ? '' : 'none';
421
+ if (!show) {
422
+ detailRows[index].style.display = 'none';
423
+ detailRows[index].classList.remove('open');
424
+ }
425
+ });
426
+ }
427
+
428
+ function exportJson() {
429
+ const blob = new Blob([JSON.stringify(reportData, null, 2)], { type: 'application/json' });
430
+ const url = URL.createObjectURL(blob);
431
+ const a = document.createElement('a');
432
+ a.href = url;
433
+ a.download = 'preflight-report.json';
434
+ a.click();
435
+ URL.revokeObjectURL(url);
436
+ }
437
+ </script>
438
+ </body>
439
+ </html>
440
+ `;
441
+ return html;
442
+ }
443
+ function writeHtmlReport(report, outputPath, options) {
444
+ const html = generateHtmlReport(report, options);
445
+ const dir = path.dirname(outputPath);
446
+ if (!fs.existsSync(dir)) {
447
+ fs.mkdirSync(dir, { recursive: true });
448
+ }
449
+ fs.writeFileSync(outputPath, html);
450
+ }
451
+ // CLI entry point
452
+ if (require.main === module) {
453
+ const args = process.argv.slice(2);
454
+ const inputPath = args[0];
455
+ const outputPath = args[1] || "preflight-report.html";
456
+ if (!inputPath) {
457
+ console.log("Usage: npx tsx html-report.ts <input.json> [output.html]");
458
+ console.log(" Generates HTML report from preflight JSON output");
459
+ process.exit(1);
460
+ }
461
+ if (!fs.existsSync(inputPath)) {
462
+ console.error(`Input file not found: ${inputPath}`);
463
+ process.exit(1);
464
+ }
465
+ const report = JSON.parse(fs.readFileSync(inputPath, "utf-8"));
466
+ writeHtmlReport(report, outputPath, { title: `Preflight Report - ${path.basename(process.cwd())}` });
467
+ console.log(`HTML report generated: ${outputPath}`);
468
+ }
469
+ //# sourceMappingURL=html-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-report.js","sourceRoot":"","sources":["../../src/reporters/html-report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Preflight Reporters
3
+ *
4
+ * Export all report generators for different output formats
5
+ */
6
+ export { generateHtmlReport, writeHtmlReport } from "./html-report";
7
+ export { generateMarkdownReport, postPrComment, updateCommitStatus, detectGitHubEnvironment, getGitInfo, } from "./github-reporter";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reporters/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,uBAAuB,EACvB,UAAU,GACX,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ /**
3
+ * Preflight Reporters
4
+ *
5
+ * Export all report generators for different output formats
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.getGitInfo = exports.detectGitHubEnvironment = exports.updateCommitStatus = exports.postPrComment = exports.generateMarkdownReport = exports.writeHtmlReport = exports.generateHtmlReport = void 0;
9
+ var html_report_1 = require("./html-report");
10
+ Object.defineProperty(exports, "generateHtmlReport", { enumerable: true, get: function () { return html_report_1.generateHtmlReport; } });
11
+ Object.defineProperty(exports, "writeHtmlReport", { enumerable: true, get: function () { return html_report_1.writeHtmlReport; } });
12
+ var github_reporter_1 = require("./github-reporter");
13
+ Object.defineProperty(exports, "generateMarkdownReport", { enumerable: true, get: function () { return github_reporter_1.generateMarkdownReport; } });
14
+ Object.defineProperty(exports, "postPrComment", { enumerable: true, get: function () { return github_reporter_1.postPrComment; } });
15
+ Object.defineProperty(exports, "updateCommitStatus", { enumerable: true, get: function () { return github_reporter_1.updateCommitStatus; } });
16
+ Object.defineProperty(exports, "detectGitHubEnvironment", { enumerable: true, get: function () { return github_reporter_1.detectGitHubEnvironment; } });
17
+ Object.defineProperty(exports, "getGitInfo", { enumerable: true, get: function () { return github_reporter_1.getGitInfo; } });
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reporters/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,6CAAoE;AAA3D,iHAAA,kBAAkB,OAAA;AAAE,8GAAA,eAAe,OAAA;AAC5C,qDAM2B;AALzB,yHAAA,sBAAsB,OAAA;AACtB,gHAAA,aAAa,OAAA;AACb,qHAAA,kBAAkB,OAAA;AAClB,0HAAA,uBAAuB,OAAA;AACvB,6GAAA,UAAU,OAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empline/preflight",
3
- "version": "1.1.58",
3
+ "version": "1.1.59",
4
4
  "description": "Distributable preflight validation system with app-specific plugin support",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",