@ultikits/cli 1.0.1 → 1.2.0
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/README.md +27 -6
- package/dist/bin/ultikits.js +3 -1
- package/dist/src/commands/create.d.ts +2 -0
- package/dist/src/commands/create.js +95 -0
- package/dist/src/commands/modules.js +220 -1
- package/dist/src/lib/api-client.d.ts +1 -0
- package/dist/src/lib/api-client.js +12 -0
- package/dist/src/lib/templates.d.ts +9 -0
- package/dist/src/lib/templates.js +251 -0
- package/dist/src/types.d.ts +7 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,14 +13,13 @@ Requires Node.js 18 or later.
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
# 1.
|
|
17
|
-
ultikits
|
|
18
|
-
|
|
19
|
-
# 2. Initialize project config (optional, recommended)
|
|
20
|
-
ultikits init
|
|
16
|
+
# 1. Scaffold a new UltiTools module project
|
|
17
|
+
ultikits create
|
|
21
18
|
|
|
22
|
-
#
|
|
19
|
+
# 2. Build and publish to UltiCloud
|
|
20
|
+
cd MyModule
|
|
23
21
|
mvn clean package
|
|
22
|
+
ultikits login
|
|
24
23
|
ultikits publish
|
|
25
24
|
```
|
|
26
25
|
|
|
@@ -58,6 +57,28 @@ Credentials are stored in `~/.ultikits/credentials.json`.
|
|
|
58
57
|
|
|
59
58
|
## Commands
|
|
60
59
|
|
|
60
|
+
### `ultikits create`
|
|
61
|
+
|
|
62
|
+
Scaffold a new UltiTools module project. Interactive prompts collect module name, package name, description, author, and API version, then generate a complete project with:
|
|
63
|
+
|
|
64
|
+
- `pom.xml` — Maven build config with UltiTools-API dependency, test deps, JaCoCo
|
|
65
|
+
- `src/main/java/.../ModuleName.java` — Main class with `@UltiToolsModule` annotation
|
|
66
|
+
- `src/main/resources/plugin.yml` — Plugin descriptor
|
|
67
|
+
- `src/main/resources/lang/en.yml` and `zh.yml` — i18n language files
|
|
68
|
+
- `README.md` — Bilingual project readme
|
|
69
|
+
- `.gitignore` — Standard Java/Maven ignores
|
|
70
|
+
- `.git/` — Initialized git repository
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Create in current directory (prompts for module name)
|
|
74
|
+
ultikits create
|
|
75
|
+
|
|
76
|
+
# Create in a specific directory
|
|
77
|
+
ultikits create my-plugin-dir
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The generated project compiles immediately with `mvn compile`.
|
|
81
|
+
|
|
61
82
|
### `ultikits login`
|
|
62
83
|
|
|
63
84
|
Authenticate with UltiKits. Choose between browser-based magic link or pasting an access token.
|
package/dist/bin/ultikits.js
CHANGED
|
@@ -7,11 +7,12 @@ import { registerInitCommand } from '../src/commands/init.js';
|
|
|
7
7
|
import { registerPublishCommand } from '../src/commands/publish.js';
|
|
8
8
|
import { registerModulesCommand } from '../src/commands/modules.js';
|
|
9
9
|
import { registerVersionsCommand } from '../src/commands/versions.js';
|
|
10
|
+
import { registerCreateCommand } from '../src/commands/create.js';
|
|
10
11
|
const program = new Command();
|
|
11
12
|
program
|
|
12
13
|
.name('ultikits')
|
|
13
14
|
.description('CLI for publishing UltiTools plugin modules to UltiCloud')
|
|
14
|
-
.version('1.0
|
|
15
|
+
.version('1.2.0');
|
|
15
16
|
registerLoginCommand(program);
|
|
16
17
|
registerLogoutCommand(program);
|
|
17
18
|
registerWhoamiCommand(program);
|
|
@@ -19,5 +20,6 @@ registerInitCommand(program);
|
|
|
19
20
|
registerPublishCommand(program);
|
|
20
21
|
registerModulesCommand(program);
|
|
21
22
|
registerVersionsCommand(program);
|
|
23
|
+
registerCreateCommand(program);
|
|
22
24
|
program.parse();
|
|
23
25
|
//# sourceMappingURL=ultikits.js.map
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import { execFileSync } from 'node:child_process';
|
|
3
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import * as log from '../lib/logger.js';
|
|
6
|
+
import { derivePackageName, generatePomXml, generatePluginYml, generateMainClass, generateEnLang, generateZhLang, generateReadme, generateGitignore, } from '../lib/templates.js';
|
|
7
|
+
function getGitUserName() {
|
|
8
|
+
try {
|
|
9
|
+
return execFileSync('git', ['config', 'user.name'], { encoding: 'utf-8' }).trim();
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function registerCreateCommand(program) {
|
|
16
|
+
program
|
|
17
|
+
.command('create')
|
|
18
|
+
.argument('[directory]', 'Target directory name (defaults to module name)')
|
|
19
|
+
.description('Scaffold a new UltiTools module project')
|
|
20
|
+
.action(async (directory) => {
|
|
21
|
+
const answers = await inquirer.prompt([
|
|
22
|
+
{
|
|
23
|
+
type: 'input',
|
|
24
|
+
name: 'moduleName',
|
|
25
|
+
message: 'Module name (e.g., UltiHome):',
|
|
26
|
+
validate: (v) => /^[A-Z][a-zA-Z0-9]+$/.test(v)
|
|
27
|
+
? true
|
|
28
|
+
: 'Must start with uppercase letter, alphanumeric only',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: 'input',
|
|
32
|
+
name: 'packageName',
|
|
33
|
+
message: 'Java package name:',
|
|
34
|
+
default: (prev) => derivePackageName(prev.moduleName),
|
|
35
|
+
validate: (v) => /^[a-z][a-z0-9_.]*[a-z0-9]$/.test(v)
|
|
36
|
+
? true
|
|
37
|
+
: 'Must be a valid Java package name (lowercase, dots)',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
type: 'input',
|
|
41
|
+
name: 'description',
|
|
42
|
+
message: 'Short description:',
|
|
43
|
+
validate: (v) => (v.trim().length > 0 ? true : 'Required'),
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
type: 'input',
|
|
47
|
+
name: 'author',
|
|
48
|
+
message: 'Author:',
|
|
49
|
+
default: getGitUserName(),
|
|
50
|
+
validate: (v) => (v.trim().length > 0 ? true : 'Required'),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
type: 'input',
|
|
54
|
+
name: 'apiVersion',
|
|
55
|
+
message: 'UltiTools-API version:',
|
|
56
|
+
default: '6.2.2',
|
|
57
|
+
},
|
|
58
|
+
]);
|
|
59
|
+
const params = answers;
|
|
60
|
+
const targetDir = join(process.cwd(), directory ?? params.moduleName);
|
|
61
|
+
if (existsSync(targetDir)) {
|
|
62
|
+
log.error(`Directory already exists: ${targetDir}`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const spin = log.spinner('Creating project...');
|
|
66
|
+
spin.start();
|
|
67
|
+
const packagePath = params.packageName.replace(/\./g, '/');
|
|
68
|
+
const srcMain = join(targetDir, 'src/main/java', packagePath);
|
|
69
|
+
const srcTest = join(targetDir, 'src/test/java', packagePath);
|
|
70
|
+
const resources = join(targetDir, 'src/main/resources');
|
|
71
|
+
const langDir = join(resources, 'lang');
|
|
72
|
+
mkdirSync(srcMain, { recursive: true });
|
|
73
|
+
mkdirSync(srcTest, { recursive: true });
|
|
74
|
+
mkdirSync(langDir, { recursive: true });
|
|
75
|
+
writeFileSync(join(targetDir, 'pom.xml'), generatePomXml(params));
|
|
76
|
+
writeFileSync(join(resources, 'plugin.yml'), generatePluginYml(params));
|
|
77
|
+
writeFileSync(join(srcMain, `${params.moduleName}.java`), generateMainClass(params));
|
|
78
|
+
writeFileSync(join(langDir, 'en.yml'), generateEnLang(params));
|
|
79
|
+
writeFileSync(join(langDir, 'zh.yml'), generateZhLang(params));
|
|
80
|
+
writeFileSync(join(targetDir, 'README.md'), generateReadme(params));
|
|
81
|
+
writeFileSync(join(targetDir, '.gitignore'), generateGitignore());
|
|
82
|
+
try {
|
|
83
|
+
execFileSync('git', ['init'], { cwd: targetDir, stdio: 'ignore' });
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
log.warn('Could not initialize git repository');
|
|
87
|
+
}
|
|
88
|
+
spin.stop();
|
|
89
|
+
log.success(`Created ${params.moduleName} at ${targetDir}`);
|
|
90
|
+
log.info('Next steps:');
|
|
91
|
+
log.info(` cd ${directory ?? params.moduleName}`);
|
|
92
|
+
log.info(' mvn compile');
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
1
2
|
import inquirer from 'inquirer';
|
|
2
3
|
import { readCredentials } from '../lib/config.js';
|
|
3
4
|
import { ApiClient } from '../lib/api-client.js';
|
|
4
5
|
import * as log from '../lib/logger.js';
|
|
6
|
+
const CATEGORY_NAMES = {
|
|
7
|
+
1: 'Utilities',
|
|
8
|
+
2: 'Economy',
|
|
9
|
+
3: 'World Management',
|
|
10
|
+
4: 'Social & Chat',
|
|
11
|
+
5: 'Permissions & Security',
|
|
12
|
+
6: 'Gameplay',
|
|
13
|
+
};
|
|
5
14
|
export function registerModulesCommand(program) {
|
|
6
15
|
const modules = program
|
|
7
16
|
.command('modules')
|
|
@@ -43,14 +52,98 @@ export function registerModulesCommand(program) {
|
|
|
43
52
|
process.exit(1);
|
|
44
53
|
}
|
|
45
54
|
const mod = res.data;
|
|
55
|
+
const category = mod.categoryId ? (CATEGORY_NAMES[mod.categoryId] ?? `#${mod.categoryId}`) : 'N/A';
|
|
46
56
|
console.log();
|
|
47
57
|
console.log(` Name: ${mod.name}`);
|
|
48
58
|
console.log(` ID: ${mod.identifyString}`);
|
|
49
|
-
console.log(`
|
|
59
|
+
console.log(` Summary: ${mod.shortDescription || 'N/A'}`);
|
|
60
|
+
console.log(` Category: ${category}`);
|
|
61
|
+
console.log(` Compatible: ${mod.compatibleVersions || 'N/A'}`);
|
|
62
|
+
console.log(` Tags: ${mod.tags?.length ? mod.tags.join(', ') : 'N/A'}`);
|
|
50
63
|
console.log(` Downloads: ${mod.downloads ?? 0}`);
|
|
51
64
|
console.log(` Version: ${mod.latestVersion?.version ?? 'N/A'}`);
|
|
65
|
+
if (mod.description) {
|
|
66
|
+
const preview = mod.description.length > 200
|
|
67
|
+
? mod.description.slice(0, 200) + '...'
|
|
68
|
+
: mod.description;
|
|
69
|
+
console.log(` Description: ${preview.split('\n')[0]}`);
|
|
70
|
+
const lines = preview.split('\n').slice(1);
|
|
71
|
+
for (const line of lines) {
|
|
72
|
+
console.log(` ${line}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
console.log(` Description: N/A`);
|
|
77
|
+
}
|
|
52
78
|
console.log();
|
|
53
79
|
});
|
|
80
|
+
modules
|
|
81
|
+
.command('update <identifyString>')
|
|
82
|
+
.description('Update module metadata')
|
|
83
|
+
.option('--name <name>', 'Display name')
|
|
84
|
+
.option('--short-description <text>', 'Short description (one-liner)')
|
|
85
|
+
.option('--description <text>', 'Full description (Markdown)')
|
|
86
|
+
.option('--description-file <path>', 'Read full description from a file')
|
|
87
|
+
.option('--category <id>', 'Category ID (1-6)')
|
|
88
|
+
.option('--compatible-versions <range>', 'Compatible MC versions (e.g. "1.8-1.21+")')
|
|
89
|
+
.option('--tags <csv>', 'Comma-separated tags (max 5)')
|
|
90
|
+
.option('-y, --yes', 'Skip confirmation')
|
|
91
|
+
.action(async (identifyString, options) => {
|
|
92
|
+
const client = getClient();
|
|
93
|
+
const spin = log.spinner('Loading module...');
|
|
94
|
+
spin.start();
|
|
95
|
+
const infoRes = await client.get(`/plugin/get?identifyString=${identifyString}`);
|
|
96
|
+
if (infoRes.code !== '200' || !infoRes.data) {
|
|
97
|
+
spin.fail('Module not found: ' + identifyString);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
spin.succeed(`Found module: ${infoRes.data.name}`);
|
|
101
|
+
const mod = infoRes.data;
|
|
102
|
+
const hasFlags = options.name || options.shortDescription || options.description
|
|
103
|
+
|| options.descriptionFile || options.category || options.compatibleVersions || options.tags;
|
|
104
|
+
let updates;
|
|
105
|
+
if (hasFlags) {
|
|
106
|
+
updates = buildUpdatesFromFlags(options);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
updates = await promptForUpdates(mod);
|
|
110
|
+
}
|
|
111
|
+
if (Object.keys(updates).length === 0) {
|
|
112
|
+
log.info('No changes to apply.');
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Show summary
|
|
116
|
+
console.log();
|
|
117
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
118
|
+
const display = key === 'description'
|
|
119
|
+
? value.split('\n')[0].slice(0, 80) + (value.length > 80 ? '...' : '')
|
|
120
|
+
: key === 'tags'
|
|
121
|
+
? value.join(', ')
|
|
122
|
+
: String(value);
|
|
123
|
+
console.log(` ${key}: ${display}`);
|
|
124
|
+
}
|
|
125
|
+
console.log();
|
|
126
|
+
if (!options.yes) {
|
|
127
|
+
const { confirm } = await inquirer.prompt([
|
|
128
|
+
{
|
|
129
|
+
type: 'confirm',
|
|
130
|
+
name: 'confirm',
|
|
131
|
+
message: `Update module "${identifyString}"?`,
|
|
132
|
+
default: true,
|
|
133
|
+
},
|
|
134
|
+
]);
|
|
135
|
+
if (!confirm)
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const updateSpin = log.spinner('Updating module...');
|
|
139
|
+
updateSpin.start();
|
|
140
|
+
const res = await client.put(`/developer/modules/${mod.id}`, updates);
|
|
141
|
+
if (res.code !== '200') {
|
|
142
|
+
updateSpin.fail('Failed to update: ' + res.msg);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
updateSpin.succeed(`Updated module: ${identifyString}`);
|
|
146
|
+
});
|
|
54
147
|
modules
|
|
55
148
|
.command('delete <identifyString>')
|
|
56
149
|
.description('Delete a module')
|
|
@@ -80,6 +173,132 @@ export function registerModulesCommand(program) {
|
|
|
80
173
|
log.success(`Deleted module: ${identifyString}`);
|
|
81
174
|
});
|
|
82
175
|
}
|
|
176
|
+
function buildUpdatesFromFlags(options) {
|
|
177
|
+
const updates = {};
|
|
178
|
+
if (options.name)
|
|
179
|
+
updates.name = options.name;
|
|
180
|
+
if (options.shortDescription)
|
|
181
|
+
updates.shortDescription = options.shortDescription;
|
|
182
|
+
if (options.descriptionFile) {
|
|
183
|
+
const filePath = options.descriptionFile;
|
|
184
|
+
if (!fs.existsSync(filePath)) {
|
|
185
|
+
log.error(`File not found: ${filePath}`);
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
updates.description = fs.readFileSync(filePath, 'utf-8');
|
|
189
|
+
}
|
|
190
|
+
else if (options.description) {
|
|
191
|
+
updates.description = options.description;
|
|
192
|
+
}
|
|
193
|
+
if (options.category) {
|
|
194
|
+
const id = parseInt(options.category);
|
|
195
|
+
if (isNaN(id) || id < 1 || id > 6) {
|
|
196
|
+
log.error('Category must be 1-6');
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
updates.categoryId = id;
|
|
200
|
+
}
|
|
201
|
+
if (options.compatibleVersions)
|
|
202
|
+
updates.compatibleVersions = options.compatibleVersions;
|
|
203
|
+
if (options.tags) {
|
|
204
|
+
const tags = options.tags.split(',').map((t) => t.trim()).filter(Boolean);
|
|
205
|
+
if (tags.length > 5) {
|
|
206
|
+
log.error('Maximum 5 tags allowed');
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
updates.tags = tags;
|
|
210
|
+
}
|
|
211
|
+
return updates;
|
|
212
|
+
}
|
|
213
|
+
async function promptForUpdates(mod) {
|
|
214
|
+
const updates = {};
|
|
215
|
+
const { name } = await inquirer.prompt([{
|
|
216
|
+
type: 'input',
|
|
217
|
+
name: 'name',
|
|
218
|
+
message: 'Display name:',
|
|
219
|
+
default: mod.name,
|
|
220
|
+
}]);
|
|
221
|
+
if (name !== mod.name)
|
|
222
|
+
updates.name = name;
|
|
223
|
+
const { shortDesc } = await inquirer.prompt([{
|
|
224
|
+
type: 'input',
|
|
225
|
+
name: 'shortDesc',
|
|
226
|
+
message: 'Short description:',
|
|
227
|
+
default: mod.shortDescription || '',
|
|
228
|
+
}]);
|
|
229
|
+
if (shortDesc !== (mod.shortDescription || ''))
|
|
230
|
+
updates.shortDescription = shortDesc;
|
|
231
|
+
const { descMode } = await inquirer.prompt([{
|
|
232
|
+
type: 'list',
|
|
233
|
+
name: 'descMode',
|
|
234
|
+
message: 'Full description:',
|
|
235
|
+
choices: [
|
|
236
|
+
{ name: 'Keep current', value: 'keep' },
|
|
237
|
+
{ name: 'Enter text', value: 'text' },
|
|
238
|
+
{ name: 'Read from file', value: 'file' },
|
|
239
|
+
],
|
|
240
|
+
}]);
|
|
241
|
+
if (descMode === 'text') {
|
|
242
|
+
const { desc } = await inquirer.prompt([{
|
|
243
|
+
type: 'editor',
|
|
244
|
+
name: 'desc',
|
|
245
|
+
message: 'Enter description (opens editor):',
|
|
246
|
+
default: mod.description || '',
|
|
247
|
+
}]);
|
|
248
|
+
if (desc.trim())
|
|
249
|
+
updates.description = desc.trim();
|
|
250
|
+
}
|
|
251
|
+
else if (descMode === 'file') {
|
|
252
|
+
const { filePath } = await inquirer.prompt([{
|
|
253
|
+
type: 'input',
|
|
254
|
+
name: 'filePath',
|
|
255
|
+
message: 'File path:',
|
|
256
|
+
}]);
|
|
257
|
+
if (filePath && fs.existsSync(filePath)) {
|
|
258
|
+
updates.description = fs.readFileSync(filePath, 'utf-8');
|
|
259
|
+
}
|
|
260
|
+
else if (filePath) {
|
|
261
|
+
log.warn('File not found, skipping description.');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const { category } = await inquirer.prompt([{
|
|
265
|
+
type: 'list',
|
|
266
|
+
name: 'category',
|
|
267
|
+
message: 'Category:',
|
|
268
|
+
choices: [
|
|
269
|
+
{ name: `Keep current (${CATEGORY_NAMES[mod.categoryId] ?? 'N/A'})`, value: 0 },
|
|
270
|
+
...Object.entries(CATEGORY_NAMES).map(([id, label]) => ({
|
|
271
|
+
name: `${id}. ${label}`,
|
|
272
|
+
value: parseInt(id),
|
|
273
|
+
})),
|
|
274
|
+
],
|
|
275
|
+
}]);
|
|
276
|
+
if (category !== 0 && category !== mod.categoryId)
|
|
277
|
+
updates.categoryId = category;
|
|
278
|
+
const { compat } = await inquirer.prompt([{
|
|
279
|
+
type: 'input',
|
|
280
|
+
name: 'compat',
|
|
281
|
+
message: 'Compatible MC versions:',
|
|
282
|
+
default: mod.compatibleVersions || '',
|
|
283
|
+
}]);
|
|
284
|
+
if (compat !== (mod.compatibleVersions || ''))
|
|
285
|
+
updates.compatibleVersions = compat;
|
|
286
|
+
const currentTags = mod.tags?.join(', ') || '';
|
|
287
|
+
const { tags } = await inquirer.prompt([{
|
|
288
|
+
type: 'input',
|
|
289
|
+
name: 'tags',
|
|
290
|
+
message: 'Tags (comma-separated, max 5):',
|
|
291
|
+
default: currentTags,
|
|
292
|
+
}]);
|
|
293
|
+
const tagList = tags.split(',').map((t) => t.trim()).filter(Boolean);
|
|
294
|
+
if (tags !== currentTags && tagList.length <= 5) {
|
|
295
|
+
updates.tags = tagList;
|
|
296
|
+
}
|
|
297
|
+
else if (tagList.length > 5) {
|
|
298
|
+
log.warn('Too many tags (max 5), skipping.');
|
|
299
|
+
}
|
|
300
|
+
return updates;
|
|
301
|
+
}
|
|
83
302
|
function getClient() {
|
|
84
303
|
const credentials = readCredentials();
|
|
85
304
|
const client = ApiClient.fromEnvOrCredentials(credentials);
|
|
@@ -8,5 +8,6 @@ export declare class ApiClient {
|
|
|
8
8
|
get<T = any>(path: string): Promise<ApiResponse<T>>;
|
|
9
9
|
post<T = any>(path: string, body?: any): Promise<ApiResponse<T>>;
|
|
10
10
|
postMultipart<T = any>(path: string, formData: FormData, extraHeaders?: Record<string, string>): Promise<ApiResponse<T>>;
|
|
11
|
+
put<T = any>(path: string, body?: any): Promise<ApiResponse<T>>;
|
|
11
12
|
delete<T = any>(path: string): Promise<ApiResponse<T>>;
|
|
12
13
|
}
|
|
@@ -60,6 +60,18 @@ export class ApiClient {
|
|
|
60
60
|
});
|
|
61
61
|
return response.json();
|
|
62
62
|
}
|
|
63
|
+
async put(path, body) {
|
|
64
|
+
const headers = {
|
|
65
|
+
...this.getHeaders(),
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
};
|
|
68
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
69
|
+
method: 'PUT',
|
|
70
|
+
headers,
|
|
71
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
72
|
+
});
|
|
73
|
+
return response.json();
|
|
74
|
+
}
|
|
63
75
|
async delete(path) {
|
|
64
76
|
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
65
77
|
method: 'DELETE',
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CreateParams } from '../types.js';
|
|
2
|
+
export declare function derivePackageName(moduleName: string): string;
|
|
3
|
+
export declare function generatePomXml(params: CreateParams): string;
|
|
4
|
+
export declare function generatePluginYml(params: CreateParams): string;
|
|
5
|
+
export declare function generateMainClass(params: CreateParams): string;
|
|
6
|
+
export declare function generateEnLang(params: CreateParams): string;
|
|
7
|
+
export declare function generateZhLang(params: CreateParams): string;
|
|
8
|
+
export declare function generateReadme(params: CreateParams): string;
|
|
9
|
+
export declare function generateGitignore(): string;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
export function derivePackageName(moduleName) {
|
|
2
|
+
const lower = moduleName.toLowerCase();
|
|
3
|
+
const suffix = lower.startsWith('ulti') ? lower.slice(4) : lower;
|
|
4
|
+
return `com.ultikits.plugins.${suffix}`;
|
|
5
|
+
}
|
|
6
|
+
export function generatePomXml(params) {
|
|
7
|
+
const mv = (name) => '${' + name + '}';
|
|
8
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
9
|
+
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
10
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
11
|
+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
12
|
+
<modelVersion>4.0.0</modelVersion>
|
|
13
|
+
|
|
14
|
+
<groupId>com.ultikits.plugins</groupId>
|
|
15
|
+
<artifactId>${params.moduleName}</artifactId>
|
|
16
|
+
<version>1.0.0</version>
|
|
17
|
+
<packaging>jar</packaging>
|
|
18
|
+
|
|
19
|
+
<name>${params.moduleName}</name>
|
|
20
|
+
<description>${params.description}</description>
|
|
21
|
+
|
|
22
|
+
<properties>
|
|
23
|
+
<java.version>1.8</java.version>
|
|
24
|
+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
25
|
+
<ultitools.version>${params.apiVersion}</ultitools.version>
|
|
26
|
+
</properties>
|
|
27
|
+
|
|
28
|
+
<repositories>
|
|
29
|
+
<repository>
|
|
30
|
+
<id>spigot-repo</id>
|
|
31
|
+
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
|
32
|
+
</repository>
|
|
33
|
+
</repositories>
|
|
34
|
+
|
|
35
|
+
<dependencies>
|
|
36
|
+
<dependency>
|
|
37
|
+
<groupId>org.spigotmc</groupId>
|
|
38
|
+
<artifactId>spigot-api</artifactId>
|
|
39
|
+
<version>1.20.1-R0.1-SNAPSHOT</version>
|
|
40
|
+
<scope>provided</scope>
|
|
41
|
+
</dependency>
|
|
42
|
+
<dependency>
|
|
43
|
+
<groupId>com.ultikits</groupId>
|
|
44
|
+
<artifactId>UltiTools-API</artifactId>
|
|
45
|
+
<version>${mv('ultitools.version')}</version>
|
|
46
|
+
<scope>provided</scope>
|
|
47
|
+
</dependency>
|
|
48
|
+
<dependency>
|
|
49
|
+
<groupId>org.projectlombok</groupId>
|
|
50
|
+
<artifactId>lombok</artifactId>
|
|
51
|
+
<version>1.18.30</version>
|
|
52
|
+
<scope>provided</scope>
|
|
53
|
+
</dependency>
|
|
54
|
+
|
|
55
|
+
<!-- Test dependencies -->
|
|
56
|
+
<dependency>
|
|
57
|
+
<groupId>org.junit.jupiter</groupId>
|
|
58
|
+
<artifactId>junit-jupiter-engine</artifactId>
|
|
59
|
+
<version>5.10.0</version>
|
|
60
|
+
<scope>test</scope>
|
|
61
|
+
</dependency>
|
|
62
|
+
<dependency>
|
|
63
|
+
<groupId>org.junit.jupiter</groupId>
|
|
64
|
+
<artifactId>junit-jupiter-api</artifactId>
|
|
65
|
+
<version>5.10.0</version>
|
|
66
|
+
<scope>test</scope>
|
|
67
|
+
</dependency>
|
|
68
|
+
<dependency>
|
|
69
|
+
<groupId>org.junit.jupiter</groupId>
|
|
70
|
+
<artifactId>junit-jupiter-params</artifactId>
|
|
71
|
+
<version>5.10.0</version>
|
|
72
|
+
<scope>test</scope>
|
|
73
|
+
</dependency>
|
|
74
|
+
<dependency>
|
|
75
|
+
<groupId>org.mockito</groupId>
|
|
76
|
+
<artifactId>mockito-core</artifactId>
|
|
77
|
+
<version>5.5.0</version>
|
|
78
|
+
<scope>test</scope>
|
|
79
|
+
</dependency>
|
|
80
|
+
<dependency>
|
|
81
|
+
<groupId>org.mockito</groupId>
|
|
82
|
+
<artifactId>mockito-junit-jupiter</artifactId>
|
|
83
|
+
<version>5.5.0</version>
|
|
84
|
+
<scope>test</scope>
|
|
85
|
+
</dependency>
|
|
86
|
+
<dependency>
|
|
87
|
+
<groupId>org.assertj</groupId>
|
|
88
|
+
<artifactId>assertj-core</artifactId>
|
|
89
|
+
<version>3.24.2</version>
|
|
90
|
+
<scope>test</scope>
|
|
91
|
+
</dependency>
|
|
92
|
+
</dependencies>
|
|
93
|
+
|
|
94
|
+
<build>
|
|
95
|
+
<resources>
|
|
96
|
+
<resource>
|
|
97
|
+
<directory>src/main/resources</directory>
|
|
98
|
+
<filtering>true</filtering>
|
|
99
|
+
</resource>
|
|
100
|
+
</resources>
|
|
101
|
+
<plugins>
|
|
102
|
+
<plugin>
|
|
103
|
+
<groupId>org.apache.maven.plugins</groupId>
|
|
104
|
+
<artifactId>maven-compiler-plugin</artifactId>
|
|
105
|
+
<version>3.11.0</version>
|
|
106
|
+
<configuration>
|
|
107
|
+
<source>${mv('java.version')}</source>
|
|
108
|
+
<target>${mv('java.version')}</target>
|
|
109
|
+
<annotationProcessorPaths>
|
|
110
|
+
<path>
|
|
111
|
+
<groupId>org.projectlombok</groupId>
|
|
112
|
+
<artifactId>lombok</artifactId>
|
|
113
|
+
<version>1.18.30</version>
|
|
114
|
+
</path>
|
|
115
|
+
</annotationProcessorPaths>
|
|
116
|
+
</configuration>
|
|
117
|
+
</plugin>
|
|
118
|
+
<plugin>
|
|
119
|
+
<groupId>org.apache.maven.plugins</groupId>
|
|
120
|
+
<artifactId>maven-surefire-plugin</artifactId>
|
|
121
|
+
<version>3.1.2</version>
|
|
122
|
+
</plugin>
|
|
123
|
+
<plugin>
|
|
124
|
+
<groupId>org.jacoco</groupId>
|
|
125
|
+
<artifactId>jacoco-maven-plugin</artifactId>
|
|
126
|
+
<version>0.8.11</version>
|
|
127
|
+
<executions>
|
|
128
|
+
<execution>
|
|
129
|
+
<goals>
|
|
130
|
+
<goal>prepare-agent</goal>
|
|
131
|
+
</goals>
|
|
132
|
+
</execution>
|
|
133
|
+
<execution>
|
|
134
|
+
<id>report</id>
|
|
135
|
+
<phase>test</phase>
|
|
136
|
+
<goals>
|
|
137
|
+
<goal>report</goal>
|
|
138
|
+
</goals>
|
|
139
|
+
</execution>
|
|
140
|
+
</executions>
|
|
141
|
+
</plugin>
|
|
142
|
+
</plugins>
|
|
143
|
+
</build>
|
|
144
|
+
</project>
|
|
145
|
+
`;
|
|
146
|
+
}
|
|
147
|
+
export function generatePluginYml(params) {
|
|
148
|
+
return `name: ${params.moduleName}
|
|
149
|
+
version: '\${project.version}'
|
|
150
|
+
main: ${params.packageName}.${params.moduleName}
|
|
151
|
+
authors:
|
|
152
|
+
- ${params.author}
|
|
153
|
+
- UltiKits Team
|
|
154
|
+
description: ${params.description}
|
|
155
|
+
api-version: 620
|
|
156
|
+
loadAfter: []
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
159
|
+
export function generateMainClass(params) {
|
|
160
|
+
return `package ${params.packageName};
|
|
161
|
+
|
|
162
|
+
import com.ultikits.ultitools.abstracts.UltiToolsPlugin;
|
|
163
|
+
import com.ultikits.ultitools.annotations.UltiToolsModule;
|
|
164
|
+
|
|
165
|
+
import java.util.List;
|
|
166
|
+
import java.util.Arrays;
|
|
167
|
+
|
|
168
|
+
@UltiToolsModule(scanBasePackages = "${params.packageName}")
|
|
169
|
+
public class ${params.moduleName} extends UltiToolsPlugin {
|
|
170
|
+
|
|
171
|
+
@Override
|
|
172
|
+
public boolean registerSelf() {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@Override
|
|
177
|
+
public void unregisterSelf() {
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@Override
|
|
181
|
+
public void reloadSelf() {
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@Override
|
|
185
|
+
public List<String> supported() {
|
|
186
|
+
return Arrays.asList("en", "zh");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
`;
|
|
190
|
+
}
|
|
191
|
+
export function generateEnLang(params) {
|
|
192
|
+
return `# ${params.moduleName} - English language file
|
|
193
|
+
|
|
194
|
+
module_enabled: "${params.moduleName} has been enabled."
|
|
195
|
+
module_disabled: "${params.moduleName} has been disabled."
|
|
196
|
+
`;
|
|
197
|
+
}
|
|
198
|
+
export function generateZhLang(params) {
|
|
199
|
+
return `# ${params.moduleName} - 中文语言文件
|
|
200
|
+
|
|
201
|
+
module_enabled: "${params.moduleName} 已启用。"
|
|
202
|
+
module_disabled: "${params.moduleName} 已禁用。"
|
|
203
|
+
`;
|
|
204
|
+
}
|
|
205
|
+
export function generateReadme(params) {
|
|
206
|
+
return `# ${params.moduleName}
|
|
207
|
+
|
|
208
|
+
${params.description}
|
|
209
|
+
|
|
210
|
+
## Installation
|
|
211
|
+
|
|
212
|
+
1. Download the latest release JAR
|
|
213
|
+
2. Place it in \`plugins/UltiTools/plugins/\` directory
|
|
214
|
+
3. Restart the server
|
|
215
|
+
|
|
216
|
+
## 安装
|
|
217
|
+
|
|
218
|
+
1. 下载最新版本的 JAR 文件
|
|
219
|
+
2. 将其放入 \`plugins/UltiTools/plugins/\` 目录
|
|
220
|
+
3. 重启服务器
|
|
221
|
+
|
|
222
|
+
## Requirements
|
|
223
|
+
|
|
224
|
+
- Minecraft 1.21+
|
|
225
|
+
- UltiTools-API ${params.apiVersion}+
|
|
226
|
+
|
|
227
|
+
## License
|
|
228
|
+
|
|
229
|
+
MIT
|
|
230
|
+
`;
|
|
231
|
+
}
|
|
232
|
+
export function generateGitignore() {
|
|
233
|
+
return `target/
|
|
234
|
+
*.class
|
|
235
|
+
*.jar
|
|
236
|
+
*.log
|
|
237
|
+
|
|
238
|
+
# IDE
|
|
239
|
+
.idea/
|
|
240
|
+
*.iml
|
|
241
|
+
.vscode/
|
|
242
|
+
.settings/
|
|
243
|
+
.project
|
|
244
|
+
.classpath
|
|
245
|
+
|
|
246
|
+
# OS
|
|
247
|
+
.DS_Store
|
|
248
|
+
Thumbs.db
|
|
249
|
+
`;
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=templates.js.map
|
package/dist/src/types.d.ts
CHANGED