@zincapp/znvault-cli 2.1.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.
Files changed (122) hide show
  1. package/README.md +310 -0
  2. package/dist/commands/agent.d.ts +3 -0
  3. package/dist/commands/agent.d.ts.map +1 -0
  4. package/dist/commands/agent.js +660 -0
  5. package/dist/commands/agent.js.map +1 -0
  6. package/dist/commands/apikey.d.ts +3 -0
  7. package/dist/commands/apikey.d.ts.map +1 -0
  8. package/dist/commands/apikey.js +767 -0
  9. package/dist/commands/apikey.js.map +1 -0
  10. package/dist/commands/audit.d.ts +3 -0
  11. package/dist/commands/audit.d.ts.map +1 -0
  12. package/dist/commands/audit.js +147 -0
  13. package/dist/commands/audit.js.map +1 -0
  14. package/dist/commands/auth.d.ts +3 -0
  15. package/dist/commands/auth.d.ts.map +1 -0
  16. package/dist/commands/auth.js +426 -0
  17. package/dist/commands/auth.js.map +1 -0
  18. package/dist/commands/cert.d.ts +3 -0
  19. package/dist/commands/cert.d.ts.map +1 -0
  20. package/dist/commands/cert.js +398 -0
  21. package/dist/commands/cert.js.map +1 -0
  22. package/dist/commands/cluster.d.ts +3 -0
  23. package/dist/commands/cluster.d.ts.map +1 -0
  24. package/dist/commands/cluster.js +228 -0
  25. package/dist/commands/cluster.js.map +1 -0
  26. package/dist/commands/emergency.d.ts +3 -0
  27. package/dist/commands/emergency.d.ts.map +1 -0
  28. package/dist/commands/emergency.js +223 -0
  29. package/dist/commands/emergency.js.map +1 -0
  30. package/dist/commands/health.d.ts +3 -0
  31. package/dist/commands/health.d.ts.map +1 -0
  32. package/dist/commands/health.js +188 -0
  33. package/dist/commands/health.js.map +1 -0
  34. package/dist/commands/lockdown.d.ts +3 -0
  35. package/dist/commands/lockdown.d.ts.map +1 -0
  36. package/dist/commands/lockdown.js +232 -0
  37. package/dist/commands/lockdown.js.map +1 -0
  38. package/dist/commands/permissions.d.ts +3 -0
  39. package/dist/commands/permissions.d.ts.map +1 -0
  40. package/dist/commands/permissions.js +168 -0
  41. package/dist/commands/permissions.js.map +1 -0
  42. package/dist/commands/policy.d.ts +3 -0
  43. package/dist/commands/policy.d.ts.map +1 -0
  44. package/dist/commands/policy.js +660 -0
  45. package/dist/commands/policy.js.map +1 -0
  46. package/dist/commands/superadmin.d.ts +3 -0
  47. package/dist/commands/superadmin.d.ts.map +1 -0
  48. package/dist/commands/superadmin.js +203 -0
  49. package/dist/commands/superadmin.js.map +1 -0
  50. package/dist/commands/tenant.d.ts +3 -0
  51. package/dist/commands/tenant.d.ts.map +1 -0
  52. package/dist/commands/tenant.js +277 -0
  53. package/dist/commands/tenant.js.map +1 -0
  54. package/dist/commands/update.d.ts +9 -0
  55. package/dist/commands/update.d.ts.map +1 -0
  56. package/dist/commands/update.js +359 -0
  57. package/dist/commands/update.js.map +1 -0
  58. package/dist/commands/user.d.ts +3 -0
  59. package/dist/commands/user.d.ts.map +1 -0
  60. package/dist/commands/user.js +363 -0
  61. package/dist/commands/user.js.map +1 -0
  62. package/dist/index.d.ts +3 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +82 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/lib/client.d.ts +246 -0
  67. package/dist/lib/client.d.ts.map +1 -0
  68. package/dist/lib/client.js +734 -0
  69. package/dist/lib/client.js.map +1 -0
  70. package/dist/lib/config.d.ts +130 -0
  71. package/dist/lib/config.d.ts.map +1 -0
  72. package/dist/lib/config.js +342 -0
  73. package/dist/lib/config.js.map +1 -0
  74. package/dist/lib/db.d.ts +111 -0
  75. package/dist/lib/db.d.ts.map +1 -0
  76. package/dist/lib/db.js +698 -0
  77. package/dist/lib/db.js.map +1 -0
  78. package/dist/lib/local.d.ts +41 -0
  79. package/dist/lib/local.d.ts.map +1 -0
  80. package/dist/lib/local.js +236 -0
  81. package/dist/lib/local.js.map +1 -0
  82. package/dist/lib/mode.d.ts +210 -0
  83. package/dist/lib/mode.d.ts.map +1 -0
  84. package/dist/lib/mode.js +389 -0
  85. package/dist/lib/mode.js.map +1 -0
  86. package/dist/lib/output.d.ts +61 -0
  87. package/dist/lib/output.d.ts.map +1 -0
  88. package/dist/lib/output.js +190 -0
  89. package/dist/lib/output.js.map +1 -0
  90. package/dist/lib/prompts.d.ts +32 -0
  91. package/dist/lib/prompts.d.ts.map +1 -0
  92. package/dist/lib/prompts.js +96 -0
  93. package/dist/lib/prompts.js.map +1 -0
  94. package/dist/services/auto-update-daemon.d.ts +48 -0
  95. package/dist/services/auto-update-daemon.d.ts.map +1 -0
  96. package/dist/services/auto-update-daemon.js +296 -0
  97. package/dist/services/auto-update-daemon.js.map +1 -0
  98. package/dist/services/signature-verifier.d.ts +38 -0
  99. package/dist/services/signature-verifier.d.ts.map +1 -0
  100. package/dist/services/signature-verifier.js +209 -0
  101. package/dist/services/signature-verifier.js.map +1 -0
  102. package/dist/services/update-checker.d.ts +39 -0
  103. package/dist/services/update-checker.d.ts.map +1 -0
  104. package/dist/services/update-checker.js +198 -0
  105. package/dist/services/update-checker.js.map +1 -0
  106. package/dist/services/update-installer.d.ts +54 -0
  107. package/dist/services/update-installer.d.ts.map +1 -0
  108. package/dist/services/update-installer.js +360 -0
  109. package/dist/services/update-installer.js.map +1 -0
  110. package/dist/types/index.d.ts +411 -0
  111. package/dist/types/index.d.ts.map +1 -0
  112. package/dist/types/index.js +2 -0
  113. package/dist/types/index.js.map +1 -0
  114. package/dist/types/update.d.ts +137 -0
  115. package/dist/types/update.d.ts.map +1 -0
  116. package/dist/types/update.js +27 -0
  117. package/dist/types/update.js.map +1 -0
  118. package/dist/utils/platform.d.ts +35 -0
  119. package/dist/utils/platform.d.ts.map +1 -0
  120. package/dist/utils/platform.js +115 -0
  121. package/dist/utils/platform.js.map +1 -0
  122. package/package.json +59 -0
