cyclops-infobook-html 5.0.0 → 5.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.
Files changed (56) hide show
  1. package/README.md +35 -14
  2. package/bin/compress-icons.d.ts +2 -0
  3. package/bin/compress-icons.js +82 -0
  4. package/bin/convert-pom-to-modpack.d.ts +2 -0
  5. package/bin/convert-pom-to-modpack.js +96 -0
  6. package/bin/generate-icons.d.ts +2 -0
  7. package/bin/generate-icons.js +103 -0
  8. package/bin/generate-infobook-html.js +60 -16
  9. package/bin/generate-mod-metadata.js +62 -16
  10. package/index.d.ts +25 -23
  11. package/index.js +39 -24
  12. package/lib/icon/IconsCompressor.d.ts +18 -0
  13. package/lib/icon/IconsCompressor.js +112 -0
  14. package/lib/icon/IconsGenerator.d.ts +150 -0
  15. package/lib/icon/IconsGenerator.js +683 -0
  16. package/lib/infobook/FileWriter.d.ts +3 -4
  17. package/lib/infobook/FileWriter.js +15 -7
  18. package/lib/infobook/IFileWriter.d.ts +2 -3
  19. package/lib/infobook/IInfoAppendix.d.ts +3 -3
  20. package/lib/infobook/IInfoBook.d.ts +2 -4
  21. package/lib/infobook/IInfoSection.d.ts +1 -1
  22. package/lib/infobook/IInfobookPlugin.d.ts +5 -5
  23. package/lib/infobook/InfoBookInitializer.d.ts +7 -9
  24. package/lib/infobook/InfoBookInitializer.js +11 -3
  25. package/lib/infobook/appendix/IInfoBookAppendixHandler.d.ts +2 -2
  26. package/lib/infobook/appendix/InfoBookAppendixAd.d.ts +3 -3
  27. package/lib/infobook/appendix/InfoBookAppendixAd.js +17 -4
  28. package/lib/infobook/appendix/InfoBookAppendixHandlerAbstractRecipe.d.ts +12 -14
  29. package/lib/infobook/appendix/InfoBookAppendixHandlerAbstractRecipe.js +51 -10
  30. package/lib/infobook/appendix/InfoBookAppendixHandlerAdvancementRewards.d.ts +3 -3
  31. package/lib/infobook/appendix/InfoBookAppendixHandlerAdvancementRewards.js +15 -6
  32. package/lib/infobook/appendix/InfoBookAppendixHandlerCraftingRecipe.d.ts +6 -5
  33. package/lib/infobook/appendix/InfoBookAppendixHandlerCraftingRecipe.js +14 -5
  34. package/lib/infobook/appendix/InfoBookAppendixHandlerImage.d.ts +3 -3
  35. package/lib/infobook/appendix/InfoBookAppendixHandlerImage.js +14 -6
  36. package/lib/infobook/appendix/InfoBookAppendixHandlerKeybinding.d.ts +3 -3
  37. package/lib/infobook/appendix/InfoBookAppendixHandlerKeybinding.js +13 -4
  38. package/lib/infobook/appendix/InfoBookAppendixHandlerSmeltingRecipe.d.ts +6 -5
  39. package/lib/infobook/appendix/InfoBookAppendixHandlerSmeltingRecipe.js +13 -4
  40. package/lib/infobook/appendix/InfoBookAppendixHandlerTextfield.d.ts +3 -3
  41. package/lib/infobook/appendix/InfoBookAppendixHandlerTextfield.js +13 -6
  42. package/lib/infobook/appendix/InfoBookAppendixTagIndex.d.ts +4 -4
  43. package/lib/infobook/appendix/InfoBookAppendixTagIndex.js +12 -3
  44. package/lib/modloader/ModLoader.d.ts +15 -5
  45. package/lib/modloader/ModLoader.js +189 -86
  46. package/lib/modloader/PomConverter.d.ts +19 -0
  47. package/lib/modloader/PomConverter.js +138 -0
  48. package/lib/parse/XmlInfoBookParser.d.ts +5 -7
  49. package/lib/parse/XmlInfoBookParser.js +42 -9
  50. package/lib/resource/ResourceHandler.d.ts +7 -13
  51. package/lib/resource/ResourceHandler.js +16 -11
  52. package/lib/resource/ResourceLoader.d.ts +4 -5
  53. package/lib/resource/ResourceLoader.js +54 -44
  54. package/lib/serialize/HtmlInfoBookSerializer.d.ts +10 -16
  55. package/lib/serialize/HtmlInfoBookSerializer.js +102 -91
  56. package/package.json +35 -25
