Repository navigation
Expand file tree
/
Copy pathcli.js
More file actions
executable file
·142 lines (118 loc) · 4.87 KB
/
Copy pathcli.js
File metadata and controls
executable file
·142 lines (118 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/env node
const { colorize } = require('./lib/core/colors');
const { ErrorHandler } = require('./lib/core/error-handler');
const { config } = require('./lib/core/config');
const { parseCopyArgs, handleCopyCommand } = require('./commands/copy');
const { parseListArgs, handleListCommand } = require('./commands/list');
const { parseInspectArgs, handleInspectCommand } = require('./commands/inspect');
const { parseInteractiveArgs, handleInteractiveCommand } = require('./commands/interactive');
const debugLogger = require('./lib/core/debug-logger');
// Global error handlers for debugging
process.on('uncaughtException', (error) => {
debugLogger.error('CLI', 'UNCAUGHT EXCEPTION', error);
// Don't pollute interactive mode with debug output
const isInteractive = debugLogger.isInteractiveMode();
if (!isInteractive) {
console.error('\x1b[31mUNCAUGHT EXCEPTION:\x1b[0m', error.message);
console.error('Stack:', error.stack);
if (process.env.LOWKEY_DEBUG === 'true') {
console.error('Debug log saved to:', debugLogger.getLogPath());
}
}
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
debugLogger.error('CLI', 'UNHANDLED REJECTION', reason);
// Don't pollute interactive mode with debug output
const isInteractive = debugLogger.isInteractiveMode();
if (!isInteractive) {
console.error('\x1b[31mUNHANDLED REJECTION:\x1b[0m', reason);
console.error('Promise:', promise);
if (process.env.LOWKEY_DEBUG === 'true') {
console.error('Debug log saved to:', debugLogger.getLogPath());
}
}
process.exit(1);
});
function parseArgs() {
const args = process.argv.slice(2);
if (args.length === 0) {
showHelp();
process.exit(1);
}
const command = args[0];
if (command === '--version' || command === '-v') {
showVersion();
process.exit(0);
} else if (command === '--help' || command === '-h') {
showHelp();
process.exit(0);
}
if (!['copy', 'list', 'inspect', 'interactive', 'x'].includes(command)) {
console.error(colorize(`Error: Unknown command '${command}'. Available commands: copy, list, inspect, interactive (x)`, 'red'));
showHelp();
process.exit(1);
}
if (command === 'copy') {
return parseCopyArgs(args.slice(1));
} else if (command === 'list') {
return parseListArgs(args.slice(1));
} else if (command === 'inspect') {
return parseInspectArgs(args.slice(1));
} else if (command === 'interactive' || command === 'x') {
return parseInteractiveArgs(args.slice(1));
}
}
function showVersion() {
const packageJson = require('./package.json');
console.log(`lowkey v${packageJson.version}`);
}
function showHelp() {
console.log(`
${colorize('Usage:', 'cyan')} lowkey <command> [options]
${colorize('Commands:', 'cyan')}
${colorize('copy', 'bold')} Copy secrets between storage types
${colorize('list', 'bold')} List available secrets for each storage type
${colorize('inspect', 'bold')} Show help for inspecting secrets
${colorize('interactive, x', 'bold')} Interactive secret browser and inspector
${colorize('Global Options:', 'cyan')}
${colorize('--version, -v', 'bold')} Show version number
${colorize('--help, -h', 'bold')} Show this help message
Use ${colorize("'lowkey <command> --help'", 'bold')} for more information about a command.
${colorize('Examples:', 'cyan')}
lowkey ${colorize('copy', 'bold')} --input-type env --input-name .env --output-type json
lowkey ${colorize('list', 'bold')} --type aws-secrets-manager --region us-east-1
lowkey ${colorize('list', 'bold')} --type env --path ./config
lowkey ${colorize('interactive', 'bold')} ${colorize('# Interactive secret browser', 'gray')}
lowkey ${colorize('x', 'bold')} ${colorize('# Same as interactive (alias)', 'gray')}
lowkey ${colorize('inspect', 'bold')} --help ${colorize('# Show inspect help', 'gray')}
`);
}
async function main() {
// Initialize configuration early
config.initialize();
debugLogger.log('CLI', 'Starting lowkey', { argv: process.argv });
try {
const options = parseArgs();
debugLogger.log('CLI', 'Parsed options', options);
if (options.command === 'copy') {
await handleCopyCommand(options);
} else if (options.command === 'list') {
await handleListCommand(options);
} else if (options.command === 'inspect') {
await handleInspectCommand(options);
} else if (options.command === 'interactive') {
await handleInteractiveCommand(options);
} else {
throw new Error(`Unknown command: ${options.command}`);
}
// Ensure the process exits cleanly
process.exit(0);
} catch (error) {
console.error(colorize(`Error: ${error.message}`, 'red'));
process.exit(1);
}
}
if (require.main === module) {
main();
}