com.jimuwd.xian.registry-proxy 1.0.3 → 1.0.4
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/README.MD +3 -2
- package/dist/index.js +16 -5
- package/package.json +1 -1
- package/src/index.ts +18 -5
package/README.MD
CHANGED
|
@@ -138,6 +138,7 @@ com.jimuwd.xian.registry-proxy/
|
|
|
138
138
|
### 功能实现
|
|
139
139
|
1. **配置加载(`loadRegistries`)**:
|
|
140
140
|
- **代理配置文件**:从指定路径(默认 `./.registry-proxy.yml`)读取 `registries`,提取 `registryUrl` 和 `npmAuthToken`。
|
|
141
|
+
- **URL 规范化**:自动去除 `registryUrl` 尾部斜杠,确保 `https://example.com/path/` 和 `https://example.com/path` 被视为同一地址,后配置覆盖前配置。
|
|
141
142
|
- **Yarn 配置文件回退**:如果 `.registry-proxy.yml` 中 token 缺失,依次从本地 `.yarnrc.yml`(默认 `./.yarnrc.yml`)和全局 `~/.yarnrc.yml`(默认 `~/.yarnrc.yml`)读取对应 `registryUrl` 的 `npmAuthToken`。
|
|
142
143
|
- **安全设计**:将 `registryUrl` 和 token 配置独立于 `.registry-proxy.yml`,避免敏感信息直接写入 Yarn 配置文件并提交到代码仓库。回退到 Yarn 配置的 token(尤其是全局配置)进一步降低安全隐患。
|
|
143
144
|
- **优先级**:`.registry-proxy.yml` token > 本地 `.yarnrc.yml` token > 全局 `~/.yarnrc.yml` token > 无 token。
|
|
@@ -180,8 +181,8 @@ yarn run registry-proxy ./custom-registry.yml ./custom-yarn.yml ~/.custom-yarn.y
|
|
|
180
181
|
- **格式要求**:每个 `registryUrl` 后必须跟一个对象(至少是 `{}`),否则解析为 `null` 会导致运行时错误。例如:
|
|
181
182
|
```yaml
|
|
182
183
|
registries:
|
|
183
|
-
"https://repo.jimuwd.com/
|
|
184
|
-
"https://repo.jimuwd.com/
|
|
184
|
+
"https://repo.jimuwd.com/some/project/path/~npm/": {} # 正确
|
|
185
|
+
"https://repo.jimuwd.com/some/project/path1/~npm/": # 错误,会解析为 null
|
|
185
186
|
```
|
|
186
187
|
- 示例:
|
|
187
188
|
```yaml
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,10 @@ 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
|
+
// 规范化 URL,去除尾部斜杠
|
|
9
|
+
function normalizeUrl(url) {
|
|
10
|
+
return url.endsWith('/') ? url.slice(0, -1) : url;
|
|
11
|
+
}
|
|
8
12
|
async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYarnConfigPath = './.yarnrc.yml', globalYarnConfigPath = join(homedir(), '.yarnrc.yml')) {
|
|
9
13
|
let proxyConfig = { registries: {} };
|
|
10
14
|
try {
|
|
@@ -38,17 +42,24 @@ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYa
|
|
|
38
42
|
catch (e) {
|
|
39
43
|
console.warn(`Failed to load ${globalYarnConfigPath}: ${e.message}`);
|
|
40
44
|
}
|
|
41
|
-
|
|
45
|
+
// 使用 Map 合并重复的 URL
|
|
46
|
+
const registryMap = new Map();
|
|
47
|
+
for (const [url, regConfig] of Object.entries(proxyConfig.registries)) {
|
|
48
|
+
const normalizedUrl = normalizeUrl(url);
|
|
49
|
+
registryMap.set(normalizedUrl, regConfig); // 后配置覆盖前配置
|
|
50
|
+
}
|
|
51
|
+
const registries = Array.from(registryMap.entries()).map(([url, regConfig]) => {
|
|
42
52
|
let token;
|
|
43
53
|
if (regConfig && 'npmAuthToken' in regConfig) {
|
|
44
54
|
token = regConfig.npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || regConfig.npmAuthToken;
|
|
45
55
|
}
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
const normalizedUrl = normalizeUrl(url);
|
|
57
|
+
if (!token && localYarnConfig.npmRegistries?.[normalizedUrl] && 'npmAuthToken' in localYarnConfig.npmRegistries[normalizedUrl]) {
|
|
58
|
+
token = localYarnConfig.npmRegistries[normalizedUrl].npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || localYarnConfig.npmRegistries[normalizedUrl].npmAuthToken;
|
|
48
59
|
console.log(`Token for ${url} not found in ${proxyConfigPath}, using local Yarn config`);
|
|
49
60
|
}
|
|
50
|
-
if (!token && globalYarnConfig.npmRegistries?.[
|
|
51
|
-
token = globalYarnConfig.npmRegistries[
|
|
61
|
+
if (!token && globalYarnConfig.npmRegistries?.[normalizedUrl] && 'npmAuthToken' in globalYarnConfig.npmRegistries[normalizedUrl]) {
|
|
62
|
+
token = globalYarnConfig.npmRegistries[normalizedUrl].npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || globalYarnConfig.npmRegistries[normalizedUrl].npmAuthToken;
|
|
52
63
|
console.log(`Token for ${url} not found in local Yarn config, using global Yarn config`);
|
|
53
64
|
}
|
|
54
65
|
console.log(`Registry ${url}: token=${token ? 'present' : 'missing'}`);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -10,6 +10,11 @@ interface RegistryConfig { npmAuthToken?: string; }
|
|
|
10
10
|
interface ProxyConfig { registries: Record<string, RegistryConfig | null>; }
|
|
11
11
|
interface YarnConfig { npmRegistries?: Record<string, RegistryConfig | null>; }
|
|
12
12
|
|
|
13
|
+
// 规范化 URL,去除尾部斜杠
|
|
14
|
+
function normalizeUrl(url: string): string {
|
|
15
|
+
return url.endsWith('/') ? url.slice(0, -1) : url;
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYarnConfigPath = './.yarnrc.yml', globalYarnConfigPath = join(homedir(), '.yarnrc.yml')): Promise<{ url: string; token?: string }[]> {
|
|
14
19
|
let proxyConfig: ProxyConfig = { registries: {} };
|
|
15
20
|
try {
|
|
@@ -44,20 +49,28 @@ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYa
|
|
|
44
49
|
console.warn(`Failed to load ${globalYarnConfigPath}: ${(e as Error).message}`);
|
|
45
50
|
}
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
// 使用 Map 合并重复的 URL
|
|
53
|
+
const registryMap = new Map<string, RegistryConfig | null>();
|
|
54
|
+
for (const [url, regConfig] of Object.entries(proxyConfig.registries)) {
|
|
55
|
+
const normalizedUrl = normalizeUrl(url);
|
|
56
|
+
registryMap.set(normalizedUrl, regConfig); // 后配置覆盖前配置
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const registries = Array.from(registryMap.entries()).map(([url, regConfig]) => {
|
|
48
60
|
let token: string | undefined;
|
|
49
61
|
|
|
50
62
|
if (regConfig && 'npmAuthToken' in regConfig) {
|
|
51
63
|
token = regConfig.npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || regConfig.npmAuthToken;
|
|
52
64
|
}
|
|
53
65
|
|
|
54
|
-
|
|
55
|
-
|
|
66
|
+
const normalizedUrl = normalizeUrl(url);
|
|
67
|
+
if (!token && localYarnConfig.npmRegistries?.[normalizedUrl] && 'npmAuthToken' in localYarnConfig.npmRegistries[normalizedUrl]) {
|
|
68
|
+
token = localYarnConfig.npmRegistries[normalizedUrl]!.npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || localYarnConfig.npmRegistries[normalizedUrl]!.npmAuthToken;
|
|
56
69
|
console.log(`Token for ${url} not found in ${proxyConfigPath}, using local Yarn config`);
|
|
57
70
|
}
|
|
58
71
|
|
|
59
|
-
if (!token && globalYarnConfig.npmRegistries?.[
|
|
60
|
-
token = globalYarnConfig.npmRegistries[
|
|
72
|
+
if (!token && globalYarnConfig.npmRegistries?.[normalizedUrl] && 'npmAuthToken' in globalYarnConfig.npmRegistries[normalizedUrl]) {
|
|
73
|
+
token = globalYarnConfig.npmRegistries[normalizedUrl]!.npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || globalYarnConfig.npmRegistries[normalizedUrl]!.npmAuthToken;
|
|
61
74
|
console.log(`Token for ${url} not found in local Yarn config, using global Yarn config`);
|
|
62
75
|
}
|
|
63
76
|
|