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.
Files changed (73) hide show
  1. package/README.md +70 -4
  2. package/dist/cli.js +104 -486
  3. package/dist/commands/doctor.js +427 -0
  4. package/dist/commands/init.js +371 -0
  5. package/dist/constants/api.js +94 -0
  6. package/dist/constants/commands.js +64 -0
  7. package/dist/constants/config.js +56 -0
  8. package/dist/constants/database.js +21 -0
  9. package/dist/constants/errors.js +79 -0
  10. package/dist/constants/index.js +28 -0
  11. package/dist/constants/paths.js +28 -0
  12. package/dist/constants/ui.js +73 -0
  13. package/dist/constants/validation.js +124 -0
  14. package/dist/daemon/lshd.js +11 -32
  15. package/dist/lib/daemon-client-helper.js +7 -4
  16. package/dist/lib/daemon-client.js +9 -2
  17. package/dist/lib/format-utils.js +163 -0
  18. package/dist/lib/job-manager.js +2 -1
  19. package/dist/lib/platform-utils.js +211 -0
  20. package/dist/lib/secrets-manager.js +11 -1
  21. package/dist/lib/string-utils.js +128 -0
  22. package/dist/services/daemon/daemon-registrar.js +3 -2
  23. package/dist/services/secrets/secrets.js +154 -30
  24. package/package.json +10 -74
  25. package/dist/app.js +0 -33
  26. package/dist/cicd/analytics.js +0 -261
  27. package/dist/cicd/auth.js +0 -269
  28. package/dist/cicd/cache-manager.js +0 -172
  29. package/dist/cicd/data-retention.js +0 -305
  30. package/dist/cicd/performance-monitor.js +0 -224
  31. package/dist/cicd/webhook-receiver.js +0 -640
  32. package/dist/commands/api.js +0 -346
  33. package/dist/commands/theme.js +0 -261
  34. package/dist/commands/zsh-import.js +0 -240
  35. package/dist/components/App.js +0 -1
  36. package/dist/components/Divider.js +0 -29
  37. package/dist/components/REPL.js +0 -43
  38. package/dist/components/Terminal.js +0 -232
  39. package/dist/components/UserInput.js +0 -30
  40. package/dist/daemon/api-server.js +0 -316
  41. package/dist/daemon/monitoring-api.js +0 -220
  42. package/dist/lib/api-error-handler.js +0 -185
  43. package/dist/lib/associative-arrays.js +0 -285
  44. package/dist/lib/base-api-server.js +0 -290
  45. package/dist/lib/brace-expansion.js +0 -160
  46. package/dist/lib/builtin-commands.js +0 -439
  47. package/dist/lib/executors/builtin-executor.js +0 -52
  48. package/dist/lib/extended-globbing.js +0 -411
  49. package/dist/lib/extended-parameter-expansion.js +0 -227
  50. package/dist/lib/interactive-shell.js +0 -460
  51. package/dist/lib/job-builtins.js +0 -582
  52. package/dist/lib/pathname-expansion.js +0 -216
  53. package/dist/lib/script-runner.js +0 -226
  54. package/dist/lib/shell-executor.js +0 -2504
  55. package/dist/lib/shell-parser.js +0 -958
  56. package/dist/lib/shell-types.js +0 -6
  57. package/dist/lib/shell.lib.js +0 -40
  58. package/dist/lib/theme-manager.js +0 -476
  59. package/dist/lib/variable-expansion.js +0 -385
  60. package/dist/lib/zsh-compatibility.js +0 -659
  61. package/dist/lib/zsh-import-manager.js +0 -707
  62. package/dist/lib/zsh-options.js +0 -328
  63. package/dist/pipeline/job-tracker.js +0 -491
  64. package/dist/pipeline/mcli-bridge.js +0 -309
  65. package/dist/pipeline/pipeline-service.js +0 -1119
  66. package/dist/pipeline/workflow-engine.js +0 -870
  67. package/dist/services/api/api.js +0 -58
  68. package/dist/services/api/auth.js +0 -35
  69. package/dist/services/api/config.js +0 -7
  70. package/dist/services/api/file.js +0 -22
  71. package/dist/services/shell/shell.js +0 -28
  72. package/dist/services/zapier.js +0 -16
  73. package/dist/simple-api-server.js +0 -148
