lsh-framework 0.9.0 → 0.9.2

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.
@@ -63,6 +63,7 @@ function verifyGitHubSignature(payload, signature) {
63
63
  const checksum = `sha256=${digest}`;
64
64
  return crypto.timingSafeEqual(Buffer.from(signature, 'utf8'), Buffer.from(checksum, 'utf8'));
65
65
  }
66
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
67
  function parseGitHubWorkflowEvent(body) {
67
68
  const { workflow_run, workflow_job, action } = body;
68
69
  if (!workflow_run && !workflow_job)
@@ -127,6 +128,7 @@ function verifyGitLabSignature(payload, signature) {
127
128
  const digest = hmac.update(payload, 'utf8').digest('hex');
128
129
  return crypto.timingSafeEqual(Buffer.from(signature, 'utf8'), Buffer.from(digest, 'utf8'));
129
130
  }
131
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
132
  function parseGitLabPipelineEvent(body) {
131
133
  const { object_kind, object_attributes, project, user } = body;
132
134
  if (object_kind !== 'pipeline' && object_kind !== 'job')
@@ -192,6 +194,7 @@ function mapGitLabConclusion(status) {
192
194
  default: return 'failure';
193
195
  }
194
196
  }
197
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
195
198
  function parseJenkinsEvent(body) {
196
199
  const { name, url, build, timestamp } = body;
197
200
  if (!build)
@@ -574,7 +577,8 @@ app.post('/auth/register', async (req, res) => {
574
577
  res.json({ user, token });
575
578
  }
576
579
  catch (error) {
577
- res.status(400).json({ error: error.message });
580
+ const err = error;
581
+ res.status(400).json({ error: err.message });
578
582
  }
579
583
  });
580
584
  app.post('/auth/login', async (req, res) => {
@@ -584,7 +588,8 @@ app.post('/auth/login', async (req, res) => {
584
588
  res.json(result);
585
589
  }
586
590
  catch (error) {
587
- res.status(401).json({ error: error.message });
591
+ const err = error;
592
+ res.status(401).json({ error: err.message });
588
593
  }
589
594
  });
590
595
  app.post('/auth/api-key', authenticate(authService), authorize('admin', 'developer'), async (req, res) => {
@@ -594,7 +599,8 @@ app.post('/auth/api-key', authenticate(authService), authorize('admin', 'develop
594
599
  res.json({ apiKey });
595
600
  }
596
601
  catch (error) {
597
- res.status(400).json({ error: error.message });
602
+ const err = error;
603
+ res.status(400).json({ error: err.message });
598
604
  }
599
605
  });
600
606
  // Protected admin endpoints
package/dist/cli.js CHANGED
@@ -482,6 +482,7 @@ async function validateConfig(rcFile) {
482
482
  /**
483
483
  * Load rc file
484
484
  */
485
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
485
486
  async function loadRcFile(executor, rcFile) {
486
487
  if (!fs.existsSync(rcFile)) {
487
488
  console.error(`Configuration file not found: ${rcFile}`);
@@ -42,7 +42,8 @@ export function registerApiCommands(program) {
42
42
  console.log(chalk.gray(` curl -H "X-API-Key: ${apiKey}" http://localhost:${options.port}/api/status`));
43
43
  }
44
44
  catch (error) {
45
- console.error(chalk.red(`❌ Failed to start API server: ${error.message}`));
45
+ const err = error;
46
+ console.error(chalk.red(`❌ Failed to start API server: ${err.message}`));
46
47
  process.exit(1);
47
48
  }
48
49
  });
@@ -85,7 +86,8 @@ export function registerApiCommands(program) {
85
86
  }
86
87
  }
87
88
  catch (error) {
88
- console.error(chalk.red(`❌ Failed to connect to API server: ${error.message}`));
89
+ const err = error;
90
+ console.error(chalk.red(`❌ Failed to connect to API server: ${err.message}`));
89
91
  console.log(chalk.yellow('Make sure the daemon is running with API enabled:'));
90
92
  console.log(chalk.gray(' lsh api start'));
91
93
  }
@@ -148,7 +150,8 @@ export function registerApiCommands(program) {
148
150
  }
149
151
  }
150
152
  catch (error) {
151
- console.error(chalk.red(`❌ Failed: ${error.message}`));
153
+ const err = error;
154
+ console.error(chalk.red(`❌ Failed: ${err.message}`));
152
155
  }
153
156
  });
