vercel 58.9.2 → 58.9.3

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.
@@ -24,7 +24,7 @@ import {
24
24
  apiCommand,
25
25
  listSubcommand4 as listSubcommand,
26
26
  loginCommand
27
- } from "./chunk-QXXH6L46.js";
27
+ } from "./chunk-FKN6MI3N.js";
28
28
  import {
29
29
  require_semver
30
30
  } from "./chunk-IB5L4LKZ.js";
@@ -32,7 +32,11 @@ import {
32
32
  help
33
33
  } from "./chunk-ZX2FSPWV.js";
34
34
  import {
35
- login
35
+ login,
36
+ require_chownr,
37
+ require_mkdirp,
38
+ require_pump,
39
+ require_tar_stream
36
40
  } from "./chunk-J23MTK5H.js";
37
41
  import {
38
42
  TelemetryClient,
@@ -55,6 +59,10 @@ import {
55
59
  import {
56
60
  pkg_default
57
61
  } from "./chunk-P4QNYOFB.js";
62
+ import {
63
+ fetch as fetch2,
64
+ toNodeReadable
65
+ } from "./chunk-52QYYTM5.js";
58
66
  import {
59
67
  output_manager_default
60
68
  } from "./chunk-OX7KI3LF.js";
@@ -63,6 +71,7 @@ import {
63
71
  } from "./chunk-S7KYDPEM.js";
64
72
  import {
65
73
  __commonJS,
74
+ __require,
66
75
  __toESM
67
76
  } from "./chunk-TZ2YI2VH.js";
68
77
 
@@ -500,6 +509,347 @@ var require_ci_info = __commonJS({
500
509
  }
501
510
  });
502
511
 
512
+ // ../../node_modules/.pnpm/tar-fs@1.16.5/node_modules/tar-fs/index.js
513
+ var require_tar_fs = __commonJS({
514
+ "../../node_modules/.pnpm/tar-fs@1.16.5/node_modules/tar-fs/index.js"(exports) {
515
+ var chownr = require_chownr();
516
+ var tar2 = require_tar_stream();
517
+ var pump = require_pump();
518
+ var mkdirp = require_mkdirp();
519
+ var fs = __require("fs");
520
+ var path = __require("path");
521
+ var os = __require("os");
522
+ var win32 = os.platform() === "win32";
523
+ var noop = function() {
524
+ };
525
+ var echo = function(name) {
526
+ return name;
527
+ };
528
+ var normalize = !win32 ? echo : function(name) {
529
+ return name.replace(/\\/g, "/").replace(/[:?<>|]/g, "_");
530
+ };
531
+ var statAll = function(fs2, stat2, cwd, ignore, entries, sort) {
532
+ var queue = entries || ["."];
533
+ return function loop(callback) {
534
+ if (!queue.length)
535
+ return callback();
536
+ var next = queue.shift();
537
+ var nextAbs = path.join(cwd, next);
538
+ stat2(nextAbs, function(err, stat3) {
539
+ if (err)
540
+ return callback(err);
541
+ if (!stat3.isDirectory())
542
+ return callback(null, next, stat3);
543
+ fs2.readdir(nextAbs, function(err2, files) {
544
+ if (err2)
545
+ return callback(err2);
546
+ if (sort)
547
+ files.sort();
548
+ for (var i = 0; i < files.length; i++) {
549
+ if (!ignore(path.join(cwd, next, files[i])))
550
+ queue.push(path.join(next, files[i]));
551
+ }
552
+ callback(null, next, stat3);
553
+ });
554
+ });
555
+ };
556
+ };
557
+ var strip = function(map, level) {
558
+ return function(header) {
559
+ header.name = header.name.split("/").slice(level).join("/");
560
+ var linkname = header.linkname;
561
+ if (linkname && (header.type === "link" || path.isAbsolute(linkname))) {
562
+ header.linkname = linkname.split("/").slice(level).join("/");
563
+ }
564
+ return map(header);
565
+ };
566
+ };
567
+ exports.pack = function(cwd, opts) {
568
+ if (!cwd)
569
+ cwd = ".";
570
+ if (!opts)
571
+ opts = {};
572
+ var xfs = opts.fs || fs;
573
+ var ignore = opts.ignore || opts.filter || noop;
574
+ var map = opts.map || noop;
575
+ var mapStream = opts.mapStream || echo;
576
+ var statNext = statAll(xfs, opts.dereference ? xfs.stat : xfs.lstat, cwd, ignore, opts.entries, opts.sort);
577
+ var strict = opts.strict !== false;
578
+ var umask = typeof opts.umask === "number" ? ~opts.umask : ~processUmask();
579
+ var dmode = typeof opts.dmode === "number" ? opts.dmode : 0;
580
+ var fmode = typeof opts.fmode === "number" ? opts.fmode : 0;
581
+ var pack = opts.pack || tar2.pack();
582
+ var finish = opts.finish || noop;
583
+ if (opts.strip)
584
+ map = strip(map, opts.strip);
585
+ if (opts.readable) {
586
+ dmode |= parseInt(555, 8);
587
+ fmode |= parseInt(444, 8);
588
+ }
589
+ if (opts.writable) {
590
+ dmode |= parseInt(333, 8);
591
+ fmode |= parseInt(222, 8);
592
+ }
593
+ var onsymlink = function(filename, header) {
594
+ xfs.readlink(path.join(cwd, filename), function(err, linkname) {
595
+ if (err)
596
+ return pack.destroy(err);
597
+ header.linkname = normalize(linkname);
598
+ pack.entry(header, onnextentry);
599
+ });
600
+ };
601
+ var onstat = function(err, filename, stat2) {
602
+ if (err)
603
+ return pack.destroy(err);
604
+ if (!filename) {
605
+ if (opts.finalize !== false)
606
+ pack.finalize();
607
+ return finish(pack);
608
+ }
609
+ if (stat2.isSocket())
610
+ return onnextentry();
611
+ var header = {
612
+ name: normalize(filename),
613
+ mode: (stat2.mode | (stat2.isDirectory() ? dmode : fmode)) & umask,
614
+ mtime: stat2.mtime,
615
+ size: stat2.size,
616
+ type: "file",
617
+ uid: stat2.uid,
618
+ gid: stat2.gid
619
+ };
620
+ if (stat2.isDirectory()) {
621
+ header.size = 0;
622
+ header.type = "directory";
623
+ header = map(header) || header;
624
+ return pack.entry(header, onnextentry);
625
+ }
626
+ if (stat2.isSymbolicLink()) {
627
+ header.size = 0;
628
+ header.type = "symlink";
629
+ header = map(header) || header;
630
+ return onsymlink(filename, header);
631
+ }
632
+ header = map(header) || header;
633
+ if (!stat2.isFile()) {
634
+ if (strict)
635
+ return pack.destroy(new Error("unsupported type for " + filename));
636
+ return onnextentry();
637
+ }
638
+ var entry = pack.entry(header, onnextentry);
639
+ if (!entry)
640
+ return;
641
+ var rs = mapStream(xfs.createReadStream(path.join(cwd, filename)), header);
642
+ rs.on("error", function(err2) {
643
+ entry.destroy(err2);
644
+ });
645
+ pump(rs, entry);
646
+ };
647
+ var onnextentry = function(err) {
648
+ if (err)
649
+ return pack.destroy(err);
650
+ statNext(onstat);
651
+ };
652
+ onnextentry();
653
+ return pack;
654
+ };
655
+ var head = function(list) {
656
+ return list.length ? list[list.length - 1] : null;
657
+ };
658
+ var processGetuid = function() {
659
+ return process.getuid ? process.getuid() : -1;
660
+ };
661
+ var processUmask = function() {
662
+ return process.umask ? process.umask() : 0;
663
+ };
664
+ exports.extract = function(cwd, opts) {
665
+ if (!cwd)
666
+ cwd = ".";
667
+ if (!opts)
668
+ opts = {};
669
+ var xfs = opts.fs || fs;
670
+ var ignore = opts.ignore || opts.filter || noop;
671
+ var map = opts.map || noop;
672
+ var mapStream = opts.mapStream || echo;
673
+ var own = opts.chown !== false && !win32 && processGetuid() === 0;
674
+ var extract = opts.extract || tar2.extract();
675
+ var stack = [];
676
+ var now = /* @__PURE__ */ new Date();
677
+ var umask = typeof opts.umask === "number" ? ~opts.umask : ~processUmask();
678
+ var dmode = typeof opts.dmode === "number" ? opts.dmode : 0;
679
+ var fmode = typeof opts.fmode === "number" ? opts.fmode : 0;
680
+ var strict = opts.strict !== false;
681
+ if (opts.strip)
682
+ map = strip(map, opts.strip);
683
+ if (opts.readable) {
684
+ dmode |= parseInt(555, 8);
685
+ fmode |= parseInt(444, 8);
686
+ }
687
+ if (opts.writable) {
688
+ dmode |= parseInt(333, 8);
689
+ fmode |= parseInt(222, 8);
690
+ }
691
+ var utimesParent = function(name, cb) {
692
+ var top;
693
+ while ((top = head(stack)) && name.slice(0, top[0].length) !== top[0])
694
+ stack.pop();
695
+ if (!top)
696
+ return cb();
697
+ xfs.utimes(top[0], now, top[1], cb);
698
+ };
699
+ var utimes = function(name, header, cb) {
700
+ if (opts.utimes === false)
701
+ return cb();
702
+ if (header.type === "directory")
703
+ return xfs.utimes(name, now, header.mtime, cb);
704
+ if (header.type === "symlink")
705
+ return utimesParent(name, cb);
706
+ xfs.utimes(name, now, header.mtime, function(err) {
707
+ if (err)
708
+ return cb(err);
709
+ utimesParent(name, cb);
710
+ });
711
+ };
712
+ var chperm = function(name, header, cb) {
713
+ var link = header.type === "symlink";
714
+ var chmod2 = link ? xfs.lchmod : xfs.chmod;
715
+ var chown = link ? xfs.lchown : xfs.chown;
716
+ if (!chmod2)
717
+ return cb();
718
+ var mode = (header.mode | (header.type === "directory" ? dmode : fmode)) & umask;
719
+ chmod2(name, mode, function(err) {
720
+ if (err)
721
+ return cb(err);
722
+ if (!own)
723
+ return cb();
724
+ if (!chown)
725
+ return cb();
726
+ chown(name, header.uid, header.gid, cb);
727
+ });
728
+ };
729
+ extract.on("entry", function(header, stream, next) {
730
+ header = map(header) || header;
731
+ header.name = normalize(header.name);
732
+ var name = path.join(cwd, path.join("/", header.name));
733
+ if (ignore(name, header)) {
734
+ stream.resume();
735
+ return next();
736
+ }
737
+ var stat2 = function(err) {
738
+ if (err)
739
+ return next(err);
740
+ utimes(name, header, function(err2) {
741
+ if (err2)
742
+ return next(err2);
743
+ if (win32)
744
+ return next();
745
+ chperm(name, header, next);
746
+ });
747
+ };
748
+ var onsymlink = function() {
749
+ if (win32)
750
+ return next();
751
+ xfs.unlink(name, function() {
752
+ var dst = path.resolve(path.dirname(name), header.linkname);
753
+ if (!dst.startsWith(path.resolve(cwd)))
754
+ return next(new Error(name + " is not a valid symlink"));
755
+ xfs.symlink(header.linkname, name, stat2);
756
+ });
757
+ };
758
+ var onlink = function() {
759
+ if (win32)
760
+ return next();
761
+ xfs.unlink(name, function() {
762
+ var srcpath = path.join(cwd, path.join("/", header.linkname));
763
+ xfs.realpath(srcpath, function(err, dst) {
764
+ if (err || !dst.startsWith(path.resolve(cwd)))
765
+ return next(new Error(name + " is not a valid hardlink"));
766
+ xfs.link(dst, name, function(err2) {
767
+ if (err2 && err2.code === "EPERM" && opts.hardlinkAsFilesFallback) {
768
+ stream = xfs.createReadStream(srcpath);
769
+ return onfile();
770
+ }
771
+ stat2(err2);
772
+ });
773
+ });
774
+ });
775
+ };
776
+ var onfile = function() {
777
+ var ws = xfs.createWriteStream(name);
778
+ var rs = mapStream(stream, header);
779
+ ws.on("error", function(err) {
780
+ rs.destroy(err);
781
+ });
782
+ pump(rs, ws, function(err) {
783
+ if (err)
784
+ return next(err);
785
+ ws.on("close", stat2);
786
+ });
787
+ };
788
+ if (header.type === "directory") {
789
+ stack.push([name, header.mtime]);
790
+ return mkdirfix(name, {
791
+ fs: xfs,
792
+ own,
793
+ uid: header.uid,
794
+ gid: header.gid
795
+ }, stat2);
796
+ }
797
+ var dir = path.dirname(name);
798
+ validate(xfs, dir, path.join(cwd, "."), function(err, valid) {
799
+ if (err)
800
+ return next(err);
801
+ if (!valid)
802
+ return next(new Error(dir + " is not a valid path"));
803
+ mkdirfix(dir, {
804
+ fs: xfs,
805
+ own,
806
+ uid: header.uid,
807
+ gid: header.gid
808
+ }, function(err2) {
809
+ if (err2)
810
+ return next(err2);
811
+ switch (header.type) {
812
+ case "file":
813
+ return onfile();
814
+ case "link":
815
+ return onlink();
816
+ case "symlink":
817
+ return onsymlink();
818
+ }
819
+ if (strict)
820
+ return next(new Error("unsupported type for " + name + " (" + header.type + ")"));
821
+ stream.resume();
822
+ next();
823
+ });
824
+ });
825
+ });
826
+ if (opts.finish)
827
+ extract.on("finish", opts.finish);
828
+ return extract;
829
+ };
830
+ function validate(fs2, name, root, cb) {
831
+ if (name === root)
832
+ return cb(null, true);
833
+ fs2.lstat(name, function(err, st) {
834
+ if (err && err.code !== "ENOENT")
835
+ return cb(err);
836
+ if (err || st.isDirectory())
837
+ return validate(fs2, path.join(name, ".."), root, cb);
838
+ cb(null, false);
839
+ });
840
+ }
841
+ function mkdirfix(name, opts, cb) {
842
+ mkdirp(name, { fs: opts.fs }, function(err, made) {
843
+ if (!err && made && opts.own) {
844
+ chownr(made, opts.uid, opts.gid, cb);
845
+ } else {
846
+ cb(err);
847
+ }
848
+ });
849
+ }
850
+ }
851
+ });
852
+
503
853
  // ../../node_modules/.pnpm/jaro-winkler@0.2.8/node_modules/jaro-winkler/index.js
504
854
  var require_jaro_winkler = __commonJS({
505
855
  "../../node_modules/.pnpm/jaro-winkler@0.2.8/node_modules/jaro-winkler/index.js"(exports, module) {
@@ -2889,7 +3239,7 @@ function renderUpgradeProgress(current, total, phase) {
2889
3239
  );
2890
3240
  }
2891
3241
  function execFileStdout(command, args) {
2892
- return new Promise((resolve3, reject) => {
3242
+ return new Promise((resolve4, reject) => {
2893
3243
  execFile(
2894
3244
  command,
2895
3245
  args,
@@ -2899,7 +3249,7 @@ function execFileStdout(command, args) {
2899
3249
  reject(error);
2900
3250
  return;
2901
3251
  }
2902
- resolve3(stdout.toString());
3252
+ resolve4(stdout.toString());
2903
3253
  }
2904
3254
  );
2905
3255
  });
@@ -2967,7 +3317,7 @@ async function executeUpgrade(targetVersion) {
2967
3317
  }
2968
3318
  output_manager_default.debug(`Executing: ${updateCommand} (cwd: ${cwd})`);
2969
3319
  renderUpgradeProgress(targetVersion ? 1 : 2, totalSteps, "Installing\u2026");
2970
- return new Promise((resolve3) => {
3320
+ return new Promise((resolve4) => {
2971
3321
  const stdout = [];
2972
3322
  const stderr = [];
2973
3323
  const upgradeProcess = spawn(command, args, {
@@ -2987,7 +3337,7 @@ async function executeUpgrade(targetVersion) {
2987
3337
  output_manager_default.stopSpinner();
2988
3338
  output_manager_default.error(`Failed to execute upgrade command: ${err.message}`);
2989
3339
  output_manager_default.log(`You can try running the command manually: ${updateCommand}`);
2990
- resolve3(1);
3340
+ resolve4(1);
2991
3341
  });
2992
3342
  upgradeProcess.on("close", (code) => {
2993
3343
  if (code !== 0) {
@@ -3004,7 +3354,7 @@ async function executeUpgrade(targetVersion) {
3004
3354
  output_manager_default.log(
3005
3355
  `You can try running the command manually: ${updateCommand}`
3006
3356
  );
3007
- resolve3(code ?? 1);
3357
+ resolve4(code ?? 1);
3008
3358
  return;
3009
3359
  }
3010
3360
  renderUpgradeProgress(totalSteps, totalSteps);
@@ -3013,17 +3363,412 @@ async function executeUpgrade(targetVersion) {
3013
3363
  output_manager_default.success(
3014
3364
  `Vercel CLI has been upgraded to v${resolvedTargetVersion} successfully!`
3015
3365
  );
3016
- resolve3(0);
3366
+ resolve4(0);
3017
3367
  return;
3018
3368
  }
3019
3369
  output_manager_default.success("Vercel CLI has been upgraded successfully!");
3020
- resolve3(0);
3370
+ resolve4(0);
3021
3371
  });
3022
3372
  });
3023
3373
  }
3024
3374
 
3025
3375
  // src/util/updates.ts
3026
3376
  var import_ci_info = __toESM(require_ci_info(), 1);
3377
+
3378
+ // src/util/native-self-update.ts
3379
+ var import_tar_fs = __toESM(require_tar_fs(), 1);
3380
+ var import_semver2 = __toESM(require_semver(), 1);
3381
+ import { createGunzip } from "zlib";
3382
+ import { createHash as createHash2 } from "crypto";
3383
+ import { createWriteStream } from "fs";
3384
+ import { homedir, tmpdir as tmpdir2 } from "os";
3385
+ import { join as join2, resolve as resolve3, sep } from "path";
3386
+ import { pipeline } from "stream/promises";
3387
+ import {
3388
+ chmod,
3389
+ copyFile,
3390
+ mkdir as mkdir2,
3391
+ mkdtemp,
3392
+ readdir,
3393
+ readFile as readFile4,
3394
+ readlink,
3395
+ realpath,
3396
+ rename,
3397
+ rm,
3398
+ stat,
3399
+ symlink,
3400
+ unlink,
3401
+ writeFile as writeFile2
3402
+ } from "fs/promises";
3403
+ var REGISTRY = "https://registry.npmjs.org";
3404
+ async function moveFile(source, destination) {
3405
+ try {
3406
+ await rename(source, destination);
3407
+ } catch (err) {
3408
+ if (err.code !== "EXDEV") {
3409
+ throw err;
3410
+ }
3411
+ await copyFile(source, destination);
3412
+ await rm(source, { force: true });
3413
+ }
3414
+ }
3415
+ var CURL_INSTALL_COMMAND = "curl -fsSL https://api-frameworks.vercel.sh/install | sh";
3416
+ var SUPPORTED_PLATFORMS = /* @__PURE__ */ new Set([
3417
+ "darwin-arm64",
3418
+ "darwin-x64",
3419
+ "linux-arm64",
3420
+ "linux-x64"
3421
+ ]);
3422
+ function getInstallRoot() {
3423
+ const root = process.env.VERCEL_INSTALL_DIR;
3424
+ return root ? resolve3(root) : join2(homedir(), ".vercel");
3425
+ }
3426
+ function platformTarget() {
3427
+ return `${process.platform}-${process.arch}`;
3428
+ }
3429
+ function isSupportedPlatform() {
3430
+ return SUPPORTED_PLATFORMS.has(platformTarget());
3431
+ }
3432
+ function unsupportedPlatformMessage() {
3433
+ const supported = Array.from(SUPPORTED_PLATFORMS).join(", ");
3434
+ return `The native Vercel CLI binary is not available for your platform (${platformTarget()}). Supported platforms: ${supported}. You can install the CLI with a package manager instead: npm i -g vercel@latest`;
3435
+ }
3436
+ function nativePackageSuffix() {
3437
+ return `vc-native-${platformTarget()}`;
3438
+ }
3439
+ function nativePackageName() {
3440
+ return `@vercel/${nativePackageSuffix()}`;
3441
+ }
3442
+ async function isCurlInstall() {
3443
+ if (!isNativeBinaryInstall()) {
3444
+ return false;
3445
+ }
3446
+ const versionsPrefix = join2(getInstallRoot(), "versions") + sep;
3447
+ if (process.execPath.startsWith(versionsPrefix)) {
3448
+ return true;
3449
+ }
3450
+ try {
3451
+ const real = await realpath(process.execPath);
3452
+ return real.startsWith(versionsPrefix);
3453
+ } catch {
3454
+ return false;
3455
+ }
3456
+ }
3457
+ async function resolveLatestVersion(pkgName) {
3458
+ const res = await fetch2(`${REGISTRY}/${pkgName}/latest`);
3459
+ if (!res.ok) {
3460
+ throw new Error(
3461
+ `Failed to fetch package metadata from the npm registry (HTTP ${res.status})`
3462
+ );
3463
+ }
3464
+ const manifest = await res.json();
3465
+ if (!manifest.version || !import_semver2.default.valid(manifest.version)) {
3466
+ throw new Error("Could not resolve the latest native binary version");
3467
+ }
3468
+ return manifest.version;
3469
+ }
3470
+ async function resolveLatestNativeVersion() {
3471
+ return resolveLatestVersion(nativePackageName());
3472
+ }
3473
+ async function listAvailableVersions(pkgName) {
3474
+ const res = await fetch2(`${REGISTRY}/${pkgName}`, {
3475
+ headers: {
3476
+ // Abbreviated metadata: much smaller response.
3477
+ accept: "application/vnd.npm.install-v1+json"
3478
+ }
3479
+ });
3480
+ if (!res.ok) {
3481
+ throw new Error(
3482
+ `Failed to fetch package metadata from the npm registry (HTTP ${res.status})`
3483
+ );
3484
+ }
3485
+ const manifest = await res.json();
3486
+ const versions = Object.keys(manifest.versions ?? {}).filter(
3487
+ (v) => import_semver2.default.valid(v)
3488
+ );
3489
+ return versions.sort(import_semver2.default.rcompare);
3490
+ }
3491
+ async function downloadAndExtractBinary(version, destination) {
3492
+ if (!isSupportedPlatform()) {
3493
+ throw new Error(unsupportedPlatformMessage());
3494
+ }
3495
+ const suffix = nativePackageSuffix();
3496
+ const tarballUrl = `${REGISTRY}/@vercel/${suffix}/-/${suffix}-${version}.tgz`;
3497
+ const res = await fetch2(tarballUrl);
3498
+ if (res.status === 404) {
3499
+ throw new Error(
3500
+ `No native binary is available for Vercel CLI v${version} on ${platformTarget()}. Older versions may predate native binary builds. You can install that version with a package manager instead: npm i -g vercel@${version}`
3501
+ );
3502
+ }
3503
+ if (!res.ok) {
3504
+ throw new Error(`Failed to download ${tarballUrl} (HTTP ${res.status})`);
3505
+ }
3506
+ const tmpDir = await mkdtemp(join2(tmpdir2(), "vercel-upgrade-"));
3507
+ try {
3508
+ await pipeline(
3509
+ toNodeReadable(res.body),
3510
+ createGunzip(),
3511
+ import_tar_fs.default.extract(tmpDir, {
3512
+ // Drop symlink/hardlink entries: they're the tar link-following
3513
+ // traversal vector (CVE-2024-12905 / CVE-2025-48387).
3514
+ ignore: (_name, header) => header?.type !== "file" && header?.type !== "directory"
3515
+ })
3516
+ );
3517
+ const binary = join2(tmpDir, "package", "bin", "vercel");
3518
+ const stats = await stat(binary).catch(() => null);
3519
+ if (!stats?.isFile()) {
3520
+ throw new Error(
3521
+ "Downloaded tarball did not contain the expected binary (package/bin/vercel)"
3522
+ );
3523
+ }
3524
+ await mkdir2(destination, { recursive: true });
3525
+ await chmod(binary, 493);
3526
+ await moveFile(binary, join2(destination, "vercel"));
3527
+ } finally {
3528
+ await rm(tmpDir, { recursive: true, force: true });
3529
+ }
3530
+ }
3531
+ async function forceSymlink(target, linkPath) {
3532
+ await unlink(linkPath).catch(() => {
3533
+ });
3534
+ await symlink(target, linkPath);
3535
+ }
3536
+ async function linkVersion(version) {
3537
+ const installRoot = getInstallRoot();
3538
+ const binaryPath = join2(installRoot, "versions", version, "vercel");
3539
+ const binDir = join2(installRoot, "bin");
3540
+ await mkdir2(binDir, { recursive: true });
3541
+ await forceSymlink(binaryPath, join2(binDir, "vercel"));
3542
+ await forceSymlink(binaryPath, join2(binDir, "vc"));
3543
+ }
3544
+ async function installAndLinkVersion(version) {
3545
+ const installRoot = getInstallRoot();
3546
+ const versionDir = join2(installRoot, "versions", version);
3547
+ const binaryPath = join2(versionDir, "vercel");
3548
+ const existing = await stat(binaryPath).catch(() => null);
3549
+ if (!existing?.isFile()) {
3550
+ output_manager_default.spinner(`Downloading Vercel CLI v${version}\u2026`, 0);
3551
+ await downloadAndExtractBinary(version, versionDir);
3552
+ }
3553
+ await linkVersion(version);
3554
+ }
3555
+ var PR_BINARIES_URL = process.env.VERCEL_PR_BINARIES_URL || "https://api-frameworks.vercel.sh/pr-binaries";
3556
+ function parsePrTarget(target) {
3557
+ const match = /^pr[/-](\d+)$/i.exec(target.trim());
3558
+ if (!match) {
3559
+ return void 0;
3560
+ }
3561
+ const pr = Number(match[1]);
3562
+ return Number.isSafeInteger(pr) && pr > 0 ? pr : void 0;
3563
+ }
3564
+ function prVersionDirName(pr) {
3565
+ return `pr-${pr}`;
3566
+ }
3567
+ function isPrVersionName(name) {
3568
+ return /^pr-\d+$/.test(name);
3569
+ }
3570
+ async function fetchPrChecksum(pr) {
3571
+ const url = `${PR_BINARIES_URL}/${pr}/vercel-${platformTarget()}.sha256`;
3572
+ const res = await fetch2(url);
3573
+ if (res.status === 404) {
3574
+ throw new Error(
3575
+ `No binary found for PR #${pr} on ${platformTarget()}. The PR may not have a build yet, or the build may still be running.`
3576
+ );
3577
+ }
3578
+ if (!res.ok) {
3579
+ throw new Error(
3580
+ `Failed to fetch checksum for PR #${pr} (HTTP ${res.status})`
3581
+ );
3582
+ }
3583
+ const text = (await res.text()).trim();
3584
+ const sha = text.split(/\s+/)[0]?.toLowerCase();
3585
+ if (!/^[0-9a-f]{64}$/.test(sha ?? "")) {
3586
+ throw new Error(`Unexpected checksum format for PR #${pr}`);
3587
+ }
3588
+ return sha;
3589
+ }
3590
+ async function downloadPrBinary(pr, expectedSha, destination) {
3591
+ if (!isSupportedPlatform()) {
3592
+ throw new Error(unsupportedPlatformMessage());
3593
+ }
3594
+ const url = `${PR_BINARIES_URL}/${pr}/vercel-${platformTarget()}`;
3595
+ const res = await fetch2(url);
3596
+ if (res.status === 404) {
3597
+ throw new Error(
3598
+ `No binary found for PR #${pr} on ${platformTarget()}. The PR may not have a build yet, or the build may still be running.`
3599
+ );
3600
+ }
3601
+ if (!res.ok) {
3602
+ throw new Error(`Failed to download ${url} (HTTP ${res.status})`);
3603
+ }
3604
+ const tmpDir = await mkdtemp(join2(tmpdir2(), "vercel-pr-"));
3605
+ try {
3606
+ const tmpBinary = join2(tmpDir, "vercel");
3607
+ const hash = createHash2("sha256");
3608
+ const body = toNodeReadable(res.body);
3609
+ body.on("data", (chunk) => hash.update(chunk));
3610
+ await pipeline(body, createWriteStream(tmpBinary));
3611
+ const actualSha = hash.digest("hex");
3612
+ if (actualSha !== expectedSha) {
3613
+ throw new Error(
3614
+ `Checksum mismatch for PR #${pr} binary. The build may have been updated mid-download; try again.`
3615
+ );
3616
+ }
3617
+ await mkdir2(destination, { recursive: true });
3618
+ await chmod(tmpBinary, 493);
3619
+ await moveFile(tmpBinary, join2(destination, "vercel"));
3620
+ await writeFile2(join2(destination, "vercel.sha256"), `${actualSha}
3621
+ `);
3622
+ } finally {
3623
+ await rm(tmpDir, { recursive: true, force: true });
3624
+ }
3625
+ }
3626
+ async function installAndLinkPrBinary(pr) {
3627
+ const installRoot = getInstallRoot();
3628
+ const versionDir = join2(installRoot, "versions", prVersionDirName(pr));
3629
+ const binaryPath = join2(versionDir, "vercel");
3630
+ const shaPath = join2(versionDir, "vercel.sha256");
3631
+ output_manager_default.spinner(`Checking latest build for PR #${pr}\u2026`, 0);
3632
+ const remoteSha = await fetchPrChecksum(pr);
3633
+ const existing = await stat(binaryPath).catch(() => null);
3634
+ const localSha = existing?.isFile() ? (await readFile4(shaPath, "utf8").catch(() => "")).trim().split(/\s+/)[0] : void 0;
3635
+ if (existing?.isFile() && localSha === remoteSha) {
3636
+ await linkVersion(prVersionDirName(pr));
3637
+ return { updated: false, sha: remoteSha };
3638
+ }
3639
+ output_manager_default.spinner(`Downloading Vercel CLI build for PR #${pr}\u2026`, 0);
3640
+ await downloadPrBinary(pr, remoteSha, versionDir);
3641
+ await linkVersion(prVersionDirName(pr));
3642
+ return { updated: true, sha: remoteSha };
3643
+ }
3644
+ async function listInstalledVersions() {
3645
+ const versionsDir = join2(getInstallRoot(), "versions");
3646
+ const entries = await readdir(versionsDir, { withFileTypes: true }).catch(
3647
+ () => []
3648
+ );
3649
+ const versions = [];
3650
+ const prBuilds = [];
3651
+ for (const entry of entries) {
3652
+ const isPr = isPrVersionName(entry.name);
3653
+ if (!entry.isDirectory() || !import_semver2.default.valid(entry.name) && !isPr) {
3654
+ continue;
3655
+ }
3656
+ const binary = join2(versionsDir, entry.name, "vercel");
3657
+ const stats = await stat(binary).catch(() => null);
3658
+ if (stats?.isFile()) {
3659
+ (isPr ? prBuilds : versions).push(entry.name);
3660
+ }
3661
+ }
3662
+ return [...versions.sort(import_semver2.default.rcompare), ...prBuilds.sort()];
3663
+ }
3664
+ async function getLinkedVersion() {
3665
+ const link = join2(getInstallRoot(), "bin", "vercel");
3666
+ try {
3667
+ const target = await readlink(link);
3668
+ const segments = target.split(sep);
3669
+ const versionsIdx = segments.lastIndexOf("versions");
3670
+ const version = versionsIdx >= 0 ? segments[versionsIdx + 1] : void 0;
3671
+ return version && (import_semver2.default.valid(version) || isPrVersionName(version)) ? version : void 0;
3672
+ } catch {
3673
+ return void 0;
3674
+ }
3675
+ }
3676
+ async function isLinkedToPrBuild() {
3677
+ const linked = await getLinkedVersion();
3678
+ return linked !== void 0 && isPrVersionName(linked);
3679
+ }
3680
+ function pinFilePath() {
3681
+ return join2(getInstallRoot(), "pinned");
3682
+ }
3683
+ async function setPinnedVersion(version) {
3684
+ await writeFile2(pinFilePath(), `${version}
3685
+ `);
3686
+ }
3687
+ async function clearPinnedVersion() {
3688
+ await unlink(pinFilePath()).catch(() => {
3689
+ });
3690
+ }
3691
+ async function getPinnedVersion() {
3692
+ const pinned = (await readFile4(pinFilePath(), "utf8").catch(() => "")).trim().split(/\s+/)[0];
3693
+ if (!pinned) {
3694
+ return void 0;
3695
+ }
3696
+ const linked = await getLinkedVersion();
3697
+ return pinned === linked ? pinned : void 0;
3698
+ }
3699
+ async function getPrBuildSha(name) {
3700
+ const shaPath = join2(getInstallRoot(), "versions", name, "vercel.sha256");
3701
+ const sha = (await readFile4(shaPath, "utf8").catch(() => "")).trim().split(/\s+/)[0];
3702
+ return /^[0-9a-f]{64}$/.test(sha) ? sha : void 0;
3703
+ }
3704
+ function packageManagerRemovalCommand() {
3705
+ const segments = process.execPath.split(sep);
3706
+ if (segments.includes("pnpm") || segments.includes(".pnpm")) {
3707
+ return "pnpm rm -g vercel";
3708
+ }
3709
+ if (segments.includes("yarn") || segments.includes(".yarn")) {
3710
+ return "yarn global remove vercel";
3711
+ }
3712
+ return "npm rm -g vercel";
3713
+ }
3714
+ async function printMigrationCleanup() {
3715
+ if (await isCurlInstall()) {
3716
+ return;
3717
+ }
3718
+ const removalCommand = packageManagerRemovalCommand();
3719
+ const binDir = join2(getInstallRoot(), "bin");
3720
+ output_manager_default.print("\n");
3721
+ output_manager_default.log(
3722
+ `The Vercel CLI now updates itself in ${binDir} and no longer needs your package manager.`
3723
+ );
3724
+ output_manager_default.log(
3725
+ `Remove the old install so the new binary takes effect: ${removalCommand}`
3726
+ );
3727
+ output_manager_default.log(
3728
+ "Then open a new terminal (or run `hash -r`) so your shell picks up the new binary."
3729
+ );
3730
+ }
3731
+ async function executeNativeSelfUpdate(targetVersion) {
3732
+ try {
3733
+ output_manager_default.spinner("Checking for updates\u2026", 0);
3734
+ const version = targetVersion ?? await resolveLatestNativeVersion();
3735
+ const onPrBuild = await isLinkedToPrBuild();
3736
+ if (!targetVersion && !onPrBuild && import_semver2.default.valid(version) && import_semver2.default.valid(pkg_default.version) && import_semver2.default.gte(pkg_default.version, version)) {
3737
+ output_manager_default.stopSpinner();
3738
+ output_manager_default.log(
3739
+ `No upgrade available. Vercel CLI is already up to date (v${pkg_default.version}).`
3740
+ );
3741
+ return 0;
3742
+ }
3743
+ if (onPrBuild) {
3744
+ output_manager_default.stopSpinner();
3745
+ output_manager_default.log(
3746
+ `Currently on a PR build (${await getLinkedVersion()}). Switching back to the latest release\u2026`
3747
+ );
3748
+ }
3749
+ await installAndLinkVersion(version);
3750
+ await clearPinnedVersion();
3751
+ output_manager_default.stopSpinner();
3752
+ output_manager_default.success(`Vercel CLI has been upgraded to v${version} successfully!`);
3753
+ await printMigrationCleanup();
3754
+ return 0;
3755
+ } catch (error) {
3756
+ output_manager_default.stopSpinner();
3757
+ output_manager_default.error(
3758
+ `Upgrade failed: ${error instanceof Error ? error.message : String(error)}`
3759
+ );
3760
+ output_manager_default.log(`You can try reinstalling manually: ${CURL_INSTALL_COMMAND}`);
3761
+ return 1;
3762
+ }
3763
+ }
3764
+
3765
+ // src/util/updates.ts
3766
+ async function isVersionPinned() {
3767
+ if (!isNativeBinaryInstall()) {
3768
+ return false;
3769
+ }
3770
+ return await getPinnedVersion() !== void 0;
3771
+ }
3027
3772
  function isAutoUpdateEnabled(config) {
3028
3773
  return config.updates?.auto === true;
3029
3774
  }
@@ -3206,6 +3951,21 @@ export {
3206
3951
  tryOpenApiFallback,
3207
3952
  executeUpgrade,
3208
3953
  require_ci_info,
3954
+ require_tar_fs,
3955
+ CURL_INSTALL_COMMAND,
3956
+ isCurlInstall,
3957
+ listAvailableVersions,
3958
+ installAndLinkVersion,
3959
+ parsePrTarget,
3960
+ installAndLinkPrBinary,
3961
+ listInstalledVersions,
3962
+ getLinkedVersion,
3963
+ isLinkedToPrBuild,
3964
+ setPinnedVersion,
3965
+ getPinnedVersion,
3966
+ getPrBuildSha,
3967
+ executeNativeSelfUpdate,
3968
+ isVersionPinned,
3209
3969
  isAutoUpdateEnabled,
3210
3970
  hasAutoUpdatePreference,
3211
3971
  setAutoUpdate,