@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.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +186 -203
  3. package/dist/cli.js +34 -46
  4. package/dist/commands/backup.d.ts +2 -2
  5. package/dist/commands/backup.js +23 -24
  6. package/dist/commands/config.d.ts +1 -1
  7. package/dist/commands/config.js +60 -61
  8. package/dist/commands/console.d.ts +2 -2
  9. package/dist/commands/console.js +98 -99
  10. package/dist/commands/doctor.d.ts +2 -2
  11. package/dist/commands/doctor.js +97 -98
  12. package/dist/commands/info.d.ts +2 -2
  13. package/dist/commands/info.js +41 -42
  14. package/dist/commands/init.d.ts +2 -2
  15. package/dist/commands/init.js +87 -66
  16. package/dist/commands/install.js +45 -0
  17. package/dist/commands/logs.d.ts +2 -2
  18. package/dist/commands/logs.js +60 -61
  19. package/dist/commands/menu.js +94 -86
  20. package/dist/commands/plugin/index.d.ts +2 -2
  21. package/dist/commands/plugin/index.js +13 -13
  22. package/dist/commands/plugin/info.d.ts +2 -2
  23. package/dist/commands/plugin/info.js +39 -40
  24. package/dist/commands/plugin/install.d.ts +2 -2
  25. package/dist/commands/plugin/install.js +56 -57
  26. package/dist/commands/plugin/installed.d.ts +2 -2
  27. package/dist/commands/plugin/installed.js +41 -42
  28. package/dist/commands/plugin/list.d.ts +2 -2
  29. package/dist/commands/plugin/list.js +47 -49
  30. package/dist/commands/plugin/remove.d.ts +2 -2
  31. package/dist/commands/plugin/remove.js +44 -45
  32. package/dist/commands/plugin/search.d.ts +2 -2
  33. package/dist/commands/plugin/search.js +11 -12
  34. package/dist/commands/plugin/update.d.ts +2 -2
  35. package/dist/commands/plugin/update.js +52 -53
  36. package/dist/commands/start.d.ts +2 -2
  37. package/dist/commands/start.js +74 -75
  38. package/dist/commands/stop.d.ts +2 -2
  39. package/dist/commands/stop.js +26 -27
  40. package/dist/commands/update.d.ts +2 -2
  41. package/dist/commands/update.js +34 -35
  42. package/dist/commands/use.d.ts +2 -2
  43. package/dist/commands/use.js +39 -40
  44. package/dist/infra/http.js +119 -121
  45. package/dist/infra/paths.js +15 -20
  46. package/dist/infra/store.js +24 -27
  47. package/dist/services/backup.js +34 -40
  48. package/dist/services/plugins.js +139 -111
  49. package/dist/services/process.js +41 -43
  50. package/dist/services/release.js +51 -38
  51. package/dist/services/server.js +81 -89
  52. package/dist/ui/output.js +67 -71
  53. package/dist/ui/prompts.js +26 -30
  54. package/dist/ui/theme.js +16 -18
  55. package/package.json +44 -46
  56. package/dist/bundle.js +0 -18
  57. package/dist/commands/cfg.d.ts +0 -2
  58. package/dist/commands/cfg.js +0 -61
  59. package/dist/commands/lang.d.ts +0 -2
  60. package/dist/commands/lang.js +0 -28
  61. package/dist/commands/plugin.d.ts +0 -1
  62. package/dist/commands/plugin.js +0 -1
  63. package/dist/core/config.d.ts +0 -13
  64. package/dist/core/config.js +0 -31
  65. package/dist/core/network.d.ts +0 -13
  66. package/dist/core/network.js +0 -139
  67. package/dist/core/output.d.ts +0 -33
  68. package/dist/core/output.js +0 -75
  69. package/dist/core/process.d.ts +0 -10
  70. package/dist/core/process.js +0 -53
  71. package/dist/i18n/en.json +0 -174
  72. package/dist/i18n/fr.json +0 -174
  73. package/dist/i18n/index.js +0 -58
  74. package/dist/index.d.ts +0 -1
  75. package/dist/index.js +0 -1
  76. package/dist/lang/en.json +0 -146
  77. package/dist/lang/fr.json +0 -146
  78. package/dist/lang/index.d.ts +0 -7
  79. package/dist/lang/index.js +0 -83
  80. package/dist/main.d.ts +0 -2
  81. package/dist/main.js +0 -28
  82. package/dist/plugins.json +0 -66
  83. package/dist/types.d.ts +0 -61
  84. package/dist/types.js +0 -1
  85. package/dist/utils/api.d.ts +0 -9
  86. package/dist/utils/api.js +0 -24
  87. package/dist/utils/github.d.ts +0 -20
  88. package/dist/utils/github.js +0 -60
  89. package/dist/utils/logger.d.ts +0 -15
  90. package/dist/utils/logger.js +0 -72
  91. package/dist/utils/pause.d.ts +0 -1
  92. package/dist/utils/pause.js +0 -6
  93. package/dist/utils/plugins.d.ts +0 -4
  94. package/dist/utils/plugins.js +0 -34
  95. package/dist/utils/server.d.ts +0 -3
  96. package/dist/utils/server.js +0 -32
  97. package/dist/utils/updater.d.ts +0 -1
  98. package/dist/utils/updater.js +0 -86