154
157
  // Example client code generator
@@ -127,6 +127,7 @@ async function checkCIStatus(_version) {
127
127
  const ghData = JSON.parse(data);
128
128
  const runs = ghData.workflow_runs || [];
129
129
  // Find the most recent workflow run for main branch
130
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
131
  const mainRuns = runs.filter((run) => run.head_branch === 'main' && run.status === 'completed');
131
132
  if (mainRuns.length > 0) {
132
133
  const latestRun = mainRuns[0];
@@ -83,7 +83,8 @@ export function registerThemeCommands(program) {
83
83
  process.exit(0);
84
84
  }
85
85
  catch (error) {
86
- console.error(chalk.red(`✗ Failed to import theme: ${error.message}`));
86
+ const err = error;
87
+ console.error(chalk.red(`✗ Failed to import theme: ${err.message}`));
87
88
  process.exit(1);
88
89
  }
89
90
  });
@@ -164,7 +165,8 @@ ${commands}
164
165
  process.exit(0);
165
166
  }
166
167
  catch (error) {
167
- console.error(chalk.red(`✗ Failed to apply theme: ${error.message}`));
168
+ const err = error;
169
+ console.error(chalk.red(`✗ Failed to apply theme: ${err.message}`));
168
170
  process.exit(1);
169
171
  }
170
172
  });
@@ -251,7 +253,8 @@ ${commands}
251
253
  process.exit(0);
252
254
  }
253
255
  catch (error) {
254
- console.error(chalk.red(`✗ Failed to import theme: ${error.message}`));
256
+ const err = error;
257
+ console.error(chalk.red(`✗ Failed to import theme: ${err.message}`));
255
258
  process.exit(1);
256
259
  }
257
260
  });
@@ -155,7 +155,8 @@ export class LSHApiServer extends BaseAPIServer {
155
155
  results.push({ success: true, job });
156
156
  }
157
157
  catch (error) {
158
- results.push({ success: false, error: error.message, jobSpec });
158
+ const err = error;
159
+ results.push({ success: false, error: err.message, jobSpec });
159
160
  }
160
161
  }
161
162
  res.json({ results });
