vercel 53.3.2 → 54.0.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 (68) hide show
  1. package/dist/chunks/{add-3SVEYCYO.js → add-FEHGU5ZE.js} +8 -8
  2. package/dist/chunks/{chunk-X7KU44KR.js → chunk-23SNIB7J.js} +1 -1
  3. package/dist/chunks/{chunk-NIOGCTVR.js → chunk-2GC2GW2H.js} +2 -2
  4. package/dist/chunks/{chunk-WOWCXMTU.js → chunk-3CBPQ6CA.js} +1 -1
  5. package/dist/chunks/{chunk-FVDSS6AL.js → chunk-4243WWHE.js} +4 -4
  6. package/dist/chunks/{chunk-OY4HIPQO.js → chunk-4I5SPKXV.js} +99 -41
  7. package/dist/chunks/{chunk-E4OPPX7M.js → chunk-4UJDQ2WM.js} +2 -2
  8. package/dist/chunks/{chunk-HFCK3QBJ.js → chunk-4WPY4WO3.js} +6 -6
  9. package/dist/chunks/{chunk-EBEBY45K.js → chunk-4XB5UFP4.js} +2 -2
  10. package/dist/chunks/{chunk-KSIISCB2.js → chunk-5GZAC4CI.js} +1 -1
  11. package/dist/chunks/{chunk-K5WXYAUP.js → chunk-AH6RCY4L.js} +1 -1
  12. package/dist/chunks/{chunk-LQOXSEJW.js → chunk-DIOSHJ4H.js} +5 -5
  13. package/dist/chunks/{chunk-NF7HK5MP.js → chunk-DVV42VA6.js} +2 -2
  14. package/dist/chunks/{chunk-E6EUZBB3.js → chunk-DXZ5RVOC.js} +6 -6
  15. package/dist/chunks/{chunk-X32G5X53.js → chunk-F6MUOB5B.js} +1 -1
  16. package/dist/chunks/{chunk-QGLS47RE.js → chunk-GRPLZLEB.js} +1 -1
  17. package/dist/chunks/{chunk-3JREBTWA.js → chunk-GWM32SE3.js} +16 -3
  18. package/dist/chunks/{chunk-U7NBRDCA.js → chunk-JWN6JMVY.js} +2 -2
  19. package/dist/chunks/{chunk-Z2O2S6ZA.js → chunk-KAC4IO5S.js} +483 -62
  20. package/dist/chunks/{chunk-ADLCFLGH.js → chunk-LANWQ2NA.js} +9 -9
  21. package/dist/chunks/{chunk-5V2IIK5P.js → chunk-MEAUBEGT.js} +3 -3
  22. package/dist/chunks/{chunk-3NSIZGHP.js → chunk-MWQHQ7FW.js} +3 -3
  23. package/dist/chunks/{chunk-H2IRGYM2.js → chunk-MXSNLYVL.js} +6 -6
  24. package/dist/chunks/{chunk-HAJ2XRTQ.js → chunk-NQQWZYTY.js} +2 -2
  25. package/dist/chunks/{chunk-JZLADLMF.js → chunk-NVV6BWQP.js} +2 -2
  26. package/dist/chunks/{chunk-P6Z4AGTA.js → chunk-OGWD7VBC.js} +2 -2
  27. package/dist/chunks/{chunk-6ESUYMQ6.js → chunk-OLJ6HISC.js} +3 -3
  28. package/dist/chunks/{chunk-GQLARSTH.js → chunk-P5NASM3L.js} +1 -1
  29. package/dist/chunks/{chunk-GCKUEAUE.js → chunk-Q5MHVELE.js} +2 -2
  30. package/dist/chunks/{chunk-IS56OO2J.js → chunk-S62XC5XL.js} +2 -2
  31. package/dist/chunks/{chunk-ONYQGA2O.js → chunk-S6EMI466.js} +2 -2
  32. package/dist/chunks/{chunk-SIRIGCP6.js → chunk-TEDMSWBX.js} +2 -2
  33. package/dist/chunks/{chunk-435PAKFA.js → chunk-TTEDSKHO.js} +4 -4
  34. package/dist/chunks/{chunk-4LDQIDKG.js → chunk-U5GMPX5T.js} +2 -2
  35. package/dist/chunks/{chunk-AXQNAI65.js → chunk-V6BFG564.js} +1 -1
  36. package/dist/chunks/{chunk-HENJXUSM.js → chunk-VOXVKDJQ.js} +4 -4
  37. package/dist/chunks/{chunk-KSF2MOCF.js → chunk-Y6X3VMO3.js} +1 -1
  38. package/dist/chunks/{compile-vercel-config-LDMZFRM6.js → compile-vercel-config-SGZPQDRN.js} +4 -4
  39. package/dist/chunks/{delete-Y2K2SKOJ.js → delete-WMHTTHG3.js} +6 -6
  40. package/dist/chunks/{disable-P72GFXPO.js → disable-QBDO6UIV.js} +6 -6
  41. package/dist/chunks/{discard-PJICIKZS.js → discard-GZZ553AR.js} +6 -6
  42. package/dist/chunks/{edit-UBF4GZ74.js → edit-H2BF2MZY.js} +7 -7
  43. package/dist/chunks/{enable-WKNZCBBP.js → enable-YYWIMKHP.js} +6 -6
  44. package/dist/chunks/{export-47S3H44M.js → export-D3XBBQZD.js} +6 -6
  45. package/dist/chunks/{inspect-VN5RPWZ4.js → inspect-LUCGK7HU.js} +8 -8
  46. package/dist/chunks/{list-2MOCSIVK.js → list-EGJ7X43H.js} +6 -6
  47. package/dist/chunks/{list-E2776667.js → list-WV3JSWCB.js} +9 -9
  48. package/dist/chunks/{ls-K6VVPESL.js → ls-DXRXKG6Q.js} +8 -8
  49. package/dist/chunks/{publish-YTJF333F.js → publish-LW57QZ56.js} +6 -6
  50. package/dist/chunks/{query-573BCOCL.js → query-AQSXA32P.js} +11 -11
  51. package/dist/chunks/{reorder-WGMITOMK.js → reorder-YJGPY7SA.js} +6 -6
  52. package/dist/chunks/{restore-R5SP6QDT.js → restore-VANQDIFO.js} +6 -6
  53. package/dist/chunks/{rm-3CARKENK.js → rm-GNY6PA2Z.js} +8 -8
  54. package/dist/chunks/{rule-inspect-N6HDKT6I.js → rule-inspect-EECXOMPN.js} +8 -8
  55. package/dist/chunks/{rules-D32GEN6D.js → rules-G2VMMW7U.js} +8 -8
  56. package/dist/chunks/{schema-7I3UHM6W.js → schema-4TUQAXX6.js} +9 -9
  57. package/dist/chunks/{types-7VDI75PV.js → types-54VLSVRV.js} +4 -4
  58. package/dist/chunks/{update-RQ7YZS6M.js → update-GSE7WNBV.js} +8 -8
  59. package/dist/commands/build/index.js +86 -53
  60. package/dist/commands/deploy/index.js +24 -24
  61. package/dist/commands/dev/index.js +254 -52
  62. package/dist/commands/env/index.js +18 -18
  63. package/dist/commands/link/index.js +19 -19
  64. package/dist/commands/list/index.js +10 -10
  65. package/dist/commands-bulk.js +1845 -1356
  66. package/dist/index.js +22 -22
  67. package/dist/version.mjs +1 -1
  68. package/package.json +20 -20
