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 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: Github" 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/generateLockfile-tests.yml"><img alt="Tests: github.com/nickesc/modpack-lock/actions/workflows/generateLockfile-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>
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.0",
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@nescobar.media> (https://nickesc.github.io/)",
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';
@@ -1,5 +1,8 @@
1
1
  import pkg from '../../package.json' with { type: 'json' };
2
2
 
3
+ /** Author username */
4
+ export const AUTHOR_USERNAME = 'nickesc';
5
+
3
6
  /** Lockfile format version -- increment on changes to the format */
4
7
  export const LOCKFILE_VERSION = "1.0.1";
5
8
 
@@ -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}`);