lsh-framework 1.2.0 → 1.3.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.
Files changed (74) hide show
  1. package/README.md +40 -3
  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/fuzzy-match.js +123 -0
  19. package/dist/lib/job-manager.js +2 -1
  20. package/dist/lib/platform-utils.js +211 -0
  21. package/dist/lib/secrets-manager.js +11 -1
  22. package/dist/lib/string-utils.js +128 -0
  23. package/dist/services/daemon/daemon-registrar.js +3 -2
  24. package/dist/services/secrets/secrets.js +119 -59
  25. package/package.json +10 -74
  26. package/dist/app.js +0 -33
  27. package/dist/cicd/analytics.js +0 -261
  28. package/dist/cicd/auth.js +0 -269
  29. package/dist/cicd/cache-manager.js +0 -172
  30. package/dist/cicd/data-retention.js +0 -305
  31. package/dist/cicd/performance-monitor.js +0 -224
  32. package/dist/cicd/webhook-receiver.js +0 -640
  33. package/dist/commands/api.js +0 -346
  34. package/dist/commands/theme.js +0 -261
  35. package/dist/commands/zsh-import.js +0 -240
  36. package/dist/components/App.js +0 -1
  37. package/dist/components/Divider.js +0 -29
  38. package/dist/components/REPL.js +0 -43
  39. package/dist/components/Terminal.js +0 -232
  40. package/dist/components/UserInput.js +0 -30
  41. package/dist/daemon/api-server.js +0 -316
  42. package/dist/daemon/monitoring-api.js +0 -220
  43. package/dist/lib/api-error-handler.js +0 -185
  44. package/dist/lib/associative-arrays.js +0 -285
  45. package/dist/lib/base-api-server.js +0 -290
  46. package/dist/lib/brace-expansion.js +0 -160
  47. package/dist/lib/builtin-commands.js +0 -439
  48. package/dist/lib/executors/builtin-executor.js +0 -52
  49. package/dist/lib/extended-globbing.js +0 -411
  50. package/dist/lib/extended-parameter-expansion.js +0 -227
  51. package/dist/lib/interactive-shell.js +0 -460
  52. package/dist/lib/job-builtins.js +0 -582
  53. package/dist/lib/pathname-expansion.js +0 -216
  54. package/dist/lib/script-runner.js +0 -226
  55. package/dist/lib/shell-executor.js +0 -2504
  56. package/dist/lib/shell-parser.js +0 -958
  57. package/dist/lib/shell-types.js +0 -6
  58. package/dist/lib/shell.lib.js +0 -40
  59. package/dist/lib/theme-manager.js +0 -476
  60. package/dist/lib/variable-expansion.js +0 -385
  61. package/dist/lib/zsh-compatibility.js +0 -659
  62. package/dist/lib/zsh-import-manager.js +0 -707
  63. package/dist/lib/zsh-options.js +0 -328
  64. package/dist/pipeline/job-tracker.js +0 -491
  65. package/dist/pipeline/mcli-bridge.js +0 -309
  66. package/dist/pipeline/pipeline-service.js +0 -1119
  67. package/dist/pipeline/workflow-engine.js +0 -870
  68. package/dist/services/api/api.js +0 -58
  69. package/dist/services/api/auth.js +0 -35
  70. package/dist/services/api/config.js +0 -7
  71. package/dist/services/api/file.js +0 -22
  72. package/dist/services/shell/shell.js +0 -28
  73. package/dist/services/zapier.js +0 -16
  74. package/dist/simple-api-server.js +0 -148
