@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,13 +1,13 @@
1
- import { defineCommand } from 'citty';
2
- export const pluginCmd = defineCommand({
3
- meta: { description: 'Plugin management' },
4
- subCommands: {
5
- install: () => import('./install.js').then(m => m.installCmd),
6
- list: () => import('./list.js').then(m => m.listCmd),
7
- search: () => import('./search.js').then(m => m.searchCmd),
8
- info: () => import('./info.js').then(m => m.infoCmd),
9
- update: () => import('./update.js').then(m => m.updateCmd),
10
- remove: () => import('./remove.js').then(m => m.removeCmd),
11
- installed: () => import('./installed.js').then(m => m.installedCmd),
12
- },
13
- });
1
+ import { defineCommand } from 'citty';
2
+ export const pluginCmd = defineCommand({
3
+ meta: { description: 'Plugin management' },
4
+ subCommands: {
5
+ install: () => import('./install.js').then(m => m.installCmd),
6
+ list: () => import('./list.js').then(m => m.listCmd),
7
+ search: () => import('./search.js').then(m => m.searchCmd),
8
+ info: () => import('./info.js').then(m => m.infoCmd),
9
+ update: () => import('./update.js').then(m => m.updateCmd),
10
+ remove: () => import('./remove.js').then(m => m.removeCmd),
11
+ installed: () => import('./installed.js').then(m => m.installedCmd),
12
+ },
13
+ });
@@ -1,2 +1,2 @@
1
- import type { CommandDef } from 'citty';
2
- export declare const infoCmd: CommandDef;
1
+ import type { CommandDef } from 'citty';
2
+ export declare const infoCmd: CommandDef;
@@ -1,40 +1,39 @@
1
- import { defineCommand } from 'citty';
2
- import { intro, outro, log, spin } from '../../ui/output.js';
3
- import { c } from '../../ui/theme.js';
4
- import { promptText } from '../../ui/prompts.js';
5
- import { getPluginDetail } from '../../services/plugins.js';
6
- import { t } from '../../i18n/index.js';
7
- export const infoCmd = defineCommand({
8
- meta: { description: 'Show plugin details' },
9
- args: { slug: { type: 'positional', description: 'Plugin slug', required: false } },
10
- async run({ args }) {
11
- const slug = args.slug ?? await promptText({ message: t('plugin.slugPrompt') });
12
- const sp = spin(slug);
13
- try {
14
- const d = await getPluginDetail(slug);
15
- sp.stop(d.name);
16
- intro(`📖 ${d.name}`);
17
- if (d.description)
18
- log.dim(d.description);
19
- log.info(`Author: ${c.accent(d.author)}`);
20
- log.info(`Version: ${c.green(d.latest_version)}`);
21
- log.info(`Downloads: ${c.cyan(d.downloads >= 1000 ? (d.downloads / 1000).toFixed(1) + 'k' : String(d.downloads))}`);
22
- log.info(`Updated: ${new Date(d.updated_at).toLocaleDateString()}`);
23
- if (d.tags.length)
24
- log.info(`Tags: ${d.tags.map(tag => c.cyan(tag)).join(', ')}`);
25
- if (d.repository_url)
26
- log.info(`Repo: ${c.blue(d.repository_url)}`);
27
- if (d.releases.length) {
28
- log.step(t('plugin.versionsAvailable'));
29
- for (const r of d.releases.slice(0, 5)) {
30
- const stable = r.is_stable ? c.green('●') : c.dim('○');
31
- log.raw(` ${stable} v${r.version} ${c.dim(new Date(r.created_at).toLocaleDateString())}`);
32
- }
33
- }
34
- outro('');
35
- }
36
- catch {
37
- sp.fail(t('plugin.notFound', slug));
38
- }
39
- },
40
- });
1
+ import { defineCommand } from 'citty';
2
+ import { intro, outro, log, spin } from '../../ui/output.js';
3
+ import { c } from '../../ui/theme.js';
4
+ import { promptText } from '../../ui/prompts.js';
5
+ import { getPluginDetail } from '../../services/plugins.js';
6
+ export const infoCmd = defineCommand({
7
+ meta: { description: 'Show plugin details' },
8
+ args: { slug: { type: 'positional', description: 'Plugin slug', required: false } },
9
+ async run({ args }) {
10
+ const slug = args.slug ?? await promptText({ message: "Plugin slug:" });
11
+ const sp = spin(slug);
12
+ try {
13
+ const d = await getPluginDetail(slug);
14
+ sp.stop(d.name);
15
+ intro(`📖 ${d.name}`);
16
+ if (d.description)
17
+ log.dim(d.description);
18
+ log.info(`Author: ${c.accent(d.author)}`);
19
+ log.info(`Version: ${c.green(d.latest_version)}`);
20
+ log.info(`Downloads: ${c.cyan(d.downloads >= 1000 ? (d.downloads / 1000).toFixed(1) + 'k' : String(d.downloads))}`);
21
+ log.info(`Updated: ${new Date(d.updated_at).toLocaleDateString()}`);
22
+ if (d.tags.length)
23
+ log.info(`Tags: ${d.tags.map(tag => c.cyan(tag)).join(', ')}`);
24
+ if (d.repository_url)
25
+ log.info(`Repo: ${c.blue(d.repository_url)}`);
26
+ if (d.releases.length) {
27
+ log.step("Available versions:");
28
+ for (const r of d.releases.slice(0, 5)) {
29
+ const stable = r.is_stable ? c.green('●') : c.dim('○');
30
+ log.raw(` ${stable} v${r.version} ${c.dim(new Date(r.created_at).toLocaleDateString())}`);
31
+ }
32
+ }
33
+ outro('');
34
+ }
35
+ catch {
36
+ sp.fail(`Plugin not found: ${slug}`);
37
+ }
38
+ },
39
+ });
@@ -1,2 +1,2 @@
1
- import type { CommandDef } from 'citty';
2
- export declare const installCmd: CommandDef;
1
+ import type { CommandDef } from 'citty';
2
+ export declare const installCmd: CommandDef;
@@ -1,57 +1,56 @@
1
- import { join } from 'node:path';
2
- import { defineCommand } from 'citty';
3
- import { intro, outro, log, spin, progress } from '../../ui/output.js';
4
- import { promptMulti } from '../../ui/prompts.js';
5
- import { resolveServerDir } from '../../services/server.js';
6
- import { searchPlugins, installPlugin, installFromUrl } from '../../services/plugins.js';
7
- import { t } from '../../i18n/index.js';
8
- export const installCmd = defineCommand({
9
- meta: { description: 'Install plugins' },
10
- args: { names: { type: 'positional', description: 'Plugin slugs or .jar URLs', required: false } },
11
- async run({ args }) {
12
- const serverPath = (await resolveServerDir()) ?? '.';
13
- const pluginsDir = join(serverPath, 'plugins');
14
- let names = args.names ? [args.names] : [];
15
- if (names.length === 0) {
16
- intro(`📦 ${t('plugin.titleInstall')}`);
17
- const sp = spin(t('plugin.fetching'));
18
- const resp = await searchPlugins({ sort: 'stars', limit: 50 });
19
- sp.stop(`${resp.plugins.length} plugins`);
20
- names = await promptMulti(t('plugin.selectInstall'), resp.plugins.map(p => ({ value: p.slug, label: p.name, hint: p.description })));
21
- if (names.length === 0) {
22
- log.info(t('plugin.noneSelected'));
23
- return;
24
- }
25
- }
26
- intro(`📦 ${t('plugin.titleInstall')}`);
27
- for (const name of names) {
28
- if (name.startsWith('http://') || name.startsWith('https://')) {
29
- try {
30
- const file = await installFromUrl(name, pluginsDir, (pct, f) => progress(pct, f));
31
- log.success(t('plugin.installSuccess', file));
32
- }
33
- catch {
34
- log.error(t('plugin.urlInvalid'));
35
- }
36
- continue;
37
- }
38
- const sp = spin(name);
39
- try {
40
- const entry = await installPlugin(name, pluginsDir, (pct, f) => progress(pct, f));
41
- sp.stop(`${entry.name} v${entry.version}`);
42
- log.success(t('plugin.installSuccess', entry.name));
43
- }
44
- catch (e) {
45
- const msg = e.message;
46
- if (msg.startsWith('no-release'))
47
- sp.fail(t('plugin.noRelease', name));
48
- else if (msg.startsWith('no-file'))
49
- sp.fail(t('plugin.noFile', name));
50
- else
51
- sp.fail(t('plugin.installError', name));
52
- }
53
- }
54
- log.info(t('plugin.restartHint'));
55
- outro('');
56
- },
57
- });
1
+ import { join } from 'node:path';
2
+ import { defineCommand } from 'citty';
3
+ import { intro, outro, log, spin, progress } from '../../ui/output.js';
4
+ import { promptMulti } from '../../ui/prompts.js';
5
+ import { resolveServerDir } from '../../services/server.js';
6
+ import { searchPlugins, installPlugin, installFromUrl } from '../../services/plugins.js';
7
+ export const installCmd = defineCommand({
8
+ meta: { description: 'Install plugins' },
9
+ args: { names: { type: 'positional', description: 'Plugin slugs or .jar URLs', required: false } },
10
+ async run({ args }) {
11
+ const serverPath = (await resolveServerDir()) ?? '.';
12
+ const pluginsDir = join(serverPath, 'plugins');
13
+ let names = args.names ? [args.names] : [];
14
+ if (names.length === 0) {
15
+ intro(`📦 ${"Install plugins"}`);
16
+ const sp = spin("Fetching from marketplace...");
17
+ const resp = await searchPlugins({ sort: 'stars', limit: 50 });
18
+ sp.stop(`${resp.plugins.length} plugins`);
19
+ names = await promptMulti("Select plugins to install:", resp.plugins.map(p => ({ value: p.slug, label: p.name, hint: p.description })));
20
+ if (names.length === 0) {
21
+ log.info("No plugin selected");
22
+ return;
23
+ }
24
+ }
25
+ intro(`📦 ${"Install plugins"}`);
26
+ for (const name of names) {
27
+ if (name.startsWith('http://') || name.startsWith('https://')) {
28
+ try {
29
+ const file = await installFromUrl(name, pluginsDir, (pct, f) => progress(pct, f));
30
+ log.success(`${file} installed`);
31
+ }
32
+ catch {
33
+ log.error("URL must point to a .jar file");
34
+ }
35
+ continue;
36
+ }
37
+ const sp = spin(name);
38
+ try {
39
+ const entry = await installPlugin(name, pluginsDir, (pct, f) => progress(pct, f));
40
+ sp.stop(`${entry.name} v${entry.version}`);
41
+ log.success(`${entry.name} installed`);
42
+ }
43
+ catch (e) {
44
+ const msg = e.message;
45
+ if (msg.startsWith('no-release'))
46
+ sp.fail(`No release available for ${name}`);
47
+ else if (msg.startsWith('no-file'))
48
+ sp.fail(`No file for ${name}`);
49
+ else
50
+ sp.fail(`Error installing ${name}`);
51
+ }
52
+ }
53
+ log.info("Restart the server to load plugins");
54
+ outro('');
55
+ },
56
+ });
@@ -1,2 +1,2 @@
1
- import type { CommandDef } from 'citty';
2
- export declare const installedCmd: CommandDef;
1
+ import type { CommandDef } from 'citty';
2
+ export declare const installedCmd: CommandDef;
@@ -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 { defineCommand } from 'citty';
5
- import { intro, outro, log, isJson, json } from '../../ui/output.js';
6
- import { c } from '../../ui/theme.js';
7
- import { resolveServerDir } from '../../services/server.js';
8
- import { getInstalled } from '../../services/plugins.js';
9
- import { t } from '../../i18n/index.js';
10
- export const installedCmd = defineCommand({
11
- meta: { description: 'List installed plugins' },
12
- args: {},
13
- async run() {
14
- const serverPath = await resolveServerDir();
15
- const pluginsDir = serverPath ? join(serverPath, 'plugins') : 'plugins';
16
- if (!existsSync(pluginsDir)) {
17
- if (isJson())
18
- json({ plugins: [] });
19
- log.warn(t('plugin.noPluginsDir'));
20
- return;
21
- }
22
- const jars = (await readdir(pluginsDir)).filter(f => f.endsWith('.jar'));
23
- if (isJson())
24
- json({ plugins: jars.map(j => ({ file: j })) });
25
- intro(`📁 ${t('plugin.titleInstalled')}`);
26
- if (jars.length === 0) {
27
- log.warn(t('plugin.noPlugins'));
28
- return;
29
- }
30
- const tracked = await getInstalled();
31
- for (const j of jars) {
32
- const meta = tracked.find(p => p.fileName === j);
33
- if (meta)
34
- log.raw(` ${c.accent('●')} ${c.bold(meta.name)} ${c.dim('v' + meta.version)}`);
35
- else
36
- log.raw(` ${c.dim('○')} ${j.replace('.jar', '')}`);
37
- }
38
- log.info(t('plugin.count', String(jars.length)));
39
- log.info(t('plugin.restartHint'));
40
- outro('');
41
- },
42
- });
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, isJson, json } from '../../ui/output.js';
6
+ import { c } from '../../ui/theme.js';
7
+ import { resolveServerDir } from '../../services/server.js';
8
+ import { getInstalled } from '../../services/plugins.js';
9
+ export const installedCmd = defineCommand({
10
+ meta: { description: 'List installed plugins' },
11
+ args: {},
12
+ async run() {
13
+ const serverPath = await resolveServerDir();
14
+ const pluginsDir = serverPath ? join(serverPath, 'plugins') : 'plugins';
15
+ if (!existsSync(pluginsDir)) {
16
+ if (isJson())
17
+ json({ plugins: [] });
18
+ log.warn("No plugins/ directory");
19
+ return;
20
+ }
21
+ const jars = (await readdir(pluginsDir)).filter(f => f.endsWith('.jar'));
22
+ if (isJson())
23
+ json({ plugins: jars.map(j => ({ file: j })) });
24
+ intro(`📁 ${"Installed plugins"}`);
25
+ if (jars.length === 0) {
26
+ log.warn("No plugins installed");
27
+ return;
28
+ }
29
+ const tracked = await getInstalled();
30
+ for (const j of jars) {
31
+ const meta = tracked.find(p => p.fileName === j);
32
+ if (meta)
33
+ log.raw(` ${c.accent('●')} ${c.bold(meta.name)} ${c.dim('v' + meta.version)}`);
34
+ else
35
+ log.raw(` ${c.dim('○')} ${j.replace('.jar', '')}`);
36
+ }
37
+ log.info(`${String(jars.length)} plugin(s)`);
38
+ log.info("Restart the server to load plugins");
39
+ outro('');
40
+ },
41
+ });
@@ -1,2 +1,2 @@
1
- import type { CommandDef } from 'citty';
2
- export declare const listCmd: CommandDef;
1
+ import type { CommandDef } from 'citty';
2
+ export declare const listCmd: CommandDef;
@@ -1,49 +1,47 @@
1
- import { defineCommand } from 'citty';
2
- import { intro, outro, log, spin, isJson, json } from '../../ui/output.js';
3
- import { c } from '../../ui/theme.js';
4
- import { searchPlugins } from '../../services/plugins.js';
5
- import { t } from '../../i18n/index.js';
6
- function stars(n) {
7
- const full = ''.repeat(Math.min(Math.floor(n / 10), 5));
8
- const empty = '☆'.repeat(5 - full.length);
9
- return (n >= 50 ? c.yellow : c.dim)(full + empty);
10
- }
11
- function dl(n) { return n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n); }
12
- /** Rendu partagé (utilisé par `list` et `search`). */
13
- export async function renderList(params) {
14
- const sp = spin(t('plugin.fetching'));
15
- try {
16
- const resp = await searchPlugins(params);
17
- sp.stop(`${resp.plugins.length} plugins`);
18
- if (isJson())
19
- json({ plugins: resp.plugins, count: resp.count });
20
- intro(`📋 ${t('plugin.titleList')}`);
21
- for (const p of resp.plugins) {
22
- log.raw(` ${c.accent.bold(p.name)} ${c.dim('by ' + p.author)} ${stars(p.stars)} ${c.cyan(dl(p.downloads) + ' dl')} ${c.dim('v' + p.version)}`);
23
- if (p.description)
24
- log.raw(` ${c.dim(p.description)}`);
25
- log.raw(` ${c.dim('→')} ${c.blue('pnx plugin install ' + p.slug)}\n`);
26
- }
27
- if (resp.count > resp.plugins.length)
28
- log.info(`${resp.plugins.length}/${resp.count}`);
29
- outro('');
30
- }
31
- catch (e) {
32
- sp.fail(t('plugin.fetchError', e.message));
33
- }
34
- }
35
- export const listCmd = defineCommand({
36
- meta: { description: 'List available plugins' },
37
- args: {
38
- sort: { type: 'string', description: 'Sort: newest|updated|stars' },
39
- limit: { type: 'string', description: 'Results per page', default: '20' },
40
- page: { type: 'string', description: 'Page number', default: '1' },
41
- query: { type: 'string', description: 'Search query' },
42
- },
43
- run: ({ args }) => renderList({
44
- sort: args.sort,
45
- limit: parseInt(args.limit),
46
- page: parseInt(args.page),
47
- q: args.query,
48
- }),
49
- });
1
+ import { defineCommand } from 'citty';
2
+ import { intro, outro, log, spin, isJson, json } from '../../ui/output.js';
3
+ import { c } from '../../ui/theme.js';
4
+ import { searchPlugins } from '../../services/plugins.js';
5
+ function stars(n) {
6
+ const full = '★'.repeat(Math.min(Math.floor(n / 10), 5));
7
+ const empty = ''.repeat(5 - full.length);
8
+ return (n >= 50 ? c.yellow : c.dim)(full + empty);
9
+ }
10
+ function dl(n) { return n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n); }
11
+ export async function renderList(params) {
12
+ const sp = spin("Fetching from marketplace...");
13
+ try {
14
+ const resp = await searchPlugins(params);
15
+ sp.stop(`${resp.plugins.length} plugins`);
16
+ if (isJson())
17
+ json({ plugins: resp.plugins, count: resp.count });
18
+ intro(`📋 ${"Plugin catalog"}`);
19
+ for (const p of resp.plugins) {
20
+ log.raw(` ${c.accent.bold(p.name)} ${c.dim('by ' + p.author)} ${stars(p.stars)} ${c.cyan(dl(p.downloads) + ' dl')} ${c.dim('v' + p.version)}`);
21
+ if (p.description)
22
+ log.raw(` ${c.dim(p.description)}`);
23
+ log.raw(` ${c.dim('→')} ${c.blue('pnx plugin install ' + p.slug)}\n`);
24
+ }
25
+ if (resp.count > resp.plugins.length)
26
+ log.info(`${resp.plugins.length}/${resp.count}`);
27
+ outro('');
28
+ }
29
+ catch (e) {
30
+ sp.fail(`Error: ${e.message}`);
31
+ }
32
+ }
33
+ export const listCmd = defineCommand({
34
+ meta: { description: 'List available plugins' },
35
+ args: {
36
+ sort: { type: 'string', description: 'Sort: newest|updated|stars' },
37
+ limit: { type: 'string', description: 'Results per page', default: '20' },
38
+ page: { type: 'string', description: 'Page number', default: '1' },
39
+ query: { type: 'string', description: 'Search query' },
40
+ },
41
+ run: ({ args }) => renderList({
42
+ sort: args.sort,
43
+ limit: parseInt(args.limit),
44
+ page: parseInt(args.page),
45
+ q: args.query,
46
+ }),
47
+ });
@@ -1,2 +1,2 @@
1
- import type { CommandDef } from 'citty';
2
- export declare const removeCmd: CommandDef;
1
+ import type { CommandDef } from 'citty';
2
+ export declare const removeCmd: CommandDef;
@@ -1,45 +1,44 @@
1
- import { existsSync } from 'node:fs';
2
- import { readdir, rm } from 'node:fs/promises';
3
- import { join } from 'node:path';
4
- import { defineCommand } from 'citty';
5
- import { intro, outro, log } from '../../ui/output.js';
6
- import { promptMulti, promptConfirm } from '../../ui/prompts.js';
7
- import { resolveServerDir } from '../../services/server.js';
8
- import { removeInstalled } from '../../services/plugins.js';
9
- import { t } from '../../i18n/index.js';
10
- export const removeCmd = defineCommand({
11
- meta: { description: 'Remove installed plugins' },
12
- args: { names: { type: 'positional', description: 'Plugin names', 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
- if (jars.length === 0) {
22
- log.warn(t('plugin.noPlugins'));
23
- return;
24
- }
25
- let names = args.names ? [args.names] : [];
26
- if (names.length === 0) {
27
- names = await promptMulti(t('plugin.selectRemove'), jars.map(j => ({ value: j, label: j.replace('.jar', '') })));
28
- }
29
- intro(`🗑️ ${t('plugin.titleRemove')}`);
30
- for (const name of names) {
31
- const target = name.endsWith('.jar') ? name : `${name}.jar`;
32
- const found = jars.find(j => j.toLowerCase() === target.toLowerCase());
33
- if (!found) {
34
- log.warn(t('plugin.notFound', name));
35
- continue;
36
- }
37
- if (await promptConfirm(t('plugin.removeConfirm', found), false)) {
38
- await rm(join(pluginsDir, found));
39
- await removeInstalled(found.replace('.jar', ''));
40
- log.success(t('plugin.removed', found));
41
- }
42
- }
43
- outro('');
44
- },
45
- });
1
+ import { existsSync } from 'node:fs';
2
+ import { readdir, rm } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { defineCommand } from 'citty';
5
+ import { intro, outro, log } from '../../ui/output.js';
6
+ import { promptMulti, promptConfirm } from '../../ui/prompts.js';
7
+ import { resolveServerDir } from '../../services/server.js';
8
+ import { removeInstalled } from '../../services/plugins.js';
9
+ export const removeCmd = defineCommand({
10
+ meta: { description: 'Remove installed plugins' },
11
+ args: { names: { type: 'positional', description: 'Plugin names', 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
+ if (jars.length === 0) {
21
+ log.warn("No plugins installed");
22
+ return;
23
+ }
24
+ let names = args.names ? [args.names] : [];
25
+ if (names.length === 0) {
26
+ names = await promptMulti("Select plugins to remove:", jars.map(j => ({ value: j, label: j.replace('.jar', '') })));
27
+ }
28
+ intro(`🗑️ ${"Remove plugins"}`);
29
+ for (const name of names) {
30
+ const target = name.endsWith('.jar') ? name : `${name}.jar`;
31
+ const found = jars.find(j => j.toLowerCase() === target.toLowerCase());
32
+ if (!found) {
33
+ log.warn(`Plugin not found: ${name}`);
34
+ continue;
35
+ }
36
+ if (await promptConfirm(`Remove ${found}?`, false)) {
37
+ await rm(join(pluginsDir, found));
38
+ await removeInstalled(found.replace('.jar', ''));
39
+ log.success(`${found} removed`);
40
+ }
41
+ }
42
+ outro('');
43
+ },
44
+ });
@@ -1,2 +1,2 @@
1
- import type { CommandDef } from 'citty';
2
- export declare const searchCmd: CommandDef;
1
+ import type { CommandDef } from 'citty';
2
+ export declare const searchCmd: CommandDef;
@@ -1,12 +1,11 @@
1
- import { defineCommand } from 'citty';
2
- import { promptText } from '../../ui/prompts.js';
3
- import { renderList } from './list.js';
4
- import { t } from '../../i18n/index.js';
5
- export const searchCmd = defineCommand({
6
- meta: { description: 'Search plugins' },
7
- args: { term: { type: 'positional', description: 'Search term', required: false } },
8
- async run({ args }) {
9
- const term = args.term ?? await promptText({ message: t('plugin.searchPrompt') });
10
- await renderList({ q: term, limit: 20, page: 1 });
11
- },
12
- });
1
+ import { defineCommand } from 'citty';
2
+ import { promptText } from '../../ui/prompts.js';
3
+ import { renderList } from './list.js';
4
+ export const searchCmd = defineCommand({
5
+ meta: { description: 'Search plugins' },
6
+ args: { term: { type: 'positional', description: 'Search term', required: false } },
7
+ async run({ args }) {
8
+ const term = args.term ?? await promptText({ message: "Search plugins:" });
9
+ await renderList({ q: term, limit: 20, page: 1 });
10
+ },
11
+ });
@@ -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;