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.
- package/dist/index.js +22 -18
- package/package.json +1 -1
- 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 {
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
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
|
|
133
|
-
const registries =
|
|
134
|
-
const basePathPrefixedWithSlash = removeEndingSlashAndForceStartingSlash(
|
|
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:', !!
|
|
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, `${
|
|
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 = `${
|
|
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 (
|
|
229
|
-
const { key, cert } =
|
|
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 ${
|
|
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
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {createServer, Server as HttpServer,
|
|
2
|
+
import {createServer, IncomingMessage, OutgoingHttpHeaders, Server as HttpServer, ServerResponse} from 'http';
|
|
3
3
|
import {createServer as createHttpsServer, Server as HttpsServer} from 'https';
|
|
4
|
-
import {
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
150
|
+
async function loadProxyInfo(
|
|
144
151
|
proxyConfigPath = './.registry-proxy.yml',
|
|
145
152
|
localYarnConfigPath = './.yarnrc.yml',
|
|
146
153
|
globalYarnConfigPath = join(homedir(), '.yarnrc.yml')
|
|
147
|
-
): Promise<
|
|
154
|
+
): Promise<ProxyInfo> {
|
|
148
155
|
const [proxyConfig, localYarnConfig, globalYarnConfig] = await Promise.all([
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
|
|
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
|
|
182
|
-
const registries =
|
|
183
|
-
const basePathPrefixedWithSlash: string = removeEndingSlashAndForceStartingSlash(
|
|
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:', !!
|
|
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, `${
|
|
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 = `${
|
|
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 (
|
|
281
|
-
const {key, cert} =
|
|
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 ${
|
|
322
|
+
console.log(`Proxy server running on ${proxyInfo.https ? 'https' : 'http'}://localhost:${proxyPort}${basePathPrefixedWithSlash}`);
|
|
315
323
|
resolve(server);
|
|
316
324
|
});
|
|
317
325
|
});
|