com.jimuwd.xian.registry-proxy 1.0.29 → 1.0.30

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 +22 -18
  2. package/package.json +1 -1
  3. package/src/index.ts +30 -22
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createServer } from 'http';
3
3
  import { createServer as createHttpsServer } from 'https';
4
- import { readFileSync, promises as fsPromises } from 'fs';
4
+ import { promises as fsPromises, readFileSync } from 'fs';
5
5
  import { load } from 'js-yaml';
6
6
  import fetch from 'node-fetch';
7
7
  import { homedir } from 'os';
@@ -78,13 +78,14 @@ function removeRegistryPrefix(tarballUrl, registries) {
78
78
  }
79
79
  throw new Error(`Can't find tarball url ${tarballUrl} does not match given registries ${normalizedRegistries}`);
80
80
  }
81
- async function loadProxyConfig(proxyConfigPath = './.registry-proxy.yml') {
81
+ async function readProxyConfig(proxyConfigPath = './.registry-proxy.yml') {
82
82
  const resolvedPath = resolvePath(proxyConfigPath);
83
83
  try {
84
84
  const content = await readFile(resolvedPath, 'utf8');
85
85
  const config = load(content);
86
86
  if (!config.registries) {
87
- throw new Error('Missing required "registries" field in config');
87
+ console.error('Missing required "registries" field in config');
88
+ process.exit(1);
88
89
  }
89
90
  return config;
90
91
  }
@@ -93,7 +94,7 @@ async function loadProxyConfig(proxyConfigPath = './.registry-proxy.yml') {
93
94
  process.exit(1);
94
95
  }
95
96
  }
96
- async function loadYarnConfig(path) {
97
+ async function readYarnConfig(path) {
97
98
  try {
98
99
  const content = await readFile(resolvePath(path), 'utf8');
99
100
  return load(content);
@@ -103,11 +104,11 @@ async function loadYarnConfig(path) {
103
104
  return {};
104
105
  }
105
106
  }
106
- async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYarnConfigPath = './.yarnrc.yml', globalYarnConfigPath = join(homedir(), '.yarnrc.yml')) {
107
+ async function loadProxyInfo(proxyConfigPath = './.registry-proxy.yml', localYarnConfigPath = './.yarnrc.yml', globalYarnConfigPath = join(homedir(), '.yarnrc.yml')) {
107
108
  const [proxyConfig, localYarnConfig, globalYarnConfig] = await Promise.all([
108
- loadProxyConfig(proxyConfigPath),
109
- loadYarnConfig(localYarnConfigPath),
110
- loadYarnConfig(globalYarnConfigPath)
109
+ readProxyConfig(proxyConfigPath),
110
+ readYarnConfig(localYarnConfigPath),
111
+ readYarnConfig(globalYarnConfigPath)
111
112
  ]);
112
113
  const registryMap = new Map();
113
114
  for (const [url, regConfig] of Object.entries(proxyConfig.registries)) {
@@ -126,15 +127,18 @@ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYa
126
127
  }
127
128
  registryMap.set(normalizedUrl, { url: normalizedUrl, token });
128
129
  }
129
- return Array.from(registryMap.values());
130
+ const registries = Array.from(registryMap.values());
131
+ const https = proxyConfig.https;
132
+ const basePath = removeEndingSlashAndForceStartingSlash(proxyConfig.basePath);
133
+ return { registries, https, basePath };
130
134
  }
131
135
  export async function startProxyServer(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath, port = 0) {
132
- const proxyConfig = await loadProxyConfig(proxyConfigPath);
133
- const registries = await loadRegistries(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath);
134
- const basePathPrefixedWithSlash = removeEndingSlashAndForceStartingSlash(proxyConfig.basePath);
136
+ const proxyInfo = await loadProxyInfo(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath);
137
+ const registries = proxyInfo.registries;
138
+ const basePathPrefixedWithSlash = removeEndingSlashAndForceStartingSlash(proxyInfo.basePath);
135
139
  console.log('Active registries:', registries.map(r => r.url));
136
140
  console.log('Proxy base path:', basePathPrefixedWithSlash);
137
- console.log('HTTPS:', !!proxyConfig.https);
141
+ console.log('HTTPS:', !!proxyInfo.https);
138
142
  let proxyPort;
139
143
  const requestHandler = async (req, res) => {
140
144
  if (!req.url || !req.headers.host) {
@@ -142,7 +146,7 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
142
146
  res.writeHead(400).end('Invalid Request');
143
147
  return;
144
148
  }
145
- const fullUrl = new URL(req.url, `${proxyConfig.https ? 'https' : 'http'}://${req.headers.host}`);
149
+ const fullUrl = new URL(req.url, `${proxyInfo.https ? 'https' : 'http'}://${req.headers.host}`);
146
150
  console.log(`Proxy server received request on ${fullUrl.toString()}`);
147
151
  if (!fullUrl.pathname.startsWith(basePathPrefixedWithSlash)) {
148
152
  console.error(`Path ${fullUrl.pathname} does not match basePath ${basePathPrefixedWithSlash}`);
@@ -184,7 +188,7 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
184
188
  if (data.versions) {
185
189
  const requestHeadersHostFromYarnClient = req.headers.host || 'localhost:' + proxyPort;
186
190
  console.log("Request headers.host from yarn client is", requestHeadersHostFromYarnClient);
187
- const proxyBaseUrlNoSuffixedWithSlash = `${proxyConfig.https ? 'https' : 'http'}://${requestHeadersHostFromYarnClient}${basePathPrefixedWithSlash === '/' ? '' : basePathPrefixedWithSlash}`;
191
+ const proxyBaseUrlNoSuffixedWithSlash = `${proxyInfo.https ? 'https' : 'http'}://${requestHeadersHostFromYarnClient}${basePathPrefixedWithSlash === '/' ? '' : basePathPrefixedWithSlash}`;
188
192
  console.log("proxyBaseUrlNoSuffixedWithSlash", proxyBaseUrlNoSuffixedWithSlash);
189
193
  for (const version in data.versions) {
190
194
  const dist = data.versions[version]?.dist;
@@ -225,8 +229,8 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
225
229
  }
226
230
  };
227
231
  let server;
228
- if (proxyConfig.https) {
229
- const { key, cert } = proxyConfig.https;
232
+ if (proxyInfo.https) {
233
+ const { key, cert } = proxyInfo.https;
230
234
  const keyPath = resolvePath(key);
231
235
  const certPath = resolvePath(cert);
232
236
  try {
@@ -260,7 +264,7 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
260
264
  proxyPort = address.port;
261
265
  const portFile = join(process.env.PROJECT_ROOT || process.cwd(), '.registry-proxy-port');
262
266
  writeFile(portFile, proxyPort.toString()).catch(e => console.error('Failed to write port file:', e));
263
- console.log(`Proxy server running on ${proxyConfig.https ? 'https' : 'http'}://localhost:${proxyPort}${basePathPrefixedWithSlash}`);
267
+ console.log(`Proxy server running on ${proxyInfo.https ? 'https' : 'http'}://localhost:${proxyPort}${basePathPrefixedWithSlash}`);
264
268
  resolve(server);
265
269
  });
266
270
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.jimuwd.xian.registry-proxy",
3
- "version": "1.0.29",
3
+ "version": "1.0.30",
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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import {createServer, Server as HttpServer, IncomingMessage, ServerResponse, OutgoingHttpHeaders} from 'http';
2
+ import {createServer, IncomingMessage, OutgoingHttpHeaders, Server as HttpServer, ServerResponse} from 'http';
3
3
  import {createServer as createHttpsServer, Server as HttpsServer} from 'https';
4
- import {readFileSync, promises as fsPromises} from 'fs';
4
+ import {promises as fsPromises, readFileSync} from 'fs';
5
5
  import {AddressInfo} from 'net';
6
6
  import {load} from 'js-yaml';
7
7
  import fetch, {Response} from 'node-fetch';
@@ -35,6 +35,12 @@ interface RegistryInfo {
35
35
  token?: string;
36
36
  }
37
37
 
38
+ interface ProxyInfo {
39
+ registries: RegistryInfo[];
40
+ https?: HttpsConfig;
41
+ basePath?: string;
42
+ }
43
+
38
44
  interface PackageVersion {
39
45
  dist?: { tarball?: string };
40
46
  }
@@ -115,13 +121,14 @@ function removeRegistryPrefix(tarballUrl: string, registries: RegistryInfo[]): s
115
121
  throw new Error(`Can't find tarball url ${tarballUrl} does not match given registries ${normalizedRegistries}`)
116
122
  }
117
123
 
118
- async function loadProxyConfig(proxyConfigPath = './.registry-proxy.yml'): Promise<ProxyConfig> {
124
+ async function readProxyConfig(proxyConfigPath = './.registry-proxy.yml'): Promise<ProxyConfig> {
119
125
  const resolvedPath = resolvePath(proxyConfigPath);
120
126
  try {
121
127
  const content = await readFile(resolvedPath, 'utf8');
122
128
  const config = load(content) as ProxyConfig;
123
129
  if (!config.registries) {
124
- throw new Error('Missing required "registries" field in config');
130
+ console.error('Missing required "registries" field in config');
131
+ process.exit(1);
125
132
  }
126
133
  return config;
127
134
  } catch (e) {
@@ -130,7 +137,7 @@ async function loadProxyConfig(proxyConfigPath = './.registry-proxy.yml'): Promi
130
137
  }
131
138
  }
132
139
 
133
- async function loadYarnConfig(path: string): Promise<YarnConfig> {
140
+ async function readYarnConfig(path: string): Promise<YarnConfig> {
134
141
  try {
135
142
  const content = await readFile(resolvePath(path), 'utf8');
136
143
  return load(content) as YarnConfig;
@@ -140,22 +147,20 @@ async function loadYarnConfig(path: string): Promise<YarnConfig> {
140
147
  }
141
148
  }
142
149
 
143
- async function loadRegistries(
150
+ async function loadProxyInfo(
144
151
  proxyConfigPath = './.registry-proxy.yml',
145
152
  localYarnConfigPath = './.yarnrc.yml',
146
153
  globalYarnConfigPath = join(homedir(), '.yarnrc.yml')
147
- ): Promise<RegistryInfo[]> {
154
+ ): Promise<ProxyInfo> {
148
155
  const [proxyConfig, localYarnConfig, globalYarnConfig] = await Promise.all([
149
- loadProxyConfig(proxyConfigPath),
150
- loadYarnConfig(localYarnConfigPath),
151
- loadYarnConfig(globalYarnConfigPath)
156
+ readProxyConfig(proxyConfigPath),
157
+ readYarnConfig(localYarnConfigPath),
158
+ readYarnConfig(globalYarnConfigPath)
152
159
  ]);
153
-
154
160
  const registryMap = new Map<string, RegistryInfo>();
155
161
  for (const [url, regConfig] of Object.entries(proxyConfig.registries)) {
156
162
  const normalizedUrl = normalizeUrl(url);
157
163
  let token = regConfig?.npmAuthToken;
158
-
159
164
  if (!token) {
160
165
  const yarnConfigs = [localYarnConfig, globalYarnConfig];
161
166
  for (const config of yarnConfigs) {
@@ -169,7 +174,10 @@ async function loadRegistries(
169
174
  }
170
175
  registryMap.set(normalizedUrl, {url: normalizedUrl, token});
171
176
  }
172
- return Array.from(registryMap.values());
177
+ const registries = Array.from(registryMap.values());
178
+ const https = proxyConfig.https;
179
+ const basePath = removeEndingSlashAndForceStartingSlash(proxyConfig.basePath);
180
+ return {registries, https, basePath};
173
181
  }
174
182
 
175
183
  export async function startProxyServer(
@@ -178,13 +186,13 @@ export async function startProxyServer(
178
186
  globalYarnConfigPath?: string,
179
187
  port: number = 0
180
188
  ): Promise<HttpServer | HttpsServer> {
181
- const proxyConfig = await loadProxyConfig(proxyConfigPath);
182
- const registries = await loadRegistries(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath);
183
- const basePathPrefixedWithSlash: string = removeEndingSlashAndForceStartingSlash(proxyConfig.basePath);
189
+ const proxyInfo = await loadProxyInfo(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath);
190
+ const registries = proxyInfo.registries;
191
+ const basePathPrefixedWithSlash: string = removeEndingSlashAndForceStartingSlash(proxyInfo.basePath);
184
192
 
185
193
  console.log('Active registries:', registries.map(r => r.url));
186
194
  console.log('Proxy base path:', basePathPrefixedWithSlash);
187
- console.log('HTTPS:', !!proxyConfig.https);
195
+ console.log('HTTPS:', !!proxyInfo.https);
188
196
 
189
197
  let proxyPort: number;
190
198
 
@@ -195,7 +203,7 @@ export async function startProxyServer(
195
203
  return;
196
204
  }
197
205
 
198
- const fullUrl = new URL(req.url, `${proxyConfig.https ? 'https' : 'http'}://${req.headers.host}`);
206
+ const fullUrl = new URL(req.url, `${proxyInfo.https ? 'https' : 'http'}://${req.headers.host}`);
199
207
  console.log(`Proxy server received request on ${fullUrl.toString()}`)
200
208
  if (!fullUrl.pathname.startsWith(basePathPrefixedWithSlash)) {
201
209
  console.error(`Path ${fullUrl.pathname} does not match basePath ${basePathPrefixedWithSlash}`);
@@ -239,7 +247,7 @@ export async function startProxyServer(
239
247
  if (data.versions) {
240
248
  const requestHeadersHostFromYarnClient = req.headers.host || 'localhost:' + proxyPort;
241
249
  console.log("Request headers.host from yarn client is", requestHeadersHostFromYarnClient);
242
- const proxyBaseUrlNoSuffixedWithSlash = `${proxyConfig.https ? 'https' : 'http'}://${requestHeadersHostFromYarnClient}${basePathPrefixedWithSlash === '/' ? '' : basePathPrefixedWithSlash}`;
250
+ const proxyBaseUrlNoSuffixedWithSlash = `${proxyInfo.https ? 'https' : 'http'}://${requestHeadersHostFromYarnClient}${basePathPrefixedWithSlash === '/' ? '' : basePathPrefixedWithSlash}`;
243
251
  console.log("proxyBaseUrlNoSuffixedWithSlash", proxyBaseUrlNoSuffixedWithSlash);
244
252
  for (const version in data.versions) {
245
253
  const dist = data.versions[version]?.dist;
@@ -277,8 +285,8 @@ export async function startProxyServer(
277
285
  };
278
286
 
279
287
  let server: HttpServer | HttpsServer;
280
- if (proxyConfig.https) {
281
- const {key, cert} = proxyConfig.https;
288
+ if (proxyInfo.https) {
289
+ const {key, cert} = proxyInfo.https;
282
290
  const keyPath = resolvePath(key);
283
291
  const certPath = resolvePath(cert);
284
292
  try {
@@ -311,7 +319,7 @@ export async function startProxyServer(
311
319
  proxyPort = address.port;
312
320
  const portFile = join(process.env.PROJECT_ROOT || process.cwd(), '.registry-proxy-port');
313
321
  writeFile(portFile, proxyPort.toString()).catch(e => console.error('Failed to write port file:', e));
314
- console.log(`Proxy server running on ${proxyConfig.https ? 'https' : 'http'}://localhost:${proxyPort}${basePathPrefixedWithSlash}`);
322
+ console.log(`Proxy server running on ${proxyInfo.https ? 'https' : 'http'}://localhost:${proxyPort}${basePathPrefixedWithSlash}`);
315
323
  resolve(server);
316
324
  });
317
325
  });