@@ -14,7 +14,7 @@ import {
14
14
  getPreservedArgsForEnvPull,
15
15
  outputActionRequired,
16
16
  outputAgentError
17
- } from "./chunk-AXQNAI65.js";
17
+ } from "./chunk-V6BFG564.js";
18
18
  import {
19
19
  require_ms,
20
20
  stamp_default
@@ -28,7 +28,7 @@ import {
28
28
  require_string_width,
29
29
  require_strip_ansi,
30
30
  yesOption
31
- } from "./chunk-GQLARSTH.js";
31
+ } from "./chunk-P5NASM3L.js";
32
32
  import {
33
33
  APIError,
34
34
  CantParseJSONFile,
@@ -43,7 +43,7 @@ import {
43
43
  isAPIError,
44
44
  packageName,
45
45
  require_lib
46
- } from "./chunk-EBEBY45K.js";
46
+ } from "./chunk-4XB5UFP4.js";
47
47
  import {
48
48
  emoji,
49
49
  eraseLines,
@@ -15966,6 +15966,40 @@ var require_frameworks = __commonJS({
15966
15966
  }
15967
15967
  ]
15968
15968
  },
15969
+ {
15970
+ name: "Ash",
15971
+ slug: "ash",
15972
+ logo: "https://api-frameworks.vercel.sh/framework-logos/ash.svg",
15973
+ darkModeLogo: "https://api-frameworks.vercel.sh/framework-logos/ash-dark.svg",
15974
+ tagline: "A filesystem-first framework for durable backend agents on Vercel.",
15975
+ description: "An Ash app: agents authored as a directory of files, compiled and served on Vercel.",
15976
+ detectors: {
15977
+ every: [
15978
+ {
15979
+ path: "package.json",
15980
+ matchContent: '"(dev)?(d|D)ependencies":\\s*{[^}]*"experimental-ash":\\s*".+?"[^}]*}'
15981
+ }
15982
+ ]
15983
+ },
15984
+ settings: {
15985
+ installCommand: {
15986
+ placeholder: "`pnpm install`, `yarn install`, or `npm install`"
15987
+ },
15988
+ buildCommand: {
15989
+ value: "ash build",
15990
+ placeholder: "`npm run build` or `ash build`"
15991
+ },
15992
+ devCommand: {
15993
+ value: "ash dev",
15994
+ placeholder: "ash dev"
15995
+ },
15996
+ outputDirectory: {
15997
+ value: ".output"
15998
+ }
15999
+ },
16000
+ getOutputDirName: async () => ".output",
16001
+ experimental: true
16002
+ },
15969
16003
  {
15970
16004
  name: "Sanity (v3)",
15971
16005
  slug: "sanity-v3",
@@ -22640,9 +22674,11 @@ var require_utils3 = __commonJS({
22640
22674
  inferRuntimeFromFramework: () => inferRuntimeFromFramework,
22641
22675
  inferServiceRuntime: () => inferServiceRuntime,
22642
22676
  isFrontendFramework: () => isFrontendFramework,
22677
+ isPublicServicesEnabled: () => isPublicServicesEnabled2,
22643
22678
  isRouteOwningBuilder: () => isRouteOwningBuilder2,
22644
22679
  isStaticBuild: () => isStaticBuild2,
22645
- readVercelConfig: () => readVercelConfig
22680
+ readVercelConfig: () => readVercelConfig,
22681
+ validateServicesConfigGate: () => validateServicesConfigGate
22646
22682
  });
22647
22683
  module.exports = __toCommonJS2(utils_exports);
22648
22684
  var import_framework_helpers = __require("@vercel/build-utils/dist/framework-helpers");
@@ -22655,6 +22691,18 @@ var require_utils3 = __commonJS({
22655
22691
  return false;
22656
22692
  }
22657
22693
  }
22694
+ function isPublicServicesEnabled2() {
22695
+ return process.env.VERCEL_USE_SERVICES === "1" || process.env.VERCEL_USE_SERVICES?.toLowerCase() === "true";
22696
+ }
22697
+ function validateServicesConfigGate(config) {
22698
+ if (config?.services !== void 0 && !isPublicServicesEnabled2()) {
22699
+ return {
22700
+ code: "INVALID_VERCEL_CONFIG",
22701
+ message: "Invalid vercel.json - should NOT have additional property `services`. Please remove it."
22702
+ };
22703
+ }
22704
+ return null;
22705
+ }
22658
22706
  var INTERNAL_QUEUES_PREFIX = "/_svc/_queues";
22659
22707
  function normalizeInternalServiceEntrypoint(entrypoint) {
22660
22708
  const normalized = entrypoint.replace(/\\/g, "/").replace(/^\/+/, "").replace(/\.[^/.]+$/, "");
@@ -22739,6 +22787,10 @@ var require_utils3 = __commonJS({
22739
22787
  try {
22740
22788
  const content = await fs5.readFile("vercel.json");
22741
22789
  const config = JSON.parse(content.toString());
22790
+ const gateError = validateServicesConfigGate(config);
22791
+ if (gateError) {
22792
+ return { config: null, error: gateError };
22793
+ }
22742
22794
  return { config, error: null };
22743
22795
  } catch {
22744
22796
  return {
@@ -22756,6 +22808,10 @@ var require_utils3 = __commonJS({
22756
22808
  const { parse: tomlParse3 } = await import("smol-toml");
22757
22809
  const content = await fs5.readFile("vercel.toml");
22758
22810
  const config = tomlParse3(content.toString());
22811
+ const gateError = validateServicesConfigGate(config);
22812
+ if (gateError) {
22813
+ return { config: null, error: gateError };
22814
+ }
22759
22815
  return { config, error: null };
22760
22816
  } catch {
22761
22817
  return {
@@ -23074,7 +23130,12 @@ var require_resolve2 = __commonJS({
23074
23130
  }
23075
23131
  var SERVICE_NAME_REGEX = /^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$/;
23076
23132
  var DNS_LABEL_RE = /^(?!-)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i;
23077
- var ENV_PREFIX_RE = /^[A-Z][A-Z0-9_]*_$/;
23133
+ var ENV_VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
23134
+ var ENTRYPOINT_REQUIRED_RUNTIMES = /* @__PURE__ */ new Set([
23135
+ "node",
23136
+ "python",
23137
+ "go"
23138
+ ]);
23078
23139
  async function getServiceFs(fs5, serviceName, root) {
23079
23140
  if (!root) {
23080
23141
  return { fs: fs5 };
@@ -23106,6 +23167,38 @@ var require_resolve2 = __commonJS({
23106
23167
  const normalized = import_path11.posix.normalize(entrypoint);
23107
23168
  return normalized === "" ? "." : normalized;
23108
23169
  }
23170
+ function getEffectiveServiceTrigger(config) {
23171
+ if (config.type === "cron") {
23172
+ return "schedule";
23173
+ }
23174
+ if (config.type === "worker") {
23175
+ return "queue";
23176
+ }
23177
+ if (config.type !== "job") {
23178
+ return void 0;
23179
+ }
23180
+ return config.trigger;
23181
+ }
23182
+ function getEntrypointRequiredRuntime(config) {
23183
+ if (config.runtime && config.runtime in import_types.RUNTIME_BUILDERS) {
23184
+ return config.runtime;
23185
+ }
23186
+ return (0, import_utils4.inferRuntimeFromFramework)(config.framework);
23187
+ }
23188
+ function validateBackendFileEntrypoint(name, config, resolvedEntrypoint, options) {
23189
+ if (!options.requireFileEntrypointForBackendRuntimes || !resolvedEntrypoint?.isDirectory) {
23190
+ return null;
23191
+ }
23192
+ const runtime = getEntrypointRequiredRuntime(config);
23193
+ if (!runtime || !ENTRYPOINT_REQUIRED_RUNTIMES.has(runtime)) {
23194
+ return null;
23195
+ }
23196
+ return {
23197
+ code: "INVALID_ENTRYPOINT",
23198
+ message: `Service "${name}" must specify a file "entrypoint" when using "${config.runtime ? "runtime" : "framework"}" "${config.runtime || config.framework}".`,
23199
+ serviceName: name
23200
+ };
23201
+ }
23109
23202
  async function resolveEntrypointPath({
23110
23203
  fs: fs5,
23111
23204
  serviceName,
@@ -23200,7 +23293,7 @@ var require_resolve2 = __commonJS({
23200
23293
  return {
23201
23294
  error: {
23202
23295
  code: "MULTIPLE_FRAMEWORKS_SERVICE",
23203
- message: `Multiple frameworks detected in ${workspace === "." ? "project root" : `${workspace}/`}: ${frameworkNames}. Specify "framework" explicitly in experimentalServices.`,
23296
+ message: `Multiple frameworks detected in ${workspace === "." ? "project root" : `${workspace}/`}: ${frameworkNames}. Specify "framework" explicitly in services.`,
23204
23297
  serviceName
23205
23298
  }
23206
23299
  };
@@ -23294,7 +23387,7 @@ var require_resolve2 = __commonJS({
23294
23387
  }
23295
23388
  };
23296
23389
  }
23297
- function validateServiceConfig(name, config) {
23390
+ function validateServiceConfig(name, config, options = {}) {
23298
23391
  if (!SERVICE_NAME_REGEX.test(name)) {
23299
23392
  return {
23300
23393
  code: "INVALID_SERVICE_NAME",
@@ -23310,13 +23403,15 @@ var require_resolve2 = __commonJS({
23310
23403
  };
23311
23404
  }
23312
23405
  const serviceType = config.type || "web";
23313
- const isJobService = serviceType === "job" || serviceType === "cron";
23314
- const isScheduleJobService = (0, import_build_utils5.isScheduleTriggeredService)({
23406
+ const effectiveTrigger = getEffectiveServiceTrigger(config);
23407
+ const effectiveService = {
23315
23408
  type: serviceType,
23316
- trigger: config.trigger
23317
- });
23318
- const isQueueJobService = serviceType === "job" && config.trigger === "queue";
23319
- const isWorkflowService = serviceType === "job" && config.trigger === "workflow";
23409
+ trigger: effectiveTrigger
23410
+ };
23411
+ const isJobService = serviceType === "job" || serviceType === "cron";
23412
+ const isScheduleJobService = (0, import_build_utils5.isScheduleTriggeredService)(effectiveService);
23413
+ const isQueueJobService = serviceType === "job" && (0, import_build_utils5.isQueueTriggeredService)(effectiveService);
23414
+ const isWorkflowService = serviceType === "job" && effectiveTrigger === "workflow";
23320
23415
  const isNonWebService = serviceType === "worker" || isJobService;
23321
23416
  const serviceTypeLabel = isJobService ? "Job" : serviceType === "worker" ? "Worker" : "Web";
23322
23417
  const routingResult = resolveServiceRoutingConfig(name, config);
@@ -23362,17 +23457,17 @@ var require_resolve2 = __commonJS({
23362
23457
  serviceName: name
23363
23458
  };
23364
23459
  }
23365
- if (serviceType === "job" && config.trigger === void 0) {
23460
+ if (serviceType === "job" && effectiveTrigger === void 0) {
23366
23461
  return {
23367
23462
  code: "MISSING_JOB_TRIGGER",
23368
23463
  message: `Job service "${name}" is missing required "trigger" field.`,
23369
23464
  serviceName: name
23370
23465
  };
23371
23466
  }
23372
- if (serviceType === "job" && config.trigger && !import_build_utils5.JOB_TRIGGERS.includes(config.trigger)) {
23467
+ if (serviceType === "job" && effectiveTrigger && !import_build_utils5.JOB_TRIGGERS.includes(effectiveTrigger)) {
23373
23468
  return {
23374
23469
  code: "INVALID_JOB_TRIGGER",
23375
- message: `Job service "${name}" has invalid trigger "${config.trigger}". Expected ${import_build_utils5.JOB_TRIGGERS.map((t) => `"${t}"`).join(", ")}.`,
23470
+ message: `Job service "${name}" has invalid trigger "${effectiveTrigger}". Expected ${import_build_utils5.JOB_TRIGGERS.map((t) => `"${t}"`).join(", ")}.`,
23376
23471
  serviceName: name
23377
23472
  };
23378
23473
  }
@@ -23414,14 +23509,46 @@ var require_resolve2 = __commonJS({
23414
23509
  };
23415
23510
  }
23416
23511
  }
23417
- if (config.envPrefix !== void 0) {
23418
- if (!ENV_PREFIX_RE.test(config.envPrefix)) {
23512
+ if (config.env !== void 0) {
23513
+ if (typeof config.env !== "object" || Array.isArray(config.env)) {
23419
23514
  return {
23420
- code: "INVALID_ENV_PREFIX",
23421
- message: `Service "${name}" has invalid envPrefix "${config.envPrefix}". Must start with an uppercase letter, contain only uppercase letters, digits, and underscores, and end with "_" (e.g., "MY_SERVICE_").`,
23515
+ code: "INVALID_ENV_VARS",
23516
+ message: `Service "${name}" has invalid "env". Must be an object keyed by environment variable name.`,
23422
23517
  serviceName: name
23423
23518
  };
23424
23519
  }
23520
+ for (const [envVarName, envVar] of Object.entries(config.env)) {
23521
+ if (!ENV_VAR_NAME_RE.test(envVarName)) {
23522
+ return {
23523
+ code: "INVALID_ENV_VAR_NAME",
23524
+ message: `Service "${name}" has invalid env key "${envVarName}". Must match /^[A-Za-z_][A-Za-z0-9_]*$/.`,
23525
+ serviceName: name
23526
+ };
23527
+ }
23528
+ if (!envVar || typeof envVar !== "object" || Array.isArray(envVar)) {
23529
+ return {
23530
+ code: "INVALID_ENV_VAR",
23531
+ message: `Service "${name}" has invalid env["${envVarName}"]. Must be an object with a "type" discriminator.`,
23532
+ serviceName: name
23533
+ };
23534
+ }
23535
+ const envVarType = envVar.type;
23536
+ if (envVarType !== "service-ref") {
23537
+ return {
23538
+ code: "INVALID_ENV_VAR_TYPE",
23539
+ message: `Service "${name}" env["${envVarName}"] has unknown type "${envVarType}".`,
23540
+ serviceName: name
23541
+ };
23542
+ }
23543
+ const refService = envVar.service;
23544
+ if (typeof refService !== "string" || refService.length === 0) {
23545
+ return {
23546
+ code: "INVALID_ENV_VAR_REF",
23547
+ message: `Service "${name}" env["${envVarName}"] must specify "service" as a non-empty string.`,
23548
+ serviceName: name
23549
+ };
23550
+ }
23551
+ }
23425
23552
  }
23426
23553
  if (config.runtime && !(config.runtime in import_types.RUNTIME_BUILDERS)) {
23427
23554
  return {
@@ -23450,6 +23577,7 @@ var require_resolve2 = __commonJS({
23450
23577
  const hasFramework = Boolean(config.framework);
23451
23578
  const hasBuilderOrRuntime = Boolean(config.builder || config.runtime);
23452
23579
  const hasEntrypoint = Boolean(config.entrypoint);
23580
+ const entrypointRequiredRuntime = getEntrypointRequiredRuntime(config);
23453
23581
  if (!hasFramework && !hasBuilderOrRuntime && !hasEntrypoint) {
23454
23582
  return {
23455
23583
  code: "MISSING_SERVICE_CONFIG",
@@ -23457,6 +23585,13 @@ var require_resolve2 = __commonJS({
23457
23585
  serviceName: name
23458
23586
  };
23459
23587
  }
23588
+ if (options.requireFileEntrypointForBackendRuntimes && !hasEntrypoint && entrypointRequiredRuntime && ENTRYPOINT_REQUIRED_RUNTIMES.has(entrypointRequiredRuntime)) {
23589
+ return {
23590
+ code: "MISSING_ENTRYPOINT",
23591
+ message: `Service "${name}" must specify "entrypoint" when using "${config.runtime ? "runtime" : "framework"}" "${config.runtime || config.framework}".`,
23592
+ serviceName: name
23593
+ };
23594
+ }
23460
23595
  if (hasBuilderOrRuntime && !hasFramework && !hasEntrypoint) {
23461
23596
  return {
23462
23597
  code: "MISSING_ENTRYPOINT",
@@ -23494,7 +23629,7 @@ var require_resolve2 = __commonJS({
23494
23629
  routePrefixSource = "configured"
23495
23630
  } = options;
23496
23631
  const type = config.type || "web";
23497
- const trigger = type === "cron" ? "schedule" : type === "job" ? config.trigger : void 0;
23632
+ const trigger = getEffectiveServiceTrigger(config);
23498
23633
  const rawEntrypoint = config.entrypoint;
23499
23634
  const moduleAttrParsed = typeof rawEntrypoint === "string" ? parsePyModuleAttrEntrypoint(rawEntrypoint) : null;
23500
23635
  const routingResult = resolveServiceRoutingConfig(name, config);
@@ -23637,16 +23772,16 @@ var require_resolve2 = __commonJS({
23637
23772
  schedule: config.schedule,
23638
23773
  handlerFunction: moduleAttrParsed?.attrName,
23639
23774
  topics,
23640
- envPrefix: config.envPrefix
23775
+ env: config.env
23641
23776
  };
23642
23777
  }
23643
- async function resolveAllConfiguredServices(services, fs5, routePrefixSource = "configured") {
23778
+ async function resolveAllConfiguredServices(services, fs5, routePrefixSource = "configured", options = {}) {
23644
23779
  const resolved = [];
23645
23780
  const errors = [];
23646
23781
  const webServicesByRoutePrefix = /* @__PURE__ */ new Map();
23647
23782
  for (const name of Object.keys(services)) {
23648
23783
  const serviceConfig = services[name];
23649
- const validationError = validateServiceConfig(name, serviceConfig);
23784
+ const validationError = validateServiceConfig(name, serviceConfig, options);
23650
23785
  if (validationError) {
23651
23786
  errors.push(validationError);
23652
23787
  continue;
@@ -23684,6 +23819,16 @@ var require_resolve2 = __commonJS({
23684
23819
  continue;
23685
23820
  }
23686
23821
  }
23822
+ const explicitBackendEntrypointError = validateBackendFileEntrypoint(
23823
+ name,
23824
+ serviceConfig,
23825
+ resolvedEntrypoint,
23826
+ options
23827
+ );
23828
+ if (explicitBackendEntrypointError) {
23829
+ errors.push(explicitBackendEntrypointError);
23830
+ continue;
23831
+ }
23687
23832
  let resolvedConfig = serviceConfig;
23688
23833
  if (!serviceConfig.framework && resolvedEntrypoint) {
23689
23834
  if (resolvedEntrypoint.isDirectory) {
@@ -23740,6 +23885,16 @@ var require_resolve2 = __commonJS({
23740
23885
  }
23741
23886
  }
23742
23887
  }
23888
+ const backendEntrypointError = validateBackendFileEntrypoint(
23889
+ name,
23890
+ resolvedConfig,
23891
+ resolvedEntrypoint,
23892
+ options
23893
+ );
23894
+ if (backendEntrypointError) {
23895
+ errors.push(backendEntrypointError);
23896
+ continue;
23897
+ }
23743
23898
  const service = await resolveConfiguredService({
23744
23899
  name,
23745
23900
  config: resolvedConfig,
@@ -23765,8 +23920,49 @@ var require_resolve2 = __commonJS({
23765
23920
  }
23766
23921
  resolved.push(service);
23767
23922
  }
23923
+ const servicesByName = new Map(resolved.map((s) => [s.name, s]));
23924
+ for (const service of resolved) {
23925
+ if (!service.env)
23926
+ continue;
23927
+ validateEnvRefs(
23928
+ service.env,
23929
+ `Service "${service.name}" env`,
23930
+ servicesByName,
23931
+ errors,
23932
+ service.name
23933
+ );
23934
+ }
23935
+ if (options.rootEnv) {
23936
+ validateEnvRefs(options.rootEnv, "env", servicesByName, errors);
23937
+ for (const service of resolved) {
23938
+ service.env = { ...options.rootEnv, ...service.env ?? {} };
23939
+ }
23940
+ }
23768
23941
  return { services: resolved, errors };
23769
23942
  }
23943
+ function validateEnvRefs(env, pathPrefix, servicesByName, errors, serviceName) {
23944
+ for (const [envVarName, envVar] of Object.entries(env)) {
23945
+ if (envVar.type !== "service-ref")
23946
+ continue;
23947
+ const refName = envVar.service;
23948
+ const target = servicesByName.get(refName);
23949
+ if (!target) {
23950
+ errors.push({
23951
+ code: "UNKNOWN_SERVICE_REF",
23952
+ message: `${pathPrefix}["${envVarName}"] references unknown service "${refName}".`,
23953
+ ...serviceName ? { serviceName } : {}
23954
+ });
23955
+ continue;
23956
+ }
23957
+ if (target.type !== "web") {
23958
+ errors.push({
23959
+ code: "INVALID_SERVICE_REF_TYPE",
23960
+ message: `${pathPrefix}["${envVarName}"] references service "${refName}" which is a ${target.type} service and has no URL. Only web services can be referenced.`,
23961
+ ...serviceName ? { serviceName } : {}
23962
+ });
23963
+ }
23964
+ }
23965
+ }
23770
23966
  }
23771
23967
  });
23772
23968
 
@@ -23819,7 +24015,7 @@ var require_auto_detect = __commonJS({
23819
24015
  errors: [
23820
24016
  {
23821
24017
  code: "MULTIPLE_FRAMEWORKS_ROOT",
23822
- message: `Multiple frameworks detected at root: ${frameworkNames}. Use explicit experimentalServices config.`
24018
+ message: `Multiple frameworks detected at root: ${frameworkNames}. Use explicit services config.`
23823
24019
  }
23824
24020
  ]
23825
24021
  };
@@ -23844,7 +24040,7 @@ var require_auto_detect = __commonJS({
23844
24040
  errors: [
23845
24041
  {
23846
24042
  code: "MULTIPLE_FRAMEWORKS_SERVICE",
23847
- message: `Multiple frameworks detected in ${frontendLocation}/: ${frameworkNames}. Use explicit experimentalServices config.`
24043
+ message: `Multiple frameworks detected in ${frontendLocation}/: ${frameworkNames}. Use explicit services config.`
23848
24044
  }
23849
24045
  ]
23850
24046
  };
@@ -23862,7 +24058,7 @@ var require_auto_detect = __commonJS({
23862
24058
  errors: [
23863
24059
  {
23864
24060
  code: "NO_SERVICES_CONFIGURED",
23865
- message: "No services detected. Configure experimentalServices in vercel.json or ensure a framework exists at project root, frontend/, or apps/web/."
24061
+ message: "No services detected. Configure services in vercel.json or ensure a framework exists at project root, frontend/, or apps/web/."
23866
24062
  }
23867
24063
  ]
23868
24064
  };
@@ -23943,7 +24139,7 @@ var require_auto_detect = __commonJS({
23943
24139
  services: {},
23944
24140
  error: {
23945
24141
  code: "SERVICE_NAME_CONFLICT",
23946
- message: `Service name conflict: "${serviceName}" exists in both ${BACKEND_DIR}/ and ${SERVICES_DIR}/${serviceName}/. Rename one of the directories or use explicit experimentalServices config.`,
24142
+ message: `Service name conflict: "${serviceName}" exists in both ${BACKEND_DIR}/ and ${SERVICES_DIR}/${serviceName}/. Rename one of the directories or use explicit services config.`,
23947
24143
  serviceName
23948
24144
  }
23949
24145
  };
@@ -23992,7 +24188,7 @@ var require_auto_detect = __commonJS({
23992
24188
  return {
23993
24189
  error: {
23994
24190
  code: "MULTIPLE_FRAMEWORKS_SERVICE",
23995
- message: `Multiple frameworks detected in ${dirPath}/: ${frameworkNames}. Use explicit experimentalServices config.`,
24191
+ message: `Multiple frameworks detected in ${dirPath}/: ${frameworkNames}. Use explicit services config.`,
23996
24192
  serviceName
23997
24193
  }
23998
24194
  };
@@ -24126,7 +24322,7 @@ var require_detect_railway = __commonJS({
24126
24322
  if (frameworks.length === 0) {
24127
24323
  warnings.push({
24128
24324
  code: "SERVICE_SKIPPED",
24129
- message: `Skipped service in ${dirLabel}/: no framework detected. Configure it manually in experimentalServices.`
24325
+ message: `Skipped service in ${dirLabel}/: no framework detected. Configure it manually in services.`
24130
24326
  });
24131
24327
  continue;
24132
24328
  }
@@ -24134,7 +24330,7 @@ var require_detect_railway = __commonJS({
24134
24330
  const names = frameworks.map((f) => f.name).join(", ");
24135
24331
  errors.push({
24136
24332
  code: "MULTIPLE_FRAMEWORKS_SERVICE",
24137
- message: `Multiple frameworks detected in ${dirLabel}/: ${names}. Use explicit experimentalServices config.`,
24333
+ message: `Multiple frameworks detected in ${dirLabel}/: ${names}. Use explicit services config.`,
24138
24334
  serviceName
24139
24335
  });
24140
24336
  continue;
@@ -24332,10 +24528,17 @@ var require_detect_services = __commonJS({
24332
24528
  workers: []
24333
24529
  };
24334
24530
  }
24531
+ function isEnvVars(env) {
24532
+ if (!env)
24533
+ return false;
24534
+ const first = Object.values(env)[0];
24535
+ return typeof first === "object" && first !== null;
24536
+ }
24335
24537
  function withResolvedResult(resolved, inferred = null) {
24336
24538
  return {
24337
24539
  services: resolved.services,
24338
24540
  source: resolved.source,
24541
+ useImplicitEnvInjection: resolved.useImplicitEnvInjection,
24339
24542
  routes: resolved.routes,
24340
24543
  errors: resolved.errors,
24341
24544
  warnings: resolved.warnings,
@@ -24371,12 +24574,14 @@ var require_detect_services = __commonJS({
24371
24574
  return withResolvedResult({
24372
24575
  services: [],
24373
24576
  source: "configured",
24577
+ useImplicitEnvInjection: true,
24374
24578
  routes: emptyRoutes(),
24375
24579
  errors: [configError],
24376
24580
  warnings: []
24377
24581
  });
24378
24582
  }
24379
- const configuredServices = vercelConfig?.experimentalServices;
24583
+ const hasNonEmptyPublicServicesConfig = vercelConfig?.services && Object.keys(vercelConfig.services).length > 0;
24584
+ const configuredServices = hasNonEmptyPublicServicesConfig ? vercelConfig.services : vercelConfig?.experimentalServices;
24380
24585
  const hasConfiguredServices = configuredServices && Object.keys(configuredServices).length > 0;
24381
24586
  if (!hasConfiguredServices) {
24382
24587
  const railwayResult = await (0, import_detect_railway.detectRailwayServices)({ fs: scopedFs });
@@ -24384,6 +24589,7 @@ var require_detect_services = __commonJS({
24384
24589
  return withResolvedResult({
24385
24590
  services: [],
24386
24591
  source: "auto-detected",
24592
+ useImplicitEnvInjection: true,
24387
24593
  routes: emptyRoutes(),
24388
24594
  errors: railwayResult.errors,
24389
24595
  warnings: railwayResult.warnings
@@ -24405,6 +24611,7 @@ var require_detect_services = __commonJS({
24405
24611
  {
24406
24612
  services: [],
24407
24613
  source: "auto-detected",
24614
+ useImplicitEnvInjection: true,
24408
24615
  routes: emptyRoutes(),
24409
24616
  errors: result2.errors,
24410
24617
  warnings: railwayResult.warnings
@@ -24423,6 +24630,7 @@ var require_detect_services = __commonJS({
24423
24630
  const resolved = {
24424
24631
  services: result2.services,
24425
24632
  source: "auto-detected",
24633
+ useImplicitEnvInjection: true,
24426
24634
  routes: routes2,
24427
24635
  errors: result2.errors,
24428
24636
  warnings: []
@@ -24441,6 +24649,7 @@ var require_detect_services = __commonJS({
24441
24649
  return withResolvedResult({
24442
24650
  services: [],
24443
24651
  source: "auto-detected",
24652
+ useImplicitEnvInjection: true,
24444
24653
  routes: emptyRoutes(),
24445
24654
  errors: autoResult.errors,
24446
24655
  warnings: []
@@ -24449,11 +24658,12 @@ var require_detect_services = __commonJS({
24449
24658
  return withResolvedResult({
24450
24659
  services: [],
24451
24660
  source: "auto-detected",
24661
+ useImplicitEnvInjection: true,
24452
24662
  routes: emptyRoutes(),
24453
24663
  errors: [
24454
24664
  {
24455
24665
  code: "NO_SERVICES_CONFIGURED",
24456
- message: "No services configured. Add `experimentalServices` to vercel.json."
24666
+ message: "No services configured. Add `services` to vercel.json."
24457
24667
  }
24458
24668
  ],
24459
24669
  warnings: []
@@ -24462,12 +24672,21 @@ var require_detect_services = __commonJS({
24462
24672
  const result = await (0, import_resolve.resolveAllConfiguredServices)(
24463
24673
  configuredServices,
24464
24674
  scopedFs,
24465
- "configured"
24675
+ "configured",
24676
+ {
24677
+ requireFileEntrypointForBackendRuntimes: Boolean(
24678
+ hasNonEmptyPublicServicesConfig
24679
+ ),
24680
+ rootEnv: isEnvVars(vercelConfig?.env) ? vercelConfig?.env : void 0
24681
+ }
24466
24682
  );
24467
24683
  const routes = generateServicesRoutes2(result.services);
24468
24684
  return withResolvedResult({
24469
24685
  services: result.services,
24470
24686
  source: "configured",
24687
+ // GA `services` opts into explicit `env`; experimentalServices keeps
24688
+ // the legacy `{NAME}_URL` injection.
24689
+ useImplicitEnvInjection: !hasNonEmptyPublicServicesConfig,
24471
24690
  routes,
24472
24691
  errors: result.errors,
24473
24692
  warnings: []
@@ -24890,7 +25109,7 @@ var require_get_services_builders = __commonJS({
24890
25109
  errors: [
24891
25110
  {
24892
25111
  code: "NO_SERVICES_CONFIGURED",
24893
- message: "No services configured. Add `experimentalServices` to vercel.json."
25112
+ message: "No services configured. Add `services` to vercel.json."
24894
25113
  }
24895
25114
  ],
24896
25115
  warnings: warningResponses,
@@ -24917,7 +25136,8 @@ var require_get_services_builders = __commonJS({
24917
25136
  ...result.routes.crons
24918
25137
  ] : null,
24919
25138
  errorRoutes: [],
24920
- services: result.services
25139
+ services: result.services,
25140
+ useImplicitEnvInjection: result.useImplicitEnvInjection
24921
25141
  };
24922
25142
  }
24923
25143
  }
@@ -25020,13 +25240,14 @@ var require_detect_builders = __commonJS({
25020
25240
  return publicBuilder ? publicBuilder.src.replace("/**/*", "") : null;
25021
25241
  }
25022
25242
  async function detectBuilders2(files, pkg, options = {}) {
25023
- const { experimentalServices: services, projectSettings = {} } = options;
25243
+ const { services, experimentalServices, projectSettings = {} } = options;
25024
25244
  const { framework } = projectSettings;
25025
- const hasServicesConfig = services != null && typeof services === "object";
25245
+ const configuredServices = services ?? experimentalServices;
25246
+ const hasServicesConfig = configuredServices != null && typeof configuredServices === "object";
25026
25247
  if (hasServicesConfig || framework === "services") {
25027
25248
  return (0, import_get_services_builders.getServicesBuilders)({
25028
25249
  workPath: options.workPath,
25029
- configuredServices: services,
25250
+ configuredServices,
25030
25251
  projectFramework: framework
25031
25252
  });
25032
25253
  }
@@ -38908,7 +39129,7 @@ var require_package = __commonJS({
38908
39129
  "../client/package.json"(exports, module) {
38909
39130
  module.exports = {
38910
39131
  name: "@vercel/client",
38911
- version: "17.4.2",
39132
+ version: "17.5.0",
38912
39133
  main: "dist/index.js",
38913
39134
  typings: "dist/index.d.ts",
38914
39135
  homepage: "https://vercel.com",
@@ -55073,7 +55294,13 @@ var parseEnv = (env) => {
55073
55294
  return o;
55074
55295
  }, startingDict);
55075
55296
  }
55076
- return env;
55297
+ const result = {};
55298
+ for (const [key, value] of Object.entries(env)) {
55299
+ if (typeof value === "string") {
55300
+ result[key] = value;
55301
+ }
55302
+ }
55303
+ return result;
55077
55304
  };
55078
55305
 
55079
55306
  // src/util/env/diff-env-files.ts
@@ -55193,6 +55420,9 @@ var envTargetChoices = import_constants.PROJECT_ENV_TARGET.map((t) => ({
55193
55420
  name: (0, import_title.default)(t),
55194
55421
  value: t
55195
55422
  }));
55423
+ function isValidEnvTarget(target) {
55424
+ return typeof target === "undefined" || envTargetChoices.map((c) => c.value).includes(target);
55425
+ }
55196
55426
  function getEnvTargetPlaceholder() {
55197
55427
  return `<${envTargetChoices.map((c) => c.value).join(" | ")}>`;
55198
55428
  }
@@ -55965,7 +56195,7 @@ var cronsSchema = {
55965
56195
  }
55966
56196
  }
55967
56197
  };
55968
- var serviceMountSchema = {
56198
+ var experimentalServicesMountSchema = {
55969
56199
  oneOf: [
55970
56200
  {
55971
56201
  type: "string",
@@ -55991,10 +56221,46 @@ var serviceMountSchema = {
55991
56221
  }
55992
56222
  ]
55993
56223
  };
55994
- var serviceScheduleSchema = {
56224
+ var servicesMountSchema = {
56225
+ oneOf: [
56226
+ {
56227
+ type: "string",
56228
+ minLength: 1,
56229
+ maxLength: 512
56230
+ },
56231
+ {
56232
+ type: "object",
56233
+ additionalProperties: false,
56234
+ required: ["path"],
56235
+ properties: {
56236
+ path: {
56237
+ type: "string",
56238
+ minLength: 1,
56239
+ maxLength: 512
56240
+ }
56241
+ }
56242
+ }
56243
+ ]
56244
+ };
56245
+ var staticServiceScheduleSchema = {
55995
56246
  type: "string",
55996
56247
  minLength: 9,
55997
- maxLength: 256
56248
+ maxLength: 256,
56249
+ not: { const: "<dynamic>" }
56250
+ };
56251
+ var serviceScheduleSchema = {
56252
+ oneOf: [
56253
+ {
56254
+ type: "string",
56255
+ minLength: 9,
56256
+ maxLength: 256
56257
+ },
56258
+ {
56259
+ type: "array",
56260
+ minItems: 1,
56261
+ items: staticServiceScheduleSchema
56262
+ }
56263
+ ]
55998
56264
  };
55999
56265
  var serviceQueueTopicSchema = {
56000
56266
  type: "object",
@@ -56036,13 +56302,55 @@ var serviceTopicsSchema = {
56036
56302
  }
56037
56303
  ]
56038
56304
  };
56039
- var serviceCommonProperties = {
56305
+ var envVarNamesSchema = {
56306
+ pattern: "^[A-Za-z_][A-Za-z0-9_]*$",
56307
+ maxLength: 256
56308
+ };
56309
+ var envVarSchema = {
56310
+ oneOf: [
56311
+ {
56312
+ type: "object",
56313
+ additionalProperties: false,
56314
+ required: ["type", "service"],
56315
+ properties: {
56316
+ type: { const: "service-ref" },
56317
+ service: {
56318
+ type: "string",
56319
+ minLength: 1,
56320
+ maxLength: 64,
56321
+ pattern: "^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$"
56322
+ }
56323
+ }
56324
+ }
56325
+ ]
56326
+ };
56327
+ var envVarRecordSchema = {
56328
+ type: "object",
56329
+ additionalProperties: envVarSchema,
56330
+ propertyNames: envVarNamesSchema
56331
+ };
56332
+ var topLevelEnvSchema = {
56333
+ oneOf: [
56334
+ {
56335
+ type: "object",
56336
+ additionalProperties: { type: "string" },
56337
+ propertyNames: envVarNamesSchema
56338
+ },
56339
+ envVarRecordSchema
56340
+ ]
56341
+ };
56342
+ var experimentalServicesCommonProperties = {
56343
+ entrypoint: {
56344
+ type: "string",
56345
+ minLength: 1,
56346
+ maxLength: 512
56347
+ },
56040
56348
  root: {
56041
56349
  type: "string",
56042
56350
  minLength: 1,
56043
56351
  maxLength: 512
56044
56352
  },
56045
- entrypoint: {
56353
+ workspace: {
56046
56354
  type: "string",
56047
56355
  minLength: 1,
56048
56356
  maxLength: 512
@@ -56072,6 +56380,11 @@ var serviceCommonProperties = {
56072
56380
  minLength: 1,
56073
56381
  maxLength: 2048
56074
56382
  },
56383
+ preDeployCommand: {
56384
+ type: "string",
56385
+ minLength: 1,
56386
+ maxLength: 2048
56387
+ },
56075
56388
  memory: {
56076
56389
  type: "integer",
56077
56390
  minimum: 128,
@@ -56102,8 +56415,8 @@ var serviceCommonProperties = {
56102
56415
  ]
56103
56416
  }
56104
56417
  };
56105
- var serviceRoutableProperties = {
56106
- mount: serviceMountSchema,
56418
+ var experimentalServicesRoutableProperties = {
56419
+ mount: experimentalServicesMountSchema,
56107
56420
  routePrefix: {
56108
56421
  type: "string",
56109
56422
  minLength: 1,
@@ -56115,14 +56428,31 @@ var serviceRoutableProperties = {
56115
56428
  maxLength: 63
56116
56429
  }
56117
56430
  };
56118
- var serviceConfigSchema = {
56431
+ var servicesCommonProperties = {
56432
+ entrypoint: experimentalServicesCommonProperties.entrypoint,
56433
+ root: experimentalServicesCommonProperties.root,
56434
+ framework: experimentalServicesCommonProperties.framework,
56435
+ runtime: experimentalServicesCommonProperties.runtime,
56436
+ buildCommand: experimentalServicesCommonProperties.buildCommand,
56437
+ preDeployCommand: experimentalServicesCommonProperties.preDeployCommand,
56438
+ memory: experimentalServicesCommonProperties.memory,
56439
+ maxDuration: experimentalServicesCommonProperties.maxDuration,
56440
+ includeFiles: experimentalServicesCommonProperties.includeFiles,
56441
+ excludeFiles: experimentalServicesCommonProperties.excludeFiles,
56442
+ env: envVarRecordSchema
56443
+ };
56444
+ var servicesRoutableProperties = {
56445
+ mount: servicesMountSchema
56446
+ };
56447
+ var servicesRequiredProperties = ["type", "root"];
56448
+ var experimentalServicesServiceConfigSchema = {
56119
56449
  oneOf: [
56120
56450
  {
56121
56451
  type: "object",
56122
56452
  additionalProperties: false,
56123
56453
  properties: {
56124
- ...serviceCommonProperties,
56125
- ...serviceRoutableProperties,
56454
+ ...experimentalServicesCommonProperties,
56455
+ ...experimentalServicesRoutableProperties,
56126
56456
  type: {
56127
56457
  enum: ["web"]
56128
56458
  }
@@ -56133,7 +56463,7 @@ var serviceConfigSchema = {
56133
56463
  additionalProperties: false,
56134
56464
  required: ["type", "trigger", "schedule"],
56135
56465
  properties: {
56136
- ...serviceCommonProperties,
56466
+ ...experimentalServicesCommonProperties,
56137
56467
  type: {
56138
56468
  const: "job"
56139
56469
  },
@@ -56148,7 +56478,7 @@ var serviceConfigSchema = {
56148
56478
  additionalProperties: false,
56149
56479
  required: ["type", "trigger", "topics"],
56150
56480
  properties: {
56151
- ...serviceCommonProperties,
56481
+ ...experimentalServicesCommonProperties,
56152
56482
  type: {
56153
56483
  const: "job"
56154
56484
  },
@@ -56168,7 +56498,7 @@ var serviceConfigSchema = {
56168
56498
  additionalProperties: false,
56169
56499
  required: ["type", "trigger", "entrypoint"],
56170
56500
  properties: {
56171
- ...serviceCommonProperties,
56501
+ ...experimentalServicesCommonProperties,
56172
56502
  type: {
56173
56503
  const: "job"
56174
56504
  },
@@ -56182,7 +56512,7 @@ var serviceConfigSchema = {
56182
56512
  additionalProperties: false,
56183
56513
  required: ["type"],
56184
56514
  properties: {
56185
- ...serviceCommonProperties,
56515
+ ...experimentalServicesCommonProperties,
56186
56516
  type: {
56187
56517
  const: "worker"
56188
56518
  },
@@ -56207,7 +56537,7 @@ var serviceConfigSchema = {
56207
56537
  additionalProperties: false,
56208
56538
  required: ["type", "schedule"],
56209
56539
  properties: {
56210
- ...serviceCommonProperties,
56540
+ ...experimentalServicesCommonProperties,
56211
56541
  type: {
56212
56542
  const: "cron"
56213
56543
  },
@@ -56216,13 +56546,81 @@ var serviceConfigSchema = {
56216
56546
  }
56217
56547
  ]
56218
56548
  };
56549
+ var servicesServiceConfigSchema = {
56550
+ oneOf: [
56551
+ {
56552
+ type: "object",
56553
+ additionalProperties: false,
56554
+ required: servicesRequiredProperties,
56555
+ properties: {
56556
+ ...servicesCommonProperties,
56557
+ ...servicesRoutableProperties,
56558
+ type: {
56559
+ enum: ["web"]
56560
+ }
56561
+ }
56562
+ },
56563
+ {
56564
+ type: "object",
56565
+ additionalProperties: false,
56566
+ required: [...servicesRequiredProperties, "trigger", "schedule"],
56567
+ properties: {
56568
+ ...servicesCommonProperties,
56569
+ type: {
56570
+ const: "job"
56571
+ },
56572
+ trigger: {
56573
+ const: "schedule"
56574
+ },
56575
+ schedule: serviceScheduleSchema
56576
+ }
56577
+ },
56578
+ {
56579
+ type: "object",
56580
+ additionalProperties: false,
56581
+ required: [...servicesRequiredProperties, "trigger", "topics"],
56582
+ properties: {
56583
+ ...servicesCommonProperties,
56584
+ type: {
56585
+ const: "job"
56586
+ },
56587
+ trigger: {
56588
+ const: "queue"
56589
+ },
56590
+ topics: serviceTopicsSchema
56591
+ }
56592
+ },
56593
+ {
56594
+ type: "object",
56595
+ additionalProperties: false,
56596
+ required: [...servicesRequiredProperties, "trigger", "entrypoint"],
56597
+ properties: {
56598
+ ...servicesCommonProperties,
56599
+ type: {
56600
+ const: "job"
56601
+ },
56602
+ trigger: {
56603
+ const: "workflow"
56604
+ }
56605
+ }
56606
+ }
56607
+ ]
56608
+ };
56609
+ var servicesSchema = {
56610
+ type: "object",
56611
+ propertyNames: {
56612
+ pattern: "^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$",
56613
+ maxLength: 64
56614
+ },
56615
+ additionalProperties: servicesServiceConfigSchema
56616
+ };
56219
56617
  var experimentalServicesSchema = {
56220
56618
  type: "object",
56221
56619
  propertyNames: {
56222
56620
  pattern: "^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$",
56223
56621
  maxLength: 64
56224
56622
  },
56225
- additionalProperties: serviceConfigSchema
56623
+ additionalProperties: experimentalServicesServiceConfigSchema
56226
56624
  };
56227
56625
  var experimentalServiceGroupsSchema = {
56228
56626
  type: "object",
@@ -56256,13 +56654,27 @@ var vercelConfigSchema = {
56256
56654
  images: imagesSchema,
56257
56655
  crons: cronsSchema,
56258
56656
  bunVersion: { type: "string" },
56657
+ env: topLevelEnvSchema,
56658
+ services: servicesSchema,
56259
56659
  experimentalServices: experimentalServicesSchema,
56260
56660
  experimentalServiceGroups: experimentalServiceGroupsSchema
56261
56661
  }
56262
56662
  };
56263
56663
  var ajv = new import_ajv.default();
56264
56664
  var validate = ajv.compile(vercelConfigSchema);
56665
+ function isPublicServicesEnabled() {
56666
+ return process.env.VERCEL_USE_SERVICES === "1" || process.env.VERCEL_USE_SERVICES?.toLowerCase() === "true";
56667
+ }
56265
56668
  function validateConfig(config) {
56669
+ if (Object.prototype.hasOwnProperty.call(config, "services") && !isPublicServicesEnabled()) {
56670
+ const fileName = config[import_client.fileNameSymbol] || "vercel.json";
56671
+ const niceError = getPrettyError({
56672
+ dataPath: "",
56673
+ params: { additionalProperty: "services" }
56674
+ });
56675
+ niceError.message = `Invalid ${fileName} - ${niceError.message}`;
56676
+ return niceError;
56677
+ }
56266
56678
  if (!validate(config)) {
56267
56679
  if (validate.errors && validate.errors[0]) {
56268
56680
  const error = validate.errors[0];
@@ -56279,16 +56691,24 @@ function validateConfig(config) {
56279
56691
  link: "https://vercel.link/functions-and-builds"
56280
56692
  });
56281
56693
  }
56282
- if (config.experimentalServices && config.builds) {
56694
+ const hasServices = Boolean(config.services);
56695
+ const hasExperimentalServices = Boolean(config.experimentalServices);
56696
+ if (hasServices && hasExperimentalServices) {
56697
+ return new NowBuildError({
56698
+ code: "SERVICES_AND_EXPERIMENTAL_SERVICES",
56699
+ message: "The `services` property cannot be used in conjunction with the `experimentalServices` property. Please remove one of them."
56700
+ });
56701
+ }
56702
+ if ((hasServices || hasExperimentalServices) && config.builds) {
56283
56703
  return new NowBuildError({
56284
56704
  code: "SERVICES_AND_BUILDS",
56285
- message: "The `experimentalServices` property cannot be used in conjunction with the `builds` property. Please remove one of them."
56705
+ message: "The `services` property cannot be used in conjunction with the `builds` property. Please remove one of them."
56286
56706
  });
56287
56707
  }
56288
- if (config.experimentalServices && config.functions) {
56708
+ if ((hasServices || hasExperimentalServices) && config.functions) {
56289
56709
  return new NowBuildError({
56290
56710
  code: "SERVICES_AND_FUNCTIONS",
56291
- message: "The `experimentalServices` property cannot be used in conjunction with the `functions` property. Please remove one of them."
56711
+ message: "The `services` property cannot be used in conjunction with the `functions` property. Please remove one of them."
56292
56712
  });
56293
56713
  }
56294
56714
  if (config.experimentalServiceGroups && !config.experimentalServices) {
@@ -56314,7 +56734,7 @@ async function hasExperimentalServicesConfig(cwd) {
56314
56734
  );
56315
56735
  if (!config || config instanceof Error)
56316
56736
  return false;
56317
- return config.experimentalServices != null && typeof config.experimentalServices === "object";
56737
+ return config.services != null && typeof config.services === "object" || config.experimentalServices != null && typeof config.experimentalServices === "object";
56318
56738
  } catch {
56319
56739
  return false;
56320
56740
  }
@@ -57135,6 +57555,7 @@ export {
57135
57555
  require_lib2 as require_lib,
57136
57556
  humanizePath,
57137
57557
  envTargetChoices,
57558
+ isValidEnvTarget,
57138
57559
  getEnvTargetPlaceholder,
57139
57560
  listSubcommand,
57140
57561
  addSubcommand,