lsh-framework 1.1.0 → 1.2.1
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/README.md +70 -4
- package/dist/cli.js +104 -486
- package/dist/commands/doctor.js +427 -0
- package/dist/commands/init.js +371 -0
- package/dist/constants/api.js +94 -0
- package/dist/constants/commands.js +64 -0
- package/dist/constants/config.js +56 -0
- package/dist/constants/database.js +21 -0
- package/dist/constants/errors.js +79 -0
- package/dist/constants/index.js +28 -0
- package/dist/constants/paths.js +28 -0
- package/dist/constants/ui.js +73 -0
- package/dist/constants/validation.js +124 -0
- package/dist/daemon/lshd.js +11 -32
- package/dist/lib/daemon-client-helper.js +7 -4
- package/dist/lib/daemon-client.js +9 -2
- package/dist/lib/format-utils.js +163 -0
- package/dist/lib/job-manager.js +2 -1
- package/dist/lib/platform-utils.js +211 -0
- package/dist/lib/secrets-manager.js +11 -1
- package/dist/lib/string-utils.js +128 -0
- package/dist/services/daemon/daemon-registrar.js +3 -2
- package/dist/services/secrets/secrets.js +154 -30
- package/package.json +10 -74
- package/dist/app.js +0 -33
- package/dist/cicd/analytics.js +0 -261
- package/dist/cicd/auth.js +0 -269
- package/dist/cicd/cache-manager.js +0 -172
- package/dist/cicd/data-retention.js +0 -305
- package/dist/cicd/performance-monitor.js +0 -224
- package/dist/cicd/webhook-receiver.js +0 -640
- package/dist/commands/api.js +0 -346
- package/dist/commands/theme.js +0 -261
- package/dist/commands/zsh-import.js +0 -240
- package/dist/components/App.js +0 -1
- package/dist/components/Divider.js +0 -29
- package/dist/components/REPL.js +0 -43
- package/dist/components/Terminal.js +0 -232
- package/dist/components/UserInput.js +0 -30
- package/dist/daemon/api-server.js +0 -316
- package/dist/daemon/monitoring-api.js +0 -220
- package/dist/lib/api-error-handler.js +0 -185
- package/dist/lib/associative-arrays.js +0 -285
- package/dist/lib/base-api-server.js +0 -290
- package/dist/lib/brace-expansion.js +0 -160
- package/dist/lib/builtin-commands.js +0 -439
- package/dist/lib/executors/builtin-executor.js +0 -52
- package/dist/lib/extended-globbing.js +0 -411
- package/dist/lib/extended-parameter-expansion.js +0 -227
- package/dist/lib/interactive-shell.js +0 -460
- package/dist/lib/job-builtins.js +0 -582
- package/dist/lib/pathname-expansion.js +0 -216
- package/dist/lib/script-runner.js +0 -226
- package/dist/lib/shell-executor.js +0 -2504
- package/dist/lib/shell-parser.js +0 -958
- package/dist/lib/shell-types.js +0 -6
- package/dist/lib/shell.lib.js +0 -40
- package/dist/lib/theme-manager.js +0 -476
- package/dist/lib/variable-expansion.js +0 -385
- package/dist/lib/zsh-compatibility.js +0 -659
- package/dist/lib/zsh-import-manager.js +0 -707
- package/dist/lib/zsh-options.js +0 -328
- package/dist/pipeline/job-tracker.js +0 -491
- package/dist/pipeline/mcli-bridge.js +0 -309
- package/dist/pipeline/pipeline-service.js +0 -1119
- package/dist/pipeline/workflow-engine.js +0 -870
- package/dist/services/api/api.js +0 -58
- package/dist/services/api/auth.js +0 -35
- package/dist/services/api/config.js +0 -7
- package/dist/services/api/file.js +0 -22
- package/dist/services/shell/shell.js +0 -28
- package/dist/services/zapier.js +0 -16
- package/dist/simple-api-server.js +0 -148
|
@@ -1,659 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ZSH Compatibility Layer
|
|
3
|
-
* Provides compatibility with ZSH configurations and completions
|
|
4
|
-
*/
|
|
5
|
-
import * as fs from 'fs';
|
|
6
|
-
import * as path from 'path';
|
|
7
|
-
import * as os from 'os';
|
|
8
|
-
import { parseShellCommand } from './shell-parser.js';
|
|
9
|
-
import { ZshImportManager } from './zsh-import-manager.js';
|
|
10
|
-
export class ZshCompatibility {
|
|
11
|
-
executor;
|
|
12
|
-
options;
|
|
13
|
-
importManager;
|
|
14
|
-
constructor(executor, options = {}) {
|
|
15
|
-
this.executor = executor;
|
|
16
|
-
this.options = {
|
|
17
|
-
sourceZshrc: true,
|
|
18
|
-
zshrcPath: path.join(os.homedir(), '.zshrc'),
|
|
19
|
-
respectZshCompletions: true,
|
|
20
|
-
zshCompletionsPath: path.join(os.homedir(), '.zsh/completions'),
|
|
21
|
-
installPackages: true,
|
|
22
|
-
packageManager: 'npm',
|
|
23
|
-
...options,
|
|
24
|
-
};
|
|
25
|
-
// Initialize import manager with options
|
|
26
|
-
this.importManager = new ZshImportManager(executor, this.options.importOptions);
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Source ZSH configuration files (enhanced version)
|
|
30
|
-
*/
|
|
31
|
-
async sourceZshConfig() {
|
|
32
|
-
const result = await this.importManager.importZshConfig(this.options.zshrcPath);
|
|
33
|
-
return {
|
|
34
|
-
success: result.success,
|
|
35
|
-
message: result.message,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Source ZSH configuration files (legacy method for backward compatibility)
|
|
40
|
-
*/
|
|
41
|
-
async sourceZshConfigLegacy() {
|
|
42
|
-
try {
|
|
43
|
-
// Check if .zshrc exists
|
|
44
|
-
if (!fs.existsSync(this.options.zshrcPath)) {
|
|
45
|
-
return {
|
|
46
|
-
success: false,
|
|
47
|
-
message: `ZSH configuration not found: ${this.options.zshrcPath}`,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
// Read and parse .zshrc
|
|
51
|
-
const zshrcContent = fs.readFileSync(this.options.zshrcPath, 'utf8');
|
|
52
|
-
const parsedConfig = this.parseZshrc(zshrcContent);
|
|
53
|
-
// Apply compatible configurations
|
|
54
|
-
await this.applyZshConfig(parsedConfig);
|
|
55
|
-
return {
|
|
56
|
-
success: true,
|
|
57
|
-
message: `Successfully sourced ZSH configuration from ${this.options.zshrcPath}`,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
return {
|
|
62
|
-
success: false,
|
|
63
|
-
message: `Error sourcing ZSH config: ${error.message}`,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Parse .zshrc content and extract compatible configurations
|
|
69
|
-
*/
|
|
70
|
-
parseZshrc(content) {
|
|
71
|
-
const lines = content.split('\n');
|
|
72
|
-
const config = {
|
|
73
|
-
aliases: [],
|
|
74
|
-
functions: [],
|
|
75
|
-
exports: [],
|
|
76
|
-
setopts: [],
|
|
77
|
-
completions: [],
|
|
78
|
-
plugins: [],
|
|
79
|
-
};
|
|
80
|
-
let inFunction = false;
|
|
81
|
-
let currentFunction = '';
|
|
82
|
-
let functionBody = '';
|
|
83
|
-
for (const line of lines) {
|
|
84
|
-
const trimmed = line.trim();
|
|
85
|
-
// Skip comments and empty lines
|
|
86
|
-
if (trimmed.startsWith('#') || trimmed === '') {
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
// Handle function definitions
|
|
90
|
-
if (trimmed.match(/^[a-zA-Z_][a-zA-Z0-9_]*\s*\(\)\s*\{/)) {
|
|
91
|
-
inFunction = true;
|
|
92
|
-
currentFunction = trimmed.split('(')[0].trim();
|
|
93
|
-
functionBody = trimmed;
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
if (inFunction) {
|
|
97
|
-
functionBody += '\n' + line;
|
|
98
|
-
if (trimmed === '}' || trimmed.endsWith('}')) {
|
|
99
|
-
inFunction = false;
|
|
100
|
-
config.functions.push({
|
|
101
|
-
name: currentFunction,
|
|
102
|
-
body: functionBody,
|
|
103
|
-
});
|
|
104
|
-
currentFunction = '';
|
|
105
|
-
functionBody = '';
|
|
106
|
-
}
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
// Parse aliases
|
|
110
|
-
const aliasMatch = trimmed.match(/^alias\s+([^=]+)=(.+)$/);
|
|
111
|
-
if (aliasMatch) {
|
|
112
|
-
config.aliases.push({
|
|
113
|
-
name: aliasMatch[1],
|
|
114
|
-
value: aliasMatch[2].replace(/^['"]|['"]$/g, ''), // Remove quotes
|
|
115
|
-
});
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
// Parse exports
|
|
119
|
-
const exportMatch = trimmed.match(/^export\s+([^=]+)=(.+)$/);
|
|
120
|
-
if (exportMatch) {
|
|
121
|
-
config.exports.push({
|
|
122
|
-
name: exportMatch[1],
|
|
123
|
-
value: exportMatch[2].replace(/^['"]|['"]$/g, ''), // Remove quotes
|
|
124
|
-
});
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
// Parse setopt
|
|
128
|
-
const setoptMatch = trimmed.match(/^setopt\s+(.+)$/);
|
|
129
|
-
if (setoptMatch) {
|
|
130
|
-
const options = setoptMatch[1].split(/\s+/);
|
|
131
|
-
for (const option of options) {
|
|
132
|
-
config.setopts.push({
|
|
133
|
-
option: option.trim(),
|
|
134
|
-
enabled: true,
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
// Parse unsetopt
|
|
140
|
-
const unsetoptMatch = trimmed.match(/^unsetopt\s+(.+)$/);
|
|
141
|
-
if (unsetoptMatch) {
|
|
142
|
-
const options = unsetoptMatch[1].split(/\s+/);
|
|
143
|
-
for (const option of options) {
|
|
144
|
-
config.setopts.push({
|
|
145
|
-
option: option.trim(),
|
|
146
|
-
enabled: false,
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
// Parse completions
|
|
152
|
-
if (trimmed.includes('compinit') || trimmed.includes('autoload')) {
|
|
153
|
-
config.completions.push(trimmed);
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
// Parse plugins (Oh My Zsh, etc.)
|
|
157
|
-
if (trimmed.includes('plugins=') || trimmed.includes('plugin=')) {
|
|
158
|
-
const pluginMatch = trimmed.match(/plugins?=['"]([^'"]+)['"]/);
|
|
159
|
-
if (pluginMatch) {
|
|
160
|
-
const plugins = pluginMatch[1].split(/\s+/);
|
|
161
|
-
config.plugins.push(...plugins);
|
|
162
|
-
}
|
|
163
|
-
continue;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return config;
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Apply parsed ZSH configuration to LSH
|
|
170
|
-
*/
|
|
171
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
172
|
-
async applyZshConfig(config) {
|
|
173
|
-
// Apply aliases
|
|
174
|
-
for (const alias of config.aliases) {
|
|
175
|
-
try {
|
|
176
|
-
const ast = parseShellCommand(`alias ${alias.name}="${alias.value}"`);
|
|
177
|
-
await this.executor.execute(ast);
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
console.error(`Failed to apply alias ${alias.name}: ${error.message}`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
// Apply exports
|
|
184
|
-
for (const export_ of config.exports) {
|
|
185
|
-
try {
|
|
186
|
-
const ast = parseShellCommand(`export ${export_.name}="${export_.value}"`);
|
|
187
|
-
await this.executor.execute(ast);
|
|
188
|
-
}
|
|
189
|
-
catch (error) {
|
|
190
|
-
console.error(`Failed to apply export ${export_.name}: ${error.message}`);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
// Apply setopts
|
|
194
|
-
for (const setopt of config.setopts) {
|
|
195
|
-
try {
|
|
196
|
-
const command = setopt.enabled ? 'setopt' : 'unsetopt';
|
|
197
|
-
const ast = parseShellCommand(`${command} ${setopt.option}`);
|
|
198
|
-
await this.executor.execute(ast);
|
|
199
|
-
}
|
|
200
|
-
catch (error) {
|
|
201
|
-
console.error(`Failed to apply setopt ${setopt.option}: ${error.message}`);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
// Apply functions
|
|
205
|
-
for (const func of config.functions) {
|
|
206
|
-
try {
|
|
207
|
-
const ast = parseShellCommand(func.body);
|
|
208
|
-
await this.executor.execute(ast);
|
|
209
|
-
}
|
|
210
|
-
catch (error) {
|
|
211
|
-
console.error(`Failed to apply function ${func.name}: ${error.message}`);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
// Load ZSH completions
|
|
215
|
-
if (this.options.respectZshCompletions) {
|
|
216
|
-
await this.loadZshCompletions(config.completions);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Load ZSH completions
|
|
221
|
-
*/
|
|
222
|
-
async loadZshCompletions(_completionConfigs) {
|
|
223
|
-
// Common ZSH completion paths
|
|
224
|
-
const completionPaths = [
|
|
225
|
-
path.join(os.homedir(), '.zsh/completions'),
|
|
226
|
-
path.join(os.homedir(), '.oh-my-zsh/completions'),
|
|
227
|
-
'/usr/local/share/zsh/site-functions',
|
|
228
|
-
'/usr/share/zsh/site-functions',
|
|
229
|
-
'/usr/share/zsh/functions',
|
|
230
|
-
];
|
|
231
|
-
for (const completionPath of completionPaths) {
|
|
232
|
-
if (fs.existsSync(completionPath)) {
|
|
233
|
-
await this.loadCompletionsFromPath(completionPath);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
// Load Oh My Zsh completions
|
|
237
|
-
const ohMyZshPath = path.join(os.homedir(), '.oh-my-zsh');
|
|
238
|
-
if (fs.existsSync(ohMyZshPath)) {
|
|
239
|
-
await this.loadOhMyZshCompletions(ohMyZshPath);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Load completions from a specific path
|
|
244
|
-
*/
|
|
245
|
-
async loadCompletionsFromPath(completionPath) {
|
|
246
|
-
try {
|
|
247
|
-
const files = fs.readdirSync(completionPath);
|
|
248
|
-
for (const file of files) {
|
|
249
|
-
if (file.endsWith('.zsh') || file.endsWith('_completion')) {
|
|
250
|
-
const filePath = path.join(completionPath, file);
|
|
251
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
252
|
-
// Parse completion file and register completions
|
|
253
|
-
await this.parseCompletionFile(content, file);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
catch (error) {
|
|
258
|
-
console.error(`Error loading completions from ${completionPath}: ${error.message}`);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Load Oh My Zsh completions
|
|
263
|
-
*/
|
|
264
|
-
async loadOhMyZshCompletions(ohMyZshPath) {
|
|
265
|
-
const pluginsPath = path.join(ohMyZshPath, 'plugins');
|
|
266
|
-
const customPath = path.join(ohMyZshPath, 'custom');
|
|
267
|
-
// Load plugin completions
|
|
268
|
-
if (fs.existsSync(pluginsPath)) {
|
|
269
|
-
const plugins = fs.readdirSync(pluginsPath);
|
|
270
|
-
for (const plugin of plugins) {
|
|
271
|
-
const pluginPath = path.join(pluginsPath, plugin);
|
|
272
|
-
const completionPath = path.join(pluginPath, '_' + plugin);
|
|
273
|
-
if (fs.existsSync(completionPath)) {
|
|
274
|
-
await this.loadCompletionsFromPath(completionPath);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
// Load custom completions
|
|
279
|
-
if (fs.existsSync(customPath)) {
|
|
280
|
-
await this.loadCompletionsFromPath(customPath);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Parse completion file and register with LSH completion system
|
|
285
|
-
*/
|
|
286
|
-
async parseCompletionFile(content, filename) {
|
|
287
|
-
try {
|
|
288
|
-
// Extract command name from filename
|
|
289
|
-
const commandName = filename.replace(/^_/, '').replace(/\.zsh$/, '');
|
|
290
|
-
// Parse completion patterns
|
|
291
|
-
const patterns = this.extractCompletionPatterns(content);
|
|
292
|
-
// Register completion function
|
|
293
|
-
if (patterns.length > 0) {
|
|
294
|
-
this.executor.registerCompletion(commandName, async (context) => {
|
|
295
|
-
return this.generateCompletions(context, patterns);
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
catch (error) {
|
|
300
|
-
console.error(`Error parsing completion file ${filename}: ${error.message}`);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
/**
|
|
304
|
-
* Extract completion patterns from ZSH completion file
|
|
305
|
-
*/
|
|
306
|
-
extractCompletionPatterns(content) {
|
|
307
|
-
const patterns = [];
|
|
308
|
-
// Look for common completion patterns
|
|
309
|
-
const filePatterns = content.match(/compadd.*-f/g);
|
|
310
|
-
if (filePatterns) {
|
|
311
|
-
patterns.push({ type: 'files', pattern: '*' });
|
|
312
|
-
}
|
|
313
|
-
const dirPatterns = content.match(/compadd.*-d/g);
|
|
314
|
-
if (dirPatterns) {
|
|
315
|
-
patterns.push({ type: 'directories', pattern: '*/' });
|
|
316
|
-
}
|
|
317
|
-
const commandPatterns = content.match(/compadd.*-c/g);
|
|
318
|
-
if (commandPatterns) {
|
|
319
|
-
patterns.push({ type: 'commands', pattern: 'command' });
|
|
320
|
-
}
|
|
321
|
-
// Look for specific option patterns
|
|
322
|
-
const optionMatches = content.match(/--[a-zA-Z-]+/g);
|
|
323
|
-
if (optionMatches) {
|
|
324
|
-
for (const option of optionMatches) {
|
|
325
|
-
patterns.push({ type: 'options', pattern: option });
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
return patterns;
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Generate completions based on patterns
|
|
332
|
-
*/
|
|
333
|
-
async generateCompletions(context, patterns) {
|
|
334
|
-
const completions = [];
|
|
335
|
-
for (const pattern of patterns) {
|
|
336
|
-
switch (pattern.type) {
|
|
337
|
-
case 'files':
|
|
338
|
-
// Generate file completions
|
|
339
|
-
try {
|
|
340
|
-
const files = fs.readdirSync(context.cwd);
|
|
341
|
-
for (const file of files) {
|
|
342
|
-
completions.push({
|
|
343
|
-
word: file,
|
|
344
|
-
type: 'file',
|
|
345
|
-
description: 'File',
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
catch (_error) {
|
|
350
|
-
// Ignore directory read errors
|
|
351
|
-
}
|
|
352
|
-
break;
|
|
353
|
-
case 'directories':
|
|
354
|
-
// Generate directory completions
|
|
355
|
-
try {
|
|
356
|
-
const files = fs.readdirSync(context.cwd, { withFileTypes: true });
|
|
357
|
-
for (const file of files) {
|
|
358
|
-
if (file.isDirectory()) {
|
|
359
|
-
completions.push({
|
|
360
|
-
word: file.name + '/',
|
|
361
|
-
type: 'directory',
|
|
362
|
-
description: 'Directory',
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
catch (_error) {
|
|
368
|
-
// Ignore directory read errors
|
|
369
|
-
}
|
|
370
|
-
break;
|
|
371
|
-
case 'commands': {
|
|
372
|
-
// Generate command completions
|
|
373
|
-
const pathDirs = (context.env.PATH || '').split(':');
|
|
374
|
-
for (const dir of pathDirs) {
|
|
375
|
-
try {
|
|
376
|
-
const files = fs.readdirSync(dir);
|
|
377
|
-
for (const file of files) {
|
|
378
|
-
if (fs.statSync(path.join(dir, file)).isFile()) {
|
|
379
|
-
completions.push({
|
|
380
|
-
word: file,
|
|
381
|
-
type: 'command',
|
|
382
|
-
description: `Command in ${dir}`,
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
catch (_error) {
|
|
388
|
-
// Ignore directory read errors
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
break;
|
|
392
|
-
}
|
|
393
|
-
case 'options':
|
|
394
|
-
// Add specific option
|
|
395
|
-
completions.push({
|
|
396
|
-
word: pattern.pattern,
|
|
397
|
-
type: 'option',
|
|
398
|
-
description: 'Option',
|
|
399
|
-
});
|
|
400
|
-
break;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
return completions;
|
|
404
|
-
}
|
|
405
|
-
/**
|
|
406
|
-
* Install packages using package manager
|
|
407
|
-
*/
|
|
408
|
-
async installPackage(packageName) {
|
|
409
|
-
if (!this.options.installPackages) {
|
|
410
|
-
return {
|
|
411
|
-
success: false,
|
|
412
|
-
message: 'Package installation is disabled',
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
try {
|
|
416
|
-
const { spawn } = await import('child_process');
|
|
417
|
-
let command;
|
|
418
|
-
let args;
|
|
419
|
-
switch (this.options.packageManager) {
|
|
420
|
-
case 'npm':
|
|
421
|
-
command = 'npm';
|
|
422
|
-
args = ['install', '-g', packageName];
|
|
423
|
-
break;
|
|
424
|
-
case 'yarn':
|
|
425
|
-
command = 'yarn';
|
|
426
|
-
args = ['global', 'add', packageName];
|
|
427
|
-
break;
|
|
428
|
-
case 'pnpm':
|
|
429
|
-
command = 'pnpm';
|
|
430
|
-
args = ['add', '-g', packageName];
|
|
431
|
-
break;
|
|
432
|
-
case 'brew':
|
|
433
|
-
command = 'brew';
|
|
434
|
-
args = ['install', packageName];
|
|
435
|
-
break;
|
|
436
|
-
case 'apt':
|
|
437
|
-
command = 'sudo';
|
|
438
|
-
args = ['apt', 'install', packageName];
|
|
439
|
-
break;
|
|
440
|
-
case 'yum':
|
|
441
|
-
command = 'sudo';
|
|
442
|
-
args = ['yum', 'install', packageName];
|
|
443
|
-
break;
|
|
444
|
-
default:
|
|
445
|
-
return {
|
|
446
|
-
success: false,
|
|
447
|
-
message: `Unsupported package manager: ${this.options.packageManager}`,
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
return new Promise((resolve) => {
|
|
451
|
-
const child = spawn(command, args, {
|
|
452
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
453
|
-
});
|
|
454
|
-
let _stdout = '';
|
|
455
|
-
let stderr = '';
|
|
456
|
-
child.stdout?.on('data', (data) => {
|
|
457
|
-
_stdout += data.toString();
|
|
458
|
-
});
|
|
459
|
-
child.stderr?.on('data', (data) => {
|
|
460
|
-
stderr += data.toString();
|
|
461
|
-
});
|
|
462
|
-
child.on('close', (code) => {
|
|
463
|
-
if (code === 0) {
|
|
464
|
-
resolve({
|
|
465
|
-
success: true,
|
|
466
|
-
message: `Successfully installed ${packageName}`,
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
else {
|
|
470
|
-
resolve({
|
|
471
|
-
success: false,
|
|
472
|
-
message: `Failed to install ${packageName}: ${stderr}`,
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
});
|
|
476
|
-
child.on('error', (error) => {
|
|
477
|
-
resolve({
|
|
478
|
-
success: false,
|
|
479
|
-
message: `Error installing ${packageName}: ${error.message}`,
|
|
480
|
-
});
|
|
481
|
-
});
|
|
482
|
-
});
|
|
483
|
-
}
|
|
484
|
-
catch (error) {
|
|
485
|
-
return {
|
|
486
|
-
success: false,
|
|
487
|
-
message: `Error installing ${packageName}: ${error.message}`,
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* Uninstall packages using package manager
|
|
493
|
-
*/
|
|
494
|
-
async uninstallPackage(packageName) {
|
|
495
|
-
if (!this.options.installPackages) {
|
|
496
|
-
return {
|
|
497
|
-
success: false,
|
|
498
|
-
message: 'Package uninstallation is disabled',
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
try {
|
|
502
|
-
const { spawn } = await import('child_process');
|
|
503
|
-
let command;
|
|
504
|
-
let args;
|
|
505
|
-
switch (this.options.packageManager) {
|
|
506
|
-
case 'npm':
|
|
507
|
-
command = 'npm';
|
|
508
|
-
args = ['uninstall', '-g', packageName];
|
|
509
|
-
break;
|
|
510
|
-
case 'yarn':
|
|
511
|
-
command = 'yarn';
|
|
512
|
-
args = ['global', 'remove', packageName];
|
|
513
|
-
break;
|
|
514
|
-
case 'pnpm':
|
|
515
|
-
command = 'pnpm';
|
|
516
|
-
args = ['remove', '-g', packageName];
|
|
517
|
-
break;
|
|
518
|
-
case 'brew':
|
|
519
|
-
command = 'brew';
|
|
520
|
-
args = ['uninstall', packageName];
|
|
521
|
-
break;
|
|
522
|
-
case 'apt':
|
|
523
|
-
command = 'sudo';
|
|
524
|
-
args = ['apt', 'remove', packageName];
|
|
525
|
-
break;
|
|
526
|
-
case 'yum':
|
|
527
|
-
command = 'sudo';
|
|
528
|
-
args = ['yum', 'remove', packageName];
|
|
529
|
-
break;
|
|
530
|
-
default:
|
|
531
|
-
return {
|
|
532
|
-
success: false,
|
|
533
|
-
message: `Unsupported package manager: ${this.options.packageManager}`,
|
|
534
|
-
};
|
|
535
|
-
}
|
|
536
|
-
return new Promise((resolve) => {
|
|
537
|
-
const child = spawn(command, args, {
|
|
538
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
539
|
-
});
|
|
540
|
-
let _stdout = '';
|
|
541
|
-
let stderr = '';
|
|
542
|
-
child.stdout?.on('data', (data) => {
|
|
543
|
-
_stdout += data.toString();
|
|
544
|
-
});
|
|
545
|
-
child.stderr?.on('data', (data) => {
|
|
546
|
-
stderr += data.toString();
|
|
547
|
-
});
|
|
548
|
-
child.on('close', (code) => {
|
|
549
|
-
if (code === 0) {
|
|
550
|
-
resolve({
|
|
551
|
-
success: true,
|
|
552
|
-
message: `Successfully uninstalled ${packageName}`,
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
else {
|
|
556
|
-
resolve({
|
|
557
|
-
success: false,
|
|
558
|
-
message: `Failed to uninstall ${packageName}: ${stderr}`,
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
});
|
|
562
|
-
child.on('error', (error) => {
|
|
563
|
-
resolve({
|
|
564
|
-
success: false,
|
|
565
|
-
message: `Error uninstalling ${packageName}: ${error.message}`,
|
|
566
|
-
});
|
|
567
|
-
});
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
catch (error) {
|
|
571
|
-
return {
|
|
572
|
-
success: false,
|
|
573
|
-
message: `Error uninstalling ${packageName}: ${error.message}`,
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
/**
|
|
578
|
-
* Check if ZSH is available and get version
|
|
579
|
-
*/
|
|
580
|
-
async checkZshAvailability() {
|
|
581
|
-
try {
|
|
582
|
-
const { exec } = await import('child_process');
|
|
583
|
-
const { promisify } = await import('util');
|
|
584
|
-
const execAsync = promisify(exec);
|
|
585
|
-
const { stdout } = await execAsync('zsh --version');
|
|
586
|
-
const versionMatch = stdout.match(/zsh\s+([0-9.]+)/);
|
|
587
|
-
return {
|
|
588
|
-
available: true,
|
|
589
|
-
version: versionMatch ? versionMatch[1] : 'unknown',
|
|
590
|
-
path: '/bin/zsh', // This could be enhanced to find actual path
|
|
591
|
-
};
|
|
592
|
-
}
|
|
593
|
-
catch (_error) {
|
|
594
|
-
return {
|
|
595
|
-
available: false,
|
|
596
|
-
};
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
/**
|
|
600
|
-
* Migrate ZSH configuration to LSH
|
|
601
|
-
*/
|
|
602
|
-
async migrateZshConfig() {
|
|
603
|
-
try {
|
|
604
|
-
const zshrcPath = this.options.zshrcPath;
|
|
605
|
-
const lshrcPath = path.join(os.homedir(), '.lshrc');
|
|
606
|
-
if (!fs.existsSync(zshrcPath)) {
|
|
607
|
-
return {
|
|
608
|
-
success: false,
|
|
609
|
-
message: 'No ZSH configuration found to migrate',
|
|
610
|
-
};
|
|
611
|
-
}
|
|
612
|
-
// Read ZSH config
|
|
613
|
-
const zshrcContent = fs.readFileSync(zshrcPath, 'utf8');
|
|
614
|
-
// Convert to LSH format
|
|
615
|
-
const lshrcContent = this.convertZshToLsh(zshrcContent);
|
|
616
|
-
// Write LSH config
|
|
617
|
-
fs.writeFileSync(lshrcPath, lshrcContent, 'utf8');
|
|
618
|
-
return {
|
|
619
|
-
success: true,
|
|
620
|
-
message: `Successfully migrated ZSH configuration to ${lshrcPath}`,
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
catch (error) {
|
|
624
|
-
return {
|
|
625
|
-
success: false,
|
|
626
|
-
message: `Migration failed: ${error.message}`,
|
|
627
|
-
};
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
/**
|
|
631
|
-
* Convert ZSH configuration to LSH format
|
|
632
|
-
*/
|
|
633
|
-
convertZshToLsh(zshContent) {
|
|
634
|
-
let lshContent = '# LSH Configuration (migrated from ZSH)\n';
|
|
635
|
-
lshContent += '# This file was automatically generated from ~/.zshrc\n\n';
|
|
636
|
-
const lines = zshContent.split('\n');
|
|
637
|
-
for (const line of lines) {
|
|
638
|
-
const trimmed = line.trim();
|
|
639
|
-
// Skip comments and empty lines
|
|
640
|
-
if (trimmed.startsWith('#') || trimmed === '') {
|
|
641
|
-
lshContent += line + '\n';
|
|
642
|
-
continue;
|
|
643
|
-
}
|
|
644
|
-
// Convert ZSH-specific syntax to LSH
|
|
645
|
-
let convertedLine = line;
|
|
646
|
-
// Convert ZSH-specific functions to LSH format
|
|
647
|
-
if (trimmed.includes('autoload') && trimmed.includes('compinit')) {
|
|
648
|
-
convertedLine = '# ' + line + ' # Converted to LSH completion system';
|
|
649
|
-
}
|
|
650
|
-
// Convert Oh My Zsh specific syntax
|
|
651
|
-
if (trimmed.includes('ZSH_THEME=')) {
|
|
652
|
-
convertedLine = '# ' + line + ' # Use LSH prompt themes instead';
|
|
653
|
-
}
|
|
654
|
-
lshContent += convertedLine + '\n';
|
|
655
|
-
}
|
|
656
|
-
return lshContent;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
export default ZshCompatibility;
|