spec-up-t-healthcheck 1.0.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.
@@ -0,0 +1,127 @@
1
+ /**
2
+ * @fileoverview Cross-platform file opener utility
3
+ *
4
+ * This module provides functionality to open files and URLs in the user's default
5
+ * application across different operating systems. It handles platform-specific
6
+ * commands and provides consistent error handling and feedback.
7
+ *
8
+ * @author spec-up-t-healthcheck
9
+
10
+ */
11
+
12
+ import { spawn } from 'child_process';
13
+ import { platform } from 'os';
14
+ import { existsSync } from 'fs';
15
+
16
+ /**
17
+ * Opens a file or URL in the default application.
18
+ *
19
+ * This function automatically detects the operating system and uses the appropriate
20
+ * command to open files or URLs. It provides cross-platform compatibility for
21
+ * opening HTML files in the default browser.
22
+ *
23
+ * @param {string} target - The file path or URL to open
24
+ * @returns {Promise<boolean>} Promise that resolves to true if successful, false otherwise
25
+ *
26
+ * @example
27
+ * ```javascript
28
+ * // Open an HTML file
29
+ * const success = await openFile('/path/to/report.html');
30
+ * if (success) {
31
+ * console.log('Report opened in browser');
32
+ * }
33
+ *
34
+ * // Open a URL
35
+ * await openFile('https://example.com');
36
+ * ```
37
+ */
38
+ export async function openFile(target) {
39
+ return new Promise((resolve) => {
40
+ // Validate file exists if it's a local path
41
+ if (!target.startsWith('http') && !existsSync(target)) {
42
+ console.error(`File does not exist: ${target}`);
43
+ resolve(false);
44
+ return;
45
+ }
46
+
47
+ const platformType = platform();
48
+ const commands = {
49
+ 'darwin': ['open', target],
50
+ 'win32': ['cmd', '/c', 'start', '', target],
51
+ 'default': ['xdg-open', target]
52
+ };
53
+
54
+ const [command, ...args] = commands[platformType] || commands.default;
55
+
56
+ const child = spawn(command, args, {
57
+ detached: true,
58
+ stdio: 'ignore'
59
+ });
60
+
61
+ // Simple error handling - resolve false on error, true on success
62
+ child.on('error', () => resolve(false));
63
+ child.on('spawn', () => {
64
+ child.unref();
65
+ resolve(true);
66
+ });
67
+ });
68
+ }
69
+
70
+ /**
71
+ * Opens an HTML file in the default browser.
72
+ *
73
+ * This is a convenience wrapper around openFile specifically for HTML files.
74
+ * It provides additional validation and more specific error messages for HTML content.
75
+ *
76
+ * @param {string} htmlFilePath - Path to the HTML file to open
77
+ * @returns {Promise<boolean>} Promise that resolves to true if successful, false otherwise
78
+ *
79
+ * @example
80
+ * ```javascript
81
+ * const reportPath = '/tmp/health-report.html';
82
+ * const opened = await openHtmlFile(reportPath);
83
+ * if (!opened) {
84
+ * console.error('Failed to open HTML report');
85
+ * }
86
+ * ```
87
+ */
88
+ export async function openHtmlFile(htmlFilePath) {
89
+ if (!htmlFilePath.toLowerCase().endsWith('.html') && !htmlFilePath.toLowerCase().endsWith('.htm')) {
90
+ console.warn('Warning: File does not appear to be an HTML file');
91
+ }
92
+
93
+ return await openFile(htmlFilePath);
94
+ }
95
+
96
+ /**
97
+ * Gets the platform-specific command for opening files.
98
+ *
99
+ * This utility function returns the command name that would be used to open files
100
+ * on the current platform. This is useful for debugging or displaying information to users.
101
+ * NOTE: This function only returns the command name as a string - it does NOT open files.
102
+ * To actually open files, use openFile() or openHtmlFile() instead.
103
+ *
104
+ * @returns {string} The platform-specific open command name
105
+ *
106
+ * @example
107
+ * ```javascript
108
+ * const commandName = getOpenCommand();
109
+ * console.log(`Using command: ${commandName}`); // e.g., "open" on macOS
110
+ *
111
+ * // To actually open a file, use openFile() or openHtmlFile():
112
+ * const success = await openFile('report.html');
113
+ * const success2 = await openHtmlFile('report.html');
114
+ * ```
115
+ */
116
+ export function getOpenCommand() {
117
+ const platformType = platform();
118
+
119
+ switch (platformType) {
120
+ case 'darwin':
121
+ return 'open';
122
+ case 'win32':
123
+ return 'start';
124
+ default:
125
+ return 'xdg-open';
126
+ }
127
+ }
@@ -0,0 +1,176 @@
1
+ /**
2
+ * @fileoverview Output formatters for health check results
3
+ *
4
+ * This module provides various formatting options for health check results,
5
+ * including human-readable text output with icons, structured JSON output,
6
+ * and interactive HTML reports with Bootstrap styling.
7
+ * The formatters support customization options and maintain consistent styling.
8
+ *
9
+ * @author spec-up-t-healthcheck
10
+
11
+ */
12
+
13
+ import { generateHtmlReport } from './html-formatter.js';
14
+
15
+ /**
16
+ * Formats health check results as human-readable text with emojis and structured layout.
17
+ *
18
+ * This formatter creates a comprehensive text report that's suitable for console output
19
+ * or text files. It includes a summary section, overall status, and detailed results
20
+ * for each individual check. The output uses Unicode emojis for visual clarity.
21
+ *
22
+ * @param {import('./health-checker.js').HealthCheckReport} healthCheckOutput - The complete health check report
23
+ * @param {boolean} [useColors=false] - Whether to include ANSI color codes (reserved for future use)
24
+ * @returns {string} Formatted text report ready for display or logging
25
+ *
26
+ * @example
27
+ * ```javascript
28
+ * const report = await runHealthChecks(provider);
29
+ * const textOutput = formatResultsAsText(report);
30
+ * console.log(textOutput);
31
+ *
32
+ * // Example output:
33
+ * // 📋 Spec-up-t Health Check Report
34
+ * // Generated: 9/18/2025, 10:30:00 AM
35
+ * //
36
+ * // Repository: /path/to/spec
37
+ * //
38
+ * // 📊 Summary
39
+ * // Total checks: 2
40
+ * // ✓ Passed: 2
41
+ * // ✗ Failed: 0
42
+ * // Score: 100%
43
+ * ```
44
+ */
45
+ export function formatResultsAsText(healthCheckOutput, useColors = false) {
46
+ const { results, summary, timestamp, provider } = healthCheckOutput;
47
+
48
+ let output = [];
49
+
50
+ output.push('📋 Spec-up-t Health Check Report');
51
+ output.push(`Generated: ${new Date(timestamp).toLocaleString()}`);
52
+ output.push('');
53
+
54
+ if (provider.repoPath) {
55
+ output.push(`Repository: ${provider.repoPath}`);
56
+ }
57
+ output.push('');
58
+
59
+ output.push('📊 Summary');
60
+ output.push(`Total checks: ${summary.total}`);
61
+ output.push(`✓ Passed: ${summary.passed}`);
62
+ output.push(`✗ Failed: ${summary.failed}`);
63
+ if (summary.warnings > 0) output.push(`⚠ Warnings: ${summary.warnings}`);
64
+ if (summary.skipped > 0) output.push(`○ Skipped: ${summary.skipped}`);
65
+ output.push(`Score: ${Math.round(summary.score)}%`);
66
+ output.push('');
67
+
68
+ if (summary.hasErrors) {
69
+ output.push('❌ Overall Status: FAILED');
70
+ } else if (summary.hasWarnings) {
71
+ output.push('⚠️ Overall Status: PASSED WITH WARNINGS');
72
+ } else {
73
+ output.push('✅ Overall Status: PASSED');
74
+ }
75
+ output.push('');
76
+
77
+ output.push('📝 Detailed Results');
78
+ output.push('');
79
+
80
+ results.forEach((result, index) => {
81
+ const statusIcon = {
82
+ pass: '✓',
83
+ fail: '✗',
84
+ warn: '⚠',
85
+ skip: '○'
86
+ }[result.status];
87
+
88
+ output.push(`${index + 1}. ${statusIcon} ${result.check}`);
89
+ output.push(` ${result.message}`);
90
+
91
+ if (result.details && Object.keys(result.details).length > 0) {
92
+ if (result.details.missingFields) {
93
+ output.push(` Missing fields: ${result.details.missingFields.join(', ')}`);
94
+ }
95
+ if (result.details.count) {
96
+ output.push(` Files found: ${result.details.count}`);
97
+ }
98
+ if (result.details.packageData) {
99
+ output.push(` Package: ${result.details.packageData.name}@${result.details.packageData.version}`);
100
+ }
101
+ }
102
+
103
+ output.push('');
104
+ });
105
+
106
+ return output.join('\n');
107
+ }
108
+
109
+ /**
110
+ * Formats health check results as structured JSON with optional pretty-printing.
111
+ *
112
+ * This formatter converts the health check report to JSON format, making it suitable
113
+ * for programmatic consumption, API responses, or storage. The output maintains the
114
+ * complete structure of the original report with configurable indentation.
115
+ *
116
+ * @param {import('./health-checker.js').HealthCheckReport} healthCheckOutput - The complete health check report
117
+ * @param {number} [indent=2] - Number of spaces for JSON indentation (0 for compact output)
118
+ * @returns {string} JSON-formatted string representation of the health check report
119
+ *
120
+ * @example
121
+ * ```javascript
122
+ * const report = await runHealthChecks(provider);
123
+ *
124
+ * // Pretty-printed JSON (default)
125
+ * const prettyJson = formatResultsAsJson(report);
126
+ *
127
+ * // Compact JSON
128
+ * const compactJson = formatResultsAsJson(report, 0);
129
+ *
130
+ * // Custom indentation
131
+ * const customJson = formatResultsAsJson(report, 4);
132
+ *
133
+ * // Parse back to object
134
+ * const parsedReport = JSON.parse(prettyJson);
135
+ * ```
136
+ */
137
+ export function formatResultsAsJson(healthCheckOutput, indent = 2) {
138
+ return JSON.stringify(healthCheckOutput, null, indent);
139
+ }
140
+
141
+ /**
142
+ * Formats health check results as an interactive Bootstrap-styled HTML report.
143
+ *
144
+ * This formatter creates a comprehensive HTML document with responsive design,
145
+ * interactive filtering capabilities, and visual status indicators. The report
146
+ * follows modern web design patterns and provides an excellent user experience
147
+ * for reviewing health check results in a browser.
148
+ *
149
+ * @param {import('./health-checker.js').HealthCheckReport} healthCheckOutput - The complete health check report
150
+ * @param {Object} [options={}] - Configuration options for HTML generation
151
+ * @param {string} [options.title='Spec-Up-T Health Check Report'] - Custom title for the report
152
+ * @param {boolean} [options.showPassingByDefault=true] - Whether to show passing checks by default
153
+ * @param {string} [options.repositoryUrl] - URL to the repository being checked
154
+ * @returns {string} Complete HTML document ready for saving or displaying
155
+ *
156
+ * @example
157
+ * ```javascript
158
+ * const report = await runHealthChecks(provider);
159
+ *
160
+ * // Basic HTML report
161
+ * const htmlReport = formatResultsAsHtml(report);
162
+ *
163
+ * // Customized HTML report
164
+ * const customHtml = formatResultsAsHtml(report, {
165
+ * title: 'My Project Health Check',
166
+ * repositoryUrl: 'https://github.com/user/repo',
167
+ * showPassingByDefault: false
168
+ * });
169
+ *
170
+ * // Save to file
171
+ * fs.writeFileSync('health-report.html', htmlReport);
172
+ * ```
173
+ */
174
+ export function formatResultsAsHtml(healthCheckOutput, options = {}) {
175
+ return generateHtmlReport(healthCheckOutput, options);
176
+ }