@@ -160,6 +160,7 @@ export class CronJobManager extends BaseJobManager {
160
160
  */
161
161
  async getJobReport(jobId) {
162
162
  // Try to get historical data from database if available, otherwise use current job info
163
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
163
164
  let jobs = [];
164
165
  try {
165
166
  jobs = await this.daemonClient.getJobHistory(jobId, 1000);
@@ -58,11 +58,12 @@ export async function withDaemonClient(operation, config = {}) {
58
58
  return result;
59
59
  }
60
60
  catch (error) {
61
+ const err = error;
61
62
  // Always disconnect on error
62
63
  client.disconnect();
63
64
  // Handle errors with helpful messages
64
- if (error.message.includes('Permission denied')) {
65
- const enhancedError = new Error(`❌ ${error.message}\n` +
65
+ if (err.message.includes('Permission denied')) {
66
+ const enhancedError = new Error(`❌ ${err.message}\n` +
66
67
  `The daemon socket may be owned by another user.\n` +
67
68
  `Try starting your own daemon with: lsh daemon start`);
68
69
  if (exitOnError) {
@@ -71,7 +72,7 @@ export async function withDaemonClient(operation, config = {}) {
71
72
  }
72
73
  throw enhancedError;
73
74
  }
74
- else if (error.message.includes('not found') || error.message.includes('ENOENT')) {
75
+ else if (err.message.includes('not found') || err.message.includes('ENOENT')) {
75
76
  const enhancedError = new Error(`❌ Daemon socket not found.\n` +
76
77
  `Start the daemon with: lsh daemon start`);
77
78
  if (exitOnError) {
@@ -80,7 +81,7 @@ export async function withDaemonClient(operation, config = {}) {
80
81
  }
81
82
  throw enhancedError;
82
83
  }
83
- else if (error.message.includes('ECONNREFUSED')) {
84
+ else if (err.message.includes('ECONNREFUSED')) {
84
85
  const enhancedError = new Error(`❌ Daemon is not responding.\n` +
85
86
  `The daemon may have crashed. Try restarting with: lsh daemon restart`);
86
87
  if (exitOnError) {
@@ -91,7 +92,7 @@ export async function withDaemonClient(operation, config = {}) {
91
92
  }
92
93
  else {
93
94
  if (exitOnError) {
94
- console.error('❌ Error:', error.message);
95
+ console.error('❌ Error:', err.message);
95
96
  process.exit(1);
96
97
  }
97
98
  throw error;
@@ -144,7 +144,8 @@ export function isEnvIgnored(dir = process.cwd()) {
144
144
  return false;
145
145
  }
146
146
  catch (error) {
147
- logger.warn(`Failed to read .gitignore: ${error.message}`);
147
+ const err = error;
148
+ logger.warn(`Failed to read .gitignore: ${err.message}`);
148
149
  return false;
149
150
  }
150
151
  }
@@ -170,7 +171,8 @@ export function ensureEnvInGitignore(dir = process.cwd()) {
170
171
  logger.info('✅ Added .env to .gitignore');
171
172
  }
172
173
  catch (error) {
173
- logger.warn(`Failed to update .gitignore: ${error.message}`);
174
+ const err = error;
175
+ logger.warn(`Failed to update .gitignore: ${err.message}`);
174
176
  }
175
177
  }
176
178
  export default {
@@ -438,7 +438,9 @@ export class JobBuiltins {
438
438
  }
439
439
  }
440
440
  // Helper methods for parsing options and formatting output
441
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
441
442
  parseCreateOptions(args) {
443
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
442
444
  const options = { tags: [] };
443
445
  for (let i = 0; i < args.length; i++) {
444
446
  const arg = args[i];
@@ -136,9 +136,10 @@ export class JobManager extends BaseJobManager {
136
136
  return updatedJob;
137
137
  }
138
138
  catch (error) {
139
+ const err = error;
139
140
  await this.updateJobStatus(job.id, 'failed', {
140
141
  completedAt: new Date(),
141
- stderr: error.message,
142
+ stderr: err.message,
142
143
  });
143
144
  this.emit('jobFailed', job, error);
144
145
  throw error;
@@ -169,6 +170,7 @@ export class JobManager extends BaseJobManager {
169
170
  job.process.kill(signal);
170
171
  }
171
172
  catch (error) {
173
+ const err = error;
172
174
  this.logger.error(`Failed to kill job ${jobId}`, error);
173
175
  }
174
176
  // Update status
@@ -291,6 +293,7 @@ export class JobManager extends BaseJobManager {
291
293
  /**
292
294
  * Get job statistics
293
295
  */
296
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
294
297
  getJobStats() {
295
298
  const jobs = Array.from(this.jobs.values());
296
299
  const stats = {
@@ -46,7 +46,8 @@ export class LshrcManager {
46
46
  return true;
47
47
  }
48
48
  catch (error) {
49
- console.error(`Failed to initialize .lshrc: ${error.message}`);
49
+ const err = error;
50
+ console.error(`Failed to initialize .lshrc: ${err.message}`);
50
51
  return false;
51
52
  }
52
53
  }
@@ -75,6 +76,7 @@ zsh-source${options.importOptions ? ' ' + options.importOptions.join(' ') : ''}
75
76
  /**
76
77
  * Source .lshrc commands
77
78
  */
79
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
80
  async source(_executor) {
79
81
  if (!this.exists()) {
80
82
  return [];
@@ -93,7 +95,8 @@ zsh-source${options.importOptions ? ' ' + options.importOptions.join(' ') : ''}
93
95
  return commands;
94
96
  }
95
97
  catch (error) {
96
- console.error(`Failed to source .lshrc: ${error.message}`);
98
+ const err = error;
99
+ console.error(`Failed to source .lshrc: ${err.message}`);
97
100
  return [];
98
101
  }
99
102
  }
@@ -130,7 +133,8 @@ zsh-source${options.length > 0 ? ' ' + options.join(' ') : ''}
130
133
  return true;
131
134
  }
132
135
  catch (error) {
133
- console.error(`Failed to enable auto-import: ${error.message}`);
136
+ const err = error;
137
+ console.error(`Failed to enable auto-import: ${err.message}`);
134
138
  return false;
135
139
  }
136
140
  }
@@ -152,7 +156,8 @@ zsh-source${options.length > 0 ? ' ' + options.join(' ') : ''}
152
156
  return true;
153
157
  }
154
158
  catch (error) {
155
- console.error(`Failed to disable auto-import: ${error.message}`);
159
+ const err = error;
160
+ console.error(`Failed to disable auto-import: ${err.message}`);
156
161
  return false;
157
162
  }
158
163
  }
@@ -750,10 +750,15 @@ LSH_SECRETS_KEY=${this.encryptionKey}
750
750
  */
751
751
  showLoadInstructions(envFilePath) {
752
752
  console.log('📝 To load secrets in your current shell:');
753
- console.log(` export $(cat ${envFilePath} | grep -v '^#' | xargs)`);
754
753
  console.log();
755
- console.log(' Or for safer loading (preserves quotes):');
756
- console.log(` set -a; source ${envFilePath}; set +a`);
754
+ console.log(' bash/zsh:');
755
+ console.log(` set -a && source ${envFilePath} && set +a`);
756
+ console.log();
757
+ console.log(' fish:');
758
+ console.log(` export (cat ${envFilePath} | grep -v '^#')`);
759
+ console.log();
760
+ console.log(' Or use lsh to load:');
761
+ console.log(` eval "$(lsh get --all --export)"`);
757
762
  console.log();
758
763
  }
759
764
  /**
@@ -814,13 +819,15 @@ LSH_SECRETS_KEY=${this.encryptionKey}
814
819
  if (status.localExists && status.keySet) {
815
820
  suggestions.push('');
816
821
  suggestions.push('📝 To load secrets in your current shell:');
817
- suggestions.push(` export $(cat ${envFilePath} | grep -v '^#' | xargs)`);
818
822
  suggestions.push('');
819
- suggestions.push(' Or for safer loading (with quotes):');
820
- suggestions.push(` set -a; source ${envFilePath}; set +a`);
823
+ suggestions.push(' bash/zsh:');
824
+ suggestions.push(` set -a && source ${envFilePath} && set +a`);
825
+ suggestions.push('');
826
+ suggestions.push(' fish:');
827
+ suggestions.push(` export (cat ${envFilePath} | grep -v '^#')`);
821
828
  suggestions.push('');
822
829
  suggestions.push('💡 Add to your shell profile for auto-loading:');
823
- suggestions.push(` echo "set -a; source ${path.resolve(envFilePath)}; set +a" >> ~/.zshrc`);
830
+ suggestions.push(` echo "set -a && source ${path.resolve(envFilePath)} && set +a" >> ~/.zshrc`);
824
831
  }
825
832
  // Display suggestions
826
833
  if (suggestions.length > 0) {
@@ -9,6 +9,7 @@ const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBh
9
9
  // Database connection string (for direct PostgreSQL access if needed)
10
10
  const DATABASE_URL = 'postgresql://postgres:[YOUR-PASSWORD]@db.uljsqvwkomdrlnofmlad.supabase.co:5432/postgres';
11
11
  export class SupabaseClient {
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
13
  client;
13
14
  config;
14
15
  constructor(config) {
@@ -168,6 +168,7 @@ export class ZshCompatibility {
168
168
  /**
169
169
  * Apply parsed ZSH configuration to LSH
170
170
  */
171
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
171
172
  async applyZshConfig(config) {
172
173
  // Apply aliases
173
174
  for (const alias of config.aliases) {
@@ -329,6 +330,7 @@ export class ZshCompatibility {
329
330
  /**
330
331
  * Generate completions based on patterns
331
332
  */
333
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
332
334
  async generateCompletions(context, patterns) {
333
335
  const completions = [];
334
336
  for (const pattern of patterns) {
@@ -25,6 +25,7 @@ function getCurrentDirname() {
25
25
  const currentDir = getCurrentDirname();
26
26
  export class PipelineService {
27
27
  app;
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
29
  server;
29
30
  io;
30
31
  pool;
@@ -34,7 +35,9 @@ export class PipelineService {
34
35
  config;
35
36
  isDemoMode = false;
36
37
  streamlitProcess = null;
38
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
39
  getSystemJobs() {
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
41
  const jobs = [];
39
42
  const monitoringJobs = [
40
43
  { script: 'db-health-monitor', name: 'Database Health Monitor', type: 'monitoring', owner: 'ops-team', schedule: '*/5 * * * *' },
@@ -208,7 +208,8 @@ export class DaemonCommandRegistrar extends BaseCommandRegistrar {
208
208
  }
209
209
  }
210
210
  catch (error) {
211
- this.logError(` ${job.name} failed: ${error.message || error}`);
211
+ const err = error;
212
+ this.logError(` ${job.name} failed: ${err.message || err}`);
212
213
  }
213
214
  }
214
215
  }, { forUser: true });
@@ -423,7 +424,8 @@ export class DaemonCommandRegistrar extends BaseCommandRegistrar {
423
424
  syncCount++;
424
425
  }
425
426
  catch (error) {
426
- this.logError(` Failed to sync ${job.name}: ${error.message}`);
427
+ const err = error;
428
+ this.logError(` Failed to sync ${job.name}: ${err.message}`);
427
429
  }
428
430
  }
429
431
  return { syncCount, totalJobs: jobs.length };
@@ -494,7 +496,8 @@ export class DaemonCommandRegistrar extends BaseCommandRegistrar {
494
496
  }
495
497
  }
496
498
  catch (error) {
497
- this.logWarning(`Could not remove: ${socket} (${error.message})`);
499
+ const err = error;
500
+ this.logWarning(`Could not remove: ${socket} (${err.message})`);
498
501
  }
499
502
  }
500
503
  }
@@ -521,7 +524,8 @@ export class DaemonCommandRegistrar extends BaseCommandRegistrar {
521
524
  }
522
525
  }
523
526
  catch (error) {
524
- this.logWarning(`Could not remove: ${pidFile} (${error.message})`);
527
+ const err = error;
528
+ this.logWarning(`Could not remove: ${pidFile} (${err.message})`);
525
529
  }
526
530
  }
527
531
  }
@@ -573,7 +577,8 @@ export class DaemonCommandRegistrar extends BaseCommandRegistrar {
573
577
  }
574
578
  }
575
579
  catch (error) {
576
- throw new Error(`Cleanup failed: ${error.message}`);
580
+ const err = error;
581
+ throw new Error(`Cleanup failed: ${err.message}`);
577
582
  }
578
583
  }
579
584
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lsh-framework",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "Encrypted secrets manager with automatic rotation, team sync, and multi-environment support. Built on a powerful shell with daemon scheduling and CI/CD integration.",
5
5
  "main": "dist/app.js",
6
6
  "bin": {