@powernukkitx/cli 1.0.0 → 1.0.2
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/LICENSE +21 -0
- package/README.md +186 -203
- package/dist/cli.js +34 -46
- package/dist/commands/backup.d.ts +2 -2
- package/dist/commands/backup.js +23 -24
- package/dist/commands/config.d.ts +1 -1
- package/dist/commands/config.js +60 -61
- package/dist/commands/console.d.ts +2 -2
- package/dist/commands/console.js +98 -99
- package/dist/commands/doctor.d.ts +2 -2
- package/dist/commands/doctor.js +97 -98
- package/dist/commands/info.d.ts +2 -2
- package/dist/commands/info.js +41 -42
- package/dist/commands/init.d.ts +2 -2
- package/dist/commands/init.js +87 -66
- package/dist/commands/install.js +45 -0
- package/dist/commands/logs.d.ts +2 -2
- package/dist/commands/logs.js +60 -61
- package/dist/commands/menu.js +94 -86
- package/dist/commands/plugin/index.d.ts +2 -2
- package/dist/commands/plugin/index.js +13 -13
- package/dist/commands/plugin/info.d.ts +2 -2
- package/dist/commands/plugin/info.js +39 -40
- package/dist/commands/plugin/install.d.ts +2 -2
- package/dist/commands/plugin/install.js +56 -57
- package/dist/commands/plugin/installed.d.ts +2 -2
- package/dist/commands/plugin/installed.js +41 -42
- package/dist/commands/plugin/list.d.ts +2 -2
- package/dist/commands/plugin/list.js +47 -49
- package/dist/commands/plugin/remove.d.ts +2 -2
- package/dist/commands/plugin/remove.js +44 -45
- package/dist/commands/plugin/search.d.ts +2 -2
- package/dist/commands/plugin/search.js +11 -12
- package/dist/commands/plugin/update.d.ts +2 -2
- package/dist/commands/plugin/update.js +52 -53
- package/dist/commands/start.d.ts +2 -2
- package/dist/commands/start.js +74 -75
- package/dist/commands/stop.d.ts +2 -2
- package/dist/commands/stop.js +26 -27
- package/dist/commands/update.d.ts +2 -2
- package/dist/commands/update.js +34 -35
- package/dist/commands/use.d.ts +2 -2
- package/dist/commands/use.js +39 -40
- package/dist/infra/http.js +119 -121
- package/dist/infra/paths.js +15 -20
- package/dist/infra/store.js +24 -27
- package/dist/services/backup.js +34 -40
- package/dist/services/plugins.js +139 -111
- package/dist/services/process.js +41 -43
- package/dist/services/release.js +51 -38
- package/dist/services/server.js +81 -89
- package/dist/ui/output.js +67 -71
- package/dist/ui/prompts.js +26 -30
- package/dist/ui/theme.js +16 -18
- package/package.json +44 -46
- package/dist/bundle.js +0 -18
- package/dist/commands/cfg.d.ts +0 -2
- package/dist/commands/cfg.js +0 -61
- package/dist/commands/lang.d.ts +0 -2
- package/dist/commands/lang.js +0 -28
- package/dist/commands/plugin.d.ts +0 -1
- package/dist/commands/plugin.js +0 -1
- package/dist/core/config.d.ts +0 -13
- package/dist/core/config.js +0 -31
- package/dist/core/network.d.ts +0 -13
- package/dist/core/network.js +0 -139
- package/dist/core/output.d.ts +0 -33
- package/dist/core/output.js +0 -75
- package/dist/core/process.d.ts +0 -10
- package/dist/core/process.js +0 -53
- package/dist/i18n/en.json +0 -174
- package/dist/i18n/fr.json +0 -174
- package/dist/i18n/index.js +0 -58
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/lang/en.json +0 -146
- package/dist/lang/fr.json +0 -146
- package/dist/lang/index.d.ts +0 -7
- package/dist/lang/index.js +0 -83
- package/dist/main.d.ts +0 -2
- package/dist/main.js +0 -28
- package/dist/plugins.json +0 -66
- package/dist/types.d.ts +0 -61
- package/dist/types.js +0 -1
- package/dist/utils/api.d.ts +0 -9
- package/dist/utils/api.js +0 -24
- package/dist/utils/github.d.ts +0 -20
- package/dist/utils/github.js +0 -60
- package/dist/utils/logger.d.ts +0 -15
- package/dist/utils/logger.js +0 -72
- package/dist/utils/pause.d.ts +0 -1
- package/dist/utils/pause.js +0 -6
- package/dist/utils/plugins.d.ts +0 -4
- package/dist/utils/plugins.js +0 -34
- package/dist/utils/server.d.ts +0 -3
- package/dist/utils/server.js +0 -32
- package/dist/utils/updater.d.ts +0 -1
- package/dist/utils/updater.js +0 -86
package/dist/commands/info.js
CHANGED
|
@@ -1,42 +1,41 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { readdir } from 'node:fs/promises';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { freemem, totalmem } from 'node:os';
|
|
5
|
-
import { defineCommand } from 'citty';
|
|
6
|
-
import { intro, outro, log, section, isJson, json } from '../ui/output.js';
|
|
7
|
-
import { c } from '../ui/theme.js';
|
|
8
|
-
import { resolveServerDir } from '../services/server.js';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
log.info(`${
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
});
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readdir } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { freemem, totalmem } from 'node:os';
|
|
5
|
+
import { defineCommand } from 'citty';
|
|
6
|
+
import { intro, outro, log, section, isJson, json } from '../ui/output.js';
|
|
7
|
+
import { c } from '../ui/theme.js';
|
|
8
|
+
import { resolveServerDir } from '../services/server.js';
|
|
9
|
+
export const infoCmd = defineCommand({
|
|
10
|
+
meta: { description: 'Show server information' },
|
|
11
|
+
args: {},
|
|
12
|
+
async run() {
|
|
13
|
+
const serverPath = await resolveServerDir();
|
|
14
|
+
const installed = serverPath !== null;
|
|
15
|
+
let plugins = [], worlds = [];
|
|
16
|
+
if (serverPath && existsSync(join(serverPath, 'plugins'))) {
|
|
17
|
+
plugins = (await readdir(join(serverPath, 'plugins'))).filter(f => f.endsWith('.jar'));
|
|
18
|
+
}
|
|
19
|
+
if (serverPath && existsSync(join(serverPath, 'worlds'))) {
|
|
20
|
+
worlds = await readdir(join(serverPath, 'worlds'));
|
|
21
|
+
}
|
|
22
|
+
const freeMb = Math.round(freemem() / 1024 / 1024);
|
|
23
|
+
const totalMb = Math.round(totalmem() / 1024 / 1024);
|
|
24
|
+
if (isJson())
|
|
25
|
+
json({
|
|
26
|
+
status: installed ? 'installed' : 'not_installed',
|
|
27
|
+
serverDir: serverPath, plugins: plugins.length, worlds: worlds.length,
|
|
28
|
+
ram: { freeMb, totalMb },
|
|
29
|
+
});
|
|
30
|
+
intro(`📊 ${"Server info"}`);
|
|
31
|
+
section("Server");
|
|
32
|
+
log.info(`${"Status".padEnd(12)} ${installed ? c.green('✔ ' + "Installed") : c.red('✘ ' + "Not installed")}`);
|
|
33
|
+
if (serverPath)
|
|
34
|
+
log.info(`${"Path".padEnd(12)} ${c.accent(serverPath)}`);
|
|
35
|
+
log.info(`${"Plugins".padEnd(12)} ${plugins.length}`);
|
|
36
|
+
log.info(`${"Worlds".padEnd(12)} ${worlds.length}`);
|
|
37
|
+
section("System");
|
|
38
|
+
log.info(`${"Free RAM".padEnd(12)} ${freeMb} MB / ${totalMb} MB`);
|
|
39
|
+
outro(installed ? "Ready to start with 'pnx start'" : "Run 'pnx init' to create a server");
|
|
40
|
+
},
|
|
41
|
+
});
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { CommandDef } from 'citty';
|
|
2
|
-
export declare const initCmd: CommandDef;
|
|
1
|
+
import type { CommandDef } from 'citty';
|
|
2
|
+
export declare const initCmd: CommandDef;
|
package/dist/commands/init.js
CHANGED
|
@@ -1,66 +1,87 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { mkdir } from 'node:fs/promises';
|
|
3
|
-
import { join, resolve } from 'node:path';
|
|
4
|
-
import { cwd } from 'node:process';
|
|
5
|
-
import { defineCommand } from 'citty';
|
|
6
|
-
import { intro, outro, log, spin, progress } from '../ui/output.js';
|
|
7
|
-
import { promptText, promptConfirm } from '../ui/prompts.js';
|
|
8
|
-
import {
|
|
9
|
-
import { startScripts } from '../services/server.js';
|
|
10
|
-
import { downloadFile } from '../infra/http.js';
|
|
11
|
-
import { JAR_NAME } from '../infra/paths.js';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
dev: { type: 'boolean', description: 'Install dev version', default: false },
|
|
18
|
-
},
|
|
19
|
-
async run({ args }) {
|
|
20
|
-
intro(`⚡ ${
|
|
21
|
-
let target = args.dir;
|
|
22
|
-
if (!target) {
|
|
23
|
-
target = await promptText({
|
|
24
|
-
message:
|
|
25
|
-
defaultValue: 'pnx-server',
|
|
26
|
-
validate: v => {
|
|
27
|
-
if (!v || !v.trim())
|
|
28
|
-
return 'Required';
|
|
29
|
-
if (existsSync(join(resolve(cwd(), v), JAR_NAME)))
|
|
30
|
-
return
|
|
31
|
-
return undefined;
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
const serverDir = resolve(cwd(), target);
|
|
36
|
-
if (existsSync(join(serverDir, JAR_NAME)) && args.dir) {
|
|
37
|
-
log.error(
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
const sp = spin(
|
|
42
|
-
const
|
|
43
|
-
sp.stop(`${
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
});
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { mkdir } from 'node:fs/promises';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
import { cwd } from 'node:process';
|
|
5
|
+
import { defineCommand } from 'citty';
|
|
6
|
+
import { intro, outro, log, spin, progress, isJson } from '../ui/output.js';
|
|
7
|
+
import { promptText, promptConfirm, promptSelect } from '../ui/prompts.js';
|
|
8
|
+
import { listReleases, downloadCore } from '../services/release.js';
|
|
9
|
+
import { startScripts, setDefaultServer } from '../services/server.js';
|
|
10
|
+
import { downloadFile } from '../infra/http.js';
|
|
11
|
+
import { JAR_NAME } from '../infra/paths.js';
|
|
12
|
+
export const initCmd = defineCommand({
|
|
13
|
+
meta: { description: 'Create a new PowerNukkitX server' },
|
|
14
|
+
args: {
|
|
15
|
+
dir: { type: 'string', description: 'Target directory' },
|
|
16
|
+
version: { type: 'string', description: 'Version to install (tag), skips the picker' },
|
|
17
|
+
dev: { type: 'boolean', description: 'Install dev version', default: false },
|
|
18
|
+
},
|
|
19
|
+
async run({ args }) {
|
|
20
|
+
intro(`⚡ ${"Create a PowerNukkitX server"}`);
|
|
21
|
+
let target = args.dir;
|
|
22
|
+
if (!target) {
|
|
23
|
+
target = await promptText({
|
|
24
|
+
message: "Server directory?",
|
|
25
|
+
defaultValue: 'pnx-server',
|
|
26
|
+
validate: v => {
|
|
27
|
+
if (!v || !v.trim())
|
|
28
|
+
return 'Required';
|
|
29
|
+
if (existsSync(join(resolve(cwd(), v), JAR_NAME)))
|
|
30
|
+
return "A server already exists here";
|
|
31
|
+
return undefined;
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const serverDir = resolve(cwd(), target);
|
|
36
|
+
if (existsSync(join(serverDir, JAR_NAME)) && args.dir) {
|
|
37
|
+
log.error("A server already exists here");
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const sp = spin("Fetching versions...");
|
|
42
|
+
const releases = await listReleases();
|
|
43
|
+
sp.stop(`${String(releases.length)} versions found`);
|
|
44
|
+
if (releases.length === 0)
|
|
45
|
+
throw new Error("No releases available");
|
|
46
|
+
let release;
|
|
47
|
+
if (args.version) {
|
|
48
|
+
const wanted = args.version.replace(/^v/, '');
|
|
49
|
+
release = releases.find(r => r.tag === args.version || r.version === wanted);
|
|
50
|
+
if (!release)
|
|
51
|
+
throw new Error(`Version ${args.version} not found`);
|
|
52
|
+
}
|
|
53
|
+
else if (isJson()) {
|
|
54
|
+
release = releases[0];
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const chosen = await promptSelect("Select a version", releases.map((r, i) => ({
|
|
58
|
+
value: r.tag,
|
|
59
|
+
label: i === 0 ? `${r.tag} (${"latest"})` : r.tag,
|
|
60
|
+
hint: r.prerelease ? "pre-release" : undefined,
|
|
61
|
+
})));
|
|
62
|
+
release = releases.find(r => r.tag === chosen) ?? releases[0];
|
|
63
|
+
}
|
|
64
|
+
await mkdir(serverDir, { recursive: true });
|
|
65
|
+
log.step("Downloading");
|
|
66
|
+
const { size } = await downloadCore(release, join(serverDir, JAR_NAME), pct => progress(pct, JAR_NAME));
|
|
67
|
+
log.success(`Downloaded (${(size / 1024 / 1024).toFixed(1)} MB)`);
|
|
68
|
+
const sp2 = spin("Downloading start scripts...");
|
|
69
|
+
for (const s of startScripts())
|
|
70
|
+
await downloadFile(s.url, join(serverDir, s.name));
|
|
71
|
+
sp2.stop("Start scripts downloaded");
|
|
72
|
+
await setDefaultServer(serverDir);
|
|
73
|
+
log.success("Server ready!");
|
|
74
|
+
if (await promptConfirm("Start the server now?", false)) {
|
|
75
|
+
const { runStart } = await import('./start.js');
|
|
76
|
+
await runStart({ dir: serverDir });
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
outro("Server ready!");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
log.error(e.message);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { defineCommand } from 'citty';
|
|
3
|
+
import { intro, outro, log, spin, progress } from '../ui/output.js';
|
|
4
|
+
import { promptText } from '../ui/prompts.js';
|
|
5
|
+
import { resolveServerDir } from '../services/server.js';
|
|
6
|
+
import { installApprovedPlugin } from '../services/plugins.js';
|
|
7
|
+
export async function runInstall(slug) {
|
|
8
|
+
intro(`📦 ${"Install plugin"}`);
|
|
9
|
+
let name = slug?.trim();
|
|
10
|
+
if (!name) {
|
|
11
|
+
const answer = await promptText({ message: "Plugin slug? (owner.name)", placeholder: 'Owner.Plugin' });
|
|
12
|
+
name = answer?.trim();
|
|
13
|
+
}
|
|
14
|
+
if (!name) {
|
|
15
|
+
log.info("No plugin specified");
|
|
16
|
+
outro('');
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const serverPath = (await resolveServerDir()) ?? '.';
|
|
20
|
+
const pluginsDir = join(serverPath, 'plugins');
|
|
21
|
+
const sp = spin(name);
|
|
22
|
+
try {
|
|
23
|
+
const entry = await installApprovedPlugin(name, pluginsDir, (pct, f) => progress(pct, f));
|
|
24
|
+
sp.stop(`${entry.name} v${entry.version}`);
|
|
25
|
+
log.success(`Installed ${entry.name}`);
|
|
26
|
+
log.info("Restart the server to load plugins");
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
const msg = e?.message ?? '';
|
|
30
|
+
if (msg.startsWith('not-approved'))
|
|
31
|
+
sp.fail(`${name} is not approved or does not exist`);
|
|
32
|
+
else if (msg.startsWith('no-file'))
|
|
33
|
+
sp.fail(`No file for ${name}`);
|
|
34
|
+
else
|
|
35
|
+
sp.fail(`Failed to install ${name}`);
|
|
36
|
+
}
|
|
37
|
+
outro('');
|
|
38
|
+
}
|
|
39
|
+
export const installCmd = defineCommand({
|
|
40
|
+
meta: { name: 'install', description: 'Install an approved plugin by slug (owner.name)' },
|
|
41
|
+
args: { slug: { type: 'positional', description: 'Plugin slug, e.g. RedstoneCloud.CloudBridge', required: false } },
|
|
42
|
+
async run({ args }) {
|
|
43
|
+
await runInstall(args.slug);
|
|
44
|
+
},
|
|
45
|
+
});
|
package/dist/commands/logs.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { CommandDef } from 'citty';
|
|
2
|
-
export declare const logsCmd: CommandDef;
|
|
1
|
+
import type { CommandDef } from 'citty';
|
|
2
|
+
export declare const logsCmd: CommandDef;
|
package/dist/commands/logs.js
CHANGED
|
@@ -1,61 +1,60 @@
|
|
|
1
|
-
import { existsSync, readdirSync, statSync, readFileSync, watch } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { defineCommand } from 'citty';
|
|
4
|
-
import { intro, log } from '../ui/output.js';
|
|
5
|
-
import { c } from '../ui/theme.js';
|
|
6
|
-
import { resolveServerDir } from '../services/server.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.
|
|
28
|
-
.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
.replace(/\[
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
});
|
|
1
|
+
import { existsSync, readdirSync, statSync, readFileSync, watch } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { defineCommand } from 'citty';
|
|
4
|
+
import { intro, log } from '../ui/output.js';
|
|
5
|
+
import { c } from '../ui/theme.js';
|
|
6
|
+
import { resolveServerDir } from '../services/server.js';
|
|
7
|
+
export const logsCmd = defineCommand({
|
|
8
|
+
meta: { description: 'View server logs' },
|
|
9
|
+
args: {
|
|
10
|
+
lines: { type: 'string', description: 'Number of lines to show', default: '50' },
|
|
11
|
+
follow: { type: 'boolean', description: 'Follow log output', default: true },
|
|
12
|
+
},
|
|
13
|
+
async run({ args }) {
|
|
14
|
+
intro(`📋 ${"Server logs"}`);
|
|
15
|
+
const serverPath = await resolveServerDir();
|
|
16
|
+
if (!serverPath) {
|
|
17
|
+
log.error("No server detected");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const logsDir = join(serverPath, 'logs');
|
|
21
|
+
if (!existsSync(logsDir)) {
|
|
22
|
+
log.error("No log files found");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const files = readdirSync(logsDir)
|
|
26
|
+
.filter(f => f.endsWith('.log') || f === 'latest.log')
|
|
27
|
+
.map(f => ({ name: f, mtime: statSync(join(logsDir, f)).mtime.getTime() }))
|
|
28
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
29
|
+
if (files.length === 0) {
|
|
30
|
+
log.error("No log files found");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
const logPath = join(logsDir, files[0].name);
|
|
34
|
+
log.step(`Reading ${files[0].name}`);
|
|
35
|
+
const n = parseInt(args.lines) || 50;
|
|
36
|
+
const content = readFileSync(logPath, 'utf-8');
|
|
37
|
+
const colorize = (line) => line.replace(/\[ERROR\]/g, c.red('[ERROR]'))
|
|
38
|
+
.replace(/\[WARN\]/g, c.yellow('[WARN]'))
|
|
39
|
+
.replace(/\[INFO\]/g, c.blue('[INFO]'));
|
|
40
|
+
for (const line of content.split('\n').filter(Boolean).slice(-n)) {
|
|
41
|
+
process.stdout.write(colorize(line) + '\n');
|
|
42
|
+
}
|
|
43
|
+
if (args.follow) {
|
|
44
|
+
log.dim("Live mode (Ctrl+C to quit)");
|
|
45
|
+
process.on('SIGINT', () => { process.stdout.write('\n'); process.exit(0); });
|
|
46
|
+
let buf = content;
|
|
47
|
+
watch(logPath, () => {
|
|
48
|
+
try {
|
|
49
|
+
const updated = readFileSync(logPath, 'utf-8');
|
|
50
|
+
if (updated.length > buf.length) {
|
|
51
|
+
process.stdout.write(updated.slice(buf.length));
|
|
52
|
+
buf = updated;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch { }
|
|
56
|
+
});
|
|
57
|
+
await new Promise(() => { });
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
});
|
package/dist/commands/menu.js
CHANGED
|
@@ -1,86 +1,94 @@
|
|
|
1
|
-
import { intro, outro, log } from '../ui/output.js';
|
|
2
|
-
import { promptSelect } from '../ui/prompts.js';
|
|
3
|
-
import {
|
|
4
|
-
import { loadPid, isAlive } from '../services/process.js';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (
|
|
21
|
-
|
|
22
|
-
if (hasServer
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
options.push({ value: '
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
1
|
+
import { intro, outro, log } from '../ui/output.js';
|
|
2
|
+
import { promptSelect, promptText } from '../ui/prompts.js';
|
|
3
|
+
import { resolveServerDir } from '../services/server.js';
|
|
4
|
+
import { loadPid, isAlive } from '../services/process.js';
|
|
5
|
+
import { c } from '../ui/theme.js';
|
|
6
|
+
export async function runMenu() {
|
|
7
|
+
while (true) {
|
|
8
|
+
const done = await menuStep();
|
|
9
|
+
if (done)
|
|
10
|
+
return;
|
|
11
|
+
await promptText({ message: "Press enter to return to the menu", placeholder: '' });
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function menuStep() {
|
|
15
|
+
const serverPath = await resolveServerDir();
|
|
16
|
+
const hasServer = serverPath !== null;
|
|
17
|
+
const pid = await loadPid();
|
|
18
|
+
const running = pid !== null && isAlive(pid.pid);
|
|
19
|
+
intro(c.green(`⚡ ${"PowerNukkitX Menu"}`));
|
|
20
|
+
if (running)
|
|
21
|
+
log.info(`Server running (PID ${String(pid.pid)})`);
|
|
22
|
+
else if (hasServer)
|
|
23
|
+
log.info("Server stopped");
|
|
24
|
+
else
|
|
25
|
+
log.warn("No server detected");
|
|
26
|
+
const options = [];
|
|
27
|
+
if (!hasServer)
|
|
28
|
+
options.push({ value: 'create', label: "Create a server" });
|
|
29
|
+
if (hasServer && !running)
|
|
30
|
+
options.push({ value: 'start', label: "Start the server" });
|
|
31
|
+
if (running)
|
|
32
|
+
options.push({ value: 'stop', label: "Stop the server" });
|
|
33
|
+
if (hasServer) {
|
|
34
|
+
options.push({ value: 'plugins', label: "Manage plugins" });
|
|
35
|
+
options.push({ value: 'install', label: "Install a plugin" });
|
|
36
|
+
options.push({ value: 'update', label: "Update the core" });
|
|
37
|
+
options.push({ value: 'backup', label: "Backup" });
|
|
38
|
+
}
|
|
39
|
+
options.push({ value: 'doctor', label: "Diagnostics" });
|
|
40
|
+
options.push({ value: 'info', label: "Information" });
|
|
41
|
+
options.push({ value: 'quit', label: "Quit" });
|
|
42
|
+
const choice = await promptSelect("What do you want to do?", options);
|
|
43
|
+
switch (choice) {
|
|
44
|
+
case 'create': {
|
|
45
|
+
const { initCmd } = await import('./init.js');
|
|
46
|
+
await initCmd.run({ args: {} });
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case 'start': {
|
|
50
|
+
const { runStart } = await import('./start.js');
|
|
51
|
+
await runStart({});
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case 'stop': {
|
|
55
|
+
const { runStop } = await import('./stop.js');
|
|
56
|
+
await runStop();
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case 'plugins': {
|
|
60
|
+
const { installCmd } = await import('./plugin/install.js');
|
|
61
|
+
await installCmd.run({ args: {} });
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
case 'install': {
|
|
65
|
+
const { runInstall } = await import('./install.js');
|
|
66
|
+
await runInstall();
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case 'update': {
|
|
70
|
+
const { runUpdate } = await import('./update.js');
|
|
71
|
+
await runUpdate();
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case 'backup': {
|
|
75
|
+
const { runBackup } = await import('./backup.js');
|
|
76
|
+
await runBackup();
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case 'doctor': {
|
|
80
|
+
const { doctorCmd } = await import('./doctor.js');
|
|
81
|
+
await doctorCmd.run({ args: {} });
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case 'info': {
|
|
85
|
+
const { infoCmd } = await import('./info.js');
|
|
86
|
+
await infoCmd.run({ args: {} });
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
case 'quit':
|
|
90
|
+
outro("See you soon!");
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { CommandDef } from 'citty';
|
|
2
|
-
export declare const pluginCmd: CommandDef;
|
|
1
|
+
import type { CommandDef } from 'citty';
|
|
2
|
+
export declare const pluginCmd: CommandDef;
|