@vercel/static-build 2.9.24 → 2.9.25

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 +159 -29
  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 {
@@ -22801,6 +22857,11 @@ var require_resolve = __commonJS({
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
22859
  var ENV_PREFIX_RE = /^[A-Z][A-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
  }
@@ -23176,6 +23271,7 @@ var require_resolve = __commonJS({
23176
23271
  const hasFramework = Boolean(config.framework);
23177
23272
  const hasBuilderOrRuntime = Boolean(config.builder || config.runtime);
23178
23273
  const hasEntrypoint = Boolean(config.entrypoint);
23274
+ const entrypointRequiredRuntime = getEntrypointRequiredRuntime(config);
23179
23275
  if (!hasFramework && !hasBuilderOrRuntime && !hasEntrypoint) {
23180
23276
  return {
23181
23277
  code: "MISSING_SERVICE_CONFIG",
@@ -23183,6 +23279,13 @@ var require_resolve = __commonJS({
23183
23279
  serviceName: name
23184
23280
  };
23185
23281
  }
23282
+ if (options.requireFileEntrypointForBackendRuntimes && !hasEntrypoint && entrypointRequiredRuntime && ENTRYPOINT_REQUIRED_RUNTIMES.has(entrypointRequiredRuntime)) {
23283
+ return {
23284
+ code: "MISSING_ENTRYPOINT",
23285
+ message: `Service "${name}" must specify "entrypoint" when using "${config.runtime ? "runtime" : "framework"}" "${config.runtime || config.framework}".`,
23286
+ serviceName: name
23287
+ };
23288
+ }
23186
23289
  if (hasBuilderOrRuntime && !hasFramework && !hasEntrypoint) {
23187
23290
  return {
23188
23291
  code: "MISSING_ENTRYPOINT",
@@ -23220,7 +23323,7 @@ var require_resolve = __commonJS({
23220
23323
  routePrefixSource = "configured"
23221
23324
  } = options;
23222
23325
  const type = config.type || "web";
23223
- const trigger = type === "cron" ? "schedule" : type === "job" ? config.trigger : void 0;
23326
+ const trigger = getEffectiveServiceTrigger(config);
23224
23327
  const rawEntrypoint = config.entrypoint;
23225
23328
  const moduleAttrParsed = typeof rawEntrypoint === "string" ? parsePyModuleAttrEntrypoint(rawEntrypoint) : null;
23226
23329
  const routingResult = resolveServiceRoutingConfig(name, config);
@@ -23366,13 +23469,13 @@ var require_resolve = __commonJS({
23366
23469
  envPrefix: config.envPrefix
23367
23470
  };
23368
23471
  }
23369
- async function resolveAllConfiguredServices(services, fs5, routePrefixSource = "configured") {
23472
+ async function resolveAllConfiguredServices(services, fs5, routePrefixSource = "configured", options = {}) {
23370
23473
  const resolved = [];
23371
23474
  const errors = [];
23372
23475
  const webServicesByRoutePrefix = /* @__PURE__ */ new Map();
23373
23476
  for (const name of Object.keys(services)) {
23374
23477
  const serviceConfig = services[name];
23375
- const validationError = validateServiceConfig(name, serviceConfig);
23478
+ const validationError = validateServiceConfig(name, serviceConfig, options);
23376
23479
  if (validationError) {
23377
23480
  errors.push(validationError);
23378
23481
  continue;
@@ -23410,6 +23513,16 @@ var require_resolve = __commonJS({
23410
23513
  continue;
23411
23514
  }
23412
23515
  }
23516
+ const explicitBackendEntrypointError = validateBackendFileEntrypoint(
23517
+ name,
23518
+ serviceConfig,
23519
+ resolvedEntrypoint,
23520
+ options
23521
+ );
23522
+ if (explicitBackendEntrypointError) {
23523
+ errors.push(explicitBackendEntrypointError);
23524
+ continue;
23525
+ }
23413
23526
  let resolvedConfig = serviceConfig;
23414
23527
  if (!serviceConfig.framework && resolvedEntrypoint) {
23415
23528
  if (resolvedEntrypoint.isDirectory) {
@@ -23466,6 +23579,16 @@ var require_resolve = __commonJS({
23466
23579
  }
23467
23580
  }
23468
23581
  }
23582
+ const backendEntrypointError = validateBackendFileEntrypoint(
23583
+ name,
23584
+ resolvedConfig,
23585
+ resolvedEntrypoint,
23586
+ options
23587
+ );
23588
+ if (backendEntrypointError) {
23589
+ errors.push(backendEntrypointError);
23590
+ continue;
23591
+ }
23469
23592
  const service = await resolveConfiguredService({
23470
23593
  name,
23471
23594
  config: resolvedConfig,
@@ -23545,7 +23668,7 @@ var require_auto_detect = __commonJS({
23545
23668
  errors: [
23546
23669
  {
23547
23670
  code: "MULTIPLE_FRAMEWORKS_ROOT",
23548
- message: `Multiple frameworks detected at root: ${frameworkNames}. Use explicit experimentalServices config.`
23671
+ message: `Multiple frameworks detected at root: ${frameworkNames}. Use explicit services config.`
23549
23672
  }
23550
23673
  ]
23551
23674
  };
@@ -23570,7 +23693,7 @@ var require_auto_detect = __commonJS({
23570
23693
  errors: [
23571
23694
  {
23572
23695
  code: "MULTIPLE_FRAMEWORKS_SERVICE",
23573
- message: `Multiple frameworks detected in ${frontendLocation}/: ${frameworkNames}. Use explicit experimentalServices config.`
23696
+ message: `Multiple frameworks detected in ${frontendLocation}/: ${frameworkNames}. Use explicit services config.`
23574
23697
  }
23575
23698
  ]
23576
23699
  };
@@ -23588,7 +23711,7 @@ var require_auto_detect = __commonJS({
23588
23711
  errors: [
23589
23712
  {
23590
23713
  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/."
23714
+ message: "No services detected. Configure services in vercel.json or ensure a framework exists at project root, frontend/, or apps/web/."
23592
23715
  }
23593
23716
  ]
23594
23717
  };
@@ -23669,7 +23792,7 @@ var require_auto_detect = __commonJS({
23669
23792
  services: {},
23670
23793
  error: {
23671
23794
  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.`,
23795
+ 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
23796
  serviceName
23674
23797
  }
23675
23798
  };
@@ -23718,7 +23841,7 @@ var require_auto_detect = __commonJS({
23718
23841
  return {
23719
23842
  error: {
23720
23843
  code: "MULTIPLE_FRAMEWORKS_SERVICE",
23721
- message: `Multiple frameworks detected in ${dirPath}/: ${frameworkNames}. Use explicit experimentalServices config.`,
23844
+ message: `Multiple frameworks detected in ${dirPath}/: ${frameworkNames}. Use explicit services config.`,
23722
23845
  serviceName
23723
23846
  }
23724
23847
  };
@@ -23852,7 +23975,7 @@ var require_detect_railway = __commonJS({
23852
23975
  if (frameworks2.length === 0) {
23853
23976
  warnings.push({
23854
23977
  code: "SERVICE_SKIPPED",
23855
- message: `Skipped service in ${dirLabel}/: no framework detected. Configure it manually in experimentalServices.`
23978
+ message: `Skipped service in ${dirLabel}/: no framework detected. Configure it manually in services.`
23856
23979
  });
23857
23980
  continue;
23858
23981
  }
@@ -23860,7 +23983,7 @@ var require_detect_railway = __commonJS({
23860
23983
  const names = frameworks2.map((f) => f.name).join(", ");
23861
23984
  errors.push({
23862
23985
  code: "MULTIPLE_FRAMEWORKS_SERVICE",
23863
- message: `Multiple frameworks detected in ${dirLabel}/: ${names}. Use explicit experimentalServices config.`,
23986
+ message: `Multiple frameworks detected in ${dirLabel}/: ${names}. Use explicit services config.`,
23864
23987
  serviceName
23865
23988
  });
23866
23989
  continue;
@@ -24102,7 +24225,8 @@ var require_detect_services = __commonJS({
24102
24225
  warnings: []
24103
24226
  });
24104
24227
  }
24105
- const configuredServices = vercelConfig?.experimentalServices;
24228
+ const hasNonEmptyPublicServicesConfig = vercelConfig?.services && Object.keys(vercelConfig.services).length > 0;
24229
+ const configuredServices = hasNonEmptyPublicServicesConfig ? vercelConfig.services : vercelConfig?.experimentalServices;
24106
24230
  const hasConfiguredServices = configuredServices && Object.keys(configuredServices).length > 0;
24107
24231
  if (!hasConfiguredServices) {
24108
24232
  const railwayResult = await (0, import_detect_railway.detectRailwayServices)({ fs: scopedFs });
@@ -24179,7 +24303,7 @@ var require_detect_services = __commonJS({
24179
24303
  errors: [
24180
24304
  {
24181
24305
  code: "NO_SERVICES_CONFIGURED",
24182
- message: "No services configured. Add `experimentalServices` to vercel.json."
24306
+ message: "No services configured. Add `services` to vercel.json."
24183
24307
  }
24184
24308
  ],
24185
24309
  warnings: []
@@ -24188,7 +24312,12 @@ var require_detect_services = __commonJS({
24188
24312
  const result = await (0, import_resolve.resolveAllConfiguredServices)(
24189
24313
  configuredServices,
24190
24314
  scopedFs,
24191
- "configured"
24315
+ "configured",
24316
+ {
24317
+ requireFileEntrypointForBackendRuntimes: Boolean(
24318
+ hasNonEmptyPublicServicesConfig
24319
+ )
24320
+ }
24192
24321
  );
24193
24322
  const routes = generateServicesRoutes2(result.services);
24194
24323
  return withResolvedResult({
@@ -24616,7 +24745,7 @@ var require_get_services_builders = __commonJS({
24616
24745
  errors: [
24617
24746
  {
24618
24747
  code: "NO_SERVICES_CONFIGURED",
24619
- message: "No services configured. Add `experimentalServices` to vercel.json."
24748
+ message: "No services configured. Add `services` to vercel.json."
24620
24749
  }
24621
24750
  ],
24622
24751
  warnings: warningResponses,
@@ -24746,13 +24875,14 @@ var require_detect_builders = __commonJS({
24746
24875
  return publicBuilder ? publicBuilder.src.replace("/**/*", "") : null;
24747
24876
  }
24748
24877
  async function detectBuilders2(files, pkg, options = {}) {
24749
- const { experimentalServices: services, projectSettings = {} } = options;
24878
+ const { services, experimentalServices, projectSettings = {} } = options;
24750
24879
  const { framework } = projectSettings;
24751
- const hasServicesConfig = services != null && typeof services === "object";
24880
+ const configuredServices = services ?? experimentalServices;
24881
+ const hasServicesConfig = configuredServices != null && typeof configuredServices === "object";
24752
24882
  if (hasServicesConfig || framework === "services") {
24753
24883
  return (0, import_get_services_builders.getServicesBuilders)({
24754
24884
  workPath: options.workPath,
24755
- configuredServices: services,
24885
+ configuredServices,
24756
24886
  projectFramework: framework
24757
24887
  });
24758
24888
  }
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.25",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/build-step",
@@ -14,8 +14,8 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "ts-morph": "12.0.0",
17
+ "@vercel/gatsby-plugin-vercel-builder": "2.2.3",
17
18
  "@vercel/gatsby-plugin-vercel-analytics": "1.0.11",
18
- "@vercel/gatsby-plugin-vercel-builder": "2.2.2",
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.23.0",
41
41
  "@vercel/error-utils": "2.1.0",
42
- "@vercel/frameworks": "3.25.1",
43
- "@vercel/fs-detectors": "6.2.1",
42
+ "@vercel/frameworks": "3.26.0",
43
+ "@vercel/fs-detectors": "6.2.2",
44
44
  "@vercel/routing-utils": "6.2.0"
45
45
  },
46
46
  "scripts": {