cyclops-infobook-html 5.2.0 → 5.2.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.
@@ -52,7 +52,6 @@ const fs = __importStar(require("node:fs"));
52
52
  const Path = __importStar(require("node:path"));
53
53
  const node_path_1 = require("node:path");
54
54
  const node_util_1 = require("node:util");
55
- const mvn_artifact_download_1 = __importDefault(require("mvn-artifact-download"));
56
55
  const ncp_1 = require("ncp");
57
56
  const node_fetch_1 = __importDefault(require("node-fetch"));
58
57
  const rimraf_1 = __importDefault(require("rimraf"));
@@ -170,14 +169,7 @@ class ModLoader {
170
169
  }
171
170
  else if (mod.type === 'maven') {
172
171
  process.stdout.write(` - ${mod.artifact} from ${mod.repo}...\n`);
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
- }
172
+ const name = yield this.downloadMavenArtifact(mod.artifact, mod.repo, modsDir, mod.headers);
181
173
  // Rename file if needed
182
174
  if ('name' in mod) {
183
175
  fs.renameSync(name, (0, node_path_1.join)(modsDir, mod.name));
@@ -1,3 +1,12 @@
1
+ /**
2
+ * Build the URL for a Maven artifact JAR in a repository.
3
+ */
4
+ export declare function buildMavenArtifactUrl(groupId: string, artifactId: string, version: string, classifier: string | undefined, repoUrl: string): string;
5
+ /**
6
+ * Check if a Maven artifact exists in a repository by sending an HTTP HEAD request.
7
+ * Returns true if the server responds with a 2xx status, false otherwise.
8
+ */
9
+ export declare function artifactExistsInRepo(groupId: string, artifactId: string, version: string, classifier: string | undefined, repoUrl: string, headers?: Record<string, string>): Promise<boolean>;
1
10
  export interface IModpackMod {
2
11
  type: 'maven';
3
12
  artifact: string;
@@ -8,13 +8,70 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.buildMavenArtifactUrl = buildMavenArtifactUrl;
16
+ exports.artifactExistsInRepo = artifactExistsInRepo;
12
17
  exports.convertPomToModpack = convertPomToModpack;
13
18
  const node_util_1 = require("node:util");
19
+ const node_fetch_1 = __importDefault(require("node-fetch"));
14
20
  const xml2js_1 = require("xml2js");
15
21
  const parseStringPromise = (0, node_util_1.promisify)(xml2js_1.parseString);
16
22
  /** Default Maven repository URL, used when no settings.xml is provided. */
17
- const DEFAULT_MAVEN_REPO = 'https://repo.maven.apache.org/maven2';
23
+ const DEFAULT_MAVEN_REPO = 'https://repo.maven.apache.org/maven2/';
24
+ /**
25
+ * Build the URL for a Maven artifact JAR in a repository.
26
+ */
27
+ function buildMavenArtifactUrl(groupId, artifactId, version, classifier, repoUrl) {
28
+ const groupPath = groupId.replaceAll('.', '/');
29
+ const suffix = classifier ? `-${classifier}` : '';
30
+ const fileName = `${artifactId}-${version}${suffix}.jar`;
31
+ const base = repoUrl.endsWith('/') ? repoUrl : `${repoUrl}/`;
32
+ return `${base}${groupPath}/${artifactId}/${version}/${fileName}`;
33
+ }
34
+ /**
35
+ * Check if a Maven artifact exists in a repository by sending an HTTP HEAD request.
36
+ * Returns true if the server responds with a 2xx status, false otherwise.
37
+ */
38
+ function artifactExistsInRepo(groupId, artifactId, version, classifier, repoUrl, headers) {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ const url = buildMavenArtifactUrl(groupId, artifactId, version, classifier, repoUrl);
41
+ try {
42
+ const response = yield (0, node_fetch_1.default)(url, { method: 'HEAD', headers: headers !== null && headers !== void 0 ? headers : {} });
43
+ return response.ok;
44
+ }
45
+ catch (_a) {
46
+ return false;
47
+ }
48
+ });
49
+ }
50
+ /**
51
+ * Build Authorization headers for a server entry.
52
+ * Returns a Bearer header for placeholder passwords, or a Basic header for literal credentials.
53
+ * Returns an empty object if no password is configured.
54
+ */
55
+ function buildAuthHeaders(server) {
56
+ var _a;
57
+ if (!(server === null || server === void 0 ? void 0 : server.password)) {
58
+ return {};
59
+ }
60
+ const headers = {};
61
+ // If the password is an environment variable placeholder (e.g. ${GITHUB_TOKEN}),
62
+ // use Bearer authentication to avoid having to base64-encode at generation time.
63
+ if (/^\$\{[^}]+\}$/u.test(server.password)) {
64
+ headers.Authorization = `Bearer ${server.password}`;
65
+ }
66
+ else {
67
+ // Literal credentials: encode as Basic auth
68
+ const credentials = Buffer
69
+ .from(`${(_a = server.username) !== null && _a !== void 0 ? _a : 'token'}:${server.password}`)
70
+ .toString('base64');
71
+ headers.Authorization = `Basic ${credentials}`;
72
+ }
73
+ return headers;
74
+ }
18
75
  /**
19
76
  * Convert a Maven pom.xml (and optional settings.xml) into a modpack.json object.
20
77
  * @param pomXml The contents of the pom.xml file.
@@ -23,7 +80,7 @@ const DEFAULT_MAVEN_REPO = 'https://repo.maven.apache.org/maven2';
23
80
  */
