@minecraft-docker/mcctl 1.5.0 → 1.6.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 (141) hide show
  1. package/dist/application/index.d.ts +2 -0
  2. package/dist/application/index.d.ts.map +1 -0
  3. package/dist/application/index.js +5 -0
  4. package/dist/application/index.js.map +1 -0
  5. package/dist/commands/backup.d.ts +16 -0
  6. package/dist/commands/backup.d.ts.map +1 -0
  7. package/dist/commands/backup.js +182 -0
  8. package/dist/commands/backup.js.map +1 -0
  9. package/dist/commands/ban.d.ts +14 -0
  10. package/dist/commands/ban.d.ts.map +1 -0
  11. package/dist/commands/ban.js +418 -0
  12. package/dist/commands/ban.js.map +1 -0
  13. package/dist/commands/config.d.ts +18 -0
  14. package/dist/commands/config.d.ts.map +1 -0
  15. package/dist/commands/config.js +106 -0
  16. package/dist/commands/config.js.map +1 -0
  17. package/dist/commands/create.d.ts +22 -0
  18. package/dist/commands/create.d.ts.map +1 -0
  19. package/dist/commands/create.js +83 -0
  20. package/dist/commands/create.js.map +1 -0
  21. package/dist/commands/delete.d.ts +17 -0
  22. package/dist/commands/delete.d.ts.map +1 -0
  23. package/dist/commands/delete.js +71 -0
  24. package/dist/commands/delete.js.map +1 -0
  25. package/dist/commands/exec.d.ts +10 -0
  26. package/dist/commands/exec.d.ts.map +1 -0
  27. package/dist/commands/exec.js +29 -0
  28. package/dist/commands/exec.js.map +1 -0
  29. package/dist/commands/index.d.ts +18 -0
  30. package/dist/commands/index.d.ts.map +1 -0
  31. package/dist/commands/index.js +18 -0
  32. package/dist/commands/index.js.map +1 -0
  33. package/dist/commands/init.d.ts +9 -0
  34. package/dist/commands/init.d.ts.map +1 -0
  35. package/dist/commands/init.js +186 -0
  36. package/dist/commands/init.js.map +1 -0
  37. package/dist/commands/kick.d.ts +12 -0
  38. package/dist/commands/kick.d.ts.map +1 -0
  39. package/dist/commands/kick.js +71 -0
  40. package/dist/commands/kick.js.map +1 -0
  41. package/dist/commands/migrate.d.ts +18 -0
  42. package/dist/commands/migrate.d.ts.map +1 -0
  43. package/dist/commands/migrate.js +470 -0
  44. package/dist/commands/migrate.js.map +1 -0
  45. package/dist/commands/op.d.ts +12 -0
  46. package/dist/commands/op.d.ts.map +1 -0
  47. package/dist/commands/op.js +220 -0
  48. package/dist/commands/op.js.map +1 -0
  49. package/dist/commands/player-online.d.ts +11 -0
  50. package/dist/commands/player-online.d.ts.map +1 -0
  51. package/dist/commands/player-online.js +151 -0
  52. package/dist/commands/player-online.js.map +1 -0
  53. package/dist/commands/player.d.ts +18 -0
  54. package/dist/commands/player.d.ts.map +1 -0
  55. package/dist/commands/player.js +352 -0
  56. package/dist/commands/player.js.map +1 -0
  57. package/dist/commands/server-backup.d.ts +36 -0
  58. package/dist/commands/server-backup.d.ts.map +1 -0
  59. package/dist/commands/server-backup.js +320 -0
  60. package/dist/commands/server-backup.js.map +1 -0
  61. package/dist/commands/server-restore.d.ts +13 -0
  62. package/dist/commands/server-restore.d.ts.map +1 -0
  63. package/dist/commands/server-restore.js +294 -0
  64. package/dist/commands/server-restore.js.map +1 -0
  65. package/dist/commands/status.d.ts +13 -0
  66. package/dist/commands/status.d.ts.map +1 -0
  67. package/dist/commands/status.js +325 -0
  68. package/dist/commands/status.js.map +1 -0
  69. package/dist/commands/whitelist.d.ts +12 -0
  70. package/dist/commands/whitelist.d.ts.map +1 -0
  71. package/dist/commands/whitelist.js +316 -0
  72. package/dist/commands/whitelist.js.map +1 -0
  73. package/dist/commands/world.d.ts +16 -0
  74. package/dist/commands/world.d.ts.map +1 -0
  75. package/dist/commands/world.js +135 -0
  76. package/dist/commands/world.js.map +1 -0
  77. package/dist/domain/index.d.ts +2 -0
  78. package/dist/domain/index.d.ts.map +1 -0
  79. package/dist/domain/index.js +7 -0
  80. package/dist/domain/index.js.map +1 -0
  81. package/dist/index.d.ts +3 -0
  82. package/dist/index.d.ts.map +1 -0
  83. package/dist/index.js +609 -0
  84. package/dist/index.js.map +1 -0
  85. package/dist/infrastructure/adapters/ClackPromptAdapter.d.ts +29 -0
  86. package/dist/infrastructure/adapters/ClackPromptAdapter.d.ts.map +1 -0
  87. package/dist/infrastructure/adapters/ClackPromptAdapter.js +419 -0
  88. package/dist/infrastructure/adapters/ClackPromptAdapter.js.map +1 -0
  89. package/dist/infrastructure/adapters/index.d.ts +3 -0
  90. package/dist/infrastructure/adapters/index.d.ts.map +1 -0
  91. package/dist/infrastructure/adapters/index.js +5 -0
  92. package/dist/infrastructure/adapters/index.js.map +1 -0
  93. package/dist/infrastructure/di/container.d.ts +47 -0
  94. package/dist/infrastructure/di/container.d.ts.map +1 -0
  95. package/dist/infrastructure/di/container.js +140 -0
  96. package/dist/infrastructure/di/container.js.map +1 -0
  97. package/dist/infrastructure/di/index.d.ts +2 -0
  98. package/dist/infrastructure/di/index.d.ts.map +1 -0
  99. package/dist/infrastructure/di/index.js +2 -0
  100. package/dist/infrastructure/di/index.js.map +1 -0
  101. package/dist/infrastructure/index.d.ts +4 -0
  102. package/dist/infrastructure/index.d.ts.map +1 -0
  103. package/dist/infrastructure/index.js +7 -0
  104. package/dist/infrastructure/index.js.map +1 -0
  105. package/dist/lib/mojang-api.d.ts +51 -0
  106. package/dist/lib/mojang-api.d.ts.map +1 -0
  107. package/dist/lib/mojang-api.js +136 -0
  108. package/dist/lib/mojang-api.js.map +1 -0
  109. package/dist/lib/player-cache.d.ts +79 -0
  110. package/dist/lib/player-cache.d.ts.map +1 -0
  111. package/dist/lib/player-cache.js +302 -0
  112. package/dist/lib/player-cache.js.map +1 -0
  113. package/dist/lib/player-json.d.ts +69 -0
  114. package/dist/lib/player-json.d.ts.map +1 -0
  115. package/dist/lib/player-json.js +96 -0
  116. package/dist/lib/player-json.js.map +1 -0
  117. package/dist/lib/prompts/action-select.d.ts +23 -0
  118. package/dist/lib/prompts/action-select.d.ts.map +1 -0
  119. package/dist/lib/prompts/action-select.js +124 -0
  120. package/dist/lib/prompts/action-select.js.map +1 -0
  121. package/dist/lib/prompts/index.d.ts +7 -0
  122. package/dist/lib/prompts/index.d.ts.map +1 -0
  123. package/dist/lib/prompts/index.js +7 -0
  124. package/dist/lib/prompts/index.js.map +1 -0
  125. package/dist/lib/prompts/player-select.d.ts +25 -0
  126. package/dist/lib/prompts/player-select.d.ts.map +1 -0
  127. package/dist/lib/prompts/player-select.js +122 -0
  128. package/dist/lib/prompts/player-select.js.map +1 -0
  129. package/dist/lib/prompts/server-select.d.ts +26 -0
  130. package/dist/lib/prompts/server-select.d.ts.map +1 -0
  131. package/dist/lib/prompts/server-select.js +99 -0
  132. package/dist/lib/prompts/server-select.js.map +1 -0
  133. package/dist/lib/rcon.d.ts +53 -0
  134. package/dist/lib/rcon.d.ts.map +1 -0
  135. package/dist/lib/rcon.js +131 -0
  136. package/dist/lib/rcon.js.map +1 -0
  137. package/dist/lib/shell.d.ts +109 -0
  138. package/dist/lib/shell.d.ts.map +1 -0
  139. package/dist/lib/shell.js +318 -0
  140. package/dist/lib/shell.js.map +1 -0
  141. package/package.json +2 -2
