lsh-framework 1.2.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 +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/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 +54 -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,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;