@@ -1,240 +0,0 @@
1
- /**
2
- * ZSH Import Commands
3
- * CLI commands for importing ZSH configurations
4
- */
5
- import { ShellExecutor } from '../lib/shell-executor.js';
6
- import { ZshImportManager } from '../lib/zsh-import-manager.js';
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
- import * as os from 'os';
10
- export function registerZshImportCommands(program) {
11
- const zshCommand = program
12
- .command('zsh-import')
13
- .description('Import ZSH configurations (aliases, functions, exports)');
14
- zshCommand
15
- .command('all')
16
- .description('Import all ZSH configurations from .zshrc')
17
- .option('--skip-conflicts', 'Skip items that conflict with existing ones', false)
18
- .option('--rename-conflicts', 'Rename conflicting items with _zsh suffix', false)
19
- .option('--overwrite-conflicts', 'Overwrite existing items', false)
20
- .option('--exclude <patterns...>', 'Exclude items matching patterns (supports wildcards)')
21
- .option('--include <patterns...>', 'Only include items matching patterns')
22
- .option('--no-aliases', 'Skip importing aliases')
23
- .option('--no-exports', 'Skip importing environment variables')
24
- .option('--no-functions', 'Skip importing functions')
25
- .option('--no-options', 'Skip importing ZSH options (setopt/unsetopt)')
26
- .option('--diagnostic-log <path>', 'Path to diagnostic log file')
27
- .action(async (options) => {
28
- const executor = new ShellExecutor();
29
- // Determine conflict resolution strategy
30
- let conflictResolution = 'skip';
31
- if (options.renameConflicts)
32
- conflictResolution = 'rename';
33
- if (options.overwriteConflicts)
34
- conflictResolution = 'overwrite';
35
- const importOptions = {
36
- conflictResolution,
37
- includeAliases: options.aliases !== false,
38
- includeExports: options.exports !== false,
39
- includeFunctions: options.functions !== false,
40
- includeOptions: options.options !== false,
41
- includePlugins: true,
42
- excludePatterns: options.exclude || [],
43
- includePatterns: options.include || [],
44
- diagnosticLog: options.diagnosticLog,
45
- };
46
- const manager = new ZshImportManager(executor, importOptions);
47
- const result = await manager.importZshConfig();
48
- console.log(result.message);
49
- if (result.diagnostics.filter(d => d.status === 'failed').length > 0) {
50
- console.log(`\n⚠️ Some imports failed. Check diagnostic log: ${importOptions.diagnosticLog || '~/.lsh/zsh-import.log'}`);
51
- }
52
- process.exit(result.success ? 0 : 1);
53
- });
54
- zshCommand
55
- .command('aliases')
56
- .description('Import only aliases from .zshrc')
57
- .option('--exclude <patterns...>', 'Exclude aliases matching patterns')
58
- .option('--include <patterns...>', 'Only include aliases matching patterns')
59
- .option('--rename-conflicts', 'Rename conflicting aliases')
60
- .action(async (options) => {
61
- const executor = new ShellExecutor();
62
- const importOptions = {
63
- includeAliases: true,
64
- includeExports: false,
65
- includeFunctions: false,
66
- includeOptions: false,
67
- includePlugins: false,
68
- conflictResolution: options.renameConflicts ? 'rename' : 'skip',
69
- excludePatterns: options.exclude || [],
70
- includePatterns: options.include || [],
71
- };
72
- const manager = new ZshImportManager(executor, importOptions);
73
- const result = await manager.importZshConfig();
74
- console.log(result.message);
75
- process.exit(result.success ? 0 : 1);
76
- });
77
- zshCommand
78
- .command('exports')
79
- .description('Import only environment variables from .zshrc')
80
- .option('--exclude <patterns...>', 'Exclude exports matching patterns')
81
- .option('--include <patterns...>', 'Only include exports matching patterns')
82
- .action(async (options) => {
83
- const executor = new ShellExecutor();
84
- const importOptions = {
85
- includeAliases: false,
86
- includeExports: true,
87
- includeFunctions: false,
88
- includeOptions: false,
89
- includePlugins: false,
90
- excludePatterns: options.exclude || [],
91
- includePatterns: options.include || [],
92
- };
93
- const manager = new ZshImportManager(executor, importOptions);
94
- const result = await manager.importZshConfig();
95
- console.log(result.message);
96
- process.exit(result.success ? 0 : 1);
97
- });
98
- zshCommand
99
- .command('functions')
100
- .description('Import only functions from .zshrc')
101
- .option('--exclude <patterns...>', 'Exclude functions matching patterns')
102
- .option('--include <patterns...>', 'Only include functions matching patterns')
103
- .option('--rename-conflicts', 'Rename conflicting functions')
104
- .action(async (options) => {
105
- const executor = new ShellExecutor();
106
- const importOptions = {
107
- includeAliases: false,
108
- includeExports: false,
109
- includeFunctions: true,
110
- includeOptions: false,
111
- includePlugins: false,
112
- conflictResolution: options.renameConflicts ? 'rename' : 'skip',
113
- excludePatterns: options.exclude || [],
114
- includePatterns: options.include || [],
115
- };
116
- const manager = new ZshImportManager(executor, importOptions);
117
- const result = await manager.importZshConfig();
118
- console.log(result.message);
119
- process.exit(result.success ? 0 : 1);
120
- });
121
- zshCommand
122
- .command('setup-auto-import')
123
- .description('Configure auto-import of ZSH config on LSH startup')
124
- .option('--disable', 'Disable auto-import')
125
- .option('--aliases-only', 'Only auto-import aliases')
126
- .option('--exports-only', 'Only auto-import exports')
127
- .option('--rename-conflicts', 'Auto-rename conflicts')
128
- .action(async (options) => {
129
- const lshrcPath = path.join(os.homedir(), '.lshrc');
130
- if (options.disable) {
131
- // Remove auto-import from .lshrc
132
- if (fs.existsSync(lshrcPath)) {
133
- let content = fs.readFileSync(lshrcPath, 'utf8');
134
- content = content.replace(/# ZSH Auto-Import[\s\S]*?# End ZSH Auto-Import\n*/g, '');
135
- fs.writeFileSync(lshrcPath, content, 'utf8');
136
- console.log('✅ Auto-import disabled');
137
- }
138
- process.exit(0);
139
- return;
140
- }
141
- // Generate auto-import configuration
142
- const importCommand = 'zsh-source';
143
- const options_list = [];
144
- if (options.aliasesOnly) {
145
- options_list.push('--no-exports', '--no-functions', '--no-options');
146
- }
147
- else if (options.exportsOnly) {
148
- options_list.push('--no-aliases', '--no-functions', '--no-options');
149
- }
150
- if (options.renameConflicts) {
151
- options_list.push('--rename-conflicts');
152
- }
153
- const autoImportConfig = `
154
- # ZSH Auto-Import
155
- # Automatically import ZSH configurations on startup
156
- ${importCommand}${options_list.length > 0 ? ' ' + options_list.join(' ') : ''}
157
- # End ZSH Auto-Import
158
- `;
159
- // Read or create .lshrc
160
- let lshrcContent = '';
161
- if (fs.existsSync(lshrcPath)) {
162
- lshrcContent = fs.readFileSync(lshrcPath, 'utf8');
163
- // Remove existing auto-import config
164
- lshrcContent = lshrcContent.replace(/# ZSH Auto-Import[\s\S]*?# End ZSH Auto-Import\n*/g, '');
165
- }
166
- // Append new auto-import config
167
- lshrcContent += autoImportConfig;
168
- fs.writeFileSync(lshrcPath, lshrcContent, 'utf8');
169
- console.log('✅ Auto-import configured in ~/.lshrc');
170
- console.log(` ZSH config will be imported automatically on LSH startup`);
171
- console.log(`\nConfiguration added:`);
172
- console.log(autoImportConfig.trim());
173
- process.exit(0);
174
- });
175
- zshCommand
176
- .command('status')
177
- .description('Show ZSH import status and diagnostics')
178
- .action(async () => {
179
- const executor = new ShellExecutor();
180
- const manager = new ZshImportManager(executor);
181
- const stats = manager.getLastImportStats();
182
- if (!stats) {
183
- console.log('No ZSH import has been performed yet.');
184
- console.log('\nRun one of these commands to import:');
185
- console.log(' lsh zsh-import all # Import everything');
186
- console.log(' lsh zsh-import aliases # Import only aliases');
187
- console.log(' lsh zsh-import exports # Import only exports');
188
- console.log(' lsh zsh-import functions # Import only functions');
189
- process.exit(0);
190
- return;
191
- }
192
- console.log('📊 Last ZSH Import Status:\n');
193
- console.log(` Total Items: ${stats.total}`);
194
- console.log(` ✅ Succeeded: ${stats.succeeded}`);
195
- console.log(` ❌ Failed: ${stats.failed}`);
196
- console.log(` ⏭️ Skipped: ${stats.skipped}`);
197
- console.log(` ⚠️ Conflicts: ${stats.conflicts}\n`);
198
- if (stats.byType) {
199
- console.log('By Type:');
200
- for (const [type, typeStats] of Object.entries(stats.byType)) {
201
- const ts = typeStats;
202
- console.log(` ${type.padEnd(12)}: ${ts.succeeded}/${ts.total} succeeded, ${ts.failed} failed, ${ts.skipped} skipped`);
203
- }
204
- }
205
- const diagnosticLog = path.join(os.homedir(), '.lsh', 'zsh-import.log');
206
- if (fs.existsSync(diagnosticLog)) {
207
- console.log(`\nDiagnostic log: ${diagnosticLog}`);
208
- console.log('Run: cat ' + diagnosticLog + ' | tail -50');
209
- }
210
- process.exit(0);
211
- });
212
- zshCommand
213
- .command('diagnose')
214
- .description('Show failed imports from diagnostic log')
215
- .option('-n <number>', 'Number of recent entries to show', '20')
216
- .action((options) => {
217
- const diagnosticLog = path.join(os.homedir(), '.lsh', 'zsh-import.log');
218
- if (!fs.existsSync(diagnosticLog)) {
219
- console.log('No diagnostic log found.');
220
- console.log('Import ZSH config first: lsh zsh-import all');
221
- process.exit(1);
222
- return;
223
- }
224
- const content = fs.readFileSync(diagnosticLog, 'utf8');
225
- const lines = content.trim().split('\n');
226
- const numLines = parseInt(options.n, 10) || 20;
227
- const recentLines = lines.slice(-numLines);
228
- console.log(`📋 Recent ZSH Import Diagnostics (last ${numLines} entries):\n`);
229
- const failedLines = recentLines.filter(line => line.includes('failed') || line.includes('disabled'));
230
- if (failedLines.length === 0) {
231
- console.log('✅ No failed imports found!');
232
- }
233
- else {
234
- failedLines.forEach(line => {
235
- console.log(' ' + line);
236
- });
237
- }
238
- process.exit(0);
239
- });
240
- }
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,29 +0,0 @@
1
- // Divider
2
- import { Text } from 'ink';
3
- import React from 'react';
4
- import stringWidth from 'string-width';
5
- export const Divider = ({ title, width, padding, titlePadding, titleColor, dividerChar }) => {
6
- const getSideDividerWidth = (width, titleWidth) => (width - titleWidth) / 2;
7
- const getNumberOfCharsPerWidth = (char, width) => width / stringWidth(char);
8
- const PAD = ' ';
9
- const titleString = title ? `${PAD.repeat(titlePadding) + title + PAD.repeat(titlePadding)}` : '';
10
- const titleWidth = stringWidth(titleString);
11
- const dividerWidth = getSideDividerWidth(width, titleWidth);
12
- const numberOfCharsPerSide = getNumberOfCharsPerWidth(dividerChar, dividerWidth);
13
- const dividerSideString = dividerChar.repeat(numberOfCharsPerSide);
14
- const paddingString = PAD.repeat(padding);
15
- return (React.createElement(React.Fragment, null,
16
- paddingString,
17
- React.createElement(Text, { color: "grey" }, dividerSideString),
18
- React.createElement(Text, { color: titleColor }, titleString),
19
- React.createElement(Text, { color: "grey" }, dividerSideString),
20
- paddingString));
21
- };
22
- Divider.defaultProps = {
23
- title: "LSH REPL",
24
- width: 60,
25
- padding: 0,
26
- titlePadding: 1,
27
- titleColor: 'white',
28
- dividerChar: '~'
29
- };
@@ -1,43 +0,0 @@
1
- import chalk from 'chalk';
2
- import hljs from 'highlightjs';
3
- import { Box, Text, useApp, useInput } from 'ink';
4
- import TextInput from 'ink-text-input';
5
- import React, { useState } from 'react';
6
- import vm from 'vm';
7
- // REPL Component
8
- export const REPL = () => {
9
- const { exit } = useApp();
10
- const [input, setInput] = useState('');
11
- const [history, setHistory] = useState([]);
12
- useInput((input, key) => {
13
- if (key.escape) {
14
- exit();
15
- }
16
- });
17
- const handleInput = (value) => {
18
- setInput(value);
19
- };
20
- const executeCommand = () => {
21
- try {
22
- const script = new vm.Script(input);
23
- const context = vm.createContext(global);
24
- const result = script.runInContext(context);
25
- const output = result === undefined || result === null ? 'undefined' : result.toString();
26
- const highlightedOutput = chalk.green(highlight(output));
27
- setHistory([...history, `> ${chalk.yellow(highlight(input))}`, `= ${highlightedOutput}`]);
28
- }
29
- catch (err) {
30
- setHistory([...history, `> ${chalk.yellow(highlight(input))}`, `! Error: ${chalk.red(err.message)}`]);
31
- }
32
- finally {
33
- setInput('');
34
- }
35
- };
36
- return (React.createElement(Box, { flexDirection: "column", flexGrow: 1 },
37
- React.createElement(Box, { flexGrow: 1, flexDirection: "column", borderColor: "cyan", borderStyle: "round" },
38
- React.createElement(Box, { marginBottom: 1, flexDirection: "column" }, history.map((entry, index) => (React.createElement(Text, { key: index }, entry)))),
39
- React.createElement(TextInput, { value: input, onChange: handleInput, onSubmit: executeCommand, placeholder: "Type JavaScript code and press Enter..." }))));
40
- };
41
- const highlight = (code) => {
42
- return hljs.highlight(code, { language: 'javascript' }).value;
43
- };
@@ -1,232 +0,0 @@
1
- import { Box, Text, useApp, useInput } from "ink";
2
- import TextInput from "ink-text-input";
3
- import { stdout } from "process";
4
- import React, { useEffect, useState } from "react";
5
- import { Script, createContext } from "vm";
6
- import { shell_exec } from "../lib/shell.lib.js";
7
- import { parseShellCommand } from "../lib/shell-parser.js";
8
- import { ShellExecutor } from "../lib/shell-executor.js";
9
- export const Terminal = () => {
10
- const [input, setInput] = useState("");
11
- const [lines, setLines] = useState([]);
12
- const [_mode, _setMode] = useState("auto"); // auto, js, shell
13
- const [workingDir, setWorkingDir] = useState(process.cwd());
14
- const [shellExecutor] = useState(() => new ShellExecutor());
15
- const { exit } = useApp();
16
- // Check if raw mode is supported synchronously
17
- const isRawModeSupported = process.stdin.isTTY && process.stdin.setRawMode !== undefined;
18
- // Detect if input is a shell command or JavaScript
19
- const detectInputType = (input) => {
20
- const trimmed = input.trim();
21
- // Check for common shell commands
22
- const shellCommands = ["ls", "cd", "pwd", "mkdir", "rm", "cp", "mv", "cat", "grep", "find", "ps", "kill", "chmod", "chown", "git", "npm", "node", "python", "curl", "wget"];
23
- const firstWord = trimmed.split(' ')[0];
24
- // Check for JavaScript patterns
25
- const jsPatterns = [
26
- /^(const|let|var|function|class|\{|\[|if|for|while|try|async|await)/,
27
- /^[a-zA-Z_$][a-zA-Z0-9_$]*\s*[=]/,
28
- /\.(map|filter|reduce|forEach)/,
29
- /^Math\.|^JSON\.|^console\./,
30
- /^[0-9]+(\.[0-9]+)?(\s*[+\-*/])/
31
- ];
32
- // Force modes
33
- if (trimmed.startsWith("js:"))
34
- return "js";
35
- if (trimmed.startsWith("sh:") || trimmed.startsWith("$"))
36
- return "shell";
37
- // JavaScript detection
38
- if (jsPatterns.some(pattern => pattern.test(trimmed)))
39
- return "js";
40
- // Shell command detection
41
- if (shellCommands.includes(firstWord))
42
- return "shell";
43
- // Default to shell for most other cases
44
- return "shell";
45
- };
46
- // Execute JavaScript code in a VM context with enhanced features
47
- const executeScript = async (input) => {
48
- try {
49
- let code = input;
50
- if (code.startsWith("js:"))
51
- code = code.substring(3).trim();
52
- // Create context with useful globals
53
- const context = createContext({
54
- console,
55
- process,
56
- __dirname: workingDir,
57
- __filename: '',
58
- global,
59
- Buffer,
60
- setTimeout,
61
- setInterval,
62
- clearTimeout,
63
- clearInterval,
64
- shell_exec, // Make shell_exec available in JS context
65
- sh: shell_exec, // Short alias
66
- });
67
- const script = new Script(code);
68
- const result = script.runInContext(context);
69
- return `${result !== undefined ? result : '(undefined)'}`;
70
- }
71
- catch (error) {
72
- return `JS Error: ${error.message}`;
73
- }
74
- };
75
- // Execute shell command using POSIX parser and executor
76
- const executeShell = async (input) => {
77
- try {
78
- let command = input.trim();
79
- if (command.startsWith("sh:"))
80
- command = command.substring(3).trim();
81
- if (command.startsWith("$"))
82
- command = command.substring(1).trim();
83
- // Parse the command using POSIX grammar
84
- const ast = parseShellCommand(command);
85
- // Execute the parsed command
86
- const result = await shellExecutor.execute(ast);
87
- // Update working directory from executor context
88
- const context = shellExecutor.getContext();
89
- if (context.cwd !== workingDir) {
90
- setWorkingDir(context.cwd);
91
- }
92
- if (!result.success && result.stderr) {
93
- return `Shell Error: ${result.stderr}`;
94
- }
95
- let output = "";
96
- if (result.stdout)
97
- output += result.stdout;
98
- if (result.stderr)
99
- output += (output ? "\n" : "") + `stderr: ${result.stderr}`;
100
- return output || "(no output)";
101
- }
102
- catch (error) {
103
- // Fallback to old shell execution for unparseable commands
104
- try {
105
- let command = input.trim();
106
- if (command.startsWith("sh:"))
107
- command = command.substring(3).trim();
108
- if (command.startsWith("$"))
109
- command = command.substring(1).trim();
110
- const result = await shell_exec(command);
111
- if (result.error) {
112
- return `Shell Error: ${result.error}`;
113
- }
114
- let output = "";
115
- if (result.stdout)
116
- output += result.stdout;
117
- if (result.stderr)
118
- output += (output ? "\n" : "") + `stderr: ${result.stderr}`;
119
- return output || "(no output)";
120
- }
121
- catch (_fallbackError) {
122
- return `Shell Error: ${error.message}`;
123
- }
124
- }
125
- };
126
- // Handle input submission
127
- const handleSubmit = async () => {
128
- if (!input.trim())
129
- return;
130
- const inputType = detectInputType(input);
131
- const prompt = `[${workingDir.split('/').pop() || '/'}] ${inputType === 'js' ? 'js>' : '$'} ${input}`;
132
- setLines(prev => [...prev, prompt]);
133
- try {
134
- let result;
135
- if (inputType === "js") {
136
- result = await executeScript(input);
137
- }
138
- else {
139
- result = await executeShell(input);
140
- }
141
- // Add result with proper formatting and spacing
142
- setLines(prev => [...prev, result, ""]);
143
- }
144
- catch (error) {
145
- // Add error and a blank line for spacing
146
- setLines(prev => [...prev, `Error: ${error.message}`, ""]);
147
- }
148
- setInput("");
149
- };
150
- // Handle resizing of the terminal
151
- const [size, setSize] = useState({
152
- columns: stdout.columns,
153
- rows: stdout.rows,
154
- });
155
- useEffect(() => {
156
- const handleResize = () => {
157
- setSize({
158
- columns: stdout.columns,
159
- rows: stdout.rows,
160
- });
161
- };
162
- stdout.on("resize", handleResize);
163
- return () => {
164
- stdout.off("resize", handleResize);
165
- };
166
- }, []);
167
- // Only use input if raw mode is supported
168
- const [_isInteractive, setIsInteractive] = useState(false);
169
- useEffect(() => {
170
- // Check if raw mode is supported
171
- setIsInteractive(process.stdin.isTTY && process.stdin.setRawMode !== undefined);
172
- }, []);
173
- useInput((input, key) => {
174
- if (!isRawModeSupported)
175
- return;
176
- if (key.return) {
177
- handleSubmit();
178
- }
179
- else if (key.ctrl && input === "c") {
180
- exit();
181
- }
182
- });
183
- // Initialize with welcome message
184
- useEffect(() => {
185
- setLines([
186
- "🚀 LSH Interactive Shell",
187
- "Mix shell commands and JavaScript seamlessly!",
188
- "Examples:",
189
- " ls -la (shell command)",
190
- " 2 + 2 (JavaScript expression)",
191
- " js: console.log('Hello') (force JS mode)",
192
- " sh: echo 'Hi' (force shell mode)",
193
- " await sh('ls') (call shell from JS)",
194
- "---"
195
- ]);
196
- }, []);
197
- const currentDir = workingDir.split('/').pop() || '/';
198
- const nextInputType = detectInputType(input);
199
- const promptSymbol = nextInputType === 'js' ? 'js>' : '$';
200
- if (!isRawModeSupported) {
201
- return (React.createElement(Box, { flexDirection: "column", padding: 1 },
202
- React.createElement(Text, { color: "red", bold: true }, "\u26A0\uFE0F Interactive mode not supported"),
203
- React.createElement(Text, { color: "yellow" }, "Raw mode is not supported in this environment."),
204
- React.createElement(Text, { color: "gray" }, "To use the interactive REPL, run this command in a proper terminal:"),
205
- React.createElement(Text, { color: "cyan" }, " npm start repl"),
206
- React.createElement(Text, { color: "gray" }, "or"),
207
- React.createElement(Text, { color: "cyan" }, " node dist/app.js repl"),
208
- React.createElement(Text, { color: "gray" }, "For testing, use the shell lib functions directly in your Node.js code.")));
209
- }
210
- return (React.createElement(Box, { flexDirection: "column", padding: 1, width: size.columns, height: size.rows },
211
- React.createElement(Box, { flexDirection: "column", width: "100%" },
212
- React.createElement(Text, { color: "cyan", bold: true }, "LSH - Interactive Shell with JavaScript"),
213
- React.createElement(Text, { color: "gray" },
214
- "Current directory: ",
215
- workingDir),
216
- React.createElement(Text, { color: "gray" },
217
- "Mode: Auto-detect (",
218
- nextInputType === 'js' ? 'JavaScript' : 'Shell',
219
- ")"),
220
- React.createElement(Box, { borderStyle: "round", borderColor: "blue", paddingX: 1, marginY: 1, height: size.rows - 8, flexDirection: "column", width: "100%" },
221
- React.createElement(Box, { flexDirection: "column", flexGrow: 1, overflowY: "hidden", width: "100%" }, lines.slice(Math.max(0, lines.length - (size.rows - 15))).map((line, index) => (React.createElement(Text, { key: index, wrap: "wrap", width: size.columns - 6 }, line)))),
222
- React.createElement(Box, { flexDirection: "row", marginTop: 1, width: "100%" },
223
- React.createElement(Text, { color: "green" },
224
- "[",
225
- currentDir,
226
- "] ",
227
- promptSymbol,
228
- " "),
229
- React.createElement(Box, { flexGrow: 1, width: size.columns - currentDir.length - 8 },
230
- React.createElement(TextInput, { value: input, onChange: setInput, placeholder: "Enter shell command or JavaScript..." }))))),
231
- React.createElement(Text, { color: "grey" }, "Press Ctrl+C to exit. Use js: or sh: to force execution mode.")));
232
- };
@@ -1,30 +0,0 @@
1
- import { useInput, useStdout } from 'ink';
2
- import React, { useState } from 'react';
3
- import { Divider } from './Divider.js';
4
- export function UserInput({ ..._props }) {
5
- const [_feature, _setFeature] = useState('');
6
- const [_readData, _setReadData] = useState([]);
7
- const [_writeData, _setWriteData] = useState([]);
8
- const [_userInput, _setUserInput] = useState('');
9
- const [_name, _setName] = useState('');
10
- const _handleSubmit = (_query) => {
11
- // Do something with query
12
- console.log(_query);
13
- _setUserInput('');
14
- };
15
- const { stdout: _stdout, write: _write } = useStdout();
16
- const _handleChange = (_query) => {
17
- };
18
- useInput((input, _key) => {
19
- console.log(input);
20
- // console.log(key);
21
- if (input === 'q') {
22
- // Exit program
23
- }
24
- ;
25
- });
26
- const input = (React.createElement(React.Fragment, null,
27
- React.createElement(Divider, null),
28
- React.createElement(Divider, null)));
29
- return input;
30
- }