@minecraft-docker/mcctl 1.6.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.
- package/dist/application/index.d.ts +2 -0
- package/dist/application/index.d.ts.map +1 -0
- package/dist/application/index.js +5 -0
- package/dist/application/index.js.map +1 -0
- package/dist/commands/backup.d.ts +16 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/backup.js +182 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/ban.d.ts +14 -0
- package/dist/commands/ban.d.ts.map +1 -0
- package/dist/commands/ban.js +418 -0
- package/dist/commands/ban.js.map +1 -0
- package/dist/commands/config.d.ts +18 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +106 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/create.d.ts +22 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +83 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/delete.d.ts +17 -0
- package/dist/commands/delete.d.ts.map +1 -0
- package/dist/commands/delete.js +71 -0
- package/dist/commands/delete.js.map +1 -0
- package/dist/commands/exec.d.ts +10 -0
- package/dist/commands/exec.d.ts.map +1 -0
- package/dist/commands/exec.js +29 -0
- package/dist/commands/exec.js.map +1 -0
- package/dist/commands/index.d.ts +18 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +18 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +186 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/kick.d.ts +12 -0
- package/dist/commands/kick.d.ts.map +1 -0
- package/dist/commands/kick.js +71 -0
- package/dist/commands/kick.js.map +1 -0
- package/dist/commands/migrate.d.ts +18 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +470 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/op.d.ts +12 -0
- package/dist/commands/op.d.ts.map +1 -0
- package/dist/commands/op.js +220 -0
- package/dist/commands/op.js.map +1 -0
- package/dist/commands/player-online.d.ts +11 -0
- package/dist/commands/player-online.d.ts.map +1 -0
- package/dist/commands/player-online.js +151 -0
- package/dist/commands/player-online.js.map +1 -0
- package/dist/commands/player.d.ts +18 -0
- package/dist/commands/player.d.ts.map +1 -0
- package/dist/commands/player.js +352 -0
- package/dist/commands/player.js.map +1 -0
- package/dist/commands/server-backup.d.ts +36 -0
- package/dist/commands/server-backup.d.ts.map +1 -0
- package/dist/commands/server-backup.js +320 -0
- package/dist/commands/server-backup.js.map +1 -0
- package/dist/commands/server-restore.d.ts +13 -0
- package/dist/commands/server-restore.d.ts.map +1 -0
- package/dist/commands/server-restore.js +294 -0
- package/dist/commands/server-restore.js.map +1 -0
- package/dist/commands/status.d.ts +13 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +325 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/whitelist.d.ts +12 -0
- package/dist/commands/whitelist.d.ts.map +1 -0
- package/dist/commands/whitelist.js +316 -0
- package/dist/commands/whitelist.js.map +1 -0
- package/dist/commands/world.d.ts +16 -0
- package/dist/commands/world.d.ts.map +1 -0
- package/dist/commands/world.js +135 -0
- package/dist/commands/world.js.map +1 -0
- package/dist/domain/index.d.ts +2 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +7 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +609 -0
- package/dist/index.js.map +1 -0
- package/dist/infrastructure/adapters/ClackPromptAdapter.d.ts +29 -0
- package/dist/infrastructure/adapters/ClackPromptAdapter.d.ts.map +1 -0
- package/dist/infrastructure/adapters/ClackPromptAdapter.js +419 -0
- package/dist/infrastructure/adapters/ClackPromptAdapter.js.map +1 -0
- package/dist/infrastructure/adapters/index.d.ts +3 -0
- package/dist/infrastructure/adapters/index.d.ts.map +1 -0
- package/dist/infrastructure/adapters/index.js +5 -0
- package/dist/infrastructure/adapters/index.js.map +1 -0
- package/dist/infrastructure/di/container.d.ts +47 -0
- package/dist/infrastructure/di/container.d.ts.map +1 -0
- package/dist/infrastructure/di/container.js +140 -0
- package/dist/infrastructure/di/container.js.map +1 -0
- package/dist/infrastructure/di/index.d.ts +2 -0
- package/dist/infrastructure/di/index.d.ts.map +1 -0
- package/dist/infrastructure/di/index.js +2 -0
- package/dist/infrastructure/di/index.js.map +1 -0
- package/dist/infrastructure/index.d.ts +4 -0
- package/dist/infrastructure/index.d.ts.map +1 -0
- package/dist/infrastructure/index.js +7 -0
- package/dist/infrastructure/index.js.map +1 -0
- package/dist/lib/mojang-api.d.ts +51 -0
- package/dist/lib/mojang-api.d.ts.map +1 -0
- package/dist/lib/mojang-api.js +136 -0
- package/dist/lib/mojang-api.js.map +1 -0
- package/dist/lib/player-cache.d.ts +79 -0
- package/dist/lib/player-cache.d.ts.map +1 -0
- package/dist/lib/player-cache.js +302 -0
- package/dist/lib/player-cache.js.map +1 -0
- package/dist/lib/player-json.d.ts +69 -0
- package/dist/lib/player-json.d.ts.map +1 -0
- package/dist/lib/player-json.js +96 -0
- package/dist/lib/player-json.js.map +1 -0
- package/dist/lib/prompts/action-select.d.ts +23 -0
- package/dist/lib/prompts/action-select.d.ts.map +1 -0
- package/dist/lib/prompts/action-select.js +124 -0
- package/dist/lib/prompts/action-select.js.map +1 -0
- package/dist/lib/prompts/index.d.ts +7 -0
- package/dist/lib/prompts/index.d.ts.map +1 -0
- package/dist/lib/prompts/index.js +7 -0
- package/dist/lib/prompts/index.js.map +1 -0
- package/dist/lib/prompts/player-select.d.ts +25 -0
- package/dist/lib/prompts/player-select.d.ts.map +1 -0
- package/dist/lib/prompts/player-select.js +122 -0
- package/dist/lib/prompts/player-select.js.map +1 -0
- package/dist/lib/prompts/server-select.d.ts +26 -0
- package/dist/lib/prompts/server-select.d.ts.map +1 -0
- package/dist/lib/prompts/server-select.js +99 -0
- package/dist/lib/prompts/server-select.js.map +1 -0
- package/dist/lib/rcon.d.ts +53 -0
- package/dist/lib/rcon.d.ts.map +1 -0
- package/dist/lib/rcon.js +131 -0
- package/dist/lib/rcon.js.map +1 -0
- package/dist/lib/shell.d.ts +109 -0
- package/dist/lib/shell.d.ts.map +1 -0
- package/dist/lib/shell.js +318 -0
- package/dist/lib/shell.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Player entry in Minecraft JSON files (whitelist.json, ops.json, etc.)
|
|
3
|
+
*/
|
|
4
|
+
export interface PlayerEntry {
|
|
5
|
+
uuid: string;
|
|
6
|
+
name: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Banned player entry
|
|
10
|
+
*/
|
|
11
|
+
export interface BannedPlayerEntry {
|
|
12
|
+
uuid: string;
|
|
13
|
+
name: string;
|
|
14
|
+
created: string;
|
|
15
|
+
source: string;
|
|
16
|
+
expires: string;
|
|
17
|
+
reason: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Banned IP entry
|
|
21
|
+
*/
|
|
22
|
+
export interface BannedIpEntry {
|
|
23
|
+
ip: string;
|
|
24
|
+
created: string;
|
|
25
|
+
source: string;
|
|
26
|
+
expires: string;
|
|
27
|
+
reason: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Read player JSON file (whitelist.json, ops.json)
|
|
31
|
+
*/
|
|
32
|
+
export declare function readPlayerJson(path: string): Promise<PlayerEntry[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Write player JSON file
|
|
35
|
+
*/
|
|
36
|
+
export declare function writePlayerJson(path: string, entries: PlayerEntry[]): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Read banned players JSON file
|
|
39
|
+
*/
|
|
40
|
+
export declare function readBannedPlayersJson(path: string): Promise<BannedPlayerEntry[]>;
|
|
41
|
+
/**
|
|
42
|
+
* Write banned players JSON file
|
|
43
|
+
*/
|
|
44
|
+
export declare function writeBannedPlayersJson(path: string, entries: BannedPlayerEntry[]): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Read banned IPs JSON file
|
|
47
|
+
*/
|
|
48
|
+
export declare function readBannedIpsJson(path: string): Promise<BannedIpEntry[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Write banned IPs JSON file
|
|
51
|
+
*/
|
|
52
|
+
export declare function writeBannedIpsJson(path: string, entries: BannedIpEntry[]): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Find player by name in entries (case-insensitive)
|
|
55
|
+
*/
|
|
56
|
+
export declare function findPlayerByName(entries: PlayerEntry[], name: string): PlayerEntry | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Find banned player by name (case-insensitive)
|
|
59
|
+
*/
|
|
60
|
+
export declare function findBannedPlayerByName(entries: BannedPlayerEntry[], name: string): BannedPlayerEntry | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Find banned IP
|
|
63
|
+
*/
|
|
64
|
+
export declare function findBannedIp(entries: BannedIpEntry[], ip: string): BannedIpEntry | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Create ISO timestamp string
|
|
67
|
+
*/
|
|
68
|
+
export declare function createTimestamp(): string;
|
|
69
|
+
//# sourceMappingURL=player-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player-json.d.ts","sourceRoot":"","sources":["../../src/lib/player-json.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAYzE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGzF;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAYtF;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAY9E;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAE9F;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,iBAAiB,EAAE,EAC5B,IAAI,EAAE,MAAM,GACX,iBAAiB,GAAG,SAAS,CAE/B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAE5F;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
/**
|
|
4
|
+
* Read player JSON file (whitelist.json, ops.json)
|
|
5
|
+
*/
|
|
6
|
+
export async function readPlayerJson(path) {
|
|
7
|
+
if (!existsSync(path)) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
const content = await readFile(path, 'utf-8');
|
|
12
|
+
const data = JSON.parse(content);
|
|
13
|
+
return Array.isArray(data) ? data : [];
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Write player JSON file
|
|
21
|
+
*/
|
|
22
|
+
export async function writePlayerJson(path, entries) {
|
|
23
|
+
const content = JSON.stringify(entries, null, 2);
|
|
24
|
+
await writeFile(path, content, 'utf-8');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Read banned players JSON file
|
|
28
|
+
*/
|
|
29
|
+
export async function readBannedPlayersJson(path) {
|
|
30
|
+
if (!existsSync(path)) {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const content = await readFile(path, 'utf-8');
|
|
35
|
+
const data = JSON.parse(content);
|
|
36
|
+
return Array.isArray(data) ? data : [];
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Write banned players JSON file
|
|
44
|
+
*/
|
|
45
|
+
export async function writeBannedPlayersJson(path, entries) {
|
|
46
|
+
const content = JSON.stringify(entries, null, 2);
|
|
47
|
+
await writeFile(path, content, 'utf-8');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Read banned IPs JSON file
|
|
51
|
+
*/
|
|
52
|
+
export async function readBannedIpsJson(path) {
|
|
53
|
+
if (!existsSync(path)) {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const content = await readFile(path, 'utf-8');
|
|
58
|
+
const data = JSON.parse(content);
|
|
59
|
+
return Array.isArray(data) ? data : [];
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Write banned IPs JSON file
|
|
67
|
+
*/
|
|
68
|
+
export async function writeBannedIpsJson(path, entries) {
|
|
69
|
+
const content = JSON.stringify(entries, null, 2);
|
|
70
|
+
await writeFile(path, content, 'utf-8');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Find player by name in entries (case-insensitive)
|
|
74
|
+
*/
|
|
75
|
+
export function findPlayerByName(entries, name) {
|
|
76
|
+
return entries.find((entry) => entry.name.toLowerCase() === name.toLowerCase());
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Find banned player by name (case-insensitive)
|
|
80
|
+
*/
|
|
81
|
+
export function findBannedPlayerByName(entries, name) {
|
|
82
|
+
return entries.find((entry) => entry.name.toLowerCase() === name.toLowerCase());
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Find banned IP
|
|
86
|
+
*/
|
|
87
|
+
export function findBannedIp(entries, ip) {
|
|
88
|
+
return entries.find((entry) => entry.ip === ip);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Create ISO timestamp string
|
|
92
|
+
*/
|
|
93
|
+
export function createTimestamp() {
|
|
94
|
+
return new Date().toISOString().replace('T', ' ').replace('Z', ' +0000');
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=player-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player-json.js","sourceRoot":"","sources":["../../src/lib/player-json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action selection prompt component
|
|
3
|
+
* Reusable prompt for selecting player management actions
|
|
4
|
+
*/
|
|
5
|
+
export type PlayerAction = 'info' | 'whitelist-add' | 'whitelist-remove' | 'op-add' | 'op-remove' | 'ban' | 'unban' | 'kick' | 'back' | 'exit';
|
|
6
|
+
export interface ActionSelectOptions {
|
|
7
|
+
message?: string;
|
|
8
|
+
playerName: string;
|
|
9
|
+
isOnline: boolean;
|
|
10
|
+
isWhitelisted?: boolean;
|
|
11
|
+
isOperator?: boolean;
|
|
12
|
+
isBanned?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Prompt user to select an action for a player
|
|
16
|
+
* Returns the selected action or null if cancelled
|
|
17
|
+
*/
|
|
18
|
+
export declare function selectAction(options: ActionSelectOptions): Promise<PlayerAction | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Prompt for continue or another action
|
|
21
|
+
*/
|
|
22
|
+
export declare function promptContinue(playerName: string): Promise<'another' | 'back' | 'exit' | null>;
|
|
23
|
+
//# sourceMappingURL=action-select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-select.d.ts","sourceRoot":"","sources":["../../../src/lib/prompts/action-select.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,eAAe,GACf,kBAAkB,GAClB,QAAQ,GACR,WAAW,GACX,KAAK,GACL,OAAO,GACP,MAAM,GACN,MAAM,GACN,MAAM,CAAC;AAEX,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAmED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAgD7F;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,CAepG"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action selection prompt component
|
|
3
|
+
* Reusable prompt for selecting player management actions
|
|
4
|
+
*/
|
|
5
|
+
import { select, isCancel } from '@clack/prompts';
|
|
6
|
+
import { colors } from '@minecraft-docker/shared';
|
|
7
|
+
const ACTIONS = [
|
|
8
|
+
{
|
|
9
|
+
value: 'info',
|
|
10
|
+
label: 'View player info',
|
|
11
|
+
hint: 'UUID, skin, status',
|
|
12
|
+
enabled: () => true,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
value: 'whitelist-add',
|
|
16
|
+
label: 'Add to whitelist',
|
|
17
|
+
enabled: (opts) => !opts.isWhitelisted,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
value: 'whitelist-remove',
|
|
21
|
+
label: 'Remove from whitelist',
|
|
22
|
+
enabled: (opts) => opts.isWhitelisted === true,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
value: 'op-add',
|
|
26
|
+
label: 'Add as operator',
|
|
27
|
+
enabled: (opts) => !opts.isOperator,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
value: 'op-remove',
|
|
31
|
+
label: 'Remove as operator',
|
|
32
|
+
enabled: (opts) => opts.isOperator === true,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
value: 'ban',
|
|
36
|
+
label: 'Ban player',
|
|
37
|
+
enabled: (opts) => !opts.isBanned,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
value: 'unban',
|
|
41
|
+
label: 'Unban player',
|
|
42
|
+
enabled: (opts) => opts.isBanned === true,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
value: 'kick',
|
|
46
|
+
label: 'Kick player',
|
|
47
|
+
hint: 'online only',
|
|
48
|
+
enabled: (opts) => opts.isOnline,
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
const NAVIGATION = [
|
|
52
|
+
{
|
|
53
|
+
value: 'back',
|
|
54
|
+
label: '← Back to player selection',
|
|
55
|
+
enabled: () => true,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
value: 'exit',
|
|
59
|
+
label: '✕ Exit',
|
|
60
|
+
enabled: () => true,
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
/**
|
|
64
|
+
* Prompt user to select an action for a player
|
|
65
|
+
* Returns the selected action or null if cancelled
|
|
66
|
+
*/
|
|
67
|
+
export async function selectAction(options) {
|
|
68
|
+
const { message = `Select action for ${options.playerName}:` } = options;
|
|
69
|
+
// Filter enabled actions
|
|
70
|
+
const enabledActions = ACTIONS.filter(action => action.enabled(options));
|
|
71
|
+
// Build options list
|
|
72
|
+
const selectOptions = [];
|
|
73
|
+
for (const action of enabledActions) {
|
|
74
|
+
selectOptions.push({
|
|
75
|
+
value: action.value,
|
|
76
|
+
label: action.label,
|
|
77
|
+
hint: action.hint,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// Add separator-like divider
|
|
81
|
+
selectOptions.push({
|
|
82
|
+
value: 'back',
|
|
83
|
+
label: colors.dim('─────────────────'),
|
|
84
|
+
hint: '',
|
|
85
|
+
});
|
|
86
|
+
// Add navigation options
|
|
87
|
+
for (const nav of NAVIGATION) {
|
|
88
|
+
selectOptions.push({
|
|
89
|
+
value: nav.value,
|
|
90
|
+
label: nav.label,
|
|
91
|
+
hint: nav.hint,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const selected = await select({
|
|
95
|
+
message,
|
|
96
|
+
options: selectOptions,
|
|
97
|
+
});
|
|
98
|
+
if (isCancel(selected)) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
// Handle divider selection (treat as back)
|
|
102
|
+
if (selected.startsWith('─')) {
|
|
103
|
+
return 'back';
|
|
104
|
+
}
|
|
105
|
+
return selected;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Prompt for continue or another action
|
|
109
|
+
*/
|
|
110
|
+
export async function promptContinue(playerName) {
|
|
111
|
+
const selected = await select({
|
|
112
|
+
message: `Another action for ${playerName}?`,
|
|
113
|
+
options: [
|
|
114
|
+
{ value: 'another', label: 'Yes, perform another action' },
|
|
115
|
+
{ value: 'back', label: '← Back to player selection' },
|
|
116
|
+
{ value: 'exit', label: '✕ Exit' },
|
|
117
|
+
],
|
|
118
|
+
});
|
|
119
|
+
if (isCancel(selected)) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
return selected;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=action-select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-select.js","sourceRoot":"","sources":["../../../src/lib/prompts/action-select.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reusable prompt components for CLI
|
|
3
|
+
*/
|
|
4
|
+
export { selectServer, getServerList, type ServerInfo, type ServerSelectOptions } from './server-select.js';
|
|
5
|
+
export { selectPlayer, promptPlayerName, type PlayerSelectOptions, type SelectedPlayer } from './player-select.js';
|
|
6
|
+
export { selectAction, promptContinue, type PlayerAction, type ActionSelectOptions } from './action-select.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/prompts/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC5G,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACnH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reusable prompt components for CLI
|
|
3
|
+
*/
|
|
4
|
+
export { selectServer, getServerList } from './server-select.js';
|
|
5
|
+
export { selectPlayer, promptPlayerName } from './player-select.js';
|
|
6
|
+
export { selectAction, promptContinue } from './action-select.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/prompts/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAA6C,MAAM,oBAAoB,CAAC;AAC5G,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAiD,MAAM,oBAAoB,CAAC;AACnH,OAAO,EAAE,YAAY,EAAE,cAAc,EAA+C,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Player selection prompt component
|
|
3
|
+
* Reusable prompt for selecting a player from online players or manual entry
|
|
4
|
+
*/
|
|
5
|
+
export interface PlayerSelectOptions {
|
|
6
|
+
message?: string;
|
|
7
|
+
containerName: string;
|
|
8
|
+
allowManualEntry?: boolean;
|
|
9
|
+
includeOffline?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface SelectedPlayer {
|
|
12
|
+
name: string;
|
|
13
|
+
isOnline: boolean;
|
|
14
|
+
source: 'online' | 'manual';
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Prompt user to select a player
|
|
18
|
+
* Returns the selected player info or null if cancelled
|
|
19
|
+
*/
|
|
20
|
+
export declare function selectPlayer(options: PlayerSelectOptions): Promise<SelectedPlayer | null>;
|
|
21
|
+
/**
|
|
22
|
+
* Simple text prompt for player name
|
|
23
|
+
*/
|
|
24
|
+
export declare function promptPlayerName(message?: string): Promise<string | null>;
|
|
25
|
+
//# sourceMappingURL=player-select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player-select.d.ts","sourceRoot":"","sources":["../../../src/lib/prompts/player-select.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC7B;AAID;;;GAGG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAgF/F;AA2BD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,SAAuB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoB7F"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Player selection prompt component
|
|
3
|
+
* Reusable prompt for selecting a player from online players or manual entry
|
|
4
|
+
*/
|
|
5
|
+
import { select, text, isCancel } from '@clack/prompts';
|
|
6
|
+
import { colors, log } from '@minecraft-docker/shared';
|
|
7
|
+
import { getOnlinePlayers } from '../rcon.js';
|
|
8
|
+
const MANUAL_ENTRY_VALUE = '__manual__';
|
|
9
|
+
/**
|
|
10
|
+
* Prompt user to select a player
|
|
11
|
+
* Returns the selected player info or null if cancelled
|
|
12
|
+
*/
|
|
13
|
+
export async function selectPlayer(options) {
|
|
14
|
+
const { containerName, message = 'Select player:', allowManualEntry = true, includeOffline = false, } = options;
|
|
15
|
+
// Get online players
|
|
16
|
+
let onlinePlayers = [];
|
|
17
|
+
try {
|
|
18
|
+
const result = await getOnlinePlayers(containerName);
|
|
19
|
+
onlinePlayers = result.players;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Ignore errors, just show empty list
|
|
23
|
+
}
|
|
24
|
+
// Build options list
|
|
25
|
+
const selectOptions = [];
|
|
26
|
+
// Add online players
|
|
27
|
+
for (const player of onlinePlayers) {
|
|
28
|
+
selectOptions.push({
|
|
29
|
+
value: player,
|
|
30
|
+
label: player,
|
|
31
|
+
hint: colors.green('online'),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// Add manual entry option if allowed
|
|
35
|
+
if (allowManualEntry) {
|
|
36
|
+
selectOptions.push({
|
|
37
|
+
value: MANUAL_ENTRY_VALUE,
|
|
38
|
+
label: 'Enter player name manually',
|
|
39
|
+
hint: colors.dim('type a name'),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
// If no options available
|
|
43
|
+
if (selectOptions.length === 0) {
|
|
44
|
+
log.error('No players available and manual entry is disabled');
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
// If only manual entry is available
|
|
48
|
+
const firstOption = selectOptions[0];
|
|
49
|
+
if (selectOptions.length === 1 && firstOption && firstOption.value === MANUAL_ENTRY_VALUE) {
|
|
50
|
+
log.info('No players online, entering manual mode');
|
|
51
|
+
const playerName = await promptManualPlayerName();
|
|
52
|
+
if (!playerName)
|
|
53
|
+
return null;
|
|
54
|
+
return { name: playerName, isOnline: false, source: 'manual' };
|
|
55
|
+
}
|
|
56
|
+
const selected = await select({
|
|
57
|
+
message,
|
|
58
|
+
options: selectOptions,
|
|
59
|
+
});
|
|
60
|
+
if (isCancel(selected)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
// Handle manual entry
|
|
64
|
+
if (selected === MANUAL_ENTRY_VALUE) {
|
|
65
|
+
const playerName = await promptManualPlayerName();
|
|
66
|
+
if (!playerName)
|
|
67
|
+
return null;
|
|
68
|
+
const isOnline = onlinePlayers.some(p => p.toLowerCase() === playerName.toLowerCase());
|
|
69
|
+
return { name: playerName, isOnline, source: 'manual' };
|
|
70
|
+
}
|
|
71
|
+
// Return selected online player
|
|
72
|
+
return {
|
|
73
|
+
name: selected,
|
|
74
|
+
isOnline: true,
|
|
75
|
+
source: 'online',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Prompt for manual player name entry
|
|
80
|
+
*/
|
|
81
|
+
async function promptManualPlayerName() {
|
|
82
|
+
const playerName = await text({
|
|
83
|
+
message: 'Enter player name:',
|
|
84
|
+
placeholder: 'Notch',
|
|
85
|
+
validate: (value) => {
|
|
86
|
+
if (!value || value.trim().length === 0) {
|
|
87
|
+
return 'Player name is required';
|
|
88
|
+
}
|
|
89
|
+
if (!/^[a-zA-Z0-9_]{3,16}$/.test(value.trim())) {
|
|
90
|
+
return 'Invalid player name (3-16 characters, letters, numbers, underscore)';
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
if (isCancel(playerName)) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return playerName.trim();
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Simple text prompt for player name
|
|
102
|
+
*/
|
|
103
|
+
export async function promptPlayerName(message = 'Enter player name:') {
|
|
104
|
+
const playerName = await text({
|
|
105
|
+
message,
|
|
106
|
+
placeholder: 'Notch',
|
|
107
|
+
validate: (value) => {
|
|
108
|
+
if (!value || value.trim().length === 0) {
|
|
109
|
+
return 'Player name is required';
|
|
110
|
+
}
|
|
111
|
+
if (!/^[a-zA-Z0-9_]{3,16}$/.test(value.trim())) {
|
|
112
|
+
return 'Invalid player name (3-16 characters, letters, numbers, underscore)';
|
|
113
|
+
}
|
|
114
|
+
return undefined;
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
if (isCancel(playerName)) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
return playerName.trim();
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=player-select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player-select.js","sourceRoot":"","sources":["../../../src/lib/prompts/player-select.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server selection prompt component
|
|
3
|
+
* Reusable prompt for selecting a Minecraft server
|
|
4
|
+
*/
|
|
5
|
+
export interface ServerInfo {
|
|
6
|
+
name: string;
|
|
7
|
+
containerName: string;
|
|
8
|
+
status: 'running' | 'stopped' | 'unknown';
|
|
9
|
+
playerCount?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface ServerSelectOptions {
|
|
12
|
+
message?: string;
|
|
13
|
+
servers: ServerInfo[];
|
|
14
|
+
includeAllOption?: boolean;
|
|
15
|
+
allowOffline?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Prompt user to select a server
|
|
19
|
+
* Returns the server name or null if cancelled
|
|
20
|
+
*/
|
|
21
|
+
export declare function selectServer(options: ServerSelectOptions): Promise<string | null>;
|
|
22
|
+
/**
|
|
23
|
+
* Get list of servers from Docker
|
|
24
|
+
*/
|
|
25
|
+
export declare function getServerList(): Promise<ServerInfo[]>;
|
|
26
|
+
//# sourceMappingURL=server-select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-select.d.ts","sourceRoot":"","sources":["../../../src/lib/prompts/server-select.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoEvF;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAkC3D"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server selection prompt component
|
|
3
|
+
* Reusable prompt for selecting a Minecraft server
|
|
4
|
+
*/
|
|
5
|
+
import { select, isCancel } from '@clack/prompts';
|
|
6
|
+
import { colors, log } from '@minecraft-docker/shared';
|
|
7
|
+
import { getOnlinePlayerCount } from '../rcon.js';
|
|
8
|
+
/**
|
|
9
|
+
* Prompt user to select a server
|
|
10
|
+
* Returns the server name or null if cancelled
|
|
11
|
+
*/
|
|
12
|
+
export async function selectServer(options) {
|
|
13
|
+
const { servers, message = 'Select server:', includeAllOption = false, allowOffline = false } = options;
|
|
14
|
+
if (servers.length === 0) {
|
|
15
|
+
log.error('No servers found');
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
// Filter to running servers only if not allowing offline
|
|
19
|
+
const availableServers = allowOffline ? servers : servers.filter(s => s.status === 'running');
|
|
20
|
+
if (availableServers.length === 0) {
|
|
21
|
+
log.error('No running servers found');
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
// Fetch player counts for running servers
|
|
25
|
+
const serversWithPlayers = await Promise.all(availableServers.map(async (server) => {
|
|
26
|
+
if (server.status === 'running' && server.playerCount === undefined) {
|
|
27
|
+
try {
|
|
28
|
+
const count = await getOnlinePlayerCount(server.containerName);
|
|
29
|
+
return { ...server, playerCount: count };
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return { ...server, playerCount: 0 };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return server;
|
|
36
|
+
}));
|
|
37
|
+
// Build options list
|
|
38
|
+
const selectOptions = [];
|
|
39
|
+
if (includeAllOption) {
|
|
40
|
+
selectOptions.push({
|
|
41
|
+
value: '__all__',
|
|
42
|
+
label: 'All servers',
|
|
43
|
+
hint: `${serversWithPlayers.length} servers`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
for (const server of serversWithPlayers) {
|
|
47
|
+
const statusLabel = server.status === 'running'
|
|
48
|
+
? colors.green('online')
|
|
49
|
+
: colors.dim('offline');
|
|
50
|
+
const playerLabel = server.status === 'running' && server.playerCount !== undefined
|
|
51
|
+
? `${server.playerCount} player${server.playerCount !== 1 ? 's' : ''}`
|
|
52
|
+
: '';
|
|
53
|
+
selectOptions.push({
|
|
54
|
+
value: server.name,
|
|
55
|
+
label: server.name,
|
|
56
|
+
hint: [statusLabel, playerLabel].filter(Boolean).join(', '),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const selected = await select({
|
|
60
|
+
message,
|
|
61
|
+
options: selectOptions,
|
|
62
|
+
});
|
|
63
|
+
if (isCancel(selected)) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
return selected;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get list of servers from Docker
|
|
70
|
+
*/
|
|
71
|
+
export async function getServerList() {
|
|
72
|
+
// This function should be implemented to get servers from Docker
|
|
73
|
+
// For now, we'll import from the shell executor pattern
|
|
74
|
+
const { execSync } = await import('node:child_process');
|
|
75
|
+
try {
|
|
76
|
+
// Get all mc-* containers
|
|
77
|
+
const output = execSync('docker ps -a --filter "name=mc-" --format "{{.Names}}|{{.Status}}"', { encoding: 'utf-8' });
|
|
78
|
+
const servers = [];
|
|
79
|
+
for (const line of output.trim().split('\n')) {
|
|
80
|
+
if (!line || line.includes('mc-router'))
|
|
81
|
+
continue;
|
|
82
|
+
const [containerName, status] = line.split('|');
|
|
83
|
+
if (!containerName)
|
|
84
|
+
continue;
|
|
85
|
+
const name = containerName.replace('mc-', '');
|
|
86
|
+
const isRunning = status?.toLowerCase().includes('up');
|
|
87
|
+
servers.push({
|
|
88
|
+
name,
|
|
89
|
+
containerName,
|
|
90
|
+
status: isRunning ? 'running' : 'stopped',
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return servers;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=server-select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-select.js","sourceRoot":"","sources":["../../../src/lib/prompts/server-select.ts"],"names":[],"mappings":"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"}
|