24
81
  function convertPomToModpack(pomXml, settingsXml) {
25
82
  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;
83
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
27
84
  const pomDoc = (yield parseStringPromise(pomXml));
28
85
  const project = pomDoc.project;
29
86
  // Extract Minecraft version from the project <version>
@@ -63,7 +120,8 @@ function convertPomToModpack(pomXml, settingsXml) {
63
120
  if ((_g = (_f = profile.repositories) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.repository) {
64
121
  for (const repo of profile.repositories[0].repository) {
65
122
  const repoId = repo.id[0];
66
- const repoUrl = repo.url[0].replace(/\/$/u, '');
123
+ const rawUrl = repo.url[0];
124
+ const repoUrl = rawUrl.endsWith('/') ? rawUrl : `${rawUrl}/`;
67
125
  repoMap.set(repoId, { id: repoId, url: repoUrl });
68
126
  }
69
127
  }
@@ -91,8 +149,21 @@ function convertPomToModpack(pomXml, settingsXml) {
91
149
  const artifact = classifier ?
92
150
  `${groupId}:${artifactId}:${version}:${classifier}` :
93
151
  `${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 };
152
+ // Determine repo: when multiple repos are configured, probe each one in order
153
+ // and use the first that has the artifact (mirrors Maven's repository resolution).
154
+ // When only one repo is configured, skip probing and use it directly.
155
+ let repo = (_q = repos[0]) !== null && _q !== void 0 ? _q : { id: 'central', url: DEFAULT_MAVEN_REPO };
156
+ if (repos.length > 1) {
157
+ for (const candidateRepo of repos) {
158
+ const candidateServer = serverMap.get(candidateRepo.id);
159
+ const probeHeaders = buildAuthHeaders(candidateServer);
160
+ const found = yield artifactExistsInRepo(groupId, artifactId, version, classifier, candidateRepo.url, probeHeaders);
161
+ if (found) {
162
+ repo = candidateRepo;
163
+ break;
164
+ }
165
+ }
166
+ }
96
167
  const mod = {
97
168
  type: 'maven',
98
169
  artifact,
@@ -101,21 +172,7 @@ function convertPomToModpack(pomXml, settingsXml) {
101
172
  // If the repo has a server entry with credentials, add auth headers
102
173
  const server = serverMap.get(repo.id);
103
174
  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;
175
+ mod.headers = buildAuthHeaders(server);
119
176
  }
120
177
  mods.push(mod);
121
178
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyclops-infobook-html",
3
- "version": "5.2.0",
3
+ "version": "5.2.2",
4
4
  "description": "Output Cyclops infobooks as HTML",
5
5
  "author": "Ruben Taelman <rubensworks@gmail.com>",
6
6
  "license": "MIT",