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,185 +0,0 @@
1
- /**
2
- * API Error Handler
3
- * Consolidates error response formatting across all API endpoints
4
- */
5
- /**
6
- * HTTP status codes for common error types
7
- */
8
- export const ErrorStatusCodes = {
9
- BAD_REQUEST: 400,
10
- UNAUTHORIZED: 401,
11
- FORBIDDEN: 403,
12
- NOT_FOUND: 404,
13
- CONFLICT: 409,
14
- INTERNAL_SERVER_ERROR: 500,
15
- SERVICE_UNAVAILABLE: 503,
16
- };
17
- /**
18
- * Custom API Error class with status code
19
- */
20
- export class ApiError extends Error {
21
- statusCode;
22
- code;
23
- details;
24
- constructor(message, statusCode = ErrorStatusCodes.INTERNAL_SERVER_ERROR, code, details) {
25
- super(message);
26
- this.statusCode = statusCode;
27
- this.code = code;
28
- this.details = details;
29
- this.name = 'ApiError';
30
- }
31
- }
32
- /**
33
- * Send error response with consistent formatting
34
- *
35
- * @param res - Express response object
36
- * @param error - Error object
37
- * @param statusCode - HTTP status code (default: 500)
38
- */
39
- export function sendError(res, error, statusCode) {
40
- const err = error instanceof Error ? error : new Error(String(error));
41
- const status = statusCode || (err instanceof ApiError ? err.statusCode : 500);
42
- const response = {
43
- error: err.message || 'An unexpected error occurred',
44
- timestamp: new Date().toISOString(),
45
- };
46
- if (err instanceof ApiError) {
47
- if (err.code)
48
- response.code = err.code;
49
- if (err.details)
50
- response.details = err.details;
51
- }
52
- // Log error for debugging (in production, use proper logger)
53
- if (status >= 500) {
54
- console.error('API Error:', err);
55
- }
56
- res.status(status).json(response);
57
- }
58
- /**
59
- * Send success response with consistent formatting
60
- *
61
- * @param res - Express response object
62
- * @param data - Response data
63
- * @param statusCode - HTTP status code (default: 200)
64
- * @param includeTimestamp - Include timestamp in response
65
- */
66
- export function sendSuccess(res, data, statusCode = 200, includeTimestamp = false) {
67
- if (statusCode === 204) {
68
- res.status(204).send();
69
- return;
70
- }
71
- const response = includeTimestamp
72
- ? { data, timestamp: new Date().toISOString() }
73
- : data;
74
- res.status(statusCode).json(response);
75
- }
76
- /**
77
- * Wrapper for async route handlers with automatic error handling
78
- *
79
- * Eliminates the need for try-catch blocks in every route handler
80
- *
81
- * @param handler - Async route handler function
82
- * @returns Express middleware function
83
- *
84
- * @example
85
- * ```typescript
86
- * app.get('/api/jobs', asyncHandler(async (req, res) => {
87
- * const jobs = await getJobs();
88
- * sendSuccess(res, jobs);
89
- * }));
90
- * ```
91
- */
92
- export function asyncHandler(handler) {
93
- return (req, res, next) => {
94
- Promise.resolve(handler(req, res, next)).catch((error) => {
95
- sendError(res, error);
96
- });
97
- };
98
- }
99
- /**
100
- * Execute an operation with automatic success/error handling
101
- *
102
- * This is the most powerful wrapper - it handles:
103
- * - Try-catch
104
- * - Success response formatting
105
- * - Error response formatting
106
- * - Optional webhook triggering
107
- *
108
- * @param res - Express response object
109
- * @param operation - Async operation to execute
110
- * @param config - Configuration options
111
- * @param webhookTrigger - Optional webhook trigger function
112
- *
113
- * @example
114
- * ```typescript
115
- * app.post('/api/jobs', async (req, res) => {
116
- * await handleApiOperation(
117
- * res,
118
- * async () => this.daemon.addJob(req.body),
119
- * {
120
- * successStatus: 201,
121
- * webhookEvent: 'job.created'
122
- * },
123
- * (event, data) => this.triggerWebhook(event, data)
124
- * );
125
- * });
126
- * ```
127
- */
128
- export async function handleApiOperation(res, operation, config = {}, webhookTrigger) {
129
- const { successStatus = 200, includeTimestamp = false, webhookEvent, webhookData, } = config;
130
- try {
131
- const result = await operation();
132
- // Send success response
133
- sendSuccess(res, result, successStatus, includeTimestamp);
134
- // Trigger webhook if configured
135
- if (webhookEvent && webhookTrigger) {
136
- const webhookPayload = webhookData ? webhookData(result) : result;
137
- webhookTrigger(webhookEvent, webhookPayload);
138
- }
139
- }
140
- catch (error) {
141
- const err = error;
142
- // Determine appropriate status code
143
- let statusCode = 400;
144
- if (err instanceof ApiError) {
145
- statusCode = err.statusCode;
146
- }
147
- else if (err.message.includes('not found') || err.message.includes('Not found')) {
148
- statusCode = 404;
149
- }
150
- else if (err.message.includes('permission') || err.message.includes('unauthorized')) {
151
- statusCode = 403;
152
- }
153
- else if (err.message.includes('exists') || err.message.includes('duplicate')) {
154
- statusCode = 409;
155
- }
156
- sendError(res, err, statusCode);
157
- }
158
- }
159
- /**
160
- * Create a typed API handler with webhook support
161
- *
162
- * Returns a function that can be used to handle API operations with
163
- * automatic error handling and webhook triggering
164
- *
165
- * @param webhookTrigger - Webhook trigger function
166
- * @returns Handler function
167
- */
168
- export function createApiHandler(webhookTrigger) {
169
- return async function (res, operation, config = {}) {
170
- await handleApiOperation(res, operation, config, webhookTrigger);
171
- };
172
- }
173
- /**
174
- * Express error handling middleware
175
- *
176
- * Should be added after all routes
177
- *
178
- * @example
179
- * ```typescript
180
- * app.use(errorMiddleware);
181
- * ```
182
- */
183
- export function errorMiddleware(error, req, res, _next) {
184
- sendError(res, error);
185
- }
@@ -1,285 +0,0 @@
1
- /**
2
- * Associative Arrays Implementation
3
- * Provides ZSH-compatible associative array functionality
4
- */
5
- export class AssociativeArrayManager {
6
- context;
7
- constructor() {
8
- this.context = {
9
- arrays: new Map(),
10
- arrayTypes: new Map(),
11
- };
12
- }
13
- /**
14
- * Declare an associative array with typeset -A
15
- */
16
- declareAssociativeArray(name) {
17
- this.context.arrays.set(name, {});
18
- this.context.arrayTypes.set(name, 'associative');
19
- }
20
- /**
21
- * Declare an indexed array with typeset -a
22
- */
23
- declareIndexedArray(name) {
24
- this.context.arrays.set(name, {});
25
- this.context.arrayTypes.set(name, 'indexed');
26
- }
27
- /**
28
- * Set a value in an associative array
29
- */
30
- setAssociativeValue(arrayName, key, value) {
31
- if (!this.context.arrays.has(arrayName)) {
32
- this.declareAssociativeArray(arrayName);
33
- }
34
- const array = this.context.arrays.get(arrayName);
35
- array[key] = value;
36
- }
37
- /**
38
- * Set a value in an indexed array
39
- */
40
- setIndexedValue(arrayName, index, value) {
41
- if (!this.context.arrays.has(arrayName)) {
42
- this.declareIndexedArray(arrayName);
43
- }
44
- const array = this.context.arrays.get(arrayName);
45
- array[index.toString()] = value;
46
- }
47
- /**
48
- * Get a value from an array
49
- */
50
- getValue(arrayName, key) {
51
- const array = this.context.arrays.get(arrayName);
52
- return array ? array[key] : undefined;
53
- }
54
- /**
55
- * Get all keys from an associative array
56
- */
57
- getKeys(arrayName) {
58
- const array = this.context.arrays.get(arrayName);
59
- if (!array)
60
- return [];
61
- const type = this.context.arrayTypes.get(arrayName);
62
- if (type === 'indexed') {
63
- // For indexed arrays, return sorted numeric keys
64
- return Object.keys(array)
65
- .map(k => parseInt(k, 10))
66
- .filter(k => !isNaN(k))
67
- .sort((a, b) => a - b)
68
- .map(k => k.toString());
69
- }
70
- else {
71
- // For associative arrays, return all keys
72
- return Object.keys(array);
73
- }
74
- }
75
- /**
76
- * Get all values from an array
77
- */
78
- getValues(arrayName) {
79
- const array = this.context.arrays.get(arrayName);
80
- if (!array)
81
- return [];
82
- const type = this.context.arrayTypes.get(arrayName);
83
- if (type === 'indexed') {
84
- // For indexed arrays, return values in order
85
- const keys = this.getKeys(arrayName);
86
- return keys.map(key => array[key]);
87
- }
88
- else {
89
- // For associative arrays, return all values
90
- return Object.values(array);
91
- }
92
- }
93
- /**
94
- * Get array length
95
- */
96
- getLength(arrayName) {
97
- const array = this.context.arrays.get(arrayName);
98
- return array ? Object.keys(array).length : 0;
99
- }
100
- /**
101
- * Check if an array exists
102
- */
103
- hasArray(arrayName) {
104
- return this.context.arrays.has(arrayName);
105
- }
106
- /**
107
- * Get array type
108
- */
109
- getArrayType(arrayName) {
110
- return this.context.arrayTypes.get(arrayName);
111
- }
112
- /**
113
- * Remove an array
114
- */
115
- removeArray(arrayName) {
116
- const hadArray = this.context.arrays.has(arrayName);
117
- this.context.arrays.delete(arrayName);
118
- this.context.arrayTypes.delete(arrayName);
119
- return hadArray;
120
- }
121
- /**
122
- * Get all array names
123
- */
124
- getAllArrayNames() {
125
- return Array.from(this.context.arrays.keys());
126
- }
127
- /**
128
- * Clear all arrays
129
- */
130
- clearAllArrays() {
131
- this.context.arrays.clear();
132
- this.context.arrayTypes.clear();
133
- }
134
- /**
135
- * Get array slice (for indexed arrays)
136
- */
137
- getSlice(arrayName, start, end) {
138
- const array = this.context.arrays.get(arrayName);
139
- if (!array)
140
- return [];
141
- const type = this.context.arrayTypes.get(arrayName);
142
- if (type !== 'indexed')
143
- return [];
144
- const keys = this.getKeys(arrayName);
145
- const startIdx = Math.max(0, start - 1); // Convert to 0-based
146
- const endIdx = end ? Math.min(keys.length, end) : keys.length;
147
- return keys.slice(startIdx, endIdx).map(key => array[key]);
148
- }
149
- /**
150
- * Expand array reference like ${array[key]} or ${array[@]}
151
- */
152
- expandArrayReference(reference) {
153
- // Match patterns like ${array[key]}, ${array[@]}, ${array[*]}
154
- const match = reference.match(/^\$\{([^[\]]+)(?:\[([^\]]+)\])?(?:\[@\*\]|\[@\]|\[\*\]|\[@\])?\}$/);
155
- if (!match)
156
- return [];
157
- const arrayName = match[1];
158
- const key = match[2];
159
- if (!this.hasArray(arrayName))
160
- return [];
161
- if (key) {
162
- // Single element access
163
- const value = this.getValue(arrayName, key);
164
- return value !== undefined ? [value] : [];
165
- }
166
- else {
167
- // All elements access
168
- return this.getValues(arrayName);
169
- }
170
- }
171
- /**
172
- * Expand array keys like ${(k)array}
173
- */
174
- expandArrayKeys(reference) {
175
- const match = reference.match(/^\$\{\(k\)([^}]+)\}$/);
176
- if (!match)
177
- return [];
178
- const arrayName = match[1];
179
- return this.getKeys(arrayName);
180
- }
181
- /**
182
- * Expand array values like ${(v)array}
183
- */
184
- expandArrayValues(reference) {
185
- const match = reference.match(/^\$\{\(v\)([^}]+)\}$/);
186
- if (!match)
187
- return [];
188
- const arrayName = match[1];
189
- return this.getValues(arrayName);
190
- }
191
- /**
192
- * Expand array length like ${#array}
193
- */
194
- expandArrayLength(reference) {
195
- const match = reference.match(/^\$\{#([^}]+)\}$/);
196
- if (!match)
197
- return '';
198
- const arrayName = match[1];
199
- return this.getLength(arrayName).toString();
200
- }
201
- /**
202
- * Parse typeset command
203
- */
204
- parseTypesetCommand(args) {
205
- if (args.length === 0) {
206
- return { success: false, message: 'typeset: missing arguments' };
207
- }
208
- for (const arg of args) {
209
- if (arg === '-A') {
210
- // Declare associative array - next argument should be the name
211
- const nameIndex = args.indexOf('-A') + 1;
212
- if (nameIndex < args.length) {
213
- const name = args[nameIndex];
214
- this.declareAssociativeArray(name);
215
- }
216
- }
217
- else if (arg === '-a') {
218
- // Declare indexed array - next argument should be the name
219
- const nameIndex = args.indexOf('-a') + 1;
220
- if (nameIndex < args.length) {
221
- const name = args[nameIndex];
222
- this.declareIndexedArray(name);
223
- }
224
- }
225
- else if (arg.includes('=')) {
226
- // Assignment: name=value or name[key]=value
227
- const [left, right] = arg.split('=', 2);
228
- const arrayMatch = left.match(/^([^[\]]+)(?:\[([^\]]+)\])?$/);
229
- if (arrayMatch) {
230
- const arrayName = arrayMatch[1];
231
- const key = arrayMatch[2];
232
- if (key) {
233
- // Associative array assignment
234
- this.setAssociativeValue(arrayName, key, right);
235
- }
236
- else {
237
- // Regular variable assignment (not array)
238
- // This would be handled by the regular variable system
239
- }
240
- }
241
- }
242
- }
243
- return { success: true, message: '' };
244
- }
245
- /**
246
- * Get array information for display
247
- */
248
- getArrayInfo(arrayName) {
249
- if (!this.hasArray(arrayName))
250
- return null;
251
- const type = this.getArrayType(arrayName);
252
- const length = this.getLength(arrayName);
253
- const keys = this.getKeys(arrayName);
254
- const values = this.getValues(arrayName);
255
- return {
256
- type: type || 'unknown',
257
- length,
258
- keys,
259
- values,
260
- };
261
- }
262
- /**
263
- * Export array data for serialization
264
- */
265
- exportArrays() {
266
- const arrays = {};
267
- const types = {};
268
- for (const [name, array] of this.context.arrays) {
269
- arrays[name] = { ...array };
270
- types[name] = this.context.arrayTypes.get(name) || 'unknown';
271
- }
272
- return { arrays, types };
273
- }
274
- /**
275
- * Import array data from serialization
276
- */
277
- importArrays(data) {
278
- this.clearAllArrays();
279
- for (const [name, array] of Object.entries(data.arrays)) {
280
- this.context.arrays.set(name, { ...array });
281
- this.context.arrayTypes.set(name, data.types[name]);
282
- }
283
- }
284
- }
285
- export default AssociativeArrayManager;