@@ -1,18 +1,62 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
2
47
  Object.defineProperty(exports, "__esModule", { value: true });
3
48
  exports.ModLoader = void 0;
4
- const tslib_1 = require("tslib");
5
- const child_process_1 = require("child_process");
6
- const fs_1 = require("fs");
7
- const fs = require("fs");
8
- const mvn_artifact_download_1 = require("mvn-artifact-download");
49
+ const node_child_process_1 = require("node:child_process");
50
+ const node_fs_1 = require("node:fs");
51
+ const fs = __importStar(require("node:fs"));
52
+ const Path = __importStar(require("node:path"));
53
+ const node_path_1 = require("node:path");
54
+ const node_util_1 = require("node:util");
55
+ const mvn_artifact_download_1 = __importDefault(require("mvn-artifact-download"));
9
56
  const ncp_1 = require("ncp");
10
- const node_fetch_1 = require("node-fetch");
11
- const path_1 = require("path");
12
- const rimraf = require("rimraf");
13
- const util_1 = require("util");
57
+ const node_fetch_1 = __importDefault(require("node-fetch"));
58
+ const rimraf_1 = __importDefault(require("rimraf"));
14
59
  const yauzl_1 = require("yauzl");
15
- const Path = require("path");
16
60
  /**
17
61
  * Takes care of installing Forge, installing mods, starting a Forge server, and fetching metadata.
18
62
  */
