modpack-lock 0.5.0 → 0.5.1
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 +2 -2
- package/package.json +2 -2
- package/src/config/api.js +9 -0
- package/src/config/constants.js +3 -0
- package/src/generate_lockfile.js +65 -2
- package/src/github_interactions.js +14 -2
- package/src/modrinth_interactions.js +21 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<a href="https://www.npmjs.com/package/modpack-lock"><img alt="NPM: npmjs.com/package/modpack-lock" src="https://img.shields.io/npm/v/modpack-lock?style=for-the-badge&logo=npm&logoColor=white&label=npm&color=%23C12127&labelColor=%23505050"></a>
|
|
2
|
-
<a href="https://github.com/nickesc/modpack-lock"><img alt="Source:
|
|
3
|
-
<a href="https://github.com/nickesc/modpack-lock/actions/workflows/
|
|
2
|
+
<a href="https://github.com/nickesc/modpack-lock"><img alt="Source: github.com/nickesc/modpack-lock" src="https://img.shields.io/badge/source-github-brightgreen?style=for-the-badge&logo=github&labelColor=%23505050"></a>
|
|
3
|
+
<a href="https://github.com/nickesc/modpack-lock/actions/workflows/modpack-lock-tests.yml"><img alt="Tests: github.com/nickesc/modpack-lock/actions/workflows/modpack-lock-tests.yml" src="https://img.shields.io/github/actions/workflow/status/nickesc/modpack-lock/modpack-lock-tests.yml?logo=github&label=tests&logoColor=white&style=for-the-badge&labelColor=%23505050"></a>
|
|
4
4
|
|
|
5
5
|
# modpack-lock
|
|
6
6
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modpack-lock",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Creates a modpack lockfile for files hosted on Modrinth (mods, resource packs, shaders and datapacks)",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/nickesc/modpack-lock/issues"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"homepage": "https://nickesc.github.io/modpack-lock",
|
|
13
13
|
"license": "MIT",
|
|
14
|
-
"author": "N. Escobar <nick@
|
|
14
|
+
"author": "N. Escobar <nick@nickesc.io> (https://nickesc.github.io/)",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"main": "src/modpack-lock.js",
|
|
17
17
|
"bin": {
|
package/src/config/api.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import pkg from '../../package.json' with { type: 'json' };
|
|
2
|
+
import * as constants from './constants.js';
|
|
3
|
+
|
|
4
|
+
/** User-Agent header for Modrinth API requests */
|
|
5
|
+
export const PACKAGE_USER_AGENT = `${constants.AUTHOR_USERNAME}/${pkg.name}/${pkg.version}`;
|
|
6
|
+
|
|
1
7
|
/** Modrinth API base URL */
|
|
2
8
|
export const MODRINTH_API_BASE = 'https://api.modrinth.com/v2';
|
|
3
9
|
|
|
@@ -30,3 +36,6 @@ export const GITHUB_FEATURED_LICENSES_ENDPOINT = `${GITHUB_LICENSES_ENDPOINT}?fe
|
|
|
30
36
|
|
|
31
37
|
/** GitHub license endpoint */
|
|
32
38
|
export const GITHUB_LICENSE_ENDPOINT = (license) => `${GITHUB_API_BASE}/licenses/${license}`;
|
|
39
|
+
|
|
40
|
+
/** GitHub Accept request header */
|
|
41
|
+
export const GITHUB_ACCEPT_HEADER = 'application/vnd.github+json';
|
package/src/config/constants.js
CHANGED
package/src/generate_lockfile.js
CHANGED
|
@@ -71,7 +71,7 @@ async function writeLockfile(lockfile, outputPath) {
|
|
|
71
71
|
*/
|
|
72
72
|
function generateCategoryReadme(category, entries, projectsMap, usersMap) {
|
|
73
73
|
const categoryTitle = category.charAt(0).toUpperCase() + category.slice(1);
|
|
74
|
-
const lines = [`# ${categoryTitle}`, '', '| Name | Author | Version |', '
|
|
74
|
+
const lines = [`# ${categoryTitle}`, '', '| Name | Author | Version | Dependencies | Dependants |', '|-|-|-|-|-|'];
|
|
75
75
|
|
|
76
76
|
// Map category to Modrinth URL path segment
|
|
77
77
|
const categoryPathMap = {};
|
|
@@ -80,11 +80,21 @@ function generateCategoryReadme(category, entries, projectsMap, usersMap) {
|
|
|
80
80
|
}
|
|
81
81
|
const categoryPath = categoryPathMap[category] || 'project';
|
|
82
82
|
|
|
83
|
+
// Build a set of project_ids present in this category for filtering dependencies
|
|
84
|
+
const categoryProjectIds = new Set();
|
|
85
|
+
for (const entry of entries) {
|
|
86
|
+
if (entry.version && entry.version.project_id) {
|
|
87
|
+
categoryProjectIds.add(entry.version.project_id);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
83
91
|
for (const entry of entries) {
|
|
84
92
|
const version = entry.version;
|
|
85
93
|
let nameCell = '';
|
|
86
94
|
let authorCell = '';
|
|
87
95
|
let versionCell = '';
|
|
96
|
+
let dependenciesCell = '';
|
|
97
|
+
let dependantsCell = '';
|
|
88
98
|
|
|
89
99
|
if (version && version.project_id) {
|
|
90
100
|
const project = projectsMap[version.project_id];
|
|
@@ -123,15 +133,68 @@ function generateCategoryReadme(category, entries, projectsMap, usersMap) {
|
|
|
123
133
|
|
|
124
134
|
// Version column
|
|
125
135
|
versionCell = version.version_number || 'Unknown';
|
|
136
|
+
|
|
137
|
+
// Dependencies column - only show dependencies that are present in this category
|
|
138
|
+
if (version.dependencies && Array.isArray(version.dependencies) && version.dependencies.length > 0) {
|
|
139
|
+
const dependencyLinks = [];
|
|
140
|
+
for (const dep of version.dependencies) {
|
|
141
|
+
if (dep.project_id && categoryProjectIds.has(dep.project_id)) {
|
|
142
|
+
const depProject = projectsMap[dep.project_id];
|
|
143
|
+
if (depProject) {
|
|
144
|
+
const depProjectName = depProject.title || depProject.slug || 'Unknown';
|
|
145
|
+
const depProjectSlug = depProject.slug || depProject.id;
|
|
146
|
+
const depUrl = `https://modrinth.com/${categoryPath}/${depProjectSlug}`;
|
|
147
|
+
if (depProject.icon_url) {
|
|
148
|
+
dependencyLinks.push(`<a href="${depUrl}"><img alt="${depProjectName}" src="${depProject.icon_url}" height="20px"></a>`);
|
|
149
|
+
} else {
|
|
150
|
+
dependencyLinks.push(`[${depProjectName}](${depUrl})`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
dependenciesCell = dependencyLinks.length > 0 ? dependencyLinks.join(' ') : '-';
|
|
156
|
+
} else {
|
|
157
|
+
dependenciesCell = '-';
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Dependants column - find all entries in the same category that depend on this project
|
|
161
|
+
const dependants = [];
|
|
162
|
+
for (const catEntry of entries) {
|
|
163
|
+
// Skip if this is the same entry (same project_id)
|
|
164
|
+
if (catEntry.version && catEntry.version.project_id === version.project_id) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (catEntry.version && catEntry.version.dependencies && Array.isArray(catEntry.version.dependencies)) {
|
|
168
|
+
const hasDependency = catEntry.version.dependencies.some(
|
|
169
|
+
dep => dep.project_id === version.project_id
|
|
170
|
+
);
|
|
171
|
+
if (hasDependency) {
|
|
172
|
+
const depProject = projectsMap[catEntry.version.project_id];
|
|
173
|
+
if (depProject) {
|
|
174
|
+
const depProjectName = depProject.title || depProject.slug || 'Unknown';
|
|
175
|
+
const depProjectSlug = depProject.slug || depProject.id;
|
|
176
|
+
const depUrl = `https://modrinth.com/${categoryPath}/${depProjectSlug}`;
|
|
177
|
+
if (depProject.icon_url) {
|
|
178
|
+
dependants.push(`<a href="${depUrl}"><img alt="${depProjectName}" src="${depProject.icon_url}" height="20px"></a>`);
|
|
179
|
+
} else {
|
|
180
|
+
dependants.push(`[${depProjectName}](${depUrl})`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
dependantsCell = dependants.length > 0 ? dependants.join(' ') : '-';
|
|
126
187
|
} else {
|
|
127
188
|
// File not found on Modrinth
|
|
128
189
|
const fileName = path.basename(entry.path);
|
|
129
190
|
nameCell = fileName;
|
|
130
191
|
authorCell = 'Unknown';
|
|
131
192
|
versionCell = '-';
|
|
193
|
+
dependenciesCell = '-';
|
|
194
|
+
dependantsCell = '-';
|
|
132
195
|
}
|
|
133
196
|
|
|
134
|
-
lines.push(`| ${nameCell} | ${authorCell} | ${versionCell} |`);
|
|
197
|
+
lines.push(`| ${nameCell} | ${authorCell} | ${versionCell} | ${dependenciesCell} | ${dependantsCell} |`);
|
|
135
198
|
}
|
|
136
199
|
|
|
137
200
|
return lines.join('\n') + '\n';
|
|
@@ -9,7 +9,14 @@ import * as config from './config/index.js';
|
|
|
9
9
|
export async function getLicenseList(featured = false) {
|
|
10
10
|
try {
|
|
11
11
|
const url = featured ? config.GITHUB_FEATURED_LICENSES_ENDPOINT : config.GITHUB_LICENSES_ENDPOINT;
|
|
12
|
-
const response = await fetch(url
|
|
12
|
+
const response = await fetch(url,
|
|
13
|
+
{
|
|
14
|
+
headers: {
|
|
15
|
+
'Accept': config.GITHUB_ACCEPT_HEADER,
|
|
16
|
+
'User-Agent': config.PACKAGE_USER_AGENT
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
);
|
|
13
20
|
if (!response.ok) {
|
|
14
21
|
const errorText = await response.text();
|
|
15
22
|
throw new Error(`GitHub API error (${response.status}): ${errorText}`);
|
|
@@ -50,7 +57,12 @@ export async function getLicenseText(spdxId) {
|
|
|
50
57
|
}
|
|
51
58
|
try {
|
|
52
59
|
const url = config.GITHUB_LICENSE_ENDPOINT(spdxId.toLowerCase());
|
|
53
|
-
const response = await fetch(url
|
|
60
|
+
const response = await fetch(url, {
|
|
61
|
+
headers: {
|
|
62
|
+
'Accept': config.GITHUB_ACCEPT_HEADER,
|
|
63
|
+
'User-Agent': config.PACKAGE_USER_AGENT
|
|
64
|
+
},
|
|
65
|
+
});
|
|
54
66
|
if (!response.ok) {
|
|
55
67
|
const errorText = await response.text();
|
|
56
68
|
throw new Error(`GitHub API error (${response.status}): ${errorText}`);
|
|
@@ -24,6 +24,7 @@ export async function getVersionsFromHashes(hashes) {
|
|
|
24
24
|
method: 'POST',
|
|
25
25
|
headers: {
|
|
26
26
|
'Content-Type': 'application/json',
|
|
27
|
+
'User-Agent': config.PACKAGE_USER_AGENT,
|
|
27
28
|
},
|
|
28
29
|
body: JSON.stringify({
|
|
29
30
|
hashes: hashes,
|
|
@@ -57,7 +58,11 @@ export async function getProjects(projectIds) {
|
|
|
57
58
|
for (const chunk of chunks) {
|
|
58
59
|
try {
|
|
59
60
|
const url = `${config.MODRINTH_PROJECTS_ENDPOINT}?ids=${encodeURIComponent(JSON.stringify(chunk))}`;
|
|
60
|
-
const response = await fetch(url
|
|
61
|
+
const response = await fetch(url, {
|
|
62
|
+
headers: {
|
|
63
|
+
'User-Agent': config.PACKAGE_USER_AGENT,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
61
66
|
|
|
62
67
|
if (!response.ok) {
|
|
63
68
|
const errorText = await response.text();
|
|
@@ -89,7 +94,11 @@ export async function getUsers(userIds) {
|
|
|
89
94
|
for (const chunk of chunks) {
|
|
90
95
|
try {
|
|
91
96
|
const url = `${config.MODRINTH_USERS_ENDPOINT}?ids=${encodeURIComponent(JSON.stringify(chunk))}`;
|
|
92
|
-
const response = await fetch(url
|
|
97
|
+
const response = await fetch(url, {
|
|
98
|
+
headers: {
|
|
99
|
+
'User-Agent': config.PACKAGE_USER_AGENT,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
93
102
|
|
|
94
103
|
if (!response.ok) {
|
|
95
104
|
const errorText = await response.text();
|
|
@@ -114,7 +123,11 @@ export async function getUsers(userIds) {
|
|
|
114
123
|
export async function getMinecraftVersions() {
|
|
115
124
|
try {
|
|
116
125
|
const url = config.MODRINTH_MINECRAFT_VERSIONS_ENDPOINT;
|
|
117
|
-
const response = await fetch(url
|
|
126
|
+
const response = await fetch(url, {
|
|
127
|
+
headers: {
|
|
128
|
+
'User-Agent': config.PACKAGE_USER_AGENT,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
118
131
|
if (!response.ok) {
|
|
119
132
|
const errorText = await response.text();
|
|
120
133
|
throw new Error(`Modrinth API error (${response.status}): ${errorText}`);
|
|
@@ -144,7 +157,11 @@ export async function getMinecraftVersions() {
|
|
|
144
157
|
export async function getModloaders() {
|
|
145
158
|
try {
|
|
146
159
|
const url = config.MODRINTH_MODLOADERS_ENDPOINT;
|
|
147
|
-
const response = await fetch(url
|
|
160
|
+
const response = await fetch(url, {
|
|
161
|
+
headers: {
|
|
162
|
+
'User-Agent': config.PACKAGE_USER_AGENT,
|
|
163
|
+
},
|
|
164
|
+
});
|
|
148
165
|
if (!response.ok) {
|
|
149
166
|
const errorText = await response.text();
|
|
150
167
|
throw new Error(`Modrinth API error (${response.status}): ${errorText}`);
|