@vercel/static-build 2.9.24 → 2.9.26

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 (2) hide show
  1. package/dist/index.js +257 -36
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -9297,6 +9297,40 @@ var require_frameworks = __commonJS({
9297
9297
  }
9298
9298
  ]
9299
9299
  },
9300
+ {
9301
+ name: "Ash",
9302
+ slug: "ash",
9303
+ logo: "https://api-frameworks.vercel.sh/framework-logos/ash.svg",
9304
+ darkModeLogo: "https://api-frameworks.vercel.sh/framework-logos/ash-dark.svg",
9305
+ tagline: "A filesystem-first framework for durable backend agents on Vercel.",
9306
+ description: "An Ash app: agents authored as a directory of files, compiled and served on Vercel.",
9307
+ detectors: {
9308
+ every: [
9309
+ {
9310
+ path: "package.json",
9311
+ matchContent: '"(dev)?(d|D)ependencies":\\s*{[^}]*"experimental-ash":\\s*".+?"[^}]*}'
9312
+ }
9313
+ ]
9314
+ },
9315
+ settings: {
9316
+ installCommand: {
9317
+ placeholder: "`pnpm install`, `yarn install`, or `npm install`"
9318
+ },
9319
+ buildCommand: {
9320
+ value: "ash build",
9321
+ placeholder: "`npm run build` or `ash build`"
9322
+ },
9323
+ devCommand: {
9324
+ value: "ash dev",
9325
+ placeholder: "ash dev"
9326
+ },
9327
+ outputDirectory: {
9328
+ value: ".output"
9329
+ }
9330
+ },
9331
+ getOutputDirName: async () => ".output",
9332
+ experimental: true
9333
+ },
9300
9334
  {
9301
9335
  name: "Sanity (v3)",
9302
9336
  slug: "sanity-v3",
@@ -22366,9 +22400,11 @@ var require_utils4 = __commonJS({
22366
22400
  inferRuntimeFromFramework: () => inferRuntimeFromFramework,
22367
22401
  inferServiceRuntime: () => inferServiceRuntime,
22368
22402
  isFrontendFramework: () => isFrontendFramework,
22403
+ isPublicServicesEnabled: () => isPublicServicesEnabled,
22369
22404
  isRouteOwningBuilder: () => isRouteOwningBuilder2,
22370
22405
  isStaticBuild: () => isStaticBuild2,
22371
- readVercelConfig: () => readVercelConfig
22406
+ readVercelConfig: () => readVercelConfig,
22407
+ validateServicesConfigGate: () => validateServicesConfigGate
22372
22408
  });
22373
22409
  module2.exports = __toCommonJS2(utils_exports);
22374
22410
  var import_framework_helpers = require("@vercel/build-utils/dist/framework-helpers");
@@ -22381,6 +22417,18 @@ var require_utils4 = __commonJS({
22381
22417
  return false;
22382
22418
  }
22383
22419
  }
22420
+ function isPublicServicesEnabled() {
22421
+ return process.env.VERCEL_USE_SERVICES === "1" || process.env.VERCEL_USE_SERVICES?.toLowerCase() === "true";
22422
+ }
22423
+ function validateServicesConfigGate(config) {
22424
+ if (config?.services !== void 0 && !isPublicServicesEnabled()) {
22425
+ return {
22426
+ code: "INVALID_VERCEL_CONFIG",
22427
+ message: "Invalid vercel.json - should NOT have additional property `services`. Please remove it."
22428
+ };
22429
+ }
22430
+ return null;
22431
+ }
22384
22432
  var INTERNAL_QUEUES_PREFIX = "/_svc/_queues";
22385
22433
  function normalizeInternalServiceEntrypoint(entrypoint) {
22386
22434
  const normalized = entrypoint.replace(/\\/g, "/").replace(/^\/+/, "").replace(/\.[^/.]+$/, "");
@@ -22465,6 +22513,10 @@ var require_utils4 = __commonJS({
22465
22513
  try {
22466
22514
  const content = await fs5.readFile("vercel.json");
22467
22515
  const config = JSON.parse(content.toString());
22516
+ const gateError = validateServicesConfigGate(config);
22517
+ if (gateError) {
22518
+ return { config: null, error: gateError };
22519
+ }
22468
22520
  return { config, error: null };
22469
22521
  } catch {
22470
22522
  return {
@@ -22482,6 +22534,10 @@ var require_utils4 = __commonJS({
22482
22534
  const { parse: tomlParse } = await Promise.resolve().then(() => (init_dist(), dist_exports));
22483
22535
  const content = await fs5.readFile("vercel.toml");
22484
22536
  const config = tomlParse(content.toString());
22537
+ const gateError = validateServicesConfigGate(config);
22538
+ if (gateError) {
22539
+ return { config: null, error: gateError };
22540
+ }
22485
22541
  return { config, error: null };
22486
22542
  } catch {
22487
22543
  return {
@@ -22800,7 +22856,12 @@ var require_resolve = __commonJS({
22800
22856
  }
22801
22857
  var SERVICE_NAME_REGEX = /^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$/;
22802
22858
  var DNS_LABEL_RE = /^(?!-)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i;
22803
- var ENV_PREFIX_RE = /^[A-Z][A-Z0-9_]*_$/;
22859
+ var ENV_VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
22860
+ var ENTRYPOINT_REQUIRED_RUNTIMES = /* @__PURE__ */ new Set([
22861
+ "node",
22862
+ "python",
22863
+ "go"
22864
+ ]);
22804
22865
  async function getServiceFs(fs5, serviceName, root) {
22805
22866
  if (!root) {
22806
22867
  return { fs: fs5 };
@@ -22832,6 +22893,38 @@ var require_resolve = __commonJS({
22832
22893
  const normalized = import_path7.posix.normalize(entrypoint);
22833
22894
  return normalized === "" ? "." : normalized;
22834
22895
  }
22896
+ function getEffectiveServiceTrigger(config) {
22897
+ if (config.type === "cron") {
22898
+ return "schedule";
22899
+ }
22900
+ if (config.type === "worker") {
22901
+ return "queue";
22902
+ }
22903
+ if (config.type !== "job") {
22904
+ return void 0;
22905
+ }
22906
+ return config.trigger;
22907
+ }
22908
+ function getEntrypointRequiredRuntime(config) {
22909
+ if (config.runtime && config.runtime in import_types.RUNTIME_BUILDERS) {
22910
+ return config.runtime;
22911
+ }
22912
+ return (0, import_utils.inferRuntimeFromFramework)(config.framework);
22913
+ }
22914
+ function validateBackendFileEntrypoint(name, config, resolvedEntrypoint, options) {
22915
+ if (!options.requireFileEntrypointForBackendRuntimes || !resolvedEntrypoint?.isDirectory) {
22916
+ return null;
22917
+ }
22918
+ const runtime = getEntrypointRequiredRuntime(config);
22919
+ if (!runtime || !ENTRYPOINT_REQUIRED_RUNTIMES.has(runtime)) {
22920
+ return null;
22921
+ }
22922
+ return {
22923
+ code: "INVALID_ENTRYPOINT",
22924
+ message: `Service "${name}" must specify a file "entrypoint" when using "${config.runtime ? "runtime" : "framework"}" "${config.runtime || config.framework}".`,
22925
+ serviceName: name
22926
+ };
22927
+ }
22835
22928
  async function resolveEntrypointPath({
22836
22929
  fs: fs5,
22837
22930
  serviceName,
@@ -22926,7 +23019,7 @@ var require_resolve = __commonJS({
22926
23019
  return {
22927
23020
  error: {
22928
23021
  code: "MULTIPLE_FRAMEWORKS_SERVICE",
22929
- message: `Multiple frameworks detected in ${workspace === "." ? "project root" : `${workspace}/`}: ${frameworkNames}. Specify "framework" explicitly in experimentalServices.`,
23022
+ message: `Multiple frameworks detected in ${workspace === "." ? "project root" : `${workspace}/`}: ${frameworkNames}. Specify "framework" explicitly in services.`,
22930
23023
  serviceName
22931
23024
  }
22932
23025
  };
@@ -23020,7 +23113,7 @@ var require_resolve = __commonJS({
23020
23113
  }
23021
23114
  };
23022
23115
  }
23023
- function validateServiceConfig(name, config) {
23116
+ function validateServiceConfig(name, config, options = {}) {
23024
23117
  if (!SERVICE_NAME_REGEX.test(name)) {
23025
23118
  return {
23026
23119
  code: "INVALID_SERVICE_NAME",
@@ -23036,13 +23129,15 @@ var require_resolve = __commonJS({
23036
23129
  };
23037
23130
  }
23038
23131
  const serviceType = config.type || "web";
23039
- const isJobService = serviceType === "job" || serviceType === "cron";
23040
- const isScheduleJobService = (0, import_build_utils5.isScheduleTriggeredService)({
23132
+ const effectiveTrigger = getEffectiveServiceTrigger(config);
23133
+ const effectiveService = {
23041
23134
  type: serviceType,
23042
- trigger: config.trigger
23043
- });
23044
- const isQueueJobService = serviceType === "job" && config.trigger === "queue";
23045
- const isWorkflowService = serviceType === "job" && config.trigger === "workflow";
23135
+ trigger: effectiveTrigger
23136
+ };
23137
+ const isJobService = serviceType === "job" || serviceType === "cron";
23138
+ const isScheduleJobService = (0, import_build_utils5.isScheduleTriggeredService)(effectiveService);
23139
+ const isQueueJobService = serviceType === "job" && (0, import_build_utils5.isQueueTriggeredService)(effectiveService);
23140
+ const isWorkflowService = serviceType === "job" && effectiveTrigger === "workflow";
23046
23141
  const isNonWebService = serviceType === "worker" || isJobService;
23047
23142
  const serviceTypeLabel = isJobService ? "Job" : serviceType === "worker" ? "Worker" : "Web";
23048
23143
  const routingResult = resolveServiceRoutingConfig(name, config);
@@ -23088,17 +23183,17 @@ var require_resolve = __commonJS({
23088
23183
  serviceName: name
23089
23184
  };
23090
23185
  }
23091
- if (serviceType === "job" && config.trigger === void 0) {
23186
+ if (serviceType === "job" && effectiveTrigger === void 0) {
23092
23187
  return {
23093
23188
  code: "MISSING_JOB_TRIGGER",
23094
23189
  message: `Job service "${name}" is missing required "trigger" field.`,
23095
23190
  serviceName: name
23096
23191
  };
23097
23192
  }
23098
- if (serviceType === "job" && config.trigger && !import_build_utils5.JOB_TRIGGERS.includes(config.trigger)) {
23193
+ if (serviceType === "job" && effectiveTrigger && !import_build_utils5.JOB_TRIGGERS.includes(effectiveTrigger)) {
23099
23194
  return {
23100
23195
  code: "INVALID_JOB_TRIGGER",
23101
- message: `Job service "${name}" has invalid trigger "${config.trigger}". Expected ${import_build_utils5.JOB_TRIGGERS.map((t) => `"${t}"`).join(", ")}.`,
23196
+ message: `Job service "${name}" has invalid trigger "${effectiveTrigger}". Expected ${import_build_utils5.JOB_TRIGGERS.map((t) => `"${t}"`).join(", ")}.`,
23102
23197
  serviceName: name
23103
23198
  };
23104
23199
  }
@@ -23140,14 +23235,46 @@ var require_resolve = __commonJS({
23140
23235
  };
23141
23236
  }
23142
23237
  }
23143
- if (config.envPrefix !== void 0) {
23144
- if (!ENV_PREFIX_RE.test(config.envPrefix)) {
23238
+ if (config.env !== void 0) {
23239
+ if (typeof config.env !== "object" || Array.isArray(config.env)) {
23145
23240
  return {
23146
- code: "INVALID_ENV_PREFIX",
23147
- 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_").`,
23241
+ code: "INVALID_ENV_VARS",
23242
+ message: `Service "${name}" has invalid "env". Must be an object keyed by environment variable name.`,
23148
23243
  serviceName: name
23149
23244
  };
23150
23245
  }
23246
+ for (const [envVarName, envVar] of Object.entries(config.env)) {
23247
+ if (!ENV_VAR_NAME_RE.test(envVarName)) {
23248
+ return {
23249
+ code: "INVALID_ENV_VAR_NAME",
23250
+ message: `Service "${name}" has invalid env key "${envVarName}". Must match /^[A-Za-z_][A-Za-z0-9_]*$/.`,
23251
+ serviceName: name
23252
+ };
23253
+ }
23254
+ if (!envVar || typeof envVar !== "object" || Array.isArray(envVar)) {
23255
+ return {
23256
+ code: "INVALID_ENV_VAR",
23257
+ message: `Service "${name}" has invalid env["${envVarName}"]. Must be an object with a "type" discriminator.`,
23258
+ serviceName: name
23259
+ };
23260
+ }
23261
+ const envVarType = envVar.type;
23262
+ if (envVarType !== "service-ref") {
23263
+ return {
23264
+ code: "INVALID_ENV_VAR_TYPE",
23265
+ message: `Service "${name}" env["${envVarName}"] has unknown type "${envVarType}".`,
23266
+ serviceName: name
23267
+ };
23268
+ }
23269
+ const refService = envVar.service;
23270
+ if (typeof refService !== "string" || refService.length === 0) {
23271
+ return {
23272
+ code: "INVALID_ENV_VAR_REF",
23273
+ message: `Service "${name}" env["${envVarName}"] must specify "service" as a non-empty string.`,
23274
+ serviceName: name
23275
+ };
23276
+ }
23277
+ }
23151
23278
  }
23152
23279
  if (config.runtime && !(config.runtime in import_types.RUNTIME_BUILDERS)) {
23153
23280
  return {
@@ -23176,6 +23303,7 @@ var require_resolve = __commonJS({
23176
23303
  const hasFramework = Boolean(config.framework);
23177
23304
  const hasBuilderOrRuntime = Boolean(config.builder || config.runtime);
23178
23305
  const hasEntrypoint = Boolean(config.entrypoint);
23306
+ const entrypointRequiredRuntime = getEntrypointRequiredRuntime(config);
23179
23307
  if (!hasFramework && !hasBuilderOrRuntime && !hasEntrypoint) {
23180
23308
  return {
23181
23309
  code: "MISSING_SERVICE_CONFIG",
@@ -23183,6 +23311,13 @@ var require_resolve = __commonJS({
23183
23311
  serviceName: name
23184
23312
  };
23185
23313
  }
23314
+ if (options.requireFileEntrypointForBackendRuntimes && !hasEntrypoint && entrypointRequiredRuntime && ENTRYPOINT_REQUIRED_RUNTIMES.has(entrypointRequiredRuntime)) {
23315
+ return {
23316
+ code: "MISSING_ENTRYPOINT",
23317
+ message: `Service "${name}" must specify "entrypoint" when using "${config.runtime ? "runtime" : "framework"}" "${config.runtime || config.framework}".`,
23318
+ serviceName: name
23319
+ };
23320
+ }
23186
23321
  if (hasBuilderOrRuntime && !hasFramework && !hasEntrypoint) {
23187
23322
  return {
23188
23323
  code: "MISSING_ENTRYPOINT",
@@ -23220,7 +23355,7 @@ var require_resolve = __commonJS({
23220
23355
  routePrefixSource = "configured"
23221
23356
  } = options;
23222
23357
  const type = config.type || "web";
23223
- const trigger = type === "cron" ? "schedule" : type === "job" ? config.trigger : void 0;
23358
+ const trigger = getEffectiveServiceTrigger(config);
23224
23359
  const rawEntrypoint = config.entrypoint;
23225
23360
  const moduleAttrParsed = typeof rawEntrypoint === "string" ? parsePyModuleAttrEntrypoint(rawEntrypoint) : null;
23226
23361
  const routingResult = resolveServiceRoutingConfig(name, config);
@@ -23363,16 +23498,16 @@ var require_resolve = __commonJS({
23363
23498
  schedule: config.schedule,
23364
23499
  handlerFunction: moduleAttrParsed?.attrName,
23365
23500
  topics,
23366
- envPrefix: config.envPrefix
23501
+ env: config.env
23367
23502
  };
23368
23503
  }
23369
- async function resolveAllConfiguredServices(services, fs5, routePrefixSource = "configured") {
23504
+ async function resolveAllConfiguredServices(services, fs5, routePrefixSource = "configured", options = {}) {
23370
23505
  const resolved = [];
23371
23506
  const errors = [];
23372
23507
  const webServicesByRoutePrefix = /* @__PURE__ */ new Map();
23373
23508
  for (const name of Object.keys(services)) {
23374
23509
  const serviceConfig = services[name];
23375
- const validationError = validateServiceConfig(name, serviceConfig);
23510
+ const validationError = validateServiceConfig(name, serviceConfig, options);
23376
23511
  if (validationError) {
23377
23512
  errors.push(validationError);
23378
23513
  continue;
@@ -23410,6 +23545,16 @@ var require_resolve = __commonJS({
23410
23545
  continue;
23411
23546
  }
23412
23547
  }
23548
+ const explicitBackendEntrypointError = validateBackendFileEntrypoint(
23549
+ name,
23550
+ serviceConfig,
23551
+ resolvedEntrypoint,
23552
+ options
23553
+ );
23554
+ if (explicitBackendEntrypointError) {
23555
+ errors.push(explicitBackendEntrypointError);
23556
+ continue;
23557
+ }
23413
23558
  let resolvedConfig = serviceConfig;
23414
23559
  if (!serviceConfig.framework && resolvedEntrypoint) {
23415
23560
  if (resolvedEntrypoint.isDirectory) {
@@ -23466,6 +23611,16 @@ var require_resolve = __commonJS({
23466
23611
  }
23467
23612
  }
23468
23613
  }
23614
+ const backendEntrypointError = validateBackendFileEntrypoint(
23615
+ name,
23616
+ resolvedConfig,
23617
+ resolvedEntrypoint,
23618
+ options
23619
+ );
23620
+ if (backendEntrypointError) {
23621
+ errors.push(backendEntrypointError);
23622
+ continue;
23623
+ }
23469
23624
  const service = await resolveConfiguredService({
23470
23625
  name,
23471
23626
  config: resolvedConfig,
@@ -23491,8 +23646,49 @@ var require_resolve = __commonJS({
23491
23646
  }
23492
23647
  resolved.push(service);
23493
23648
  }
23649
+ const servicesByName = new Map(resolved.map((s) => [s.name, s]));
23650
+ for (const service of resolved) {
23651
+ if (!service.env)
23652
+ continue;
23653
+ validateEnvRefs(
23654
+ service.env,
23655
+ `Service "${service.name}" env`,
23656
+ servicesByName,
23657
+ errors,
23658
+ service.name
23659
+ );
23660
+ }
23661
+ if (options.rootEnv) {
23662
+ validateEnvRefs(options.rootEnv, "env", servicesByName, errors);
23663
+ for (const service of resolved) {
23664
+ service.env = { ...options.rootEnv, ...service.env ?? {} };
23665
+ }
23666
+ }
23494
23667
  return { services: resolved, errors };
23495
23668
  }
23669
+ function validateEnvRefs(env, pathPrefix, servicesByName, errors, serviceName) {
23670
+ for (const [envVarName, envVar] of Object.entries(env)) {
23671
+ if (envVar.type !== "service-ref")
23672
+ continue;
23673
+ const refName = envVar.service;
23674
+ const target = servicesByName.get(refName);
23675
+ if (!target) {
23676
+ errors.push({
23677
+ code: "UNKNOWN_SERVICE_REF",
23678
+ message: `${pathPrefix}["${envVarName}"] references unknown service "${refName}".`,
23679
+ ...serviceName ? { serviceName } : {}
23680
+ });
23681
+ continue;
23682
+ }
23683
+ if (target.type !== "web") {
23684
+ errors.push({
23685
+ code: "INVALID_SERVICE_REF_TYPE",
23686
+ message: `${pathPrefix}["${envVarName}"] references service "${refName}" which is a ${target.type} service and has no URL. Only web services can be referenced.`,
23687
+ ...serviceName ? { serviceName } : {}
23688
+ });
23689
+ }
23690
+ }
23691
+ }
23496
23692
  }
23497
23693
  });
23498
23694
 
@@ -23545,7 +23741,7 @@ var require_auto_detect = __commonJS({
23545
23741
  errors: [
23546
23742
  {
23547
23743
  code: "MULTIPLE_FRAMEWORKS_ROOT",
23548
- message: `Multiple frameworks detected at root: ${frameworkNames}. Use explicit experimentalServices config.`
23744
+ message: `Multiple frameworks detected at root: ${frameworkNames}. Use explicit services config.`
23549
23745
  }
23550
23746
  ]
23551
23747
  };
@@ -23570,7 +23766,7 @@ var require_auto_detect = __commonJS({
23570
23766
  errors: [
23571
23767
  {
23572
23768
  code: "MULTIPLE_FRAMEWORKS_SERVICE",
23573
- message: `Multiple frameworks detected in ${frontendLocation}/: ${frameworkNames}. Use explicit experimentalServices config.`
23769
+ message: `Multiple frameworks detected in ${frontendLocation}/: ${frameworkNames}. Use explicit services config.`
23574
23770
  }
23575
23771
  ]
23576
23772
  };
@@ -23588,7 +23784,7 @@ var require_auto_detect = __commonJS({
23588
23784
  errors: [
23589
23785
  {
23590
23786
  code: "NO_SERVICES_CONFIGURED",
23591
- message: "No services detected. Configure experimentalServices in vercel.json or ensure a framework exists at project root, frontend/, or apps/web/."
23787
+ message: "No services detected. Configure services in vercel.json or ensure a framework exists at project root, frontend/, or apps/web/."
23592
23788
  }
23593
23789
  ]
23594
23790
  };
@@ -23669,7 +23865,7 @@ var require_auto_detect = __commonJS({
23669
23865
  services: {},
23670
23866
  error: {
23671
23867
  code: "SERVICE_NAME_CONFLICT",
23672
- message: `Service name conflict: "${serviceName}" exists in both ${BACKEND_DIR}/ and ${SERVICES_DIR}/${serviceName}/. Rename one of the directories or use explicit experimentalServices config.`,
23868
+ message: `Service name conflict: "${serviceName}" exists in both ${BACKEND_DIR}/ and ${SERVICES_DIR}/${serviceName}/. Rename one of the directories or use explicit services config.`,
23673
23869
  serviceName
23674
23870
  }
23675
23871
  };
@@ -23718,7 +23914,7 @@ var require_auto_detect = __commonJS({
23718
23914
  return {
23719
23915
  error: {
23720
23916
  code: "MULTIPLE_FRAMEWORKS_SERVICE",
23721
- message: `Multiple frameworks detected in ${dirPath}/: ${frameworkNames}. Use explicit experimentalServices config.`,
23917
+ message: `Multiple frameworks detected in ${dirPath}/: ${frameworkNames}. Use explicit services config.`,
23722
23918
  serviceName
23723
23919
  }
23724
23920
  };
@@ -23852,7 +24048,7 @@ var require_detect_railway = __commonJS({
23852
24048
  if (frameworks2.length === 0) {
23853
24049
  warnings.push({
23854
24050
  code: "SERVICE_SKIPPED",
23855
- message: `Skipped service in ${dirLabel}/: no framework detected. Configure it manually in experimentalServices.`
24051
+ message: `Skipped service in ${dirLabel}/: no framework detected. Configure it manually in services.`
23856
24052
  });
23857
24053
  continue;
23858
24054
  }
@@ -23860,7 +24056,7 @@ var require_detect_railway = __commonJS({
23860
24056
  const names = frameworks2.map((f) => f.name).join(", ");
23861
24057
  errors.push({
23862
24058
  code: "MULTIPLE_FRAMEWORKS_SERVICE",
23863
- message: `Multiple frameworks detected in ${dirLabel}/: ${names}. Use explicit experimentalServices config.`,
24059
+ message: `Multiple frameworks detected in ${dirLabel}/: ${names}. Use explicit services config.`,
23864
24060
  serviceName
23865
24061
  });
23866
24062
  continue;
@@ -24058,10 +24254,17 @@ var require_detect_services = __commonJS({
24058
24254
  workers: []
24059
24255
  };
24060
24256
  }
24257
+ function isEnvVars(env) {
24258
+ if (!env)
24259
+ return false;
24260
+ const first = Object.values(env)[0];
24261
+ return typeof first === "object" && first !== null;
24262
+ }
24061
24263
  function withResolvedResult(resolved, inferred = null) {
24062
24264
  return {
24063
24265
  services: resolved.services,
24064
24266
  source: resolved.source,
24267
+ useImplicitEnvInjection: resolved.useImplicitEnvInjection,
24065
24268
  routes: resolved.routes,
24066
24269
  errors: resolved.errors,
24067
24270
  warnings: resolved.warnings,
@@ -24097,12 +24300,14 @@ var require_detect_services = __commonJS({
24097
24300
  return withResolvedResult({
24098
24301
  services: [],
24099
24302
  source: "configured",
24303
+ useImplicitEnvInjection: true,
24100
24304
  routes: emptyRoutes(),
24101
24305
  errors: [configError],
24102
24306
  warnings: []
24103
24307
  });
24104
24308
  }
24105
- const configuredServices = vercelConfig?.experimentalServices;
24309
+ const hasNonEmptyPublicServicesConfig = vercelConfig?.services && Object.keys(vercelConfig.services).length > 0;
24310
+ const configuredServices = hasNonEmptyPublicServicesConfig ? vercelConfig.services : vercelConfig?.experimentalServices;
24106
24311
  const hasConfiguredServices = configuredServices && Object.keys(configuredServices).length > 0;
24107
24312
  if (!hasConfiguredServices) {
24108
24313
  const railwayResult = await (0, import_detect_railway.detectRailwayServices)({ fs: scopedFs });
@@ -24110,6 +24315,7 @@ var require_detect_services = __commonJS({
24110
24315
  return withResolvedResult({
24111
24316
  services: [],
24112
24317
  source: "auto-detected",
24318
+ useImplicitEnvInjection: true,
24113
24319
  routes: emptyRoutes(),
24114
24320
  errors: railwayResult.errors,
24115
24321
  warnings: railwayResult.warnings
@@ -24131,6 +24337,7 @@ var require_detect_services = __commonJS({
24131
24337
  {
24132
24338
  services: [],
24133
24339
  source: "auto-detected",
24340
+ useImplicitEnvInjection: true,
24134
24341
  routes: emptyRoutes(),
24135
24342
  errors: result2.errors,
24136
24343
  warnings: railwayResult.warnings
@@ -24149,6 +24356,7 @@ var require_detect_services = __commonJS({
24149
24356
  const resolved = {
24150
24357
  services: result2.services,
24151
24358
  source: "auto-detected",
24359
+ useImplicitEnvInjection: true,
24152
24360
  routes: routes2,
24153
24361
  errors: result2.errors,
24154
24362
  warnings: []
@@ -24167,6 +24375,7 @@ var require_detect_services = __commonJS({
24167
24375
  return withResolvedResult({
24168
24376
  services: [],
24169
24377
  source: "auto-detected",
24378
+ useImplicitEnvInjection: true,
24170
24379
  routes: emptyRoutes(),
24171
24380
  errors: autoResult.errors,
24172
24381
  warnings: []
@@ -24175,11 +24384,12 @@ var require_detect_services = __commonJS({
24175
24384
  return withResolvedResult({
24176
24385
  services: [],
24177
24386
  source: "auto-detected",
24387
+ useImplicitEnvInjection: true,
24178
24388
  routes: emptyRoutes(),
24179
24389
  errors: [
24180
24390
  {
24181
24391
  code: "NO_SERVICES_CONFIGURED",
24182
- message: "No services configured. Add `experimentalServices` to vercel.json."
24392
+ message: "No services configured. Add `services` to vercel.json."
24183
24393
  }
24184
24394
  ],
24185
24395
  warnings: []
@@ -24188,12 +24398,21 @@ var require_detect_services = __commonJS({
24188
24398
  const result = await (0, import_resolve.resolveAllConfiguredServices)(
24189
24399
  configuredServices,
24190
24400
  scopedFs,
24191
- "configured"
24401
+ "configured",
24402
+ {
24403
+ requireFileEntrypointForBackendRuntimes: Boolean(
24404
+ hasNonEmptyPublicServicesConfig
24405
+ ),
24406
+ rootEnv: isEnvVars(vercelConfig?.env) ? vercelConfig?.env : void 0
24407
+ }
24192
24408
  );
24193
24409
  const routes = generateServicesRoutes2(result.services);
24194
24410
  return withResolvedResult({
24195
24411
  services: result.services,
24196
24412
  source: "configured",
24413
+ // GA `services` opts into explicit `env`; experimentalServices keeps
24414
+ // the legacy `{NAME}_URL` injection.
24415
+ useImplicitEnvInjection: !hasNonEmptyPublicServicesConfig,
24197
24416
  routes,
24198
24417
  errors: result.errors,
24199
24418
  warnings: []
@@ -24616,7 +24835,7 @@ var require_get_services_builders = __commonJS({
24616
24835
  errors: [
24617
24836
  {
24618
24837
  code: "NO_SERVICES_CONFIGURED",
24619
- message: "No services configured. Add `experimentalServices` to vercel.json."
24838
+ message: "No services configured. Add `services` to vercel.json."
24620
24839
  }
24621
24840
  ],
24622
24841
  warnings: warningResponses,
@@ -24643,7 +24862,8 @@ var require_get_services_builders = __commonJS({
24643
24862
  ...result.routes.crons
24644
24863
  ] : null,
24645
24864
  errorRoutes: [],
24646
- services: result.services
24865
+ services: result.services,
24866
+ useImplicitEnvInjection: result.useImplicitEnvInjection
24647
24867
  };
24648
24868
  }
24649
24869
  }
@@ -24746,13 +24966,14 @@ var require_detect_builders = __commonJS({
24746
24966
  return publicBuilder ? publicBuilder.src.replace("/**/*", "") : null;
24747
24967
  }
24748
24968
  async function detectBuilders2(files, pkg, options = {}) {
24749
- const { experimentalServices: services, projectSettings = {} } = options;
24969
+ const { services, experimentalServices, projectSettings = {} } = options;
24750
24970
  const { framework } = projectSettings;
24751
- const hasServicesConfig = services != null && typeof services === "object";
24971
+ const configuredServices = services ?? experimentalServices;
24972
+ const hasServicesConfig = configuredServices != null && typeof configuredServices === "object";
24752
24973
  if (hasServicesConfig || framework === "services") {
24753
24974
  return (0, import_get_services_builders.getServicesBuilders)({
24754
24975
  workPath: options.workPath,
24755
- configuredServices: services,
24976
+ configuredServices,
24756
24977
  projectFramework: framework
24757
24978
  });
24758
24979
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/static-build",
3
- "version": "2.9.24",
3
+ "version": "2.9.26",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/build-step",
@@ -15,7 +15,7 @@
15
15
  "dependencies": {
16
16
  "ts-morph": "12.0.0",
17
17
  "@vercel/gatsby-plugin-vercel-analytics": "1.0.11",
18
- "@vercel/gatsby-plugin-vercel-builder": "2.2.2",
18
+ "@vercel/gatsby-plugin-vercel-builder": "2.2.4",
19
19
  "@vercel/static-config": "3.3.0"
20
20
  },
21
21
  "devDependencies": {
@@ -37,10 +37,10 @@
37
37
  "semver": "7.5.2",
38
38
  "tree-kill": "1.2.2",
39
39
  "vitest": "2.0.3",
40
- "@vercel/build-utils": "13.22.1",
40
+ "@vercel/build-utils": "13.24.0",
41
+ "@vercel/frameworks": "3.26.0",
42
+ "@vercel/fs-detectors": "6.3.0",
41
43
  "@vercel/error-utils": "2.1.0",
42
- "@vercel/frameworks": "3.25.1",
43
- "@vercel/fs-detectors": "6.2.1",
44
44
  "@vercel/routing-utils": "6.2.0"
45
45
  },
46
46
  "scripts": {