redblue-cli 0.1.0-next.50 → 0.1.0-next.52

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 CHANGED
@@ -156,6 +156,11 @@ npm exec --package redblue-cli rb -- tls security audit github.com
156
156
  # Install the wrapper in a project
157
157
  npm install redblue-cli
158
158
  npx rb network ports scan 192.168.1.1 --preset common
159
+
160
+ # Let the wrapper manage the release binary
161
+ npx redblue-cli --install --print-binary-path
162
+ npx redblue-cli --check-update
163
+ npx redblue-cli --upgrade --channel next
159
164
  ```
160
165
 
161
166
  ```js
@@ -633,9 +638,9 @@ const { createClient } = require('redblue-cli');
633
638
  })();
634
639
  ```
635
640
 
636
- If you want the wrapper to manage the binary for you, use `autoDownload: true` with a `targetDir`.
641
+ If you want the wrapper to manage the binary for you, use `--install`, `--check-update`, or `--upgrade`. Managed installs default to `~/.local/bin`, and the wrapper still detects legacy installs in `~/.redblue/bin`. For SDK consumers, `autoDownload: true` still works and can be combined with a custom `targetDir`.
637
642
 
638
- > **Note:** the exact command `npx rb` works after `redblue-cli` is installed in the project or globally. For zero-install usage, prefer `npx redblue-cli ...` or `npm exec --package redblue-cli rb -- ...`.
643
+ > **Note:** the exact command `npx rb` works after `redblue-cli` is installed in the project or globally. For zero-install usage, prefer `npx redblue-cli ...` or `npm exec --package redblue-cli rb -- ...`. Use bare `rb --version` to query the real binary version; use wrapper `--version <tag>` or `--release-version <tag>` before the command when you want to pin a release download.
639
644
 
640
645
  ### Build from Source
641
646
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redblue-cli",
3
- "version": "0.1.0-next.50+ae22e15",
3
+ "version": "0.1.0-next.52+be56ddf",
4
4
  "description": "JavaScript SDK wrapper for the redblue CLI",
5
5
  "type": "commonjs",
6
6
  "main": "./sdk/redblue-sdk.js",
@@ -20,13 +20,19 @@ const WRAPPER_OPTION_TYPES = Object.freeze({
20
20
  'auto-download': 'boolean',
21
21
  'binary-path': 'string',
22
22
  channel: 'string',
23
+ 'check-update': 'boolean',
23
24
  download: 'boolean',
25
+ force: 'boolean',
24
26
  'github-token': 'string',
27
+ install: 'boolean',
25
28
  'no-verify': 'boolean',
29
+ 'print-binary-path': 'boolean',
30
+ 'release-version': 'string',
26
31
  repo: 'string',
27
32
  'sdk-help': 'boolean',
28
33
  'static-build': 'boolean',
29
34
  'target-dir': 'string',
35
+ upgrade: 'boolean',
30
36
  version: 'string',
31
37
  verify: 'boolean'
32
38
  });
@@ -45,12 +51,28 @@ const WRAPPER_OPTION_SCHEMA = Object.freeze({
45
51
  channel: {
46
52
  type: 'string'
47
53
  },
54
+ 'check-update': {
55
+ type: 'boolean'
56
+ },
48
57
  'github-token': {
49
58
  type: 'string'
50
59
  },
60
+ force: {
61
+ type: 'boolean'
62
+ },
63
+ install: {
64
+ type: 'boolean'
65
+ },
51
66
  repo: {
52
67
  type: 'string'
53
68
  },
69
+ 'print-binary-path': {
70
+ type: 'boolean'
71
+ },
72
+ 'release-version': {
73
+ type: 'string',
74
+ aliases: ['version']
75
+ },
54
76
  'sdk-help': {
55
77
  type: 'boolean'
56
78
  },
@@ -60,8 +82,8 @@ const WRAPPER_OPTION_SCHEMA = Object.freeze({
60
82
  'target-dir': {
61
83
  type: 'string'
62
84
  },
63
- version: {
64
- type: 'string'
85
+ upgrade: {
86
+ type: 'boolean'
65
87
  },
66
88
  verify: {
67
89
  type: 'boolean'
@@ -122,9 +144,31 @@ function resolveFromPath(binaryName) {
122
144
  }
123
145
 
124
146
  function defaultInstallDir() {
147
+ return process.env.REDBLUE_INSTALL_DIR || process.env.INSTALL_DIR || path.join(os.homedir(), '.local', 'bin');
148
+ }
149
+
150
+ function legacyInstallDir() {
125
151
  return path.join(os.homedir(), '.redblue', 'bin');
126
152
  }
127
153
 
154
+ function resolveManagedBinaryPath(options = {}) {
155
+ if (options.binaryPath) {
156
+ return path.resolve(options.binaryPath);
157
+ }
158
+
159
+ const installDir = options.targetDir || defaultInstallDir();
160
+ const binaryName = options.binaryName || DEFAULT_BINARY_NAME;
161
+ return path.resolve(installDir, binaryName);
162
+ }
163
+
164
+ function resolveLegacyBinaryPath(options = {}) {
165
+ if (options.binaryPath || options.targetDir) {
166
+ return null;
167
+ }
168
+
169
+ return path.resolve(legacyInstallDir(), options.binaryName || DEFAULT_BINARY_NAME);
170
+ }
171
+
128
172
  function resolveAssetName(options = {}) {
129
173
  const platform = options.platform || process.platform;
130
174
  const arch = options.arch || process.arch;
@@ -203,13 +247,15 @@ async function requestText(url, options = {}) {
203
247
 
204
248
  async function getReleaseTag(options = {}) {
205
249
  const repo = options.repo || DEFAULT_REPO;
206
- const githubToken = options.githubToken || process.env.GITHUB_TOKEN;
250
+ const githubToken =
251
+ options.githubToken || (options.env && options.env.GITHUB_TOKEN) || process.env.GITHUB_TOKEN;
207
252
  const headers = githubToken ? { Authorization: `Bearer ${githubToken}` } : {};
253
+ const requestedVersion = options.releaseVersion || options.version;
208
254
 
209
- if (options.version) {
210
- return String(options.version).startsWith('v')
211
- ? String(options.version)
212
- : `v${options.version}`;
255
+ if (requestedVersion) {
256
+ return String(requestedVersion).startsWith('v')
257
+ ? String(requestedVersion)
258
+ : `v${requestedVersion}`;
213
259
  }
214
260
 
215
261
  const channel = options.channel || 'stable';
@@ -281,9 +327,7 @@ async function verifyChecksum(filePath, checksumUrl, options = {}) {
281
327
  async function downloadBinary(options = {}) {
282
328
  const repo = options.repo || DEFAULT_REPO;
283
329
  const assetName = options.assetName || resolveAssetName(options);
284
- const installDir = options.targetDir || defaultInstallDir();
285
- const binaryName = options.binaryName || DEFAULT_BINARY_NAME;
286
- const destination = path.resolve(installDir, binaryName);
330
+ const destination = resolveManagedBinaryPath(options);
287
331
  const releaseTag = await getReleaseTag(options);
288
332
  const githubToken = options.githubToken || process.env.GITHUB_TOKEN;
289
333
  const headers = githubToken ? { Authorization: `Bearer ${githubToken}` } : {};
@@ -303,29 +347,48 @@ async function downloadBinary(options = {}) {
303
347
  return destination;
304
348
  }
305
349
 
306
- async function resolveBinary(options = {}) {
350
+ async function resolveBinaryWithInfo(options = {}) {
307
351
  if (options.binaryPath) {
308
352
  const binaryPath = path.resolve(options.binaryPath);
309
353
  if (!exists(binaryPath)) {
310
354
  throw new Error(`redblue binary not found at ${binaryPath}`);
311
355
  }
312
- return binaryPath;
356
+ return {
357
+ binaryPath,
358
+ source: 'explicit'
359
+ };
313
360
  }
314
361
 
315
- const installDir = options.targetDir || defaultInstallDir();
316
362
  const binaryName = options.binaryName || DEFAULT_BINARY_NAME;
317
- const installedCandidate = path.resolve(installDir, binaryName);
363
+ const installedCandidate = resolveManagedBinaryPath(options);
318
364
  if (exists(installedCandidate)) {
319
- return installedCandidate;
365
+ return {
366
+ binaryPath: installedCandidate,
367
+ source: 'managed'
368
+ };
369
+ }
370
+
371
+ const legacyCandidate = resolveLegacyBinaryPath(options);
372
+ if (legacyCandidate && exists(legacyCandidate)) {
373
+ return {
374
+ binaryPath: legacyCandidate,
375
+ source: 'legacy'
376
+ };
320
377
  }
321
378
 
322
379
  const pathCandidate = resolveFromPath(binaryName);
323
380
  if (pathCandidate) {
324
- return pathCandidate;
381
+ return {
382
+ binaryPath: pathCandidate,
383
+ source: 'path'
384
+ };
325
385
  }
326
386
 
327
387
  if (options.autoDownload) {
328
- return downloadBinary(options);
388
+ return {
389
+ binaryPath: await downloadBinary(options),
390
+ source: 'downloaded'
391
+ };
329
392
  }
330
393
 
331
394
  throw new Error(
@@ -333,6 +396,152 @@ async function resolveBinary(options = {}) {
333
396
  );
334
397
  }
335
398
 
399
+ async function resolveBinary(options = {}) {
400
+ const resolved = await resolveBinaryWithInfo(options);
401
+ return resolved.binaryPath;
402
+ }
403
+
404
+ function normalizeReleaseTag(value) {
405
+ if (!value) {
406
+ return null;
407
+ }
408
+
409
+ const stringValue = String(value).trim();
410
+ if (!stringValue) {
411
+ return null;
412
+ }
413
+
414
+ return stringValue.startsWith('v') ? stringValue : `v${stringValue}`;
415
+ }
416
+
417
+ function parseInstalledVersion(output) {
418
+ const text = String(output || '').trim();
419
+ if (!text) {
420
+ return null;
421
+ }
422
+
423
+ const match = text.match(/\bv\d+\.\d+\.\d+(?:[-+][^\s]+)?\b/);
424
+ if (match) {
425
+ return match[0];
426
+ }
427
+
428
+ const bare = text.match(/\b\d+\.\d+\.\d+(?:[-+][^\s]+)?\b/);
429
+ return bare ? `v${bare[0]}` : null;
430
+ }
431
+
432
+ async function getInstalledVersion(binaryPath, options = {}) {
433
+ try {
434
+ const result = await execFilePromise(binaryPath, ['--version'], options);
435
+ return parseInstalledVersion(result.stdout || result.stderr);
436
+ } catch (_) {
437
+ return null;
438
+ }
439
+ }
440
+
441
+ async function getBinaryInfo(options = {}) {
442
+ const resolved = await resolveBinaryWithInfo(options);
443
+ const version = await getInstalledVersion(resolved.binaryPath, options);
444
+ return {
445
+ binaryPath: resolved.binaryPath,
446
+ source: resolved.source,
447
+ version
448
+ };
449
+ }
450
+
451
+ function resolveManagedUpgradeDestination(options = {}, currentInfo = null) {
452
+ if (options.binaryPath) {
453
+ return path.resolve(options.binaryPath);
454
+ }
455
+
456
+ if (options.targetDir) {
457
+ return resolveManagedBinaryPath(options);
458
+ }
459
+
460
+ if (currentInfo && (currentInfo.source === 'managed' || currentInfo.source === 'legacy')) {
461
+ return currentInfo.binaryPath;
462
+ }
463
+
464
+ return resolveManagedBinaryPath(options);
465
+ }
466
+
467
+ async function ensureInstalled(options = {}) {
468
+ try {
469
+ const info = await getBinaryInfo(Object.assign({}, options, { autoDownload: false }));
470
+ return Object.assign({ changed: false }, info);
471
+ } catch (_) {
472
+ const releaseTag = normalizeReleaseTag(options.releaseVersion || options.version) || (await getReleaseTag(options));
473
+ const binaryPath = await downloadBinary(
474
+ Object.assign({}, options, {
475
+ version: releaseTag
476
+ })
477
+ );
478
+ return {
479
+ binaryPath,
480
+ source: 'downloaded',
481
+ version: releaseTag,
482
+ changed: true
483
+ };
484
+ }
485
+ }
486
+
487
+ async function checkForUpdates(options = {}) {
488
+ const releaseTag = await getReleaseTag(options);
489
+ let current = null;
490
+
491
+ try {
492
+ current = await getBinaryInfo(Object.assign({}, options, { autoDownload: false }));
493
+ } catch (_) {
494
+ current = null;
495
+ }
496
+
497
+ return {
498
+ binaryPath: current ? current.binaryPath : resolveManagedBinaryPath(options),
499
+ currentVersion: current ? current.version : null,
500
+ latestVersion: releaseTag,
501
+ source: current ? current.source : null,
502
+ hasUpdate: !current || current.version !== releaseTag
503
+ };
504
+ }
505
+
506
+ async function upgradeBinary(options = {}) {
507
+ const releaseTag = await getReleaseTag(options);
508
+ let current = null;
509
+
510
+ try {
511
+ current = await getBinaryInfo(Object.assign({}, options, { autoDownload: false }));
512
+ } catch (_) {
513
+ current = null;
514
+ }
515
+
516
+ const destination = resolveManagedUpgradeDestination(options, current);
517
+ const currentVersion = current ? current.version : null;
518
+ const needsDownload = options.force === true || !exists(destination) || currentVersion !== releaseTag;
519
+
520
+ if (!needsDownload) {
521
+ return {
522
+ binaryPath: destination,
523
+ previousVersion: currentVersion,
524
+ version: releaseTag,
525
+ changed: false,
526
+ source: current.source
527
+ };
528
+ }
529
+
530
+ const binaryPath = await downloadBinary(
531
+ Object.assign({}, options, {
532
+ binaryPath: destination
533
+ })
534
+ );
535
+
536
+ return {
537
+ binaryPath,
538
+ previousVersion: currentVersion,
539
+ version: releaseTag,
540
+ changed: true,
541
+ source: current ? current.source : 'managed'
542
+ };
543
+ }
544
+
336
545
  function execFilePromise(binaryPath, args, options = {}) {
337
546
  return new Promise((resolve, reject) => {
338
547
  execFile(
@@ -461,6 +670,18 @@ function splitWrapperArgs(argv) {
461
670
  break;
462
671
  }
463
672
 
673
+ if (optionType === 'string' && eqIndex === -1) {
674
+ const nextToken = rawArgs[index + 1];
675
+ if (optionName === 'version' && (!nextToken || String(nextToken).startsWith('-'))) {
676
+ break;
677
+ }
678
+ if (nextToken === undefined) {
679
+ wrapperArgs.push(token);
680
+ index += 1;
681
+ continue;
682
+ }
683
+ }
684
+
464
685
  wrapperArgs.push(token);
465
686
  index += 1;
466
687
 
@@ -495,29 +716,71 @@ async function parseWrapperArgs(argv, runtime = {}) {
495
716
  }
496
717
 
497
718
  const options = parsed.options || {};
719
+ const releaseVersion = options['release-version'] || options.version;
498
720
 
499
721
  return {
500
722
  passthroughArgs: split.passthroughArgs,
501
723
  rawArgs,
502
724
  resolveOptions: {
503
725
  assetName: options['asset-name'],
504
- autoDownload: options['auto-download'] === true,
726
+ autoDownload: options['auto-download'] === true || options.download === true,
505
727
  binaryPath: options['binary-path'],
506
728
  channel: options.channel,
729
+ force: options.force === true,
507
730
  githubToken: options['github-token'],
508
731
  repo: options.repo,
732
+ releaseVersion,
509
733
  staticBuild: options['static-build'] === true,
510
734
  targetDir: options['target-dir'],
511
735
  verify: options.verify !== false,
512
- version: options.version
736
+ version: releaseVersion
513
737
  },
514
738
  usedDoubleDash: split.usedDoubleDash,
515
739
  wrapperOptions: {
516
- sdkHelp: options['sdk-help'] === true
740
+ checkUpdate: options['check-update'] === true,
741
+ install: options.install === true,
742
+ printBinaryPath: options['print-binary-path'] === true,
743
+ sdkHelp: options['sdk-help'] === true,
744
+ upgrade: options.upgrade === true
517
745
  }
518
746
  };
519
747
  }
520
748
 
749
+ function writeLine(stream, message) {
750
+ stream.write(`${message}\n`);
751
+ }
752
+
753
+ function formatWrapperBinaryStatus(result) {
754
+ if (result && Object.prototype.hasOwnProperty.call(result, 'latestVersion')) {
755
+ if (!result.currentVersion) {
756
+ return `redblue is not installed; latest available is ${result.latestVersion}`;
757
+ }
758
+ if (result.hasUpdate) {
759
+ return `redblue update available at ${result.binaryPath}: ${result.currentVersion} -> ${result.latestVersion}`;
760
+ }
761
+ return `redblue is up to date at ${result.binaryPath} (${result.currentVersion})`;
762
+ }
763
+
764
+ if (result && Object.prototype.hasOwnProperty.call(result, 'previousVersion')) {
765
+ if (!result.changed) {
766
+ return `redblue already at ${result.binaryPath} (${result.version || 'version unknown'})`;
767
+ }
768
+ if (result.previousVersion) {
769
+ return `redblue upgraded at ${result.binaryPath}: ${result.previousVersion} -> ${result.version}`;
770
+ }
771
+ return `redblue installed at ${result.binaryPath} (${result.version || 'version unknown'})`;
772
+ }
773
+
774
+ if (result && result.binaryPath) {
775
+ if (!result.changed) {
776
+ return `redblue already installed at ${result.binaryPath}${result.version ? ` (${result.version})` : ''}`;
777
+ }
778
+ return `redblue installed at ${result.binaryPath}${result.version ? ` (${result.version})` : ''}`;
779
+ }
780
+
781
+ return 'redblue binary status unavailable';
782
+ }
783
+
521
784
  function formatWrapperHelp() {
522
785
  return [
523
786
  'redblue-cli wrapper',
@@ -529,19 +792,27 @@ function formatWrapperHelp() {
529
792
  '',
530
793
  'Wrapper options:',
531
794
  ' --binary-path <path> Use an explicit redblue binary',
532
- ' --target-dir <dir> Resolve or download the binary in this directory',
533
- ' --auto-download Download the binary if it is missing',
795
+ ' --target-dir <dir> Resolve or install the managed binary in this directory',
796
+ ' --auto-download Download the binary if it is missing before command execution',
797
+ ' --install Ensure the managed binary is installed',
798
+ ' --upgrade Upgrade the managed binary to the requested release',
799
+ ' --check-update Check the installed binary against the latest release',
800
+ ' --print-binary-path Print the resolved binary path and exit',
534
801
  ' --channel <name> Release channel for downloads (stable, latest, next)',
535
- ' --version <tag> Pin a release version for downloads',
802
+ ' --release-version <tag> Pin a release version for install or upgrade',
803
+ ' --version <tag> Alias for --release-version',
536
804
  ' --asset-name <name> Override the release asset name',
537
805
  ' --repo <owner/name> Override the GitHub repository',
538
806
  ' --github-token <token> GitHub token for release downloads',
539
807
  ' --static-build Prefer static Linux assets when available',
808
+ ' --force Force a reinstall when used with --upgrade',
540
809
  ' --no-verify Skip SHA256 verification on download',
541
810
  ' --sdk-help Show this wrapper help',
542
811
  '',
543
812
  'Notes:',
544
813
  ' Wrapper options must come before the redblue command.',
814
+ ' Managed installs default to ~/.local/bin and still detect legacy ~/.redblue/bin installs.',
815
+ ' Use "rb --version" to query the real redblue binary version after installation.',
545
816
  ' The exact command "npx rb" only works when a package named "rb" exists or when this package is already installed and exposes the rb bin.',
546
817
  ''
547
818
  ].join('\n');
@@ -568,13 +839,71 @@ async function runCli(argv = process.argv.slice(2), runtime = {}) {
568
839
 
569
840
  try {
570
841
  const parsed = await parseWrapperArgs(argv, runtime);
842
+ const cliOptions = Object.assign({}, parsed.resolveOptions, {
843
+ cwd: runtime.cwd || process.cwd(),
844
+ env: Object.assign({}, process.env, runtime.env || {})
845
+ });
571
846
 
572
847
  if (parsed.wrapperOptions.sdkHelp) {
573
- stdout.write(formatWrapperHelp());
848
+ writeLine(stdout, formatWrapperHelp());
574
849
  return 0;
575
850
  }
576
851
 
577
- const binaryPath = await resolveBinary(parsed.resolveOptions);
852
+ let resolvedInfo = null;
853
+
854
+ if (parsed.wrapperOptions.checkUpdate) {
855
+ const updateStatus = await checkForUpdates(cliOptions);
856
+ const updateMessage = formatWrapperBinaryStatus(updateStatus);
857
+
858
+ if (parsed.passthroughArgs.length === 0) {
859
+ writeLine(stdout, updateMessage);
860
+ return 0;
861
+ }
862
+
863
+ writeLine(stderr, updateMessage);
864
+ }
865
+
866
+ if (parsed.wrapperOptions.upgrade) {
867
+ const upgradeResult = await upgradeBinary(cliOptions);
868
+ resolvedInfo = {
869
+ binaryPath: upgradeResult.binaryPath,
870
+ source: upgradeResult.source
871
+ };
872
+
873
+ if (parsed.passthroughArgs.length === 0 && !parsed.wrapperOptions.printBinaryPath) {
874
+ writeLine(stdout, formatWrapperBinaryStatus(upgradeResult));
875
+ return 0;
876
+ }
877
+
878
+ writeLine(stderr, formatWrapperBinaryStatus(upgradeResult));
879
+ } else if (parsed.wrapperOptions.install) {
880
+ const installResult = await ensureInstalled(cliOptions);
881
+ resolvedInfo = {
882
+ binaryPath: installResult.binaryPath,
883
+ source: installResult.source
884
+ };
885
+
886
+ if (parsed.passthroughArgs.length === 0 && !parsed.wrapperOptions.printBinaryPath) {
887
+ writeLine(stdout, formatWrapperBinaryStatus(installResult));
888
+ return 0;
889
+ }
890
+
891
+ writeLine(stderr, formatWrapperBinaryStatus(installResult));
892
+ }
893
+
894
+ if (!resolvedInfo) {
895
+ resolvedInfo = await resolveBinaryWithInfo(cliOptions);
896
+ }
897
+
898
+ if (parsed.wrapperOptions.printBinaryPath) {
899
+ if (parsed.passthroughArgs.length === 0) {
900
+ writeLine(stdout, resolvedInfo.binaryPath);
901
+ return 0;
902
+ }
903
+ writeLine(stderr, `redblue binary: ${resolvedInfo.binaryPath}`);
904
+ }
905
+
906
+ const binaryPath = resolvedInfo.binaryPath;
578
907
  /* node:coverage disable */
579
908
  const spawnOptions = {
580
909
  cwd: runtime.cwd || process.cwd(),
@@ -898,43 +1227,62 @@ async function createClient(options = {}) {
898
1227
  }
899
1228
 
900
1229
  module.exports = {
1230
+ checkForUpdates,
901
1231
  createClient,
902
1232
  downloadBinary,
1233
+ ensureInstalled,
1234
+ getBinaryInfo,
903
1235
  getManifest,
1236
+ getInstalledVersion,
904
1237
  runCli,
905
1238
  resolveAssetName,
906
- resolveBinary
1239
+ resolveBinary,
1240
+ upgradeBinary
907
1241
  };
908
1242
 
909
1243
  module.exports._internal = {
910
1244
  attachRoute,
911
1245
  buildInvocation,
1246
+ checkForUpdates,
912
1247
  createDomainProxy,
913
1248
  defaultInstallDir,
914
1249
  downloadToFile,
1250
+ ensureInstalled,
915
1251
  ensureObject,
916
1252
  execFilePromise,
917
1253
  exists,
1254
+ formatWrapperBinaryStatus,
918
1255
  formatWrapperHelp,
919
1256
  findFlag,
1257
+ getBinaryInfo,
920
1258
  getParserCandidatePaths,
921
1259
  getDefaultBinaryName,
1260
+ getInstalledVersion,
922
1261
  getReleaseTag,
923
1262
  invokeJson,
924
1263
  invokeRaw,
925
1264
  isExecutable,
926
1265
  kebabToCamel,
1266
+ legacyInstallDir,
927
1267
  loadCliArgsParser,
1268
+ normalizeReleaseTag,
928
1269
  parseWrapperArgs,
1270
+ parseInstalledVersion,
929
1271
  request,
930
1272
  requestJson,
931
1273
  requestText,
932
1274
  resolveFromPath,
1275
+ resolveBinaryWithInfo,
1276
+ resolveLegacyBinaryPath,
1277
+ resolveManagedBinaryPath,
1278
+ resolveManagedUpgradeDestination,
933
1279
  sha256File,
934
1280
  splitWrapperArgs,
935
1281
  spawnBinary,
936
1282
  toImportSpecifier,
1283
+ upgradeBinary,
937
1284
  waitForChild,
1285
+ writeLine,
938
1286
  verifyChecksum
939
1287
  };
940
1288