com.jimuwd.xian.registry-proxy 1.0.2 → 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 +61 -72
- package/dist/index.js +23 -15
- package/package.json +1 -1
- package/src/index.ts +28 -17
package/README.MD
CHANGED
|
@@ -17,24 +17,23 @@
|
|
|
17
17
|
## 快速上手指南
|
|
18
18
|
|
|
19
19
|
### 安装
|
|
20
|
-
在你的业务项目中,将 `com.jimuwd.xian.registry-proxy` 添加为开发依赖。假设你的私有 Yarn 仓库地址为 `https://
|
|
20
|
+
在你的业务项目中,将 `com.jimuwd.xian.registry-proxy` 添加为开发依赖。假设你的私有 Yarn 仓库地址为 `https://repo.jimuwd.com/jimuwd/~npm/`:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
yarn add --dev com.jimuwd.xian.registry-proxy --registry https://
|
|
23
|
+
yarn add --dev com.jimuwd.xian.registry-proxy --registry https://repo.jimuwd.com/jimuwd/~npm/
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
### 配置
|
|
27
27
|
1. **代理配置文件 `.registry-proxy.yml`**
|
|
28
|
-
在业务项目根目录创建 `.registry-proxy.yml`,指定需要代理的 registry
|
|
28
|
+
在业务项目根目录创建 `.registry-proxy.yml`,指定需要代理的 registry 列表。每个 registry 必须至少是一个空对象 `{}`,否则会导致解析错误:
|
|
29
29
|
```yaml
|
|
30
30
|
registries:
|
|
31
31
|
"http://localhost:4873/":
|
|
32
32
|
npmAuthToken: "local-token" # 可选
|
|
33
33
|
"https://registry.npmjs.org/":
|
|
34
|
-
# token
|
|
35
|
-
"https://
|
|
34
|
+
{} # 无 token 时使用空对象
|
|
35
|
+
"https://repo.jimuwd.com/jimuwd/~npm/":
|
|
36
36
|
npmAuthToken: "private-token" # 可选
|
|
37
|
-
npmAlwaysAuth: true # 强制要求认证
|
|
38
37
|
```
|
|
39
38
|
|
|
40
39
|
2. **本地 `.yarnrc.yml`**
|
|
@@ -51,9 +50,9 @@ yarn add --dev com.jimuwd.xian.registry-proxy --registry https://your-private-re
|
|
|
51
50
|
npmRegistries:
|
|
52
51
|
"https://registry.npmjs.org/":
|
|
53
52
|
npmAuthToken: "global-npm-token"
|
|
54
|
-
"https://
|
|
53
|
+
"https://repo.jimuwd.com/jimuwd/~npm/":
|
|
55
54
|
npmAuthToken: "global-private-token"
|
|
56
|
-
npmAlwaysAuth: true
|
|
55
|
+
npmAlwaysAuth: true # 可选,控制 Yarn 行为
|
|
57
56
|
```
|
|
58
57
|
|
|
59
58
|
### 使用
|
|
@@ -109,7 +108,7 @@ yarn add --dev com.jimuwd.xian.registry-proxy --registry https://your-private-re
|
|
|
109
108
|
```bash
|
|
110
109
|
yarn install
|
|
111
110
|
```
|
|
112
|
-
|
|
111
|
+
- 代理会在安装完成后自动停止。
|
|
113
112
|
|
|
114
113
|
### 输出示例
|
|
115
114
|
运行后,你会看到类似以下输出:
|
|
@@ -138,27 +137,28 @@ com.jimuwd.xian.registry-proxy/
|
|
|
138
137
|
|
|
139
138
|
### 功能实现
|
|
140
139
|
1. **配置加载(`loadRegistries`)**:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
140
|
+
- **代理配置文件**:从指定路径(默认 `./.registry-proxy.yml`)读取 `registries`,提取 `registryUrl` 和 `npmAuthToken`。
|
|
141
|
+
- **URL 规范化**:自动去除 `registryUrl` 尾部斜杠,确保 `https://example.com/path/` 和 `https://example.com/path` 被视为同一地址,后配置覆盖前配置。
|
|
142
|
+
- **Yarn 配置文件回退**:如果 `.registry-proxy.yml` 中 token 缺失,依次从本地 `.yarnrc.yml`(默认 `./.yarnrc.yml`)和全局 `~/.yarnrc.yml`(默认 `~/.yarnrc.yml`)读取对应 `registryUrl` 的 `npmAuthToken`。
|
|
143
|
+
- **安全设计**:将 `registryUrl` 和 token 配置独立于 `.registry-proxy.yml`,避免敏感信息直接写入 Yarn 配置文件并提交到代码仓库。回退到 Yarn 配置的 token(尤其是全局配置)进一步降低安全隐患。
|
|
144
|
+
- **优先级**:`.registry-proxy.yml` token > 本地 `.yarnrc.yml` token > 全局 `~/.yarnrc.yml` token > 无 token。
|
|
145
|
+
- **错误处理**:`.registry-proxy.yml` 必须存在且包含 `registries`,否则退出。
|
|
146
146
|
|
|
147
147
|
2. **代理逻辑**:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
- **服务器**:使用 Node.js 的 `http.createServer` 创建本地 HTTP 服务,默认监听 `4873` 端口。
|
|
149
|
+
- **请求转发**:将所有请求按配置顺序转发到目标 registry,附带对应的 `Authorization: Bearer <token>`(如果存在)。
|
|
150
|
+
- **Fallback**:依次尝试每个 registry,直到返回成功响应(`response.ok`)或全部失败(返回 404)。
|
|
151
151
|
|
|
152
152
|
3. **进程管理**:
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
- **优雅关闭**:监听 `SIGTERM` 信号,关闭服务器并退出进程。
|
|
154
|
+
- **脚本集成**:通过 shell 脚本记录 PID,安装完成后发送 SIGTERM 停止服务。
|
|
155
155
|
|
|
156
156
|
### 技术栈
|
|
157
157
|
- **语言**:TypeScript(ES Modules)。
|
|
158
158
|
- **模块系统**:`"module": "nodenext"`,兼容 Node.js v20+。
|
|
159
159
|
- **依赖**:
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
- `node-fetch@^3.3.2`:发起 HTTP 请求。
|
|
161
|
+
- `js-yaml@^4.1.0`:解析 `.registry-proxy.yml` 和 `.yarnrc.yml` 文件。
|
|
162
162
|
- **Node.js 版本**:推荐 v14+,测试于 v20.17.0。
|
|
163
163
|
|
|
164
164
|
### CLI 参数
|
|
@@ -177,32 +177,36 @@ yarn run registry-proxy ./custom-registry.yml ./custom-yarn.yml ~/.custom-yarn.y
|
|
|
177
177
|
|
|
178
178
|
### 配置说明
|
|
179
179
|
- **`.registry-proxy.yml`**:
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
-
|
|
192
|
-
|
|
180
|
+
- 使用 `registries` 字段定义代理的 registry 列表,与 Yarn 的 `npmRegistries` 区分。
|
|
181
|
+
- **格式要求**:每个 `registryUrl` 后必须跟一个对象(至少是 `{}`),否则解析为 `null` 会导致运行时错误。例如:
|
|
182
|
+
```yaml
|
|
183
|
+
registries:
|
|
184
|
+
"https://repo.jimuwd.com/some/project/path/~npm/": {} # 正确
|
|
185
|
+
"https://repo.jimuwd.com/some/project/path1/~npm/": # 错误,会解析为 null
|
|
186
|
+
```
|
|
187
|
+
- 示例:
|
|
188
|
+
```yaml
|
|
189
|
+
registries:
|
|
190
|
+
"https://repo.jimuwd.com/jimuwd/~npm/":
|
|
191
|
+
npmAuthToken: "private-token"
|
|
192
|
+
```
|
|
193
|
+
- **注意**:无需配置 `npmAlwaysAuth`,此项仅适用于 Yarn 的 `.yarnrc.yml`,对代理行为无影响。
|
|
194
|
+
- **`.yarnrc.yml`**:
|
|
195
|
+
- 仅用于设置 `npmRegistryServer` 和回退 token。
|
|
196
|
+
- 如果需要强制认证,可在回退的 Yarn 配置中添加 `npmAlwaysAuth: true`。
|
|
193
197
|
|
|
194
198
|
### 注意事项
|
|
195
199
|
1. **端口冲突**:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
200
|
+
- 默认端口 `4873` 是 Verdaccio 的惯用端口,可能与其他工具冲突。
|
|
201
|
+
- 检查端口占用:`lsof -i :4873`。
|
|
202
|
+
- 可通过参数指定其他端口(如 `54321`)。
|
|
199
203
|
2. **配置文件格式**:
|
|
200
|
-
|
|
204
|
+
- 确保 `.registry-proxy.yml` 包含 `registries` 字段,`.yarnrc.yml` 包含 `npmRegistryServer`。
|
|
201
205
|
3. **日志**:
|
|
202
|
-
|
|
206
|
+
- 当前通过 `console.log` 输出启动信息,可扩展为文件日志。
|
|
203
207
|
4. **安全性**:
|
|
204
|
-
|
|
205
|
-
|
|
208
|
+
- 代理运行于本地,未开放外部访问,确保 `unsafeHttpWhitelist` 配置正确。
|
|
209
|
+
- 优先将 token 放入 `.registry-proxy.yml` 或全局 `.yarnrc.yml`,避免提交到代码仓库。
|
|
206
210
|
|
|
207
211
|
### 开发与发布
|
|
208
212
|
1. **构建**:
|
|
@@ -211,46 +215,31 @@ yarn run registry-proxy ./custom-registry.yml ./custom-yarn.yml ~/.custom-yarn.y
|
|
|
211
215
|
```
|
|
212
216
|
2. **发布到私有仓库**:
|
|
213
217
|
```bash
|
|
214
|
-
yarn publish --registry https://
|
|
218
|
+
yarn publish --registry https://repo.jimuwd.com/jimuwd/~npm/
|
|
215
219
|
```
|
|
216
220
|
|
|
217
221
|
---
|
|
218
222
|
|
|
219
223
|
### 测试流程
|
|
220
|
-
1.
|
|
224
|
+
1. **更新 `.registry-proxy.yml`**:
|
|
225
|
+
```yaml
|
|
226
|
+
registries:
|
|
227
|
+
"https://repo.jimuwd.com/jimuwd/~npm/": {}
|
|
228
|
+
"https://registry.npmjs.org/": {}
|
|
229
|
+
```
|
|
230
|
+
2. **构建并发布**:
|
|
221
231
|
```bash
|
|
222
232
|
cd registry-proxy
|
|
223
233
|
yarn install
|
|
224
234
|
yarn build
|
|
225
|
-
yarn publish --registry https://
|
|
235
|
+
yarn publish --registry https://repo.jimuwd.com/jimuwd/~npm/
|
|
226
236
|
```
|
|
227
|
-
|
|
228
|
-
- `.registry-proxy.yml`:
|
|
229
|
-
```yaml
|
|
230
|
-
registries:
|
|
231
|
-
"http://localhost:4873/":
|
|
232
|
-
npmAuthToken: "local-token"
|
|
233
|
-
"https://registry.npmjs.org/":
|
|
234
|
-
# 无 token,回退到 Yarn 配置
|
|
235
|
-
"https://your-private-registry.example.com/":
|
|
236
|
-
npmAuthToken: "private-token"
|
|
237
|
-
npmAlwaysAuth: true
|
|
238
|
-
```
|
|
239
|
-
- `.yarnrc.yml`:
|
|
240
|
-
```yaml
|
|
241
|
-
npmRegistryServer: "http://localhost:4873/"
|
|
242
|
-
unsafeHttpWhitelist:
|
|
243
|
-
- "localhost"
|
|
244
|
-
```
|
|
245
|
-
- `~/.yarnrc.yml`:
|
|
246
|
-
```yaml
|
|
247
|
-
npmRegistries:
|
|
248
|
-
"https://registry.npmjs.org/":
|
|
249
|
-
npmAuthToken: "global-npm-token"
|
|
250
|
-
```
|
|
251
|
-
3. **运行**:
|
|
237
|
+
3. **更新业务项目**:
|
|
252
238
|
```bash
|
|
253
|
-
|
|
239
|
+
cd your-business-project
|
|
240
|
+
yarn add com.jimuwd.xian.registry-proxy@latest --registry https://repo.jimuwd.com/jimuwd/~npm/
|
|
241
|
+
```
|
|
242
|
+
4. **运行**:
|
|
243
|
+
```bash
|
|
244
|
+
bash start-proxy.sh
|
|
254
245
|
```
|
|
255
|
-
|
|
256
|
-
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,11 @@ 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
|
-
// 读取独立的 .registry-proxy.yml
|
|
10
13
|
let proxyConfig = { registries: {} };
|
|
11
14
|
try {
|
|
12
15
|
const proxyYamlContent = await readFile(proxyConfigPath, 'utf8');
|
|
@@ -15,14 +18,13 @@ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYa
|
|
|
15
18
|
}
|
|
16
19
|
catch (e) {
|
|
17
20
|
console.error(`Failed to load ${proxyConfigPath}: ${e.message}`);
|
|
18
|
-
process.exit(1);
|
|
21
|
+
process.exit(1);
|
|
19
22
|
}
|
|
20
23
|
if (!proxyConfig.registries || !Object.keys(proxyConfig.registries).length) {
|
|
21
24
|
console.error(`No registries found in ${proxyConfigPath}`);
|
|
22
25
|
process.exit(1);
|
|
23
26
|
}
|
|
24
|
-
|
|
25
|
-
let localYarnConfig = {};
|
|
27
|
+
let localYarnConfig = { npmRegistries: {} };
|
|
26
28
|
try {
|
|
27
29
|
const localYamlContent = await readFile(localYarnConfigPath, 'utf8');
|
|
28
30
|
localYarnConfig = load(localYamlContent);
|
|
@@ -31,8 +33,7 @@ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYa
|
|
|
31
33
|
catch (e) {
|
|
32
34
|
console.warn(`Failed to load ${localYarnConfigPath}: ${e.message}`);
|
|
33
35
|
}
|
|
34
|
-
|
|
35
|
-
let globalYarnConfig = {};
|
|
36
|
+
let globalYarnConfig = { npmRegistries: {} };
|
|
36
37
|
try {
|
|
37
38
|
const globalYamlContent = await readFile(globalYarnConfigPath, 'utf8');
|
|
38
39
|
globalYarnConfig = load(globalYamlContent);
|
|
@@ -41,17 +42,24 @@ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYa
|
|
|
41
42
|
catch (e) {
|
|
42
43
|
console.warn(`Failed to load ${globalYarnConfigPath}: ${e.message}`);
|
|
43
44
|
}
|
|
44
|
-
//
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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]) => {
|
|
52
|
+
let token;
|
|
53
|
+
if (regConfig && 'npmAuthToken' in regConfig) {
|
|
54
|
+
token = regConfig.npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || regConfig.npmAuthToken;
|
|
55
|
+
}
|
|
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;
|
|
50
59
|
console.log(`Token for ${url} not found in ${proxyConfigPath}, using local Yarn config`);
|
|
51
60
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
token = globalYarnConfig.npmRegistries[url].npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || globalYarnConfig.npmRegistries[url].npmAuthToken;
|
|
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;
|
|
55
63
|
console.log(`Token for ${url} not found in local Yarn config, using global Yarn config`);
|
|
56
64
|
}
|
|
57
65
|
console.log(`Registry ${url}: token=${token ? 'present' : 'missing'}`);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -7,11 +7,15 @@ 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>; }
|
|
11
|
-
interface YarnConfig { npmRegistries?: Record<string, RegistryConfig>; }
|
|
10
|
+
interface ProxyConfig { registries: Record<string, RegistryConfig | null>; }
|
|
11
|
+
interface YarnConfig { npmRegistries?: Record<string, RegistryConfig | null>; }
|
|
12
|
+
|
|
13
|
+
// 规范化 URL,去除尾部斜杠
|
|
14
|
+
function normalizeUrl(url: string): string {
|
|
15
|
+
return url.endsWith('/') ? url.slice(0, -1) : url;
|
|
16
|
+
}
|
|
12
17
|
|
|
13
18
|
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
19
|
let proxyConfig: ProxyConfig = { registries: {} };
|
|
16
20
|
try {
|
|
17
21
|
const proxyYamlContent = await readFile(proxyConfigPath, 'utf8');
|
|
@@ -19,7 +23,7 @@ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYa
|
|
|
19
23
|
console.log(`Loaded proxy config from ${proxyConfigPath}`);
|
|
20
24
|
} catch (e) {
|
|
21
25
|
console.error(`Failed to load ${proxyConfigPath}: ${(e as Error).message}`);
|
|
22
|
-
process.exit(1);
|
|
26
|
+
process.exit(1);
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
if (!proxyConfig.registries || !Object.keys(proxyConfig.registries).length) {
|
|
@@ -27,8 +31,7 @@ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYa
|
|
|
27
31
|
process.exit(1);
|
|
28
32
|
}
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
let localYarnConfig: YarnConfig = {};
|
|
34
|
+
let localYarnConfig: YarnConfig = { npmRegistries: {} };
|
|
32
35
|
try {
|
|
33
36
|
const localYamlContent = await readFile(localYarnConfigPath, 'utf8');
|
|
34
37
|
localYarnConfig = load(localYamlContent) as YarnConfig;
|
|
@@ -37,8 +40,7 @@ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYa
|
|
|
37
40
|
console.warn(`Failed to load ${localYarnConfigPath}: ${(e as Error).message}`);
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
let globalYarnConfig: YarnConfig = {};
|
|
43
|
+
let globalYarnConfig: YarnConfig = { npmRegistries: {} };
|
|
42
44
|
try {
|
|
43
45
|
const globalYamlContent = await readFile(globalYarnConfigPath, 'utf8');
|
|
44
46
|
globalYarnConfig = load(globalYamlContent) as YarnConfig;
|
|
@@ -47,19 +49,28 @@ async function loadRegistries(proxyConfigPath = './.registry-proxy.yml', localYa
|
|
|
47
49
|
console.warn(`Failed to load ${globalYarnConfigPath}: ${(e as Error).message}`);
|
|
48
50
|
}
|
|
49
51
|
|
|
50
|
-
//
|
|
51
|
-
const
|
|
52
|
-
|
|
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]) => {
|
|
60
|
+
let token: string | undefined;
|
|
61
|
+
|
|
62
|
+
if (regConfig && 'npmAuthToken' in regConfig) {
|
|
63
|
+
token = regConfig.npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || regConfig.npmAuthToken;
|
|
64
|
+
}
|
|
53
65
|
|
|
54
|
-
|
|
55
|
-
if (!token && localYarnConfig.npmRegistries && localYarnConfig.npmRegistries[
|
|
56
|
-
token = localYarnConfig.npmRegistries[
|
|
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;
|
|
57
69
|
console.log(`Token for ${url} not found in ${proxyConfigPath}, using local Yarn config`);
|
|
58
70
|
}
|
|
59
71
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
token = globalYarnConfig.npmRegistries[url].npmAuthToken?.replace(/\${(.+)}/, (_, key) => process.env[key] || '') || globalYarnConfig.npmRegistries[url].npmAuthToken;
|
|
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;
|
|
63
74
|
console.log(`Token for ${url} not found in local Yarn config, using global Yarn config`);
|
|
64
75
|
}
|
|
65
76
|
|