com.jimuwd.xian.registry-proxy 1.0.10 → 1.0.11

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/dist/index.js CHANGED
@@ -13,6 +13,7 @@ function resolvePath(path) {
13
13
  return path.startsWith('~/') ? join(homedir(), path.slice(2)) : resolve(path);
14
14
  }
15
15
  async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYarnConfigPath = './.yarnrc.yml', globalYarnConfigPath = join(homedir(), '.yarnrc.yml')) {
16
+ // 原有逻辑保持不变
16
17
  const resolvedProxyPath = resolvePath(proxyConfigPath);
17
18
  const resolvedLocalYarnPath = resolvePath(localYarnConfigPath);
18
19
  const resolvedGlobalYarnPath = resolvePath(globalYarnConfigPath);
@@ -101,12 +102,12 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
101
102
  return;
102
103
  }
103
104
  const fullUrl = new URL(req.url, `http://${req.headers.host}`);
104
- console.log(`Received request: ${fullUrl.pathname} (Full URL: ${fullUrl.href})`); // 增强日志
105
+ console.log(`Received request: ${fullUrl.pathname} (Full URL: ${fullUrl.href})`);
105
106
  const pathname = fullUrl.pathname;
106
107
  const fetchPromises = registries.map(async ({ url: registry, token }) => {
107
108
  const targetUrl = `${registry}${pathname}`;
108
109
  const headers = token ? { Authorization: `Bearer ${token}` } : undefined;
109
- console.log(`Fetching ${targetUrl} with headers:`, JSON.stringify(headers, null, 2)); // 打印完整 headers
110
+ console.log(`Fetching ${targetUrl} with headers:`, JSON.stringify(headers, null, 2));
110
111
  try {
111
112
  const response = await fetch(targetUrl, { headers });
112
113
  console.log(`Response from ${targetUrl}: ${response.status} ${response.statusText}`);
@@ -125,10 +126,36 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
125
126
  const successResponse = responses.find((r) => r?.ok);
126
127
  if (successResponse) {
127
128
  console.log(`Forwarding successful response from ${successResponse.url}: ${successResponse.status} ${successResponse.statusText}`);
128
- res.writeHead(successResponse.status, {
129
- 'Content-Type': successResponse.headers.get('Content-Type') || 'application/octet-stream',
130
- });
131
- successResponse.body?.pipe(res);
129
+ const contentType = successResponse.headers.get('Content-Type') || 'application/octet-stream';
130
+ // 检查是否为元数据(JSON 格式)
131
+ if (contentType.includes('application/json')) {
132
+ const jsonData = await successResponse.json();
133
+ const proxyBaseUrl = `http://localhost:${server.address().port}`;
134
+ // 修改 tarball 地址
135
+ if (jsonData.versions) {
136
+ for (const version in jsonData.versions) {
137
+ const dist = jsonData.versions[version].dist;
138
+ if (dist && dist.tarball) {
139
+ const originalTarball = dist.tarball;
140
+ // 将 tarball 地址替换为代理地址
141
+ const tarballPath = new URL(originalTarball).pathname; // 提取路径部分
142
+ dist.tarball = `${proxyBaseUrl}${tarballPath}`;
143
+ console.log(`Rewrote tarball URL from ${originalTarball} to ${dist.tarball}`);
144
+ }
145
+ }
146
+ }
147
+ // 返回修改后的 JSON
148
+ res.writeHead(successResponse.status, { 'Content-Type': 'application/json' });
149
+ res.end(JSON.stringify(jsonData));
150
+ }
151
+ else {
152
+ // 非 JSON 响应(例如 tarball 文件),直接转发
153
+ res.writeHead(successResponse.status, {
154
+ 'Content-Type': contentType,
155
+ 'Content-Length': successResponse.headers.get('Content-Length') || undefined,
156
+ });
157
+ successResponse.body?.pipe(res);
158
+ }
132
159
  }
133
160
  else {
134
161
  console.log('No successful response found, returning 404');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.jimuwd.xian.registry-proxy",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "type": "module",
5
5
  "description": "A lightweight npm registry proxy with fallback support",
6
6
  "main": "dist/index.js",
package/src/index.ts CHANGED
@@ -21,6 +21,7 @@ function resolvePath(path: string): string {
21
21
  }
22
22
 
23
23
  async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYarnConfigPath = './.yarnrc.yml', globalYarnConfigPath = join(homedir(), '.yarnrc.yml')): Promise<{ url: string; token?: string }[]> {
24
+ // 原有逻辑保持不变
24
25
  const resolvedProxyPath = resolvePath(proxyConfigPath);
25
26
  const resolvedLocalYarnPath = resolvePath(localYarnConfigPath);
26
27
  const resolvedGlobalYarnPath = resolvePath(globalYarnConfigPath);
@@ -119,13 +120,13 @@ export async function startProxyServer(proxyConfigPath?: string, localYarnConfig
119
120
  }
120
121
 
121
122
  const fullUrl = new URL(req.url, `http://${req.headers.host}`);
122
- console.log(`Received request: ${fullUrl.pathname} (Full URL: ${fullUrl.href})`); // 增强日志
123
+ console.log(`Received request: ${fullUrl.pathname} (Full URL: ${fullUrl.href})`);
123
124
  const pathname = fullUrl.pathname;
124
125
 
125
126
  const fetchPromises = registries.map(async ({ url: registry, token }) => {
126
127
  const targetUrl = `${registry}${pathname}`;
127
128
  const headers: Record<string, string> | undefined = token ? { Authorization: `Bearer ${token}` } : undefined;
128
- console.log(`Fetching ${targetUrl} with headers:`, JSON.stringify(headers, null, 2)); // 打印完整 headers
129
+ console.log(`Fetching ${targetUrl} with headers:`, JSON.stringify(headers, null, 2));
129
130
  try {
130
131
  const response = await fetch(targetUrl, { headers });
131
132
  console.log(`Response from ${targetUrl}: ${response.status} ${response.statusText}`);
@@ -145,10 +146,38 @@ export async function startProxyServer(proxyConfigPath?: string, localYarnConfig
145
146
 
146
147
  if (successResponse) {
147
148
  console.log(`Forwarding successful response from ${successResponse.url}: ${successResponse.status} ${successResponse.statusText}`);
148
- res.writeHead(successResponse.status, {
149
- 'Content-Type': successResponse.headers.get('Content-Type') || 'application/octet-stream',
150
- });
151
- successResponse.body?.pipe(res);
149
+ const contentType = successResponse.headers.get('Content-Type') || 'application/octet-stream';
150
+
151
+ // 检查是否为元数据(JSON 格式)
152
+ if (contentType.includes('application/json')) {
153
+ const jsonData:any = await successResponse.json();
154
+ const proxyBaseUrl = `http://localhost:${(server.address() as AddressInfo).port}`;
155
+
156
+ // 修改 tarball 地址
157
+ if (jsonData.versions) {
158
+ for (const version in jsonData.versions) {
159
+ const dist = jsonData.versions[version].dist;
160
+ if (dist && dist.tarball) {
161
+ const originalTarball = dist.tarball;
162
+ // 将 tarball 地址替换为代理地址
163
+ const tarballPath = new URL(originalTarball).pathname; // 提取路径部分
164
+ dist.tarball = `${proxyBaseUrl}${tarballPath}`;
165
+ console.log(`Rewrote tarball URL from ${originalTarball} to ${dist.tarball}`);
166
+ }
167
+ }
168
+ }
169
+
170
+ // 返回修改后的 JSON
171
+ res.writeHead(successResponse.status, { 'Content-Type': 'application/json' });
172
+ res.end(JSON.stringify(jsonData));
173
+ } else {
174
+ // 非 JSON 响应(例如 tarball 文件),直接转发
175
+ res.writeHead(successResponse.status, {
176
+ 'Content-Type': contentType,
177
+ 'Content-Length': successResponse.headers.get('Content-Length') || undefined,
178
+ });
179
+ successResponse.body?.pipe(res);
180
+ }
152
181
  } else {
153
182
  console.log('No successful response found, returning 404');
154
183
  res.writeHead(404, { 'Content-Type': 'text/plain' });