vercel 54.15.1 → 54.17.0

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.
Files changed (54) hide show
  1. package/dist/chunks/{add-BHCMFK52.js → add-QQY6QOTO.js} +5 -5
  2. package/dist/chunks/{chunk-4TL5EF3A.js → chunk-2F6JT2OC.js} +4 -1
  3. package/dist/chunks/{chunk-AWD3IGXU.js → chunk-3NR6OYDV.js} +1 -1
  4. package/dist/chunks/{chunk-RWRYDAUG.js → chunk-4D42VZRX.js} +1 -1
  5. package/dist/chunks/{chunk-OOGTHUXU.js → chunk-5X7FBWLF.js} +6 -6
  6. package/dist/chunks/{chunk-CQ24PL4F.js → chunk-7AQDR2RX.js} +48 -9
  7. package/dist/chunks/{chunk-TAUAS27Y.js → chunk-7B44AIGE.js} +2 -2
  8. package/dist/chunks/{chunk-CBMMVXLH.js → chunk-A4B4JQVP.js} +11 -3
  9. package/dist/chunks/{chunk-AQWK7XXE.js → chunk-BRLY3Q4U.js} +18 -3
  10. package/dist/chunks/{chunk-D7U6YBVT.js → chunk-DDTKG4J3.js} +1 -1
  11. package/dist/chunks/{chunk-OEFNWW5M.js → chunk-E6FCE2XJ.js} +2 -2
  12. package/dist/chunks/{chunk-JNVCGTF2.js → chunk-HJ2TEW5Y.js} +1 -1
  13. package/dist/chunks/{chunk-PMUUPCDL.js → chunk-JFA4NUXP.js} +1 -1
  14. package/dist/chunks/{chunk-MABHXDYV.js → chunk-KTX4RQFM.js} +520 -133
  15. package/dist/chunks/{chunk-TDFUNPL7.js → chunk-KWCZRH7N.js} +5 -8
  16. package/dist/chunks/{chunk-B5DP7FOH.js → chunk-LGR4JRFA.js} +6 -6
  17. package/dist/chunks/{chunk-UJZ4RUU6.js → chunk-MS3WAXLU.js} +1 -1
  18. package/dist/chunks/{chunk-4OEXX4CB.js → chunk-NRIXI6V5.js} +1 -1
  19. package/dist/chunks/{chunk-4GQBO7KU.js → chunk-P5AZW6W6.js} +8 -2
  20. package/dist/chunks/{chunk-HIYWSGI7.js → chunk-Q77ALSXR.js} +3 -0
  21. package/dist/chunks/{chunk-5X6ILMYI.js → chunk-V7JDSYIZ.js} +3 -3
  22. package/dist/chunks/{chunk-UYC2Q5YZ.js → chunk-WJPWCLMH.js} +1 -1
  23. package/dist/chunks/{chunk-UEPXHHDN.js → chunk-YW7AYO7N.js} +1 -1
  24. package/dist/chunks/{compile-vercel-config-LUMMHFTD.js → compile-vercel-config-D2OQCK4B.js} +2 -2
  25. package/dist/chunks/{delete-X6VOLLCP.js → delete-VMW7FORM.js} +3 -3
  26. package/dist/chunks/{disable-LFH5IOCZ.js → disable-BDFZELDL.js} +3 -3
  27. package/dist/chunks/{discard-EVD33PAE.js → discard-WIN3BOXR.js} +3 -3
  28. package/dist/chunks/{edit-FL3SRS2I.js → edit-IZQX4XAG.js} +5 -5
  29. package/dist/chunks/{enable-HTU7LQK5.js → enable-RFODZ2L7.js} +3 -3
  30. package/dist/chunks/{export-R222C6IH.js → export-5CCLXZYT.js} +3 -3
  31. package/dist/chunks/{inspect-YYTAQP3A.js → inspect-GEUUTDBY.js} +4 -4
  32. package/dist/chunks/{list-SWJFJSEE.js → list-H35AGNO2.js} +3 -3
  33. package/dist/chunks/{list-AOJMWKA7.js → list-JIYDXQDJ.js} +4 -4
  34. package/dist/chunks/{ls-H7KDHFK6.js → ls-WPNFJAS6.js} +5 -5
  35. package/dist/chunks/{publish-O5VKBFJ6.js → publish-K7OPKXYC.js} +3 -3
  36. package/dist/chunks/{query-7UDJEOOR.js → query-MAN4NKU4.js} +3 -3
  37. package/dist/chunks/{reorder-ZPI6Q7DQ.js → reorder-GQ7BOQA7.js} +3 -3
  38. package/dist/chunks/{restore-7FNMEG4A.js → restore-MODYFJSP.js} +3 -3
  39. package/dist/chunks/{rm-U37YHRNF.js → rm-A45OKS6U.js} +5 -5
  40. package/dist/chunks/{routes-YEU33SON.js → routes-KUTLDFIF.js} +2 -2
  41. package/dist/chunks/{rule-inspect-CVI3TQHN.js → rule-inspect-HJCERQHK.js} +5 -5
  42. package/dist/chunks/{rules-ZTL4JCZO.js → rules-UNL3IB4P.js} +6 -6
  43. package/dist/chunks/{schema-LZ6VDRGM.js → schema-WOW2BATT.js} +3 -3
  44. package/dist/chunks/{update-O6FSP627.js → update-MOM4T2RN.js} +5 -5
  45. package/dist/commands/build/index.js +18 -18
  46. package/dist/commands/deploy/index.js +160 -13
  47. package/dist/commands/dev/index.js +665 -104
  48. package/dist/commands/env/index.js +6 -6
  49. package/dist/commands/link/index.js +47 -13
  50. package/dist/commands/list/index.js +5 -5
  51. package/dist/commands-bulk.js +44 -40
  52. package/dist/index.js +46 -42
  53. package/dist/version.mjs +1 -1
  54. package/package.json +21 -20
