@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,121 +1,119 @@
1
- import https from 'node:https';
2
- import http from 'node:http';
3
- import { createWriteStream } from 'node:fs';
4
- const REDIRECT_CODES = [301, 302, 303, 307, 308];
5
- export class NetworkError extends Error {
6
- statusCode;
7
- constructor(message, statusCode) {
8
- super(message);
9
- this.statusCode = statusCode;
10
- this.name = 'NetworkError';
11
- }
12
- }
13
- const sleep = (ms) => new Promise(r => setTimeout(r, ms));
14
- function get(url, timeoutMs, headers) {
15
- return new Promise((resolve, reject) => {
16
- const mod = url.startsWith('https') ? https : http;
17
- const req = mod.get(url, { timeout: timeoutMs, headers }, (res) => {
18
- let body = '';
19
- res.on('data', (chunk) => (body += chunk.toString()));
20
- res.on('end', () => resolve({ statusCode: res.statusCode ?? 0, location: res.headers.location, body }));
21
- res.on('error', reject);
22
- });
23
- req.on('error', reject);
24
- req.on('timeout', function () {
25
- this.destroy();
26
- reject(new NetworkError('Request timed out'));
27
- });
28
- });
29
- }
30
- async function getFollow(url, timeout, headers, redirects = 5) {
31
- if (redirects <= 0)
32
- throw new NetworkError('Too many redirects');
33
- const res = await get(url, timeout, { 'User-Agent': 'pnx-cli', ...headers });
34
- if (REDIRECT_CODES.includes(res.statusCode) && res.location) {
35
- return getFollow(res.location, timeout, headers, redirects - 1);
36
- }
37
- if (res.statusCode !== 200)
38
- throw new NetworkError(`HTTP ${res.statusCode}`, res.statusCode);
39
- return res.body;
40
- }
41
- /** GET JSON avec suivi des redirections et retry exponentiel. */
42
- export async function fetchJSON(url, opts) {
43
- const retries = opts?.retries ?? 3;
44
- const timeout = opts?.timeout ?? 15_000;
45
- const headers = opts?.headers ?? {};
46
- let lastErr = new Error('Unknown error');
47
- for (let attempt = 1; attempt <= retries; attempt++) {
48
- try {
49
- return JSON.parse(await getFollow(url, timeout, headers));
50
- }
51
- catch (err) {
52
- lastErr = err;
53
- if (attempt < retries) {
54
- opts?.onRetry?.(lastErr.message, attempt, retries);
55
- await sleep(2 ** (attempt - 1) * 1000);
56
- }
57
- }
58
- }
59
- throw lastErr;
60
- }
61
- function stream(url, dest, timeout, onData) {
62
- return new Promise((resolve, reject) => {
63
- const mod = url.startsWith('https') ? https : http;
64
- const file = createWriteStream(dest);
65
- const req = mod.get(url, { timeout, headers: { 'User-Agent': 'pnx-cli' } }, (res) => {
66
- const code = res.statusCode ?? 0;
67
- if (REDIRECT_CODES.includes(code) && res.headers.location) {
68
- file.close();
69
- resolve(stream(res.headers.location, dest, timeout, onData));
70
- return;
71
- }
72
- if (code !== 200) {
73
- file.close();
74
- reject(new NetworkError(`HTTP ${code}`, code));
75
- return;
76
- }
77
- const total = parseInt(res.headers['content-length'] || '0', 10);
78
- res.on('data', (chunk) => onData(chunk, total));
79
- res.pipe(file);
80
- file.on('finish', () => { file.close(); resolve(); });
81
- file.on('error', reject);
82
- });
83
- req.on('error', err => { file.close(); reject(err); });
84
- req.on('timeout', function () {
85
- this.destroy();
86
- file.close();
87
- reject(new NetworkError('Download timed out'));
88
- });
89
- });
90
- }
91
- /** Télécharge un fichier vers `dest` avec progression et retry. */
92
- export async function downloadFile(url, dest, opts) {
93
- const retries = opts?.retries ?? 3;
94
- const timeout = opts?.timeout ?? 120_000;
95
- let lastErr = new Error('Unknown error');
96
- for (let attempt = 1; attempt <= retries; attempt++) {
97
- try {
98
- let downloaded = 0;
99
- let lastPct = -1;
100
- await stream(url, dest, timeout, (chunk, total) => {
101
- downloaded += chunk.length;
102
- if (opts?.onProgress && total > 0) {
103
- const pct = Math.round((downloaded / total) * 100);
104
- if (pct !== lastPct && pct % 5 === 0) {
105
- opts.onProgress(pct, downloaded, total);
106
- lastPct = pct;
107
- }
108
- }
109
- });
110
- return;
111
- }
112
- catch (err) {
113
- lastErr = err;
114
- if (attempt < retries) {
115
- opts?.onRetry?.(lastErr.message, attempt, retries);
116
- await sleep(2 ** (attempt - 1) * 1000);
117
- }
118
- }
119
- }
120
- throw lastErr;
121
- }
1
+ import https from 'node:https';
2
+ import http from 'node:http';
3
+ import { createWriteStream } from 'node:fs';
4
+ const REDIRECT_CODES = [301, 302, 303, 307, 308];
5
+ export class NetworkError extends Error {
6
+ statusCode;
7
+ constructor(message, statusCode) {
8
+ super(message);
9
+ this.statusCode = statusCode;
10
+ this.name = 'NetworkError';
11
+ }
12
+ }
13
+ const sleep = (ms) => new Promise(r => setTimeout(r, ms));
14
+ function get(url, timeoutMs, headers) {
15
+ return new Promise((resolve, reject) => {
16
+ const mod = url.startsWith('https') ? https : http;
17
+ const req = mod.get(url, { timeout: timeoutMs, headers }, (res) => {
18
+ let body = '';
19
+ res.on('data', (chunk) => (body += chunk.toString()));
20
+ res.on('end', () => resolve({ statusCode: res.statusCode ?? 0, location: res.headers.location, body }));
21
+ res.on('error', reject);
22
+ });
23
+ req.on('error', reject);
24
+ req.on('timeout', function () {
25
+ this.destroy();
26
+ reject(new NetworkError('Request timed out'));
27
+ });
28
+ });
29
+ }
30
+ async function getFollow(url, timeout, headers, redirects = 5) {
31
+ if (redirects <= 0)
32
+ throw new NetworkError('Too many redirects');
33
+ const res = await get(url, timeout, { 'User-Agent': 'pnx-cli', ...headers });
34
+ if (REDIRECT_CODES.includes(res.statusCode) && res.location) {
35
+ return getFollow(res.location, timeout, headers, redirects - 1);
36
+ }
37
+ if (res.statusCode !== 200)
38
+ throw new NetworkError(`HTTP ${res.statusCode}`, res.statusCode);
39
+ return res.body;
40
+ }
41
+ export async function fetchJSON(url, opts) {
42
+ const retries = opts?.retries ?? 3;
43
+ const timeout = opts?.timeout ?? 15_000;
44
+ const headers = opts?.headers ?? {};
45
+ let lastErr = new Error('Unknown error');
46
+ for (let attempt = 1; attempt <= retries; attempt++) {
47
+ try {
48
+ return JSON.parse(await getFollow(url, timeout, headers));
49
+ }
50
+ catch (err) {
51
+ lastErr = err;
52
+ if (attempt < retries) {
53
+ opts?.onRetry?.(lastErr.message, attempt, retries);
54
+ await sleep(2 ** (attempt - 1) * 1000);
55
+ }
56
+ }
57
+ }
58
+ throw lastErr;
59
+ }
60
+ function stream(url, dest, timeout, onData) {
61
+ return new Promise((resolve, reject) => {
62
+ const mod = url.startsWith('https') ? https : http;
63
+ const file = createWriteStream(dest);
64
+ const req = mod.get(url, { timeout, headers: { 'User-Agent': 'pnx-cli' } }, (res) => {
65
+ const code = res.statusCode ?? 0;
66
+ if (REDIRECT_CODES.includes(code) && res.headers.location) {
67
+ file.close();
68
+ resolve(stream(res.headers.location, dest, timeout, onData));
69
+ return;
70
+ }
71
+ if (code !== 200) {
72
+ file.close();
73
+ reject(new NetworkError(`HTTP ${code}`, code));
74
+ return;
75
+ }
76
+ const total = parseInt(res.headers['content-length'] || '0', 10);
77
+ res.on('data', (chunk) => onData(chunk, total));
78
+ res.pipe(file);
79
+ file.on('finish', () => { file.close(); resolve(); });
80
+ file.on('error', reject);
81
+ });
82
+ req.on('error', err => { file.close(); reject(err); });
83
+ req.on('timeout', function () {
84
+ this.destroy();
85
+ file.close();
86
+ reject(new NetworkError('Download timed out'));
87
+ });
88
+ });
89
+ }
90
+ export async function downloadFile(url, dest, opts) {
91
+ const retries = opts?.retries ?? 3;
92
+ const timeout = opts?.timeout ?? 120_000;
93
+ let lastErr = new Error('Unknown error');
94
+ for (let attempt = 1; attempt <= retries; attempt++) {
95
+ try {
96
+ let downloaded = 0;
97
+ let lastPct = -1;
98
+ await stream(url, dest, timeout, (chunk, total) => {
99
+ downloaded += chunk.length;
100
+ if (opts?.onProgress && total > 0) {
101
+ const pct = Math.round((downloaded / total) * 100);
102
+ if (pct !== lastPct && pct % 5 === 0) {
103
+ opts.onProgress(pct, downloaded, total);
104
+ lastPct = pct;
105
+ }
106
+ }
107
+ });
108
+ return;
109
+ }
110
+ catch (err) {
111
+ lastErr = err;
112
+ if (attempt < retries) {
113
+ opts?.onRetry?.(lastErr.message, attempt, retries);
114
+ await sleep(2 ** (attempt - 1) * 1000);
115
+ }
116
+ }
117
+ }
118
+ throw lastErr;
119
+ }
@@ -1,20 +1,15 @@
1
- import { homedir } from 'node:os';
2
- import { join } from 'node:path';
3
- /** Répertoire d'état du CLI (~/.pnx-cli), surchargeable via PNX_HOME (tests). */
4
- export function pnxHome() {
5
- return process.env.PNX_HOME || join(homedir(), '.pnx-cli');
6
- }
7
- /** Chemin absolu d'un fichier du store dans le répertoire d'état. */
8
- export function storePath(name) {
9
- return join(pnxHome(), name);
10
- }
11
- /** Nom du fichier jar du core. */
12
- export const JAR_NAME = 'powernukkitx.jar';
13
- /** Endpoint GitHub de la dernière release du core. */
14
- export const GITHUB_LATEST_RELEASE = 'https://api.github.com/repos/PowerNukkitX/PowerNukkitX/releases/latest';
15
- /** Base des scripts de démarrage officiels. */
16
- export const SCRIPTS_BASE = 'https://raw.githubusercontent.com/PowerNukkitX/scripts/master';
17
- /** Base de l'API marketplace, surchargeable via PNX_API_URL. */
18
- export function apiBase() {
19
- return (process.env.PNX_API_URL ?? 'https://api.powernukkitx.org').replace(/\/$/, '');
20
- }
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ export function pnxHome() {
4
+ return process.env.PNX_HOME || join(homedir(), '.pnx-cli');
5
+ }
6
+ export function storePath(name) {
7
+ return join(pnxHome(), name);
8
+ }
9
+ export const JAR_NAME = 'powernukkitx.jar';
10
+ export const GITHUB_LATEST_RELEASE = 'https://api.github.com/repos/PowerNukkitX/PowerNukkitX/releases/latest';
11
+ export const GITHUB_RELEASES = 'https://api.github.com/repos/PowerNukkitX/PowerNukkitX/releases';
12
+ export const SCRIPTS_BASE = 'https://raw.githubusercontent.com/PowerNukkitX/scripts/master';
13
+ export function apiBase() {
14
+ return (process.env.PNX_API_URL ?? 'https://api.powernukkitx.org').replace(/\/$/, '');
15
+ }
@@ -1,27 +1,24 @@
1
- import { existsSync } from 'node:fs';
2
- import { readFile, writeFile, mkdir, rm } from 'node:fs/promises';
3
- import { dirname } from 'node:path';
4
- import { storePath } from './paths.js';
5
- /** Lit un fichier JSON du store, renvoie `fallback` si absent ou illisible. */
6
- export async function readJson(name, fallback) {
7
- try {
8
- const file = storePath(name);
9
- if (existsSync(file))
10
- return JSON.parse(await readFile(file, 'utf-8'));
11
- }
12
- catch { /* corrompu → fallback */ }
13
- return fallback;
14
- }
15
- /** Écrit un objet en JSON dans le store (crée le répertoire au besoin). */
16
- export async function writeJson(name, data) {
17
- const file = storePath(name);
18
- await mkdir(dirname(file), { recursive: true });
19
- await writeFile(file, JSON.stringify(data, null, 2), 'utf-8');
20
- }
21
- /** Supprime un fichier du store (silencieux s'il n'existe pas). */
22
- export async function removeFile(name) {
23
- try {
24
- await rm(storePath(name));
25
- }
26
- catch { /* absent */ }
27
- }
1
+ import { existsSync } from 'node:fs';
2
+ import { readFile, writeFile, mkdir, rm } from 'node:fs/promises';
3
+ import { dirname } from 'node:path';
4
+ import { storePath } from './paths.js';
5
+ export async function readJson(name, fallback) {
6
+ try {
7
+ const file = storePath(name);
8
+ if (existsSync(file))
9
+ return JSON.parse(await readFile(file, 'utf-8'));
10
+ }
11
+ catch { }
12
+ return fallback;
13
+ }
14
+ export async function writeJson(name, data) {
15
+ const file = storePath(name);
16
+ await mkdir(dirname(file), { recursive: true });
17
+ await writeFile(file, JSON.stringify(data, null, 2), 'utf-8');
18
+ }
19
+ export async function removeFile(name) {
20
+ try {
21
+ await rm(storePath(name));
22
+ }
23
+ catch { }
24
+ }
@@ -1,40 +1,34 @@
1
- import { readdirSync, statSync } from 'node:fs';
2
- import { mkdir, cp, readdir } from 'node:fs/promises';
3
- import { join } from 'node:path';
4
- const IGNORE = new Set(['logs', 'cache', 'crash-reports', 'backups', '.git']);
5
- /** Taille récursive d'un dossier en octets. */
6
- export function dirSize(dir) {
7
- let total = 0;
8
- try {
9
- for (const f of readdirSync(dir)) {
10
- const full = join(dir, f);
11
- const s = statSync(full);
12
- total += s.isDirectory() ? dirSize(full) : s.size;
13
- }
14
- }
15
- catch { /* ignore */ }
16
- return total;
17
- }
18
- /** Formatte une taille en octets. */
19
- export function fmtSize(b) {
20
- if (b < 1024)
21
- return `${b} B`;
22
- if (b < 1024 ** 2)
23
- return `${(b / 1024).toFixed(1)} KB`;
24
- return `${(b / 1024 / 1024).toFixed(1)} MB`;
25
- }
26
- /**
27
- * Crée une sauvegarde horodatée du serveur dans `<serverDir>/backups/`.
28
- * Copie récursive (zéro dépendance), en ignorant logs/cache/backups.
29
- */
30
- export async function createBackup(serverDir) {
31
- const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
32
- const destDir = join(serverDir, 'backups', `pnx-backup-${ts}`);
33
- await mkdir(destDir, { recursive: true });
34
- for (const item of await readdir(serverDir)) {
35
- if (IGNORE.has(item) || item.startsWith('.'))
36
- continue;
37
- await cp(join(serverDir, item), join(destDir, item), { recursive: true, force: true });
38
- }
39
- return { path: destDir, size: dirSize(destDir) };
40
- }
1
+ import { readdirSync, statSync } from 'node:fs';
2
+ import { mkdir, cp, readdir } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ const IGNORE = new Set(['logs', 'cache', 'crash-reports', 'backups', '.git']);
5
+ export function dirSize(dir) {
6
+ let total = 0;
7
+ try {
8
+ for (const f of readdirSync(dir)) {
9
+ const full = join(dir, f);
10
+ const s = statSync(full);
11
+ total += s.isDirectory() ? dirSize(full) : s.size;
12
+ }
13
+ }
14
+ catch { }
15
+ return total;
16
+ }
17
+ export function fmtSize(b) {
18
+ if (b < 1024)
19
+ return `${b} B`;
20
+ if (b < 1024 ** 2)
21
+ return `${(b / 1024).toFixed(1)} KB`;
22
+ return `${(b / 1024 / 1024).toFixed(1)} MB`;
23
+ }
24
+ export async function createBackup(serverDir) {
25
+ const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
26
+ const destDir = join(serverDir, 'backups', `pnx-backup-${ts}`);
27
+ await mkdir(destDir, { recursive: true });
28
+ for (const item of await readdir(serverDir)) {
29
+ if (IGNORE.has(item) || item.startsWith('.'))
30
+ continue;
31
+ await cp(join(serverDir, item), join(destDir, item), { recursive: true, force: true });
32
+ }
33
+ return { path: destDir, size: dirSize(destDir) };
34
+ }