envprobe 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/LICENSE +21 -0
- package/README.md +316 -0
- package/bin/envcheck.js +68 -0
- package/package.json +49 -0
- package/src/analyzer.js +179 -0
- package/src/autocomplete.js +135 -0
- package/src/cache.js +114 -0
- package/src/cli.js +606 -0
- package/src/config.js +118 -0
- package/src/formatters/github.js +164 -0
- package/src/formatters/json.js +114 -0
- package/src/formatters/table.js +92 -0
- package/src/formatters/text.js +198 -0
- package/src/ignore.js +313 -0
- package/src/parser.js +119 -0
- package/src/plugins.js +138 -0
- package/src/progress.js +181 -0
- package/src/repl.js +416 -0
- package/src/scanner.js +182 -0
- package/src/scanners/go.js +89 -0
- package/src/scanners/javascript.js +93 -0
- package/src/scanners/python.js +97 -0
- package/src/scanners/ruby.js +90 -0
- package/src/scanners/rust.js +103 -0
- package/src/scanners/shell.js +125 -0
- package/src/security.js +411 -0
- package/src/suggestions.js +154 -0
- package/src/utils.js +57 -0
- package/src/watch.js +131 -0
package/src/utils.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utility functions for envcheck-cli
|
|
3
|
+
* @module utils
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Normalize a file path to use forward slashes and remove redundant separators
|
|
10
|
+
* @param {string} filePath - The file path to normalize
|
|
11
|
+
* @returns {string} The normalized file path
|
|
12
|
+
*/
|
|
13
|
+
export function normalizePath(filePath) {
|
|
14
|
+
if (!filePath || filePath === '') {
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Use path.normalize to handle platform-specific separators and redundant separators
|
|
19
|
+
// Then convert all backslashes to forward slashes for consistency
|
|
20
|
+
return path.normalize(filePath).replace(/\\/g, '/');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Convert an absolute path to a relative path from the base directory
|
|
25
|
+
* @param {string} absolutePath - The absolute path to convert
|
|
26
|
+
* @param {string} basePath - The base directory path
|
|
27
|
+
* @returns {string} The relative path
|
|
28
|
+
*/
|
|
29
|
+
export function toRelativePath(absolutePath, basePath) {
|
|
30
|
+
if (!absolutePath || !basePath) {
|
|
31
|
+
return absolutePath || '';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// If paths are the same, return '.'
|
|
35
|
+
if (path.resolve(absolutePath) === path.resolve(basePath)) {
|
|
36
|
+
return '.';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Use path.relative to compute relative path, then normalize to forward slashes
|
|
40
|
+
const relativePath = path.relative(basePath, absolutePath);
|
|
41
|
+
return relativePath.replace(/\\/g, '/');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Validate if a string is a valid environment variable name
|
|
46
|
+
* Must match pattern: ^[A-Z_][A-Z0-9_]*$
|
|
47
|
+
* @param {string} varName - The variable name to validate
|
|
48
|
+
* @returns {boolean} True if valid, false otherwise
|
|
49
|
+
*/
|
|
50
|
+
export function isValidEnvVarName(varName) {
|
|
51
|
+
if (!varName || typeof varName !== 'string') {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const pattern = /^[A-Z_][A-Z0-9_]*$/;
|
|
56
|
+
return pattern.test(varName);
|
|
57
|
+
}
|
package/src/watch.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Watch mode for continuous validation
|
|
3
|
+
* Monitors file changes and re-runs validation automatically
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { watch } from 'fs';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Watch mode manager
|
|
11
|
+
*/
|
|
12
|
+
export class Watcher {
|
|
13
|
+
constructor(path, options, onChange) {
|
|
14
|
+
this.path = path;
|
|
15
|
+
this.options = options;
|
|
16
|
+
this.onChangeCallback = onChange;
|
|
17
|
+
this.watchers = [];
|
|
18
|
+
this.debounceTimer = null;
|
|
19
|
+
this.debounceDelay = 300;
|
|
20
|
+
this.isRunning = false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
start() {
|
|
24
|
+
console.log(`\nš Watching for changes in ${this.path}...`);
|
|
25
|
+
console.log('Press Ctrl+C to stop\n');
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const watcher = watch(
|
|
29
|
+
this.path,
|
|
30
|
+
{ recursive: true },
|
|
31
|
+
(eventType, filename) => {
|
|
32
|
+
if (filename && this.shouldProcess(filename)) {
|
|
33
|
+
this.handleChange(eventType, filename);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
this.watchers.push(watcher);
|
|
39
|
+
this.isRunning = true;
|
|
40
|
+
|
|
41
|
+
// Initial run
|
|
42
|
+
this.triggerChange('initial', 'startup');
|
|
43
|
+
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error(`Failed to start watch mode: ${error.message}`);
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
shouldProcess(filename) {
|
|
51
|
+
// Ignore common non-source files
|
|
52
|
+
const ignorePatterns = [
|
|
53
|
+
/node_modules/,
|
|
54
|
+
/\.git/,
|
|
55
|
+
/dist/,
|
|
56
|
+
/build/,
|
|
57
|
+
/\.log$/,
|
|
58
|
+
/\.tmp$/,
|
|
59
|
+
/~$/,
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
return !ignorePatterns.some(pattern => pattern.test(filename));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
handleChange(eventType, filename) {
|
|
66
|
+
// Debounce rapid changes
|
|
67
|
+
if (this.debounceTimer) {
|
|
68
|
+
clearTimeout(this.debounceTimer);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this.debounceTimer = setTimeout(() => {
|
|
72
|
+
this.triggerChange(eventType, filename);
|
|
73
|
+
}, this.debounceDelay);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async triggerChange(eventType, filename) {
|
|
77
|
+
if (this.onChangeCallback) {
|
|
78
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
79
|
+
console.log(`\n[${timestamp}] Change detected: ${filename}`);
|
|
80
|
+
console.log('ā'.repeat(50));
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
await this.onChangeCallback();
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error(`Error during validation: ${error.message}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log('ā'.repeat(50));
|
|
89
|
+
console.log('Waiting for changes...\n');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
stop() {
|
|
94
|
+
this.isRunning = false;
|
|
95
|
+
|
|
96
|
+
for (const watcher of this.watchers) {
|
|
97
|
+
watcher.close();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this.watchers = [];
|
|
101
|
+
|
|
102
|
+
if (this.debounceTimer) {
|
|
103
|
+
clearTimeout(this.debounceTimer);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
console.log('\nš Watch mode stopped');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Start watch mode
|
|
112
|
+
*/
|
|
113
|
+
export async function startWatchMode(path, options, runValidation) {
|
|
114
|
+
const watcher = new Watcher(path, options, runValidation);
|
|
115
|
+
|
|
116
|
+
// Handle graceful shutdown
|
|
117
|
+
process.on('SIGINT', () => {
|
|
118
|
+
watcher.stop();
|
|
119
|
+
process.exit(0);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
process.on('SIGTERM', () => {
|
|
123
|
+
watcher.stop();
|
|
124
|
+
process.exit(0);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
watcher.start();
|
|
128
|
+
|
|
129
|
+
// Keep process alive
|
|
130
|
+
return new Promise(() => {});
|
|
131
|
+
}
|