com.jimuwd.xian.registry-proxy 1.0.0 → 1.0.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.
Files changed (3) hide show
  1. package/dist/index.js +46 -26
  2. package/package.json +1 -1
  3. package/src/index.ts +50 -26
package/dist/index.js CHANGED
@@ -5,44 +5,63 @@ import { load } from 'js-yaml';
5
5
  import fetch from 'node-fetch';
6
6
  import { homedir } from 'os';
7
7
  import { join } from 'path';
8
- async function loadRegistries(localConfigPath = './.yarnrc.yml', globalConfigPath = join(homedir(), '.yarnrc.yml')) {
9
- let localConfig = {};
8
+ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYarnConfigPath = './.yarnrc.yml', globalYarnConfigPath = join(homedir(), '.yarnrc.yml')) {
9
+ // 读取独立的 .registry-proxy.yml
10
+ let proxyConfig = { registries: {} };
10
11
  try {
11
- const localYamlContent = await readFile(localConfigPath, 'utf8');
12
- localConfig = load(localYamlContent);
13
- console.log(`Loaded local config from ${localConfigPath}`);
12
+ const proxyYamlContent = await readFile(proxyConfigPath, 'utf8');
13
+ proxyConfig = load(proxyYamlContent);
14
+ console.log(`Loaded proxy config from ${proxyConfigPath}`);
14
15
  }
15
16
  catch (e) {
16
- console.error(`Failed to load ${localConfigPath}: ${e.message}`);
17
- process.exit(1);
17
+ console.error(`Failed to load ${proxyConfigPath}: ${e.message}`);
18
+ process.exit(1); // 代理配置文件是必须的
18
19
  }
19
- if (!localConfig.npmRegistries || !Object.keys(localConfig.npmRegistries).length) {
20
- console.error(`No npmRegistries found in ${localConfigPath}`);
20
+ if (!proxyConfig.registries || !Object.keys(proxyConfig.registries).length) {
21
+ console.error(`No registries found in ${proxyConfigPath}`);
21
22
  process.exit(1);
22
23
  }
23
- let globalConfig = {};
24
+ // 读取本地 .yarnrc.yml(用于 token 回退)
25
+ let localYarnConfig = {};
26
+ try {
27
+ const localYamlContent = await readFile(localYarnConfigPath, 'utf8');
28
+ localYarnConfig = load(localYamlContent);
29
+ console.log(`Loaded local Yarn config from ${localYarnConfigPath}`);
30
+ }
31
+ catch (e) {
32
+ console.warn(`Failed to load ${localYarnConfigPath}: ${e.message}`);
33
+ }
34
+ // 读取全局 ~/.yarnrc.yml(用于 token 回退)
35
+ let globalYarnConfig = {};
24
36
  try {
25
- const globalYamlContent = await readFile(globalConfigPath, 'utf8');
26
- globalConfig = load(globalYamlContent);
27
- console.log(`Loaded global config from ${globalConfigPath}`);
37
+ const globalYamlContent = await readFile(globalYarnConfigPath, 'utf8');
38
+ globalYarnConfig = load(globalYamlContent);
39
+ console.log(`Loaded global Yarn config from ${globalYarnConfigPath}`);
28
40
  }
29
41
  catch (e) {
30
- console.warn(`Failed to load ${globalConfigPath}: ${e.message}`);
42
+ console.warn(`Failed to load ${globalYarnConfigPath}: ${e.message}`);
31
43
  }
32
- const registries = Object.entries(localConfig.npmRegistries).map(([url, localRegConfig]) => {
33
- let token = localRegConfig.npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || localRegConfig.npmAuthToken;
34
- if (!token && globalConfig.npmRegistries && globalConfig.npmRegistries[url]) {
35
- token = globalConfig.npmRegistries[url].npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || globalConfig.npmRegistries[url].npmAuthToken;
36
- console.log(`Token for ${url} not found in local config, using global token`);
44
+ // .registry-proxy.yml 获取 registries,并回退读取 token
45
+ const registries = Object.entries(proxyConfig.registries).map(([url, regConfig]) => {
46
+ let token = regConfig.npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || regConfig.npmAuthToken;
47
+ // 如果 .registry-proxy.yml 未提供 token,从本地 .yarnrc.yml 回退
48
+ if (!token && localYarnConfig.npmRegistries && localYarnConfig.npmRegistries[url]) {
49
+ token = localYarnConfig.npmRegistries[url].npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || localYarnConfig.npmRegistries[url].npmAuthToken;
50
+ console.log(`Token for ${url} not found in ${proxyConfigPath}, using local Yarn config`);
51
+ }
52
+ // 如果本地 .yarnrc.yml 仍无 token,从全局 ~/.yarnrc.yml 回退
53
+ if (!token && globalYarnConfig.npmRegistries && globalYarnConfig.npmRegistries[url]) {
54
+ token = globalYarnConfig.npmRegistries[url].npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || globalYarnConfig.npmRegistries[url].npmAuthToken;
55
+ console.log(`Token for ${url} not found in local Yarn config, using global Yarn config`);
37
56
  }
38
57
  console.log(`Registry ${url}: token=${token ? 'present' : 'missing'}`);
39
58
  return { url, token };
40
59
  });
41
60
  return registries;
42
61
  }
43
- export async function startProxyServer(localConfigPath, globalConfigPath, port = 4873) {
62
+ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath, port = 4873) {
44
63
  console.log('Starting proxy server...');
45
- const registries = await loadRegistries(localConfigPath, globalConfigPath);
64
+ const registries = await loadRegistries(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath);
46
65
  const server = createServer(async (req, res) => {
47
66
  if (!req.url || req.method !== 'GET') {
48
67
  res.writeHead(400);
@@ -86,11 +105,12 @@ export async function startProxyServer(localConfigPath, globalConfigPath, port =
86
105
  return server;
87
106
  }
88
107
  if (import.meta.url === `file://${process.argv[1]}`) {
89
- const localConfigPath = process.argv[2];
90
- const globalConfigPath = process.argv[3];
91
- const port = parseInt(process.argv[4], 10) || 4873;
92
- console.log(`CLI: localConfigPath=${localConfigPath || './.yarnrc.yml'}, globalConfigPath=${globalConfigPath || join(homedir(), '.yarnrc.yml')}, port=${port}`);
93
- startProxyServer(localConfigPath, globalConfigPath, port).catch(err => {
108
+ const proxyConfigPath = process.argv[2];
109
+ const localYarnConfigPath = process.argv[3];
110
+ const globalYarnConfigPath = process.argv[4];
111
+ const port = parseInt(process.argv[5], 10) || 4873;
112
+ console.log(`CLI: proxyConfigPath=${proxyConfigPath || './.registry-proxy.yml'}, localYarnConfigPath=${localYarnConfigPath || './.yarnrc.yml'}, globalYarnConfigPath=${globalYarnConfigPath || join(homedir(), '.yarnrc.yml')}, port=${port}`);
113
+ startProxyServer(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath, port).catch(err => {
94
114
  console.error('Startup failed:', err.message);
95
115
  process.exit(1);
96
116
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.jimuwd.xian.registry-proxy",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
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
@@ -7,39 +7,62 @@ import { homedir } from 'os';
7
7
  import { join } from 'path';
8
8
 
9
9
  interface RegistryConfig { npmAuthToken?: string; }
10
+ interface ProxyConfig { registries: Record<string, RegistryConfig>; }
10
11
  interface YarnConfig { npmRegistries?: Record<string, RegistryConfig>; }
11
12
 
12
- async function loadRegistries(localConfigPath = './.yarnrc.yml', globalConfigPath = join(homedir(), '.yarnrc.yml')): Promise<{ url: string; token?: string }[]> {
13
- let localConfig: YarnConfig = {};
13
+ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYarnConfigPath = './.yarnrc.yml', globalYarnConfigPath = join(homedir(), '.yarnrc.yml')): Promise<{ url: string; token?: string }[]> {
14
+ // 读取独立的 .registry-proxy.yml
15
+ let proxyConfig: ProxyConfig = { registries: {} };
14
16
  try {
15
- const localYamlContent = await readFile(localConfigPath, 'utf8');
16
- localConfig = load(localYamlContent) as YarnConfig;
17
- console.log(`Loaded local config from ${localConfigPath}`);
17
+ const proxyYamlContent = await readFile(proxyConfigPath, 'utf8');
18
+ proxyConfig = load(proxyYamlContent) as ProxyConfig;
19
+ console.log(`Loaded proxy config from ${proxyConfigPath}`);
18
20
  } catch (e) {
19
- console.error(`Failed to load ${localConfigPath}: ${(e as Error).message}`);
20
- process.exit(1);
21
+ console.error(`Failed to load ${proxyConfigPath}: ${(e as Error).message}`);
22
+ process.exit(1); // 代理配置文件是必须的
21
23
  }
22
24
 
23
- if (!localConfig.npmRegistries || !Object.keys(localConfig.npmRegistries).length) {
24
- console.error(`No npmRegistries found in ${localConfigPath}`);
25
+ if (!proxyConfig.registries || !Object.keys(proxyConfig.registries).length) {
26
+ console.error(`No registries found in ${proxyConfigPath}`);
25
27
  process.exit(1);
26
28
  }
27
29
 
28
- let globalConfig: YarnConfig = {};
30
+ // 读取本地 .yarnrc.yml(用于 token 回退)
31
+ let localYarnConfig: YarnConfig = {};
32
+ try {
33
+ const localYamlContent = await readFile(localYarnConfigPath, 'utf8');
34
+ localYarnConfig = load(localYamlContent) as YarnConfig;
35
+ console.log(`Loaded local Yarn config from ${localYarnConfigPath}`);
36
+ } catch (e) {
37
+ console.warn(`Failed to load ${localYarnConfigPath}: ${(e as Error).message}`);
38
+ }
39
+
40
+ // 读取全局 ~/.yarnrc.yml(用于 token 回退)
41
+ let globalYarnConfig: YarnConfig = {};
29
42
  try {
30
- const globalYamlContent = await readFile(globalConfigPath, 'utf8');
31
- globalConfig = load(globalYamlContent) as YarnConfig;
32
- console.log(`Loaded global config from ${globalConfigPath}`);
43
+ const globalYamlContent = await readFile(globalYarnConfigPath, 'utf8');
44
+ globalYarnConfig = load(globalYamlContent) as YarnConfig;
45
+ console.log(`Loaded global Yarn config from ${globalYarnConfigPath}`);
33
46
  } catch (e) {
34
- console.warn(`Failed to load ${globalConfigPath}: ${(e as Error).message}`);
47
+ console.warn(`Failed to load ${globalYarnConfigPath}: ${(e as Error).message}`);
35
48
  }
36
49
 
37
- const registries = Object.entries(localConfig.npmRegistries).map(([url, localRegConfig]) => {
38
- let token = localRegConfig.npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || localRegConfig.npmAuthToken;
39
- if (!token && globalConfig.npmRegistries && globalConfig.npmRegistries[url]) {
40
- token = globalConfig.npmRegistries[url].npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || globalConfig.npmRegistries[url].npmAuthToken;
41
- console.log(`Token for ${url} not found in local config, using global token`);
50
+ // .registry-proxy.yml 获取 registries,并回退读取 token
51
+ const registries = Object.entries(proxyConfig.registries).map(([url, regConfig]) => {
52
+ let token = regConfig.npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || regConfig.npmAuthToken;
53
+
54
+ // 如果 .registry-proxy.yml 未提供 token,从本地 .yarnrc.yml 回退
55
+ if (!token && localYarnConfig.npmRegistries && localYarnConfig.npmRegistries[url]) {
56
+ token = localYarnConfig.npmRegistries[url].npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || localYarnConfig.npmRegistries[url].npmAuthToken;
57
+ console.log(`Token for ${url} not found in ${proxyConfigPath}, using local Yarn config`);
58
+ }
59
+
60
+ // 如果本地 .yarnrc.yml 仍无 token,从全局 ~/.yarnrc.yml 回退
61
+ if (!token && globalYarnConfig.npmRegistries && globalYarnConfig.npmRegistries[url]) {
62
+ token = globalYarnConfig.npmRegistries[url].npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || globalYarnConfig.npmRegistries[url].npmAuthToken;
63
+ console.log(`Token for ${url} not found in local Yarn config, using global Yarn config`);
42
64
  }
65
+
43
66
  console.log(`Registry ${url}: token=${token ? 'present' : 'missing'}`);
44
67
  return { url, token };
45
68
  });
@@ -47,9 +70,9 @@ async function loadRegistries(localConfigPath = './.yarnrc.yml', globalConfigPat
47
70
  return registries;
48
71
  }
49
72
 
50
- export async function startProxyServer(localConfigPath?: string, globalConfigPath?: string, port: number = 4873): Promise<Server> {
73
+ export async function startProxyServer(proxyConfigPath?: string, localYarnConfigPath?: string, globalYarnConfigPath?: string, port: number = 4873): Promise<Server> {
51
74
  console.log('Starting proxy server...');
52
- const registries = await loadRegistries(localConfigPath, globalConfigPath);
75
+ const registries = await loadRegistries(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath);
53
76
 
54
77
  const server = createServer(async (req, res) => {
55
78
  if (!req.url || req.method !== 'GET') {
@@ -99,11 +122,12 @@ export async function startProxyServer(localConfigPath?: string, globalConfigPat
99
122
  }
100
123
 
101
124
  if (import.meta.url === `file://${process.argv[1]}`) {
102
- const localConfigPath = process.argv[2];
103
- const globalConfigPath = process.argv[3];
104
- const port = parseInt(process.argv[4], 10) || 4873;
105
- console.log(`CLI: localConfigPath=${localConfigPath || './.yarnrc.yml'}, globalConfigPath=${globalConfigPath || join(homedir(), '.yarnrc.yml')}, port=${port}`);
106
- startProxyServer(localConfigPath, globalConfigPath, port).catch(err => {
125
+ const proxyConfigPath = process.argv[2];
126
+ const localYarnConfigPath = process.argv[3];
127
+ const globalYarnConfigPath = process.argv[4];
128
+ const port = parseInt(process.argv[5], 10) || 4873;
129
+ console.log(`CLI: proxyConfigPath=${proxyConfigPath || './.registry-proxy.yml'}, localYarnConfigPath=${localYarnConfigPath || './.yarnrc.yml'}, globalYarnConfigPath=${globalYarnConfigPath || join(homedir(), '.yarnrc.yml')}, port=${port}`);
130
+ startProxyServer(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath, port).catch(err => {
107
131
  console.error('Startup failed:', (err as Error).message);
108
132
  process.exit(1);
109
133
  });