urchin-vault 0.2.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.
@@ -0,0 +1,406 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import inquirer from 'inquirer';
4
+ import { fileSelector, ItemType } from 'inquirer-file-selector';
5
+ import crypto from 'crypto';
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ import { loadStore, saveStore, getSession } from '../lib/store.js';
9
+ import { restoreWeb2Session, encryptFileWeb2, decryptFileWeb2 } from '../lib/cifer.js';
10
+ import { getProvider, listProviders } from '../lib/storage.js';
11
+ import { success, error as uiError, warn, formatBytes, flowArrow, sep, createTable, providerEmoji, ACCENT, DIM, BOLD, CYAN, } from '../lib/ui.js';
12
+ // ─── Interactive prompts with arrow keys ────────────────
13
+ async function pickKey(store, session) {
14
+ const owner = session.mode === 'web2' ? session.email : session.walletAddress;
15
+ const keys = store.vaults.filter(v => v.owner === owner);
16
+ if (keys.length === 0) {
17
+ uiError('No keys found. Create one first:');
18
+ console.log(` ${ACCENT('urchin key create <name>')}\n`);
19
+ process.exit(1);
20
+ }
21
+ if (keys.length === 1)
22
+ return keys[0];
23
+ const { selected } = await inquirer.prompt([{
24
+ type: 'list',
25
+ name: 'selected',
26
+ message: ACCENT('⚷') + ' Select encryption key:',
27
+ choices: keys.map(k => {
28
+ const fileCount = store.files.filter(f => f.vaultId === k.id).length;
29
+ return {
30
+ name: `${ACCENT('⚷')} ${BOLD(k.name)} ${DIM(`secret #${k.secretId}`)} ${DIM(`(${fileCount} files)`)}`,
31
+ value: k,
32
+ short: k.name,
33
+ };
34
+ }),
35
+ loop: false,
36
+ }]);
37
+ return selected;
38
+ }
39
+ async function pickProvider(store) {
40
+ const providers = listProviders();
41
+ const defaultProv = store.settings.defaultProvider || 'storacha';
42
+ const provDescs = {
43
+ storacha: 'Filecoin + IPFS (decentralized)',
44
+ local: 'Local encrypted storage',
45
+ };
46
+ if (providers.length === 1)
47
+ return providers[0];
48
+ const { selected } = await inquirer.prompt([{
49
+ type: 'list',
50
+ name: 'selected',
51
+ message: '📦 Select storage provider:',
52
+ default: defaultProv,
53
+ choices: providers.map(name => ({
54
+ name: `${providerEmoji(name)} ${BOLD(name)} ${DIM(provDescs[name] || name)}${name === defaultProv ? ACCENT(' ★') : ''}`,
55
+ value: name,
56
+ short: name,
57
+ })),
58
+ loop: false,
59
+ }]);
60
+ return selected;
61
+ }
62
+ async function pickFile(store, label = 'Select file:') {
63
+ if (store.files.length === 0) {
64
+ uiError('No files in your vault. Push one first:');
65
+ console.log(` ${ACCENT('urchin push <file>')}\n`);
66
+ process.exit(1);
67
+ }
68
+ const { selected } = await inquirer.prompt([{
69
+ type: 'list',
70
+ name: 'selected',
71
+ message: label,
72
+ choices: store.files.map(f => {
73
+ const key = store.vaults.find(v => v.id === f.vaultId);
74
+ const prov = f.provider || 'storacha';
75
+ return {
76
+ name: `${providerEmoji(prov)} ${BOLD(f.originalName)} ${DIM(formatBytes(f.originalSize))} ${ACCENT('⚷')} ${key?.name || '?'} ${DIM(f.uploadedAt.slice(0, 10))}`,
77
+ value: f,
78
+ short: f.originalName,
79
+ };
80
+ }),
81
+ loop: false,
82
+ pageSize: 10,
83
+ }]);
84
+ return selected;
85
+ }
86
+ // ─── Register file commands ─────────────────────────────
87
+ export function registerFileCommands(program) {
88
+ const file = program.command('file').description('Encrypt, upload, download & decrypt files');
89
+ // ─── Push (Encrypt & Upload) ────────────────────────────
90
+ file
91
+ .command('push')
92
+ .description('Encrypt a file and upload to storage')
93
+ .argument('[file-path]', 'Path to file (interactive if omitted)')
94
+ .option('-k, --key <name>', 'Encryption key name or ID')
95
+ .option('-p, --provider <name>', 'Storage provider (storacha, local)')
96
+ .action(async (filePath, opts) => {
97
+ try {
98
+ const session = getSession();
99
+ const store = loadStore();
100
+ // Interactive file browser if not provided
101
+ if (!filePath) {
102
+ const selected = await fileSelector({
103
+ message: '📄 Select file to encrypt:',
104
+ basePath: process.cwd(),
105
+ type: ItemType.File,
106
+ pageSize: 15,
107
+ allowCancel: true,
108
+ filter: (item) => {
109
+ const name = path.basename(item.path);
110
+ if (name.startsWith('.') && name !== '..')
111
+ return false;
112
+ if (name === 'node_modules' || name === 'dist')
113
+ return false;
114
+ return true;
115
+ },
116
+ theme: {
117
+ style: {
118
+ file: (text) => ACCENT(text),
119
+ directory: (text) => chalk.hex('#00D4FF').bold(text + '/'),
120
+ currentDir: (text) => chalk.white.bold(text),
121
+ help: () => chalk.dim(' ↑↓ navigate → enter folder ← go back ⏎ confirm esc cancel'),
122
+ },
123
+ prefix: {
124
+ file: ' 📄 ',
125
+ directory: ' 📂 ',
126
+ currentDir: ' 📍 ',
127
+ },
128
+ },
129
+ });
130
+ if (!selected) {
131
+ console.log(chalk.dim(' Cancelled.'));
132
+ return;
133
+ }
134
+ filePath = selected.path;
135
+ }
136
+ // Interactive key selection
137
+ const owner = session.mode === 'web2' ? session.email : session.walletAddress;
138
+ let key;
139
+ if (opts.key) {
140
+ key = store.vaults.find(v => v.name === opts.key || v.id === opts.key);
141
+ if (!key) {
142
+ uiError(`Key not found: ${opts.key}`);
143
+ process.exit(1);
144
+ }
145
+ }
146
+ else {
147
+ const userKeys = store.vaults.filter(v => v.owner === owner);
148
+ if (userKeys.length > 1) {
149
+ key = await pickKey(store, session);
150
+ }
151
+ else {
152
+ key = userKeys[0];
153
+ }
154
+ if (!key) {
155
+ uiError('No key found. Create one first: urchin key create');
156
+ process.exit(1);
157
+ }
158
+ }
159
+ // Interactive provider selection
160
+ let providerName;
161
+ if (opts.provider) {
162
+ providerName = opts.provider;
163
+ }
164
+ else if (listProviders().length > 1 && !opts.provider) {
165
+ providerName = await pickProvider(store);
166
+ }
167
+ else {
168
+ providerName = store.settings.defaultProvider || 'storacha';
169
+ }
170
+ const provider = getProvider(providerName);
171
+ // Check provider is ready
172
+ const provCheck = await provider.check();
173
+ if (!provCheck.ok) {
174
+ uiError(provCheck.error);
175
+ if (providerName === 'storacha') {
176
+ console.log(DIM('\n Setup Storacha:'));
177
+ console.log(DIM(' npm i -g @storacha/cli'));
178
+ console.log(DIM(' storacha login your@email.com'));
179
+ console.log(DIM(' storacha space create my-vault\n'));
180
+ }
181
+ process.exit(1);
182
+ }
183
+ // Read file
184
+ const absPath = path.resolve(filePath);
185
+ if (!fs.existsSync(absPath)) {
186
+ uiError(`File not found: ${absPath}`);
187
+ process.exit(1);
188
+ }
189
+ const fileName = path.basename(absPath);
190
+ const fileBuffer = fs.readFileSync(absPath);
191
+ const fileSize = fileBuffer.byteLength;
192
+ // Display flow
193
+ console.log('');
194
+ flowArrow(fileName, key.name, providerName);
195
+ sep();
196
+ // Step 1: Restore session
197
+ const spinner = ora({ text: 'Connecting to CIFER...', indent: 2 }).start();
198
+ if (session.mode === 'web2') {
199
+ await restoreWeb2Session(session);
200
+ }
201
+ // Step 2: Encrypt
202
+ spinner.text = `Encrypting ${BOLD(fileName)} ${DIM(`(${formatBytes(fileSize)})`)}...`;
203
+ const { encryptedBlob } = await encryptFileWeb2(key.secretId, fileBuffer, fileName, (pct) => { spinner.text = `Encrypting... ${pct}%`; });
204
+ spinner.succeed(`Encrypted with ${ACCENT('ML-KEM-768')} + ${ACCENT('AES-256-GCM')}`);
205
+ // Step 3: Upload
206
+ const uploadSpinner = ora({ text: `Uploading to ${BOLD(providerName)}...`, indent: 2 }).start();
207
+ const blobBuffer = Buffer.from(await encryptedBlob.arrayBuffer());
208
+ const cid = await provider.upload(blobBuffer, fileName);
209
+ uploadSpinner.succeed(`Stored on ${BOLD(providerName)}`);
210
+ // Step 4: Save to index
211
+ const fileId = crypto.randomUUID();
212
+ store.files.push({
213
+ id: fileId,
214
+ vaultId: key.id,
215
+ originalName: fileName,
216
+ originalSize: fileSize,
217
+ encryptedCid: cid,
218
+ provider: providerName,
219
+ ciferJobId: '',
220
+ uploadedAt: new Date().toISOString(),
221
+ });
222
+ saveStore(store);
223
+ // Result
224
+ console.log('');
225
+ success(`${BOLD(fileName)} pushed successfully`);
226
+ console.log(` ${DIM('Key:')} ${ACCENT('⚷')} ${key.name}`);
227
+ console.log(` ${DIM('Provider:')} ${providerEmoji(providerName)} ${providerName}`);
228
+ console.log(` ${DIM('CID:')} ${CYAN(cid)}`);
229
+ console.log(` ${DIM('URL:')} ${DIM(provider.getUrl(cid))}`);
230
+ console.log('');
231
+ }
232
+ catch (err) {
233
+ uiError(err.message);
234
+ process.exit(1);
235
+ }
236
+ });
237
+ // ─── Pull (Download & Decrypt) ──────────────────────────
238
+ file
239
+ .command('pull')
240
+ .description('Download from storage and decrypt')
241
+ .argument('[name-or-id]', 'File name or ID (interactive if omitted)')
242
+ .option('-o, --output <path>', 'Output path (default: current dir)')
243
+ .action(async (nameOrId, opts) => {
244
+ try {
245
+ const session = getSession();
246
+ const store = loadStore();
247
+ // Interactive file selection
248
+ let fileRecord;
249
+ if (nameOrId) {
250
+ const found = store.files.find(f => f.id === nameOrId || f.originalName === nameOrId);
251
+ if (!found) {
252
+ uiError(`File not found: ${nameOrId}`);
253
+ console.log(DIM(' Run "urchin ls" to see available files\n'));
254
+ process.exit(1);
255
+ }
256
+ fileRecord = found;
257
+ }
258
+ else {
259
+ fileRecord = await pickFile(store, '📥 Select file to pull:');
260
+ }
261
+ const key = store.vaults.find(v => v.id === fileRecord.vaultId);
262
+ if (!key) {
263
+ uiError('Key not found for this file');
264
+ process.exit(1);
265
+ }
266
+ const providerName = fileRecord.provider || 'storacha';
267
+ const provider = getProvider(providerName);
268
+ // Display flow
269
+ console.log('');
270
+ console.log(` ${providerEmoji(providerName)} ${BOLD(providerName)} ${ACCENT('→')} ${ACCENT('⚷')} ${BOLD(key.name)} ${ACCENT('→')} ${BOLD(fileRecord.originalName)}`);
271
+ sep();
272
+ // Step 1: Restore session
273
+ const spinner = ora({ text: 'Connecting to CIFER...', indent: 2 }).start();
274
+ if (session.mode === 'web2') {
275
+ await restoreWeb2Session(session);
276
+ }
277
+ // Step 2: Download
278
+ spinner.text = `Downloading from ${BOLD(providerName)}...`;
279
+ const encryptedBuffer = await provider.download(fileRecord.encryptedCid);
280
+ spinner.succeed(`Downloaded ${DIM(`(${formatBytes(encryptedBuffer.byteLength)})`)}`);
281
+ // Step 3: Decrypt
282
+ const decryptSpinner = ora({ text: 'Decrypting...', indent: 2 }).start();
283
+ const decryptedBlob = await decryptFileWeb2(key.secretId, encryptedBuffer, fileRecord.originalName, (pct) => { decryptSpinner.text = `Decrypting... ${pct}%`; });
284
+ decryptSpinner.succeed(`Decrypted with ${ACCENT('ML-KEM-768')} + ${ACCENT('AES-256-GCM')}`);
285
+ // Step 4: Save
286
+ const outputPath = opts.output
287
+ ? path.resolve(opts.output)
288
+ : path.resolve(fileRecord.originalName);
289
+ const arrayBuffer = await decryptedBlob.arrayBuffer();
290
+ fs.writeFileSync(outputPath, Buffer.from(arrayBuffer));
291
+ console.log('');
292
+ success(`Saved to ${BOLD(outputPath)}`);
293
+ console.log(` ${DIM(`Size: ${formatBytes(fileRecord.originalSize)}`)}`);
294
+ console.log('');
295
+ }
296
+ catch (err) {
297
+ uiError(err.message);
298
+ process.exit(1);
299
+ }
300
+ });
301
+ // ─── List Files ───────────────────────────────────────────
302
+ file
303
+ .command('list')
304
+ .alias('ls')
305
+ .description('List encrypted files')
306
+ .option('-k, --key <name>', 'Filter by key name or ID')
307
+ .action((opts) => {
308
+ const store = loadStore();
309
+ if (!store.session) {
310
+ warn('Not logged in. Run: urchin login');
311
+ return;
312
+ }
313
+ let files = store.files;
314
+ if (opts.key) {
315
+ const key = store.vaults.find(v => v.name === opts.key || v.id === opts.key);
316
+ if (key) {
317
+ files = files.filter(f => f.vaultId === key.id);
318
+ }
319
+ else {
320
+ uiError(`Key not found: ${opts.key}`);
321
+ process.exit(1);
322
+ }
323
+ }
324
+ if (files.length === 0) {
325
+ warn('No files yet. Push one with: urchin push <file>');
326
+ return;
327
+ }
328
+ console.log('');
329
+ const table = createTable(['', 'File', 'Size', 'Key', 'Provider', 'Date']);
330
+ for (const f of files) {
331
+ const key = store.vaults.find(v => v.id === f.vaultId);
332
+ const prov = f.provider || 'storacha';
333
+ table.push([
334
+ providerEmoji(prov),
335
+ BOLD(f.originalName),
336
+ DIM(formatBytes(f.originalSize)),
337
+ `${ACCENT('⚷')} ${key?.name || '?'}`,
338
+ DIM(prov),
339
+ DIM(f.uploadedAt.slice(0, 10)),
340
+ ]);
341
+ }
342
+ console.log(table.toString().split('\n').map(l => ' ' + l).join('\n'));
343
+ console.log(`\n ${DIM(`${files.length} file${files.length !== 1 ? 's' : ''}`)}\n`);
344
+ });
345
+ // ─── Remove ───────────────────────────────────────────────
346
+ file
347
+ .command('rm')
348
+ .description('Remove file from local index (keeps it on storage)')
349
+ .argument('[name-or-id]', 'File name or ID (interactive if omitted)')
350
+ .action(async (nameOrId) => {
351
+ const store = loadStore();
352
+ let idx;
353
+ if (nameOrId) {
354
+ idx = store.files.findIndex(f => f.id === nameOrId || f.originalName === nameOrId);
355
+ if (idx === -1) {
356
+ uiError(`File not found: ${nameOrId}`);
357
+ process.exit(1);
358
+ }
359
+ }
360
+ else {
361
+ const selected = await pickFile(store, '🗑️ Select file to remove:');
362
+ idx = store.files.findIndex(f => f.id === selected.id);
363
+ }
364
+ const file = store.files[idx];
365
+ const prov = file.provider || 'storacha';
366
+ const { confirm } = await inquirer.prompt([{
367
+ type: 'confirm',
368
+ name: 'confirm',
369
+ message: `Remove ${BOLD(file.originalName)} from index? ${DIM(`(still on ${prov})`)}`,
370
+ default: false,
371
+ }]);
372
+ if (!confirm)
373
+ return;
374
+ store.files.splice(idx, 1);
375
+ saveStore(store);
376
+ success(`Removed ${BOLD(file.originalName)} from index`);
377
+ });
378
+ // ─── Providers ────────────────────────────────────────────
379
+ file
380
+ .command('providers')
381
+ .description('List available storage providers')
382
+ .action(async () => {
383
+ const store = loadStore();
384
+ const current = store.settings.defaultProvider || 'storacha';
385
+ const provDescs = {
386
+ storacha: 'Filecoin + IPFS (decentralized, permanent)',
387
+ local: 'Local encrypted storage (offline)',
388
+ };
389
+ console.log('');
390
+ const table = createTable(['', 'Provider', 'Description', 'Files', '']);
391
+ for (const name of listProviders()) {
392
+ const fileCount = store.files.filter(f => (f.provider || 'storacha') === name).length;
393
+ const isDefault = name === current;
394
+ table.push([
395
+ isDefault ? ACCENT('★') : ' ',
396
+ BOLD(name),
397
+ DIM(provDescs[name] || name),
398
+ DIM(String(fileCount)),
399
+ isDefault ? ACCENT('default') : '',
400
+ ]);
401
+ }
402
+ console.log(table.toString().split('\n').map(l => ' ' + l).join('\n'));
403
+ console.log(`\n ${DIM('Set default:')} ${ACCENT('urchin config set defaultProvider <name>')}\n`);
404
+ });
405
+ }
406
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/commands/files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,159 @@
1
+ import ora from 'ora';
2
+ import inquirer from 'inquirer';
3
+ import crypto from 'crypto';
4
+ import { loadStore, saveStore, getSession } from '../lib/store.js';
5
+ import { restoreWeb2Session, createWeb2Secret } from '../lib/cifer.js';
6
+ import { success, error as uiError, warn, formatBytes, createTable, progressBar, ACCENT, DIM, BOLD, CYAN, PURPLE, } from '../lib/ui.js';
7
+ export function registerKeyCommands(program) {
8
+ const key = program.command('key').description('Manage CIFER encryption keys');
9
+ // ─── Create Key ─────────────────────────────────────────
10
+ key
11
+ .command('create')
12
+ .description('Create a new encryption key (ML-KEM-768 key pair)')
13
+ .argument('[name]', 'Key name')
14
+ .action(async (name) => {
15
+ try {
16
+ const session = getSession();
17
+ if (!name) {
18
+ const answers = await inquirer.prompt([{
19
+ type: 'input',
20
+ name: 'name',
21
+ message: ACCENT('⚷') + ' Key name:',
22
+ validate: (val) => val.trim() ? true : 'Name is required',
23
+ }]);
24
+ name = answers.name.trim();
25
+ }
26
+ if (session.mode === 'web2') {
27
+ const spinner = ora({ text: 'Connecting to CIFER...', indent: 2 }).start();
28
+ await restoreWeb2Session(session);
29
+ spinner.text = `Generating ${ACCENT('ML-KEM-768')} key pair...`;
30
+ const secret = await createWeb2Secret();
31
+ spinner.succeed(`Key pair generated`);
32
+ const store = loadStore();
33
+ const keyId = crypto.randomUUID();
34
+ store.vaults.push({
35
+ id: keyId,
36
+ name: name,
37
+ secretId: secret.secretId,
38
+ authMode: 'web2',
39
+ owner: session.email,
40
+ createdAt: new Date().toISOString(),
41
+ });
42
+ saveStore(store);
43
+ console.log('');
44
+ success(`Key ${ACCENT.bold(name)} created`);
45
+ console.log(` ${DIM('Secret:')} ${PURPLE(`#${secret.secretId}`)}`);
46
+ console.log(` ${DIM('Algo:')} ${CYAN('ML-KEM-768')} + ${CYAN('AES-256-GCM')}`);
47
+ console.log(` ${DIM('ID:')} ${DIM(keyId)}`);
48
+ console.log('');
49
+ }
50
+ else {
51
+ warn('Web3 key creation not yet implemented.');
52
+ }
53
+ }
54
+ catch (err) {
55
+ uiError(err.message);
56
+ process.exit(1);
57
+ }
58
+ });
59
+ // ─── List Keys ──────────────────────────────────────────
60
+ key
61
+ .command('list')
62
+ .alias('ls')
63
+ .description('List all encryption keys')
64
+ .action(() => {
65
+ const store = loadStore();
66
+ const session = store.session;
67
+ if (!session) {
68
+ warn('Not logged in. Run: urchin login');
69
+ return;
70
+ }
71
+ const owner = session.mode === 'web2' ? session.email : session.walletAddress;
72
+ const keys = store.vaults.filter(v => v.owner === owner);
73
+ if (keys.length === 0) {
74
+ warn('No keys yet. Create one:');
75
+ console.log(` ${ACCENT('urchin key create <name>')}\n`);
76
+ return;
77
+ }
78
+ console.log('');
79
+ const table = createTable(['', 'Name', 'Secret', 'Files', 'Size', 'Created']);
80
+ for (const k of keys) {
81
+ const fileCount = store.files.filter(f => f.vaultId === k.id).length;
82
+ const totalSize = store.files
83
+ .filter(f => f.vaultId === k.id)
84
+ .reduce((sum, f) => sum + f.originalSize, 0);
85
+ table.push([
86
+ ACCENT('⚷'),
87
+ BOLD(k.name),
88
+ PURPLE(`#${k.secretId}`),
89
+ `${progressBar(fileCount, Math.max(fileCount, 5), 8)} ${DIM(String(fileCount))}`,
90
+ DIM(formatBytes(totalSize)),
91
+ DIM(k.createdAt.slice(0, 10)),
92
+ ]);
93
+ }
94
+ console.log(table.toString().split('\n').map(l => ' ' + l).join('\n'));
95
+ console.log(`\n ${DIM(`${keys.length} key${keys.length !== 1 ? 's' : ''} • ML-KEM-768`)}\n`);
96
+ });
97
+ // ─── Delete Key ─────────────────────────────────────────
98
+ key
99
+ .command('delete')
100
+ .description('Delete a key (local record only — CIFER secret remains)')
101
+ .argument('[name-or-id]', 'Key name or ID (interactive if omitted)')
102
+ .action(async (nameOrId) => {
103
+ const store = loadStore();
104
+ const session = store.session;
105
+ if (!session) {
106
+ warn('Not logged in. Run: urchin login');
107
+ return;
108
+ }
109
+ let idx;
110
+ if (nameOrId) {
111
+ idx = store.vaults.findIndex(v => v.id === nameOrId || v.name === nameOrId);
112
+ if (idx === -1) {
113
+ uiError(`Key not found: ${nameOrId}`);
114
+ process.exit(1);
115
+ }
116
+ }
117
+ else {
118
+ const owner = session.mode === 'web2' ? session.email : session.walletAddress;
119
+ const keys = store.vaults.filter(v => v.owner === owner);
120
+ if (keys.length === 0) {
121
+ warn('No keys to delete.');
122
+ return;
123
+ }
124
+ const { selected } = await inquirer.prompt([{
125
+ type: 'list',
126
+ name: 'selected',
127
+ message: '🗑️ Select key to delete:',
128
+ choices: keys.map(k => {
129
+ const fileCount = store.files.filter(f => f.vaultId === k.id).length;
130
+ return {
131
+ name: `${ACCENT('⚷')} ${BOLD(k.name)} ${DIM(`secret #${k.secretId}`)} ${DIM(`(${fileCount} files)`)}`,
132
+ value: k.id,
133
+ short: k.name,
134
+ };
135
+ }),
136
+ loop: false,
137
+ }]);
138
+ idx = store.vaults.findIndex(v => v.id === selected);
139
+ }
140
+ const vault = store.vaults[idx];
141
+ const fileCount = store.files.filter(f => f.vaultId === vault.id).length;
142
+ const { confirm } = await inquirer.prompt([{
143
+ type: 'confirm',
144
+ name: 'confirm',
145
+ message: `Delete key ${BOLD(vault.name)}?${fileCount > 0 ? ` (${fileCount} files removed from index, data stays on storage)` : ''}`,
146
+ default: false,
147
+ }]);
148
+ if (!confirm) {
149
+ console.log(DIM(' Cancelled.\n'));
150
+ return;
151
+ }
152
+ store.vaults.splice(idx, 1);
153
+ store.files = store.files.filter(f => f.vaultId !== vault.id);
154
+ saveStore(store);
155
+ success(`Key ${BOLD(vault.name)} deleted`);
156
+ console.log('');
157
+ });
158
+ }
159
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/commands/keys.ts"],"names":[],"mappings":"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"}