@tedbrain/vlink 0.1.63 → 0.1.64
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 +23 -0
- package/bin/vlink.js +35 -2
- package/binaries.json +8 -8
- package/install.js +51 -4
- package/installer.js +78 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,6 +37,29 @@ npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest --versio
|
|
|
37
37
|
|
|
38
38
|
安装命令会输出安装目标、权限回退原因及 setup 状态;失败时输出错误并返回非零退出码。
|
|
39
39
|
|
|
40
|
+
需要排查安装过程时,加上 `--verbose`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx --registry=https://registry.npmmirror.com -y \
|
|
44
|
+
@tedbrain/vlink@latest install --verbose
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
verbose 会从 npm 包的 JavaScript wrapper 开始输出 Node、包版本、平台选择、PATH
|
|
48
|
+
查找、权限检查、二进制缓存或下载、复制、补全和 setup 各阶段。也可以设置
|
|
49
|
+
`VLINK_VERBOSE=1`。日志不会打印完整环境变量、registry 凭据或下载 URL 的查询参数。
|
|
50
|
+
|
|
51
|
+
如果上面的命令连 `[TedBrain:verbose] wrapper entered` 都没有输出,使用 npm 的显式
|
|
52
|
+
package 形式,绕过 npx 的命令推断:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm exec --registry=https://registry.npmmirror.com \
|
|
56
|
+
--package=@tedbrain/vlink@latest -- \
|
|
57
|
+
vlink install --verbose
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
若显式形式可以输出,问题发生在本机 npx 的参数路由或缓存阶段;若仍无 wrapper
|
|
61
|
+
输出,可再加 npm 自身的 `--loglevel verbose` 检查 npm 在执行包之前的行为。
|
|
62
|
+
|
|
40
63
|
手动配置 Agent 时可以只安装或更新 vlink,并跳过 TedBrain 配置向导:
|
|
41
64
|
|
|
42
65
|
```bash
|
package/bin/vlink.js
CHANGED
|
@@ -2,12 +2,45 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const { spawn } = require('child_process');
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
|
|
6
|
+
function verboseEnabled(args, env = process.env) {
|
|
7
|
+
const value = String(env.VLINK_VERBOSE || '').toLowerCase();
|
|
8
|
+
return args[0] === 'install' && (
|
|
9
|
+
args.includes('--verbose') || ['1', 'true', 'yes', 'on'].includes(value)
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function verbose(message) {
|
|
14
|
+
process.stderr.write(`[TedBrain:verbose] ${message}\n`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function diagnosticArgs(args) {
|
|
18
|
+
const safe = new Set(['install', '--verbose', '--no-setup', '--help', '-h']);
|
|
19
|
+
return args.map((arg) => {
|
|
20
|
+
if (safe.has(arg)) return arg;
|
|
21
|
+
if (arg.startsWith('--')) return arg.split('=', 1)[0];
|
|
22
|
+
return '<argument>';
|
|
23
|
+
});
|
|
24
|
+
}
|
|
7
25
|
|
|
8
26
|
async function main() {
|
|
9
27
|
const args = process.argv.slice(2);
|
|
28
|
+
const diagnostic = verboseEnabled(args);
|
|
29
|
+
if (diagnostic) {
|
|
30
|
+
process.env.VLINK_VERBOSE = '1';
|
|
31
|
+
verbose('wrapper entered');
|
|
32
|
+
verbose(`node=${process.version} executable=${process.execPath}`);
|
|
33
|
+
verbose(`wrapper=${__filename}`);
|
|
34
|
+
verbose(`cwd=${process.cwd()}`);
|
|
35
|
+
verbose(`argv=${JSON.stringify(diagnosticArgs(args))}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const { ensureBinary, VERSION } = require('../install');
|
|
39
|
+
const { runInstallerFromArgs } = require('../installer');
|
|
40
|
+
if (diagnostic) verbose(`package version=${VERSION}`);
|
|
41
|
+
|
|
10
42
|
if (args[0] === 'install') {
|
|
43
|
+
if (diagnostic) verbose('dispatching install command');
|
|
11
44
|
await runInstallerFromArgs(args.slice(1));
|
|
12
45
|
return;
|
|
13
46
|
}
|
package/binaries.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.64",
|
|
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": "cd46ed189a1cb56a4d2ff84af7cda6a4870ad202f6172500e02a29654cb82b54",
|
|
5
|
+
"linux-x86_64-glibc2.17": "d578c70bafe98de520b25e78ea10919a12cb14fff0524ab3339bb0d912a78961",
|
|
6
|
+
"linux-aarch64": "8acbcce5bd84e14652f778ab987abe2a9f461b3ba4bb0dbe4022f8900a42868e",
|
|
7
|
+
"macos-x86_64": "5e96d897d75dc02a0e8acca05bfb8a5910751d38b10de0eda9f1c0ae9ac6df13",
|
|
8
|
+
"macos-aarch64": "8481807cd40cac885908550959e259164eaf9d2a20f10e2972c57a5f3e125815",
|
|
9
|
+
"windows-x86_64.exe": "90a2a090f993bc6258ccddacf62aa05d99d96b411a39a041cf2e6f19c6f8fd69",
|
|
10
|
+
"windows-aarch64.exe": "e96d0dcbfde313747a62cb7b5f945cfdf444927f40e758f25ed06da6c0d517b6"
|
|
11
11
|
}
|
|
12
12
|
}
|
package/install.js
CHANGED
|
@@ -26,6 +26,31 @@ const GLIBC217_SUFFIX = 'linux-x86_64-glibc2.17';
|
|
|
26
26
|
|
|
27
27
|
class VlinkInstallError extends Error {}
|
|
28
28
|
|
|
29
|
+
function verboseEnabled(options = {}) {
|
|
30
|
+
if (options.verbose === true) return true;
|
|
31
|
+
return ['1', 'true', 'yes', 'on'].includes(
|
|
32
|
+
String(process.env.VLINK_VERBOSE || '').toLowerCase()
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function verboseLog(message, options = {}) {
|
|
37
|
+
if (!verboseEnabled(options)) return;
|
|
38
|
+
(options.output || process.stderr).write(`[vlink:verbose] ${message}\n`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function displayUrl(value) {
|
|
42
|
+
try {
|
|
43
|
+
const url = new URL(value);
|
|
44
|
+
url.username = '';
|
|
45
|
+
url.password = '';
|
|
46
|
+
url.search = '';
|
|
47
|
+
url.hash = '';
|
|
48
|
+
return url.toString();
|
|
49
|
+
} catch {
|
|
50
|
+
return '<invalid-url>';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
29
54
|
function parseGlibcVersion(text) {
|
|
30
55
|
for (const line of String(text || '').split(/\r?\n/)) {
|
|
31
56
|
const glibcMatch = line.match(/\bglibc\s+([0-9]+(?:\.[0-9]+)+)/);
|
|
@@ -137,7 +162,7 @@ function httpGetText(url) {
|
|
|
137
162
|
if (res.statusCode !== 200) {
|
|
138
163
|
res.resume();
|
|
139
164
|
return reject(
|
|
140
|
-
new VlinkInstallError(`HTTP ${res.statusCode} from ${target}`)
|
|
165
|
+
new VlinkInstallError(`HTTP ${res.statusCode} from ${displayUrl(target)}`)
|
|
141
166
|
);
|
|
142
167
|
}
|
|
143
168
|
|
|
@@ -308,7 +333,9 @@ function downloadFile(url, destPath) {
|
|
|
308
333
|
if (res.statusCode !== 200) {
|
|
309
334
|
res.resume();
|
|
310
335
|
return reject(
|
|
311
|
-
new VlinkInstallError(
|
|
336
|
+
new VlinkInstallError(
|
|
337
|
+
`download failed: HTTP ${res.statusCode} from ${displayUrl(target)}`
|
|
338
|
+
)
|
|
312
339
|
);
|
|
313
340
|
}
|
|
314
341
|
res.pipe(fileStream);
|
|
@@ -339,14 +366,23 @@ function verifyBinary(binaryPath) {
|
|
|
339
366
|
}
|
|
340
367
|
}
|
|
341
368
|
|
|
342
|
-
async function ensureBinary(
|
|
369
|
+
async function ensureBinary(options = {}) {
|
|
370
|
+
const force = options.force === true;
|
|
343
371
|
const spec = platformSpec();
|
|
344
372
|
const binaryPath = resolveBinaryPath(spec);
|
|
373
|
+
verboseLog(
|
|
374
|
+
`binary resolver: version=${VERSION} platform=${spec.platform}/${spec.arch} ` +
|
|
375
|
+
`suffixes=${spec.suffixes.join(',')}`,
|
|
376
|
+
options
|
|
377
|
+
);
|
|
378
|
+
verboseLog(`binary resolver: selected path=${binaryPath} force=${force}`, options);
|
|
345
379
|
if (!force && isExecutable(binaryPath)) {
|
|
380
|
+
verboseLog('binary resolver: using existing executable', options);
|
|
346
381
|
return binaryPath;
|
|
347
382
|
}
|
|
348
383
|
|
|
349
384
|
const dir = path.dirname(binaryPath);
|
|
385
|
+
verboseLog(`binary resolver: creating download directory ${dir}`, options);
|
|
350
386
|
fs.mkdirSync(dir, { recursive: true });
|
|
351
387
|
|
|
352
388
|
let lastError = new VlinkInstallError('no download source available');
|
|
@@ -354,15 +390,22 @@ async function ensureBinary({ force = false } = {}) {
|
|
|
354
390
|
for (const suffix of spec.suffixes) {
|
|
355
391
|
const tempPath = path.join(dir, `.${spec.binaryName}.download-${process.pid}`);
|
|
356
392
|
const sources = buildDownloadSources(spec, suffix);
|
|
393
|
+
verboseLog(
|
|
394
|
+
`download stage: suffix=${suffix} sources=${sources.map((source) => source.name).join(',')}`,
|
|
395
|
+
options
|
|
396
|
+
);
|
|
357
397
|
for (const source of sources) {
|
|
358
398
|
try {
|
|
399
|
+
verboseLog(`download stage: resolving ${source.name}`, options);
|
|
359
400
|
const url = await source.resolve();
|
|
360
|
-
console.error(`[vlink] downloading ${url} [${source.name}]`);
|
|
401
|
+
console.error(`[vlink] downloading ${displayUrl(url)} [${source.name}]`);
|
|
361
402
|
fs.rmSync(tempPath, { force: true });
|
|
362
403
|
await downloadFile(url, tempPath);
|
|
404
|
+
verboseLog(`download stage: received ${source.name} payload`, options);
|
|
363
405
|
|
|
364
406
|
const checksum = expectedChecksum(spec, suffix);
|
|
365
407
|
if (checksum) {
|
|
408
|
+
verboseLog(`verification stage: checking SHA-256 for ${suffix}`, options);
|
|
366
409
|
const actual = await sha256File(tempPath);
|
|
367
410
|
if (actual !== checksum) {
|
|
368
411
|
throw new VlinkInstallError(
|
|
@@ -376,7 +419,9 @@ async function ensureBinary({ force = false } = {}) {
|
|
|
376
419
|
}
|
|
377
420
|
if (fs.existsSync(binaryPath)) fs.rmSync(binaryPath, { force: true });
|
|
378
421
|
fs.renameSync(tempPath, binaryPath);
|
|
422
|
+
verboseLog(`verification stage: executing ${binaryPath} -V`, options);
|
|
379
423
|
verifyBinary(binaryPath);
|
|
424
|
+
verboseLog('verification stage: binary is ready', options);
|
|
380
425
|
return binaryPath;
|
|
381
426
|
} catch (err) {
|
|
382
427
|
lastError = err;
|
|
@@ -393,6 +438,8 @@ module.exports = {
|
|
|
393
438
|
VlinkInstallError,
|
|
394
439
|
VERSION,
|
|
395
440
|
GLIBC217_SUFFIX,
|
|
441
|
+
verboseEnabled,
|
|
442
|
+
displayUrl,
|
|
396
443
|
parseGlibcVersion,
|
|
397
444
|
glibcVersion,
|
|
398
445
|
versionAtLeast,
|
package/installer.js
CHANGED
|
@@ -18,6 +18,20 @@ function log(message, output = process.stderr) {
|
|
|
18
18
|
output.write(`[TedBrain] ${message}\n`);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
function verboseEnabled(options = {}) {
|
|
22
|
+
if (options.verbose === true) return true;
|
|
23
|
+
const env = options.env || process.env;
|
|
24
|
+
return ['1', 'true', 'yes', 'on'].includes(
|
|
25
|
+
String(env.VLINK_VERBOSE || '').toLowerCase()
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function verboseLog(message, options = {}) {
|
|
30
|
+
if (!verboseEnabled(options)) return;
|
|
31
|
+
const output = options.output || process.stderr;
|
|
32
|
+
output.write(`[TedBrain:verbose] ${message}\n`);
|
|
33
|
+
}
|
|
34
|
+
|
|
21
35
|
function environmentValue(env, name) {
|
|
22
36
|
const expected = name.toLowerCase();
|
|
23
37
|
for (const key of Object.keys(env)) {
|
|
@@ -170,6 +184,7 @@ function ensureUserPath(installDir, options = {}) {
|
|
|
170
184
|
const fsImpl = options.fs || fs;
|
|
171
185
|
const output = options.output || process.stderr;
|
|
172
186
|
|
|
187
|
+
verboseLog(`PATH stage: prioritizing ${installDir}`, options);
|
|
173
188
|
prependEnvironmentPath(installDir, env, platform);
|
|
174
189
|
|
|
175
190
|
if (platform === 'win32') {
|
|
@@ -291,7 +306,11 @@ function installBinary(sourcePath, targetPath, options = {}) {
|
|
|
291
306
|
const spawnSyncImpl = options.spawnSync || spawnSync;
|
|
292
307
|
const output = options.output || process.stderr;
|
|
293
308
|
|
|
294
|
-
if (samePath(sourcePath, targetPath, platform))
|
|
309
|
+
if (samePath(sourcePath, targetPath, platform)) {
|
|
310
|
+
verboseLog(`copy stage: source already equals target ${targetPath}`, options);
|
|
311
|
+
return targetPath;
|
|
312
|
+
}
|
|
313
|
+
verboseLog(`copy stage: ${sourcePath} -> ${targetPath}`, options);
|
|
295
314
|
fsImpl.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
296
315
|
|
|
297
316
|
if (options.stopDaemon) {
|
|
@@ -365,6 +384,7 @@ function installWindowsCommandShim(vlinkPath, options = {}) {
|
|
|
365
384
|
function installShellCompletion(vlinkPath, options = {}) {
|
|
366
385
|
const spawnSyncImpl = options.spawnSync || spawnSync;
|
|
367
386
|
const output = options.output || process.stderr;
|
|
387
|
+
verboseLog(`completion stage: executing ${vlinkPath}`, options);
|
|
368
388
|
const result = spawnSyncImpl(
|
|
369
389
|
vlinkPath,
|
|
370
390
|
['completion', '--install', '--quiet'],
|
|
@@ -400,7 +420,11 @@ async function migrateStaticVlink(vlinkPath, spec, options) {
|
|
|
400
420
|
if (!binaryIsStaticElf(vlinkPath, options)) return vlinkPath;
|
|
401
421
|
|
|
402
422
|
log('migrating the installed static vlink to the glibc 2.17 build', options.output);
|
|
403
|
-
const sourcePath = await options.ensureBinary({
|
|
423
|
+
const sourcePath = await options.ensureBinary({
|
|
424
|
+
force: true,
|
|
425
|
+
verbose: verboseEnabled(options),
|
|
426
|
+
output: options.output
|
|
427
|
+
});
|
|
404
428
|
return installBinary(sourcePath, vlinkPath, {
|
|
405
429
|
...options,
|
|
406
430
|
stopDaemon: true
|
|
@@ -412,6 +436,7 @@ async function runInstaller(options = {}) {
|
|
|
412
436
|
const platform = options.platform || env.VLINK_PLATFORM || process.platform;
|
|
413
437
|
const arch = options.arch || env.VLINK_ARCH || process.arch;
|
|
414
438
|
const skipSetup = Boolean(options.skipSetup);
|
|
439
|
+
const verbose = verboseEnabled(options);
|
|
415
440
|
const home = options.home || os.homedir();
|
|
416
441
|
const fsImpl = options.fs || fs;
|
|
417
442
|
const output = options.output || process.stderr;
|
|
@@ -420,6 +445,17 @@ async function runInstaller(options = {}) {
|
|
|
420
445
|
const ensureBinary =
|
|
421
446
|
options.ensureBinary || ((settings) => installModule.ensureBinary(settings));
|
|
422
447
|
|
|
448
|
+
verboseLog(
|
|
449
|
+
`installer entered: package=${installModule.VERSION} platform=${platform} arch=${arch}`,
|
|
450
|
+
{ ...options, env, output, verbose }
|
|
451
|
+
);
|
|
452
|
+
verboseLog(`runtime: node=${process.version} executable=${process.execPath}`, {
|
|
453
|
+
...options,
|
|
454
|
+
env,
|
|
455
|
+
output,
|
|
456
|
+
verbose
|
|
457
|
+
});
|
|
458
|
+
|
|
423
459
|
const spec = platformSpec({
|
|
424
460
|
platform,
|
|
425
461
|
arch,
|
|
@@ -437,14 +473,32 @@ async function runInstaller(options = {}) {
|
|
|
437
473
|
home,
|
|
438
474
|
fs: fsImpl,
|
|
439
475
|
output,
|
|
440
|
-
spawnSync: spawnSyncImpl
|
|
476
|
+
spawnSync: spawnSyncImpl,
|
|
477
|
+
verbose
|
|
441
478
|
};
|
|
442
479
|
|
|
480
|
+
verboseLog(
|
|
481
|
+
`platform stage: suffixes=${spec.suffixes.join(',')} binary=${spec.binaryName}`,
|
|
482
|
+
sharedOptions
|
|
483
|
+
);
|
|
484
|
+
verboseLog(
|
|
485
|
+
`target stage: installDir=${installDir} configured=${Boolean(env.VLINK_INSTALL_DIR)}`,
|
|
486
|
+
sharedOptions
|
|
487
|
+
);
|
|
488
|
+
const pathEntries = String(environmentValue(env, 'PATH'))
|
|
489
|
+
.split(platform === 'win32' ? ';' : path.delimiter)
|
|
490
|
+
.filter(Boolean).length;
|
|
491
|
+
verboseLog(`PATH stage: inspecting ${pathEntries} entries`, sharedOptions);
|
|
492
|
+
|
|
443
493
|
let vlinkPath = findOnPath(spec.binaryName, {
|
|
444
494
|
env,
|
|
445
495
|
platform,
|
|
446
496
|
fs: fsImpl
|
|
447
497
|
});
|
|
498
|
+
verboseLog(
|
|
499
|
+
`discovery stage: native PATH binary=${vlinkPath || 'none'}`,
|
|
500
|
+
sharedOptions
|
|
501
|
+
);
|
|
448
502
|
|
|
449
503
|
if (vlinkPath) {
|
|
450
504
|
log(
|
|
@@ -465,9 +519,11 @@ async function runInstaller(options = {}) {
|
|
|
465
519
|
let installTarget = env.VLINK_INSTALL_DIR ? targetPath : (vlinkPath || targetPath);
|
|
466
520
|
// Avoid trying to replace a shared installation, even if its parent is writable.
|
|
467
521
|
if (vlinkPath && !env.VLINK_INSTALL_DIR && !samePath(vlinkPath, targetPath, platform)) {
|
|
522
|
+
verboseLog(`permission stage: checking ${vlinkPath} and its parent directory`, sharedOptions);
|
|
468
523
|
try {
|
|
469
524
|
fsImpl.accessSync(vlinkPath, fs.constants.W_OK);
|
|
470
525
|
fsImpl.accessSync(path.dirname(vlinkPath), fs.constants.W_OK);
|
|
526
|
+
verboseLog('permission stage: existing installation is replaceable', sharedOptions);
|
|
471
527
|
} catch (error) {
|
|
472
528
|
if (!PERMISSION_ERRORS.has(error.code)) throw error;
|
|
473
529
|
log(`cannot replace ${vlinkPath} (${error.code}); falling back to ${targetPath}`, output);
|
|
@@ -476,7 +532,9 @@ async function runInstaller(options = {}) {
|
|
|
476
532
|
}
|
|
477
533
|
installTarget = path.resolve(installTarget);
|
|
478
534
|
log(`installation target: ${installTarget}`, output);
|
|
479
|
-
|
|
535
|
+
verboseLog('binary stage: resolving packaged or cached binary', sharedOptions);
|
|
536
|
+
const sourcePath = await ensureBinary({ verbose, output });
|
|
537
|
+
verboseLog(`binary stage: source=${sourcePath}`, sharedOptions);
|
|
480
538
|
try {
|
|
481
539
|
installBinary(sourcePath, installTarget, {
|
|
482
540
|
...sharedOptions,
|
|
@@ -500,18 +558,24 @@ async function runInstaller(options = {}) {
|
|
|
500
558
|
ensureBinary
|
|
501
559
|
});
|
|
502
560
|
const commandShimPath = installWindowsCommandShim(vlinkPath, sharedOptions);
|
|
561
|
+
verboseLog(
|
|
562
|
+
`shim stage: ${commandShimPath || 'not required on this platform'}`,
|
|
563
|
+
sharedOptions
|
|
564
|
+
);
|
|
503
565
|
installShellCompletion(vlinkPath, sharedOptions);
|
|
504
566
|
|
|
505
567
|
if (skipSetup) {
|
|
506
568
|
log('skipping TedBrain Agent setup', output);
|
|
507
569
|
} else {
|
|
508
570
|
log('starting TedBrain Agent setup', output);
|
|
571
|
+
verboseLog(`setup stage: executing ${vlinkPath} setup tedbrain`, sharedOptions);
|
|
509
572
|
const setup = spawnSyncImpl(vlinkPath, ['setup', 'tedbrain'], {
|
|
510
573
|
env,
|
|
511
574
|
stdio: 'inherit'
|
|
512
575
|
});
|
|
513
576
|
const failure = commandFailure(setup, 'vlink setup tedbrain');
|
|
514
577
|
if (failure) throw new VlinkSetupError(failure);
|
|
578
|
+
verboseLog('setup stage: completed successfully', sharedOptions);
|
|
515
579
|
}
|
|
516
580
|
|
|
517
581
|
log(`installation complete: ${vlinkPath}`, output);
|
|
@@ -522,11 +586,12 @@ async function runInstaller(options = {}) {
|
|
|
522
586
|
function printInstallHelp(output = process.stdout) {
|
|
523
587
|
output.write(
|
|
524
588
|
[
|
|
525
|
-
'Usage: npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest install [--no-setup]',
|
|
589
|
+
'Usage: npx --registry=https://registry.npmmirror.com -y @tedbrain/vlink@latest install [--no-setup] [--verbose]',
|
|
526
590
|
'',
|
|
527
591
|
'Installs or updates vlink and adds it to the user PATH.',
|
|
528
592
|
'',
|
|
529
|
-
' --no-setup Install without starting the TedBrain setup wizard.'
|
|
593
|
+
' --no-setup Install without starting the TedBrain setup wizard.',
|
|
594
|
+
' --verbose Print diagnostics for every installation stage.'
|
|
530
595
|
].join('\n') + '\n'
|
|
531
596
|
);
|
|
532
597
|
}
|
|
@@ -538,18 +603,23 @@ async function runInstallerFromArgs(args, options = {}) {
|
|
|
538
603
|
}
|
|
539
604
|
|
|
540
605
|
let skipSetup = false;
|
|
606
|
+
let verbose = verboseEnabled(options);
|
|
541
607
|
for (const arg of args) {
|
|
542
608
|
if (arg === '--no-setup') {
|
|
543
609
|
skipSetup = true;
|
|
610
|
+
} else if (arg === '--verbose') {
|
|
611
|
+
verbose = true;
|
|
544
612
|
} else {
|
|
545
|
-
|
|
613
|
+
const displayArg = arg.startsWith('--') ? arg.split('=', 1)[0] : '<argument>';
|
|
614
|
+
throw new VlinkSetupError(`unknown install option: ${displayArg}`);
|
|
546
615
|
}
|
|
547
616
|
}
|
|
548
|
-
return runInstaller({ ...options, skipSetup });
|
|
617
|
+
return runInstaller({ ...options, skipSetup, verbose });
|
|
549
618
|
}
|
|
550
619
|
|
|
551
620
|
module.exports = {
|
|
552
621
|
VlinkSetupError,
|
|
622
|
+
verboseEnabled,
|
|
553
623
|
defaultInstallDir,
|
|
554
624
|
installPathFor,
|
|
555
625
|
isExecutableFile,
|
package/package.json
CHANGED