@@ -1,216 +0,0 @@
1
- /**
2
- * POSIX Pathname Expansion Implementation
3
- * Implements POSIX.1-2017 Section 2.13 Pathname Expansion (Globbing)
4
- */
5
- import * as fs from 'fs';
6
- import * as path from 'path';
7
- export class PathnameExpander {
8
- cwd;
9
- constructor(cwd = process.cwd()) {
10
- this.cwd = cwd;
11
- }
12
- async expandPathnames(pattern, options = {}) {
13
- // If no glob characters, return as-is
14
- if (!this.containsGlobChars(pattern)) {
15
- return [pattern];
16
- }
17
- // Handle tilde expansion first
18
- const expandedPattern = this.expandTilde(pattern);
19
- // Perform pathname expansion
20
- return this.glob(expandedPattern, options);
21
- }
22
- containsGlobChars(str) {
23
- // Check for unescaped glob characters
24
- return /[*?[\]{}~]/.test(str);
25
- }
26
- expandTilde(pattern) {
27
- if (pattern.startsWith('~/')) {
28
- const homeDir = process.env.HOME || '/';
29
- return path.join(homeDir, pattern.slice(2));
30
- }
31
- if (pattern === '~') {
32
- return process.env.HOME || '/';
33
- }
34
- return pattern;
35
- }
36
- async glob(pattern, options) {
37
- const baseCwd = options.cwd || this.cwd;
38
- // Handle absolute vs relative paths
39
- const isAbsolute = path.isAbsolute(pattern);
40
- const searchBase = isAbsolute ? '/' : baseCwd;
41
- const relativePath = isAbsolute ? pattern.slice(1) : pattern;
42
- // Split pattern into segments
43
- const segments = relativePath.split('/').filter(seg => seg.length > 0);
44
- if (segments.length === 0) {
45
- return [searchBase];
46
- }
47
- // Start recursive matching
48
- const results = await this.matchSegments(searchBase, segments, options);
49
- // Sort results for consistent output
50
- return results.sort();
51
- }
52
- async matchSegments(currentPath, remainingSegments, options) {
53
- if (remainingSegments.length === 0) {
54
- return [currentPath];
55
- }
56
- const [currentSegment, ...restSegments] = remainingSegments;
57
- const results = [];
58
- try {
59
- const entries = await fs.promises.readdir(currentPath, { withFileTypes: true });
60
- for (const entry of entries) {
61
- // Skip hidden files unless explicitly included
62
- if (!options.includeHidden && entry.name.startsWith('.')) {
63
- continue;
64
- }
65
- // Check if this entry matches the current segment pattern
66
- if (this.matchSegment(entry.name, currentSegment)) {
67
- const fullPath = path.join(currentPath, entry.name);
68
- if (restSegments.length === 0) {
69
- // This is the final segment, add to results
70
- results.push(fullPath);
71
- }
72
- else if (entry.isDirectory()) {
73
- // Recurse into directory for remaining segments
74
- const subResults = await this.matchSegments(fullPath, restSegments, options);
75
- results.push(...subResults);
76
- }
77
- }
78
- }
79
- }
80
- catch (_error) {
81
- // Directory doesn't exist or not readable, return empty
82
- return [];
83
- }
84
- return results;
85
- }
86
- matchSegment(filename, pattern) {
87
- // Convert glob pattern to regex
88
- const regex = this.patternToRegex(pattern);
89
- return regex.test(filename);
90
- }
91
- patternToRegex(pattern) {
92
- let regexStr = '';
93
- let i = 0;
94
- while (i < pattern.length) {
95
- const char = pattern[i];
96
- switch (char) {
97
- case '*':
98
- regexStr += '.*';
99
- break;
100
- case '?':
101
- regexStr += '.';
102
- break;
103
- case '[': {
104
- // Character class
105
- const closeIdx = this.findClosingBracket(pattern, i);
106
- if (closeIdx === -1) {
107
- // Invalid bracket, treat as literal
108
- regexStr += '\\[';
109
- }
110
- else {
111
- let charClass = pattern.slice(i + 1, closeIdx);
112
- // Handle negation
113
- if (charClass.startsWith('!') || charClass.startsWith('^')) {
114
- charClass = '^' + charClass.slice(1);
115
- }
116
- // Handle character ranges and classes
117
- charClass = this.processCharacterClass(charClass);
118
- regexStr += '[' + charClass + ']';
119
- i = closeIdx;
120
- }
121
- break;
122
- }
123
- case '{': {
124
- // Brace expansion - simplified implementation
125
- const braceEnd = this.findClosingBrace(pattern, i);
126
- if (braceEnd === -1) {
127
- regexStr += '\\{';
128
- }
129
- else {
130
- const braceContent = pattern.slice(i + 1, braceEnd);
131
- const alternatives = braceContent.split(',');
132
- regexStr += '(' + alternatives.map(alt => this.escapeRegex(alt)).join('|') + ')';
133
- i = braceEnd;
134
- }
135
- break;
136
- }
137
- case '\\':
138
- // Escape next character
139
- if (i + 1 < pattern.length) {
140
- regexStr += '\\' + pattern[i + 1];
141
- i++;
142
- }
143
- else {
144
- regexStr += '\\\\';
145
- }
146
- break;
147
- default:
148
- // Literal character - escape regex special chars
149
- regexStr += this.escapeRegex(char);
150
- break;
151
- }
152
- i++;
153
- }
154
- return new RegExp('^' + regexStr + '$');
155
- }
156
- findClosingBracket(str, startIdx) {
157
- let depth = 1;
158
- for (let i = startIdx + 1; i < str.length; i++) {
159
- if (str[i] === '[')
160
- depth++;
161
- else if (str[i] === ']') {
162
- depth--;
163
- if (depth === 0)
164
- return i;
165
- }
166
- }
167
- return -1;
168
- }
169
- findClosingBrace(str, startIdx) {
170
- let depth = 1;
171
- for (let i = startIdx + 1; i < str.length; i++) {
172
- if (str[i] === '{')
173
- depth++;
174
- else if (str[i] === '}') {
175
- depth--;
176
- if (depth === 0)
177
- return i;
178
- }
179
- }
180
- return -1;
181
- }
182
- processCharacterClass(charClass) {
183
- // Handle POSIX character classes like [:alpha:]
184
- charClass = charClass.replace(/\[:alpha:\]/g, 'a-zA-Z');
185
- charClass = charClass.replace(/\[:digit:\]/g, '0-9');
186
- charClass = charClass.replace(/\[:alnum:\]/g, 'a-zA-Z0-9');
187
- charClass = charClass.replace(/\[:lower:\]/g, 'a-z');
188
- charClass = charClass.replace(/\[:upper:\]/g, 'A-Z');
189
- charClass = charClass.replace(/\[:space:\]/g, ' \\t\\n\\r\\f\\v');
190
- charClass = charClass.replace(/\[:blank:\]/g, ' \\t');
191
- charClass = charClass.replace(/\[:punct:\]/g, '!-/:-@\\[-`{-~');
192
- charClass = charClass.replace(/\[:cntrl:\]/g, '\\x00-\\x1F\\x7F');
193
- charClass = charClass.replace(/\[:print:\]/g, '\\x20-\\x7E');
194
- charClass = charClass.replace(/\[:graph:\]/g, '\\x21-\\x7E');
195
- charClass = charClass.replace(/\[:xdigit:\]/g, '0-9A-Fa-f');
196
- return charClass;
197
- }
198
- escapeRegex(str) {
199
- return str.replace(/[.+^$()|[\]{}\\]/g, '\\$&');
200
- }
201
- // Utility method for expanding multiple patterns
202
- async expandMultiplePatterns(patterns, options = {}) {
203
- const results = [];
204
- for (const pattern of patterns) {
205
- const expanded = await this.expandPathnames(pattern, options);
206
- results.push(...expanded);
207
- }
208
- // Remove duplicates and sort
209
- return [...new Set(results)].sort();
210
- }
211
- // Check if a pattern would match any files (useful for error reporting)
212
- async hasMatches(pattern, options = {}) {
213
- const matches = await this.expandPathnames(pattern, options);
214
- return matches.length > 0 && matches[0] !== pattern;
215
- }
216
- }
@@ -1,226 +0,0 @@
1
- /**
2
- * Shell Script Runner
3
- * Executes shell scripts with LSH
4
- */
5
- import { ShellExecutor } from './shell-executor.js';
6
- import { parseShellCommand } from './shell-parser.js';
7
- import * as fs from 'fs';
8
- export class ScriptRunner {
9
- executor;
10
- constructor(options) {
11
- this.executor = new ShellExecutor({
12
- cwd: options?.cwd || process.cwd(),
13
- env: {
14
- ...Object.fromEntries(Object.entries(process.env).filter(([_, v]) => v !== undefined)),
15
- ...options?.env
16
- },
17
- });
18
- }
19
- /**
20
- * Execute a shell script file
21
- */
22
- async executeScript(scriptPath, options = {}) {
23
- try {
24
- // Read script file
25
- const scriptContent = fs.readFileSync(scriptPath, 'utf8');
26
- // Set up script context
27
- if (options.args) {
28
- this.executor.setPositionalParams(options.args);
29
- }
30
- // Parse and execute script
31
- const ast = parseShellCommand(scriptContent);
32
- const result = await this.executor.execute(ast);
33
- return {
34
- success: result.success,
35
- exitCode: result.exitCode,
36
- output: result.stdout,
37
- errors: result.stderr,
38
- };
39
- }
40
- catch (error) {
41
- return {
42
- success: false,
43
- exitCode: 1,
44
- output: '',
45
- errors: `Script execution failed: ${error.message}`,
46
- };
47
- }
48
- }
49
- /**
50
- * Execute shell commands from string
51
- */
52
- async executeCommands(commands, options = {}) {
53
- try {
54
- // Set up context
55
- if (options.args) {
56
- this.executor.setPositionalParams(options.args);
57
- }
58
- // Parse and execute commands
59
- const ast = parseShellCommand(commands);
60
- const result = await this.executor.execute(ast);
61
- return {
62
- success: result.success,
63
- exitCode: result.exitCode,
64
- output: result.stdout,
65
- errors: result.stderr,
66
- };
67
- }
68
- catch (error) {
69
- return {
70
- success: false,
71
- exitCode: 1,
72
- output: '',
73
- errors: `Command execution failed: ${error.message}`,
74
- };
75
- }
76
- }
77
- /**
78
- * Execute script with shebang detection
79
- */
80
- async executeWithShebang(scriptPath, options = {}) {
81
- try {
82
- const scriptContent = fs.readFileSync(scriptPath, 'utf8');
83
- // Check for shebang
84
- const lines = scriptContent.split('\n');
85
- const firstLine = lines[0];
86
- if (firstLine.startsWith('#!')) {
87
- const interpreter = firstLine.substring(2).trim();
88
- // Handle different interpreters
89
- if (interpreter.includes('sh') || interpreter.includes('bash') || interpreter.includes('zsh')) {
90
- // Execute as shell script
91
- return await this.executeScript(scriptPath, options);
92
- }
93
- else {
94
- // For other interpreters, delegate to system
95
- return await this.executeSystemScript(scriptPath, options);
96
- }
97
- }
98
- else {
99
- // No shebang, execute as shell script
100
- return await this.executeScript(scriptPath, options);
101
- }
102
- }
103
- catch (error) {
104
- return {
105
- success: false,
106
- exitCode: 1,
107
- output: '',
108
- errors: `Script execution failed: ${error.message}`,
109
- };
110
- }
111
- }
112
- /**
113
- * Execute system script (fallback)
114
- */
115
- async executeSystemScript(scriptPath, options) {
116
- const { spawn } = await import('child_process');
117
- return new Promise((resolve) => {
118
- const child = spawn('sh', [scriptPath], {
119
- cwd: options.cwd || process.cwd(),
120
- env: { ...process.env, ...options.env },
121
- stdio: ['pipe', 'pipe', 'pipe'],
122
- });
123
- let stdout = '';
124
- let stderr = '';
125
- child.stdout?.on('data', (data) => {
126
- stdout += data.toString();
127
- });
128
- child.stderr?.on('data', (data) => {
129
- stderr += data.toString();
130
- });
131
- child.on('close', (code) => {
132
- resolve({
133
- success: code === 0,
134
- exitCode: code || 0,
135
- output: stdout,
136
- errors: stderr,
137
- });
138
- });
139
- child.on('error', (error) => {
140
- resolve({
141
- success: false,
142
- exitCode: 1,
143
- output: '',
144
- errors: error.message,
145
- });
146
- });
147
- });
148
- }
149
- /**
150
- * Validate shell script syntax
151
- */
152
- validateScript(scriptPath) {
153
- try {
154
- const scriptContent = fs.readFileSync(scriptPath, 'utf8');
155
- const _ast = parseShellCommand(scriptContent);
156
- // Basic validation - if parsing succeeds, syntax is valid
157
- return { valid: true, errors: [] };
158
- }
159
- catch (error) {
160
- return { valid: false, errors: [error.message] };
161
- }
162
- }
163
- /**
164
- * Get script information
165
- */
166
- getScriptInfo(scriptPath) {
167
- try {
168
- const stats = fs.statSync(scriptPath);
169
- const content = fs.readFileSync(scriptPath, 'utf8');
170
- const firstLine = content.split('\n')[0];
171
- let shebang;
172
- let interpreter;
173
- if (firstLine.startsWith('#!')) {
174
- shebang = firstLine;
175
- interpreter = firstLine.substring(2).trim();
176
- }
177
- return {
178
- exists: true,
179
- executable: stats.mode & 0o111 ? true : false,
180
- size: stats.size,
181
- shebang,
182
- interpreter,
183
- };
184
- }
185
- catch {
186
- return {
187
- exists: false,
188
- executable: false,
189
- size: 0,
190
- };
191
- }
192
- }
193
- /**
194
- * Make script executable
195
- */
196
- makeExecutable(scriptPath) {
197
- try {
198
- const stats = fs.statSync(scriptPath);
199
- fs.chmodSync(scriptPath, stats.mode | 0o111);
200
- return true;
201
- }
202
- catch {
203
- return false;
204
- }
205
- }
206
- /**
207
- * Create a simple shell script
208
- */
209
- createScript(scriptPath, content, makeExecutable = true) {
210
- try {
211
- // Add shebang if not present
212
- if (!content.startsWith('#!')) {
213
- content = '#!/bin/sh\n' + content;
214
- }
215
- fs.writeFileSync(scriptPath, content, 'utf8');
216
- if (makeExecutable) {
217
- this.makeExecutable(scriptPath);
218
- }
219
- return true;
220
- }
221
- catch {
222
- return false;
223
- }
224
- }
225
- }
226
- export default ScriptRunner;