@@ -8,7 +8,7 @@ import {
8
8
  TelemetryClient,
9
9
  require_dist as require_dist2,
10
10
  require_graceful_fs
11
- } from "./chunk-HIYWSGI7.js";
11
+ } from "./chunk-Q77ALSXR.js";
12
12
  import {
13
13
  buildCommandWithYes,
14
14
  getPreservedArgsForEnvPull,
@@ -8006,7 +8006,7 @@ var require_jsonfile = __commonJS({
8006
8006
  }
8007
8007
  return obj;
8008
8008
  }
8009
- var readFile6 = universalify.fromPromise(_readFile);
8009
+ var readFile7 = universalify.fromPromise(_readFile);
8010
8010
  function readFileSync(file, options = {}) {
8011
8011
  if (typeof options === "string") {
8012
8012
  options = { encoding: options };
@@ -8038,7 +8038,7 @@ var require_jsonfile = __commonJS({
8038
8038
  return fs5.writeFileSync(file, str, options);
8039
8039
  }
8040
8040
  module.exports = {
8041
- readFile: readFile6,
8041
+ readFile: readFile7,
8042
8042
  readFileSync,
8043
8043
  writeFile: writeFile5,
8044
8044
  writeFileSync
@@ -13734,10 +13734,10 @@ var require_read_config_file = __commonJS({
13734
13734
  var import_smol_toml3 = __require("smol-toml");
13735
13735
  var import_fs4 = __require("fs");
13736
13736
  var import_error_utils5 = require_dist();
13737
- var { readFile: readFile6 } = import_fs4.promises;
13737
+ var { readFile: readFile7 } = import_fs4.promises;
13738
13738
  async function readFileOrNull(file) {
13739
13739
  try {
13740
- const data = await readFile6(file);
13740
+ const data = await readFile7(file);
13741
13741
  return data;
13742
13742
  } catch (error) {
13743
13743
  if (!(0, import_error_utils5.isErrnoException)(error)) {
@@ -13824,8 +13824,55 @@ var require_frameworks = __commonJS({
13824
13824
  var import_fs4 = __require("fs");
13825
13825
  var import_read_config_file = require_read_config_file();
13826
13826
  __reExport(frameworks_exports, require_types(), module.exports);
13827
- var { readdir, readFile: readFile6, unlink: unlink2 } = import_fs4.promises;
13827
+ var { readdir, readFile: readFile7, unlink: unlink2 } = import_fs4.promises;
13828
13828
  var frameworks = [
13829
+ {
13830
+ // A `Dockerfile.vercel` / `Containerfile.vercel` is an explicit opt-in to
13831
+ // deploy a project as a container, regardless of any other framework that
13832
+ // may also be detected. It is listed first so that framework detection
13833
+ // (which returns the first match in list order) selects it over everything
13834
+ // else — e.g. a Next.js app shipping a `Dockerfile.vercel` deploys as a
13835
+ // container, not via `@vercel/next`. Experimental for now, so it is only
13836
+ // detected when experimental frameworks are enabled
13837
+ // (`VERCEL_USE_EXPERIMENTAL_FRAMEWORKS`).
13838
+ name: "Container",
13839
+ slug: "container",
13840
+ experimental: true,
13841
+ runtimeFramework: true,
13842
+ logo: "https://api-frameworks.vercel.sh/framework-logos/container.svg",
13843
+ tagline: "Deploy any project as a container image built from a Dockerfile.",
13844
+ description: "A project deployed as a container image, built from a Dockerfile.vercel or Containerfile.vercel.",
13845
+ website: "https://docs.docker.com/reference/dockerfile/",
13846
+ useRuntime: { src: "<detect>", use: "@vercel/container" },
13847
+ detectors: {
13848
+ some: [
13849
+ {
13850
+ path: "Dockerfile.vercel"
13851
+ },
13852
+ {
13853
+ path: "Containerfile.vercel"
13854
+ }
13855
+ ]
13856
+ },
13857
+ settings: {
13858
+ installCommand: {
13859
+ placeholder: "None",
13860
+ value: null
13861
+ },
13862
+ buildCommand: {
13863
+ placeholder: "None",
13864
+ value: null
13865
+ },
13866
+ devCommand: {
13867
+ placeholder: "None",
13868
+ value: null
13869
+ },
13870
+ outputDirectory: {
13871
+ placeholder: "None"
13872
+ }
13873
+ },
13874
+ getOutputDirName: async () => "public"
13875
+ },
13829
13876
  {
13830
13877
  name: "Blitz.js (Legacy)",
13831
13878
  slug: "blitzjs",
@@ -13952,7 +13999,7 @@ var require_frameworks = __commonJS({
13952
13999
  "public",
13953
14000
  "__now_routes_g4t5bY.json"
13954
14001
  );
13955
- const content = await readFile6(nowRoutesPath, "utf8");
14002
+ const content = await readFile7(nowRoutesPath, "utf8");
13956
14003
  const nowRoutes = JSON.parse(content);
13957
14004
  try {
13958
14005
  await unlink2(nowRoutesPath);
@@ -22955,7 +23002,8 @@ var require_types3 = __commonJS({
22955
23002
  python: "@vercel/python",
22956
23003
  go: "@vercel/go",
22957
23004
  rust: "@vercel/rust",
22958
- ruby: "@vercel/ruby"
23005
+ ruby: "@vercel/ruby",
23006
+ container: "@vercel/container"
22959
23007
  };
22960
23008
  var RUNTIME_MANIFESTS = {
22961
23009
  node: ["package.json"],
@@ -23522,6 +23570,12 @@ var require_resolve2 = __commonJS({
23522
23570
  "python",
23523
23571
  "go"
23524
23572
  ]);
23573
+ function isContainerRuntime(config) {
23574
+ return config.runtime === "container";
23575
+ }
23576
+ function normalizeContainerCommand(command) {
23577
+ return Array.isArray(command) ? command : [command];
23578
+ }
23525
23579
  async function getServiceFs(fs5, serviceName, root) {
23526
23580
  if (!root) {
23527
23581
  return { fs: fs5 };
@@ -23607,6 +23661,10 @@ var require_resolve2 = __commonJS({
23607
23661
  }
23608
23662
  };
23609
23663
  }
23664
+ function isDockerfileEntrypoint(entrypoint) {
23665
+ const base = import_path12.posix.basename(entrypoint).toLowerCase();
23666
+ return base === "dockerfile" || base === "containerfile" || base.endsWith(".dockerfile");
23667
+ }
23610
23668
  function toWorkspaceRelativeEntrypoint(entrypoint, workspace) {
23611
23669
  const normalizedEntrypoint = import_path12.posix.normalize(entrypoint);
23612
23670
  if (workspace === ".") {
@@ -23985,6 +24043,13 @@ var require_resolve2 = __commonJS({
23985
24043
  serviceName: name
23986
24044
  };
23987
24045
  }
24046
+ if (config.command !== void 0 && !isContainerRuntime(config)) {
24047
+ return {
24048
+ code: "INVALID_COMMAND",
24049
+ message: `Service "${name}" can only specify "command" when using runtime "container".`,
24050
+ serviceName: name
24051
+ };
24052
+ }
23988
24053
  return null;
23989
24054
  }
23990
24055
  function validateServiceEntrypoint(name, config, resolvedEntrypoint) {
@@ -24025,8 +24090,11 @@ var require_resolve2 = __commonJS({
24025
24090
  const configuredRoutePrefix = routingResult.routing?.routePrefix;
24026
24091
  const configuredSubdomain = routingResult.routing?.subdomain;
24027
24092
  const routePrefixWasConfigured = routingResult.routing?.routePrefixConfigured ?? false;
24093
+ const containerEntrypoint = isContainerRuntime(config) && typeof rawEntrypoint === "string" ? rawEntrypoint : void 0;
24094
+ const containerDockerfile = containerEntrypoint && isDockerfileEntrypoint(containerEntrypoint) ? import_path12.posix.normalize(containerEntrypoint) : void 0;
24095
+ const containerImage = containerEntrypoint && !containerDockerfile ? containerEntrypoint : void 0;
24028
24096
  let resolvedEntrypointPath = resolvedEntrypoint;
24029
- if (!resolvedEntrypointPath && typeof rawEntrypoint === "string") {
24097
+ if (!containerEntrypoint && !resolvedEntrypointPath && typeof rawEntrypoint === "string") {
24030
24098
  const entrypointToResolve = moduleAttrParsed ? moduleAttrParsed.filePath : rawEntrypoint;
24031
24099
  const resolved = await resolveEntrypointPath({
24032
24100
  fs: serviceFs,
@@ -24035,7 +24103,7 @@ var require_resolve2 = __commonJS({
24035
24103
  });
24036
24104
  resolvedEntrypointPath = resolved.entrypoint;
24037
24105
  }
24038
- if (typeof rawEntrypoint === "string" && !resolvedEntrypointPath) {
24106
+ if (!containerEntrypoint && typeof rawEntrypoint === "string" && !resolvedEntrypointPath) {
24039
24107
  throw new Error(
24040
24108
  `Failed to resolve entrypoint "${rawEntrypoint}" for service "${name}".`
24041
24109
  );
@@ -24099,7 +24167,7 @@ var require_resolve2 = __commonJS({
24099
24167
  } else {
24100
24168
  builderUse = (0, import_utils4.getBuilderForRuntime)(inferredRuntime);
24101
24169
  }
24102
- builderSrc = resolvedEntrypointFile;
24170
+ builderSrc = inferredRuntime === "container" && typeof containerEntrypoint === "string" ? containerEntrypoint : resolvedEntrypointFile;
24103
24171
  }
24104
24172
  const normalizedSubdomain = type === "web" && typeof configuredSubdomain === "string" ? configuredSubdomain.toLowerCase() : void 0;
24105
24173
  const defaultRoutePrefix = type === "web" && normalizedSubdomain ? `/_/${name}` : void 0;
@@ -24133,6 +24201,12 @@ var require_resolve2 = __commonJS({
24133
24201
  if (config.framework) {
24134
24202
  builderConfig.framework = config.framework;
24135
24203
  }
24204
+ if (containerImage) {
24205
+ builderConfig.handler = containerImage;
24206
+ }
24207
+ if (config.command !== void 0) {
24208
+ builderConfig.command = normalizeContainerCommand(config.command);
24209
+ }
24136
24210
  if (moduleAttrParsed) {
24137
24211
  builderConfig.handlerFunction = moduleAttrParsed.attrName;
24138
24212
  }
@@ -24143,7 +24217,7 @@ var require_resolve2 = __commonJS({
24143
24217
  trigger,
24144
24218
  group,
24145
24219
  workspace,
24146
- entrypoint: resolvedEntrypointFile,
24220
+ entrypoint: containerImage ?? containerDockerfile ?? resolvedEntrypointFile,
24147
24221
  routePrefix,
24148
24222
  routePrefixSource: resolvedRoutePrefixSource,
24149
24223
  subdomain: normalizedSubdomain,
@@ -24182,7 +24256,7 @@ var require_resolve2 = __commonJS({
24182
24256
  }
24183
24257
  const serviceFs = serviceFsResult.fs;
24184
24258
  let resolvedEntrypoint;
24185
- if (typeof serviceConfig.entrypoint === "string") {
24259
+ if (typeof serviceConfig.entrypoint === "string" && !isContainerRuntime(serviceConfig)) {
24186
24260
  const moduleAttr = parsePyModuleAttrEntrypoint(serviceConfig.entrypoint);
24187
24261
  const entrypointToResolve = moduleAttr?.filePath ?? serviceConfig.entrypoint;
24188
24262
  const resolvedPath = await resolveEntrypointPath({
@@ -24379,6 +24453,67 @@ var require_resolve_v2 = __commonJS({
24379
24453
  var import_utils4 = require_utils3();
24380
24454
  var frameworksBySlug = new Map(import_frameworks2.frameworkList.map((f) => [f.slug, f]));
24381
24455
  var SERVICE_NAME_REGEX = /^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$/;
24456
+ function isDockerfileEntrypoint(entrypoint) {
24457
+ const base = import_path12.posix.basename(entrypoint).toLowerCase();
24458
+ return base === "dockerfile" || base === "containerfile" || base.endsWith(".dockerfile");
24459
+ }
24460
+ function normalizeContainerCommand(command) {
24461
+ if (command === void 0) {
24462
+ return void 0;
24463
+ }
24464
+ return Array.isArray(command) ? command : [command];
24465
+ }
24466
+ function resolveContainerServiceV2(name, config, normalizedRoot) {
24467
+ const isRoot = normalizedRoot === ".";
24468
+ const entrypoint = config.entrypoint;
24469
+ const dockerfile = typeof entrypoint === "string" && isDockerfileEntrypoint(entrypoint) ? import_path12.posix.normalize(entrypoint) : void 0;
24470
+ const image = typeof entrypoint === "string" && !dockerfile ? entrypoint : void 0;
24471
+ if (!dockerfile && !image) {
24472
+ return {
24473
+ error: {
24474
+ code: "MISSING_SERVICE_CONFIG",
24475
+ message: `Container service "${name}" must specify an "entrypoint": a Dockerfile path to build, or a prebuilt OCI image reference.`,
24476
+ serviceName: name
24477
+ }
24478
+ };
24479
+ }
24480
+ const localSrc = dockerfile ?? image ?? "Dockerfile";
24481
+ const builderSrc = isRoot ? localSrc : import_path12.posix.join(normalizedRoot, localSrc);
24482
+ const builderConfig = { zeroConfig: true };
24483
+ if (!isRoot) {
24484
+ builderConfig.workspace = normalizedRoot;
24485
+ }
24486
+ if (image) {
24487
+ builderConfig.handler = image;
24488
+ }
24489
+ const command = normalizeContainerCommand(config.command);
24490
+ if (command) {
24491
+ builderConfig.command = command;
24492
+ }
24493
+ return {
24494
+ service: {
24495
+ schema: "experimentalServicesV2",
24496
+ name,
24497
+ root: normalizedRoot,
24498
+ runtime: "container",
24499
+ entrypoint: image ?? dockerfile,
24500
+ command,
24501
+ builder: {
24502
+ src: builderSrc,
24503
+ use: "@vercel/container",
24504
+ config: builderConfig
24505
+ },
24506
+ bindings: config.bindings,
24507
+ functions: config.functions,
24508
+ headers: config.headers,
24509
+ redirects: config.redirects,
24510
+ rewrites: config.rewrites,
24511
+ routes: config.routes,
24512
+ cleanUrls: config.cleanUrls,
24513
+ trailingSlash: config.trailingSlash
24514
+ }
24515
+ };
24516
+ }
24382
24517
  function validateServiceConfigV22(name, config) {
24383
24518
  if (!SERVICE_NAME_REGEX.test(name)) {
24384
24519
  return {
@@ -24440,7 +24575,8 @@ var require_resolve_v2 = __commonJS({
24440
24575
  };
24441
24576
  }
24442
24577
  }
24443
- if (!config.framework && !config.entrypoint) {
24578
+ const isContainer = config.runtime === "container";
24579
+ if (!config.framework && !config.entrypoint && !isContainer) {
24444
24580
  return {
24445
24581
  code: "MISSING_SERVICE_CONFIG",
24446
24582
  message: `Service "${name}" must specify "framework" or "entrypoint".`,
@@ -24451,6 +24587,10 @@ var require_resolve_v2 = __commonJS({
24451
24587
  }
24452
24588
  async function resolveConfiguredServiceV22(name, config, fs5) {
24453
24589
  const normalizedRoot = (0, import_utils4.stripTrailingSlash)(import_path12.posix.normalize(config.root));
24590
+ const isContainer = config.runtime === "container" || typeof config.entrypoint === "string" && isDockerfileEntrypoint(config.entrypoint);
24591
+ if (isContainer) {
24592
+ return resolveContainerServiceV2(name, config, normalizedRoot);
24593
+ }
24454
24594
  const serviceFsResult = normalizedRoot === "." ? { fs: fs5 } : await (0, import_resolve.getServiceFs)(fs5, name, normalizedRoot);
24455
24595
  if (serviceFsResult.error) {
24456
24596
  return { error: serviceFsResult.error };
@@ -28577,8 +28717,23 @@ var require_detect_services = __commonJS({
28577
28717
  warnings: []
28578
28718
  });
28579
28719
  }
28720
+ if (vercelConfig?.services != null && vercelConfig.experimentalServicesV2 != null) {
28721
+ return withResolvedResult({
28722
+ services: [],
28723
+ source: "configured",
28724
+ useImplicitEnvInjection: false,
28725
+ routes: emptyRoutes(),
28726
+ errors: [
28727
+ {
28728
+ code: "SERVICES_AND_EXPERIMENTAL_SERVICES_V2",
28729
+ message: "The `services` property cannot be used in conjunction with its deprecated alias `experimentalServicesV2`. Please use only `services`."
28730
+ }
28731
+ ],
28732
+ warnings: []
28733
+ });
28734
+ }
28580
28735
  const hasProvidedConfiguredServices = providedConfiguredServices && Object.keys(providedConfiguredServices).length > 0;
28581
- const experimentalServicesV2 = hasProvidedConfiguredServices && providedConfiguredServicesType === "experimentalServicesV2" ? providedConfiguredServices : hasProvidedConfiguredServices ? void 0 : vercelConfig?.experimentalServicesV2;
28736
+ const experimentalServicesV2 = hasProvidedConfiguredServices && (providedConfiguredServicesType === "services" || providedConfiguredServicesType === "experimentalServicesV2") ? providedConfiguredServices : hasProvidedConfiguredServices ? void 0 : vercelConfig?.services ?? vercelConfig?.experimentalServicesV2;
28582
28737
  if (experimentalServicesV2 && Object.keys(experimentalServicesV2).length > 0) {
28583
28738
  const result2 = await (0, import_resolve_v2.resolveAllConfiguredServicesV2)(
28584
28739
  experimentalServicesV2,
@@ -28757,11 +28912,12 @@ var require_detect_services = __commonJS({
28757
28912
  }
28758
28913
  } else if (service.runtime) {
28759
28914
  const functionPath = (0, import_utils4.getInternalServiceFunctionPath)(service.name);
28915
+ const check2 = service.runtime === "container" ? void 0 : true;
28760
28916
  if (routePrefix === "/") {
28761
28917
  defaults.push({
28762
28918
  src: (0, import_routing_utils2.scopeRouteSourceToOwnership)("^/(.*)$", ownershipGuard),
28763
28919
  dest: functionPath,
28764
- check: true
28920
+ ...check2 ? { check: check2 } : {}
28765
28921
  });
28766
28922
  } else {
28767
28923
  rewrites.push({
@@ -28770,7 +28926,7 @@ var require_detect_services = __commonJS({
28770
28926
  ownershipGuard
28771
28927
  ),
28772
28928
  dest: functionPath,
28773
- check: true
28929
+ ...check2 ? { check: check2 } : {}
28774
28930
  });
28775
28931
  }
28776
28932
  }
@@ -29278,12 +29434,30 @@ var require_detect_builders = __commonJS({
29278
29434
  async function detectBuilders2(files, pkg, options = {}) {
29279
29435
  const {
29280
29436
  experimentalServices: experimentalServicesV1,
29437
+ services,
29281
29438
  experimentalServicesV2,
29282
29439
  projectSettings = {}
29283
29440
  } = options;
29441
+ if (services != null && experimentalServicesV2 != null) {
29442
+ return {
29443
+ builders: null,
29444
+ errors: [
29445
+ {
29446
+ code: "SERVICES_AND_EXPERIMENTAL_SERVICES_V2",
29447
+ message: "The `services` option cannot be used in conjunction with its deprecated alias `experimentalServicesV2`. Please use only `services`."
29448
+ }
29449
+ ],
29450
+ warnings: [],
29451
+ defaultRoutes: null,
29452
+ redirectRoutes: null,
29453
+ rewriteRoutes: null,
29454
+ errorRoutes: null
29455
+ };
29456
+ }
29284
29457
  const { framework } = projectSettings;
29285
- const configuredServices = experimentalServicesV2 ?? experimentalServicesV1;
29286
- const configuredServicesType = experimentalServicesV2 ? "experimentalServicesV2" : "experimentalServices";
29458
+ const servicesConfig = services ?? experimentalServicesV2;
29459
+ const configuredServices = servicesConfig ?? experimentalServicesV1;
29460
+ const configuredServicesType = servicesConfig ? services ? "services" : "experimentalServicesV2" : "experimentalServices";
29287
29461
  const hasServicesConfig = configuredServices != null && typeof configuredServices === "object";
29288
29462
  if (hasServicesConfig || framework === "services") {
29289
29463
  const result = await (0, import_get_services_builders.getServicesBuilders)({
@@ -36527,7 +36701,7 @@ var require_jsonfile3 = __commonJS({
36527
36701
  } catch (_) {
36528
36702
  _fs = __require("fs");
36529
36703
  }
36530
- function readFile6(file, options, callback) {
36704
+ function readFile7(file, options, callback) {
36531
36705
  if (callback == null) {
36532
36706
  callback = options;
36533
36707
  options = {};
@@ -36626,7 +36800,7 @@ var require_jsonfile3 = __commonJS({
36626
36800
  return content;
36627
36801
  }
36628
36802
  var jsonfile = {
36629
- readFile: readFile6,
36803
+ readFile: readFile7,
36630
36804
  readFileSync,
36631
36805
  writeFile: writeFile5,
36632
36806
  writeFileSync
@@ -37606,7 +37780,7 @@ var require_package = __commonJS({
37606
37780
  "../client/package.json"(exports, module) {
37607
37781
  module.exports = {
37608
37782
  name: "@vercel/client",
37609
- version: "17.5.18",
37783
+ version: "17.6.1",
37610
37784
  main: "dist/index.js",
37611
37785
  typings: "dist/index.d.ts",
37612
37786
  homepage: "https://vercel.com",
@@ -52239,6 +52413,102 @@ var require_archive = __commonJS({
52239
52413
  }
52240
52414
  });
52241
52415
 
52416
+ // ../client/dist/collect-deployment-files.js
52417
+ var require_collect_deployment_files = __commonJS({
52418
+ "../client/dist/collect-deployment-files.js"(exports, module) {
52419
+ "use strict";
52420
+ var __defProp = Object.defineProperty;
52421
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
52422
+ var __getOwnPropNames = Object.getOwnPropertyNames;
52423
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
52424
+ var __export2 = (target, all) => {
52425
+ for (var name in all)
52426
+ __defProp(target, name, { get: all[name], enumerable: true });
52427
+ };
52428
+ var __copyProps = (to, from, except, desc) => {
52429
+ if (from && typeof from === "object" || typeof from === "function") {
52430
+ for (let key of __getOwnPropNames(from))
52431
+ if (!__hasOwnProp.call(to, key) && key !== except)
52432
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
52433
+ }
52434
+ return to;
52435
+ };
52436
+ var __toCommonJS2 = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
52437
+ var collect_deployment_files_exports = {};
52438
+ __export2(collect_deployment_files_exports, {
52439
+ assertDeploymentPath: () => assertDeploymentPath,
52440
+ collectDeploymentFiles: () => collectDeploymentFiles
52441
+ });
52442
+ module.exports = __toCommonJS2(collect_deployment_files_exports);
52443
+ var import_error_utils5 = require_dist();
52444
+ var import_fs_extra9 = require_lib6();
52445
+ var import_path12 = __require("path");
52446
+ var import_errors3 = require_errors();
52447
+ var import_utils4 = require_utils9();
52448
+ var import_archive = require_archive();
52449
+ var import_hashes = require_hashes();
52450
+ function assertDeploymentPath(path, debug) {
52451
+ if (typeof path !== "string" && !Array.isArray(path)) {
52452
+ debug(
52453
+ `Error: 'path' is expected to be a string or an array. Received ${typeof path}`
52454
+ );
52455
+ throw new import_errors3.DeploymentError({
52456
+ code: "missing_path",
52457
+ message: "Path not provided"
52458
+ });
52459
+ }
52460
+ }
52461
+ async function collectDeploymentFiles(path, clientOptions, debug) {
52462
+ assertDeploymentPath(path, debug);
52463
+ const isDirectory2 = !Array.isArray(path) && (0, import_fs_extra9.lstatSync)(path).isDirectory();
52464
+ clientOptions.isDirectory = isDirectory2;
52465
+ if (Array.isArray(path)) {
52466
+ for (const filePath of path) {
52467
+ if (!(0, import_path12.isAbsolute)(filePath)) {
52468
+ throw new import_errors3.DeploymentError({
52469
+ code: "invalid_path",
52470
+ message: `Provided path ${filePath} is not absolute`
52471
+ });
52472
+ }
52473
+ }
52474
+ } else if (!(0, import_path12.isAbsolute)(path)) {
52475
+ throw new import_errors3.DeploymentError({
52476
+ code: "invalid_path",
52477
+ message: `Provided path ${path} is not absolute`
52478
+ });
52479
+ }
52480
+ if (isDirectory2 && !Array.isArray(path)) {
52481
+ debug(`Provided 'path' is a directory.`);
52482
+ } else if (Array.isArray(path)) {
52483
+ debug(`Provided 'path' is an array of file paths`);
52484
+ } else {
52485
+ debug(`Provided 'path' is a single file`);
52486
+ }
52487
+ const { fileList, ignoreList } = await (0, import_utils4.buildFileTree)(
52488
+ path,
52489
+ clientOptions,
52490
+ debug
52491
+ );
52492
+ const workPath = typeof path === "string" ? path : path[0];
52493
+ let filesMap;
52494
+ try {
52495
+ filesMap = clientOptions.archive === "tgz" ? await (0, import_archive.createTgzFiles)(workPath, fileList, debug) : await (0, import_hashes.hashes)(fileList);
52496
+ } catch (err) {
52497
+ if (clientOptions.prebuilt && (0, import_error_utils5.isErrnoException)(err) && err.code === "ENOENT" && err.path) {
52498
+ const errPath = (0, import_path12.relative)(workPath, err.path);
52499
+ err.message = `File does not exist: "${(0, import_path12.relative)(workPath, errPath)}"`;
52500
+ if (errPath.split(import_path12.sep).includes("node_modules")) {
52501
+ err.message = `Please ensure project dependencies have been installed:
52502
+ ${err.message}`;
52503
+ }
52504
+ }
52505
+ throw err;
52506
+ }
52507
+ return { fileList, filesMap, workPath, isDirectory: isDirectory2, ignoreList };
52508
+ }
52509
+ }
52510
+ });
52511
+
52242
52512
  // ../client/dist/create-deployment.js
52243
52513
  var require_create_deployment = __commonJS({
52244
52514
  "../client/dist/create-deployment.js"(exports, module) {
@@ -52265,29 +52535,18 @@ var require_create_deployment = __commonJS({
52265
52535
  default: () => buildCreateDeployment
52266
52536
  });
52267
52537
  module.exports = __toCommonJS2(create_deployment_exports);
52268
- var import_fs_extra9 = require_lib6();
52269
- var import_path12 = __require("path");
52270
52538
  var import_hashes = require_hashes();
52271
52539
  var import_deploy = require_deploy();
52272
52540
  var import_upload = require_upload();
52273
52541
  var import_utils4 = require_utils9();
52274
52542
  var import_errors3 = require_errors();
52275
- var import_error_utils5 = require_dist();
52276
- var import_archive = require_archive();
52543
+ var import_collect_deployment_files = require_collect_deployment_files();
52277
52544
  function buildCreateDeployment() {
52278
52545
  return async function* createDeployment(clientOptions, deploymentOptions = {}) {
52279
52546
  const { path } = clientOptions;
52280
52547
  const debug = (0, import_utils4.createDebug)(clientOptions.debug);
52281
52548
  debug("Creating deployment...");
52282
- if (typeof path !== "string" && !Array.isArray(path)) {
52283
- debug(
52284
- `Error: 'path' is expected to be a string or an array. Received ${typeof path}`
52285
- );
52286
- throw new import_errors3.DeploymentError({
52287
- code: "missing_path",
52288
- message: "Path not provided"
52289
- });
52290
- }
52549
+ (0, import_collect_deployment_files.assertDeploymentPath)(path, debug);
52291
52550
  if (typeof clientOptions.token !== "string") {
52292
52551
  debug(
52293
52552
  `Error: 'token' is expected to be a string. Received ${typeof clientOptions.token}`
@@ -52313,30 +52572,11 @@ var require_create_deployment = __commonJS({
52313
52572
  yield* (0, import_deploy.deploy)(/* @__PURE__ */ new Map(), clientOptions, deploymentOptions);
52314
52573
  return;
52315
52574
  }
52316
- clientOptions.isDirectory = !Array.isArray(path) && (0, import_fs_extra9.lstatSync)(path).isDirectory();
52317
- if (Array.isArray(path)) {
52318
- for (const filePath of path) {
52319
- if (!(0, import_path12.isAbsolute)(filePath)) {
52320
- throw new import_errors3.DeploymentError({
52321
- code: "invalid_path",
52322
- message: `Provided path ${filePath} is not absolute`
52323
- });
52324
- }
52325
- }
52326
- } else if (!(0, import_path12.isAbsolute)(path)) {
52327
- throw new import_errors3.DeploymentError({
52328
- code: "invalid_path",
52329
- message: `Provided path ${path} is not absolute`
52330
- });
52331
- }
52332
- if (clientOptions.isDirectory && !Array.isArray(path)) {
52333
- debug(`Provided 'path' is a directory.`);
52334
- } else if (Array.isArray(path)) {
52335
- debug(`Provided 'path' is an array of file paths`);
52336
- } else {
52337
- debug(`Provided 'path' is a single file`);
52338
- }
52339
- const { fileList } = await (0, import_utils4.buildFileTree)(path, clientOptions, debug);
52575
+ const { fileList, filesMap: files } = await (0, import_collect_deployment_files.collectDeploymentFiles)(
52576
+ path,
52577
+ clientOptions,
52578
+ debug
52579
+ );
52340
52580
  if (fileList.length === 0) {
52341
52581
  debug("Deployment path has no files. Yielding a warning event");
52342
52582
  yield {
@@ -52344,25 +52584,6 @@ var require_create_deployment = __commonJS({
52344
52584
  payload: "There are no files inside your deployment."
52345
52585
  };
52346
52586
  }
52347
- const workPath = typeof path === "string" ? path : path[0];
52348
- let files;
52349
- try {
52350
- if (clientOptions.archive === "tgz") {
52351
- files = await (0, import_archive.createTgzFiles)(workPath, fileList, debug);
52352
- } else {
52353
- files = await (0, import_hashes.hashes)(fileList);
52354
- }
52355
- } catch (err) {
52356
- if (clientOptions.prebuilt && (0, import_error_utils5.isErrnoException)(err) && err.code === "ENOENT" && err.path) {
52357
- const errPath = (0, import_path12.relative)(workPath, err.path);
52358
- err.message = `File does not exist: "${(0, import_path12.relative)(workPath, errPath)}"`;
52359
- if (errPath.split(import_path12.sep).includes("node_modules")) {
52360
- err.message = `Please ensure project dependencies have been installed:
52361
- ${err.message}`;
52362
- }
52363
- }
52364
- throw err;
52365
- }
52366
52587
  debug(`Yielding a 'hashes-calculated' event with ${files.size} hashes`);
52367
52588
  yield { type: "hashes-calculated", payload: (0, import_hashes.mapToObject)(files) };
52368
52589
  if (clientOptions.apiUrl) {
@@ -52609,6 +52830,71 @@ var require_continue = __commonJS({
52609
52830
  }
52610
52831
  });
52611
52832
 
52833
+ // ../client/dist/inspect-deployment-files.js
52834
+ var require_inspect_deployment_files = __commonJS({
52835
+ "../client/dist/inspect-deployment-files.js"(exports, module) {
52836
+ "use strict";
52837
+ var __defProp = Object.defineProperty;
52838
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
52839
+ var __getOwnPropNames = Object.getOwnPropertyNames;
52840
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
52841
+ var __export2 = (target, all) => {
52842
+ for (var name in all)
52843
+ __defProp(target, name, { get: all[name], enumerable: true });
52844
+ };
52845
+ var __copyProps = (to, from, except, desc) => {
52846
+ if (from && typeof from === "object" || typeof from === "function") {
52847
+ for (let key of __getOwnPropNames(from))
52848
+ if (!__hasOwnProp.call(to, key) && key !== except)
52849
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
52850
+ }
52851
+ return to;
52852
+ };
52853
+ var __toCommonJS2 = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
52854
+ var inspect_deployment_files_exports = {};
52855
+ __export2(inspect_deployment_files_exports, {
52856
+ inspectDeploymentFiles: () => inspectDeploymentFiles2
52857
+ });
52858
+ module.exports = __toCommonJS2(inspect_deployment_files_exports);
52859
+ var import_path12 = __require("path");
52860
+ var import_collect_deployment_files = require_collect_deployment_files();
52861
+ var import_utils4 = require_utils9();
52862
+ async function inspectDeploymentFiles2(clientOptions) {
52863
+ const { path } = clientOptions;
52864
+ const debug = (0, import_utils4.createDebug)(clientOptions.debug);
52865
+ const { filesMap, workPath, isDirectory: isDirectory2, ignoreList } = await (0, import_collect_deployment_files.collectDeploymentFiles)(path, { ...clientOptions }, debug);
52866
+ const files = [];
52867
+ let totalSize = 0;
52868
+ for (const [sha, file] of filesMap) {
52869
+ const size = file.data?.byteLength || file.data?.length || 0;
52870
+ for (const name of file.names) {
52871
+ const pathName = isDirectory2 ? (0, import_path12.relative)(workPath, name) : name.split(import_path12.sep).at(-1) || name;
52872
+ const normalizedPath = pathName.split(import_path12.sep).join("/");
52873
+ const deploymentFile = {
52874
+ path: normalizedPath,
52875
+ size,
52876
+ mode: file.mode
52877
+ };
52878
+ if (typeof sha !== "undefined") {
52879
+ deploymentFile.sha = sha;
52880
+ }
52881
+ files.push(deploymentFile);
52882
+ totalSize += size;
52883
+ }
52884
+ }
52885
+ files.sort((a, b) => a.path.localeCompare(b.path));
52886
+ return {
52887
+ basePath: workPath,
52888
+ fileCount: files.length,
52889
+ totalSize,
52890
+ ignoredCount: ignoreList.length,
52891
+ files,
52892
+ ignored: ignoreList.sort()
52893
+ };
52894
+ }
52895
+ }
52896
+ });
52897
+
52612
52898
  // ../client/dist/types.js
52613
52899
  var require_types4 = __commonJS({
52614
52900
  "../client/dist/types.js"(exports, module) {
@@ -52681,12 +52967,14 @@ var require_dist7 = __commonJS({
52681
52967
  checkDeploymentStatus: () => import_check_deployment_status.checkDeploymentStatus,
52682
52968
  continueDeployment: () => import_continue.continueDeployment,
52683
52969
  createDeployment: () => createDeployment,
52684
- getVercelIgnore: () => import_utils4.getVercelIgnore
52970
+ getVercelIgnore: () => import_utils4.getVercelIgnore,
52971
+ inspectDeploymentFiles: () => import_inspect_deployment_files.inspectDeploymentFiles
52685
52972
  });
52686
52973
  module.exports = __toCommonJS2(src_exports);
52687
52974
  var import_create_deployment = __toESM2(require_create_deployment());
52688
52975
  var import_continue = require_continue();
52689
52976
  var import_check_deployment_status = require_check_deployment_status();
52977
+ var import_inspect_deployment_files = require_inspect_deployment_files();
52690
52978
  var import_utils4 = require_utils9();
52691
52979
  __reExport(src_exports, require_errors(), module.exports);
52692
52980
  __reExport(src_exports, require_types4(), module.exports);
@@ -52696,7 +52984,7 @@ var require_dist7 = __commonJS({
52696
52984
 
52697
52985
  // src/util/compile-vercel-config.ts
52698
52986
  var import_dotenv = __toESM(require_main(), 1);
52699
- import { mkdir, readFile as readFile5, writeFile as writeFile4, unlink, access } from "fs/promises";
52987
+ import { mkdir, readFile as readFile6, writeFile as writeFile4, unlink, access } from "fs/promises";
52700
52988
  import { join as join10, basename as basename3 } from "path";
52701
52989
  import { fork } from "child_process";
52702
52990
  import { parse as tomlParse2 } from "smol-toml";
@@ -54684,6 +54972,22 @@ async function connectGitProvider(client, projectId, type, repo) {
54684
54972
  repo
54685
54973
  )} to project. Make sure there aren't any typos and that you have access to the repository if it's private.`
54686
54974
  );
54975
+ } else if (apiError && err.code === "repo_links_exceeded_limit") {
54976
+ let ctaLabel;
54977
+ let ctaUrl;
54978
+ if (typeof err.ctaLabel === "string" && typeof err.ctaUrl === "string") {
54979
+ ctaLabel = err.ctaLabel;
54980
+ ctaUrl = err.ctaUrl;
54981
+ } else if (typeof err.action === "string" && typeof err.link === "string") {
54982
+ ctaLabel = err.action;
54983
+ ctaUrl = err.link;
54984
+ }
54985
+ let message = err.message;
54986
+ if (ctaLabel && ctaUrl) {
54987
+ message += `
54988
+ ${ctaLabel}: ${link_default(ctaUrl)}`;
54989
+ }
54990
+ output_manager_default.error(message);
54687
54991
  } else if (apiError && err.action === "Add a Login Connection") {
54688
54992
  output_manager_default.error(
54689
54993
  err.message.replace(repo, import_chalk5.default.cyan(repo)) + `
@@ -55497,6 +55801,41 @@ function addDeltaSection(prefix, arr, changed = false) {
55497
55801
  return arr.sort().map((item) => ` ${prefix} ${item}${changed ? " (Updated)" : ""}`).join("\n") + "\n";
55498
55802
  }
55499
55803
 
55804
+ // src/util/env/constants.ts
55805
+ var VERCEL_OIDC_TOKEN = "VERCEL_OIDC_TOKEN";
55806
+
55807
+ // src/util/env/update-oidc-token-contents.ts
55808
+ var CONTENTS_HEADER = "# Created by Vercel CLI";
55809
+ function updateOidcTokenContents(existing, token) {
55810
+ const assignment = `${VERCEL_OIDC_TOKEN}="${escapeValue(token)}"`;
55811
+ const oidcAssignment = new RegExp(
55812
+ `^(\\uFEFF?)[\\t ]*(?:export[\\t ]+)?${VERCEL_OIDC_TOKEN}[\\t ]*=[^\\r\\n]*(\\r\\n|\\n|\\r|$)`,
55813
+ "gm"
55814
+ );
55815
+ let tokenWritten = false;
55816
+ const withoutDuplicates = existing.replace(
55817
+ oidcAssignment,
55818
+ (_match, byteOrderMark, lineEnding2) => {
55819
+ if (token !== void 0 && !tokenWritten) {
55820
+ tokenWritten = true;
55821
+ return `${byteOrderMark}${assignment}${lineEnding2}`;
55822
+ }
55823
+ return byteOrderMark;
55824
+ }
55825
+ );
55826
+ if (token === void 0 || tokenWritten) {
55827
+ return withoutDuplicates;
55828
+ }
55829
+ const lineEnding = withoutDuplicates.match(/\r\n|\n|\r/)?.[0] ?? "\n";
55830
+ const hasTrailingLineEnding = /(?:\r\n|\n|\r)$/.test(withoutDuplicates);
55831
+ const hasTrailingBlankLine = /(?:\r\n|\n|\r){2}$/.test(withoutDuplicates);
55832
+ const separator = withoutDuplicates.length === 0 || hasTrailingBlankLine ? "" : hasTrailingLineEnding ? lineEnding : `${lineEnding}${lineEnding}`;
55833
+ return `${withoutDuplicates}${separator}${CONTENTS_HEADER}${lineEnding}${assignment}${lineEnding}`;
55834
+ }
55835
+ function escapeValue(value) {
55836
+ return value ? value.replace(/\n/g, "\\n").replace(/\r/g, "\\r") : "";
55837
+ }
55838
+
55500
55839
  // src/commands/env/pull.ts
55501
55840
  var import_error_utils2 = __toESM(require_dist(), 1);
55502
55841
  var import_json_parse_better_errors = __toESM(require_json_parse_better_errors(), 1);
@@ -55565,9 +55904,9 @@ var EnvPullTelemetryClient = class extends TelemetryClient {
55565
55904
  };
55566
55905
 
55567
55906
  // src/util/env/env-target.ts
55568
- var import_constants = __toESM(require_dist2(), 1);
55907
+ var import_constants2 = __toESM(require_dist2(), 1);
55569
55908
  var import_title = __toESM(require_lib(), 1);
55570
- var envTargetChoices = import_constants.PROJECT_ENV_TARGET.map((t) => ({
55909
+ var envTargetChoices = import_constants2.PROJECT_ENV_TARGET.map((t) => ({
55571
55910
  name: (0, import_title.default)(t),
55572
55911
  value: t
55573
55912
  }));
@@ -56411,7 +56750,7 @@ var VARIABLES_TO_IGNORE = [
56411
56750
  "VERCEL_SPEED_INSIGHTS_ID",
56412
56751
  "VERCEL_WEB_ANALYTICS_ID"
56413
56752
  ];
56414
- async function pull(client, argv, source = "vercel-cli:env:pull") {
56753
+ async function pull(client, argv, source = "vercel-cli:env:pull", options = {}) {
56415
56754
  const telemetryClient = new EnvPullTelemetryClient({
56416
56755
  opts: {
56417
56756
  store: client.telemetryEventStore
@@ -56492,17 +56831,18 @@ async function pull(client, argv, source = "vercel-cli:env:pull") {
56492
56831
  gitBranch,
56493
56832
  client.cwd,
56494
56833
  source,
56495
- deploymentId
56834
+ deploymentId,
56835
+ options
56496
56836
  );
56497
56837
  return 0;
56498
56838
  }
56499
- async function envPullCommandLogic(client, filename, skipConfirmation, environment, link, gitBranch, cwd, source, deploymentId) {
56839
+ async function envPullCommandLogic(client, filename, skipConfirmation, environment, link, gitBranch, cwd, source, deploymentId, { oidcTokenOnly = false } = {}) {
56500
56840
  const fullPath = resolve3(cwd, filename);
56501
56841
  const head = tryReadHeadSync(fullPath, Buffer.byteLength(CONTENTS_PREFIX));
56502
56842
  const exists = typeof head !== "undefined";
56503
- if (head === CONTENTS_PREFIX) {
56843
+ if (head === CONTENTS_PREFIX && !oidcTokenOnly) {
56504
56844
  output_manager_default.log(`Overwriting existing ${import_chalk12.default.bold(filename)} file`);
56505
- } else if (exists && !skipConfirmation) {
56845
+ } else if (exists && !skipConfirmation && !oidcTokenOnly) {
56506
56846
  if (client.nonInteractive) {
56507
56847
  outputActionRequired(client, {
56508
56848
  status: "action_required",
@@ -56529,7 +56869,9 @@ async function envPullCommandLogic(client, filename, skipConfirmation, environme
56529
56869
  }
56530
56870
  }
56531
56871
  const projectSlugLink = formatProject(link.org.slug, link.project.name);
56532
- const downloadMessage = gitBranch ? `Downloading \`${import_chalk12.default.cyan(
56872
+ const downloadMessage = oidcTokenOnly ? `Downloading a fresh \`${import_chalk12.default.cyan(
56873
+ VERCEL_OIDC_TOKEN
56874
+ )}\` for ${projectSlugLink}` : gitBranch ? `Downloading \`${import_chalk12.default.cyan(
56533
56875
  environment
56534
56876
  )}\` environment variables for ${projectSlugLink} and any overrides for branch ${import_chalk12.default.cyan(
56535
56877
  gitBranch
@@ -56546,26 +56888,48 @@ async function envPullCommandLogic(client, filename, skipConfirmation, environme
56546
56888
  const records = deploymentId ? pullResult.buildEnv : pullResult.env;
56547
56889
  let deltaString = "";
56548
56890
  let oldEnv;
56549
- if (exists) {
56891
+ if (exists && !oidcTokenOnly) {
56550
56892
  oldEnv = await createEnvObject(fullPath);
56551
56893
  if (oldEnv) {
56552
56894
  const newEnv = (0, import_json_parse_better_errors.default)(JSON.stringify(records).replace(/\\"/g, ""));
56553
56895
  deltaString = buildDeltaString(oldEnv, newEnv);
56554
56896
  }
56555
56897
  }
56556
- const contents = CONTENTS_PREFIX + Object.keys(records).sort().filter((key) => !VARIABLES_TO_IGNORE.includes(key)).map((key) => `${key}="${escapeValue(records[key])}"`).join("\n") + "\n";
56557
- await (0, import_fs_extra5.outputFile)(fullPath, contents, "utf8");
56898
+ let contents;
56899
+ let fileChanged = true;
56900
+ if (oidcTokenOnly) {
56901
+ const existingContents = exists ? await (0, import_fs_extra5.readFile)(fullPath, "utf8") : "";
56902
+ contents = updateOidcTokenContents(
56903
+ existingContents,
56904
+ records[VERCEL_OIDC_TOKEN] || void 0
56905
+ );
56906
+ fileChanged = contents !== existingContents;
56907
+ } else {
56908
+ contents = CONTENTS_PREFIX + Object.keys(records).sort().filter((key) => !VARIABLES_TO_IGNORE.includes(key)).map((key) => `${key}="${escapeValue2(records[key])}"`).join("\n") + "\n";
56909
+ }
56910
+ if (fileChanged) {
56911
+ await (0, import_fs_extra5.outputFile)(fullPath, contents, "utf8");
56912
+ }
56558
56913
  if (deltaString) {
56559
56914
  output_manager_default.print("\n" + deltaString);
56560
56915
  } else if (oldEnv && exists) {
56561
56916
  output_manager_default.log("No changes found.");
56562
56917
  }
56563
56918
  let isGitIgnoreUpdated = false;
56564
- if (filename === ".env.local") {
56919
+ const fileExistsAfterPull = exists || contents.length > 0;
56920
+ if (filename === ".env.local" && fileExistsAfterPull) {
56565
56921
  const rootPath = link.repoRoot ?? cwd;
56566
56922
  isGitIgnoreUpdated = await addToGitIgnore(rootPath, ".env*");
56567
56923
  }
56924
+ if (!fileChanged && !isGitIgnoreUpdated) {
56925
+ output_manager_default.stopSpinner();
56926
+ return;
56927
+ }
56568
56928
  output_manager_default.print("\n");
56929
+ if (!fileChanged) {
56930
+ printAlignedLabel("Updated", `.gitignore for ${filename}`, { gutter: "\u2713" });
56931
+ return;
56932
+ }
56569
56933
  printAlignedLabel(
56570
56934
  exists ? "Updated" : "Created",
56571
56935
  `${filename} file${isGitIgnoreUpdated ? " and added it to .gitignore" : ""}`,
@@ -56620,7 +56984,7 @@ function getAcrValuesFromWWWAuthenticate(header) {
56620
56984
  );
56621
56985
  return match?.[1]?.replace(/\\(.)/g, "$1") ?? match?.[2];
56622
56986
  }
56623
- function escapeValue(value) {
56987
+ function escapeValue2(value) {
56624
56988
  return value ? value.replace(new RegExp("\n", "g"), "\\n").replace(new RegExp("\r", "g"), "\\r") : "";
56625
56989
  }
56626
56990
 
@@ -56632,7 +56996,7 @@ import { join as join8, dirname } from "path";
56632
56996
 
56633
56997
  // src/util/projects/detect-services.ts
56634
56998
  var import_fs_detectors2 = __toESM(require_dist6(), 1);
56635
- import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
56999
+ import { readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
56636
57000
  import { basename as basename2, join as join7 } from "path";
56637
57001
  import { parse as tomlParse, stringify as tomlStringify } from "smol-toml";
56638
57002
 
@@ -56950,6 +57314,16 @@ var getExperimentalServicesCommonProperties = () => ({
56950
57314
  minLength: 1,
56951
57315
  maxLength: 2048
56952
57316
  },
57317
+ command: {
57318
+ oneOf: [
57319
+ { type: "string", minLength: 1, maxLength: 2048 },
57320
+ {
57321
+ type: "array",
57322
+ minItems: 1,
57323
+ items: { type: "string", minLength: 1, maxLength: 2048 }
57324
+ }
57325
+ ]
57326
+ },
56953
57327
  memory: {
56954
57328
  type: "integer",
56955
57329
  minimum: 128,
@@ -57112,17 +57486,17 @@ var experimentalServiceGroupsSchema = {
57112
57486
  }
57113
57487
  }
57114
57488
  };
57115
- var experimentalServicesV2PathSchema = {
57489
+ var servicesPathSchema = {
57116
57490
  type: "string",
57117
57491
  minLength: 1,
57118
57492
  maxLength: 512
57119
57493
  };
57120
- var experimentalServicesV2CommandSchema = {
57494
+ var servicesCommandSchema = {
57121
57495
  type: "string",
57122
57496
  minLength: 1,
57123
57497
  maxLength: 2048
57124
57498
  };
57125
- var experimentalServicesV2BindingSchema = {
57499
+ var servicesBindingSchema = {
57126
57500
  type: "object",
57127
57501
  additionalProperties: false,
57128
57502
  required: ["type", "service", "format", "env"],
@@ -57141,17 +57515,17 @@ var experimentalServicesV2BindingSchema = {
57141
57515
  }
57142
57516
  }
57143
57517
  };
57144
- var experimentalServicesV2BindingsSchema = {
57518
+ var servicesBindingsSchema = {
57145
57519
  type: "array",
57146
57520
  maxItems: 100,
57147
- items: experimentalServicesV2BindingSchema
57521
+ items: servicesBindingSchema
57148
57522
  };
57149
- var getExperimentalServicesV2ServiceConfigSchema = () => ({
57523
+ var getServicesServiceConfigSchema = () => ({
57150
57524
  type: "object",
57151
57525
  additionalProperties: false,
57152
57526
  required: ["root"],
57153
57527
  properties: {
57154
- root: experimentalServicesV2PathSchema,
57528
+ root: servicesPathSchema,
57155
57529
  framework: {
57156
57530
  type: "string",
57157
57531
  minLength: 1,
@@ -57162,13 +57536,16 @@ var getExperimentalServicesV2ServiceConfigSchema = () => ({
57162
57536
  minLength: 1,
57163
57537
  maxLength: 256
57164
57538
  },
57165
- entrypoint: experimentalServicesV2PathSchema,
57166
- installCommand: experimentalServicesV2CommandSchema,
57167
- buildCommand: experimentalServicesV2CommandSchema,
57168
- devCommand: experimentalServicesV2CommandSchema,
57169
- ignoreCommand: experimentalServicesV2CommandSchema,
57170
- outputDirectory: experimentalServicesV2PathSchema,
57171
- bindings: experimentalServicesV2BindingsSchema,
57539
+ entrypoint: servicesPathSchema,
57540
+ command: {
57541
+ oneOf: [{ type: "string" }, { type: "array", items: { type: "string" } }]
57542
+ },
57543
+ installCommand: servicesCommandSchema,
57544
+ buildCommand: servicesCommandSchema,
57545
+ devCommand: servicesCommandSchema,
57546
+ ignoreCommand: servicesCommandSchema,
57547
+ outputDirectory: servicesPathSchema,
57548
+ bindings: servicesBindingsSchema,
57172
57549
  functions: getFunctionsSchema(),
57173
57550
  headers: import_routing_utils.headersSchema,
57174
57551
  redirects: import_routing_utils.redirectsSchema,
@@ -57178,13 +57555,13 @@ var getExperimentalServicesV2ServiceConfigSchema = () => ({
57178
57555
  trailingSlash: import_routing_utils.trailingSlashSchema
57179
57556
  }
57180
57557
  });
57181
- var getExperimentalServicesV2Schema = () => ({
57558
+ var getServicesSchema = () => ({
57182
57559
  type: "object",
57183
57560
  propertyNames: {
57184
57561
  pattern: "^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$",
57185
57562
  maxLength: 64
57186
57563
  },
57187
- additionalProperties: getExperimentalServicesV2ServiceConfigSchema()
57564
+ additionalProperties: getServicesServiceConfigSchema()
57188
57565
  });
57189
57566
  function buildVercelConfigSchema() {
57190
57567
  return {
@@ -57206,7 +57583,8 @@ function buildVercelConfigSchema() {
57206
57583
  bunVersion: { type: "string" },
57207
57584
  experimentalServices: getExperimentalServicesSchema(),
57208
57585
  experimentalServiceGroups: experimentalServiceGroupsSchema,
57209
- experimentalServicesV2: getExperimentalServicesV2Schema()
57586
+ services: getServicesSchema(),
57587
+ experimentalServicesV2: getServicesSchema()
57210
57588
  }
57211
57589
  };
57212
57590
  }
@@ -57258,20 +57636,30 @@ function validateConfig(config) {
57258
57636
  message: "The `experimentalServiceGroups` property requires `experimentalServices` to be defined. Service groups reference services by name."
57259
57637
  });
57260
57638
  }
57261
- const hasExperimentalServicesV2 = Boolean(config.experimentalServicesV2);
57262
- if (hasExperimentalServicesV2 && hasExperimentalServices) {
57639
+ const hasServices = config.services != null;
57640
+ const hasExperimentalServicesV2 = config.experimentalServicesV2 != null;
57641
+ if (hasServices && hasExperimentalServicesV2) {
57263
57642
  return new NowBuildError({
57264
- code: "EXPERIMENTAL_SERVICES_V2_AND_EXPERIMENTAL_SERVICES",
57265
- message: "The `experimentalServicesV2` property cannot be used in conjunction with the `experimentalServices` property. Please use only one services configuration."
57643
+ code: "SERVICES_AND_EXPERIMENTAL_SERVICES_V2",
57644
+ message: "The `services` property cannot be used in conjunction with its deprecated alias `experimentalServicesV2`. Please use only `services`."
57266
57645
  });
57267
57646
  }
57268
- if (hasExperimentalServicesV2 && config.builds) {
57647
+ const servicesConfig = config.services ?? config.experimentalServicesV2;
57648
+ const servicesConfigKey = hasServices ? "services" : "experimentalServicesV2";
57649
+ const servicesErrorCodePrefix = hasServices ? "SERVICES" : "EXPERIMENTAL_SERVICES_V2";
57650
+ if (servicesConfig && hasExperimentalServices) {
57269
57651
  return new NowBuildError({
57270
- code: "EXPERIMENTAL_SERVICES_V2_AND_BUILDS",
57271
- message: "The `experimentalServicesV2` property cannot be used in conjunction with the `builds` property. Please remove one of them."
57652
+ code: `${servicesErrorCodePrefix}_AND_EXPERIMENTAL_SERVICES`,
57653
+ message: `The \`${servicesConfigKey}\` property cannot be used in conjunction with the \`experimentalServices\` property. Please use only one services configuration.`
57272
57654
  });
57273
57655
  }
57274
- if (hasExperimentalServicesV2) {
57656
+ if (servicesConfig && config.builds) {
57657
+ return new NowBuildError({
57658
+ code: `${servicesErrorCodePrefix}_AND_BUILDS`,
57659
+ message: `The \`${servicesConfigKey}\` property cannot be used in conjunction with the \`builds\` property. Please remove one of them.`
57660
+ });
57661
+ }
57662
+ if (servicesConfig) {
57275
57663
  const ambiguousTopLevel = [];
57276
57664
  if (config.functions != null) {
57277
57665
  ambiguousTopLevel.push("functions");
@@ -57298,21 +57686,19 @@ function validateConfig(config) {
57298
57686
  const count = ambiguousTopLevel.length;
57299
57687
  const fields = ambiguousTopLevel.map((field) => `\`${field}\``).join(", ");
57300
57688
  return new NowBuildError({
57301
- code: "EXPERIMENTAL_SERVICES_V2_AND_TOP_LEVEL_BUILD_SETTINGS",
57302
- message: `The top-level ${count > 1 ? "properties" : "property"} ${fields} cannot be used with \`experimentalServicesV2\` because the owning service is ambiguous. Move ${count > 1 ? "them" : "it"} under the relevant service in \`experimentalServicesV2\`.`
57689
+ code: `${servicesErrorCodePrefix}_AND_TOP_LEVEL_BUILD_SETTINGS`,
57690
+ message: `The top-level ${count > 1 ? "properties" : "property"} ${fields} cannot be used with \`${servicesConfigKey}\` because the owning service is ambiguous. Move ${count > 1 ? "them" : "it"} under the relevant service in \`${servicesConfigKey}\`.`
57303
57691
  });
57304
57692
  }
57305
57693
  }
57306
- if (config.experimentalServicesV2) {
57307
- const serviceNames = new Set(Object.keys(config.experimentalServicesV2));
57308
- for (const [serviceName, serviceConfig] of Object.entries(
57309
- config.experimentalServicesV2
57310
- )) {
57694
+ if (servicesConfig) {
57695
+ const serviceNames = new Set(Object.keys(servicesConfig));
57696
+ for (const [serviceName, serviceConfig] of Object.entries(servicesConfig)) {
57311
57697
  for (const binding of serviceConfig.bindings ?? []) {
57312
57698
  if (!serviceNames.has(binding.service)) {
57313
57699
  return new NowBuildError({
57314
- code: "EXPERIMENTAL_SERVICES_V2_BINDING_UNKNOWN_SERVICE",
57315
- message: `Service "${serviceName}" declares a binding to unknown service "${binding.service}". Add "${binding.service}" to \`experimentalServicesV2\` or fix the binding.`
57700
+ code: `${servicesErrorCodePrefix}_BINDING_UNKNOWN_SERVICE`,
57701
+ message: `Service "${serviceName}" declares a binding to unknown service "${binding.service}". Add "${binding.service}" to \`${servicesConfigKey}\` or fix the binding.`
57316
57702
  });
57317
57703
  }
57318
57704
  }
@@ -57368,7 +57754,7 @@ async function hasExperimentalServicesConfig(cwd) {
57368
57754
  );
57369
57755
  if (!config || config instanceof Error)
57370
57756
  return false;
57371
- return config.experimentalServices != null && typeof config.experimentalServices === "object" || config.experimentalServicesV2 != null && typeof config.experimentalServicesV2 === "object";
57757
+ return config.experimentalServices != null && typeof config.experimentalServices === "object" || config.services != null && typeof config.services === "object" || config.experimentalServicesV2 != null && typeof config.experimentalServicesV2 === "object";
57372
57758
  } catch {
57373
57759
  return false;
57374
57760
  }
@@ -57446,7 +57832,7 @@ async function prepareTomlServicesConfigWrite(configPath, config) {
57446
57832
  const patchKeys = Object.keys(patch);
57447
57833
  let existingContent;
57448
57834
  try {
57449
- existingContent = await readFile3(configPath, "utf8");
57835
+ existingContent = await readFile4(configPath, "utf8");
57450
57836
  } catch {
57451
57837
  existingContent = "";
57452
57838
  }
@@ -57521,7 +57907,7 @@ async function resolveProjectCwd(cwd) {
57521
57907
  }
57522
57908
 
57523
57909
  // src/util/projects/link.ts
57524
- var readFile4 = promisify(fs4.readFile);
57910
+ var readFile5 = promisify(fs4.readFile);
57525
57911
  var writeFile3 = promisify(fs4.writeFile);
57526
57912
  var VERCEL_DIR = ".vercel";
57527
57913
  var VERCEL_DIR_FALLBACK = ".now";
@@ -57639,7 +58025,7 @@ async function getProjectLinkFromRepoLink(client, path, projectName, projectName
57639
58025
  }
57640
58026
  async function getLinkFromDir(dir) {
57641
58027
  try {
57642
- const json = await readFile4(join9(dir, VERCEL_DIR_PROJECT), "utf8");
58028
+ const json = await readFile5(join9(dir, VERCEL_DIR_PROJECT), "utf8");
57643
58029
  const ajv2 = new import_ajv2.default();
57644
58030
  const link = JSON.parse(json);
57645
58031
  if (!ajv2.validate(linkSchema, link)) {
@@ -58046,7 +58432,7 @@ async function compileVercelConfig(workPath) {
58046
58432
  }
58047
58433
  if (hasVercelToml) {
58048
58434
  try {
58049
- const tomlContent = await readFile5(vercelTomlPath, "utf8");
58435
+ const tomlContent = await readFile6(vercelTomlPath, "utf8");
58050
58436
  const config = tomlParse2(tomlContent);
58051
58437
  const normalizedConfig = normalizeConfig(config);
58052
58438
  await mkdir(vercelDir, { recursive: true });
@@ -58271,6 +58657,7 @@ export {
58271
58657
  pullEnvRecords,
58272
58658
  parseEnv,
58273
58659
  createEnvObject,
58660
+ VERCEL_OIDC_TOKEN,
58274
58661
  require_json_parse_better_errors,
58275
58662
  formatProject,
58276
58663
  STANDARD_ENVIRONMENTS,