com.jimuwd.xian.registry-proxy 1.0.25 → 1.0.27

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 (3) hide show
  1. package/dist/index.js +25 -25
  2. package/package.json +1 -1
  3. package/src/index.ts +22 -26
package/dist/index.js CHANGED
@@ -34,49 +34,49 @@ class ConcurrencyLimiter {
34
34
  }
35
35
  }
36
36
  const limiter = new ConcurrencyLimiter(3);
37
- function removeEndingSlashButReserveStartingSlash(str) {
37
+ function removeEndingSlashAndForceStartingSlash(str) {
38
38
  if (!str)
39
39
  return '/';
40
- if (str === '/')
40
+ let trimmed = str.trim();
41
+ if (trimmed === '/')
41
42
  return '/';
42
- return str.replace(/\/+$/, '');
43
+ if (trimmed === '')
44
+ return '/';
45
+ if (!trimmed.startsWith('/'))
46
+ trimmed = '/' + trimmed;
47
+ return trimmed.replace(/\/+$/, '');
43
48
  }
44
- function normalizeUrl(url) {
49
+ function normalizeUrl(httpOrHttpsUrl) {
50
+ if (!httpOrHttpsUrl.startsWith("http"))
51
+ throw new Error("http(s) url must starts with 'http(s)://'");
45
52
  try {
46
- const urlObj = new URL(url);
53
+ const urlObj = new URL(httpOrHttpsUrl);
47
54
  if (urlObj.protocol === 'http:' && (urlObj.port === '80' || urlObj.port === '')) {
48
55
  urlObj.port = '';
49
56
  }
50
57
  else if (urlObj.protocol === 'https:' && (urlObj.port === '443' || urlObj.port === '')) {
51
58
  urlObj.port = '';
52
59
  }
53
- urlObj.pathname = removeEndingSlashButReserveStartingSlash(urlObj.pathname);
54
- return urlObj.toString();
60
+ return urlObj.toString().replace(/\/+$/, '');
55
61
  }
56
62
  catch (e) {
57
- console.error(`Invalid URL: ${url}`, e);
58
- return url.replace(/\/+$/, '');
63
+ throw new Error(`Invalid URL: ${httpOrHttpsUrl}`, { cause: e });
59
64
  }
60
65
  }
61
66
  function resolvePath(path) {
62
67
  return path.startsWith('~/') ? join(homedir(), path.slice(2)) : resolve(path);
63
68
  }
64
69
  function removeRegistryPrefix(tarballUrl, registries) {
65
- try {
66
- const normalizedTarball = normalizeUrl(tarballUrl);
67
- const normalizedRegistries = registries
68
- .map(r => normalizeUrl(r.url))
69
- .sort((a, b) => b.length - a.length);
70
- for (const normalizedRegistry of normalizedRegistries) {
71
- if (normalizedTarball.startsWith(normalizedRegistry)) {
72
- return normalizedTarball.slice(normalizedRegistry.length) || '/';
73
- }
70
+ const normalizedTarball = normalizeUrl(tarballUrl);
71
+ const normalizedRegistries = registries
72
+ .map(r => normalizeUrl(r.url))
73
+ .sort((a, b) => b.length - a.length);
74
+ for (const normalizedRegistry of normalizedRegistries) {
75
+ if (normalizedTarball.startsWith(normalizedRegistry)) {
76
+ return normalizedTarball.slice(normalizedRegistry.length) || '/';
74
77
  }
75
78
  }
76
- catch (e) {
77
- console.error(`Invalid URL in removeRegistryPrefix: ${tarballUrl}`, e);
78
- }
79
- return tarballUrl;
79
+ throw new Error(`Can't find tarball url ${tarballUrl} does not match given registries ${normalizedRegistries}`);
80
80
  }
81
81
  async function loadProxyConfig(proxyConfigPath = './.registry-proxy.yml') {
82
82
  const resolvedPath = resolvePath(proxyConfigPath);
@@ -143,7 +143,7 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
143
143
  return;
144
144
  }
145
145
  const fullUrl = new URL(req.url, `${proxyConfig.https ? 'https' : 'http'}://${req.headers.host}`);
146
- if (basePathPrefixedWithSlash && !fullUrl.pathname.startsWith(basePathPrefixedWithSlash)) {
146
+ if (!fullUrl.pathname.startsWith(basePathPrefixedWithSlash)) {
147
147
  console.error(`Path ${fullUrl.pathname} does not match basePath ${basePathPrefixedWithSlash}`);
148
148
  res.writeHead(404).end('Not Found');
149
149
  return;
@@ -194,8 +194,8 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
194
194
  const originalSearchParamsStr = originalUrl.search || '';
195
195
  const tarballPathPrefixedWithSlash = removeRegistryPrefix(dist.tarball, registries);
196
196
  dist.tarball = `${proxyBaseUrlNoSuffixedWithSlash}${tarballPathPrefixedWithSlash}${originalSearchParamsStr}`;
197
- console.log("tarballPathPrefixedWithSlash", tarballPathPrefixedWithSlash);
198
- console.log("dist.tarballUrl", dist.tarball);
197
+ if (!tarballPathPrefixedWithSlash.startsWith("/"))
198
+ console.error("bad tarballPath, must be PrefixedWithSlash", tarballPathPrefixedWithSlash);
199
199
  }
200
200
  }
201
201
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.jimuwd.xian.registry-proxy",
3
- "version": "1.0.25",
3
+ "version": "1.0.27",
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
@@ -74,25 +74,27 @@ class ConcurrencyLimiter {
74
74
 
75
75
  const limiter = new ConcurrencyLimiter(3);
76
76
 
77
- function removeEndingSlashButReserveStartingSlash(str: string): string {
77
+ function removeEndingSlashAndForceStartingSlash(str: string): string {
78
78
  if (!str) return '/';
79
- if (str === '/') return '/';
80
- return str.replace(/\/+$/, '');
79
+ let trimmed = str.trim();
80
+ if (trimmed === '/') return '/';
81
+ if (trimmed === '') return '/';
82
+ if (!trimmed.startsWith('/')) trimmed = '/' + trimmed;
83
+ return trimmed.replace(/\/+$/, '');
81
84
  }
82
85
 
83
- function normalizeUrl(url: string): string {
86
+ function normalizeUrl(httpOrHttpsUrl: string): string {
87
+ if (!httpOrHttpsUrl.startsWith("http")) throw new Error("http(s) url must starts with 'http(s)://'");
84
88
  try {
85
- const urlObj = new URL(url);
89
+ const urlObj = new URL(httpOrHttpsUrl);
86
90
  if (urlObj.protocol === 'http:' && (urlObj.port === '80' || urlObj.port === '')) {
87
91
  urlObj.port = '';
88
92
  } else if (urlObj.protocol === 'https:' && (urlObj.port === '443' || urlObj.port === '')) {
89
93
  urlObj.port = '';
90
94
  }
91
- urlObj.pathname = removeEndingSlashButReserveStartingSlash(urlObj.pathname);
92
- return urlObj.toString();
95
+ return urlObj.toString().replace(/\/+$/, '');
93
96
  } catch (e) {
94
- console.error(`Invalid URL: ${url}`, e);
95
- return url.replace(/\/+$/, '');
97
+ throw new Error(`Invalid URL: ${httpOrHttpsUrl}`, {cause: e});
96
98
  }
97
99
  }
98
100
 
@@ -101,21 +103,16 @@ function resolvePath(path: string): string {
101
103
  }
102
104
 
103
105
  function removeRegistryPrefix(tarballUrl: string, registries: RegistryInfo[]): string {
104
- try {
105
- const normalizedTarball = normalizeUrl(tarballUrl);
106
- const normalizedRegistries = registries
107
- .map(r => normalizeUrl(r.url))
108
- .sort((a, b) => b.length - a.length);
109
-
110
- for (const normalizedRegistry of normalizedRegistries) {
111
- if (normalizedTarball.startsWith(normalizedRegistry)) {
112
- return normalizedTarball.slice(normalizedRegistry.length) || '/';
113
- }
106
+ const normalizedTarball = normalizeUrl(tarballUrl);
107
+ const normalizedRegistries = registries
108
+ .map(r => normalizeUrl(r.url))
109
+ .sort((a, b) => b.length - a.length);
110
+ for (const normalizedRegistry of normalizedRegistries) {
111
+ if (normalizedTarball.startsWith(normalizedRegistry)) {
112
+ return normalizedTarball.slice(normalizedRegistry.length) || '/';
114
113
  }
115
- } catch (e) {
116
- console.error(`Invalid URL in removeRegistryPrefix: ${tarballUrl}`, e);
117
114
  }
118
- return tarballUrl;
115
+ throw new Error(`Can't find tarball url ${tarballUrl} does not match given registries ${normalizedRegistries}`)
119
116
  }
120
117
 
121
118
  async function loadProxyConfig(proxyConfigPath = './.registry-proxy.yml'): Promise<ProxyConfig> {
@@ -183,7 +180,7 @@ export async function startProxyServer(
183
180
  ): Promise<HttpServer | HttpsServer> {
184
181
  const proxyConfig = await loadProxyConfig(proxyConfigPath);
185
182
  const registries = await loadRegistries(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath);
186
- const basePathPrefixedWithSlash = proxyConfig.basePath ? `/${proxyConfig.basePath.replace(/^\/|\/$/g, '')}` : '/';
183
+ const basePathPrefixedWithSlash: string = proxyConfig.basePath ? `/${proxyConfig.basePath.replace(/^\/|\/$/g, '')}` : '/';
187
184
 
188
185
  console.log('Active registries:', registries.map(r => r.url));
189
186
  console.log('Proxy base path:', basePathPrefixedWithSlash);
@@ -199,7 +196,7 @@ export async function startProxyServer(
199
196
  }
200
197
 
201
198
  const fullUrl = new URL(req.url, `${proxyConfig.https ? 'https' : 'http'}://${req.headers.host}`);
202
- if (basePathPrefixedWithSlash && !fullUrl.pathname.startsWith(basePathPrefixedWithSlash)) {
199
+ if (!fullUrl.pathname.startsWith(basePathPrefixedWithSlash)) {
203
200
  console.error(`Path ${fullUrl.pathname} does not match basePath ${basePathPrefixedWithSlash}`);
204
201
  res.writeHead(404).end('Not Found');
205
202
  return;
@@ -252,8 +249,7 @@ export async function startProxyServer(
252
249
  const originalSearchParamsStr = originalUrl.search || '';
253
250
  const tarballPathPrefixedWithSlash = removeRegistryPrefix(dist.tarball, registries);
254
251
  dist.tarball = `${proxyBaseUrlNoSuffixedWithSlash}${tarballPathPrefixedWithSlash}${originalSearchParamsStr}`;
255
- console.log("tarballPathPrefixedWithSlash", tarballPathPrefixedWithSlash);
256
- console.log("dist.tarballUrl", dist.tarball);
252
+ if (!tarballPathPrefixedWithSlash.startsWith("/")) console.error("bad tarballPath, must be PrefixedWithSlash", tarballPathPrefixedWithSlash);
257
253
  }
258
254
  }
259
255
  }