lsh-framework 0.5.4

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 (90) hide show
  1. package/.env.example +51 -0
  2. package/README.md +399 -0
  3. package/dist/app.js +33 -0
  4. package/dist/cicd/analytics.js +261 -0
  5. package/dist/cicd/auth.js +269 -0
  6. package/dist/cicd/cache-manager.js +172 -0
  7. package/dist/cicd/data-retention.js +305 -0
  8. package/dist/cicd/performance-monitor.js +224 -0
  9. package/dist/cicd/webhook-receiver.js +634 -0
  10. package/dist/cli.js +500 -0
  11. package/dist/commands/api.js +343 -0
  12. package/dist/commands/self.js +318 -0
  13. package/dist/commands/theme.js +257 -0
  14. package/dist/commands/zsh-import.js +240 -0
  15. package/dist/components/App.js +1 -0
  16. package/dist/components/Divider.js +29 -0
  17. package/dist/components/REPL.js +43 -0
  18. package/dist/components/Terminal.js +232 -0
  19. package/dist/components/UserInput.js +30 -0
  20. package/dist/daemon/api-server.js +315 -0
  21. package/dist/daemon/job-registry.js +554 -0
  22. package/dist/daemon/lshd.js +822 -0
  23. package/dist/daemon/monitoring-api.js +220 -0
  24. package/dist/examples/supabase-integration.js +106 -0
  25. package/dist/lib/api-error-handler.js +183 -0
  26. package/dist/lib/associative-arrays.js +285 -0
  27. package/dist/lib/base-api-server.js +290 -0
  28. package/dist/lib/base-command-registrar.js +286 -0
  29. package/dist/lib/base-job-manager.js +293 -0
  30. package/dist/lib/brace-expansion.js +160 -0
  31. package/dist/lib/builtin-commands.js +439 -0
  32. package/dist/lib/cloud-config-manager.js +347 -0
  33. package/dist/lib/command-validator.js +190 -0
  34. package/dist/lib/completion-system.js +344 -0
  35. package/dist/lib/cron-job-manager.js +364 -0
  36. package/dist/lib/daemon-client-helper.js +141 -0
  37. package/dist/lib/daemon-client.js +501 -0
  38. package/dist/lib/database-persistence.js +638 -0
  39. package/dist/lib/database-schema.js +259 -0
  40. package/dist/lib/enhanced-history-system.js +246 -0
  41. package/dist/lib/env-validator.js +265 -0
  42. package/dist/lib/executors/builtin-executor.js +52 -0
  43. package/dist/lib/extended-globbing.js +411 -0
  44. package/dist/lib/extended-parameter-expansion.js +227 -0
  45. package/dist/lib/floating-point-arithmetic.js +256 -0
  46. package/dist/lib/history-system.js +245 -0
  47. package/dist/lib/interactive-shell.js +460 -0
  48. package/dist/lib/job-builtins.js +580 -0
  49. package/dist/lib/job-manager.js +386 -0
  50. package/dist/lib/job-storage-database.js +156 -0
  51. package/dist/lib/job-storage-memory.js +73 -0
  52. package/dist/lib/logger.js +274 -0
  53. package/dist/lib/lshrc-init.js +177 -0
  54. package/dist/lib/pathname-expansion.js +216 -0
  55. package/dist/lib/prompt-system.js +328 -0
  56. package/dist/lib/script-runner.js +226 -0
  57. package/dist/lib/secrets-manager.js +193 -0
  58. package/dist/lib/shell-executor.js +2504 -0
  59. package/dist/lib/shell-parser.js +958 -0
  60. package/dist/lib/shell-types.js +6 -0
  61. package/dist/lib/shell.lib.js +40 -0
  62. package/dist/lib/supabase-client.js +58 -0
  63. package/dist/lib/theme-manager.js +476 -0
  64. package/dist/lib/variable-expansion.js +385 -0
  65. package/dist/lib/zsh-compatibility.js +658 -0
  66. package/dist/lib/zsh-import-manager.js +699 -0
  67. package/dist/lib/zsh-options.js +328 -0
  68. package/dist/pipeline/job-tracker.js +491 -0
  69. package/dist/pipeline/mcli-bridge.js +302 -0
  70. package/dist/pipeline/pipeline-service.js +1116 -0
  71. package/dist/pipeline/workflow-engine.js +867 -0
  72. package/dist/services/api/api.js +58 -0
  73. package/dist/services/api/auth.js +35 -0
  74. package/dist/services/api/config.js +7 -0
  75. package/dist/services/api/file.js +22 -0
  76. package/dist/services/cron/cron-registrar.js +235 -0
  77. package/dist/services/cron/cron.js +9 -0
  78. package/dist/services/daemon/daemon-registrar.js +565 -0
  79. package/dist/services/daemon/daemon.js +9 -0
  80. package/dist/services/lib/lib.js +86 -0
  81. package/dist/services/log-file-extractor.js +170 -0
  82. package/dist/services/secrets/secrets.js +94 -0
  83. package/dist/services/shell/shell.js +28 -0
  84. package/dist/services/supabase/supabase-registrar.js +367 -0
  85. package/dist/services/supabase/supabase.js +9 -0
  86. package/dist/services/zapier.js +16 -0
  87. package/dist/simple-api-server.js +148 -0
  88. package/dist/store/store.js +31 -0
  89. package/dist/util/lib.util.js +11 -0
  90. package/package.json +144 -0
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Environment Variable Validation
3
+ * Validates required environment variables at startup
4
+ */
5
+ /**
6
+ * Standard environment variable requirements for LSH
7
+ */
8
+ export const LSH_ENV_REQUIREMENTS = [
9
+ // Core configuration
10
+ {
11
+ name: 'NODE_ENV',
12
+ required: false,
13
+ requireInProduction: false,
14
+ description: 'Environment mode (development, production, test)',
15
+ validate: (val) => ['development', 'production', 'test'].includes(val)
16
+ },
17
+ {
18
+ name: 'USER',
19
+ required: false,
20
+ requireInProduction: false,
21
+ description: 'Current system user'
22
+ },
23
+ // API Configuration
24
+ {
25
+ name: 'LSH_API_ENABLED',
26
+ required: false,
27
+ requireInProduction: false,
28
+ description: 'Enable API server',
29
+ validate: (val) => ['true', 'false'].includes(val)
30
+ },
31
+ {
32
+ name: 'LSH_API_PORT',
33
+ required: false,
34
+ requireInProduction: false,
35
+ description: 'API server port',
36
+ defaultValue: '3030',
37
+ validate: (val) => !isNaN(parseInt(val)) && parseInt(val) > 0 && parseInt(val) < 65536
38
+ },
39
+ {
40
+ name: 'LSH_API_KEY',
41
+ required: false,
42
+ requireInProduction: true, // Required if API is enabled in production
43
+ description: 'API authentication key',
44
+ sensitiveValue: true,
45
+ validate: (val) => val.length >= 32
46
+ },
47
+ {
48
+ name: 'LSH_JWT_SECRET',
49
+ required: false,
50
+ requireInProduction: true, // Required if API is enabled in production
51
+ description: 'JWT signing secret',
52
+ sensitiveValue: true,
53
+ validate: (val) => val.length >= 32
54
+ },
55
+ // Security Configuration
56
+ {
57
+ name: 'LSH_ALLOW_DANGEROUS_COMMANDS',
58
+ required: false,
59
+ requireInProduction: false,
60
+ description: 'Allow potentially dangerous commands (use with caution)',
61
+ validate: (val) => ['true', 'false'].includes(val)
62
+ },
63
+ // Webhook Configuration
64
+ {
65
+ name: 'LSH_ENABLE_WEBHOOKS',
66
+ required: false,
67
+ requireInProduction: false,
68
+ description: 'Enable webhook receiver',
69
+ validate: (val) => ['true', 'false'].includes(val)
70
+ },
71
+ {
72
+ name: 'WEBHOOK_PORT',
73
+ required: false,
74
+ requireInProduction: false,
75
+ description: 'Webhook receiver port',
76
+ defaultValue: '3033',
77
+ validate: (val) => !isNaN(parseInt(val)) && parseInt(val) > 0 && parseInt(val) < 65536
78
+ },
79
+ {
80
+ name: 'GITHUB_WEBHOOK_SECRET',
81
+ required: false,
82
+ requireInProduction: true, // Required if webhooks enabled in production
83
+ description: 'GitHub webhook secret',
84
+ sensitiveValue: true,
85
+ validate: (val) => val.length >= 16
86
+ },
87
+ {
88
+ name: 'GITLAB_WEBHOOK_SECRET',
89
+ required: false,
90
+ requireInProduction: false,
91
+ description: 'GitLab webhook secret',
92
+ sensitiveValue: true
93
+ },
94
+ {
95
+ name: 'JENKINS_WEBHOOK_SECRET',
96
+ required: false,
97
+ requireInProduction: false,
98
+ description: 'Jenkins webhook secret',
99
+ sensitiveValue: true
100
+ },
101
+ // Database Configuration
102
+ {
103
+ name: 'DATABASE_URL',
104
+ required: false,
105
+ requireInProduction: false,
106
+ description: 'PostgreSQL connection string',
107
+ sensitiveValue: true,
108
+ validate: (val) => val.startsWith('postgresql://') || val.startsWith('postgres://')
109
+ },
110
+ {
111
+ name: 'SUPABASE_URL',
112
+ required: false,
113
+ requireInProduction: false,
114
+ description: 'Supabase project URL',
115
+ validate: (val) => val.startsWith('http://') || val.startsWith('https://')
116
+ },
117
+ {
118
+ name: 'SUPABASE_ANON_KEY',
119
+ required: false,
120
+ requireInProduction: false,
121
+ description: 'Supabase anonymous key',
122
+ sensitiveValue: true
123
+ },
124
+ {
125
+ name: 'REDIS_URL',
126
+ required: false,
127
+ requireInProduction: false,
128
+ description: 'Redis connection string',
129
+ defaultValue: 'redis://localhost:6379',
130
+ validate: (val) => val.startsWith('redis://') || val.startsWith('rediss://')
131
+ },
132
+ // Monitoring
133
+ {
134
+ name: 'MONITORING_API_PORT',
135
+ required: false,
136
+ requireInProduction: false,
137
+ description: 'Monitoring API port',
138
+ defaultValue: '3031',
139
+ validate: (val) => !isNaN(parseInt(val)) && parseInt(val) > 0 && parseInt(val) < 65536
140
+ }
141
+ ];
142
+ /**
143
+ * Validate environment variables based on requirements
144
+ */
145
+ export function validateEnvironment(requirements = LSH_ENV_REQUIREMENTS, env = process.env) {
146
+ const result = {
147
+ isValid: true,
148
+ errors: [],
149
+ warnings: [],
150
+ missing: [],
151
+ recommendations: []
152
+ };
153
+ const isProduction = env.NODE_ENV === 'production';
154
+ const apiEnabled = env.LSH_API_ENABLED === 'true';
155
+ const webhooksEnabled = env.LSH_ENABLE_WEBHOOKS === 'true';
156
+ for (const req of requirements) {
157
+ const value = env[req.name];
158
+ const isEmpty = !value || value.trim().length === 0;
159
+ // Check if variable is required
160
+ if (req.required && isEmpty) {
161
+ result.errors.push(`Missing required environment variable: ${req.name}`);
162
+ result.missing.push(req.name);
163
+ result.isValid = false;
164
+ continue;
165
+ }
166
+ // Check production requirements
167
+ if (req.requireInProduction && isProduction && isEmpty) {
168
+ // Special cases for conditional requirements
169
+ if (req.name === 'LSH_API_KEY' || req.name === 'LSH_JWT_SECRET') {
170
+ if (apiEnabled) {
171
+ result.errors.push(`${req.name} is required in production when LSH_API_ENABLED=true`);
172
+ result.missing.push(req.name);
173
+ result.isValid = false;
174
+ }
175
+ }
176
+ else if (req.name === 'GITHUB_WEBHOOK_SECRET') {
177
+ if (webhooksEnabled) {
178
+ result.errors.push(`${req.name} is required in production when LSH_ENABLE_WEBHOOKS=true`);
179
+ result.missing.push(req.name);
180
+ result.isValid = false;
181
+ }
182
+ }
183
+ else {
184
+ result.warnings.push(`${req.name} should be set in production (${req.description || 'no description'})`);
185
+ }
186
+ continue;
187
+ }
188
+ // If value exists, validate it
189
+ if (!isEmpty && req.validate) {
190
+ try {
191
+ if (!req.validate(value)) {
192
+ result.errors.push(`Invalid value for ${req.name}: ${req.description || 'validation failed'}`);
193
+ result.isValid = false;
194
+ }
195
+ }
196
+ catch (error) {
197
+ result.errors.push(`Failed to validate ${req.name}: ${error instanceof Error ? error.message : 'unknown error'}`);
198
+ result.isValid = false;
199
+ }
200
+ }
201
+ // Provide recommendations for missing optional vars
202
+ if (isEmpty && req.defaultValue) {
203
+ result.recommendations.push(`${req.name} not set, using default: ${req.defaultValue}`);
204
+ }
205
+ }
206
+ // Additional security checks
207
+ if (isProduction) {
208
+ if (env.LSH_ALLOW_DANGEROUS_COMMANDS === 'true') {
209
+ result.warnings.push('LSH_ALLOW_DANGEROUS_COMMANDS is enabled in production - this is a security risk');
210
+ }
211
+ if (apiEnabled && (!env.LSH_API_KEY || env.LSH_API_KEY.length < 32)) {
212
+ result.errors.push('LSH_API_KEY must be at least 32 characters in production');
213
+ result.isValid = false;
214
+ }
215
+ if (apiEnabled && (!env.LSH_JWT_SECRET || env.LSH_JWT_SECRET.length < 32)) {
216
+ result.errors.push('LSH_JWT_SECRET must be at least 32 characters in production');
217
+ result.isValid = false;
218
+ }
219
+ }
220
+ return result;
221
+ }
222
+ /**
223
+ * Print validation results to console
224
+ */
225
+ export function printValidationResults(result, exitOnError = false) {
226
+ if (result.errors.length > 0) {
227
+ console.error('\n❌ Environment Variable Errors:');
228
+ result.errors.forEach(err => console.error(` - ${err}`));
229
+ }
230
+ if (result.warnings.length > 0) {
231
+ console.warn('\n⚠️ Environment Variable Warnings:');
232
+ result.warnings.forEach(warn => console.warn(` - ${warn}`));
233
+ }
234
+ if (result.recommendations.length > 0) {
235
+ // eslint-disable-next-line no-console
236
+ console.log('\nℹ️ Environment Variable Recommendations:');
237
+ // eslint-disable-next-line no-console
238
+ result.recommendations.forEach(rec => console.log(` - ${rec}`));
239
+ }
240
+ if (result.isValid) {
241
+ // eslint-disable-next-line no-console
242
+ console.log('\n✅ Environment validation passed');
243
+ }
244
+ else {
245
+ console.error('\n❌ Environment validation failed');
246
+ if (exitOnError) {
247
+ console.error('\nPlease check your .env file or environment variables');
248
+ console.error('See .env.example for required configuration\n');
249
+ process.exit(1);
250
+ }
251
+ }
252
+ }
253
+ /**
254
+ * Validate and exit if invalid (for use at startup)
255
+ */
256
+ export function validateOrExit(requirements = LSH_ENV_REQUIREMENTS) {
257
+ const result = validateEnvironment(requirements);
258
+ printValidationResults(result, true);
259
+ }
260
+ export default {
261
+ validateEnvironment,
262
+ printValidationResults,
263
+ validateOrExit,
264
+ LSH_ENV_REQUIREMENTS
265
+ };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Builtin Command Executor
3
+ * Handles execution of all POSIX and extended builtin commands
4
+ */
5
+ export class BuiltinExecutor {
6
+ context;
7
+ expander;
8
+ pathExpander;
9
+ jobManager;
10
+ jobBuiltins;
11
+ constructor(context, expander, pathExpander, jobManager, jobBuiltins) {
12
+ this.context = context;
13
+ this.expander = expander;
14
+ this.pathExpander = pathExpander;
15
+ this.jobManager = jobManager;
16
+ this.jobBuiltins = jobBuiltins;
17
+ }
18
+ /**
19
+ * Execute a builtin command
20
+ * Returns null if the command is not a builtin
21
+ */
22
+ async execute(name, args) {
23
+ const builtinMethod = this.getBuiltinMethod(name);
24
+ if (!builtinMethod) {
25
+ return null;
26
+ }
27
+ return builtinMethod.call(this, args);
28
+ }
29
+ /**
30
+ * Get the builtin method for a command name
31
+ */
32
+ getBuiltinMethod(name) {
33
+ const builtins = {
34
+ 'cd': this.builtin_cd.bind(this),
35
+ 'pwd': this.builtin_pwd.bind(this),
36
+ 'echo': this.builtin_echo.bind(this),
37
+ // Will add all 38 builtins here
38
+ };
39
+ return builtins[name] || null;
40
+ }
41
+ // ========== BUILTIN IMPLEMENTATIONS ==========
42
+ async builtin_cd(_args) {
43
+ // TODO: Move full implementation from shell-executor.ts
44
+ return { stdout: '', stderr: 'cd: stub', exitCode: 1, success: false };
45
+ }
46
+ async builtin_pwd(_args) {
47
+ return { stdout: this.context.cwd + '\n', stderr: '', exitCode: 0, success: true };
48
+ }
49
+ async builtin_echo(args) {
50
+ return { stdout: args.join(' ') + '\n', stderr: '', exitCode: 0, success: true };
51
+ }
52
+ }