lsh-framework 3.1.17 ā 3.1.19
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/dist/cli.js +22 -46
- package/dist/commands/sync.js +172 -35
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -10,13 +10,9 @@ import { registerDoctorCommands } from './commands/doctor.js';
|
|
|
10
10
|
import { registerCompletionCommands } from './commands/completion.js';
|
|
11
11
|
import { registerConfigCommands } from './commands/config.js';
|
|
12
12
|
import { registerSyncHistoryCommands } from './commands/sync-history.js';
|
|
13
|
-
import { registerIPFSCommands } from './commands/ipfs.js';
|
|
14
13
|
import { registerSyncCommands } from './commands/sync.js';
|
|
15
14
|
import { registerMigrateCommand } from './commands/migrate.js';
|
|
16
15
|
import { registerContextCommand } from './commands/context.js';
|
|
17
|
-
import { init_daemon } from './services/daemon/daemon.js';
|
|
18
|
-
import { init_supabase } from './services/supabase/supabase.js';
|
|
19
|
-
import { init_cron } from './services/cron/cron.js';
|
|
20
16
|
import { init_secrets } from './services/secrets/secrets.js';
|
|
21
17
|
import { loadGlobalConfigSync } from './lib/config-manager.js';
|
|
22
18
|
import * as fs from 'fs';
|
|
@@ -67,22 +63,20 @@ program
|
|
|
67
63
|
console.log(' delete Delete .env file');
|
|
68
64
|
console.log(' status Get detailed secrets status');
|
|
69
65
|
console.log('');
|
|
70
|
-
console.log('š
|
|
71
|
-
console.log('
|
|
72
|
-
console.log('
|
|
73
|
-
console.log('
|
|
66
|
+
console.log('š IPFS Sync:');
|
|
67
|
+
console.log(' sync init Full IPFS setup (install, init, start)');
|
|
68
|
+
console.log(' sync push Push secrets to IPFS ā get CID');
|
|
69
|
+
console.log(' sync pull <cid> Pull secrets by CID');
|
|
70
|
+
console.log(' sync status Check IPFS and sync status');
|
|
71
|
+
console.log(' sync start/stop Control IPFS daemon');
|
|
74
72
|
console.log('');
|
|
75
73
|
console.log('š Quick Start:');
|
|
76
|
-
console.log(' lsh init
|
|
77
|
-
console.log(' lsh
|
|
78
|
-
console.log(' lsh
|
|
79
|
-
console.log(' lsh pull --env dev # Pull on another machine');
|
|
74
|
+
console.log(' lsh sync init # One-time IPFS setup');
|
|
75
|
+
console.log(' lsh sync push # Push secrets to IPFS');
|
|
76
|
+
console.log(' lsh sync pull <cid> # Pull on another machine');
|
|
80
77
|
console.log('');
|
|
81
78
|
console.log('š More Commands:');
|
|
82
79
|
console.log(' config Manage LSH configuration (~/.config/lsh/lshrc)');
|
|
83
|
-
console.log(' supabase Supabase database management');
|
|
84
|
-
console.log(' daemon Daemon management');
|
|
85
|
-
console.log(' cron Cron job management');
|
|
86
80
|
console.log(' self Self-management commands');
|
|
87
81
|
console.log(' --help Show all options');
|
|
88
82
|
console.log('');
|
|
@@ -148,16 +142,11 @@ function findSimilarCommands(input, validCommands) {
|
|
|
148
142
|
registerDoctorCommands(program);
|
|
149
143
|
registerConfigCommands(program);
|
|
150
144
|
registerSyncHistoryCommands(program);
|
|
151
|
-
registerIPFSCommands(program);
|
|
152
145
|
registerSyncCommands(program);
|
|
153
146
|
registerMigrateCommand(program);
|
|
154
147
|
registerContextCommand(program);
|
|
155
148
|
// Secrets management (primary feature)
|
|
156
149
|
await init_secrets(program);
|
|
157
|
-
// Supporting services
|
|
158
|
-
await init_supabase(program);
|
|
159
|
-
await init_daemon(program);
|
|
160
|
-
await init_cron(program);
|
|
161
150
|
// Shell completion
|
|
162
151
|
registerCompletionCommands(program);
|
|
163
152
|
// Self-management commands
|
|
@@ -246,50 +235,37 @@ function showDetailedHelp() {
|
|
|
246
235
|
console.log('Main Commands:');
|
|
247
236
|
console.log(' init Interactive setup wizard (first-time)');
|
|
248
237
|
console.log(' doctor Health check & troubleshooting');
|
|
249
|
-
console.log('
|
|
250
|
-
console.log(' push Upload encrypted secrets');
|
|
251
|
-
console.log(' pull Download encrypted secrets');
|
|
252
|
-
console.log(' list List local secrets');
|
|
253
|
-
console.log(' env Manage environments');
|
|
238
|
+
console.log(' env Show local .env file contents');
|
|
254
239
|
console.log(' key Generate encryption key');
|
|
255
240
|
console.log(' status Detailed status report');
|
|
256
241
|
console.log('');
|
|
257
|
-
console.log('
|
|
258
|
-
console.log('
|
|
259
|
-
console.log('
|
|
260
|
-
console.log('
|
|
261
|
-
console.log('
|
|
262
|
-
console.log('
|
|
242
|
+
console.log('IPFS Sync:');
|
|
243
|
+
console.log(' sync init Full IPFS setup (install, init, start)');
|
|
244
|
+
console.log(' sync push Push secrets to IPFS ā get CID');
|
|
245
|
+
console.log(' sync pull <cid> Pull secrets by CID');
|
|
246
|
+
console.log(' sync status Check IPFS client, daemon, and sync status');
|
|
247
|
+
console.log(' sync start Start IPFS daemon');
|
|
248
|
+
console.log(' sync stop Stop IPFS daemon');
|
|
249
|
+
console.log(' sync history View sync history');
|
|
263
250
|
console.log('');
|
|
264
251
|
console.log('Self-Management:');
|
|
265
252
|
console.log(' self update Update to latest version');
|
|
266
253
|
console.log(' self version Show version information');
|
|
267
254
|
console.log(' self uninstall Uninstall from system');
|
|
268
255
|
console.log('');
|
|
269
|
-
console.log('Database:');
|
|
270
|
-
console.log(' supabase init Initialize Supabase connection');
|
|
271
|
-
console.log(' supabase test Test Supabase connectivity');
|
|
272
|
-
console.log(' supabase reset Reset database schema');
|
|
273
|
-
console.log('');
|
|
274
256
|
console.log('Examples:');
|
|
275
257
|
console.log('');
|
|
276
258
|
console.log(' First-Time Setup:');
|
|
277
|
-
console.log(' lsh init
|
|
259
|
+
console.log(' lsh sync init # One-time IPFS setup');
|
|
278
260
|
console.log(' lsh doctor # Verify setup');
|
|
279
261
|
console.log('');
|
|
280
262
|
console.log(' Daily Usage:');
|
|
281
|
-
console.log(' lsh push
|
|
282
|
-
console.log(' lsh pull
|
|
283
|
-
console.log(' lsh
|
|
263
|
+
console.log(' lsh sync push # Push to IPFS ā get CID');
|
|
264
|
+
console.log(' lsh sync pull <cid> # Pull by CID');
|
|
265
|
+
console.log(' lsh env --masked # View local secrets');
|
|
284
266
|
console.log(' lsh get API_KEY # Get specific secret');
|
|
285
267
|
console.log(' lsh set API_KEY newvalue # Update secret');
|
|
286
268
|
console.log('');
|
|
287
|
-
console.log(' Automation:');
|
|
288
|
-
console.log(' lsh daemon start # Start daemon');
|
|
289
|
-
console.log(' lsh cron add --name rotate-keys \\');
|
|
290
|
-
console.log(' --schedule "0 0 * * *" \\');
|
|
291
|
-
console.log(' --command "./rotate.sh" # Daily rotation');
|
|
292
|
-
console.log('');
|
|
293
269
|
console.log('Features:');
|
|
294
270
|
console.log(' ā
Cross-platform (Windows, macOS, Linux)');
|
|
295
271
|
console.log(' ā
AES-256 encryption');
|
package/dist/commands/sync.js
CHANGED
|
@@ -10,6 +10,7 @@ import * as fs from 'fs';
|
|
|
10
10
|
import * as path from 'path';
|
|
11
11
|
import * as crypto from 'crypto';
|
|
12
12
|
import { getIPFSSync } from '../lib/ipfs-sync.js';
|
|
13
|
+
import { IPFSClientManager } from '../lib/ipfs-client-manager.js';
|
|
13
14
|
import { getGitRepoInfo } from '../lib/git-utils.js';
|
|
14
15
|
import { ENV_VARS } from '../constants/index.js';
|
|
15
16
|
/**
|
|
@@ -23,17 +24,21 @@ export function registerSyncCommands(program) {
|
|
|
23
24
|
// Show help when running `lsh sync` without subcommand
|
|
24
25
|
console.log(chalk.bold.cyan('\nš LSH Sync - IPFS Secrets Sync\n'));
|
|
25
26
|
console.log(chalk.gray('Sync encrypted secrets via native IPFS (no auth required)\n'));
|
|
26
|
-
console.log(chalk.bold('
|
|
27
|
-
console.log(` ${chalk.cyan('init')} š
|
|
27
|
+
console.log(chalk.bold('Setup:'));
|
|
28
|
+
console.log(` ${chalk.cyan('init')} š Full setup: install IPFS, initialize, and start daemon`);
|
|
29
|
+
console.log(` ${chalk.cyan('status')} š Show IPFS client, daemon, and sync status`);
|
|
30
|
+
console.log(` ${chalk.cyan('start')} ā¶ļø Start IPFS daemon`);
|
|
31
|
+
console.log(` ${chalk.cyan('stop')} ā¹ļø Stop IPFS daemon`);
|
|
32
|
+
console.log('');
|
|
33
|
+
console.log(chalk.bold('Sync:'));
|
|
28
34
|
console.log(` ${chalk.cyan('push')} ā¬ļø Push encrypted secrets to IPFS`);
|
|
29
35
|
console.log(` ${chalk.cyan('pull')} ā¬ļø Pull secrets from IPFS by CID`);
|
|
30
|
-
console.log(` ${chalk.cyan('status')} š Show IPFS daemon and sync status`);
|
|
31
36
|
console.log(` ${chalk.cyan('history')} š Show IPFS sync history`);
|
|
32
37
|
console.log(` ${chalk.cyan('verify')} ā
Verify that a CID is accessible on IPFS`);
|
|
33
38
|
console.log(` ${chalk.cyan('clear')} šļø Clear sync history`);
|
|
34
39
|
console.log('');
|
|
35
40
|
console.log(chalk.bold('Examples:'));
|
|
36
|
-
console.log(chalk.gray(' lsh sync init #
|
|
41
|
+
console.log(chalk.gray(' lsh sync init # One-time setup'));
|
|
37
42
|
console.log(chalk.gray(' lsh sync push # Push secrets, get CID'));
|
|
38
43
|
console.log(chalk.gray(' lsh sync pull <cid> # Pull secrets by CID'));
|
|
39
44
|
console.log('');
|
|
@@ -43,14 +48,16 @@ export function registerSyncCommands(program) {
|
|
|
43
48
|
// lsh sync init
|
|
44
49
|
syncCommand
|
|
45
50
|
.command('init')
|
|
46
|
-
.description('š
|
|
47
|
-
.
|
|
48
|
-
|
|
51
|
+
.description('š Full setup: install IPFS, initialize repo, and start daemon')
|
|
52
|
+
.option('-f, --force', 'Force reinstall even if already installed')
|
|
53
|
+
.action(async (options) => {
|
|
54
|
+
console.log(chalk.bold.cyan('\nš Setting up IPFS for sync...\n'));
|
|
55
|
+
const manager = new IPFSClientManager();
|
|
49
56
|
const ipfsSync = getIPFSSync();
|
|
50
|
-
// Check if daemon is already running
|
|
57
|
+
// Step 1: Check if daemon is already running
|
|
51
58
|
if (await ipfsSync.checkDaemon()) {
|
|
52
59
|
const info = await ipfsSync.getDaemonInfo();
|
|
53
|
-
console.log(chalk.green('ā
IPFS
|
|
60
|
+
console.log(chalk.green('ā
IPFS is already set up and running!'));
|
|
54
61
|
if (info) {
|
|
55
62
|
console.log(chalk.gray(` Peer ID: ${info.peerId.substring(0, 16)}...`));
|
|
56
63
|
console.log(chalk.gray(` Version: ${info.version}`));
|
|
@@ -61,22 +68,62 @@ export function registerSyncCommands(program) {
|
|
|
61
68
|
console.log('');
|
|
62
69
|
return;
|
|
63
70
|
}
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
// Step 2: Check if IPFS is installed
|
|
72
|
+
const clientInfo = await manager.detect();
|
|
73
|
+
if (!clientInfo.installed || options.force) {
|
|
74
|
+
const installSpinner = ora('Installing IPFS client (Kubo)...').start();
|
|
75
|
+
try {
|
|
76
|
+
await manager.install({ force: options.force });
|
|
77
|
+
installSpinner.succeed(chalk.green('IPFS client installed'));
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
const err = error;
|
|
81
|
+
installSpinner.fail(chalk.red('Failed to install IPFS'));
|
|
82
|
+
console.error(chalk.red(err.message));
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
console.log(chalk.green('ā
IPFS client already installed'));
|
|
88
|
+
console.log(chalk.gray(` Version: ${clientInfo.version}`));
|
|
89
|
+
}
|
|
90
|
+
// Step 3: Initialize IPFS repository if needed
|
|
91
|
+
const initSpinner = ora('Initializing IPFS repository...').start();
|
|
92
|
+
try {
|
|
93
|
+
await manager.init();
|
|
94
|
+
initSpinner.succeed(chalk.green('IPFS repository initialized'));
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
const err = error;
|
|
98
|
+
// Check if already initialized
|
|
99
|
+
if (err.message.includes('already') || err.message.includes('exists')) {
|
|
100
|
+
initSpinner.succeed(chalk.green('IPFS repository already initialized'));
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
initSpinner.fail(chalk.red('Failed to initialize IPFS'));
|
|
104
|
+
console.error(chalk.red(err.message));
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Step 4: Start the daemon
|
|
109
|
+
const startSpinner = ora('Starting IPFS daemon...').start();
|
|
110
|
+
try {
|
|
111
|
+
await manager.start();
|
|
112
|
+
startSpinner.succeed(chalk.green('IPFS daemon started'));
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
const err = error;
|
|
116
|
+
startSpinner.fail(chalk.red('Failed to start daemon'));
|
|
117
|
+
console.error(chalk.red(err.message));
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
// Final status
|
|
74
121
|
console.log('');
|
|
75
|
-
console.log(chalk.bold('
|
|
76
|
-
console.log(chalk.cyan(' lsh ipfs start'));
|
|
122
|
+
console.log(chalk.green.bold('ā
IPFS setup complete!'));
|
|
77
123
|
console.log('');
|
|
78
|
-
console.log(chalk.gray('
|
|
79
|
-
console.log(chalk.cyan('
|
|
124
|
+
console.log(chalk.gray('You can now sync secrets:'));
|
|
125
|
+
console.log(chalk.cyan(' lsh sync push # Push secrets ā get CID'));
|
|
126
|
+
console.log(chalk.cyan(' lsh sync pull <cid> # Pull secrets by CID'));
|
|
80
127
|
console.log('');
|
|
81
128
|
});
|
|
82
129
|
// lsh sync push
|
|
@@ -258,28 +305,78 @@ export function registerSyncCommands(program) {
|
|
|
258
305
|
// lsh sync status
|
|
259
306
|
syncCommand
|
|
260
307
|
.command('status')
|
|
261
|
-
.description('š Show IPFS daemon and sync status')
|
|
262
|
-
.
|
|
308
|
+
.description('š Show IPFS client, daemon, and sync status')
|
|
309
|
+
.option('--json', 'Output as JSON')
|
|
310
|
+
.action(async (options) => {
|
|
263
311
|
try {
|
|
312
|
+
const manager = new IPFSClientManager();
|
|
313
|
+
const clientInfo = await manager.detect();
|
|
264
314
|
const ipfsSync = getIPFSSync();
|
|
265
315
|
const daemonInfo = await ipfsSync.getDaemonInfo();
|
|
316
|
+
const history = await ipfsSync.getHistory(5);
|
|
317
|
+
if (options.json) {
|
|
318
|
+
console.log(JSON.stringify({
|
|
319
|
+
client: clientInfo,
|
|
320
|
+
daemonRunning: !!daemonInfo,
|
|
321
|
+
daemonInfo,
|
|
322
|
+
recentSyncs: history.length,
|
|
323
|
+
}, null, 2));
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
266
326
|
console.log(chalk.bold.cyan('\nš Sync Status\n'));
|
|
267
327
|
console.log(chalk.gray('ā'.repeat(50)));
|
|
268
328
|
console.log('');
|
|
329
|
+
// Client status
|
|
330
|
+
console.log(chalk.bold('IPFS Client:'));
|
|
331
|
+
if (clientInfo.installed) {
|
|
332
|
+
console.log(chalk.green(' ā
Installed'));
|
|
333
|
+
console.log(` Type: ${clientInfo.type}`);
|
|
334
|
+
console.log(` Version: ${clientInfo.version}`);
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
console.log(chalk.yellow(' ā ļø Not installed'));
|
|
338
|
+
console.log(chalk.gray(' Run: lsh sync init'));
|
|
339
|
+
}
|
|
340
|
+
console.log('');
|
|
341
|
+
// Daemon status
|
|
342
|
+
console.log(chalk.bold('IPFS Daemon:'));
|
|
269
343
|
if (daemonInfo) {
|
|
270
|
-
console.log(chalk.green('ā
|
|
271
|
-
console.log(`
|
|
272
|
-
console.log(`
|
|
273
|
-
console.log(
|
|
274
|
-
|
|
275
|
-
|
|
344
|
+
console.log(chalk.green(' ā
Running'));
|
|
345
|
+
console.log(` Peer ID: ${daemonInfo.peerId.substring(0, 16)}...`);
|
|
346
|
+
console.log(` API: http://127.0.0.1:5001`);
|
|
347
|
+
console.log(` Gateway: http://127.0.0.1:8080`);
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
console.log(chalk.yellow(' ā ļø Not running'));
|
|
351
|
+
console.log(chalk.gray(' Run: lsh sync start'));
|
|
352
|
+
}
|
|
353
|
+
console.log('');
|
|
354
|
+
// Recent syncs
|
|
355
|
+
console.log(chalk.bold('Recent Syncs:'));
|
|
356
|
+
if (history.length > 0) {
|
|
357
|
+
console.log(` ${history.length} recent sync(s)`);
|
|
358
|
+
const latest = history[0];
|
|
359
|
+
const date = new Date(latest.timestamp);
|
|
360
|
+
console.log(` Latest: ${date.toLocaleString()}`);
|
|
361
|
+
console.log(` CID: ${latest.cid.substring(0, 20)}...`);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
console.log(chalk.gray(' No sync history'));
|
|
365
|
+
}
|
|
366
|
+
console.log('');
|
|
367
|
+
// Quick actions
|
|
368
|
+
if (clientInfo.installed && daemonInfo) {
|
|
369
|
+
console.log(chalk.bold('Ready to sync:'));
|
|
370
|
+
console.log(chalk.cyan(' lsh sync push # Push secrets'));
|
|
276
371
|
console.log(chalk.cyan(' lsh sync pull <cid> # Pull by CID'));
|
|
277
372
|
}
|
|
373
|
+
else if (!clientInfo.installed) {
|
|
374
|
+
console.log(chalk.bold('Get started:'));
|
|
375
|
+
console.log(chalk.cyan(' lsh sync init # Full setup'));
|
|
376
|
+
}
|
|
278
377
|
else {
|
|
279
|
-
console.log(chalk.
|
|
280
|
-
console.log('');
|
|
281
|
-
console.log(chalk.gray('Start with:'));
|
|
282
|
-
console.log(chalk.cyan(' lsh sync init'));
|
|
378
|
+
console.log(chalk.bold('Start daemon:'));
|
|
379
|
+
console.log(chalk.cyan(' lsh sync start'));
|
|
283
380
|
}
|
|
284
381
|
console.log('');
|
|
285
382
|
}
|
|
@@ -389,5 +486,45 @@ export function registerSyncCommands(program) {
|
|
|
389
486
|
process.exit(1);
|
|
390
487
|
}
|
|
391
488
|
});
|
|
489
|
+
// lsh sync start
|
|
490
|
+
syncCommand
|
|
491
|
+
.command('start')
|
|
492
|
+
.description('ā¶ļø Start IPFS daemon')
|
|
493
|
+
.action(async () => {
|
|
494
|
+
try {
|
|
495
|
+
const manager = new IPFSClientManager();
|
|
496
|
+
const ipfsSync = getIPFSSync();
|
|
497
|
+
// Check if already running
|
|
498
|
+
if (await ipfsSync.checkDaemon()) {
|
|
499
|
+
const info = await ipfsSync.getDaemonInfo();
|
|
500
|
+
console.log(chalk.green('ā
IPFS daemon is already running'));
|
|
501
|
+
if (info) {
|
|
502
|
+
console.log(chalk.gray(` Peer ID: ${info.peerId.substring(0, 16)}...`));
|
|
503
|
+
}
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
await manager.start();
|
|
507
|
+
}
|
|
508
|
+
catch (error) {
|
|
509
|
+
const err = error;
|
|
510
|
+
console.error(chalk.red('Failed to start daemon:'), err.message);
|
|
511
|
+
process.exit(1);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
// lsh sync stop
|
|
515
|
+
syncCommand
|
|
516
|
+
.command('stop')
|
|
517
|
+
.description('ā¹ļø Stop IPFS daemon')
|
|
518
|
+
.action(async () => {
|
|
519
|
+
try {
|
|
520
|
+
const manager = new IPFSClientManager();
|
|
521
|
+
await manager.stop();
|
|
522
|
+
}
|
|
523
|
+
catch (error) {
|
|
524
|
+
const err = error;
|
|
525
|
+
console.error(chalk.red('Failed to stop daemon:'), err.message);
|
|
526
|
+
process.exit(1);
|
|
527
|
+
}
|
|
528
|
+
});
|
|
392
529
|
}
|
|
393
530
|
export default registerSyncCommands;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lsh-framework",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.19",
|
|
4
4
|
"description": "Simple, cross-platform encrypted secrets manager with automatic sync, IPFS audit logs, and multi-environment support. Just run lsh sync and start managing your secrets.",
|
|
5
5
|
"main": "dist/app.js",
|
|
6
6
|
"bin": {
|