@tedbrain/vlink 0.1.62 → 0.1.63
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 +10 -1
- package/binaries.json +8 -8
- package/installer.js +44 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,14 @@ npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest install
|
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
该命令会识别平台和架构,始终安装与当前 npm 包版本一致的 vlink,配置用户
|
|
12
|
-
PATH,并启动 `vlink setup tedbrain
|
|
12
|
+
PATH,并启动 `vlink setup tedbrain`。如果 PATH 中已有原生 vlink,会优先更新该位置;
|
|
13
|
+
旧文件或目录不可写时,自动回退到用户安装目录(Unix 为 `~/.local/bin`,Windows 为
|
|
14
|
+
`%LOCALAPPDATA%\TedBrain\bin`),保留原来的共享安装。显式设置 `VLINK_INSTALL_DIR`
|
|
15
|
+
时始终使用该目录,写入失败会报错,不会再改装到其他位置。
|
|
16
|
+
|
|
17
|
+
安装目录会优先加入当前安装进程的 PATH,补全和 setup 均使用新二进制的绝对路径。
|
|
18
|
+
默认目录还会写入 shell 配置或 Windows 用户 PATH;自定义 Unix 目录需要自行配置
|
|
19
|
+
永久 PATH。完成后请打开新终端,让 PATH 和 shell 命令缓存更新,再运行:
|
|
13
20
|
|
|
14
21
|
```bash
|
|
15
22
|
vlink --version
|
|
@@ -28,6 +35,8 @@ Windows 会在 `vlink.exe` 旁同时生成 `vlink.cmd`。安装目录加入用
|
|
|
28
35
|
npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest --version
|
|
29
36
|
```
|
|
30
37
|
|
|
38
|
+
安装命令会输出安装目标、权限回退原因及 setup 状态;失败时输出错误并返回非零退出码。
|
|
39
|
+
|
|
31
40
|
手动配置 Agent 时可以只安装或更新 vlink,并跳过 TedBrain 配置向导:
|
|
32
41
|
|
|
33
42
|
```bash
|
package/binaries.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.63",
|
|
3
3
|
"binaries": {
|
|
4
|
-
"linux-x86_64": "
|
|
5
|
-
"linux-x86_64-glibc2.17": "
|
|
6
|
-
"linux-aarch64": "
|
|
7
|
-
"macos-x86_64": "
|
|
8
|
-
"macos-aarch64": "
|
|
9
|
-
"windows-x86_64.exe": "
|
|
10
|
-
"windows-aarch64.exe": "
|
|
4
|
+
"linux-x86_64": "dffb9115be72e1b1546e5d5adc9a208de7ac869f89cfc1692edb8ef60a05e8d1",
|
|
5
|
+
"linux-x86_64-glibc2.17": "0acfdaec9e600817d55a389b9889c476dbfa9842768c9e431ef3c44df7e0fa5a",
|
|
6
|
+
"linux-aarch64": "f8a3a086cf963db72d380e410c5264dc25659c44f3770597bc36d3021bf2376c",
|
|
7
|
+
"macos-x86_64": "bc917cf21d802dc804acdcbd06eb769cd520a12475b25db9e8238036db7383ed",
|
|
8
|
+
"macos-aarch64": "14b831e1f7ff7b09def2efc34e74d0a05d437cd1650c1c6f3c254cd08fc48b64",
|
|
9
|
+
"windows-x86_64.exe": "c9ca055f7791b095f8cc958ffa0fab4d01eb0fa9b36801e25a51982ceeaf30fd",
|
|
10
|
+
"windows-aarch64.exe": "717d470b48a10b1a16d897e56738447b3b7d6128cf02ea8f428e481117e80cd4"
|
|
11
11
|
}
|
|
12
12
|
}
|
package/installer.js
CHANGED
|
@@ -8,6 +8,8 @@ const { spawnSync } = require('child_process');
|
|
|
8
8
|
|
|
9
9
|
const installModule = require('./install');
|
|
10
10
|
|
|
11
|
+
const PERMISSION_ERRORS = new Set(['EACCES', 'EPERM', 'EROFS']);
|
|
12
|
+
|
|
11
13
|
const CURRENT_WRAPPER = path.resolve(__dirname, 'bin', 'vlink.js');
|
|
12
14
|
|
|
13
15
|
class VlinkSetupError extends Error {}
|
|
@@ -110,8 +112,8 @@ function prependEnvironmentPath(directory, env, platform) {
|
|
|
110
112
|
const entries = String(current)
|
|
111
113
|
.split(delimiter)
|
|
112
114
|
.filter(Boolean);
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
+
const next = [directory, ...entries.filter((entry) => !samePath(entry, directory, platform))]
|
|
116
|
+
.join(delimiter);
|
|
115
117
|
|
|
116
118
|
for (const key of Object.keys(env)) {
|
|
117
119
|
if (key.toLowerCase() === 'path') delete env[key];
|
|
@@ -137,8 +139,9 @@ function updateWindowsUserPath(directory, options) {
|
|
|
137
139
|
"$entry = $env:TEDBRAIN_INSTALL_DIR.TrimEnd('\\')",
|
|
138
140
|
"$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')",
|
|
139
141
|
"$entries = @($userPath -split ';' | Where-Object { $_ })",
|
|
140
|
-
"
|
|
141
|
-
"
|
|
142
|
+
"$remaining = @($entries | Where-Object { $_.TrimEnd('\\') -ine $entry })",
|
|
143
|
+
"$newPath = (@($env:TEDBRAIN_INSTALL_DIR) + $remaining) -join ';'",
|
|
144
|
+
"if ($newPath -cne $userPath) {",
|
|
142
145
|
" [Environment]::SetEnvironmentVariable('Path', $newPath, 'User')",
|
|
143
146
|
" Write-Output 'changed'",
|
|
144
147
|
"}"
|
|
@@ -293,7 +296,7 @@ function installBinary(sourcePath, targetPath, options = {}) {
|
|
|
293
296
|
|
|
294
297
|
if (options.stopDaemon) {
|
|
295
298
|
log('stopping the existing vlink daemon before replacement', output);
|
|
296
|
-
const stop = spawnSyncImpl(sourcePath, ['daemon', 'stop'], { stdio: 'inherit' });
|
|
299
|
+
const stop = spawnSyncImpl(sourcePath, ['daemon', 'stop'], { stdio: 'inherit', env: options.env });
|
|
297
300
|
const failure = commandFailure(stop, 'vlink daemon stop');
|
|
298
301
|
if (failure) throw new VlinkSetupError(failure);
|
|
299
302
|
}
|
|
@@ -311,7 +314,9 @@ function installBinary(sourcePath, targetPath, options = {}) {
|
|
|
311
314
|
fsImpl.renameSync(temporary, targetPath);
|
|
312
315
|
} catch (error) {
|
|
313
316
|
fsImpl.rmSync(temporary, { force: true });
|
|
314
|
-
|
|
317
|
+
const failure = new VlinkSetupError(`failed to install vlink at ${targetPath}: ${error.message}`);
|
|
318
|
+
failure.code = error.code;
|
|
319
|
+
throw failure;
|
|
315
320
|
}
|
|
316
321
|
fsImpl.rmSync(temporary, { force: true });
|
|
317
322
|
log(`installed vlink at ${targetPath}`, output);
|
|
@@ -364,6 +369,7 @@ function installShellCompletion(vlinkPath, options = {}) {
|
|
|
364
369
|
vlinkPath,
|
|
365
370
|
['completion', '--install', '--quiet'],
|
|
366
371
|
{
|
|
372
|
+
env: options.env,
|
|
367
373
|
encoding: 'utf8',
|
|
368
374
|
stdio: ['ignore', 'pipe', 'pipe']
|
|
369
375
|
}
|
|
@@ -423,7 +429,7 @@ async function runInstaller(options = {}) {
|
|
|
423
429
|
: env.VLINK_GLIBC_VERSION,
|
|
424
430
|
spawnSync: spawnSyncImpl
|
|
425
431
|
});
|
|
426
|
-
const installDir = defaultInstallDir(spec, env, home);
|
|
432
|
+
const installDir = path.resolve(defaultInstallDir(spec, env, home));
|
|
427
433
|
const targetPath = installPathFor(spec, installDir);
|
|
428
434
|
const sharedOptions = {
|
|
429
435
|
env,
|
|
@@ -447,7 +453,6 @@ async function runInstaller(options = {}) {
|
|
|
447
453
|
);
|
|
448
454
|
} else if (isExecutableFile(targetPath, platform, fsImpl)) {
|
|
449
455
|
vlinkPath = targetPath;
|
|
450
|
-
ensureUserPath(installDir, sharedOptions);
|
|
451
456
|
log(
|
|
452
457
|
`found vlink at ${vlinkPath}; installing vlink ${installModule.VERSION}`,
|
|
453
458
|
output
|
|
@@ -457,16 +462,35 @@ async function runInstaller(options = {}) {
|
|
|
457
462
|
}
|
|
458
463
|
|
|
459
464
|
const replacingExisting = Boolean(vlinkPath);
|
|
460
|
-
|
|
465
|
+
let installTarget = env.VLINK_INSTALL_DIR ? targetPath : (vlinkPath || targetPath);
|
|
466
|
+
// Avoid trying to replace a shared installation, even if its parent is writable.
|
|
467
|
+
if (vlinkPath && !env.VLINK_INSTALL_DIR && !samePath(vlinkPath, targetPath, platform)) {
|
|
468
|
+
try {
|
|
469
|
+
fsImpl.accessSync(vlinkPath, fs.constants.W_OK);
|
|
470
|
+
fsImpl.accessSync(path.dirname(vlinkPath), fs.constants.W_OK);
|
|
471
|
+
} catch (error) {
|
|
472
|
+
if (!PERMISSION_ERRORS.has(error.code)) throw error;
|
|
473
|
+
log(`cannot replace ${vlinkPath} (${error.code}); falling back to ${targetPath}`, output);
|
|
474
|
+
installTarget = targetPath;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
installTarget = path.resolve(installTarget);
|
|
478
|
+
log(`installation target: ${installTarget}`, output);
|
|
461
479
|
const sourcePath = await ensureBinary({});
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
480
|
+
try {
|
|
481
|
+
installBinary(sourcePath, installTarget, {
|
|
482
|
+
...sharedOptions,
|
|
483
|
+
stopDaemon: replacingExisting
|
|
484
|
+
});
|
|
485
|
+
} catch (error) {
|
|
486
|
+
// Permissions may change after the access check, or an ACL can deny rename.
|
|
487
|
+
if (env.VLINK_INSTALL_DIR || samePath(installTarget, targetPath, platform) ||
|
|
488
|
+
!PERMISSION_ERRORS.has(error.code)) throw error;
|
|
489
|
+
log(`cannot replace ${installTarget} (${error.code}); falling back to ${targetPath}`, output);
|
|
490
|
+
installTarget = targetPath;
|
|
491
|
+
installBinary(sourcePath, installTarget, sharedOptions);
|
|
492
|
+
}
|
|
493
|
+
if (samePath(path.dirname(installTarget), installDir, platform)) {
|
|
470
494
|
ensureUserPath(installDir, sharedOptions);
|
|
471
495
|
}
|
|
472
496
|
vlinkPath = installTarget;
|
|
@@ -483,12 +507,15 @@ async function runInstaller(options = {}) {
|
|
|
483
507
|
} else {
|
|
484
508
|
log('starting TedBrain Agent setup', output);
|
|
485
509
|
const setup = spawnSyncImpl(vlinkPath, ['setup', 'tedbrain'], {
|
|
510
|
+
env,
|
|
486
511
|
stdio: 'inherit'
|
|
487
512
|
});
|
|
488
513
|
const failure = commandFailure(setup, 'vlink setup tedbrain');
|
|
489
514
|
if (failure) throw new VlinkSetupError(failure);
|
|
490
515
|
}
|
|
491
516
|
|
|
517
|
+
log(`installation complete: ${vlinkPath}`, output);
|
|
518
|
+
log('open a new terminal to use the updated PATH', output);
|
|
492
519
|
return { installDir, vlinkPath, commandShimPath, setupSkipped: skipSetup };
|
|
493
520
|
}
|
|
494
521
|
|
package/package.json
CHANGED