@@ -1,53 +1,52 @@
1
- import { existsSync } from 'node:fs';
2
- import { readdir } from 'node:fs/promises';
3
- import { join } from 'node:path';
4
- import { defineCommand } from 'citty';
5
- import { intro, outro, log, spin, progress } from '../../ui/output.js';
6
- import { promptMulti } from '../../ui/prompts.js';
7
- import { resolveServerDir } from '../../services/server.js';
8
- import { getInstalled, updatePlugin } from '../../services/plugins.js';
9
- import { t } from '../../i18n/index.js';
10
- export const updateCmd = defineCommand({
11
- meta: { description: 'Update installed plugins' },
12
- args: { names: { type: 'positional', description: 'Plugin slugs', required: false } },
13
- async run({ args }) {
14
- const serverPath = (await resolveServerDir()) ?? '.';
15
- const pluginsDir = join(serverPath, 'plugins');
16
- if (!existsSync(pluginsDir)) {
17
- log.error(t('plugin.noPluginsDir'));
18
- return;
19
- }
20
- const jars = (await readdir(pluginsDir)).filter(f => f.endsWith('.jar'));
21
- let names = args.names ? [args.names] : [];
22
- if (names.length === 0) {
23
- names = await promptMulti(t('plugin.selectUpdate'), jars.map(j => ({ value: j.replace('.jar', ''), label: j.replace('.jar', '') })));
24
- }
25
- intro(`🔄 ${t('plugin.titleUpdate')}`);
26
- const tracked = await getInstalled();
27
- for (const slug of names) {
28
- const sp = spin(slug);
29
- try {
30
- const meta = tracked.find(p => p.slug === slug);
31
- const existingJar = jars.find(j => j.toLowerCase().startsWith(slug.toLowerCase()));
32
- const entry = await updatePlugin(slug, pluginsDir, meta?.version, existingJar, (pct, f) => progress(pct, f));
33
- if (!entry) {
34
- sp.stop(t('plugin.alreadyLatest', slug, meta?.version ?? '?'));
35
- continue;
36
- }
37
- sp.stop(`${entry.name} v${entry.version}`);
38
- log.success(t('plugin.updated', entry.name, entry.version));
39
- }
40
- catch (e) {
41
- const msg = e.message;
42
- if (msg.startsWith('no-release'))
43
- sp.fail(t('plugin.noRelease', slug));
44
- else if (msg.startsWith('no-file'))
45
- sp.fail(t('plugin.noFile', slug));
46
- else
47
- sp.fail(t('plugin.installError', slug));
48
- }
49
- }
50
- log.info(t('plugin.restartHint'));
51
- outro('');
52
- },
53
- });
1
+ import { existsSync } from 'node:fs';
2
+ import { readdir } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { defineCommand } from 'citty';
5
+ import { intro, outro, log, spin, progress } from '../../ui/output.js';
6
+ import { promptMulti } from '../../ui/prompts.js';
7
+ import { resolveServerDir } from '../../services/server.js';
8
+ import { getInstalled, updatePlugin } from '../../services/plugins.js';
9
+ export const updateCmd = defineCommand({
10
+ meta: { description: 'Update installed plugins' },
11
+ args: { names: { type: 'positional', description: 'Plugin slugs', required: false } },
12
+ async run({ args }) {
13
+ const serverPath = (await resolveServerDir()) ?? '.';
14
+ const pluginsDir = join(serverPath, 'plugins');
15
+ if (!existsSync(pluginsDir)) {
16
+ log.error("No plugins/ directory");
17
+ return;
18
+ }
19
+ const jars = (await readdir(pluginsDir)).filter(f => f.endsWith('.jar'));
20
+ let names = args.names ? [args.names] : [];
21
+ if (names.length === 0) {
22
+ names = await promptMulti("Select plugins to update:", jars.map(j => ({ value: j.replace('.jar', ''), label: j.replace('.jar', '') })));
23
+ }
24
+ intro(`🔄 ${"Update plugins"}`);
25
+ const tracked = await getInstalled();
26
+ for (const slug of names) {
27
+ const sp = spin(slug);
28
+ try {
29
+ const meta = tracked.find(p => p.slug === slug);
30
+ const existingJar = jars.find(j => j.toLowerCase().startsWith(slug.toLowerCase()));
31
+ const entry = await updatePlugin(slug, pluginsDir, meta?.version, existingJar, (pct, f) => progress(pct, f));
32
+ if (!entry) {
33
+ sp.stop(`${slug} is already up to date (v${meta?.version ?? '?'})`);
34
+ continue;
35
+ }
36
+ sp.stop(`${entry.name} v${entry.version}`);
37
+ log.success(`${entry.name} updated to v${entry.version}`);
38
+ }
39
+ catch (e) {
40
+ const msg = e.message;
41
+ if (msg.startsWith('no-release'))
42
+ sp.fail(`No release available for ${slug}`);
43
+ else if (msg.startsWith('no-file'))
44
+ sp.fail(`No file for ${slug}`);
45
+ else
46
+ sp.fail(`Error installing ${slug}`);
47
+ }
48
+ }
49
+ log.info("Restart the server to load plugins");
50
+ outro('');
51
+ },
52
+ });
@@ -1,2 +1,2 @@
1
- import type { CommandDef } from 'citty';
2
- export declare const startCmd: CommandDef;
1
+ import type { CommandDef } from 'citty';
2
+ export declare const startCmd: CommandDef;
@@ -1,75 +1,74 @@
1
- import { existsSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import { cwd } from 'node:process';
4
- import { spawn } from 'node:child_process';
5
- import { defineCommand } from 'citty';
6
- import { intro, outro, log, spin } from '../ui/output.js';
7
- import { promptConfirm } from '../ui/prompts.js';
8
- import { resolveServerDir, checkJava, findJava, buildLaunchArgs, javaEnv } from '../services/server.js';
9
- import { savePid } from '../services/process.js';
10
- import { JAR_NAME } from '../infra/paths.js';
11
- import { t } from '../i18n/index.js';
12
- export async function runStart(opts) {
13
- const serverPath = opts.dir
14
- ? (opts.dir.includes(':') || opts.dir.startsWith('/') ? opts.dir : join(cwd(), opts.dir))
15
- : (await resolveServerDir()) ?? cwd();
16
- if (!existsSync(join(serverPath, JAR_NAME))) {
17
- log.warn(t('start.notFound'));
18
- if (!(await promptConfirm(t('start.createPrompt'), true)))
19
- process.exit(0);
20
- const { initCmd } = await import('./init.js');
21
- await initCmd.run({ args: { dir: serverPath } });
22
- return;
23
- }
24
- intro(`🚀 ${t('start.title')}`);
25
- const sp = spin(t('start.checkingJava'));
26
- const java = await checkJava();
27
- if (!java.ok) {
28
- sp.fail(t('start.javaNotFound'));
29
- process.exit(1);
30
- }
31
- sp.stop(t('start.javaOk', String(java.version)));
32
- const mem = opts.memory ?? '2G';
33
- const cmdArgs = buildLaunchArgs(mem);
34
- const javaExe = findJava();
35
- if (opts.dryRun) {
36
- log.info(`${javaExe} ${cmdArgs.join(' ')}`);
37
- outro(t('start.generated'));
38
- return;
39
- }
40
- log.step(`${t('start.starting')} (memory: ${mem})`);
41
- const run = () => {
42
- const child = spawn(javaExe, cmdArgs, { stdio: 'inherit', env: javaEnv(), cwd: serverPath });
43
- if (child.pid)
44
- savePid(child.pid, serverPath);
45
- log.success(t('start.running', String(child.pid)));
46
- child.on('exit', code => {
47
- if (code !== 0 && opts.restart) {
48
- log.warn(t('start.restarting'));
49
- run();
50
- }
51
- else {
52
- log.info(t('start.stopped', String(code ?? '?')));
53
- process.exit(code ?? 0);
54
- }
55
- });
56
- };
57
- run();
58
- }
59
- export const startCmd = defineCommand({
60
- meta: { description: 'Start the PowerNukkitX server' },
61
- args: {
62
- dir: { type: 'string', description: 'Server directory' },
63
- memory: { type: 'string', description: 'Memory (e.g. 2G)', default: '2G' },
64
- restart: { type: 'boolean', description: 'Auto-restart on crash', default: false },
65
- 'dry-run': { type: 'boolean', description: 'Print command without running', default: false },
66
- },
67
- async run({ args }) {
68
- await runStart({
69
- dir: args.dir,
70
- memory: args.memory,
71
- restart: args.restart,
72
- dryRun: args['dry-run'],
73
- });
74
- },
75
- });
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { cwd } from 'node:process';
4
+ import { spawn } from 'node:child_process';
5
+ import { defineCommand } from 'citty';
6
+ import { intro, outro, log, spin } from '../ui/output.js';
7
+ import { promptConfirm } from '../ui/prompts.js';
8
+ import { resolveServerDir, checkJava, findJava, buildLaunchArgs, javaEnv } from '../services/server.js';
9
+ import { savePid } from '../services/process.js';
10
+ import { JAR_NAME } from '../infra/paths.js';
11
+ export async function runStart(opts) {
12
+ const serverPath = opts.dir
13
+ ? (opts.dir.includes(':') || opts.dir.startsWith('/') ? opts.dir : join(cwd(), opts.dir))
14
+ : (await resolveServerDir()) ?? cwd();
15
+ if (!existsSync(join(serverPath, JAR_NAME))) {
16
+ log.warn("No server found here");
17
+ if (!(await promptConfirm("Create a server now?", true)))
18
+ process.exit(0);
19
+ const { initCmd } = await import('./init.js');
20
+ await initCmd.run({ args: { dir: serverPath } });
21
+ return;
22
+ }
23
+ intro(`🚀 ${"Start server"}`);
24
+ const sp = spin("Checking Java...");
25
+ const java = await checkJava();
26
+ if (!java.ok) {
27
+ sp.fail("Java 21+ required — https://adoptium.net/");
28
+ process.exit(1);
29
+ }
30
+ sp.stop(`Java ${String(java.version)} detected`);
31
+ const mem = opts.memory ?? '2G';
32
+ const cmdArgs = buildLaunchArgs(mem);
33
+ const javaExe = findJava();
34
+ if (opts.dryRun) {
35
+ log.info(`${javaExe} ${cmdArgs.join(' ')}`);
36
+ outro("Command generated");
37
+ return;
38
+ }
39
+ log.step(`${"Starting..."} (memory: ${mem})`);
40
+ const run = () => {
41
+ const child = spawn(javaExe, cmdArgs, { stdio: 'inherit', env: javaEnv(), cwd: serverPath });
42
+ if (child.pid)
43
+ savePid(child.pid, serverPath);
44
+ log.success(`Server running (PID ${String(child.pid)})`);
45
+ child.on('exit', code => {
46
+ if (code !== 0 && opts.restart) {
47
+ log.warn("Restarting...");
48
+ run();
49
+ }
50
+ else {
51
+ log.info(`Server stopped (code ${String(code ?? '?')})`);
52
+ process.exit(code ?? 0);
53
+ }
54
+ });
55
+ };
56
+ run();
57
+ }
58
+ export const startCmd = defineCommand({
59
+ meta: { description: 'Start the PowerNukkitX server' },
60
+ args: {
61
+ dir: { type: 'string', description: 'Server directory' },
62
+ memory: { type: 'string', description: 'Memory (e.g. 2G)', default: '2G' },
63
+ restart: { type: 'boolean', description: 'Auto-restart on crash', default: false },
64
+ 'dry-run': { type: 'boolean', description: 'Print command without running', default: false },
65
+ },
66
+ async run({ args }) {
67
+ await runStart({
68
+ dir: args.dir,
69
+ memory: args.memory,
70
+ restart: args.restart,
71
+ dryRun: args['dry-run'],
72
+ });
73
+ },
74
+ });
@@ -1,2 +1,2 @@
1
- import type { CommandDef } from 'citty';
2
- export declare const stopCmd: CommandDef;
1
+ import type { CommandDef } from 'citty';
2
+ export declare const stopCmd: CommandDef;
@@ -1,27 +1,26 @@
1
- import { defineCommand } from 'citty';
2
- import { intro, outro, log, spin } from '../ui/output.js';
3
- import { loadPid, clearPid, killProcess, isAlive } from '../services/process.js';
4
- import { t } from '../i18n/index.js';
5
- export async function runStop() {
6
- intro(`⏹ ${t('stop.title')}`);
7
- const pid = await loadPid();
8
- if (!pid || !isAlive(pid.pid)) {
9
- log.warn(t('stop.notRunning'));
10
- await clearPid();
11
- return;
12
- }
13
- const sp = spin(t('stop.killing', String(pid.pid)));
14
- const ok = await killProcess(pid.pid);
15
- await clearPid();
16
- if (ok) {
17
- sp.stop(t('stop.done'));
18
- outro(t('stop.done'));
19
- }
20
- else
21
- sp.fail(t('stop.failed'));
22
- }
23
- export const stopCmd = defineCommand({
24
- meta: { description: 'Stop the running PowerNukkitX server' },
25
- args: {},
26
- run: () => runStop(),
27
- });
1
+ import { defineCommand } from 'citty';
2
+ import { intro, outro, log, spin } from '../ui/output.js';
3
+ import { loadPid, clearPid, killProcess, isAlive } from '../services/process.js';
4
+ export async function runStop() {
5
+ intro(`⏹ ${"Stop server"}`);
6
+ const pid = await loadPid();
7
+ if (!pid || !isAlive(pid.pid)) {
8
+ log.warn("No server running");
9
+ await clearPid();
10
+ return;
11
+ }
12
+ const sp = spin(`Stopping server (PID ${String(pid.pid)})...`);
13
+ const ok = await killProcess(pid.pid);
14
+ await clearPid();
15
+ if (ok) {
16
+ sp.stop("Server stopped");
17
+ outro("Server stopped");
18
+ }
19
+ else
20
+ sp.fail("Failed to stop");
21
+ }
22
+ export const stopCmd = defineCommand({
23
+ meta: { description: 'Stop the running PowerNukkitX server' },
24
+ args: {},
25
+ run: () => runStop(),
26
+ });
@@ -1,2 +1,2 @@
1
- import type { CommandDef } from 'citty';
2
- export declare const updateCmd: CommandDef;
1
+ import type { CommandDef } from 'citty';
2
+ export declare const updateCmd: CommandDef;
@@ -1,35 +1,34 @@
1
- import { rename } from 'node:fs/promises';
2
- import { join } from 'node:path';
3
- import { defineCommand } from 'citty';
4
- import { intro, outro, log, spin, progress } from '../ui/output.js';
5
- import { resolveServerDir } from '../services/server.js';
6
- import { getLatestRelease, downloadCore } from '../services/release.js';
7
- import { JAR_NAME } from '../infra/paths.js';
8
- import { t } from '../i18n/index.js';
9
- export async function runUpdate(force = false) {
10
- intro(`🔄 ${t('update.title')}`);
11
- const serverPath = await resolveServerDir();
12
- if (!serverPath) {
13
- log.error(t('update.notFound'));
14
- process.exit(1);
15
- }
16
- const sp = spin(t('update.checking'));
17
- const release = await getLatestRelease(force);
18
- sp.stop(t('update.available', release.tag));
19
- const jarPath = join(serverPath, JAR_NAME);
20
- log.step(t('update.saving'));
21
- await rename(jarPath, `${jarPath}.old`).catch(() => { });
22
- log.step(t('update.downloading'));
23
- await downloadCore(release, jarPath, pct => progress(pct, JAR_NAME));
24
- log.success(t('update.done'));
25
- log.info(t('update.restart'));
26
- outro(t('update.done'));
27
- }
28
- export const updateCmd = defineCommand({
29
- meta: { description: 'Update PowerNukkitX to the latest version' },
30
- args: {
31
- force: { type: 'boolean', description: 'Force update', default: false },
32
- dev: { type: 'boolean', description: 'Dev version', default: false },
33
- },
34
- run: ({ args }) => runUpdate(args.force),
35
- });
1
+ import { rename } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { defineCommand } from 'citty';
4
+ import { intro, outro, log, spin, progress } from '../ui/output.js';
5
+ import { resolveServerDir } from '../services/server.js';
6
+ import { getLatestRelease, downloadCore } from '../services/release.js';
7
+ import { JAR_NAME } from '../infra/paths.js';
8
+ export async function runUpdate(force = false) {
9
+ intro(`🔄 ${"Update PowerNukkitX"}`);
10
+ const serverPath = await resolveServerDir();
11
+ if (!serverPath) {
12
+ log.error("No server found");
13
+ process.exit(1);
14
+ }
15
+ const sp = spin("Checking for updates...");
16
+ const release = await getLatestRelease(force);
17
+ sp.stop(`New version available: ${release.tag}`);
18
+ const jarPath = join(serverPath, JAR_NAME);
19
+ log.step("Backing up old version...");
20
+ await rename(jarPath, `${jarPath}.old`).catch(() => { });
21
+ log.step("Downloading...");
22
+ await downloadCore(release, jarPath, pct => progress(pct, JAR_NAME));
23
+ log.success("Update complete!");
24
+ log.info("Restart the server to apply changes");
25
+ outro("Update complete!");
26
+ }
27
+ export const updateCmd = defineCommand({
28
+ meta: { description: 'Update PowerNukkitX to the latest version' },
29
+ args: {
30
+ force: { type: 'boolean', description: 'Force update', default: false },
31
+ dev: { type: 'boolean', description: 'Dev version', default: false },
32
+ },
33
+ run: ({ args }) => runUpdate(args.force),
34
+ });
@@ -1,2 +1,2 @@
1
- import type { CommandDef } from 'citty';
2
- export declare const useCmd: CommandDef;
1
+ import type { CommandDef } from 'citty';
2
+ export declare const useCmd: CommandDef;
@@ -1,40 +1,39 @@
1
- import { existsSync } from 'node:fs';
2
- import { join, resolve } from 'node:path';
3
- import { cwd } from 'node:process';
4
- import { defineCommand } from 'citty';
5
- import { intro, outro, log } from '../ui/output.js';
6
- import { promptSelect, promptText } from '../ui/prompts.js';
7
- import { detectServers, setDefaultServer } from '../services/server.js';
8
- import { JAR_NAME } from '../infra/paths.js';
9
- import { t } from '../i18n/index.js';
10
- export const useCmd = defineCommand({
11
- meta: { description: 'Set the default PowerNukkitX server directory' },
12
- args: {
13
- dir: { type: 'positional', description: 'Server path', required: false },
14
- clear: { type: 'boolean', description: 'Remove default server', default: false },
15
- },
16
- async run({ args }) {
17
- intro(`📌 ${t('use.title')}`);
18
- if (args.clear) {
19
- await setDefaultServer(null);
20
- log.success(t('use.cleared'));
21
- outro(t('use.cleared'));
22
- return;
23
- }
24
- let target = args.dir;
25
- if (!target) {
26
- const servers = detectServers();
27
- target = servers.length > 0
28
- ? await promptSelect(t('use.prompt'), servers.map(s => ({ value: s, label: s })))
29
- : await promptText({ message: t('use.pathPrompt'), defaultValue: cwd() });
30
- }
31
- const absPath = resolve(cwd(), target);
32
- if (!existsSync(join(absPath, JAR_NAME))) {
33
- log.error(t('use.notFound', absPath));
34
- process.exit(1);
35
- }
36
- await setDefaultServer(absPath);
37
- log.success(t('use.set', absPath));
38
- outro(t('use.set', absPath));
39
- },
40
- });
1
+ import { existsSync } from 'node:fs';
2
+ import { join, resolve } from 'node:path';
3
+ import { cwd } from 'node:process';
4
+ import { defineCommand } from 'citty';
5
+ import { intro, outro, log } from '../ui/output.js';
6
+ import { promptSelect, promptText } from '../ui/prompts.js';
7
+ import { detectServers, setDefaultServer } from '../services/server.js';
8
+ import { JAR_NAME } from '../infra/paths.js';
9
+ export const useCmd = defineCommand({
10
+ meta: { description: 'Set the default PowerNukkitX server directory' },
11
+ args: {
12
+ dir: { type: 'positional', description: 'Server path', required: false },
13
+ clear: { type: 'boolean', description: 'Remove default server', default: false },
14
+ },
15
+ async run({ args }) {
16
+ intro(`📌 ${"Default server"}`);
17
+ if (args.clear) {
18
+ await setDefaultServer(null);
19
+ log.success("Default server cleared");
20
+ outro("Default server cleared");
21
+ return;
22
+ }
23
+ let target = args.dir;
24
+ if (!target) {
25
+ const servers = detectServers();
26
+ target = servers.length > 0
27
+ ? await promptSelect("Select a server:", servers.map(s => ({ value: s, label: s })))
28
+ : await promptText({ message: "Server path:", defaultValue: cwd() });
29
+ }
30
+ const absPath = resolve(cwd(), target);
31
+ if (!existsSync(join(absPath, JAR_NAME))) {
32
+ log.error(`powernukkitx.jar not found in: ${absPath}`);
33
+ process.exit(1);
34
+ }
35
+ await setDefaultServer(absPath);
36
+ log.success(`Default server set: ${absPath}`);
37
+ outro(`Default server set: ${absPath}`);
38
+ },
39
+ });