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.
package/lib/index.js ADDED
@@ -0,0 +1,123 @@
1
+ /**
2
+ * @fileoverview Main entry point for spec-up-t-healthcheck
3
+ *
4
+ * This module serves as the primary API for the spec-up-t-healthcheck library,
5
+ * providing convenient access to all core functionality including health checking,
6
+ * result formatting, and provider management. It offers both individual component
7
+ * access and a simplified high-level API.
8
+ *
9
+ * @author spec-up-t-healthcheck
10
+
11
+ */
12
+
13
+ // Re-export provider functionality
14
+ export { createProvider, createLocalProvider } from './providers.js';
15
+
16
+ // Re-export health checking functionality
17
+ export { runHealthChecks, createHealthCheckResult, checkPackageJson, checkSpecFiles, checkSpecsJson, checkExternalSpecsUrls, checkGitignore } from './health-checker.js';
18
+
19
+ // Re-export formatting functionality
20
+ export { formatResultsAsText, formatResultsAsJson, formatResultsAsHtml } from './formatters.js';
21
+
22
+ // Re-export file opening utilities
23
+ export { openFile, openHtmlFile, getOpenCommand } from './file-opener.js';
24
+
25
+ // Import functions for internal use
26
+ import { createProvider } from './providers.js';
27
+ import { runHealthChecks } from './health-checker.js';
28
+
29
+ /**
30
+ * Direct API Usage Examples
31
+ *
32
+ * For more control over the health checking process, you can use the core functions directly:
33
+ *
34
+ * @example
35
+ * ```javascript
36
+ * // Direct usage with runHealthChecks (more control)
37
+ * (async () => {
38
+ * const { createProvider, runHealthChecks } = await import('spec-up-t-healthcheck');
39
+ * const provider = createProvider('.');
40
+ * const results = await runHealthChecks(provider, {});
41
+ * console.log("🚀 ~ Healthcheck results:", results);
42
+ * })().catch(console.error);
43
+ *
44
+ * // With specific checks
45
+ * (async () => {
46
+ * const { createProvider, runHealthChecks } = await import('spec-up-t-healthcheck');
47
+ * const provider = createProvider('./my-project');
48
+ * const results = await runHealthChecks(provider, {
49
+ * checks: ['package-json', 'spec-files']
50
+ * });
51
+ * console.log("Health score:", results.summary.score + "%");
52
+ * console.log("Errors:", results.summary.hasErrors);
53
+ * })().catch(console.error);
54
+ *
55
+ * // Format results in different ways
56
+ * (async () => {
57
+ * const { createProvider, runHealthChecks, formatResultsAsHtml } = await import('spec-up-t-healthcheck');
58
+ * const provider = createProvider('.');
59
+ * const results = await runHealthChecks(provider, {});
60
+ *
61
+ * // Generate HTML report
62
+ * const htmlReport = formatResultsAsHtml(results, {
63
+ * title: 'My Project Health Check',
64
+ * repositoryUrl: 'https://github.com/user/repo'
65
+ * });
66
+ *
67
+ * // Save or display the HTML
68
+ * console.log("HTML report generated");
69
+ * })().catch(console.error);
70
+ * ```
71
+ */
72
+
73
+ /**
74
+ * Simplified high-level API for performing health checks on a specification repository.
75
+ *
76
+ * This convenience function combines provider creation and health checking into a single
77
+ * call, making it easy to perform health checks without managing providers manually.
78
+ * It automatically determines the appropriate provider type based on the input.
79
+ *
80
+ * @param {string} input - The path or URL to the specification repository
81
+ * @param {Object} [options={}] - Configuration options for the health check
82
+ * @param {string[]} [options.checks] - Specific checks to run (defaults to all registered checks)
83
+ * @param {string[]} [options.categories] - Legacy alias for checks parameter
84
+ * @param {Object} [options.providerOptions] - Options to pass to the provider
85
+ * @returns {Promise<import('./health-checker.js').HealthCheckReport>} Complete health check report
86
+ *
87
+ * @example
88
+ * ```javascript
89
+ * // Check a local repository (runs all registered checks)
90
+ * const report = await healthCheck('/path/to/spec-repo');
91
+ *
92
+ * // Check with specific options
93
+ * const customReport = await healthCheck('/path/to/spec-repo', {
94
+ * checks: ['package-json', 'spec-files']
95
+ * });
96
+ *
97
+ * // Display results
98
+ * console.log(`Health score: ${report.summary.score}%`);
99
+ * if (report.summary.hasErrors) {
100
+ * console.error('Some health checks failed');
101
+ * }
102
+ * ```
103
+ *
104
+ * @since 1.0.0
105
+ */
106
+ export async function healthCheck(input, options = {}) {
107
+ // Handle legacy 'categories' parameter
108
+ const healthCheckOptions = {
109
+ ...options,
110
+ checks: options.checks || options.categories
111
+ // If neither checks nor categories is provided, orchestrator will run all registered checks
112
+ };
113
+
114
+ const provider = createProvider(input, options.providerOptions);
115
+ return await runHealthChecks(provider, healthCheckOptions);
116
+ }
117
+
118
+ /**
119
+ * The current version of the spec-up-t-healthcheck library.
120
+ * @type {string}
121
+ * @readonly
122
+ */
123
+ export const version = '1.0.2';
@@ -0,0 +1,184 @@
1
+ /**
2
+ * @fileoverview Providers module for spec-up-t-healthcheck
3
+ *
4
+ * This module contains provider implementations for accessing specification files
5
+ * from different sources (local filesystem, remote repositories, etc.).
6
+ * Providers offer a unified interface for file operations regardless of the underlying source.
7
+ *
8
+ * @author spec-up-t-healthcheck
9
+
10
+ */
11
+
12
+ import fs from 'fs/promises';
13
+ import path from 'path';
14
+
15
+ /**
16
+ * @typedef {Object} FileEntry
17
+ * @property {string} name - The name of the file or directory
18
+ * @property {string} path - The relative path from the repository root
19
+ * @property {boolean} isDirectory - Whether this entry is a directory
20
+ * @property {boolean} isFile - Whether this entry is a file
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} Provider
25
+ * @property {string} type - The type of provider ('local', 'remote', etc.)
26
+ * @property {string} repoPath - The base path or URL for the repository
27
+ * @property {function(string): Promise<string>} readFile - Read a file and return its content
28
+ * @property {function(string): Promise<boolean>} fileExists - Check if a file exists
29
+ * @property {function(string): Promise<FileEntry[]>} listFiles - List files in a directory
30
+ */
31
+
32
+ /**
33
+ * Creates a local filesystem provider for accessing specification files.
34
+ *
35
+ * The local provider enables reading files from a local directory structure,
36
+ * providing async methods for file operations with proper error handling.
37
+ * All file paths are resolved relative to the provided repository path.
38
+ *
39
+ * @param {string} repoPath - The absolute or relative path to the local repository root
40
+ * @returns {Provider} A provider object with methods for file operations
41
+ *
42
+ * @example
43
+ * ```javascript
44
+ * const provider = createLocalProvider('/path/to/spec/repo');
45
+ * const content = await provider.readFile('spec/example.md');
46
+ * const exists = await provider.fileExists('package.json');
47
+ * const files = await provider.listFiles('spec');
48
+ * ```
49
+ *
50
+ * @throws {Error} When file operations fail due to permissions or other filesystem errors
51
+ */
52
+ export function createLocalProvider(repoPath) {
53
+ const provider = {
54
+ type: 'local',
55
+ repoPath,
56
+
57
+ /**
58
+ * Returns the base path of the repository.
59
+ *
60
+ * @returns {string} The base path of the repository
61
+ */
62
+ getBasePath() {
63
+ return repoPath;
64
+ },
65
+
66
+ /**
67
+ * Reads the content of a file from the local filesystem.
68
+ *
69
+ * @param {string} filePath - The relative path to the file from the repository root
70
+ * @returns {Promise<string>} The file content as a UTF-8 string
71
+ *
72
+ * @throws {Error} When the file is not found (ENOENT)
73
+ * @throws {Error} When there's a filesystem error reading the file
74
+ *
75
+ * @example
76
+ * ```javascript
77
+ * const content = await provider.readFile('spec/introduction.md');
78
+ * console.log(content); // File content as string
79
+ * ```
80
+ */
81
+ async readFile(filePath) {
82
+ const fullPath = path.join(repoPath, filePath);
83
+ try {
84
+ const content = await fs.readFile(fullPath, 'utf8');
85
+ return content;
86
+ } catch (error) {
87
+ if (error.code === 'ENOENT') {
88
+ throw new Error(`File not found: ${filePath}`);
89
+ }
90
+ throw new Error(`Error reading file ${filePath}: ${error.message}`);
91
+ }
92
+ },
93
+
94
+ /**
95
+ * Checks whether a file exists in the local filesystem.
96
+ *
97
+ * @param {string} filePath - The relative path to the file from the repository root
98
+ * @returns {Promise<boolean>} True if the file exists, false otherwise
99
+ *
100
+ * @example
101
+ * ```javascript
102
+ * const exists = await provider.fileExists('package.json');
103
+ * if (exists) {
104
+ * console.log('Package.json found');
105
+ * }
106
+ * ```
107
+ */
108
+ async fileExists(filePath) {
109
+ const fullPath = path.join(repoPath, filePath);
110
+ try {
111
+ await fs.access(fullPath);
112
+ return true;
113
+ } catch {
114
+ return false;
115
+ }
116
+ },
117
+
118
+ /**
119
+ * Lists all files and directories in the specified directory.
120
+ *
121
+ * @param {string} [dirPath=''] - The relative path to the directory from the repository root.
122
+ * Defaults to the repository root if not specified.
123
+ * @returns {Promise<FileEntry[]>} An array of file entries with metadata
124
+ *
125
+ * @throws {Error} When the directory cannot be read or doesn't exist
126
+ *
127
+ * @example
128
+ * ```javascript
129
+ * const entries = await provider.listFiles('spec');
130
+ * entries.forEach(entry => {
131
+ * console.log(`${entry.name} - ${entry.isDirectory ? 'DIR' : 'FILE'}`);
132
+ * });
133
+ * ```
134
+ */
135
+ async listFiles(dirPath = '') {
136
+ const fullPath = path.join(repoPath, dirPath);
137
+ try {
138
+ const entries = await fs.readdir(fullPath, { withFileTypes: true });
139
+ return entries.map(entry => ({
140
+ name: entry.name,
141
+ path: path.join(dirPath, entry.name),
142
+ isDirectory: entry.isDirectory(),
143
+ isFile: entry.isFile()
144
+ }));
145
+ } catch (error) {
146
+ throw new Error(`Error listing directory ${dirPath}: ${error.message}`);
147
+ }
148
+ }
149
+ };
150
+
151
+ return provider;
152
+ }
153
+
154
+ /**
155
+ * Creates a provider based on the input type (local path or remote URL).
156
+ *
157
+ * This factory function automatically determines the appropriate provider type
158
+ * based on the input format. Currently supports local filesystem providers,
159
+ * with remote providers planned for future implementation.
160
+ *
161
+ * @param {string} input - The path or URL to the specification repository.
162
+ * Local paths can be absolute or relative.
163
+ * Remote URLs should start with http:// or https://
164
+ * @returns {Provider} An appropriate provider instance for the input type
165
+ *
166
+ * @throws {Error} When remote URLs are provided (not yet implemented)
167
+ *
168
+ * @example
169
+ * ```javascript
170
+ * // Create a local provider
171
+ * const localProvider = createProvider('/path/to/spec');
172
+ *
173
+ * // Remote provider (throws error - not implemented)
174
+ * const remoteProvider = createProvider('https://github.com/user/spec-repo');
175
+ * ```
176
+ *
177
+ * @since 1.0.0
178
+ */
179
+ export function createProvider(input) {
180
+ if (input.startsWith('http://') || input.startsWith('https://')) {
181
+ throw new Error('Remote providers not yet implemented');
182
+ }
183
+ return createLocalProvider(input);
184
+ }
package/lib/web.js ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * @fileoverview Browser-compatible entry point for spec-up-t-healthcheck
3
+ *
4
+ * This module provides a browser-safe API that excludes Node.js-specific modules
5
+ * like file-opener which depend on child_process. This allows the health check
6
+ * functionality to work in browser environments like Vite.
7
+ *
8
+ * @author spec-up-t-healthcheck
9
+ */
10
+
11
+ // Re-export provider functionality (browser-compatible)
12
+ export { createProvider } from './providers.js';
13
+
14
+ // Re-export health checking functionality (browser-compatible)
15
+ export {
16
+ runHealthChecks,
17
+ createHealthCheckResult,
18
+ checkPackageJson,
19
+ checkSpecFiles,
20
+ checkSpecsJson
21
+ } from './health-checker.js';
22
+
23
+ // Re-export formatting functionality (browser-compatible)
24
+ export {
25
+ formatResultsAsText,
26
+ formatResultsAsJson,
27
+ formatResultsAsHtml
28
+ } from './formatters.js';
29
+
30
+ // Import functions for internal use
31
+ import { createProvider } from './providers.js';
32
+ import { runHealthChecks } from './health-checker.js';
33
+
34
+ /**
35
+ * Simplified API for browser environments
36
+ *
37
+ * This function provides the same functionality as the main package
38
+ * but excludes file opening capabilities that require Node.js
39
+ *
40
+ * @param {Object} provider - File system provider (must be provided)
41
+ * @param {Object} [options={}] - Health check options
42
+ * @returns {Promise<Object>} Health check results
43
+ *
44
+ * @example
45
+ * ```javascript
46
+ * import { runHealthCheck } from 'spec-up-t-healthcheck/web';
47
+ *
48
+ * const provider = createGitHubProvider(token, owner, repo);
49
+ * const results = await runHealthCheck(provider);
50
+ * ```
51
+ */
52
+ export async function runHealthCheck(provider, options = {}) {
53
+ if (!provider) {
54
+ throw new Error('Provider is required for browser environments');
55
+ }
56
+
57
+ return await runHealthChecks(provider, options);
58
+ }
59
+
60
+ /**
61
+ * Browser-compatible health check API
62
+ * Excludes file opening functionality for browser safety
63
+ */
64
+ export const browserApi = {
65
+ runHealthCheck,
66
+ createProvider,
67
+ runHealthChecks
68
+ };
69
+
70
+ export default browserApi;
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "spec-up-t-healthcheck",
3
+ "version": "1.0.0",
4
+ "description": "Modular health check tool for spec-up-t repositories - works in Node.js, browsers, and CLI",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "bin": {
8
+ "spec-up-t-healthcheck": "bin/cli.js"
9
+ },
10
+ "exports": {
11
+ ".": "./lib/index.js",
12
+ "./web": "./lib/web.js"
13
+ },
14
+ "scripts": {
15
+ "test": "jest",
16
+ "test:watch": "jest --watch",
17
+ "lint": "eslint lib test",
18
+ "lint:fix": "eslint lib test --fix",
19
+ "cli": "node bin/cli.js",
20
+ "example": "node examples/node-usage.js",
21
+ "examples": "node examples/comprehensive-usage.js",
22
+ "healthcheck": "node bin/cli.js check .",
23
+ "healthcheck:html": "node bin/cli.js check . --format html",
24
+ "demo:html": "node bin/demo-html.js"
25
+ },
26
+ "keywords": [
27
+ "spec-up-t",
28
+ "health-check",
29
+ "validation",
30
+ "specification",
31
+ "markdown",
32
+ "cli",
33
+ "npm",
34
+ "quality-assurance"
35
+ ],
36
+ "author": "Blockchain Bird",
37
+ "license": "Apache-2.0",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/blockchainbird/spec-up-t-healthcheck.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/blockchainbird/spec-up-t-healthcheck/issues"
44
+ },
45
+ "homepage": "https://github.com/blockchainbird/spec-up-t-healthcheck#readme",
46
+ "engines": {
47
+ "node": ">=18.0.0"
48
+ },
49
+ "files": [
50
+ "lib/",
51
+ "bin/",
52
+ "README.md",
53
+ "LICENSE"
54
+ ],
55
+ "dependencies": {
56
+ "axios": "^1.6.7",
57
+ "commander": "^12.0.0",
58
+ "chalk": "^5.3.0",
59
+ "ora": "^8.0.1"
60
+ },
61
+ "devDependencies": {
62
+ "eslint": "^8.57.0",
63
+ "jest": "^29.7.0",
64
+ "nodemon": "^3.0.3"
65
+ },
66
+ "peerDependencies": {
67
+ "node-fetch": "^3.0.0"
68
+ },
69
+ "peerDependenciesMeta": {
70
+ "node-fetch": {
71
+ "optional": true
72
+ }
73
+ },
74
+ "publishConfig": {
75
+ "access": "public"
76
+ },
77
+ "overrides": {
78
+ "@jest/environment": "^29.7.0",
79
+ "@jest/environment-jsdom-abstract": "^29.7.0",
80
+ "@jest/fake-timers": "^29.7.0",
81
+ "@jest/schemas": "^29.7.0",
82
+ "@jest/types": "^29.7.0",
83
+ "jest-environment-jsdom": "^29.7.0",
84
+ "jest-message-util": "^29.7.0",
85
+ "jest-mock": "^29.7.0",
86
+ "jest-util": "^29.7.0",
87
+ "pretty-format": "^29.7.0",
88
+ "@jest/pattern": "^29.7.0",
89
+ "jest-regex-util": "^29.7.0"
90
+ }
91
+ }