@@ -0,0 +1,398 @@
1
+ import ora from 'ora';
2
+ import * as mode from '../lib/mode.js';
3
+ import * as output from '../lib/output.js';
4
+ export function registerCertCommands(program) {
5
+ const cert = program
6
+ .command('cert')
7
+ .description('Certificate management');
8
+ // List certificates
9
+ cert
10
+ .command('list')
11
+ .description('List certificates')
12
+ .option('--status <status>', 'Filter by status (ACTIVE, EXPIRING_SOON, EXPIRED)')
13
+ .option('--kind <kind>', 'Filter by kind (AEAT, FNMT, CUSTOM, etc.)')
14
+ .option('--expiring <days>', 'Show certificates expiring within N days')
15
+ .option('--json', 'Output as JSON')
16
+ .action(async (options) => {
17
+ const spinner = ora('Fetching certificates...').start();
18
+ try {
19
+ const params = new URLSearchParams();
20
+ if (options.status)
21
+ params.append('status', options.status);
22
+ if (options.kind)
23
+ params.append('kind', options.kind);
24
+ let endpoint = '/v1/certificates';
25
+ if (options.expiring) {
26
+ endpoint = `/v1/certificates/expiring?days=${options.expiring}`;
27
+ }
28
+ else if (params.toString()) {
29
+ endpoint += '?' + params.toString();
30
+ }
31
+ const result = await mode.apiGet(endpoint);
32
+ spinner.stop();
33
+ if (options.json) {
34
+ output.json(result);
35
+ return;
36
+ }
37
+ const items = Array.isArray(result) ? result : result.items || [];
38
+ if (items.length === 0) {
39
+ console.log('No certificates found');
40
+ return;
41
+ }
42
+ output.table(['ID', 'Alias', 'Kind', 'Subject', 'Status', 'Key', 'Expires', 'Days Left'], items.map((cert) => [
43
+ cert.id.substring(0, 8),
44
+ cert.alias,
45
+ cert.kind,
46
+ cert.subjectCn.length > 25 ? cert.subjectCn.substring(0, 22) + '...' : cert.subjectCn,
47
+ formatStatus(cert.status),
48
+ cert.hasPrivateKey ? 'Yes' : 'No',
49
+ new Date(cert.notAfter).toLocaleDateString(),
50
+ formatDaysLeft(cert.daysUntilExpiry),
51
+ ]));
52
+ if (!Array.isArray(result) && result.total) {
53
+ console.log(`\nTotal: ${result.total} certificate(s)`);
54
+ }
55
+ }
56
+ catch (err) {
57
+ spinner.fail('Failed to list certificates');
58
+ output.error(err instanceof Error ? err.message : String(err));
59
+ process.exit(1);
60
+ }
61
+ finally {
62
+ await mode.closeLocalClient();
63
+ }
64
+ });
65
+ // Get certificate details
66
+ cert
67
+ .command('get <id>')
68
+ .description('Get certificate details')
69
+ .option('--json', 'Output as JSON')
70
+ .action(async (id, options) => {
71
+ const spinner = ora('Fetching certificate...').start();
72
+ try {
73
+ const result = await mode.apiGet(`/v1/certificates/${id}`);
74
+ spinner.stop();
75
+ if (options.json) {
76
+ output.json(result);
77
+ return;
78
+ }
79
+ console.log();
80
+ console.log(`ID: ${result.id}`);
81
+ console.log(`Alias: ${result.alias}`);
82
+ console.log(`Kind: ${result.kind}`);
83
+ console.log(`Client ID: ${result.clientId}`);
84
+ console.log(`Client: ${result.clientName}`);
85
+ console.log();
86
+ console.log('Certificate Details:');
87
+ console.log(` Subject: ${result.subjectCn}`);
88
+ console.log(` Issuer: ${result.issuerCn}`);
89
+ console.log(` Serial: ${result.fingerprintSha256.substring(0, 32)}...`);
90
+ console.log(` Not Before: ${new Date(result.notBefore).toLocaleString()}`);
91
+ console.log(` Not After: ${new Date(result.notAfter).toLocaleString()}`);
92
+ console.log(` Status: ${formatStatus(result.status)}`);
93
+ console.log(` Days Left: ${formatDaysLeft(result.daysUntilExpiry)}`);
94
+ console.log();
95
+ console.log('Bundle Info:');
96
+ console.log(` Has Private Key: ${result.hasPrivateKey ? 'Yes' : 'No'}`);
97
+ console.log(` Lifecycle: Enabled`); // All certs in certificates table have lifecycle enabled
98
+ console.log();
99
+ console.log('Metadata:');
100
+ console.log(` Version: ${result.version}`);
101
+ console.log(` Created: ${new Date(result.createdAt).toLocaleString()}`);
102
+ console.log(` Updated: ${new Date(result.updatedAt).toLocaleString()}`);
103
+ if (result.lastAccessedAt) {
104
+ console.log(` Accessed: ${new Date(result.lastAccessedAt).toLocaleString()}`);
105
+ }
106
+ console.log(` Access Count: ${result.accessCount}`);
107
+ if (result.tags.length > 0) {
108
+ console.log(` Tags: ${result.tags.join(', ')}`);
109
+ }
110
+ console.log();
111
+ }
112
+ catch (err) {
113
+ spinner.fail('Failed to get certificate');
114
+ output.error(err instanceof Error ? err.message : String(err));
115
+ process.exit(1);
116
+ }
117
+ finally {
118
+ await mode.closeLocalClient();
119
+ }
120
+ });
121
+ // Decrypt certificate
122
+ cert
123
+ .command('decrypt <id>')
124
+ .description('Decrypt and download certificate')
125
+ .option('--output <file>', 'Write to file instead of stdout')
126
+ .option('--purpose <purpose>', 'Purpose for access (required)', 'CLI access')
127
+ .action(async (id, options) => {
128
+ const spinner = ora('Decrypting certificate...').start();
129
+ try {
130
+ const result = await mode.apiPost(`/v1/certificates/${id}/decrypt`, {
131
+ purpose: options.purpose,
132
+ });
133
+ spinner.stop();
134
+ const certData = Buffer.from(result.certificateData, 'base64').toString('utf-8');
135
+ if (options.output) {
136
+ const fs = await import('node:fs');
137
+ fs.writeFileSync(options.output, certData);
138
+ console.log(`Certificate written to ${options.output}`);
139
+ }
140
+ else {
141
+ console.log(certData);
142
+ }
143
+ }
144
+ catch (err) {
145
+ spinner.fail('Failed to decrypt certificate');
146
+ output.error(err instanceof Error ? err.message : String(err));
147
+ process.exit(1);
148
+ }
149
+ finally {
150
+ await mode.closeLocalClient();
151
+ }
152
+ });
153
+ // Get expiring certificates
154
+ cert
155
+ .command('expiring')
156
+ .description('List certificates expiring soon')
157
+ .option('--days <days>', 'Days until expiry (default: 30)', '30')
158
+ .option('--json', 'Output as JSON')
159
+ .action(async (options) => {
160
+ const spinner = ora('Checking expiring certificates...').start();
161
+ try {
162
+ const result = await mode.apiGet(`/v1/certificates/expiring?days=${options.days}`);
163
+ spinner.stop();
164
+ if (options.json) {
165
+ output.json(result);
166
+ return;
167
+ }
168
+ const items = Array.isArray(result) ? result : [];
169
+ if (items.length === 0) {
170
+ console.log(`No certificates expiring within ${options.days} days`);
171
+ return;
172
+ }
173
+ console.log(`\nCertificates expiring within ${options.days} days:\n`);
174
+ output.table(['Alias', 'Subject', 'Expires', 'Days Left', 'Contact'], items.map((cert) => [
175
+ cert.alias,
176
+ cert.subjectCn.length > 25 ? cert.subjectCn.substring(0, 22) + '...' : cert.subjectCn,
177
+ new Date(cert.notAfter).toLocaleDateString(),
178
+ formatDaysLeft(cert.daysUntilExpiry),
179
+ cert.contactEmail || '-',
180
+ ]));
181
+ }
182
+ catch (err) {
183
+ spinner.fail('Failed to check expiring certificates');
184
+ output.error(err instanceof Error ? err.message : String(err));
185
+ process.exit(1);
186
+ }
187
+ finally {
188
+ await mode.closeLocalClient();
189
+ }
190
+ });
191
+ // Get statistics
192
+ cert
193
+ .command('stats')
194
+ .description('Get certificate statistics')
195
+ .option('--json', 'Output as JSON')
196
+ .action(async (options) => {
197
+ const spinner = ora('Fetching statistics...').start();
198
+ try {
199
+ const result = await mode.apiGet('/v1/certificates/stats');
200
+ spinner.stop();
201
+ if (options.json) {
202
+ output.json(result);
203
+ return;
204
+ }
205
+ console.log();
206
+ console.log(`Total Certificates: ${result.total}`);
207
+ console.log();
208
+ console.log('By Status:');
209
+ for (const [status, count] of Object.entries(result.byStatus)) {
210
+ console.log(` ${status}: ${count}`);
211
+ }
212
+ console.log();
213
+ console.log('By Kind:');
214
+ for (const [kind, count] of Object.entries(result.byKind)) {
215
+ console.log(` ${kind}: ${count}`);
216
+ }
217
+ console.log();
218
+ console.log('Expiring:');
219
+ console.log(` Within 7 days: ${result.expiringIn7Days}`);
220
+ console.log(` Within 30 days: ${result.expiringIn30Days}`);
221
+ console.log();
222
+ }
223
+ catch (err) {
224
+ spinner.fail('Failed to get statistics');
225
+ output.error(err instanceof Error ? err.message : String(err));
226
+ process.exit(1);
227
+ }
228
+ finally {
229
+ await mode.closeLocalClient();
230
+ }
231
+ });
232
+ // Store certificate (upload)
233
+ cert
234
+ .command('store')
235
+ .description('Store a new certificate')
236
+ .requiredOption('--file <path>', 'Certificate file path')
237
+ .requiredOption('--client-id <id>', 'Client identifier (e.g., NIF/CIF)')
238
+ .requiredOption('--kind <kind>', 'Certificate kind (AEAT, FNMT, CUSTOM, etc.)')
239
+ .requiredOption('--alias <alias>', 'Human-readable alias')
240
+ .option('--type <type>', 'Certificate type (PEM, P12, DER)', 'PEM')
241
+ .option('--purpose <purpose>', 'Purpose (SIGNING, AUTHENTICATION, ENCRYPTION)', 'SIGNING')
242
+ .option('--passphrase <pass>', 'Passphrase for P12 certificates')
243
+ .option('--client-name <name>', 'Client display name')
244
+ .option('--contact <email>', 'Contact email for notifications')
245
+ .option('--tags <tags>', 'Comma-separated tags')
246
+ .action(async (options) => {
247
+ const spinner = ora('Storing certificate...').start();
248
+ try {
249
+ const fs = await import('node:fs');
250
+ if (!fs.existsSync(options.file)) {
251
+ throw new Error(`File not found: ${options.file}`);
252
+ }
253
+ const fileData = fs.readFileSync(options.file);
254
+ const base64Data = fileData.toString('base64');
255
+ const body = {
256
+ clientId: options.clientId,
257
+ kind: options.kind,
258
+ alias: options.alias,
259
+ certificateData: base64Data,
260
+ certificateType: options.type,
261
+ purpose: options.purpose,
262
+ };
263
+ if (options.passphrase)
264
+ body.passphrase = options.passphrase;
265
+ if (options.clientName)
266
+ body.clientName = options.clientName;
267
+ if (options.contact)
268
+ body.contactEmail = options.contact;
269
+ if (options.tags)
270
+ body.tags = options.tags.split(',').map((t) => t.trim());
271
+ const result = await mode.apiPost('/v1/certificates', body);
272
+ spinner.stop();
273
+ console.log();
274
+ console.log(`Certificate stored successfully!`);
275
+ console.log();
276
+ console.log(` ID: ${result.id}`);
277
+ console.log(` Alias: ${result.alias}`);
278
+ console.log(` Subject: ${result.subjectCn}`);
279
+ console.log(` Issuer: ${result.issuerCn}`);
280
+ console.log(` Expires: ${new Date(result.notAfter).toLocaleDateString()}`);
281
+ console.log();
282
+ }
283
+ catch (err) {
284
+ spinner.fail('Failed to store certificate');
285
+ output.error(err instanceof Error ? err.message : String(err));
286
+ process.exit(1);
287
+ }
288
+ finally {
289
+ await mode.closeLocalClient();
290
+ }
291
+ });
292
+ // Rotate certificate
293
+ cert
294
+ .command('rotate <id>')
295
+ .description('Rotate/renew a certificate')
296
+ .requiredOption('--file <path>', 'New certificate file path')
297
+ .option('--type <type>', 'Certificate type (PEM, P12, DER)', 'PEM')
298
+ .option('--passphrase <pass>', 'Passphrase for P12 certificates')
299
+ .option('--reason <reason>', 'Reason for rotation', 'Certificate renewal')
300
+ .action(async (id, options) => {
301
+ const spinner = ora('Rotating certificate...').start();
302
+ try {
303
+ const fs = await import('node:fs');
304
+ if (!fs.existsSync(options.file)) {
305
+ throw new Error(`File not found: ${options.file}`);
306
+ }
307
+ const fileData = fs.readFileSync(options.file);
308
+ const base64Data = fileData.toString('base64');
309
+ const body = {
310
+ certificateData: base64Data,
311
+ certificateType: options.type,
312
+ reason: options.reason,
313
+ };
314
+ if (options.passphrase)
315
+ body.passphrase = options.passphrase;
316
+ const result = await mode.apiPost(`/v1/certificates/${id}/rotate`, body);
317
+ spinner.stop();
318
+ console.log();
319
+ console.log(`Certificate rotated successfully!`);
320
+ console.log();
321
+ console.log(` ID: ${result.id}`);
322
+ console.log(` Version: ${result.version}`);
323
+ console.log(` Subject: ${result.subjectCn}`);
324
+ console.log(` Expires: ${new Date(result.notAfter).toLocaleDateString()}`);
325
+ console.log();
326
+ }
327
+ catch (err) {
328
+ spinner.fail('Failed to rotate certificate');
329
+ output.error(err instanceof Error ? err.message : String(err));
330
+ process.exit(1);
331
+ }
332
+ finally {
333
+ await mode.closeLocalClient();
334
+ }
335
+ });
336
+ // Delete certificate
337
+ cert
338
+ .command('delete <id>')
339
+ .description('Delete a certificate')
340
+ .option('--force', 'Skip confirmation')
341
+ .action(async (id, options) => {
342
+ try {
343
+ if (!options.force) {
344
+ const readline = await import('node:readline');
345
+ const rl = readline.createInterface({
346
+ input: process.stdin,
347
+ output: process.stdout,
348
+ });
349
+ const answer = await new Promise((resolve) => {
350
+ rl.question(`Are you sure you want to delete certificate ${id}? [y/N] `, resolve);
351
+ });
352
+ rl.close();
353
+ if (answer.toLowerCase() !== 'y') {
354
+ console.log('Cancelled');
355
+ return;
356
+ }
357
+ }
358
+ const spinner = ora('Deleting certificate...').start();
359
+ await mode.apiDelete(`/v1/certificates/${id}`);
360
+ spinner.stop();
361
+ console.log('Certificate deleted successfully');
362
+ }
363
+ catch (err) {
364
+ output.error(err instanceof Error ? err.message : String(err));
365
+ process.exit(1);
366
+ }
367
+ finally {
368
+ await mode.closeLocalClient();
369
+ }
370
+ });
371
+ }
372
+ function formatStatus(status) {
373
+ switch (status) {
374
+ case 'ACTIVE':
375
+ return output.formatStatus('ok');
376
+ case 'EXPIRING_SOON':
377
+ return output.formatStatus('warning');
378
+ case 'EXPIRED':
379
+ return output.formatStatus('error');
380
+ case 'REVOKED':
381
+ return output.formatStatus('error');
382
+ default:
383
+ return status;
384
+ }
385
+ }
386
+ function formatDaysLeft(days) {
387
+ if (days < 0) {
388
+ return output.formatStatus('error') + ` (${Math.abs(days)}d ago)`;
389
+ }
390
+ if (days < 7) {
391
+ return output.formatStatus('error') + ` ${days}d`;
392
+ }
393
+ if (days < 30) {
394
+ return output.formatStatus('warning') + ` ${days}d`;
395
+ }
396
+ return `${days}d`;
397
+ }
398
+ //# sourceMappingURL=cert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cert.js","sourceRoot":"","sources":["../../src/commands/cert.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerClusterCommands(program: Command): void;
3
+ //# sourceMappingURL=cluster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/commands/cluster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwP9D"}
@@ -0,0 +1,228 @@
1
+ import ora from 'ora';
2
+ import { client } from '../lib/client.js';
3
+ import * as mode from '../lib/mode.js';
4
+ import { promptConfirm } from '../lib/prompts.js';
5
+ import * as output from '../lib/output.js';
6
+ export function registerClusterCommands(program) {
7
+ const cluster = program
8
+ .command('cluster')
9
+ .description('Cluster management commands');
10
+ // Cluster status
11
+ cluster
12
+ .command('status')
13
+ .description('Show cluster status')
14
+ .option('--json', 'Output as JSON')
15
+ .action(async (options) => {
16
+ const spinner = ora('Getting cluster status...').start();
17
+ try {
18
+ const status = await mode.clusterStatus();
19
+ spinner.stop();
20
+ if (options.json) {
21
+ output.json(status);
22
+ return;
23
+ }
24
+ output.section('Cluster Status');
25
+ output.keyValue({
26
+ 'Mode': mode.getModeDescription(),
27
+ 'Enabled': status.enabled,
28
+ 'Node ID': status.nodeId,
29
+ 'Is Leader': status.isLeader,
30
+ 'Leader Node': status.leaderNodeId || 'None',
31
+ });
32
+ if (status.nodes && status.nodes.length > 0) {
33
+ output.section('Nodes');
34
+ output.table(['Node ID', 'Host', 'Port', 'Leader', 'Status', 'Last Heartbeat'], status.nodes.map(node => [
35
+ node.nodeId,
36
+ node.host,
37
+ node.port,
38
+ node.isLeader,
39
+ node.isHealthy ? 'healthy' : 'unhealthy',
40
+ node.lastHeartbeat ? output.formatRelativeTime(node.lastHeartbeat) : '-',
41
+ ]));
42
+ }
43
+ if (status.infrastructure) {
44
+ output.section('Infrastructure');
45
+ if (status.infrastructure.postgres) {
46
+ console.log(` PostgreSQL: ${output.formatStatus(status.infrastructure.postgres.status)}`);
47
+ if (status.infrastructure.postgres.primary) {
48
+ console.log(` Primary: ${status.infrastructure.postgres.primary}`);
49
+ }
50
+ }
51
+ if (status.infrastructure.redis) {
52
+ console.log(` Redis: ${output.formatStatus(status.infrastructure.redis.status)}`);
53
+ }
54
+ if (status.infrastructure.etcd) {
55
+ console.log(` etcd: ${output.formatStatus(status.infrastructure.etcd.status)}`);
56
+ }
57
+ }
58
+ console.log();
59
+ }
60
+ catch (err) {
61
+ spinner.fail('Failed to get cluster status');
62
+ output.error(err instanceof Error ? err.message : String(err));
63
+ process.exit(1);
64
+ }
65
+ finally {
66
+ await mode.closeLocalClient();
67
+ }
68
+ });
69
+ // Cluster takeover (API only)
70
+ cluster
71
+ .command('takeover')
72
+ .description('Force this node to become cluster leader')
73
+ .option('-y, --yes', 'Skip confirmation')
74
+ .action(async (options) => {
75
+ if (mode.getMode() === 'local') {
76
+ output.error('Cluster takeover requires API mode with authentication');
77
+ output.info('Use: znvault login first, or set ZNVAULT_API_KEY');
78
+ process.exit(1);
79
+ }
80
+ try {
81
+ if (!options.yes) {
82
+ const confirmed = await promptConfirm('Are you sure you want to force a leadership takeover?');
83
+ if (!confirmed) {
84
+ output.info('Takeover cancelled');
85
+ return;
86
+ }
87
+ }
88
+ const spinner = ora('Taking over leadership...').start();
89
+ try {
90
+ const result = await client.clusterTakeover();
91
+ spinner.succeed('Leadership takeover successful');
92
+ output.keyValue({
93
+ 'Success': result.success,
94
+ 'Message': result.message,
95
+ 'Node ID': result.nodeId,
96
+ });
97
+ }
98
+ catch (err) {
99
+ spinner.fail('Takeover failed');
100
+ throw err;
101
+ }
102
+ }
103
+ catch (err) {
104
+ output.error(err instanceof Error ? err.message : String(err));
105
+ process.exit(1);
106
+ }
107
+ });
108
+ // Cluster promote (API only)
109
+ cluster
110
+ .command('promote <nodeId>')
111
+ .description('Promote a specific node to become leader')
112
+ .option('-y, --yes', 'Skip confirmation')
113
+ .action(async (nodeId, options) => {
114
+ if (mode.getMode() === 'local') {
115
+ output.error('Cluster promote requires API mode with authentication');
116
+ output.info('Use: znvault login first, or set ZNVAULT_API_KEY');
117
+ process.exit(1);
118
+ }
119
+ try {
120
+ if (!options.yes) {
121
+ const confirmed = await promptConfirm(`Are you sure you want to promote node '${nodeId}' to leader?`);
122
+ if (!confirmed) {
123
+ output.info('Promotion cancelled');
124
+ return;
125
+ }
126
+ }
127
+ const spinner = ora(`Promoting node ${nodeId}...`).start();
128
+ try {
129
+ const result = await client.clusterPromote(nodeId);
130
+ spinner.succeed('Node promoted successfully');
131
+ output.keyValue({
132
+ 'Success': result.success,
133
+ 'Message': result.message,
134
+ });
135
+ }
136
+ catch (err) {
137
+ spinner.fail('Promotion failed');
138
+ throw err;
139
+ }
140
+ }
141
+ catch (err) {
142
+ output.error(err instanceof Error ? err.message : String(err));
143
+ process.exit(1);
144
+ }
145
+ });
146
+ // Cluster release (API only)
147
+ cluster
148
+ .command('release')
149
+ .description('Release leadership from this node')
150
+ .option('-y, --yes', 'Skip confirmation')
151
+ .action(async (options) => {
152
+ if (mode.getMode() === 'local') {
153
+ output.error('Cluster release requires API mode with authentication');
154
+ output.info('Use: znvault login first, or set ZNVAULT_API_KEY');
155
+ process.exit(1);
156
+ }
157
+ try {
158
+ if (!options.yes) {
159
+ const confirmed = await promptConfirm('Are you sure you want to release leadership?');
160
+ if (!confirmed) {
161
+ output.info('Release cancelled');
162
+ return;
163
+ }
164
+ }
165
+ const spinner = ora('Releasing leadership...').start();
166
+ try {
167
+ const result = await client.clusterRelease();
168
+ spinner.succeed('Leadership released');
169
+ output.keyValue({
170
+ 'Success': result.success,
171
+ 'Message': result.message,
172
+ });
173
+ }
174
+ catch (err) {
175
+ spinner.fail('Release failed');
176
+ throw err;
177
+ }
178
+ }
179
+ catch (err) {
180
+ output.error(err instanceof Error ? err.message : String(err));
181
+ process.exit(1);
182
+ }
183
+ });
184
+ // Cluster maintenance (API only)
185
+ cluster
186
+ .command('maintenance <action>')
187
+ .description('Enable or disable maintenance mode (enable|disable)')
188
+ .option('-y, --yes', 'Skip confirmation')
189
+ .action(async (action, options) => {
190
+ if (mode.getMode() === 'local') {
191
+ output.error('Cluster maintenance requires API mode with authentication');
192
+ output.info('Use: znvault login first, or set ZNVAULT_API_KEY');
193
+ process.exit(1);
194
+ }
195
+ try {
196
+ if (!['enable', 'disable'].includes(action)) {
197
+ output.error('Action must be "enable" or "disable"');
198
+ process.exit(1);
199
+ }
200
+ const enable = action === 'enable';
201
+ if (!options.yes) {
202
+ const confirmed = await promptConfirm(`Are you sure you want to ${action} maintenance mode?`);
203
+ if (!confirmed) {
204
+ output.info('Cancelled');
205
+ return;
206
+ }
207
+ }
208
+ const spinner = ora(`${enable ? 'Enabling' : 'Disabling'} maintenance mode...`).start();
209
+ try {
210
+ const result = await client.clusterMaintenance(enable);
211
+ spinner.succeed(`Maintenance mode ${enable ? 'enabled' : 'disabled'}`);
212
+ output.keyValue({
213
+ 'Success': result.success,
214
+ 'Maintenance Mode': result.maintenanceMode,
215
+ });
216
+ }
217
+ catch (err) {
218
+ spinner.fail(`Failed to ${action} maintenance mode`);
219
+ throw err;
220
+ }
221
+ }
222
+ catch (err) {
223
+ output.error(err instanceof Error ? err.message : String(err));
224
+ process.exit(1);
225
+ }
226
+ });
227
+ }
228
+ //# sourceMappingURL=cluster.js.map