@vercel/static-build 2.11.2 → 2.11.4

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 +293 -143
  2. package/package.json +7 -7
package/dist/index.js CHANGED
@@ -7160,6 +7160,50 @@ var require_frameworks = __commonJS({
7160
7160
  __reExport(frameworks_exports, require_types(), module2.exports);
7161
7161
  var { readdir, readFile, unlink } = import_fs5.promises;
7162
7162
  var frameworks2 = [
7163
+ {
7164
+ // A `Dockerfile.vercel` / `Containerfile.vercel` is an explicit opt-in to
7165
+ // deploy a project as a container, regardless of any other framework that
7166
+ // may also be detected. It is listed first so that framework detection
7167
+ // (which returns the first match in list order) selects it over everything
7168
+ // else — e.g. a Next.js app shipping a `Dockerfile.vercel` deploys as a
7169
+ // container, not via `@vercel/next`.
7170
+ name: "Container",
7171
+ slug: "container",
7172
+ runtimeFramework: true,
7173
+ logo: "https://api-frameworks.vercel.sh/framework-logos/container.svg",
7174
+ tagline: "Deploy any project as a container image built from a Dockerfile.",
7175
+ description: "A project deployed as a container image, built from a Dockerfile.vercel or Containerfile.vercel.",
7176
+ website: "https://docs.docker.com/reference/dockerfile/",
7177
+ useRuntime: { src: "<detect>", use: "@vercel/container" },
7178
+ detectors: {
7179
+ some: [
7180
+ {
7181
+ path: "Dockerfile.vercel"
7182
+ },
7183
+ {
7184
+ path: "Containerfile.vercel"
7185
+ }
7186
+ ]
7187
+ },
7188
+ settings: {
7189
+ installCommand: {
7190
+ placeholder: "None",
7191
+ value: null
7192
+ },
7193
+ buildCommand: {
7194
+ placeholder: "None",
7195
+ value: null
7196
+ },
7197
+ devCommand: {
7198
+ placeholder: "None",
7199
+ value: null
7200
+ },
7201
+ outputDirectory: {
7202
+ placeholder: "None"
7203
+ }
7204
+ },
7205
+ getOutputDirName: async () => "public"
7206
+ },
7163
7207
  {
7164
7208
  name: "Blitz.js (Legacy)",
7165
7209
  slug: "blitzjs",
@@ -19756,7 +19800,7 @@ var require_superstatic = __commonJS({
19756
19800
  convertCleanUrls: () => convertCleanUrls,
19757
19801
  convertHeaders: () => convertHeaders,
19758
19802
  convertRedirects: () => convertRedirects,
19759
- convertRewrites: () => convertRewrites,
19803
+ convertRewrites: () => convertRewrites2,
19760
19804
  convertTrailingSlash: () => convertTrailingSlash,
19761
19805
  getCleanUrls: () => getCleanUrls2,
19762
19806
  pathToRegexp: () => pathToRegexp,
@@ -19872,7 +19916,7 @@ var require_superstatic = __commonJS({
19872
19916
  }
19873
19917
  });
19874
19918
  }
19875
- function convertRewrites(rewrites, internalParamNames) {
19919
+ function convertRewrites2(rewrites, internalParamNames) {
19876
19920
  return rewrites.map((r) => {
19877
19921
  const { src, segments } = sourceToRegex2(r.source);
19878
19922
  const hasSegments = collectHasSegments(r.has);
@@ -19890,7 +19934,7 @@ var require_superstatic = __commonJS({
19890
19934
  if (typeof r.destination === "string") {
19891
19935
  route = { src, dest: interpolate(r.destination), check: true };
19892
19936
  } else {
19893
- const destination = { ...r.destination };
19937
+ const destination = { ...r.destination, type: "service" };
19894
19938
  if (typeof destination.path === "string") {
19895
19939
  destination.path = interpolate(destination.path);
19896
19940
  }
@@ -20553,13 +20597,13 @@ var require_schemas = __commonJS({
20553
20597
  pattern: "^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$"
20554
20598
  };
20555
20599
  var serviceDestinationSchema = {
20556
- description: "A service-targeted destination that delegates routing into a named service from `services`.",
20600
+ description: "A service-targeted destination that delegates routing into a named service from `services`. Identified by the presence of `service`.",
20557
20601
  type: "object",
20558
20602
  additionalProperties: false,
20559
- required: ["type", "service"],
20603
+ required: ["service"],
20560
20604
  properties: {
20561
20605
  type: {
20562
- description: "Discriminator. Must be `service`.",
20606
+ description: "Optional explicit format marker. The destination shape is identified by the `service` property, so `type` is no longer required. When present it must be `service`.",
20563
20607
  type: "string",
20564
20608
  enum: ["service"]
20565
20609
  },
@@ -21329,6 +21373,7 @@ var require_dist7 = __commonJS({
21329
21373
  __export2(src_exports2, {
21330
21374
  appendRoutesToPhase: () => import_append.appendRoutesToPhase,
21331
21375
  compilePathToRegexpTemplate: () => import_superstatic2.compilePathToRegexpTemplate,
21376
+ convertRewrites: () => import_superstatic2.convertRewrites,
21332
21377
  getCleanUrls: () => import_superstatic2.getCleanUrls,
21333
21378
  getOwnershipGuard: () => import_service_route_ownership.getOwnershipGuard,
21334
21379
  getTransformedRoutes: () => getTransformedRoutes,
@@ -21383,6 +21428,8 @@ var require_dist7 = __commonJS({
21383
21428
  if (typeof route.destination === "string") {
21384
21429
  route.dest = route.destination;
21385
21430
  delete route.destination;
21431
+ } else if (typeof route.destination.service === "string") {
21432
+ route.destination = { ...route.destination, type: "service" };
21386
21433
  }
21387
21434
  }
21388
21435
  if (route.statusCode !== void 0) {
@@ -22752,7 +22799,7 @@ var require_utils4 = __commonJS({
22752
22799
  DETECTION_FRAMEWORKS: () => DETECTION_FRAMEWORKS,
22753
22800
  INTERNAL_QUEUES_PREFIX: () => INTERNAL_QUEUES_PREFIX,
22754
22801
  INTERNAL_SERVICE_PREFIX: () => import_build_utils5.INTERNAL_SERVICE_PREFIX,
22755
- assignRoutePrefixes: () => assignRoutePrefixes,
22802
+ assignMountPaths: () => assignMountPaths,
22756
22803
  combineBuildCommand: () => combineBuildCommand,
22757
22804
  filterFrameworksByRuntime: () => filterFrameworksByRuntime,
22758
22805
  getBuilderForRuntime: () => getBuilderForRuntime,
@@ -22764,6 +22811,7 @@ var require_utils4 = __commonJS({
22764
22811
  hasFile: () => hasFile,
22765
22812
  inferRuntimeFromFramework: () => inferRuntimeFromFramework,
22766
22813
  inferServiceRuntime: () => inferServiceRuntime,
22814
+ isBFFFramework: () => isBFFFramework,
22767
22815
  isFrontendFramework: () => isFrontendFramework,
22768
22816
  isRouteOwningBuilder: () => isRouteOwningBuilder2,
22769
22817
  isStaticBuild: () => isStaticBuild2,
@@ -22835,6 +22883,16 @@ var require_utils4 = __commonJS({
22835
22883
  }
22836
22884
  return !inferRuntimeFromFramework(framework);
22837
22885
  }
22886
+ var BFF_FRAMEWORKS = /* @__PURE__ */ new Set([
22887
+ "nextjs",
22888
+ "nuxtjs",
22889
+ "sveltekit",
22890
+ "remix",
22891
+ "solidstart"
22892
+ ]);
22893
+ function isBFFFramework(framework) {
22894
+ return !!framework && BFF_FRAMEWORKS.has(framework);
22895
+ }
22838
22896
  function filterFrameworksByRuntime(frameworks2, runtime) {
22839
22897
  if (!runtime) {
22840
22898
  return [...frameworks2];
@@ -22903,11 +22961,11 @@ var require_utils4 = __commonJS({
22903
22961
  }
22904
22962
  return { config: null, error: null };
22905
22963
  }
22906
- function assignRoutePrefixes(services) {
22964
+ function assignMountPaths(services) {
22907
22965
  const warnings = [];
22908
22966
  const names = Object.keys(services);
22909
22967
  if (names.length === 1) {
22910
- services[names[0]].routePrefix = "/";
22968
+ services[names[0]].mountPath = "/";
22911
22969
  return warnings;
22912
22970
  }
22913
22971
  const frontendNames = names.filter(
@@ -22920,11 +22978,19 @@ var require_utils4 = __commonJS({
22920
22978
  rootName = frontendNames.find((n) => n === "frontend" || n === "web") ?? frontendNames.sort()[0];
22921
22979
  warnings.push({
22922
22980
  code: "MULTIPLE_FRONTENDS",
22923
- message: `Multiple frontend services detected (${frontendNames.join(", ")}). "${rootName}" was assigned routePrefix "/". Adjust manually if a different service should be the root.`
22981
+ message: `Multiple frontend services detected (${frontendNames.join(", ")}). "${rootName}" was assigned mount path "/". Adjust manually if a different service should be the root.`
22924
22982
  });
22925
22983
  }
22984
+ const rootFramework = rootName ? services[rootName].framework : void 0;
22985
+ const isBFF = rootFramework ? isBFFFramework(rootFramework) : false;
22986
+ const nonRootNames = names.filter((n) => n !== rootName);
22987
+ const needsNamespace = isBFF || nonRootNames.length > 1;
22926
22988
  for (const name of names) {
22927
- services[name].routePrefix = name === rootName ? "/" : `/_/${name}`;
22989
+ if (name === rootName) {
22990
+ services[name].mountPath = "/";
22991
+ } else {
22992
+ services[name].mountPath = needsNamespace ? `/api/${name}` : "/api";
22993
+ }
22928
22994
  }
22929
22995
  return warnings;
22930
22996
  }
@@ -24137,9 +24203,27 @@ var require_resolve_v2 = __commonJS({
24137
24203
  var import_utils = require_utils4();
24138
24204
  var frameworksBySlug = new Map(import_frameworks2.frameworkList.map((f) => [f.slug, f]));
24139
24205
  var SERVICE_NAME_REGEX = /^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$/;
24206
+ var CONTAINER_ENTRYPOINT_CANDIDATES = [
24207
+ "Dockerfile.vercel",
24208
+ "Containerfile.vercel",
24209
+ "Dockerfile",
24210
+ "Containerfile"
24211
+ ];
24212
+ var CONTAINER_ENTRYPOINT_BASENAMES = new Set(
24213
+ CONTAINER_ENTRYPOINT_CANDIDATES.map((name) => name.toLowerCase())
24214
+ );
24140
24215
  function isDockerfileEntrypoint(entrypoint) {
24141
- const base = import_path7.posix.basename(entrypoint).toLowerCase();
24142
- return base === "dockerfile" || base === "containerfile" || base.endsWith(".dockerfile");
24216
+ return CONTAINER_ENTRYPOINT_BASENAMES.has(
24217
+ import_path7.posix.basename(entrypoint).toLowerCase()
24218
+ );
24219
+ }
24220
+ async function detectContainerEntrypoint(serviceFs) {
24221
+ for (const candidate of CONTAINER_ENTRYPOINT_CANDIDATES) {
24222
+ if (await serviceFs.hasPath(candidate)) {
24223
+ return candidate;
24224
+ }
24225
+ }
24226
+ return void 0;
24143
24227
  }
24144
24228
  function normalizeContainerCommand(command) {
24145
24229
  if (command === void 0) {
@@ -24147,29 +24231,40 @@ var require_resolve_v2 = __commonJS({
24147
24231
  }
24148
24232
  return Array.isArray(command) ? command : [command];
24149
24233
  }
24150
- function resolveContainerServiceV2(name, config, normalizedRoot) {
24234
+ async function resolveContainerServiceV2(name, config, normalizedRoot, serviceFs) {
24151
24235
  const isRoot = normalizedRoot === ".";
24152
24236
  const entrypoint = config.entrypoint;
24153
- const dockerfile = typeof entrypoint === "string" && isDockerfileEntrypoint(entrypoint) ? import_path7.posix.normalize(entrypoint) : void 0;
24154
- const image = typeof entrypoint === "string" && !dockerfile ? entrypoint : void 0;
24155
- if (!dockerfile && !image) {
24156
- return {
24157
- error: {
24158
- code: "MISSING_SERVICE_CONFIG",
24159
- message: `Container service "${name}" must specify an "entrypoint": a Dockerfile path to build, or a prebuilt OCI image reference.`,
24160
- serviceName: name
24161
- }
24162
- };
24237
+ let dockerfile;
24238
+ if (typeof entrypoint === "string") {
24239
+ if (!isDockerfileEntrypoint(entrypoint)) {
24240
+ return {
24241
+ error: {
24242
+ code: "INVALID_SERVICE_CONFIG",
24243
+ message: `Container service "${name}" has invalid "entrypoint" "${entrypoint}". It must name a Dockerfile or Containerfile.`,
24244
+ serviceName: name
24245
+ }
24246
+ };
24247
+ }
24248
+ dockerfile = import_path7.posix.normalize(entrypoint);
24249
+ } else {
24250
+ dockerfile = await detectContainerEntrypoint(serviceFs);
24251
+ if (!dockerfile) {
24252
+ return {
24253
+ error: {
24254
+ code: "MISSING_SERVICE_CONFIG",
24255
+ message: `Container service "${name}" has no "entrypoint" and no ${CONTAINER_ENTRYPOINT_CANDIDATES.join(
24256
+ ", "
24257
+ )} was found in "${normalizedRoot}".`,
24258
+ serviceName: name
24259
+ }
24260
+ };
24261
+ }
24163
24262
  }
24164
- const localSrc = dockerfile ?? image ?? "Dockerfile";
24165
- const builderSrc = isRoot ? localSrc : import_path7.posix.join(normalizedRoot, localSrc);
24263
+ const builderSrc = isRoot ? dockerfile : import_path7.posix.join(normalizedRoot, dockerfile);
24166
24264
  const builderConfig = { zeroConfig: true };
24167
24265
  if (!isRoot) {
24168
24266
  builderConfig.workspace = normalizedRoot;
24169
24267
  }
24170
- if (image) {
24171
- builderConfig.handler = image;
24172
- }
24173
24268
  const command = normalizeContainerCommand(config.command);
24174
24269
  if (command) {
24175
24270
  builderConfig.command = command;
@@ -24180,7 +24275,7 @@ var require_resolve_v2 = __commonJS({
24180
24275
  name,
24181
24276
  root: normalizedRoot,
24182
24277
  runtime: "container",
24183
- entrypoint: image ?? dockerfile,
24278
+ entrypoint: dockerfile,
24184
24279
  command,
24185
24280
  builder: {
24186
24281
  src: builderSrc,
@@ -24271,15 +24366,15 @@ var require_resolve_v2 = __commonJS({
24271
24366
  }
24272
24367
  async function resolveConfiguredServiceV22(name, config, fs5) {
24273
24368
  const normalizedRoot = (0, import_utils.stripTrailingSlash)(import_path7.posix.normalize(config.root));
24274
- const isContainer = config.runtime === "container" || typeof config.entrypoint === "string" && isDockerfileEntrypoint(config.entrypoint);
24275
- if (isContainer) {
24276
- return resolveContainerServiceV2(name, config, normalizedRoot);
24277
- }
24278
24369
  const serviceFsResult = normalizedRoot === "." ? { fs: fs5 } : await (0, import_resolve.getServiceFs)(fs5, name, normalizedRoot);
24279
24370
  if (serviceFsResult.error) {
24280
24371
  return { error: serviceFsResult.error };
24281
24372
  }
24282
24373
  const serviceFs = serviceFsResult.fs;
24374
+ const isContainer = config.runtime === "container" || typeof config.entrypoint === "string" && isDockerfileEntrypoint(config.entrypoint);
24375
+ if (isContainer) {
24376
+ return resolveContainerServiceV2(name, config, normalizedRoot, serviceFs);
24377
+ }
24283
24378
  const rawEntrypoint = config.entrypoint;
24284
24379
  const moduleAttr = typeof rawEntrypoint === "string" ? (0, import_resolve.parsePyModuleAttrEntrypoint)(rawEntrypoint) : null;
24285
24380
  let normalizedEntrypoint;
@@ -24532,8 +24627,9 @@ var require_auto_detect = __commonJS({
24532
24627
  async function detectServicesAtRoot(fs5, rootFramework, detectEntrypoint) {
24533
24628
  const services = {};
24534
24629
  services.frontend = {
24630
+ root: ".",
24535
24631
  framework: rootFramework.slug ?? void 0,
24536
- routePrefix: "/"
24632
+ mountPath: "/"
24537
24633
  };
24538
24634
  const backendResult = await detectBackendServices(fs5, detectEntrypoint);
24539
24635
  if (backendResult.error) {
@@ -24551,9 +24647,10 @@ var require_auto_detect = __commonJS({
24551
24647
  };
24552
24648
  }
24553
24649
  Object.assign(services, backendResult.services);
24650
+ const mountWarnings = (0, import_utils.assignMountPaths)(services);
24554
24651
  return {
24555
24652
  services,
24556
- warnings: [],
24653
+ warnings: mountWarnings,
24557
24654
  errors: []
24558
24655
  };
24559
24656
  }
@@ -24563,7 +24660,7 @@ var require_auto_detect = __commonJS({
24563
24660
  services[serviceName] = {
24564
24661
  framework: frontendFramework.slug ?? void 0,
24565
24662
  root: frontendLocation,
24566
- routePrefix: "/"
24663
+ mountPath: "/"
24567
24664
  };
24568
24665
  const backendResult = await detectBackendServices(fs5, detectEntrypoint);
24569
24666
  if (backendResult.error) {
@@ -24586,9 +24683,10 @@ var require_auto_detect = __commonJS({
24586
24683
  };
24587
24684
  }
24588
24685
  Object.assign(services, backendResult.services);
24686
+ const mountWarnings = (0, import_utils.assignMountPaths)(services);
24589
24687
  return {
24590
24688
  services,
24591
- warnings: [],
24689
+ warnings: mountWarnings,
24592
24690
  errors: []
24593
24691
  };
24594
24692
  }
@@ -24683,14 +24781,14 @@ var require_auto_detect = __commonJS({
24683
24781
  }
24684
24782
  const framework = frameworks2[0];
24685
24783
  const slug = framework.slug ?? void 0;
24686
- const routePrefix = `/_/${serviceName}`;
24784
+ const mountPath = `/${serviceName}`;
24687
24785
  const detected = detectEntrypoint && !(0, import_utils.isFrontendFramework)(slug) ? await detectEntrypoint({ workPath: dirPath, framework: slug }) : null;
24688
24786
  return {
24689
24787
  service: {
24690
24788
  framework: slug,
24691
24789
  root: dirPath,
24692
24790
  ...detected ? { entrypoint: detected.entrypoint } : {},
24693
- routePrefix
24791
+ mountPath
24694
24792
  }
24695
24793
  };
24696
24794
  }
@@ -24822,18 +24920,17 @@ var require_detect_railway = __commonJS({
24822
24920
  }
24823
24921
  const framework = frameworks2[0];
24824
24922
  const slug = framework.slug ?? void 0;
24825
- let serviceConfig = {};
24826
- serviceConfig.framework = slug;
24827
- if (cf.dirPath !== ".") {
24828
- serviceConfig.root = cf.dirPath;
24829
- if (detectEntrypoint && !(0, import_utils.isFrontendFramework)(slug)) {
24830
- const detected = await detectEntrypoint({
24831
- workPath: cf.dirPath,
24832
- framework: slug
24833
- });
24834
- if (detected) {
24835
- serviceConfig.entrypoint = detected.entrypoint;
24836
- }
24923
+ const serviceConfig = {
24924
+ root: cf.dirPath,
24925
+ framework: slug
24926
+ };
24927
+ if (cf.dirPath !== "." && detectEntrypoint && !(0, import_utils.isFrontendFramework)(slug)) {
24928
+ const detected = await detectEntrypoint({
24929
+ workPath: cf.dirPath,
24930
+ framework: slug
24931
+ });
24932
+ if (detected) {
24933
+ serviceConfig.entrypoint = detected.entrypoint;
24837
24934
  }
24838
24935
  }
24839
24936
  if (cf.config.build?.buildCommand) {
@@ -24852,7 +24949,7 @@ var require_detect_railway = __commonJS({
24852
24949
  if (serviceNames.length === 0) {
24853
24950
  return { services: null, errors: [], warnings };
24854
24951
  }
24855
- warnings.push(...(0, import_utils.assignRoutePrefixes)(services));
24952
+ warnings.push(...(0, import_utils.assignMountPaths)(services));
24856
24953
  return { services, errors: [], warnings };
24857
24954
  }
24858
24955
  async function findRailwayConfigs(fs5, dirPath = ".", depth = 0) {
@@ -27919,7 +28016,7 @@ var require_detect_render = __commonJS({
27919
28016
  const name = rs.name ?? "unnamed";
27920
28017
  const hint = {
27921
28018
  entrypoint: rs.rootDir ?? "<path-to-entrypoint>",
27922
- routePrefix: `/_/${name}`
28019
+ mountPath: `/api/${name}`
27923
28020
  };
27924
28021
  warnings.push({
27925
28022
  code: "RENDER_PSERV_HINT",
@@ -27973,19 +28070,18 @@ var require_detect_render = __commonJS({
27973
28070
  }
27974
28071
  const framework = frameworks2[0];
27975
28072
  const vercelType = SERVICE_TYPE_MAP[serviceType];
27976
- const serviceConfig = {};
27977
- serviceConfig.type = vercelType;
27978
- serviceConfig.framework = framework.slug ?? void 0;
27979
- if (rootDir !== ".") {
27980
- serviceConfig.root = rootDir;
27981
- if (detectEntrypoint && !(0, import_utils.isFrontendFramework)(serviceConfig.framework)) {
27982
- const detected = await detectEntrypoint({
27983
- workPath: rootDir,
27984
- framework: serviceConfig.framework
27985
- });
27986
- if (detected) {
27987
- serviceConfig.entrypoint = detected.entrypoint;
27988
- }
28073
+ const serviceConfig = {
28074
+ root: rootDir,
28075
+ type: vercelType,
28076
+ framework: framework.slug ?? void 0
28077
+ };
28078
+ if (rootDir !== "." && detectEntrypoint && !(0, import_utils.isFrontendFramework)(serviceConfig.framework)) {
28079
+ const detected = await detectEntrypoint({
28080
+ workPath: rootDir,
28081
+ framework: serviceConfig.framework
28082
+ });
28083
+ if (detected) {
28084
+ serviceConfig.entrypoint = detected.entrypoint;
27989
28085
  }
27990
28086
  }
27991
28087
  const buildCommand = (0, import_utils.combineBuildCommand)(
@@ -28003,7 +28099,7 @@ var require_detect_render = __commonJS({
28003
28099
  if (Object.keys(services).length === 0) {
28004
28100
  return { services: null, errors: [], warnings };
28005
28101
  }
28006
- warnings.push(...(0, import_utils.assignRoutePrefixes)(services));
28102
+ warnings.push(...(0, import_utils.assignMountPaths)(services));
28007
28103
  return { services, errors: [], warnings };
28008
28104
  }
28009
28105
  async function readRenderYaml(fs5) {
@@ -28160,6 +28256,7 @@ var require_detect_procfile = __commonJS({
28160
28256
  if (isWorkerLikeProcess) {
28161
28257
  if (hasSupportedWorkerCommand(tokens) && entrypoint?.endsWith(".py")) {
28162
28258
  services[processType] = {
28259
+ root: ".",
28163
28260
  type: "worker",
28164
28261
  entrypoint,
28165
28262
  runtime: "python"
@@ -28176,12 +28273,12 @@ var require_detect_procfile = __commonJS({
28176
28273
  });
28177
28274
  continue;
28178
28275
  }
28179
- const serviceConfig = { type: "web" };
28180
- if (detectedFramework) {
28181
- serviceConfig.framework = detectedFramework.slug ?? void 0;
28182
- }
28183
- serviceConfig.entrypoint = entrypoint ?? ".";
28184
- services[processType] = serviceConfig;
28276
+ services[processType] = {
28277
+ root: ".",
28278
+ type: "web",
28279
+ ...detectedFramework?.slug ? { framework: detectedFramework.slug } : {},
28280
+ entrypoint: entrypoint ?? "."
28281
+ };
28185
28282
  }
28186
28283
  if (errors.length > 0) {
28187
28284
  return { services: null, errors, warnings };
@@ -28197,7 +28294,7 @@ var require_detect_procfile = __commonJS({
28197
28294
  firstService.buildCommand = releaseCommand;
28198
28295
  }
28199
28296
  }
28200
- warnings.push(...(0, import_utils.assignRoutePrefixes)(services));
28297
+ warnings.push(...(0, import_utils.assignMountPaths)(services));
28201
28298
  return { services, errors: [], warnings };
28202
28299
  }
28203
28300
  function parseProcfile(content) {
@@ -28314,6 +28411,7 @@ var require_detect_services = __commonJS({
28314
28411
  var detect_services_exports = {};
28315
28412
  __export2(detect_services_exports, {
28316
28413
  detectServices: () => detectServices2,
28414
+ generateServiceRewrites: () => generateServiceRewrites,
28317
28415
  generateServicesRoutes: () => generateServicesRoutes2
28318
28416
  });
28319
28417
  module2.exports = __toCommonJS2(detect_services_exports);
@@ -28346,6 +28444,7 @@ var require_detect_services = __commonJS({
28346
28444
  source: resolved.source,
28347
28445
  useImplicitEnvInjection: resolved.useImplicitEnvInjection,
28348
28446
  routes: resolved.routes,
28447
+ rewrites: resolved.rewrites,
28349
28448
  errors: resolved.errors,
28350
28449
  warnings: resolved.warnings,
28351
28450
  resolved,
@@ -28355,18 +28454,17 @@ var require_detect_services = __commonJS({
28355
28454
  function toInferredLayoutConfig(services) {
28356
28455
  const inferredConfig = {};
28357
28456
  for (const [name, service] of Object.entries(services)) {
28358
- const serviceConfig = {};
28457
+ const serviceConfig = {
28458
+ root: service.root
28459
+ };
28359
28460
  if (service.type) {
28360
28461
  serviceConfig.type = service.type;
28361
28462
  }
28362
- if (typeof service.root === "string") {
28363
- serviceConfig.root = service.root;
28364
- }
28365
28463
  if (typeof service.entrypoint === "string") {
28366
28464
  serviceConfig.entrypoint = service.entrypoint;
28367
28465
  }
28368
- if (typeof service.routePrefix === "string") {
28369
- serviceConfig.routePrefix = service.routePrefix;
28466
+ if (typeof service.mountPath === "string") {
28467
+ serviceConfig.mountPath = service.mountPath;
28370
28468
  }
28371
28469
  if ((0, import_utils.isFrontendFramework)(service.framework)) {
28372
28470
  serviceConfig.framework = service.framework;
@@ -28397,6 +28495,7 @@ var require_detect_services = __commonJS({
28397
28495
  source: "configured",
28398
28496
  useImplicitEnvInjection: true,
28399
28497
  routes: emptyRoutes(),
28498
+ rewrites: [],
28400
28499
  errors: [configError],
28401
28500
  warnings: []
28402
28501
  });
@@ -28407,6 +28506,7 @@ var require_detect_services = __commonJS({
28407
28506
  source: "configured",
28408
28507
  useImplicitEnvInjection: false,
28409
28508
  routes: emptyRoutes(),
28509
+ rewrites: [],
28410
28510
  errors: [
28411
28511
  {
28412
28512
  code: "SERVICES_AND_EXPERIMENTAL_SERVICES_V2",
@@ -28419,63 +28519,66 @@ var require_detect_services = __commonJS({
28419
28519
  const hasProvidedConfiguredServices = providedConfiguredServices && Object.keys(providedConfiguredServices).length > 0;
28420
28520
  const experimentalServicesV2 = hasProvidedConfiguredServices && (providedConfiguredServicesType === "services" || providedConfiguredServicesType === "experimentalServicesV2") ? providedConfiguredServices : hasProvidedConfiguredServices ? void 0 : vercelConfig?.services ?? vercelConfig?.experimentalServicesV2;
28421
28521
  if (experimentalServicesV2 && Object.keys(experimentalServicesV2).length > 0) {
28422
- const result2 = await (0, import_resolve_v2.resolveAllConfiguredServicesV2)(
28522
+ const result = await (0, import_resolve_v2.resolveAllConfiguredServicesV2)(
28423
28523
  experimentalServicesV2,
28424
28524
  scopedFs
28425
28525
  );
28426
28526
  return withResolvedResult({
28427
- services: result2.services,
28527
+ services: result.services,
28428
28528
  source: "configured",
28429
28529
  // V2 uses explicit `bindings`, so no implicit `{NAME}_URL` injection.
28430
28530
  useImplicitEnvInjection: false,
28431
28531
  // V2 routes are explicitly carried per-service to output them separately.
28432
28532
  routes: emptyRoutes(),
28433
- errors: result2.errors,
28533
+ rewrites: [],
28534
+ errors: result.errors,
28434
28535
  warnings: []
28435
28536
  });
28436
28537
  }
28437
28538
  const experimentalServicesV1 = hasProvidedConfiguredServices ? providedConfiguredServices : vercelConfig?.experimentalServices;
28438
28539
  const hasExperimentalServicesV1 = experimentalServicesV1 && Object.keys(experimentalServicesV1).length > 0;
28439
- if (!hasExperimentalServicesV1) {
28440
- const detectors = [
28441
- { detect: import_detect_railway.detectRailwayServices, source: "railway" },
28442
- { detect: import_detect_render.detectRenderServices, source: "render" },
28443
- { detect: import_detect_procfile.detectProcfileServices, source: "procfile" },
28444
- { detect: import_auto_detect.autoDetectServices, source: "layout" }
28445
- ];
28446
- for (const { detect, source } of detectors) {
28447
- const detectResult = await detect({ fs: scopedFs, detectEntrypoint });
28448
- const match = await tryResolveInferred(detectResult, source, scopedFs);
28449
- if (match)
28450
- return match;
28451
- }
28540
+ if (hasExperimentalServicesV1) {
28541
+ const result = await (0, import_resolve.resolveAllConfiguredServices)(
28542
+ experimentalServicesV1,
28543
+ scopedFs,
28544
+ "configured"
28545
+ );
28546
+ const routes = generateServicesRoutes2(result.services);
28452
28547
  return withResolvedResult({
28453
- services: [],
28454
- source: "auto-detected",
28548
+ services: result.services,
28549
+ source: "configured",
28550
+ // experimentalServices uses the legacy `{NAME}_URL` injection.
28455
28551
  useImplicitEnvInjection: true,
28456
- routes: emptyRoutes(),
28457
- errors: [
28458
- {
28459
- code: "NO_EXPERIMENTAL_SERVICES_CONFIGURED",
28460
- message: "No services configured. Add `experimentalServices` to vercel.json."
28461
- }
28462
- ],
28552
+ routes,
28553
+ rewrites: [],
28554
+ errors: result.errors,
28463
28555
  warnings: []
28464
28556
  });
28465
28557
  }
28466
- const result = await (0, import_resolve.resolveAllConfiguredServices)(
28467
- experimentalServicesV1,
28468
- scopedFs,
28469
- "configured"
28470
- );
28471
- const routes = generateServicesRoutes2(result.services);
28558
+ const detectors = [
28559
+ { detect: import_detect_railway.detectRailwayServices, source: "railway" },
28560
+ { detect: import_detect_render.detectRenderServices, source: "render" },
28561
+ { detect: import_detect_procfile.detectProcfileServices, source: "procfile" },
28562
+ { detect: import_auto_detect.autoDetectServices, source: "layout" }
28563
+ ];
28564
+ for (const { detect, source } of detectors) {
28565
+ const detectResult = await detect({ fs: scopedFs, detectEntrypoint });
28566
+ const match = await tryResolveInferred(detectResult, source, scopedFs);
28567
+ if (match)
28568
+ return match;
28569
+ }
28472
28570
  return withResolvedResult({
28473
- services: result.services,
28474
- source: "configured",
28475
- // experimentalServices uses the legacy `{NAME}_URL` injection.
28571
+ services: [],
28572
+ source: "auto-detected",
28476
28573
  useImplicitEnvInjection: true,
28477
- routes,
28478
- errors: result.errors,
28574
+ routes: emptyRoutes(),
28575
+ rewrites: [],
28576
+ errors: [
28577
+ {
28578
+ code: "NO_EXPERIMENTAL_SERVICES_CONFIGURED",
28579
+ message: "No services configured. Add `experimentalServices` to vercel.json."
28580
+ }
28581
+ ],
28479
28582
  warnings: []
28480
28583
  });
28481
28584
  }
@@ -28484,8 +28587,9 @@ var require_detect_services = __commonJS({
28484
28587
  return withResolvedResult({
28485
28588
  services: [],
28486
28589
  source: "auto-detected",
28487
- useImplicitEnvInjection: true,
28590
+ useImplicitEnvInjection: source !== "layout",
28488
28591
  routes: emptyRoutes(),
28592
+ rewrites: [],
28489
28593
  errors: detectResult.errors,
28490
28594
  warnings: detectResult.warnings
28491
28595
  });
@@ -28493,52 +28597,96 @@ var require_detect_services = __commonJS({
28493
28597
  if (!detectResult.services) {
28494
28598
  return null;
28495
28599
  }
28600
+ if (source === "layout") {
28601
+ const v2Services = {};
28602
+ for (const [name, svc] of Object.entries(detectResult.services)) {
28603
+ v2Services[name] = {
28604
+ root: svc.root,
28605
+ ...svc.framework ? { framework: svc.framework } : {},
28606
+ ...svc.entrypoint ? { entrypoint: svc.entrypoint } : {}
28607
+ };
28608
+ }
28609
+ const result2 = await (0, import_resolve_v2.resolveAllConfiguredServicesV2)(v2Services, scopedFs);
28610
+ const rootServices = Object.values(detectResult.services).filter(
28611
+ (svc) => svc.mountPath === "/" && typeof svc.framework === "string"
28612
+ );
28613
+ const shouldInfer2 = result2.errors.length === 0 && rootServices.length === 1 && result2.services.length > 1;
28614
+ const inferred2 = shouldInfer2 ? {
28615
+ source,
28616
+ config: toInferredLayoutConfig(detectResult.services),
28617
+ services: result2.services,
28618
+ warnings: detectResult.warnings
28619
+ } : null;
28620
+ return withResolvedResult(
28621
+ {
28622
+ services: shouldInfer2 ? result2.services : [],
28623
+ source: "auto-detected",
28624
+ useImplicitEnvInjection: false,
28625
+ routes: emptyRoutes(),
28626
+ rewrites: shouldInfer2 ? generateServiceRewrites(detectResult.services) : [],
28627
+ experimentalServicesV2: shouldInfer2 ? v2Services : void 0,
28628
+ errors: result2.errors,
28629
+ warnings: detectResult.warnings
28630
+ },
28631
+ inferred2
28632
+ );
28633
+ }
28634
+ const v1Services = {};
28635
+ for (const [name, svc] of Object.entries(detectResult.services)) {
28636
+ v1Services[name] = {
28637
+ root: svc.root === "." ? void 0 : svc.root,
28638
+ ...svc.framework ? { framework: svc.framework } : {},
28639
+ ...svc.entrypoint ? { entrypoint: svc.entrypoint } : {},
28640
+ ...svc.type ? { type: svc.type } : {},
28641
+ ...svc.buildCommand ? { buildCommand: svc.buildCommand } : {},
28642
+ ...svc.preDeployCommand ? { preDeployCommand: svc.preDeployCommand } : {},
28643
+ ...svc.mountPath ? { routePrefix: svc.mountPath } : {}
28644
+ };
28645
+ }
28496
28646
  const result = await (0, import_resolve.resolveAllConfiguredServices)(
28497
- detectResult.services,
28647
+ v1Services,
28498
28648
  scopedFs,
28499
28649
  "generated"
28500
28650
  );
28501
- let shouldInfer;
28502
- if (source === "layout") {
28503
- const rootWebFrameworkServices = result.services.filter(
28504
- (service) => service.type === "web" && service.routePrefix === "/" && typeof service.framework === "string"
28505
- );
28506
- shouldInfer = result.errors.length === 0 && rootWebFrameworkServices.length === 1 && result.services.length > 1;
28507
- } else {
28508
- shouldInfer = result.errors.length === 0 && result.services.length > 0;
28509
- }
28651
+ const shouldInfer = result.errors.length === 0 && result.services.length > 0;
28510
28652
  const inferred = shouldInfer ? {
28511
28653
  source,
28512
28654
  config: toInferredLayoutConfig(detectResult.services),
28513
28655
  services: result.services,
28514
28656
  warnings: detectResult.warnings
28515
28657
  } : null;
28516
- if (source === "layout" && shouldInfer) {
28517
- const routes = generateServicesRoutes2(result.services);
28518
- return withResolvedResult(
28519
- {
28520
- services: result.services,
28521
- source: "auto-detected",
28522
- useImplicitEnvInjection: true,
28523
- routes,
28524
- errors: result.errors,
28525
- warnings: detectResult.warnings
28526
- },
28527
- inferred
28528
- );
28529
- }
28530
28658
  return withResolvedResult(
28531
28659
  {
28532
28660
  services: [],
28533
28661
  source: "auto-detected",
28534
28662
  useImplicitEnvInjection: true,
28535
28663
  routes: emptyRoutes(),
28664
+ rewrites: [],
28536
28665
  errors: result.errors,
28537
28666
  warnings: detectResult.warnings
28538
28667
  },
28539
28668
  inferred
28540
28669
  );
28541
28670
  }
28671
+ function generateServiceRewrites(services) {
28672
+ const entries = Object.entries(services).filter(
28673
+ ([, svc]) => typeof svc.mountPath === "string" && (!svc.type || svc.type === "web")
28674
+ ).sort(([, a], [, b]) => b.mountPath.length - a.mountPath.length);
28675
+ return entries.map(([name, svc]) => {
28676
+ const mountPath = svc.mountPath;
28677
+ if (mountPath === "/") {
28678
+ return {
28679
+ source: "/(.*)",
28680
+ destination: { type: "service", service: name }
28681
+ };
28682
+ }
28683
+ const prefix = mountPath.startsWith("/") ? mountPath.slice(1) : mountPath;
28684
+ return {
28685
+ source: `/${prefix}(/.*)?`,
28686
+ destination: { type: "service", service: name }
28687
+ };
28688
+ });
28689
+ }
28542
28690
  function generateServicesRoutes2(allServices) {
28543
28691
  const services = allServices.filter(import_build_utils5.isExperimentalService);
28544
28692
  const hostRewrites = [];
@@ -28995,6 +29143,8 @@ var require_get_services_builders = __commonJS({
28995
29143
  ...result.routes.crons
28996
29144
  ] : null,
28997
29145
  errorRoutes: [],
29146
+ serviceRewrites: result.rewrites.length > 0 ? result.rewrites : void 0,
29147
+ experimentalServicesV2: result.experimentalServicesV2,
28998
29148
  services: result.services,
28999
29149
  useImplicitEnvInjection: result.useImplicitEnvInjection
29000
29150
  };
@@ -29606,7 +29756,7 @@ var require_detect_builders = __commonJS({
29606
29756
  }
29607
29757
  }
29608
29758
  }
29609
- if (frontendBuilder && ((0, import_is_official_runtime.isOfficialRuntime)("express", frontendBuilder.use) || (0, import_is_official_runtime.isOfficialRuntime)("hono", frontendBuilder.use) || (0, import_is_official_runtime.isOfficialRuntime)("backends", frontendBuilder.use))) {
29759
+ if (frontendBuilder && ((0, import_is_official_runtime.isOfficialRuntime)("express", frontendBuilder.use) || (0, import_is_official_runtime.isOfficialRuntime)("hono", frontendBuilder.use) || (0, import_is_official_runtime.isOfficialRuntime)("python", frontendBuilder.use) || (0, import_is_official_runtime.isOfficialRuntime)("backends", frontendBuilder.use))) {
29610
29760
  return null;
29611
29761
  }
29612
29762
  if (unusedFunctions.size) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/static-build",
3
- "version": "2.11.2",
3
+ "version": "2.11.4",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/build-step",
@@ -14,9 +14,9 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "ts-morph": "12.0.0",
17
- "@vercel/gatsby-plugin-vercel-analytics": "1.0.11",
18
17
  "@vercel/static-config": "3.4.0",
19
- "@vercel/gatsby-plugin-vercel-builder": "2.2.22"
18
+ "@vercel/gatsby-plugin-vercel-builder": "2.2.24",
19
+ "@vercel/gatsby-plugin-vercel-analytics": "1.0.11"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/aws-lambda": "8.10.64",
@@ -37,11 +37,11 @@
37
37
  "semver": "7.5.2",
38
38
  "tree-kill": "1.2.2",
39
39
  "vitest": "2.0.3",
40
- "@vercel/frameworks": "3.29.1",
41
40
  "@vercel/error-utils": "2.2.0",
42
- "@vercel/build-utils": "13.32.0",
43
- "@vercel/fs-detectors": "6.10.0",
44
- "@vercel/routing-utils": "6.3.1"
41
+ "@vercel/frameworks": "3.30.1",
42
+ "@vercel/build-utils": "13.32.2",
43
+ "@vercel/fs-detectors": "6.11.1",
44
+ "@vercel/routing-utils": "6.4.0"
45
45
  },
46
46
  "scripts": {
47
47
  "build": "node ../../utils/build-builder.mjs",