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
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Platform Utilities
3
+ * Cross-platform path and environment handling for Windows, macOS, and Linux
4
+ */
5
+ import * as path from 'path';
6
+ import * as os from 'os';
7
+ /**
8
+ * Get platform-specific paths
9
+ * Handles differences between Windows, macOS, and Linux
10
+ */
11
+ export function getPlatformPaths(appName = 'lsh') {
12
+ const isWindows = process.platform === 'win32';
13
+ const isMac = process.platform === 'darwin';
14
+ // Temporary directory
15
+ const tmpDir = os.tmpdir();
16
+ // Home directory
17
+ const homeDir = os.homedir();
18
+ // Username
19
+ const user = os.userInfo().username;
20
+ // Application-specific temporary file paths
21
+ const pidFile = path.join(tmpDir, `${appName}-daemon-${user}.pid`);
22
+ const logFile = path.join(tmpDir, `${appName}-daemon-${user}.log`);
23
+ // Socket/IPC path (platform-specific)
24
+ // Windows uses Named Pipes, Unix systems use Unix Domain Sockets
25
+ const socketPath = isWindows
26
+ ? `\\\\.\\pipe\\${appName}-daemon-${user}`
27
+ : path.join(tmpDir, `${appName}-daemon-${user}.sock`);
28
+ // Configuration directory
29
+ // Windows: %APPDATA%\lsh
30
+ // macOS: ~/Library/Application Support/lsh
31
+ // Linux: ~/.config/lsh
32
+ let configDir;
33
+ if (isWindows) {
34
+ configDir = path.join(process.env.APPDATA || path.join(homeDir, 'AppData', 'Roaming'), appName);
35
+ }
36
+ else if (isMac) {
37
+ configDir = path.join(homeDir, 'Library', 'Application Support', appName);
38
+ }
39
+ else {
40
+ configDir = path.join(homeDir, '.config', appName);
41
+ }
42
+ // Data directory
43
+ // Windows: %LOCALAPPDATA%\lsh
44
+ // macOS: ~/Library/Application Support/lsh
45
+ // Linux: ~/.local/share/lsh
46
+ let dataDir;
47
+ if (isWindows) {
48
+ dataDir = path.join(process.env.LOCALAPPDATA || path.join(homeDir, 'AppData', 'Local'), appName);
49
+ }
50
+ else if (isMac) {
51
+ dataDir = path.join(homeDir, 'Library', 'Application Support', appName);
52
+ }
53
+ else {
54
+ dataDir = path.join(homeDir, '.local', 'share', appName);
55
+ }
56
+ return {
57
+ tmpDir,
58
+ homeDir,
59
+ user,
60
+ pidFile,
61
+ logFile,
62
+ socketPath,
63
+ configDir,
64
+ dataDir,
65
+ };
66
+ }
67
+ /**
68
+ * Normalize path for current platform
69
+ */
70
+ export function normalizePath(inputPath) {
71
+ return path.normalize(inputPath);
72
+ }
73
+ /**
74
+ * Check if running on Windows
75
+ */
76
+ export function isWindows() {
77
+ return process.platform === 'win32';
78
+ }
79
+ /**
80
+ * Check if running on macOS
81
+ */
82
+ export function isMacOS() {
83
+ return process.platform === 'darwin';
84
+ }
85
+ /**
86
+ * Check if running on Linux
87
+ */
88
+ export function isLinux() {
89
+ return process.platform === 'linux';
90
+ }
91
+ /**
92
+ * Get platform name
93
+ */
94
+ export function getPlatformName() {
95
+ const platform = process.platform;
96
+ switch (platform) {
97
+ case 'win32':
98
+ return 'Windows';
99
+ case 'darwin':
100
+ return 'macOS';
101
+ case 'linux':
102
+ return 'Linux';
103
+ default:
104
+ return platform;
105
+ }
106
+ }
107
+ /**
108
+ * Get environment variable with fallback
109
+ * Handles Windows vs Unix differences (e.g., HOME vs USERPROFILE)
110
+ */
111
+ export function getEnvVar(unixVar, windowsVar) {
112
+ if (isWindows() && windowsVar) {
113
+ return process.env[windowsVar] || process.env[unixVar];
114
+ }
115
+ return process.env[unixVar];
116
+ }
117
+ /**
118
+ * Ensure directory exists, create if needed (cross-platform)
119
+ */
120
+ export async function ensureDir(dirPath) {
121
+ const fs = await import('fs/promises');
122
+ try {
123
+ await fs.mkdir(dirPath, { recursive: true });
124
+ }
125
+ catch (error) {
126
+ // Ignore if directory already exists
127
+ if (error.code !== 'EEXIST') {
128
+ throw error;
129
+ }
130
+ }
131
+ }
132
+ /**
133
+ * Get shell executable path for current platform
134
+ */
135
+ export function getDefaultShell() {
136
+ if (isWindows()) {
137
+ return process.env.COMSPEC || 'cmd.exe';
138
+ }
139
+ return process.env.SHELL || '/bin/sh';
140
+ }
141
+ /**
142
+ * Get path separator for current platform
143
+ */
144
+ export function getPathSeparator() {
145
+ return path.delimiter; // : on Unix, ; on Windows
146
+ }
147
+ /**
148
+ * Join paths with platform-appropriate separator
149
+ */
150
+ export function joinPaths(...paths) {
151
+ return path.join(...paths);
152
+ }
153
+ /**
154
+ * Convert Unix-style path to platform path
155
+ */
156
+ export function toPlatformPath(unixPath) {
157
+ if (isWindows()) {
158
+ return unixPath.replace(/\//g, '\\');
159
+ }
160
+ return unixPath;
161
+ }
162
+ /**
163
+ * Convert platform path to Unix-style path
164
+ */
165
+ export function toUnixPath(platformPath) {
166
+ return platformPath.replace(/\\/g, '/');
167
+ }
168
+ /**
169
+ * Get executable extension for current platform
170
+ */
171
+ export function getExecutableExtension() {
172
+ return isWindows() ? '.exe' : '';
173
+ }
174
+ /**
175
+ * Check if a path is absolute (cross-platform)
176
+ */
177
+ export function isAbsolutePath(inputPath) {
178
+ return path.isAbsolute(inputPath);
179
+ }
180
+ /**
181
+ * Resolve path relative to home directory
182
+ */
183
+ export function resolveHomePath(relativePath) {
184
+ if (relativePath.startsWith('~')) {
185
+ const homeDir = os.homedir();
186
+ return path.join(homeDir, relativePath.slice(1));
187
+ }
188
+ return relativePath;
189
+ }
190
+ /**
191
+ * Get platform-specific line ending
192
+ */
193
+ export function getLineEnding() {
194
+ return isWindows() ? '\r\n' : '\n';
195
+ }
196
+ /**
197
+ * Get comprehensive platform information
198
+ */
199
+ export function getPlatformInfo() {
200
+ const paths = getPlatformPaths();
201
+ return {
202
+ platform: process.platform,
203
+ platformName: getPlatformName(),
204
+ arch: process.arch,
205
+ release: os.release(),
206
+ nodeVersion: process.version,
207
+ homeDir: paths.homeDir,
208
+ tmpDir: paths.tmpDir,
209
+ user: paths.user,
210
+ };
211
+ }
@@ -340,7 +340,7 @@ export class SecretsManager {
340
340
  /**
341
341
  * Show secrets (masked)
342
342
  */
343
- async show(environment = 'dev') {
343
+ async show(environment = 'dev', format = 'env') {
344
344
  const jobs = await this.persistence.getActiveJobs();
345
345
  const secretsJobs = jobs
346
346
  .filter(j => j.command === 'secrets_sync' && j.job_id.includes(environment))
@@ -355,6 +355,16 @@ export class SecretsManager {
355
355
  }
356
356
  const decrypted = this.decrypt(latestSecret.output);
357
357
  const env = this.parseEnvFile(decrypted);
358
+ // Convert to array format for formatSecrets
359
+ const secrets = Object.entries(env).map(([key, value]) => ({ key, value }));
360
+ // Use format utilities if not default env format
361
+ if (format !== 'env') {
362
+ const { formatSecrets } = await import('./format-utils.js');
363
+ const output = formatSecrets(secrets, format, false); // No masking for structured formats
364
+ console.log(output);
365
+ return;
366
+ }
367
+ // Default env format with masking (legacy behavior)
358
368
  console.log(`\n📦 Secrets for ${environment} (${Object.keys(env).length} total):\n`);
359
369
  for (const [key, value] of Object.entries(env)) {
360
370
  const masked = value.length > 4
@@ -0,0 +1,128 @@
1
+ /**
2
+ * String Utilities
3
+ *
4
+ * Helper functions for working with strings, especially for formatting
5
+ * constant template strings with dynamic values.
6
+ */
7
+ /**
8
+ * Format a template string by replacing ${varName} placeholders with values
9
+ *
10
+ * @param template - Template string with ${varName} placeholders
11
+ * @param vars - Object mapping variable names to values
12
+ * @returns Formatted string
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { ERRORS } from '../constants/index.js';
17
+ * import { formatMessage } from './string-utils.js';
18
+ *
19
+ * const error = formatMessage(ERRORS.JOB_NOT_FOUND, { jobId: '12345' });
20
+ * // Returns: "Job 12345 not found"
21
+ * ```
22
+ */
23
+ export function formatMessage(template, vars) {
24
+ let result = template;
25
+ // Sort keys by length (longest first) to prevent overlapping variable name issues
26
+ // Example: if we have both 'id' and 'jobId', we want to replace 'jobId' first
27
+ const sortedEntries = Object.entries(vars).sort((a, b) => b[0].length - a[0].length);
28
+ for (const [key, value] of sortedEntries) {
29
+ const placeholder = `\${${key}}`;
30
+ // Use replaceAll with literal string to avoid regex escaping complexity
31
+ result = result.replaceAll(placeholder, String(value));
32
+ }
33
+ return result;
34
+ }
35
+ /**
36
+ * Format a path template by replacing ${VAR} placeholders with environment variables
37
+ *
38
+ * @param pathTemplate - Path template with ${VAR} placeholders
39
+ * @param fallbacks - Optional fallback values for variables
40
+ * @returns Formatted path
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * import { PATHS } from '../constants/index.js';
45
+ * import { formatPath } from './string-utils.js';
46
+ *
47
+ * const socketPath = formatPath(PATHS.DAEMON_SOCKET_TEMPLATE, { USER: 'default' });
48
+ * // Returns: "/tmp/lsh-job-daemon-johndoe.sock" (if USER env var is johndoe)
49
+ * // Or: "/tmp/lsh-job-daemon-default.sock" (if USER env var is not set)
50
+ * ```
51
+ */
52
+ export function formatPath(pathTemplate, fallbacks = {}) {
53
+ let result = pathTemplate;
54
+ const pattern = /\$\{([^}]+)\}/g;
55
+ const matches = Array.from(pathTemplate.matchAll(pattern));
56
+ // Process matches to collect unique variable names and their values
57
+ const replacements = new Map();
58
+ for (const match of matches) {
59
+ const varName = match[1];
60
+ if (!replacements.has(match[0])) {
61
+ const value = process.env[varName] || fallbacks[varName] || '';
62
+ replacements.set(match[0], value);
63
+ }
64
+ }
65
+ // Replace all occurrences of each placeholder
66
+ for (const [placeholder, value] of replacements) {
67
+ result = result.replaceAll(placeholder, value);
68
+ }
69
+ return result;
70
+ }
71
+ /**
72
+ * Truncate a string to a maximum length, adding ellipsis if needed
73
+ *
74
+ * @param str - String to truncate
75
+ * @param maxLength - Maximum length (default: 50)
76
+ * @param ellipsis - Ellipsis to append (default: '...')
77
+ * @returns Truncated string
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * truncate('This is a very long error message', 20);
82
+ * // Returns: "This is a very lo..."
83
+ * ```
84
+ */
85
+ export function truncate(str, maxLength = 50, ellipsis = '...') {
86
+ // Validate that maxLength is greater than ellipsis length
87
+ if (maxLength < ellipsis.length) {
88
+ throw new Error(`maxLength (${maxLength}) must be greater than or equal to ellipsis length (${ellipsis.length})`);
89
+ }
90
+ if (str.length <= maxLength) {
91
+ return str;
92
+ }
93
+ return str.substring(0, maxLength - ellipsis.length) + ellipsis;
94
+ }
95
+ /**
96
+ * Escape special characters in a string for use in a regular expression
97
+ *
98
+ * @param str - String to escape
99
+ * @returns Escaped string
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * escapeRegex('test.file');
104
+ * // Returns: "test\\.file"
105
+ * ```
106
+ */
107
+ export function escapeRegex(str) {
108
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
109
+ }
110
+ /**
111
+ * Pluralize a word based on count
112
+ *
113
+ * @param count - Count to check
114
+ * @param singular - Singular form
115
+ * @param plural - Plural form (default: singular + 's')
116
+ * @returns Pluralized string with count
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * pluralize(1, 'job'); // "1 job"
121
+ * pluralize(5, 'job'); // "5 jobs"
122
+ * pluralize(2, 'query', 'queries'); // "2 queries"
123
+ * ```
124
+ */
125
+ export function pluralize(count, singular, plural) {
126
+ const pluralForm = plural || `${singular}s`;
127
+ return `${count} ${count === 1 ? singular : pluralForm}`;
128
+ }
@@ -6,6 +6,7 @@ import { BaseCommandRegistrar } from '../../lib/base-command-registrar.js';
6
6
  import * as fs from 'fs';
7
7
  import { exec } from 'child_process';
8
8
  import { promisify } from 'util';
9
+ import { getPlatformPaths } from '../../lib/platform-utils.js';
9
10
  const execAsync = promisify(exec);
10
11
  export class DaemonCommandRegistrar extends BaseCommandRegistrar {
11
12
  constructor() {
@@ -43,8 +44,8 @@ export class DaemonCommandRegistrar extends BaseCommandRegistrar {
43
44
  description: 'Start the daemon',
44
45
  action: async () => {
45
46
  const { spawn } = await import('child_process');
46
- const socketPath = `/tmp/lsh-job-daemon-${process.env.USER || 'user'}.sock`;
47
- const daemonProcess = spawn('node', ['dist/daemon/lshd.js', 'start', socketPath], {
47
+ const platformPaths = getPlatformPaths('lsh');
48
+ const daemonProcess = spawn('node', ['dist/daemon/lshd.js', 'start', platformPaths.socketPath], {
48
49
  detached: true,
49
50
  stdio: 'ignore'
50
51
  });
@@ -51,6 +51,8 @@ export async function init_secrets(program) {
51
51
  .description('List secrets in the current local .env file')
52
52
  .option('-f, --file <path>', 'Path to .env file', '.env')
53
53
  .option('--keys-only', 'Show only keys, not values')
54
+ .option('--format <type>', 'Output format: env, json, yaml, toml, export', 'env')
55
+ .option('--no-mask', 'Show full values (default: auto based on format)')
54
56
  .action(async (options) => {
55
57
  try {
56
58
  const envPath = path.resolve(options.file);
@@ -81,24 +83,38 @@ export async function init_secrets(program) {
81
83
  console.log('No secrets found in .env file');
82
84
  return;
83
85
  }
84
- console.log(`\n📋 Secrets in ${options.file}:\n`);
85
- for (const { key, value } of secrets) {
86
- if (options.keysOnly) {
86
+ // Handle keys-only mode
87
+ if (options.keysOnly) {
88
+ console.log(`\n📋 Keys in ${options.file}:\n`);
89
+ for (const { key } of secrets) {
87
90
  console.log(` ${key}`);
88
91
  }
89
- else {
90
- // Mask the value but show first/last 3 chars if long enough
91
- let maskedValue = value;
92
- if (value.length > 8) {
93
- maskedValue = `${value.substring(0, 3)}${'*'.repeat(value.length - 6)}${value.substring(value.length - 3)}`;
94
- }
95
- else if (value.length > 0) {
96
- maskedValue = '*'.repeat(value.length);
97
- }
98
- console.log(` ${key}=${maskedValue}`);
99
- }
92
+ console.log(`\n Total: ${secrets.length} keys\n`);
93
+ return;
94
+ }
95
+ // Handle format output
96
+ const format = options.format.toLowerCase();
97
+ const validFormats = ['env', 'json', 'yaml', 'toml', 'export'];
98
+ if (!validFormats.includes(format)) {
99
+ console.error(`❌ Invalid format: ${format}`);
100
+ console.log(`Valid formats: ${validFormats.join(', ')}`);
101
+ process.exit(1);
102
+ }
103
+ // Import format utilities dynamically
104
+ const { formatSecrets } = await import('../../lib/format-utils.js');
105
+ // Determine masking behavior
106
+ const shouldMask = options.mask !== false ? undefined : false;
107
+ const output = formatSecrets(secrets, format, shouldMask);
108
+ // Only show header for default env format
109
+ if (format === 'env') {
110
+ console.log(`\n📋 Secrets in ${options.file}:\n`);
111
+ console.log(output);
112
+ console.log(`\n Total: ${secrets.length} secrets\n`);
113
+ }
114
+ else {
115
+ // For structured formats, output directly (no decoration)
116
+ console.log(output);
100
117
  }
101
- console.log(`\n Total: ${secrets.length} secrets\n`);
102
118
  }
103
119
  catch (error) {
104
120
  const err = error;
@@ -111,6 +127,7 @@ export async function init_secrets(program) {
111
127
  .command('env [environment]')
112
128
  .description('List all stored environments or show secrets for specific environment')
113
129
  .option('--all-files', 'List all tracked .env files across environments')
130
+ .option('--format <type>', 'Output format: env, json, yaml, toml, export', 'env')
114
131
  .action(async (environment, options) => {
115
132
  try {
116
133
  const manager = new SecretsManager();
@@ -130,7 +147,14 @@ export async function init_secrets(program) {
130
147
  }
131
148
  // If environment specified, show secrets for that environment
132
149
  if (environment) {
133
- await manager.show(environment);
150
+ const format = options.format.toLowerCase();
151
+ const validFormats = ['env', 'json', 'yaml', 'toml', 'export'];
152
+ if (!validFormats.includes(format)) {
153
+ console.error(`❌ Invalid format: ${format}`);
154
+ console.log(`Valid formats: ${validFormats.join(', ')}`);
155
+ process.exit(1);
156
+ }
157
+ await manager.show(environment, format);
134
158
  return;
135
159
  }
136
160
  // Otherwise, list all environments
@@ -378,7 +402,8 @@ API_KEY=
378
402
  .description('Get a specific secret value from .env file, or all secrets with --all')
379
403
  .option('-f, --file <path>', 'Path to .env file', '.env')
380
404
  .option('--all', 'Get all secrets from the file')
381
- .option('--export', 'Output in export format for shell evaluation')
405
+ .option('--export', 'Output in export format for shell evaluation (alias for --format export)')
406
+ .option('--format <type>', 'Output format: env, json, yaml, toml, export', 'env')
382
407
  .action(async (key, options) => {
383
408
  try {
384
409
  const envPath = path.resolve(options.file);
@@ -406,20 +431,19 @@ API_KEY=
406
431
  secrets.push({ key, value });
407
432
  }
408
433
  }
409
- if (options.export) {
410
- // Output in export format for shell evaluation
411
- for (const { key, value } of secrets) {
412
- // Escape single quotes in value and wrap in single quotes
413
- const escapedValue = value.replace(/'/g, "'\\''");
414
- console.log(`export ${key}='${escapedValue}'`);
415
- }
416
- }
417
- else {
418
- // Output in KEY=VALUE format
419
- for (const { key, value } of secrets) {
420
- console.log(`${key}=${value}`);
421
- }
434
+ // Handle format output
435
+ const format = options.export ? 'export' : options.format.toLowerCase();
436
+ const validFormats = ['env', 'json', 'yaml', 'toml', 'export'];
437
+ if (!validFormats.includes(format)) {
438
+ console.error(`❌ Invalid format: ${format}`);
439
+ console.log(`Valid formats: ${validFormats.join(', ')}`);
440
+ process.exit(1);
422
441
  }
442
+ // Import format utilities dynamically
443
+ const { formatSecrets } = await import('../../lib/format-utils.js');
444
+ // For get --all, always show full values (no masking)
445
+ const output = formatSecrets(secrets, format, false);
446
+ console.log(output);
423
447
  return;
424
448
  }
425
449
  // Handle single key lookup
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lsh-framework",
3
- "version": "1.2.0",
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.",
3
+ "version": "1.2.1",
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": {
7
7
  "lsh": "./dist/cli.js"
@@ -16,24 +16,13 @@
16
16
  },
17
17
  "scripts": {
18
18
  "build": "tsc",
19
- "compile-ts": "tsc -b",
20
- "compile-nexe": "node build.js",
21
- "build-bin": "npm run clean; npm run compile-ts; npm run compile-nexe",
22
- "start": "node dist/app.js",
23
- "start:pipeline": "npm run compile-ts && node dist/pipeline/pipeline-service.js",
24
19
  "watch": "tsc --watch",
25
20
  "test": "node --experimental-vm-modules ./node_modules/.bin/jest",
26
21
  "test:coverage": "node --experimental-vm-modules ./node_modules/.bin/jest --coverage",
27
- "test:integration": "npm run test -- --testMatch=\"**/*.integration.test.(js|ts)\"",
28
22
  "clean": "rm -rf ./build; rm -rf ./bin; rm -rf ./dist",
29
- "electron": "npm run compile-ts && electron src/electron/main.cjs",
30
- "electron-dev": "NODE_ENV=development npm run electron",
31
- "dashboard": "npm run electron",
32
- "app": "npm run electron",
33
23
  "lint": "eslint src --ext .js,.ts,.tsx",
34
24
  "lint:fix": "eslint src --ext .js,.ts,.tsx --fix",
35
- "typecheck": "tsc --noEmit",
36
- "audit:security": "npm audit --audit-level moderate"
25
+ "typecheck": "tsc --noEmit"
37
26
  },
38
27
  "keywords": [
39
28
  "secrets-manager",
@@ -44,17 +33,11 @@
44
33
  "encryption",
45
34
  "credential-management",
46
35
  "team-sync",
47
- "secrets-rotation",
48
36
  "multi-environment",
49
37
  "devops",
50
38
  "security",
51
- "shell",
52
- "automation",
53
- "cron",
54
- "daemon",
55
- "job-scheduler",
56
- "cicd",
57
- "cli"
39
+ "cli",
40
+ "cross-platform"
58
41
  ],
59
42
  "engines": {
60
43
  "node": ">=20.18.0",
@@ -74,76 +57,29 @@
74
57
  "package.json"
75
58
  ],
76
59
  "dependencies": {
77
- "@deck.gl/core": "^8.9.33",
78
- "@inkjs/ui": "^1.0.0",
79
- "@octokit/rest": "^20.1.0",
80
60
  "@supabase/supabase-js": "^2.57.4",
81
- "@types/ink": "^2.0.3",
82
- "@types/ioredis": "^4.28.10",
83
- "@types/socket.io": "^3.0.1",
84
- "@xstate/react": "^4.1.0",
85
- "async": "^3.2.5",
86
- "async-lock": "^1.4.0",
87
- "axios": "^1.5.1",
88
- "bcrypt": "^5.1.1",
89
61
  "chalk": "^5.3.0",
90
- "cheerio": "^1.0.0-rc.12",
91
62
  "chokidar": "^3.6.0",
92
63
  "commander": "^10.0.1",
93
- "cors": "^2.8.5",
94
- "csv": "^6.3.5",
95
64
  "dotenv": "^16.4.5",
96
- "express": "^5.1.0",
97
- "fprint": "^2.0.1",
98
65
  "glob": "^10.3.12",
99
- "gradstop": "^2.2.3",
100
- "helmet": "^8.1.0",
101
- "highlightjs": "^9.16.2",
102
- "http-proxy-middleware": "^3.0.5",
103
- "ink": "^4.4.1",
104
- "ink-text-input": "^5.0.1",
105
66
  "inquirer": "^9.2.12",
106
- "ioredis": "^5.8.0",
107
- "jsonwebtoken": "^9.0.2",
108
- "lodash": "^4.17.21",
109
- "lsh-framework": "^0.8.2",
67
+ "js-yaml": "^4.1.0",
110
68
  "node-cron": "^3.0.3",
111
- "node-fetch": "^3.3.2",
112
69
  "ora": "^8.0.1",
113
- "path": "^0.12.7",
114
70
  "pg": "^8.16.3",
115
- "react": "^18.2.0",
116
- "repl": "^0.1.3",
117
- "sendgrid": "^5.2.3",
118
- "socket.io": "^4.8.1",
119
- "uuid": "^10.0.0",
120
- "xstate": "^5.9.1",
121
- "zx": "^7.2.3"
71
+ "smol-toml": "^1.3.1",
72
+ "uuid": "^10.0.0"
122
73
  },
123
74
  "devDependencies": {
124
- "@babel/preset-env": "^7.23.2",
125
- "@babel/preset-react": "^7.24.1",
126
- "@types/async-lock": "^1.4.2",
127
75
  "@types/jest": "^30.0.0",
76
+ "@types/js-yaml": "^4.0.9",
128
77
  "@types/node": "^20.12.7",
129
- "@types/react": "^18.2.73",
130
- "@types/request": "^2.48.12",
131
- "@types/supertest": "^6.0.3",
132
78
  "@typescript-eslint/eslint-plugin": "^8.44.1",
133
79
  "@typescript-eslint/parser": "^8.44.1",
134
- "babel-jest": "^29.7.0",
135
- "electron": "^38.1.2",
136
80
  "eslint": "^9.36.0",
137
- "eslint-plugin-react": "^7.37.5",
138
- "eslint-plugin-react-hooks": "^5.2.0",
139
81
  "jest": "^29.7.0",
140
- "mocha": "^10.3.0",
141
- "ncc": "^0.3.6",
142
- "nexe": "^4.0.0-rc.2",
143
- "nodemon": "^3.0.1",
144
- "supertest": "^7.1.4",
145
82
  "ts-jest": "^29.2.5",
146
- "typescript": "^5.4.5",
147
- "zapier-platform-core": "15.4.1"
83
+ "typescript": "^5.4.5"
148
84
  }
149
85
  }