@powernukkitx/cli 0.0.3 → 1.0.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/LICENSE +21 -0
- package/README.md +110 -101
- package/dist/cli.js +34 -0
- package/dist/commands/backup.d.ts +2 -1
- package/dist/commands/backup.js +23 -74
- package/dist/commands/config.d.ts +1 -1
- package/dist/commands/config.js +60 -114
- package/dist/commands/console.d.ts +2 -0
- package/dist/commands/console.js +98 -0
- package/dist/commands/doctor.d.ts +2 -1
- package/dist/commands/doctor.js +97 -119
- package/dist/commands/info.d.ts +2 -1
- package/dist/commands/info.js +41 -36
- package/dist/commands/init.d.ts +2 -4
- package/dist/commands/init.js +87 -73
- package/dist/commands/install.js +45 -0
- package/dist/commands/logs.d.ts +2 -0
- package/dist/commands/logs.js +60 -0
- package/dist/commands/menu.js +94 -0
- package/dist/commands/plugin/index.d.ts +2 -0
- package/dist/commands/plugin/index.js +13 -0
- package/dist/commands/plugin/info.d.ts +2 -0
- package/dist/commands/plugin/info.js +39 -0
- package/dist/commands/plugin/install.d.ts +2 -0
- package/dist/commands/plugin/install.js +56 -0
- package/dist/commands/plugin/installed.d.ts +2 -0
- package/dist/commands/plugin/installed.js +41 -0
- package/dist/commands/plugin/list.d.ts +2 -0
- package/dist/commands/plugin/list.js +47 -0
- package/dist/commands/plugin/remove.d.ts +2 -0
- package/dist/commands/plugin/remove.js +44 -0
- package/dist/commands/plugin/search.d.ts +2 -0
- package/dist/commands/plugin/search.js +11 -0
- package/dist/commands/plugin/update.d.ts +2 -0
- package/dist/commands/plugin/update.js +52 -0
- package/dist/commands/start.d.ts +2 -7
- package/dist/commands/start.js +74 -108
- package/dist/commands/stop.d.ts +2 -0
- package/dist/commands/stop.js +26 -0
- package/dist/commands/update.d.ts +2 -5
- package/dist/commands/update.js +34 -55
- package/dist/commands/use.d.ts +2 -0
- package/dist/commands/use.js +39 -0
- package/dist/infra/http.js +119 -0
- package/dist/infra/paths.js +15 -0
- package/dist/infra/store.js +24 -0
- package/dist/services/backup.js +34 -0
- package/dist/services/plugins.js +139 -0
- package/dist/services/process.js +41 -0
- package/dist/services/release.js +51 -0
- package/dist/services/server.js +81 -0
- package/dist/ui/output.js +67 -0
- package/dist/ui/prompts.js +26 -0
- package/dist/ui/theme.js +16 -0
- package/package.json +44 -63
- package/dist/bundle.js +0 -18871
- package/dist/commands/plugin.d.ts +0 -12
- package/dist/commands/plugin.js +0 -385
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -260
- package/dist/lang/en.json +0 -178
- package/dist/lang/fr.json +0 -178
- package/dist/lang/index.d.ts +0 -7
- package/dist/lang/index.js +0 -83
- 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 -18
- package/dist/utils/api.js +0 -74
- package/dist/utils/github.d.ts +0 -27
- package/dist/utils/github.js +0 -187
- 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 -39
- package/dist/utils/updater.d.ts +0 -1
- package/dist/utils/updater.js +0 -86
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AzaleeX
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,177 +1,186 @@
|
|
|
1
1
|
# pnx-cli
|
|
2
2
|
|
|
3
|
-
PowerNukkitX CLI
|
|
3
|
+
**PowerNukkitX CLI** - command line tool to manage a **Minecraft Bedrock** server powered by [PowerNukkitX](https://github.com/PowerNukkitX/PowerNukkitX).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Create, start, update and diagnose your server, manage plugins from the marketplace, all with a clean interface and an interactive menu.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Requirements](#requirements)
|
|
11
|
+
- [Quick start](#quick-start)
|
|
12
|
+
- [Commands](#commands)
|
|
13
|
+
- [Interactive mode](#interactive-mode)
|
|
14
|
+
- [Global options](#global-options)
|
|
15
|
+
- [Architecture](#architecture)
|
|
16
|
+
- [Development](#development)
|
|
17
|
+
- [Links](#links)
|
|
18
|
+
- [License](#license)
|
|
6
19
|
|
|
7
20
|
## Installation
|
|
8
21
|
|
|
9
22
|
```bash
|
|
10
|
-
npm install -g
|
|
23
|
+
npm install -g @powernukkitx/cli
|
|
11
24
|
```
|
|
12
25
|
|
|
13
|
-
|
|
26
|
+
The `pnx` command becomes available.
|
|
14
27
|
|
|
15
|
-
##
|
|
28
|
+
## Requirements
|
|
16
29
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
30
|
+
- **Node.js 20.12+**
|
|
31
|
+
- **Java 21+** to run the server ([Adoptium Temurin](https://adoptium.net/) recommended)
|
|
19
32
|
|
|
20
|
-
##
|
|
21
|
-
|
|
22
|
-
Lancer le menu interactif :
|
|
33
|
+
## Quick start
|
|
23
34
|
|
|
24
35
|
```bash
|
|
36
|
+
# Contextual interactive menu
|
|
25
37
|
pnx
|
|
26
|
-
```
|
|
27
38
|
|
|
28
|
-
|
|
39
|
+
# Create a server then start it
|
|
40
|
+
pnx init --dir ./pnx-server
|
|
41
|
+
pnx start --memory 4G
|
|
29
42
|
|
|
30
|
-
|
|
43
|
+
# Help
|
|
31
44
|
pnx --help
|
|
45
|
+
pnx <command> --help
|
|
32
46
|
```
|
|
33
47
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
pnx --lang fr
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Fonctionnalités
|
|
41
|
-
|
|
42
|
-
- Initialiser un nouveau serveur PowerNukkitX
|
|
43
|
-
- Démarrer le serveur avec options de mémoire et redémarrage automatique
|
|
44
|
-
- Installer, lister, rechercher, mettre à jour et supprimer des plugins
|
|
45
|
-
- Vérifier l’état du serveur avec un diagnostic intégré
|
|
46
|
-
- Créer des sauvegardes du serveur
|
|
47
|
-
- Consulter la configuration et les informations du serveur
|
|
48
|
-
- Mettre à jour `powernukkitx.jar`
|
|
49
|
-
- Utiliser l’interface en anglais ou en français
|
|
48
|
+
## Commands
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
### `init` - create a server
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
Downloads the latest `powernukkitx.jar` and the start scripts.
|
|
54
53
|
|
|
55
54
|
```bash
|
|
56
55
|
pnx init --dir ./pnx-server
|
|
57
56
|
```
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
| Option | Description |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `--dir <path>` | Target directory (prompted otherwise) |
|
|
61
|
+
| `--dev` | Development build |
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
- `--dev` : installer la version de développement
|
|
63
|
+
### `start` - start the server
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
Checks Java, builds optimized JVM arguments (generational ZGC, UTF-8) and launches the server.
|
|
65
66
|
|
|
66
67
|
```bash
|
|
67
68
|
pnx start --memory 4G --restart
|
|
68
69
|
```
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
| Option | Description |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `--dir <path>` | Server directory |
|
|
74
|
+
| `--memory <size>` | Allocated memory, e.g. `2G`, `4G` (default `2G`) |
|
|
75
|
+
| `--restart` | Auto restart on crash |
|
|
76
|
+
| `--dry-run` | Print the command without running it |
|
|
71
77
|
|
|
72
|
-
|
|
73
|
-
- `-r, --restart` : redémarrer automatiquement en cas de crash
|
|
74
|
-
- `-m, --memory <size>` : mémoire allouée, par exemple `2G` ou `4G`
|
|
75
|
-
- `-i, --interactive` : mode interactif avec prompts
|
|
78
|
+
### `stop` - stop the server
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
Stops the server started through its stored PID.
|
|
78
81
|
|
|
79
82
|
```bash
|
|
80
|
-
pnx
|
|
81
|
-
pnx plugin search essentials
|
|
82
|
-
pnx plugin info <slug>
|
|
83
|
-
pnx plugin install <name>
|
|
84
|
-
pnx plugin update
|
|
85
|
-
pnx plugin remove <name>
|
|
86
|
-
pnx plugin installed
|
|
83
|
+
pnx stop
|
|
87
84
|
```
|
|
88
85
|
|
|
89
|
-
|
|
86
|
+
### `update` - update the core
|
|
90
87
|
|
|
91
|
-
|
|
92
|
-
- `list` : afficher les plugins disponibles
|
|
93
|
-
- `search [term]` : rechercher par nom, description ou auteur
|
|
94
|
-
- `info [slug]` : afficher la fiche détaillée d’un plugin
|
|
95
|
-
- `installed` : lister les plugins installés localement
|
|
96
|
-
- `update [names...]` : mettre à jour les plugins installés
|
|
97
|
-
- `remove [names...]` : supprimer des plugins installés
|
|
98
|
-
|
|
99
|
-
### Mettre à jour le serveur
|
|
88
|
+
Backs up the old jar as `.old` then downloads the latest version.
|
|
100
89
|
|
|
101
90
|
```bash
|
|
102
91
|
pnx update --force
|
|
103
92
|
```
|
|
104
93
|
|
|
105
|
-
|
|
94
|
+
| Option | Description |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `--force` | Force re-download (ignore cache) |
|
|
97
|
+
| `--dev` | Development build |
|
|
106
98
|
|
|
107
|
-
|
|
108
|
-
- `-f, --force` : forcer la mise à jour même si la version correspond
|
|
99
|
+
### `plugin` - manage plugins
|
|
109
100
|
|
|
110
|
-
|
|
101
|
+
Official marketplace plus local tracking of installed versions.
|
|
111
102
|
|
|
112
103
|
```bash
|
|
113
|
-
pnx
|
|
114
|
-
pnx
|
|
115
|
-
pnx
|
|
116
|
-
pnx
|
|
117
|
-
pnx
|
|
104
|
+
pnx plugin list # catalog
|
|
105
|
+
pnx plugin search essentials # search
|
|
106
|
+
pnx plugin info <slug> # details
|
|
107
|
+
pnx plugin install <slug|url.jar> # install (marketplace or .jar URL)
|
|
108
|
+
pnx plugin installed # local plugins
|
|
109
|
+
pnx plugin update [slug] # update
|
|
110
|
+
pnx plugin remove [name] # remove
|
|
118
111
|
```
|
|
119
112
|
|
|
120
|
-
|
|
113
|
+
Without an argument, `install`, `update` and `remove` offer an interactive selection.
|
|
121
114
|
|
|
122
|
-
|
|
115
|
+
### Diagnostics and utilities
|
|
123
116
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
117
|
+
```bash
|
|
118
|
+
pnx doctor # Java, RAM, disk, port 19132, plugins/worlds
|
|
119
|
+
pnx info # status, path, plugins, worlds, RAM
|
|
120
|
+
pnx backup # timestamped server backup
|
|
121
|
+
pnx config # print pnx.yml / server.properties (colored)
|
|
122
|
+
pnx use ./server # set the default server
|
|
123
|
+
pnx logs # latest logs (with live follow)
|
|
124
|
+
pnx console # RCON console attached to the server
|
|
125
|
+
```
|
|
131
126
|
|
|
132
|
-
|
|
127
|
+
`doctor` and `info` accept `--json` for machine output.
|
|
133
128
|
|
|
134
|
-
|
|
129
|
+
## Interactive mode
|
|
135
130
|
|
|
136
|
-
|
|
137
|
-
npm install
|
|
138
|
-
```
|
|
131
|
+
Launched without a subcommand, `pnx` opens a **contextual menu** that:
|
|
139
132
|
|
|
140
|
-
|
|
133
|
+
- detects state (server present, running, PID);
|
|
134
|
+
- only offers relevant actions (create if missing, start if stopped, stop if running...);
|
|
135
|
+
- routes to the existing commands.
|
|
141
136
|
|
|
142
137
|
```bash
|
|
143
|
-
|
|
138
|
+
pnx
|
|
144
139
|
```
|
|
145
140
|
|
|
146
|
-
|
|
141
|
+
## Global options
|
|
147
142
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
143
|
+
| Option | Description |
|
|
144
|
+
|---|---|
|
|
145
|
+
| `--json` | Machine JSON output (disables decorative rendering) |
|
|
146
|
+
| `--no-color` | Disable colors |
|
|
151
147
|
|
|
152
|
-
|
|
148
|
+
CLI state is stored in `~/.pnx-cli/` (config, PID, installed plugins, version cache). Environment variables: `PNX_API_URL` (marketplace API base), `PNX_HOME` (state directory).
|
|
153
149
|
|
|
154
|
-
|
|
155
|
-
|
|
150
|
+
## Architecture
|
|
151
|
+
|
|
152
|
+
The code follows a layered architecture - thin commands, isolated business logic:
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
dist/
|
|
156
|
+
cli.js entry point (citty) + global options
|
|
157
|
+
commands/ parse arguments -> call service -> render
|
|
158
|
+
plugin/ plugin subcommands
|
|
159
|
+
services/ pure business logic (release, server, process, plugins, backup)
|
|
160
|
+
infra/ http, JSON store (~/.pnx-cli), constants/endpoints
|
|
161
|
+
ui/ single output system (clack + chalk), prompts
|
|
156
162
|
```
|
|
157
163
|
|
|
158
|
-
|
|
164
|
+
Rules: commands do no direct network/file access (everything goes through `services`/`infra`); services render nothing (they return data).
|
|
165
|
+
|
|
166
|
+
**Stack**: [citty](https://github.com/unjs/citty) (routing), [@clack/prompts](https://github.com/bombshell-dev/clack) (prompts), [chalk](https://github.com/chalk/chalk) (colors).
|
|
159
167
|
|
|
160
|
-
|
|
168
|
+
## Development
|
|
169
|
+
|
|
170
|
+
The shipped code lives in `dist/` (plain ES modules, no build step).
|
|
161
171
|
|
|
162
172
|
```bash
|
|
163
|
-
npm
|
|
164
|
-
npm run
|
|
165
|
-
npm run
|
|
173
|
+
npm install # dependencies
|
|
174
|
+
npm start # run dist/cli.js
|
|
175
|
+
npm run check # syntax check every file
|
|
176
|
+
npm run smoke # run pnx --help
|
|
166
177
|
```
|
|
167
178
|
|
|
168
|
-
##
|
|
179
|
+
## Links
|
|
169
180
|
|
|
170
|
-
-
|
|
171
|
-
-
|
|
181
|
+
- PowerNukkitX documentation: https://docs.powernukkitx.org
|
|
182
|
+
- PowerNukkitX repository: https://github.com/PowerNukkitX/PowerNukkitX
|
|
172
183
|
|
|
173
|
-
##
|
|
184
|
+
## License
|
|
174
185
|
|
|
175
186
|
MIT
|
|
176
|
-
|
|
177
|
-
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineCommand, runMain } from 'citty';
|
|
3
|
+
import { setColorEnabled } from './ui/theme.js';
|
|
4
|
+
if (process.argv.slice(2).includes('--no-color'))
|
|
5
|
+
setColorEnabled(false);
|
|
6
|
+
const main = defineCommand({
|
|
7
|
+
meta: {
|
|
8
|
+
name: 'pnx',
|
|
9
|
+
version: '1.0.0',
|
|
10
|
+
description: 'PowerNukkitX CLI — Manage your Minecraft Bedrock servers',
|
|
11
|
+
},
|
|
12
|
+
subCommands: {
|
|
13
|
+
init: () => import('./commands/init.js').then(m => m.initCmd),
|
|
14
|
+
install: () => import('./commands/install.js').then(m => m.installCmd),
|
|
15
|
+
start: () => import('./commands/start.js').then(m => m.startCmd),
|
|
16
|
+
stop: () => import('./commands/stop.js').then(m => m.stopCmd),
|
|
17
|
+
update: () => import('./commands/update.js').then(m => m.updateCmd),
|
|
18
|
+
info: () => import('./commands/info.js').then(m => m.infoCmd),
|
|
19
|
+
doctor: () => import('./commands/doctor.js').then(m => m.doctorCmd),
|
|
20
|
+
backup: () => import('./commands/backup.js').then(m => m.backupCmd),
|
|
21
|
+
config: () => import('./commands/config.js').then(m => m.configCmd),
|
|
22
|
+
use: () => import('./commands/use.js').then(m => m.useCmd),
|
|
23
|
+
logs: () => import('./commands/logs.js').then(m => m.logsCmd),
|
|
24
|
+
console: () => import('./commands/console.js').then(m => m.consoleCmd),
|
|
25
|
+
plugin: () => import('./commands/plugin/index.js').then(m => m.pluginCmd),
|
|
26
|
+
},
|
|
27
|
+
async run({ args }) {
|
|
28
|
+
if (args._.length === 0) {
|
|
29
|
+
const { runMenu } = await import('./commands/menu.js');
|
|
30
|
+
await runMenu();
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
runMain(main);
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { CommandDef } from 'citty';
|
|
2
|
+
export declare const backupCmd: CommandDef;
|
package/dist/commands/backup.js
CHANGED
|
@@ -1,74 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
catch { /* ignore */ }
|
|
25
|
-
return total;
|
|
26
|
-
}
|
|
27
|
-
function formatSize(bytes) {
|
|
28
|
-
if (bytes < 1024)
|
|
29
|
-
return `${bytes} B`;
|
|
30
|
-
if (bytes < 1024 * 1024)
|
|
31
|
-
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
32
|
-
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
33
|
-
}
|
|
34
|
-
export async function backupCmd() {
|
|
35
|
-
const serverPath = await resolveServerDir(t('backup.selectServer'));
|
|
36
|
-
if (!serverPath) {
|
|
37
|
-
error(t('backup.noServer'));
|
|
38
|
-
await pauseForExit();
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
if (serverPath === cwd()) {
|
|
42
|
-
const ok = await confirm({
|
|
43
|
-
message: t('backup.backupCurrent', highlight(serverPath)),
|
|
44
|
-
default: true,
|
|
45
|
-
});
|
|
46
|
-
if (!ok) {
|
|
47
|
-
info(t('backup.cancelled'));
|
|
48
|
-
await pauseForExit();
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
header(`💾 ${t('backup.title')}`);
|
|
53
|
-
step(t('backup.collecting'));
|
|
54
|
-
const size = getDirSize(serverPath);
|
|
55
|
-
info(t('backup.estimatedSize', formatSize(size)));
|
|
56
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
57
|
-
const backupDir = join(serverPath, 'backups');
|
|
58
|
-
const destDir = join(backupDir, `pnx-backup-${timestamp}`);
|
|
59
|
-
await mkdir(destDir, { recursive: true });
|
|
60
|
-
step(t('backup.copying'));
|
|
61
|
-
const items = await readdir(serverPath);
|
|
62
|
-
let count = 0;
|
|
63
|
-
for (const item of items) {
|
|
64
|
-
if (IGNORE.has(item) || item.startsWith('.'))
|
|
65
|
-
continue;
|
|
66
|
-
const src = join(serverPath, item);
|
|
67
|
-
const dst = join(destDir, item);
|
|
68
|
-
await cp(src, dst, { recursive: true, force: true });
|
|
69
|
-
count++;
|
|
70
|
-
}
|
|
71
|
-
const finalSize = getDirSize(destDir);
|
|
72
|
-
success(t('backup.done', destDir, formatSize(finalSize)));
|
|
73
|
-
await pauseForExit();
|
|
74
|
-
}
|
|
1
|
+
import { defineCommand } from 'citty';
|
|
2
|
+
import { intro, outro, log, spin } from '../ui/output.js';
|
|
3
|
+
import { resolveServerDir } from '../services/server.js';
|
|
4
|
+
import { createBackup, dirSize, fmtSize } from '../services/backup.js';
|
|
5
|
+
export async function runBackup() {
|
|
6
|
+
intro(`💾 ${"Backup"}`);
|
|
7
|
+
const serverPath = await resolveServerDir();
|
|
8
|
+
if (!serverPath) {
|
|
9
|
+
log.error("No server detected");
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
const sp = spin("Collecting files...");
|
|
13
|
+
sp.stop(`Estimated size: ${fmtSize(dirSize(serverPath))}`);
|
|
14
|
+
const sp2 = spin("Copying files...");
|
|
15
|
+
const { path, size } = await createBackup(serverPath);
|
|
16
|
+
sp2.stop(`Backup created: ${path} (${fmtSize(size)})`);
|
|
17
|
+
outro(`Backup created: ${path} (${fmtSize(size)})`);
|
|
18
|
+
}
|
|
19
|
+
export const backupCmd = defineCommand({
|
|
20
|
+
meta: { description: 'Create a server backup' },
|
|
21
|
+
args: {},
|
|
22
|
+
run: () => runBackup(),
|
|
23
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function configCmd(): Promise<void>;
|
|
1
|
+
export declare function configCmd(): Promise<void>;
|
package/dist/commands/config.js
CHANGED
|
@@ -1,114 +1,60 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { resolveServerDir } from '../
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
console.log(` ${chalk.dim(indent)}${chalk.white(trimmed)}`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
// Display server.properties with highlighting
|
|
67
|
-
let inSection = false;
|
|
68
|
-
for (let i = 0; i < lines.length; i++) {
|
|
69
|
-
const line = lines[i];
|
|
70
|
-
if (line.startsWith('#') || line.trim() === '') {
|
|
71
|
-
const trimmed = line.replace(/^#\s*/, '').trim();
|
|
72
|
-
if (trimmed && !inSection) {
|
|
73
|
-
console.log(`\n ${dim(trimmed)}`);
|
|
74
|
-
inSection = true;
|
|
75
|
-
}
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
inSection = false;
|
|
79
|
-
const eqIdx = line.indexOf('=');
|
|
80
|
-
if (eqIdx > 0) {
|
|
81
|
-
const key = line.slice(0, eqIdx).trim();
|
|
82
|
-
const value = line.slice(eqIdx + 1).trim();
|
|
83
|
-
console.log(` ${highlight(key)} ${dim('=')} ${colorPropsValue(value)}`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
console.log(`\n ${dim('─'.repeat(40))}`);
|
|
88
|
-
info(t('config.editHint', highlight(configPath)));
|
|
89
|
-
await pauseForExit();
|
|
90
|
-
}
|
|
91
|
-
function colorYamlValue(val) {
|
|
92
|
-
if (val === 'true')
|
|
93
|
-
return chalk.green(val);
|
|
94
|
-
if (val === 'false')
|
|
95
|
-
return chalk.red(val);
|
|
96
|
-
if (/^\d+(\.\d+)?$/.test(val))
|
|
97
|
-
return chalk.cyan(val);
|
|
98
|
-
if (val.startsWith('[') || val.startsWith('-'))
|
|
99
|
-
return chalk.hex('#E040FB')(val);
|
|
100
|
-
if (val.startsWith('"') && val.endsWith('"'))
|
|
101
|
-
return chalk.green(val);
|
|
102
|
-
if (val.startsWith("'") && val.endsWith("'"))
|
|
103
|
-
return chalk.green(val);
|
|
104
|
-
return chalk.white(val);
|
|
105
|
-
}
|
|
106
|
-
function colorPropsValue(val) {
|
|
107
|
-
if (val === 'true' || val === 'on')
|
|
108
|
-
return chalk.green(val);
|
|
109
|
-
if (val === 'false' || val === 'off')
|
|
110
|
-
return chalk.red(val);
|
|
111
|
-
if (/^\d+$/.test(val))
|
|
112
|
-
return chalk.cyan(val);
|
|
113
|
-
return chalk.white(val);
|
|
114
|
-
}
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { defineCommand } from 'citty';
|
|
4
|
+
import { intro, outro, log } from '../ui/output.js';
|
|
5
|
+
import { c } from '../ui/theme.js';
|
|
6
|
+
import { resolveServerDir } from '../services/server.js';
|
|
7
|
+
function colorVal(val) {
|
|
8
|
+
if (val === 'true' || val === 'on')
|
|
9
|
+
return c.green(val);
|
|
10
|
+
if (val === 'false' || val === 'off')
|
|
11
|
+
return c.red(val);
|
|
12
|
+
if (/^\d+(\.\d+)?$/.test(val))
|
|
13
|
+
return c.cyan(val);
|
|
14
|
+
return val;
|
|
15
|
+
}
|
|
16
|
+
export const configCmd = defineCommand({
|
|
17
|
+
meta: { description: 'View server configuration' },
|
|
18
|
+
args: {},
|
|
19
|
+
async run() {
|
|
20
|
+
intro(`⚙️ ${"Configuration"}`);
|
|
21
|
+
const serverPath = await resolveServerDir();
|
|
22
|
+
if (!serverPath) {
|
|
23
|
+
log.error("No server detected");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
let cfgPath = join(serverPath, 'pnx.yml');
|
|
27
|
+
if (!existsSync(cfgPath))
|
|
28
|
+
cfgPath = join(serverPath, 'server.properties');
|
|
29
|
+
if (!existsSync(cfgPath)) {
|
|
30
|
+
log.error("No config file found");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
let content = readFileSync(cfgPath, 'utf-8');
|
|
34
|
+
if (content.charCodeAt(0) === 0xfeff)
|
|
35
|
+
content = content.slice(1);
|
|
36
|
+
const sep = cfgPath.endsWith('.yml') ? ':' : '=';
|
|
37
|
+
for (const line of content.split('\n')) {
|
|
38
|
+
const trimmed = line.trim();
|
|
39
|
+
if (!trimmed) {
|
|
40
|
+
log.raw('');
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (trimmed.startsWith('#')) {
|
|
44
|
+
log.raw(` ${c.dim(line)}`);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const idx = trimmed.indexOf(sep);
|
|
48
|
+
if (idx > 0) {
|
|
49
|
+
const key = trimmed.slice(0, idx);
|
|
50
|
+
const val = trimmed.slice(idx + 1).trim();
|
|
51
|
+
const indent = line.match(/^(\s*)/)?.[1] ?? '';
|
|
52
|
+
log.raw(` ${indent}${c.blue(key)}${sep}${val ? ' ' + colorVal(val) : ''}`);
|
|
53
|
+
}
|
|
54
|
+
else
|
|
55
|
+
log.raw(` ${c.dim(trimmed)}`);
|
|
56
|
+
}
|
|
57
|
+
log.info(`Edit ${cfgPath} to change these values`);
|
|
58
|
+
outro('');
|
|
59
|
+
},
|
|
60
|
+
});
|