lsh-framework 1.4.0 → 1.4.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.
package/.env.example CHANGED
@@ -1,5 +1,16 @@
1
- # LSH Shell - Environment Configuration
2
- # Copy this file to .env and update with your actual values
1
+ # LSH Shell - Environment Configuration (DEPRECATED for LSH config)
2
+ #
3
+ # ⚠️ IMPORTANT: LSH configuration should now be in ~/.config/lsh/lshrc
4
+ #
5
+ # Use: lsh config # Edit configuration
6
+ # lsh config set KEY val # Set individual values
7
+ #
8
+ # This .env.example file is kept for reference and backward compatibility.
9
+ # For new installations, use: lsh config init
10
+ #
11
+ # Priority: Environment variables > ~/.config/lsh/lshrc > defaults
12
+ #
13
+ # Use .env files ONLY for application secrets, NOT for LSH configuration
3
14
 
4
15
  # Core Configuration
5
16
  USER=your_username
package/README.md CHANGED
@@ -698,6 +698,21 @@ npm run lint
698
698
  npm run lint:fix
699
699
  ```
700
700
 
701
+ ### Git Hooks
702
+
703
+ Install git hooks for automatic linting before commits:
704
+
705
+ ```bash
706
+ # Install hooks
707
+ ./scripts/install-git-hooks.sh
708
+
709
+ # Hooks will run automatically on git commit
710
+ # To skip hooks on a specific commit:
711
+ git commit --no-verify
712
+ ```
713
+
714
+ The pre-commit hook runs `npm run lint` and blocks commits if linting fails.
715
+
701
716
  ### From Source
702
717
 
703
718
  ```bash
@@ -272,12 +272,16 @@ export class ConfigManager {
272
272
  }
273
273
  /**
274
274
  * Merge config with process.env
275
- * Config file values take precedence over environment variables
275
+ * Config file values are loaded into process.env, but existing environment
276
+ * variables take precedence (config provides defaults)
276
277
  */
277
278
  mergeWithEnv() {
278
279
  for (const [key, value] of Object.entries(this.config)) {
279
280
  if (value !== undefined && value !== '') {
280
- process.env[key] = value;
281
+ // Only set if not already in environment (env vars take precedence)
282
+ if (!process.env[key]) {
283
+ process.env[key] = value;
284
+ }
281
285
  }
282
286
  }
283
287
  }
@@ -68,6 +68,16 @@ export class DatabasePersistence {
68
68
  return false;
69
69
  }
70
70
  }
71
+ /**
72
+ * Cleanup resources (stop timers, close connections)
73
+ * Call this when done to allow process to exit
74
+ */
75
+ async cleanup() {
76
+ if (this.localStorage) {
77
+ await this.localStorage.cleanup();
78
+ }
79
+ // Supabase client doesn't need cleanup (no persistent connections)
80
+ }
71
81
  /**
72
82
  * Save shell history entry
73
83
  */
@@ -22,6 +22,13 @@ export class SecretsManager {
22
22
  this.gitInfo = getGitRepoInfo();
23
23
  }
24
24
  }
25
+ /**
26
+ * Cleanup resources (stop timers, close connections)
27
+ * Call this when done to allow process to exit
28
+ */
29
+ async cleanup() {
30
+ await this.persistence.cleanup();
31
+ }
25
32
  /**
26
33
  * Get default encryption key from environment or machine
27
34
  */
@@ -16,15 +16,19 @@ export async function init_secrets(program) {
16
16
  .option('-e, --env <name>', 'Environment name (dev/staging/prod)', 'dev')
17
17
  .option('--force', 'Force push even if destructive changes detected')
18
18
  .action(async (options) => {
19
+ const manager = new SecretsManager();
19
20
  try {
20
- const manager = new SecretsManager();
21
21
  await manager.push(options.file, options.env, options.force);
22
22
  }
23
23
  catch (error) {
24
24
  const err = error;
25
25
  console.error('❌ Failed to push secrets:', err.message);
26
+ await manager.cleanup();
26
27
  process.exit(1);
27
28
  }
29
+ finally {
30
+ await manager.cleanup();
31
+ }
28
32
  });
29
33
  // Pull secrets from cloud
30
34
  program
@@ -34,15 +38,19 @@ export async function init_secrets(program) {
34
38
  .option('-e, --env <name>', 'Environment name (dev/staging/prod)', 'dev')
35
39
  .option('--force', 'Overwrite without creating backup')
36
40
  .action(async (options) => {
41
+ const manager = new SecretsManager();
37
42
  try {
38
- const manager = new SecretsManager();
39
43
  await manager.pull(options.file, options.env, options.force);
40
44
  }
41
45
  catch (error) {
42
46
  const err = error;
43
47
  console.error('❌ Failed to pull secrets:', err.message);
48
+ await manager.cleanup();
44
49
  process.exit(1);
45
50
  }
51
+ finally {
52
+ await manager.cleanup();
53
+ }
46
54
  });
47
55
  // List current local secrets
48
56
  program
@@ -262,8 +270,8 @@ API_KEY=
262
270
  .option('--load', 'Output eval-able export commands for loading secrets')
263
271
  .option('--force', 'Force sync even if destructive changes detected')
264
272
  .action(async (options) => {
273
+ const manager = new SecretsManager();
265
274
  try {
266
- const manager = new SecretsManager();
267
275
  if (options.legacy) {
268
276
  // Use legacy sync (suggestions only)
269
277
  await manager.sync(options.file, options.env);
@@ -276,8 +284,12 @@ API_KEY=
276
284
  catch (error) {
277
285
  const err = error;
278
286
  console.error('❌ Failed to sync:', err.message);
287
+ await manager.cleanup();
279
288
  process.exit(1);
280
289
  }
290
+ finally {
291
+ await manager.cleanup();
292
+ }
281
293
  });
282
294
  // Status command - get detailed status info
283
295
  program
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lsh-framework",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Simple, cross-platform encrypted secrets manager with automatic sync and multi-environment support. Just run lsh sync and start managing your secrets.",
5
5
  "main": "dist/app.js",
6
6
  "bin": {