@@ -0,0 +1,320 @@
1
+ import { Paths, log, colors } from '@minecraft-docker/shared';
2
+ import { existsSync, mkdirSync, readdirSync, readFileSync, statSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { createHash } from 'node:crypto';
5
+ import * as tar from 'tar';
6
+ /**
7
+ * Get the backup directory for a server
8
+ */
9
+ function getBackupDir(paths, serverName) {
10
+ return join(paths.backups, 'servers', serverName);
11
+ }
12
+ /**
13
+ * Calculate SHA256 checksum of a file
14
+ */
15
+ function calculateChecksum(filePath) {
16
+ const content = readFileSync(filePath);
17
+ return `sha256:${createHash('sha256').update(content).digest('hex')}`;
18
+ }
19
+ /**
20
+ * Generate backup ID from current timestamp
21
+ */
22
+ function generateBackupId() {
23
+ const now = new Date();
24
+ const year = now.getFullYear();
25
+ const month = String(now.getMonth() + 1).padStart(2, '0');
26
+ const day = String(now.getDate()).padStart(2, '0');
27
+ const hours = String(now.getHours()).padStart(2, '0');
28
+ const minutes = String(now.getMinutes()).padStart(2, '0');
29
+ const seconds = String(now.getSeconds()).padStart(2, '0');
30
+ return `${year}${month}${day}-${hours}${minutes}${seconds}`;
31
+ }
32
+ /**
33
+ * Read server config.env and extract key settings
34
+ */
35
+ function readServerConfig(configPath) {
36
+ if (!existsSync(configPath)) {
37
+ return {};
38
+ }
39
+ const content = readFileSync(configPath, 'utf-8');
40
+ const config = {};
41
+ for (const line of content.split('\n')) {
42
+ const trimmed = line.trim();
43
+ if (!trimmed || trimmed.startsWith('#'))
44
+ continue;
45
+ const match = trimmed.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);
46
+ if (match) {
47
+ const [, key, value] = match;
48
+ const cleanValue = value.replace(/^["']|["']$/g, '');
49
+ if (key === 'TYPE')
50
+ config.type = cleanValue;
51
+ if (key === 'VERSION')
52
+ config.version = cleanValue;
53
+ if (key === 'MEMORY')
54
+ config.memory = cleanValue;
55
+ }
56
+ }
57
+ return config;
58
+ }
59
+ /**
60
+ * List all backups for a server
61
+ */
62
+ async function listBackups(paths, serverName, json) {
63
+ const backupDir = getBackupDir(paths, serverName);
64
+ if (!existsSync(backupDir)) {
65
+ if (json) {
66
+ console.log(JSON.stringify({ server: serverName, backups: [] }));
67
+ }
68
+ else {
69
+ log.info(`No backups found for server '${serverName}'`);
70
+ }
71
+ return 0;
72
+ }
73
+ const files = readdirSync(backupDir)
74
+ .filter(f => f.endsWith('.tar.gz'))
75
+ .sort()
76
+ .reverse();
77
+ const backups = [];
78
+ for (const file of files) {
79
+ const filePath = join(backupDir, file);
80
+ const stat = statSync(filePath);
81
+ const id = file.replace('.tar.gz', '');
82
+ // Try to read manifest from tar
83
+ let description = '';
84
+ let fileCount = 0;
85
+ try {
86
+ const entries = [];
87
+ await tar.list({
88
+ file: filePath,
89
+ onentry: (entry) => {
90
+ entries.push(entry.path);
91
+ if (entry.path === 'manifest.json') {
92
+ const chunks = [];
93
+ entry.on('data', (chunk) => chunks.push(chunk));
94
+ entry.on('end', () => {
95
+ try {
96
+ const manifest = JSON.parse(Buffer.concat(chunks).toString('utf-8'));
97
+ description = manifest.description || '';
98
+ fileCount = manifest.files?.length || 0;
99
+ }
100
+ catch {
101
+ // Ignore parse errors
102
+ }
103
+ });
104
+ }
105
+ }
106
+ });
107
+ if (fileCount === 0) {
108
+ fileCount = entries.filter(e => e !== 'manifest.json').length;
109
+ }
110
+ }
111
+ catch {
112
+ // If we can't read the tar, just use file stats
113
+ }
114
+ backups.push({
115
+ id,
116
+ createdAt: stat.mtime.toISOString(),
117
+ description,
118
+ size: stat.size,
119
+ fileCount
120
+ });
121
+ }
122
+ if (json) {
123
+ console.log(JSON.stringify({ server: serverName, backups }));
124
+ }
125
+ else {
126
+ console.log(colors.bold(`\nBackups for ${serverName}:\n`));
127
+ if (backups.length === 0) {
128
+ console.log(' (none)');
129
+ }
130
+ else {
131
+ for (const backup of backups) {
132
+ const sizeKB = Math.round(backup.size / 1024);
133
+ const date = new Date(backup.createdAt).toLocaleString();
134
+ console.log(` ${colors.cyan(backup.id)}`);
135
+ console.log(` Created: ${date}`);
136
+ console.log(` Size: ${sizeKB} KB, Files: ${backup.fileCount}`);
137
+ if (backup.description) {
138
+ console.log(` Description: ${backup.description}`);
139
+ }
140
+ console.log('');
141
+ }
142
+ }
143
+ }
144
+ return 0;
145
+ }
146
+ /**
147
+ * Create a backup of server configuration
148
+ */
149
+ async function createBackup(paths, serverName, message, json) {
150
+ const serverDir = paths.serverDir(serverName);
151
+ if (!existsSync(serverDir)) {
152
+ if (json) {
153
+ console.log(JSON.stringify({ success: false, error: 'server_not_found', server: serverName }));
154
+ }
155
+ else {
156
+ log.error(`Server '${serverName}' not found`);
157
+ }
158
+ return 1;
159
+ }
160
+ const backupDir = getBackupDir(paths, serverName);
161
+ const backupId = generateBackupId();
162
+ const backupPath = join(backupDir, `${backupId}.tar.gz`);
163
+ // Create backup directory if needed
164
+ if (!existsSync(backupDir)) {
165
+ mkdirSync(backupDir, { recursive: true });
166
+ }
167
+ // Define files to backup
168
+ const backupTargets = [
169
+ { path: 'config.env', required: true },
170
+ { path: 'docker-compose.yml', required: true },
171
+ { path: 'data/ops.json', required: false },
172
+ { path: 'data/whitelist.json', required: false },
173
+ { path: 'data/banned-players.json', required: false },
174
+ { path: 'data/banned-ips.json', required: false },
175
+ { path: 'data/server.properties', required: false },
176
+ ];
177
+ // Collect files that exist
178
+ const filesToBackup = [];
179
+ for (const target of backupTargets) {
180
+ const fullPath = join(serverDir, target.path);
181
+ if (existsSync(fullPath)) {
182
+ const stat = statSync(fullPath);
183
+ filesToBackup.push({
184
+ path: target.path,
185
+ fullPath,
186
+ size: stat.size,
187
+ checksum: calculateChecksum(fullPath)
188
+ });
189
+ }
190
+ else if (target.required) {
191
+ if (json) {
192
+ console.log(JSON.stringify({
193
+ success: false,
194
+ error: 'missing_required_file',
195
+ file: target.path,
196
+ server: serverName
197
+ }));
198
+ }
199
+ else {
200
+ log.error(`Required file missing: ${target.path}`);
201
+ }
202
+ return 1;
203
+ }
204
+ }
205
+ // Create manifest
206
+ const configPath = join(serverDir, 'config.env');
207
+ const manifest = {
208
+ version: '1.0',
209
+ serverName,
210
+ createdAt: new Date().toISOString(),
211
+ description: message || '',
212
+ mcctlVersion: '1.3.0',
213
+ files: filesToBackup.map(f => ({
214
+ path: f.path,
215
+ size: f.size,
216
+ checksum: f.checksum
217
+ })),
218
+ serverConfig: readServerConfig(configPath)
219
+ };
220
+ // Create temporary manifest file content
221
+ const manifestContent = JSON.stringify(manifest, null, 2);
222
+ try {
223
+ // Create tar.gz with all files
224
+ const fileList = filesToBackup.map(f => f.path);
225
+ await tar.create({
226
+ gzip: true,
227
+ file: backupPath,
228
+ cwd: serverDir,
229
+ prefix: ''
230
+ }, fileList);
231
+ // We need to add manifest to the archive
232
+ // Since tar.create doesn't easily support adding strings, we'll recreate with manifest
233
+ const tempManifestPath = join(serverDir, 'manifest.json.tmp');
234
+ const fs = await import('node:fs/promises');
235
+ await fs.writeFile(tempManifestPath, manifestContent);
236
+ // Recreate archive with manifest
237
+ await tar.create({
238
+ gzip: true,
239
+ file: backupPath,
240
+ cwd: serverDir,
241
+ prefix: ''
242
+ }, ['manifest.json.tmp', ...fileList]);
243
+ // Rename manifest.json.tmp to manifest.json inside archive by recreating
244
+ // Actually, let's just create properly
245
+ await fs.unlink(tempManifestPath);
246
+ // Create the archive properly with manifest
247
+ const manifestPath = join(serverDir, 'manifest.json');
248
+ await fs.writeFile(manifestPath, manifestContent);
249
+ await tar.create({
250
+ gzip: true,
251
+ file: backupPath,
252
+ cwd: serverDir,
253
+ prefix: ''
254
+ }, ['manifest.json', ...fileList]);
255
+ await fs.unlink(manifestPath);
256
+ const stat = statSync(backupPath);
257
+ const sizeKB = Math.round(stat.size / 1024);
258
+ if (json) {
259
+ console.log(JSON.stringify({
260
+ success: true,
261
+ server: serverName,
262
+ backupId,
263
+ path: backupPath,
264
+ size: stat.size,
265
+ files: manifest.files.length,
266
+ description: message || null
267
+ }));
268
+ }
269
+ else {
270
+ console.log(colors.green(`\n✓ Backup created successfully!\n`));
271
+ console.log(` ID: ${colors.cyan(backupId)}`);
272
+ console.log(` Path: ${backupPath}`);
273
+ console.log(` Size: ${sizeKB} KB`);
274
+ console.log(` Files: ${manifest.files.length}`);
275
+ if (message) {
276
+ console.log(` Description: ${message}`);
277
+ }
278
+ console.log('');
279
+ }
280
+ return 0;
281
+ }
282
+ catch (err) {
283
+ if (json) {
284
+ console.log(JSON.stringify({
285
+ success: false,
286
+ error: 'backup_failed',
287
+ message: err instanceof Error ? err.message : String(err),
288
+ server: serverName
289
+ }));
290
+ }
291
+ else {
292
+ log.error(`Failed to create backup: ${err instanceof Error ? err.message : String(err)}`);
293
+ }
294
+ return 1;
295
+ }
296
+ }
297
+ /**
298
+ * Server backup command handler
299
+ */
300
+ export async function serverBackupCommand(options) {
301
+ const paths = new Paths(options.root);
302
+ if (!paths.isInitialized()) {
303
+ log.error('Platform not initialized. Run: mcctl init');
304
+ return 1;
305
+ }
306
+ if (!options.serverName) {
307
+ log.error('Server name is required');
308
+ log.info('Usage: mcctl server-backup <server> [--list] [-m "message"]');
309
+ return 1;
310
+ }
311
+ // Normalize server name (remove mc- prefix if present)
312
+ const serverName = options.serverName.startsWith('mc-')
313
+ ? options.serverName.slice(3)
314
+ : options.serverName;
315
+ if (options.list) {
316
+ return listBackups(paths, serverName, options.json ?? false);
317
+ }
318
+ return createBackup(paths, serverName, options.message ?? '', options.json ?? false);
319
+ }
320
+ //# sourceMappingURL=server-backup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-backup.js","sourceRoot":"","sources":["../../src/commands/server-backup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface ServerRestoreOptions {
2
+ root?: string;
3
+ serverName?: string;
4
+ backupId?: string;
5
+ force?: boolean;
6
+ dryRun?: boolean;
7
+ json?: boolean;
8
+ }
9
+ /**
10
+ * Server restore command handler
11
+ */
12
+ export declare function serverRestoreCommand(options: ServerRestoreOptions): Promise<number>;
13
+ //# sourceMappingURL=server-restore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-restore.d.ts","sourceRoot":"","sources":["../../src/commands/server-restore.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA8SD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgDzF"}
@@ -0,0 +1,294 @@
1
+ import { Paths, log, colors } from '@minecraft-docker/shared';
2
+ import { existsSync, readdirSync, statSync, copyFileSync, mkdirSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import * as tar from 'tar';
5
+ import * as readline from 'node:readline';
6
+ /**
7
+ * Get the backup directory for a server
8
+ */
9
+ function getBackupDir(paths, serverName) {
10
+ return join(paths.backups, 'servers', serverName);
11
+ }
12
+ /**
13
+ * Read manifest from backup file
14
+ */
15
+ async function readManifest(backupPath) {
16
+ return new Promise((resolve) => {
17
+ let manifest = null;
18
+ tar.list({
19
+ file: backupPath,
20
+ onentry: (entry) => {
21
+ if (entry.path === 'manifest.json') {
22
+ const chunks = [];
23
+ entry.on('data', (chunk) => chunks.push(chunk));
24
+ entry.on('end', () => {
25
+ try {
26
+ manifest = JSON.parse(Buffer.concat(chunks).toString('utf-8'));
27
+ }
28
+ catch {
29
+ // Ignore parse errors
30
+ }
31
+ });
32
+ }
33
+ }
34
+ }).then(() => resolve(manifest)).catch(() => resolve(null));
35
+ });
36
+ }
37
+ /**
38
+ * Ask user for confirmation
39
+ */
40
+ async function confirm(message) {
41
+ const rl = readline.createInterface({
42
+ input: process.stdin,
43
+ output: process.stdout
44
+ });
45
+ return new Promise((resolve) => {
46
+ rl.question(`${message} (y/N): `, (answer) => {
47
+ rl.close();
48
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
49
+ });
50
+ });
51
+ }
52
+ /**
53
+ * List available backups and let user select
54
+ */
55
+ async function selectBackup(paths, serverName) {
56
+ const backupDir = getBackupDir(paths, serverName);
57
+ if (!existsSync(backupDir)) {
58
+ log.error(`No backups found for server '${serverName}'`);
59
+ return null;
60
+ }
61
+ const files = readdirSync(backupDir)
62
+ .filter(f => f.endsWith('.tar.gz'))
63
+ .sort()
64
+ .reverse();
65
+ if (files.length === 0) {
66
+ log.error(`No backups found for server '${serverName}'`);
67
+ return null;
68
+ }
69
+ console.log(colors.bold(`\nAvailable backups for ${serverName}:\n`));
70
+ const backupInfos = [];
71
+ for (let i = 0; i < files.length; i++) {
72
+ const file = files[i];
73
+ const filePath = join(backupDir, file);
74
+ const id = file.replace('.tar.gz', '');
75
+ const stat = statSync(filePath);
76
+ const date = stat.mtime.toLocaleString();
77
+ // Try to read description from manifest
78
+ const manifest = await readManifest(filePath);
79
+ const description = manifest?.description || '';
80
+ backupInfos.push({ id, date, description });
81
+ console.log(` ${colors.cyan(`[${i + 1}]`)} ${id}`);
82
+ console.log(` Created: ${date}`);
83
+ if (description) {
84
+ console.log(` Description: ${description}`);
85
+ }
86
+ }
87
+ console.log('');
88
+ const rl = readline.createInterface({
89
+ input: process.stdin,
90
+ output: process.stdout
91
+ });
92
+ return new Promise((resolve) => {
93
+ rl.question('Select backup number (or press Enter to cancel): ', (answer) => {
94
+ rl.close();
95
+ if (!answer.trim()) {
96
+ resolve(null);
97
+ return;
98
+ }
99
+ const num = parseInt(answer, 10);
100
+ if (isNaN(num) || num < 1 || num > backupInfos.length) {
101
+ log.error('Invalid selection');
102
+ resolve(null);
103
+ return;
104
+ }
105
+ resolve(backupInfos[num - 1].id);
106
+ });
107
+ });
108
+ }
109
+ /**
110
+ * Restore a backup
111
+ */
112
+ async function restoreBackup(paths, serverName, backupId, force, dryRun, json) {
113
+ const backupDir = getBackupDir(paths, serverName);
114
+ const backupPath = join(backupDir, `${backupId}.tar.gz`);
115
+ const serverDir = paths.serverDir(serverName);
116
+ if (!existsSync(backupPath)) {
117
+ if (json) {
118
+ console.log(JSON.stringify({
119
+ success: false,
120
+ error: 'backup_not_found',
121
+ backupId,
122
+ server: serverName
123
+ }));
124
+ }
125
+ else {
126
+ log.error(`Backup '${backupId}' not found for server '${serverName}'`);
127
+ }
128
+ return 1;
129
+ }
130
+ if (!existsSync(serverDir)) {
131
+ if (json) {
132
+ console.log(JSON.stringify({
133
+ success: false,
134
+ error: 'server_not_found',
135
+ server: serverName
136
+ }));
137
+ }
138
+ else {
139
+ log.error(`Server '${serverName}' not found`);
140
+ }
141
+ return 1;
142
+ }
143
+ // Read manifest
144
+ const manifest = await readManifest(backupPath);
145
+ if (!manifest) {
146
+ if (json) {
147
+ console.log(JSON.stringify({
148
+ success: false,
149
+ error: 'invalid_backup',
150
+ message: 'Could not read backup manifest',
151
+ backupId,
152
+ server: serverName
153
+ }));
154
+ }
155
+ else {
156
+ log.error('Could not read backup manifest');
157
+ }
158
+ return 1;
159
+ }
160
+ // Show what will be restored
161
+ if (!json) {
162
+ console.log(colors.bold(`\nRestore Summary:\n`));
163
+ console.log(` Server: ${serverName}`);
164
+ console.log(` Backup: ${backupId}`);
165
+ console.log(` Created: ${new Date(manifest.createdAt).toLocaleString()}`);
166
+ if (manifest.description) {
167
+ console.log(` Description: ${manifest.description}`);
168
+ }
169
+ console.log(`\n Files to restore:`);
170
+ for (const file of manifest.files) {
171
+ const exists = existsSync(join(serverDir, file.path));
172
+ const status = exists ? colors.yellow('(overwrite)') : colors.green('(new)');
173
+ console.log(` - ${file.path} ${status}`);
174
+ }
175
+ console.log('');
176
+ }
177
+ if (dryRun) {
178
+ if (json) {
179
+ console.log(JSON.stringify({
180
+ success: true,
181
+ dryRun: true,
182
+ server: serverName,
183
+ backupId,
184
+ files: manifest.files.map(f => f.path)
185
+ }));
186
+ }
187
+ else {
188
+ log.info('Dry run complete. No changes were made.');
189
+ }
190
+ return 0;
191
+ }
192
+ // Confirm unless forced
193
+ if (!force && !json) {
194
+ const confirmed = await confirm('Proceed with restore?');
195
+ if (!confirmed) {
196
+ log.info('Restore cancelled.');
197
+ return 0;
198
+ }
199
+ }
200
+ try {
201
+ // Create backup of current files before overwriting
202
+ const preRestoreBackupDir = join(backupDir, '.pre-restore');
203
+ if (!existsSync(preRestoreBackupDir)) {
204
+ mkdirSync(preRestoreBackupDir, { recursive: true });
205
+ }
206
+ for (const file of manifest.files) {
207
+ const currentPath = join(serverDir, file.path);
208
+ if (existsSync(currentPath)) {
209
+ const backupName = `${backupId}-${file.path.replace(/\//g, '_')}`;
210
+ copyFileSync(currentPath, join(preRestoreBackupDir, backupName));
211
+ }
212
+ }
213
+ // Extract files from backup
214
+ await tar.extract({
215
+ file: backupPath,
216
+ cwd: serverDir,
217
+ filter: (path) => path !== 'manifest.json' // Don't extract manifest to server dir
218
+ });
219
+ if (json) {
220
+ console.log(JSON.stringify({
221
+ success: true,
222
+ server: serverName,
223
+ backupId,
224
+ filesRestored: manifest.files.length,
225
+ preRestoreBackup: preRestoreBackupDir
226
+ }));
227
+ }
228
+ else {
229
+ console.log(colors.green(`\n✓ Restore completed successfully!\n`));
230
+ console.log(` Files restored: ${manifest.files.length}`);
231
+ console.log(` Pre-restore backup: ${preRestoreBackupDir}`);
232
+ console.log('');
233
+ log.warn('Server may need to be restarted for changes to take effect.');
234
+ }
235
+ return 0;
236
+ }
237
+ catch (err) {
238
+ if (json) {
239
+ console.log(JSON.stringify({
240
+ success: false,
241
+ error: 'restore_failed',
242
+ message: err instanceof Error ? err.message : String(err),
243
+ server: serverName,
244
+ backupId
245
+ }));
246
+ }
247
+ else {
248
+ log.error(`Failed to restore backup: ${err instanceof Error ? err.message : String(err)}`);
249
+ }
250
+ return 1;
251
+ }
252
+ }
253
+ /**
254
+ * Server restore command handler
255
+ */
256
+ export async function serverRestoreCommand(options) {
257
+ const paths = new Paths(options.root);
258
+ if (!paths.isInitialized()) {
259
+ log.error('Platform not initialized. Run: mcctl init');
260
+ return 1;
261
+ }
262
+ if (!options.serverName) {
263
+ log.error('Server name is required');
264
+ log.info('Usage: mcctl server-restore <server> [backup-id] [--force] [--dry-run]');
265
+ return 1;
266
+ }
267
+ // Normalize server name (remove mc- prefix if present)
268
+ const serverName = options.serverName.startsWith('mc-')
269
+ ? options.serverName.slice(3)
270
+ : options.serverName;
271
+ let backupId = options.backupId;
272
+ // If no backup ID provided, show interactive selection
273
+ if (!backupId && !options.json) {
274
+ backupId = await selectBackup(paths, serverName) ?? undefined;
275
+ if (!backupId) {
276
+ return 0; // User cancelled
277
+ }
278
+ }
279
+ else if (!backupId) {
280
+ if (options.json) {
281
+ console.log(JSON.stringify({
282
+ success: false,
283
+ error: 'backup_id_required',
284
+ server: serverName
285
+ }));
286
+ }
287
+ else {
288
+ log.error('Backup ID is required');
289
+ }
290
+ return 1;
291
+ }
292
+ return restoreBackup(paths, serverName, backupId, options.force ?? false, options.dryRun ?? false, options.json ?? false);
293
+ }
294
+ //# sourceMappingURL=server-restore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-restore.js","sourceRoot":"","sources":["../../src/commands/server-restore.ts"],"names":[],"mappings":"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"}