@@ -33,7 +77,7 @@ class ModLoader {
33
77
  * Download and install Forge.
34
78
  */
35
79
  installForge() {
36
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
80
+ return __awaiter(this, void 0, void 0, function* () {
37
81
  if (!fs.existsSync(this.path)) {
38
82
  yield fs.promises.mkdir(this.path);
39
83
  }
@@ -42,65 +86,77 @@ class ModLoader {
42
86
  // Download Forge installer
43
87
  process.stdout.write('Downloading Forge...\n');
44
88
  const forgeInstaller = `https://files.minecraftforge.net/maven/net/minecraftforge/forge/${this.versionMinecraft}-${this.loader.versionForge}/forge-${this.versionMinecraft}-${this.loader.versionForge}-installer.jar`;
45
- const res = yield node_fetch_1.default(forgeInstaller);
89
+ const res = yield (0, node_fetch_1.default)(forgeInstaller);
46
90
  if (!res.ok) {
47
91
  throw new Error(`Failed to fetch (${res.statusText}): ${forgeInstaller}`);
48
92
  }
49
- installerFile = path_1.join(this.path, 'forge-installer.jar');
50
- yield new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
51
- return fs.writeFile(installerFile, yield res.buffer(), (err) => err ? reject(err) : resolve());
93
+ installerFile = (0, node_path_1.join)(this.path, 'forge-installer.jar');
94
+ const forgeBuffer = yield res.buffer();
95
+ yield new Promise((resolve, reject) => fs.writeFile(installerFile, forgeBuffer, (err) => {
96
+ if (err) {
97
+ reject(err);
98
+ }
99
+ else {
100
+ resolve();
101
+ }
52
102
  }));
53
103
  // Install Forge
54
104
  process.stdout.write('Installing Forge...\n');
55
- yield new Promise((resolve, reject) => child_process_1.exec(`cd ${this.path} && java -jar forge-installer.jar --installServer`).on('exit', resolve));
105
+ yield new Promise(resolve => (0, node_child_process_1.exec)(`cd ${this.path} && java -jar forge-installer.jar --installServer`).on('exit', resolve));
56
106
  }
57
107
  else {
58
108
  // Download NeoForge installer
59
109
  process.stdout.write('Downloading NeoForge...\n');
60
110
  const installer = `https://maven.neoforged.net/releases/net/neoforged/neoforge/${this.loader.versionNeoForge}/neoforge-${this.loader.versionNeoForge}-installer.jar`;
61
- const res = yield node_fetch_1.default(installer);
111
+ const res = yield (0, node_fetch_1.default)(installer);
62
112
  if (!res.ok) {
63
113
  throw new Error(`Failed to fetch (${res.statusText}): ${installer}`);
64
114
  }
65
- installerFile = path_1.join(this.path, 'neoforge-installer.jar');
66
- yield new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
67
- return fs.writeFile(installerFile, yield res.buffer(), (err) => err ? reject(err) : resolve());
115
+ installerFile = (0, node_path_1.join)(this.path, 'neoforge-installer.jar');
116
+ const neoBuffer = yield res.buffer();
117
+ yield new Promise((resolve, reject) => fs.writeFile(installerFile, neoBuffer, (err) => {
118
+ if (err) {
119
+ reject(err);
120
+ }
121
+ else {
122
+ resolve();
123
+ }
68
124
  }));
69
125
  // Install Forge
70
126
  process.stdout.write('Installing NeoForge...\n');
71
- yield new Promise((resolve, reject) => child_process_1.exec(`cd ${this.path} && java -jar neoforge-installer.jar --installServer`).on('exit', resolve));
127
+ yield new Promise(resolve => (0, node_child_process_1.exec)(`cd ${this.path} && java -jar neoforge-installer.jar --installServer`).on('exit', resolve));
72
128
  }
73
129
  // Wait a bit, because otherwise some files don't exist yet (while they should...)
74
130
  process.stdout.write('Wait a bit after mod loader installation...\n');
75
- yield new Promise((resolve) => setTimeout(resolve, 10000));
131
+ yield new Promise(resolve => setTimeout(resolve, 10000));
76
132
  // Cleanup
77
133
  process.stdout.write('Cleaning up...\n');
78
134
  yield fs.promises.unlink(installerFile);
79
- yield fs.promises.unlink(installerFile + '.log');
135
+ yield fs.promises.unlink(`${installerFile}.log`);
80
136
  });
81
137
  }
82
138
  /**
83
139
  * Accept the Minecraft EULA
84
140
  */
85
141
  acceptEula() {
86
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
142
+ return __awaiter(this, void 0, void 0, function* () {
87
143
  process.stdout.write('Accepting EULA...\n');
88
- yield fs.promises.writeFile(path_1.join(this.path, 'eula.txt'), 'eula=true');
144
+ yield fs.promises.writeFile((0, node_path_1.join)(this.path, 'eula.txt'), 'eula=true');
89
145
  });
90
146
  }
91
147
  /**
92
148
  * @returns {boolean} If mods are installed.
93
149
  */
94
150
  areModsInstalled() {
95
- return fs.existsSync(path_1.join(this.path, 'mods'));
151
+ return fs.existsSync((0, node_path_1.join)(this.path, 'mods'));
96
152
  }
97
153
  /**
98
154
  * Download and install mods.
99
155
  */
100
156
  installMods() {
101
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
157
+ return __awaiter(this, void 0, void 0, function* () {
102
158
  process.stdout.write('Downloading mods...\n');
103
- const modsDir = path_1.join(this.path, 'mods');
159
+ const modsDir = (0, node_path_1.join)(this.path, 'mods');
104
160
  if (!fs.existsSync(modsDir)) {
105
161
  yield fs.promises.mkdir(modsDir);
106
162
  }
@@ -109,15 +165,22 @@ class ModLoader {
109
165
  const fileName = `${mod.artifact}-${mod.version}.jar`;
110
166
  process.stdout.write(` - ${fileName} from CurseForge...\n`);
111
167
  const url = `https://minecraft.curseforge.com/api/maven/${mod.project}/${mod.artifact
112
- .replace(/-/g, '/')}/${fileName}`;
168
+ .replaceAll('-', '/')}/${fileName}`;
113
169
  yield this.downloadFile(url, fileName, modsDir);
114
170
  }
115
171
  else if (mod.type === 'maven') {
116
172
  process.stdout.write(` - ${mod.artifact} from ${mod.repo}...\n`);
117
- const name = yield mvn_artifact_download_1.default(mod.artifact, modsDir, mod.repo);
173
+ let name;
174
+ if (mod.headers && Object.keys(mod.headers).length > 0) {
175
+ // Authenticated download: construct URL manually and use fetch with headers
176
+ name = yield this.downloadMavenArtifact(mod.artifact, mod.repo, modsDir, mod.headers);
177
+ }
178
+ else {
179
+ name = yield (0, mvn_artifact_download_1.default)(mod.artifact, modsDir, mod.repo);
180
+ }
118
181
  // Rename file if needed
119
182
  if ('name' in mod) {
120
- fs.renameSync(name, path_1.join(modsDir, mod.name));
183
+ fs.renameSync(name, (0, node_path_1.join)(modsDir, mod.name));
121
184
  }
122
185
  }
123
186
  else if (mod.type === 'raw') {
@@ -125,33 +188,72 @@ class ModLoader {
125
188
  yield this.downloadFile(mod.url, mod.name, modsDir);
126
189
  }
127
190
  else {
128
- throw new Error('Unknown mod type ' + mod.type);
191
+ throw new Error(`Unknown mod type ${mod.type}`);
129
192
  }
130
193
  }
131
194
  });
132
195
  }
133
- downloadFile(url, fileName, modsDir) {
134
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
135
- const response = yield node_fetch_1.default(url);
196
+ downloadFile(url, fileName, modsDir, headers) {
197
+ return __awaiter(this, void 0, void 0, function* () {
198
+ const response = yield (0, node_fetch_1.default)(url, headers ? { headers } : undefined);
136
199
  if (response.status !== 200) {
137
- throw new Error(response.statusText + ' on ' + url);
200
+ throw new Error(`${response.statusText} on ${url}`);
138
201
  }
139
202
  yield new Promise((resolve, reject) => {
140
203
  response.body
141
204
  .on('error', reject)
142
205
  .on('end', resolve)
143
- .pipe(fs.createWriteStream(path_1.join(modsDir, fileName)));
206
+ .pipe(fs.createWriteStream((0, node_path_1.join)(modsDir, fileName)));
144
207
  });
145
208
  });
146
209
  }
210
+ /**
211
+ * Download a Maven artifact by constructing the repository URL manually.
212
+ * This is used for authenticated repositories where custom headers are needed.
213
+ * @param artifact The Maven artifact coordinates (groupId:artifactId:version[:classifier]).
214
+ * @param repoUrl The base URL of the Maven repository.
215
+ * @param modsDir The directory to save the downloaded file.
216
+ * @param headers Optional HTTP headers (e.g., Authorization).
217
+ * @returns The full path to the downloaded file.
218
+ */
219
+ downloadMavenArtifact(artifact, repoUrl, modsDir, headers) {
220
+ return __awaiter(this, void 0, void 0, function* () {
221
+ const parts = artifact.split(':');
222
+ if (parts.length < 3) {
223
+ throw new Error(`Invalid Maven artifact: ${artifact}. Expected format: groupId:artifactId:version[:classifier]`);
224
+ }
225
+ const [groupId, artifactId, version, classifier] = parts;
226
+ const groupPath = groupId.replaceAll('.', '/');
227
+ const suffix = classifier ? `-${classifier}` : '';
228
+ const fileName = `${artifactId}-${version}${suffix}.jar`;
229
+ const base = repoUrl.endsWith('/') ? repoUrl : `${repoUrl}/`;
230
+ const url = `${base}${groupPath}/${artifactId}/${version}/${fileName}`;
231
+ // Expand environment variable placeholders in header values (e.g. ${GITHUB_TOKEN})
232
+ const resolvedHeaders = {};
233
+ if (headers) {
234
+ for (const [key, value] of Object.entries(headers)) {
235
+ resolvedHeaders[key] = value.replaceAll(/\$\{([^}]+)\}/gu, (fullMatch, name) => {
236
+ const envValue = process.env[name];
237
+ if (envValue === undefined) {
238
+ process.stderr.write(`Warning: environment variable '${name}' is not set; the request header '${key}' may be invalid\n`);
239
+ return fullMatch;
240
+ }
241
+ return envValue;
242
+ });
243
+ }
244
+ }
245
+ yield this.downloadFile(url, fileName, modsDir, resolvedHeaders);
246
+ return (0, node_path_1.join)(modsDir, fileName);
247
+ });
248
+ }
147
249
  /**
148
250
  * Start the server and execute a command to dump all registries
149
251
  */
150
252
  startServer() {
151
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
253
+ return __awaiter(this, void 0, void 0, function* () {
152
254
  // Start the Forge server
153
255
  process.stdout.write('Starting server...\n');
154
- const proc = child_process_1.exec(`cd ${this.path} && ./run.sh nogui`);
256
+ const proc = (0, node_child_process_1.exec)(`cd ${this.path} && ./run.sh nogui`);
155
257
  // Ignore stdout: proc.stdout.pipe(process.stdout);
156
258
  proc.stderr.pipe(process.stderr);
157
259
  const onDone = new Promise((resolve, reject) => {
@@ -160,14 +262,14 @@ class ModLoader {
160
262
  resolve();
161
263
  }
162
264
  else {
163
- reject('Server closed with non-zero exit code');
265
+ reject(new Error('Server closed with non-zero exit code'));
164
266
  }
165
267
  });
166
268
  proc.addListener('error', reject);
167
269
  });
168
270
  // Once the loading is complete, send our command and stop the server
169
271
  proc.stdout.on('data', (line) => {
170
- if (line.indexOf('Done') >= 0 && line.indexOf('For help, type "help"') >= 0) {
272
+ if (line.includes('Done') && line.includes('For help, type "help"')) {
171
273
  process.stdout.write('Dumping registries...\n');
172
274
  this.sendCommand(proc, '/cyclopscore dumpregistries');
173
275
  this.sendCommand(proc, '/stop');
@@ -182,29 +284,29 @@ class ModLoader {
182
284
  * @param {string} command A command.
183
285
  */
184
286
  sendCommand(proc, command) {
185
- proc.stdin.write(command + '\n');
287
+ proc.stdin.write(`${command}\n`);
186
288
  }
187
289
  /**
188
290
  * Copy the resulting registry files to a target path.
189
291
  * @param {string} target A target path.
190
292
  */
191
293
  copyRegistries(target) {
192
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
294
+ return __awaiter(this, void 0, void 0, function* () {
193
295
  process.stdout.write('Copying registries...\n');
194
- if (!fs.existsSync(path_1.join(this.path, 'cyclops_registries'))) {
195
- yield fs.promises.mkdir(path_1.join(this.path, 'cyclops_registries'));
296
+ if (!fs.existsSync((0, node_path_1.join)(this.path, 'cyclops_registries'))) {
297
+ yield fs.promises.mkdir((0, node_path_1.join)(this.path, 'cyclops_registries'));
196
298
  }
197
- yield util_1.promisify(ncp_1.ncp)(path_1.join(this.path, 'cyclops_registries'), target);
299
+ yield (0, node_util_1.promisify)(ncp_1.ncp)((0, node_path_1.join)(this.path, 'cyclops_registries'), target);
198
300
  });
199
301
  }
200
302
  /**
201
303
  * Extract the Minecraft assets from the server jar
202
304
  */
203
305
  extractMinecraftAssets() {
204
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
306
+ return __awaiter(this, void 0, void 0, function* () {
205
307
  process.stdout.write('Extracting minecraft assets...\n');
206
- if (!fs.existsSync(path_1.join(this.path, 'mc_assets'))) {
207
- yield fs.promises.mkdir(path_1.join(this.path, 'mc_assets'));
308
+ if (!fs.existsSync((0, node_path_1.join)(this.path, 'mc_assets'))) {
309
+ yield fs.promises.mkdir((0, node_path_1.join)(this.path, 'mc_assets'));
208
310
  }
209
311
  // Find Minecraft jar
210
312
  let jar = null;
@@ -213,14 +315,14 @@ class ModLoader {
213
315
  if (dir.indexOf('-') > 0) {
214
316
  for (const file of yield fs.promises.readdir(Path.join(subPath, dir))) {
215
317
  if (file.startsWith('server') && file.endsWith('extra.jar')) {
216
- jar = path_1.join(subPath, dir, file);
318
+ jar = (0, node_path_1.join)(subPath, dir, file);
217
319
  }
218
320
  }
219
321
  }
220
322
  }
221
323
  // Error if no jar was found
222
324
  if (!jar) {
223
- throw new Error('Could not find a valid minecraft server in ' + this.path);
325
+ throw new Error(`Could not find a valid minecraft server in ${this.path}`);
224
326
  }
225
327
  // Unzip the jar
226
328
  process.stdout.write(`Extracting Minecraft jar...\n`);
@@ -231,16 +333,16 @@ class ModLoader {
231
333
  * Extract assets from all mod jars
232
334
  */
233
335
  extractModsAssets() {
234
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
336
+ return __awaiter(this, void 0, void 0, function* () {
235
337
  process.stdout.write('Extracting mod assets...\n');
236
- if (!fs.existsSync(path_1.join(this.path, 'mod_assets'))) {
237
- yield fs.promises.mkdir(path_1.join(this.path, 'mod_assets'));
338
+ if (!fs.existsSync((0, node_path_1.join)(this.path, 'mod_assets'))) {
339
+ yield fs.promises.mkdir((0, node_path_1.join)(this.path, 'mod_assets'));
238
340
  }
239
341
  // Loop over all mods
240
- const modsDir = path_1.join(this.path, 'mods');
342
+ const modsDir = (0, node_path_1.join)(this.path, 'mods');
241
343
  for (const mod of yield fs.promises.readdir(modsDir)) {
242
344
  if (mod.endsWith('.jar')) {
243
- const modFile = path_1.join(modsDir, mod);
345
+ const modFile = (0, node_path_1.join)(modsDir, mod);
244
346
  process.stdout.write(` - ${mod}...\n`);
245
347
  yield this.extractModAssets(modFile);
246
348
  }
@@ -252,9 +354,9 @@ class ModLoader {
252
354
  * @param {string} modFile A mod file path.
253
355
  */
254
356
  extractModAssets(modFile) {
255
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
357
+ return __awaiter(this, void 0, void 0, function* () {
256
358
  const zipFile = yield new Promise((resolve, reject) => {
257
- yauzl_1.open(modFile, { lazyEntries: true, autoClose: true }, (e, f) => {
359
+ (0, yauzl_1.open)(modFile, { lazyEntries: true, autoClose: true }, (e, f) => {
258
360
  if (e) {
259
361
  reject(e);
260
362
  }
@@ -262,33 +364,34 @@ class ModLoader {
262
364
  });
263
365
  });
264
366
  zipFile.readEntry();
265
- zipFile.on('error', (e) => process.stdout.write(e));
367
+ zipFile.on('error', e => process.stdout.write(String(e)));
266
368
  zipFile.on('entry', (entry) => {
267
369
  if (entry.fileName.endsWith('/')) {
268
370
  // Directory
269
371
  zipFile.readEntry();
270
372
  }
271
- else {
373
+ else if (entry.fileName.startsWith('assets/') || entry.fileName.startsWith('data/')) {
272
374
  // File
273
- if (entry.fileName.startsWith('assets/') || entry.fileName.startsWith('data/')) {
274
- const targetFile = path_1.join(this.path, 'mod_assets', entry.fileName.substring(entry.fileName.startsWith('assets/') ? 7 : 5, entry.fileName.length));
275
- const targetDir = path_1.dirname(targetFile);
276
- this.ensureDirExists(targetDir).then(() => {
277
- zipFile.openReadStream(entry, (e, readStream) => {
278
- if (e) {
279
- throw e;
280
- }
281
- readStream.pipe(fs_1.createWriteStream(targetFile));
282
- readStream.on('end', () => zipFile.readEntry());
283
- });
375
+ const prefix = entry.fileName.startsWith('assets/') ? 7 : 5;
376
+ const targetFile = (0, node_path_1.join)(this.path, 'mod_assets', entry.fileName.slice(prefix, entry.fileName.length));
377
+ const targetDir = (0, node_path_1.dirname)(targetFile);
378
+ void this.ensureDirExists(targetDir).then(() => {
379
+ zipFile.openReadStream(entry, (e, readStream) => {
380
+ if (e) {
381
+ throw e;
382
+ }
383
+ readStream.pipe((0, node_fs_1.createWriteStream)(targetFile));
384
+ readStream.on('end', () => zipFile.readEntry());
284
385
  });
285
- }
286
- else {
287
- zipFile.readEntry();
288
- }
386
+ }).catch((e) => {
387
+ throw e;
388
+ });
389
+ }
390
+ else {
391
+ zipFile.readEntry();
289
392
  }
290
393
  });
291
- yield new Promise((resolve) => zipFile.on('end', resolve));
394
+ yield new Promise(resolve => zipFile.on('end', resolve));
292
395
  });
293
396
  }
294
397
  /**
@@ -296,36 +399,36 @@ class ModLoader {
296
399
  * @param {string} target A target path.
297
400
  */
298
401
  copyModAssets(target) {
299
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
402
+ return __awaiter(this, void 0, void 0, function* () {
300
403
  process.stdout.write('Copying mod assets...\n');
301
- yield util_1.promisify(ncp_1.ncp)(path_1.join(this.path, 'mod_assets'), target);
404
+ yield (0, node_util_1.promisify)(ncp_1.ncp)((0, node_path_1.join)(this.path, 'mod_assets'), target);
302
405
  });
303
406
  }
304
407
  /**
305
408
  * Remove the server files.
306
409
  */
307
410
  removeServer() {
308
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
309
- yield util_1.promisify(rimraf)(this.path);
411
+ return __awaiter(this, void 0, void 0, function* () {
412
+ yield (0, node_util_1.promisify)(rimraf_1.default)(this.path);
310
413
  });
311
414
  }
312
415
  /**
313
416
  * Remove the mod directory.
314
417
  */
315
418
  removeMods() {
316
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
317
- yield util_1.promisify(rimraf)(path_1.join(this.path, 'mods'));
419
+ return __awaiter(this, void 0, void 0, function* () {
420
+ yield (0, node_util_1.promisify)(rimraf_1.default)((0, node_path_1.join)(this.path, 'mods'));
318
421
  });
319
422
  }
320
423
  ensureDirExists(path) {
321
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
322
- const segments = path.substr(this.path.length, path.length).split(path_1.sep);
424
+ return __awaiter(this, void 0, void 0, function* () {
425
+ const segments = path.slice(this.path.length, this.path.length + path.length).split(node_path_1.sep);
323
426
  for (let i = 1; i <= segments.length; i++) {
324
- const subPath = path_1.join(this.path, segments.slice(0, i).join(path_1.sep));
427
+ const subPath = (0, node_path_1.join)(this.path, segments.slice(0, i).join(node_path_1.sep));
325
428
  try {
326
429
  yield fs.promises.stat(subPath);
327
430
  }
328
- catch (e) {
431
+ catch (_a) {
329
432
  yield fs.promises.mkdir(subPath);
330
433
  }
331
434
  }
@@ -0,0 +1,19 @@
1
+ export interface IModpackMod {
2
+ type: 'maven';
3
+ artifact: string;
4
+ repo: string;
5
+ headers?: Record<string, string>;
6
+ }
7
+ export interface IModpackJson {
8
+ minecraft: string;
9
+ neoforge?: string;
10
+ forge?: string;
11
+ mods: IModpackMod[];
12
+ }
13
+ /**
14
+ * Convert a Maven pom.xml (and optional settings.xml) into a modpack.json object.
15
+ * @param pomXml The contents of the pom.xml file.
16
+ * @param settingsXml The contents of the settings.xml file, or undefined.
17
+ * @returns The generated modpack.json object.
18
+ */
19
+ export declare function convertPomToModpack(pomXml: string, settingsXml: string | undefined): Promise<IModpackJson>;
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.convertPomToModpack = convertPomToModpack;
13
+ const node_util_1 = require("node:util");
14
+ const xml2js_1 = require("xml2js");
15
+ const parseStringPromise = (0, node_util_1.promisify)(xml2js_1.parseString);
16
+ /** Default Maven repository URL, used when no settings.xml is provided. */
17
+ const DEFAULT_MAVEN_REPO = 'https://repo.maven.apache.org/maven2';
18
+ /**
19
+ * Convert a Maven pom.xml (and optional settings.xml) into a modpack.json object.
20
+ * @param pomXml The contents of the pom.xml file.
21
+ * @param settingsXml The contents of the settings.xml file, or undefined.
22
+ * @returns The generated modpack.json object.
23
+ */
24
+ function convertPomToModpack(pomXml, settingsXml) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
27
+ const pomDoc = (yield parseStringPromise(pomXml));
28
+ const project = pomDoc.project;
29
+ // Extract Minecraft version from the project <version>
30
+ const minecraftVersion = project.version[0];
31
+ // Extract NeoForge/Forge version from <properties>
32
+ let neoforgeVersion;
33
+ let forgeVersion;
34
+ if ((_a = project.properties) === null || _a === void 0 ? void 0 : _a[0]) {
35
+ const props = project.properties[0];
36
+ if (props['neoforge.version']) {
37
+ neoforgeVersion = props['neoforge.version'][0];
38
+ }
39
+ if (props['forge.version']) {
40
+ forgeVersion = props['forge.version'][0];
41
+ }
42
+ }
43
+ // Parse settings.xml if provided
44
+ const activeProfileIds = new Set();
45
+ const repoMap = new Map();
46
+ const serverMap = new Map();
47
+ if (settingsXml) {
48
+ const settingsDoc = (yield parseStringPromise(settingsXml));
49
+ const settings = settingsDoc.settings;
50
+ // Collect active profile IDs
51
+ if ((_c = (_b = settings.activeProfiles) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.activeProfile) {
52
+ for (const id of settings.activeProfiles[0].activeProfile) {
53
+ activeProfileIds.add(id);
54
+ }
55
+ }
56
+ // Collect repositories from active profiles
57
+ if ((_e = (_d = settings.profiles) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.profile) {
58
+ for (const profile of settings.profiles[0].profile) {
59
+ const profileId = profile.id[0];
60
+ if (!activeProfileIds.has(profileId)) {
61
+ continue;
62
+ }
63
+ if ((_g = (_f = profile.repositories) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.repository) {
64
+ for (const repo of profile.repositories[0].repository) {
65
+ const repoId = repo.id[0];
66
+ const repoUrl = repo.url[0].replace(/\/$/u, '');
67
+ repoMap.set(repoId, { id: repoId, url: repoUrl });
68
+ }
69
+ }
70
+ }
71
+ }
72
+ // Collect server credentials
73
+ if ((_j = (_h = settings.servers) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.server) {
74
+ for (const server of settings.servers[0].server) {
75
+ const serverId = server.id[0];
76
+ const username = (_k = server.username) === null || _k === void 0 ? void 0 : _k[0];
77
+ const password = (_l = server.password) === null || _l === void 0 ? void 0 : _l[0];
78
+ serverMap.set(serverId, { id: serverId, username, password });
79
+ }
80
+ }
81
+ }
82
+ // Collect dependencies from pom.xml
83
+ const mods = [];
84
+ if ((_o = (_m = project.dependencies) === null || _m === void 0 ? void 0 : _m[0]) === null || _o === void 0 ? void 0 : _o.dependency) {
85
+ const repos = [...repoMap.values()];
86
+ for (const dep of project.dependencies[0].dependency) {
87
+ const groupId = dep.groupId[0];
88
+ const artifactId = dep.artifactId[0];
89
+ const version = dep.version[0];
90
+ const classifier = (_p = dep.classifier) === null || _p === void 0 ? void 0 : _p[0];
91
+ const artifact = classifier ?
92
+ `${groupId}:${artifactId}:${version}:${classifier}` :
93
+ `${groupId}:${artifactId}:${version}`;
94
+ // Determine repo: use the first active repo as default
95
+ const repo = (_q = repos[0]) !== null && _q !== void 0 ? _q : { id: 'central', url: DEFAULT_MAVEN_REPO };
96
+ const mod = {
97
+ type: 'maven',
98
+ artifact,
99
+ repo: repo.url,
100
+ };
101
+ // If the repo has a server entry with credentials, add auth headers
102
+ const server = serverMap.get(repo.id);
103
+ if (server === null || server === void 0 ? void 0 : server.password) {
104
+ // If the password is an environment variable placeholder (e.g. ${GITHUB_TOKEN}),
105
+ // use Bearer authentication to avoid having to base64-encode at generation time.
106
+ const passwordIsPlaceholder = /^\$\{[^}]+\}$/u.test(server.password);
107
+ const authHeaders = {};
108
+ if (passwordIsPlaceholder) {
109
+ authHeaders.Authorization = `Bearer ${server.password}`;
110
+ }
111
+ else {
112
+ // Literal credentials: encode as Basic auth
113
+ const credentials = Buffer
114
+ .from(`${(_r = server.username) !== null && _r !== void 0 ? _r : 'token'}:${server.password}`)
115
+ .toString('base64');
116
+ authHeaders.Authorization = `Basic ${credentials}`;
117
+ }
118
+ mod.headers = authHeaders;
119
+ }
120
+ mods.push(mod);
121
+ }
122
+ }
123
+ // Build the modpack.json output
124
+ const modpack = {
125
+ minecraft: minecraftVersion,
126
+ mods,
127
+ };
128
+ if (neoforgeVersion) {
129
+ modpack.neoforge = neoforgeVersion;
130
+ }
131
+ else if (forgeVersion) {
132
+ modpack.forge = forgeVersion;
133
+ }
134
+ // Reorder so minecraft/neoforge/forge come before mods
135
+ return Object.assign(Object.assign(Object.assign({ minecraft: modpack.minecraft }, (modpack.neoforge ? { neoforge: modpack.neoforge } : {})), (modpack.forge ? { forge: modpack.forge } : {})), { mods: modpack.mods });
136
+ });
137
+ }
138
+ //# sourceMappingURL=PomConverter.js.map