@vercel/build-utils 13.2.11 → 13.2.13

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @vercel/build-utils
2
2
 
3
+ ## 13.2.13
4
+
5
+ ### Patch Changes
6
+
7
+ - [python] experimental python runtime framework preset ([#14646](https://github.com/vercel/vercel/pull/14646))
8
+
9
+ ## 13.2.12
10
+
11
+ ### Patch Changes
12
+
13
+ - Add `findPackageJson` function for optimized package.json lookup without lockfile scanning. This improves `getNodeVersion` performance by avoiding unnecessary lockfile parsing. ([#14658](https://github.com/vercel/vercel/pull/14658))
14
+
3
15
  ## 13.2.10
4
16
 
5
17
  ### Patch Changes
@@ -3,12 +3,16 @@ import { Builder } from '.';
3
3
  * List of backend frameworks supported by the experimental backends feature
4
4
  */
5
5
  export declare const BACKEND_FRAMEWORKS: readonly ["express", "hono", "h3", "koa", "nestjs", "fastify", "elysia"];
6
+ export declare const PYTHON_FRAMEWORKS: readonly ["fastapi", "flask", "python"];
7
+ export declare const RUNTIME_FRAMEWORKS: readonly ["python"];
6
8
  export declare const BACKEND_BUILDERS: readonly ["@vercel/express", "@vercel/hono", "@vercel/h3", "@vercel/koa", "@vercel/nestjs", "@vercel/fastify", "@vercel/elysia"];
7
9
  export type BackendFramework = (typeof BACKEND_FRAMEWORKS)[number];
10
+ export type PythonFramework = (typeof PYTHON_FRAMEWORKS)[number];
8
11
  /**
9
12
  * Checks if the given framework is a backend framework
10
13
  */
11
14
  export declare function isBackendFramework(framework: string | null | undefined): framework is BackendFramework;
15
+ export declare function isPythonFramework(framework: string | null | undefined): framework is (typeof PYTHON_FRAMEWORKS)[number];
12
16
  export declare function isExperimentalBackendsWithoutIntrospectionEnabled(): boolean;
13
17
  export declare function isExperimentalBackendsEnabled(): boolean;
14
18
  export declare function isBackendBuilder(builder: Builder | null | undefined): boolean;
@@ -20,10 +20,13 @@ var framework_helpers_exports = {};
20
20
  __export(framework_helpers_exports, {
21
21
  BACKEND_BUILDERS: () => BACKEND_BUILDERS,
22
22
  BACKEND_FRAMEWORKS: () => BACKEND_FRAMEWORKS,
23
+ PYTHON_FRAMEWORKS: () => PYTHON_FRAMEWORKS,
24
+ RUNTIME_FRAMEWORKS: () => RUNTIME_FRAMEWORKS,
23
25
  isBackendBuilder: () => isBackendBuilder,
24
26
  isBackendFramework: () => isBackendFramework,
25
27
  isExperimentalBackendsEnabled: () => isExperimentalBackendsEnabled,
26
28
  isExperimentalBackendsWithoutIntrospectionEnabled: () => isExperimentalBackendsWithoutIntrospectionEnabled,
29
+ isPythonFramework: () => isPythonFramework,
27
30
  shouldUseExperimentalBackends: () => shouldUseExperimentalBackends
28
31
  });
29
32
  module.exports = __toCommonJS(framework_helpers_exports);
@@ -36,6 +39,13 @@ const BACKEND_FRAMEWORKS = [
36
39
  "fastify",
37
40
  "elysia"
38
41
  ];
42
+ const PYTHON_FRAMEWORKS = [
43
+ "fastapi",
44
+ "flask",
45
+ "python"
46
+ // Generic Python framework preset
47
+ ];
48
+ const RUNTIME_FRAMEWORKS = ["python"];
39
49
  const BACKEND_BUILDERS = [
40
50
  "@vercel/express",
41
51
  "@vercel/hono",
@@ -50,6 +60,11 @@ function isBackendFramework(framework) {
50
60
  return false;
51
61
  return BACKEND_FRAMEWORKS.includes(framework);
52
62
  }
63
+ function isPythonFramework(framework) {
64
+ if (!framework)
65
+ return false;
66
+ return PYTHON_FRAMEWORKS.includes(framework);
67
+ }
53
68
  function isExperimentalBackendsWithoutIntrospectionEnabled() {
54
69
  return process.env.VERCEL_BACKENDS_BUILDS === "1";
55
70
  }
@@ -70,9 +85,12 @@ function shouldUseExperimentalBackends(framework) {
70
85
  0 && (module.exports = {
71
86
  BACKEND_BUILDERS,
72
87
  BACKEND_FRAMEWORKS,
88
+ PYTHON_FRAMEWORKS,
89
+ RUNTIME_FRAMEWORKS,
73
90
  isBackendBuilder,
74
91
  isBackendFramework,
75
92
  isExperimentalBackendsEnabled,
76
93
  isExperimentalBackendsWithoutIntrospectionEnabled,
94
+ isPythonFramework,
77
95
  shouldUseExperimentalBackends
78
96
  });
@@ -2,11 +2,7 @@
2
2
  import { SpawnOptions } from 'child_process';
3
3
  import { Meta, PackageJson, NodeVersion, Config, BunVersion } from '../types';
4
4
  export type CliType = 'yarn' | 'npm' | 'pnpm' | 'bun' | 'vlt';
5
- export interface ScanParentDirsResult {
6
- /**
7
- * "yarn", "npm", or "pnpm" depending on the presence of lockfiles.
8
- */
9
- cliType: CliType;
5
+ export interface FindPackageJsonResult {
10
6
  /**
11
7
  * The file path of found `package.json` file, or `undefined` if not found.
12
8
  */
@@ -16,6 +12,12 @@ export interface ScanParentDirsResult {
16
12
  * option is enabled.
17
13
  */
18
14
  packageJson?: PackageJson;
15
+ }
16
+ export interface ScanParentDirsResult extends FindPackageJsonResult {
17
+ /**
18
+ * "yarn", "npm", or "pnpm" depending on the presence of lockfiles.
19
+ */
20
+ cliType: CliType;
19
21
  /**
20
22
  * The file path of the lockfile (`yarn.lock`, `package-lock.json`, or `pnpm-lock.yaml`)
21
23
  * or `undefined` if not found.
@@ -91,6 +93,12 @@ export declare function runShellScript(fsPath: string, args?: string[], spawnOpt
91
93
  */
92
94
  export declare function getSpawnOptions(meta: Meta, nodeVersion: NodeVersion): SpawnOptions;
93
95
  export declare function getNodeVersion(destPath: string, fallbackVersion?: string | undefined, config?: Config, meta?: Meta, availableVersions?: number[]): Promise<NodeVersion | BunVersion>;
96
+ /**
97
+ * Traverses up directories to find and optionally read package.json.
98
+ * This is a lightweight alternative to `scanParentDirs` when only
99
+ * package.json information is needed (without lockfile detection).
100
+ */
101
+ export declare function findPackageJson(destPath: string, readPackageJson?: boolean, base?: string): Promise<FindPackageJsonResult>;
94
102
  export declare function scanParentDirs(destPath: string, readPackageJson?: boolean, base?: string): Promise<ScanParentDirsResult>;
95
103
  export declare function turboVersionSpecifierSupportsCorepack(turboVersionSpecifier: string): boolean;
96
104
  export declare function usingCorepack(env: {
@@ -31,6 +31,7 @@ __export(run_user_scripts_exports, {
31
31
  PNPM_10_PREFERRED_AT: () => PNPM_10_PREFERRED_AT,
32
32
  detectPackageManager: () => detectPackageManager,
33
33
  execCommand: () => execCommand,
34
+ findPackageJson: () => findPackageJson,
34
35
  getEnvForPackageManager: () => getEnvForPackageManager,
35
36
  getNodeBinPath: () => getNodeBinPath,
36
37
  getNodeBinPaths: () => getNodeBinPaths,
@@ -212,7 +213,7 @@ async function getNodeVersion(destPath, fallbackVersion = process.env.VERCEL_PRO
212
213
  latestVersion.runtime = "nodejs";
213
214
  return latestVersion;
214
215
  }
215
- const { packageJson } = await scanParentDirs(destPath, true);
216
+ const { packageJson } = await findPackageJson(destPath, true);
216
217
  const configuredVersion = config.nodeVersion || fallbackVersion;
217
218
  const packageJsonVersion = packageJson?.engines?.node;
218
219
  const supportedNodeVersion = await (0, import_node_version.getSupportedNodeVersion)(
@@ -239,7 +240,7 @@ async function getNodeVersion(destPath, fallbackVersion = process.env.VERCEL_PRO
239
240
  }
240
241
  return supportedNodeVersion;
241
242
  }
242
- async function scanParentDirs(destPath, readPackageJson = false, base = "/") {
243
+ async function findPackageJson(destPath, readPackageJson = false, base = "/") {
243
244
  (0, import_assert.default)(import_path.default.isAbsolute(destPath));
244
245
  const pkgJsonPath = await walkParentDirs({
245
246
  base,
@@ -256,6 +257,18 @@ async function scanParentDirs(destPath, readPackageJson = false, base = "/") {
256
257
  );
257
258
  }
258
259
  }
260
+ return {
261
+ packageJsonPath: pkgJsonPath || void 0,
262
+ packageJson
263
+ };
264
+ }
265
+ async function scanParentDirs(destPath, readPackageJson = false, base = "/") {
266
+ (0, import_assert.default)(import_path.default.isAbsolute(destPath));
267
+ const { packageJsonPath: pkgJsonPath, packageJson } = await findPackageJson(
268
+ destPath,
269
+ readPackageJson,
270
+ base
271
+ );
259
272
  const {
260
273
  paths: [
261
274
  yarnLockPath,
@@ -1089,6 +1102,7 @@ const installDependencies = (0, import_util.deprecate)(
1089
1102
  PNPM_10_PREFERRED_AT,
1090
1103
  detectPackageManager,
1091
1104
  execCommand,
1105
+ findPackageJson,
1092
1106
  getEnvForPackageManager,
1093
1107
  getNodeBinPath,
1094
1108
  getNodeBinPaths,
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ import download, { downloadFile, DownloadedFiles, isSymbolicLink, isDirectory }
8
8
  import getWriteableDirectory from './fs/get-writable-directory';
9
9
  import glob, { GlobOptions } from './fs/glob';
10
10
  import rename from './fs/rename';
11
- import { spawnAsync, execCommand, spawnCommand, walkParentDirs, getScriptName, installDependencies, runPackageJsonScript, runNpmInstall, runBundleInstall, runPipInstall, runShellScript, runCustomInstallCommand, resetCustomInstallCommandSet, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, detectPackageManager, getSpawnOptions, getNodeBinPath, getNodeBinPaths, scanParentDirs, traverseUpDirectories } from './fs/run-user-scripts';
11
+ import { spawnAsync, execCommand, spawnCommand, walkParentDirs, getScriptName, installDependencies, runPackageJsonScript, runNpmInstall, runBundleInstall, runPipInstall, runShellScript, runCustomInstallCommand, resetCustomInstallCommandSet, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, detectPackageManager, getSpawnOptions, getNodeBinPath, getNodeBinPaths, scanParentDirs, findPackageJson, traverseUpDirectories } from './fs/run-user-scripts';
12
12
  import { getLatestNodeVersion, getDiscontinuedNodeVersions, getSupportedNodeVersion, isBunVersion, getSupportedBunVersion } from './fs/node-version';
13
13
  import streamToBuffer, { streamToBufferChunks } from './fs/stream-to-buffer';
14
14
  import debug from './debug';
@@ -18,7 +18,7 @@ import { getPrefixedEnvVars } from './get-prefixed-env-vars';
18
18
  import { cloneEnv } from './clone-env';
19
19
  import { hardLinkDir } from './hard-link-dir';
20
20
  import { validateNpmrc } from './validate-npmrc';
21
- export { FileBlob, FileFsRef, FileRef, Lambda, NodejsLambda, createLambda, Prerender, download, downloadFile, DownloadedFiles, getWriteableDirectory, glob, GlobOptions, rename, spawnAsync, getScriptName, installDependencies, runPackageJsonScript, execCommand, spawnCommand, walkParentDirs, getNodeBinPath, getNodeBinPaths, getSupportedNodeVersion, isBunVersion, getSupportedBunVersion, detectPackageManager, runNpmInstall, runBundleInstall, runPipInstall, runShellScript, runCustomInstallCommand, resetCustomInstallCommandSet, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, getLatestNodeVersion, getDiscontinuedNodeVersions, getSpawnOptions, getPlatformEnv, getPrefixedEnvVars, streamToBuffer, streamToBufferChunks, debug, isSymbolicLink, isDirectory, getLambdaOptionsFromFunction, scanParentDirs, getIgnoreFilter, cloneEnv, hardLinkDir, traverseUpDirectories, validateNpmrc, };
21
+ export { FileBlob, FileFsRef, FileRef, Lambda, NodejsLambda, createLambda, Prerender, download, downloadFile, DownloadedFiles, getWriteableDirectory, glob, GlobOptions, rename, spawnAsync, getScriptName, installDependencies, runPackageJsonScript, execCommand, spawnCommand, walkParentDirs, getNodeBinPath, getNodeBinPaths, getSupportedNodeVersion, isBunVersion, getSupportedBunVersion, detectPackageManager, runNpmInstall, runBundleInstall, runPipInstall, runShellScript, runCustomInstallCommand, resetCustomInstallCommandSet, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, getLatestNodeVersion, getDiscontinuedNodeVersions, getSpawnOptions, getPlatformEnv, getPrefixedEnvVars, streamToBuffer, streamToBufferChunks, debug, isSymbolicLink, isDirectory, getLambdaOptionsFromFunction, scanParentDirs, findPackageJson, getIgnoreFilter, cloneEnv, hardLinkDir, traverseUpDirectories, validateNpmrc, };
22
22
  export { EdgeFunction } from './edge-function';
23
23
  export { readConfigFile, getPackageJson } from './fs/read-config-file';
24
24
  export { normalizePath } from './fs/normalize-path';
@@ -32,5 +32,5 @@ export { NODE_VERSIONS } from './fs/node-version';
32
32
  export { getInstalledPackageVersion } from './get-installed-package-version';
33
33
  export { defaultCachePathGlob } from './default-cache-path-glob';
34
34
  export { generateNodeBuilderFunctions } from './generate-node-builder-functions';
35
- export { BACKEND_FRAMEWORKS, BackendFramework, isBackendFramework, isBackendBuilder, isExperimentalBackendsEnabled, isExperimentalBackendsWithoutIntrospectionEnabled, shouldUseExperimentalBackends, } from './framework-helpers';
35
+ export { BACKEND_FRAMEWORKS, BackendFramework, isBackendFramework, isBackendBuilder, isExperimentalBackendsEnabled, isExperimentalBackendsWithoutIntrospectionEnabled, shouldUseExperimentalBackends, PYTHON_FRAMEWORKS, PythonFramework, isPythonFramework, } from './framework-helpers';
36
36
  export * from './python';
package/dist/index.js CHANGED
@@ -23728,6 +23728,7 @@ __export(src_exports, {
23728
23728
  NodeVersion: () => NodeVersion,
23729
23729
  NodejsLambda: () => NodejsLambda,
23730
23730
  NowBuildError: () => NowBuildError,
23731
+ PYTHON_FRAMEWORKS: () => PYTHON_FRAMEWORKS,
23731
23732
  Prerender: () => Prerender,
23732
23733
  Span: () => Span,
23733
23734
  Version: () => Version,
@@ -23740,6 +23741,7 @@ __export(src_exports, {
23740
23741
  download: () => download,
23741
23742
  downloadFile: () => downloadFile,
23742
23743
  execCommand: () => execCommand,
23744
+ findPackageJson: () => findPackageJson,
23743
23745
  functionsSchema: () => functionsSchema,
23744
23746
  generateNodeBuilderFunctions: () => generateNodeBuilderFunctions,
23745
23747
  getDiscontinuedNodeVersions: () => getDiscontinuedNodeVersions,
@@ -23773,6 +23775,7 @@ __export(src_exports, {
23773
23775
  isExperimentalBackendsEnabled: () => isExperimentalBackendsEnabled,
23774
23776
  isExperimentalBackendsWithoutIntrospectionEnabled: () => isExperimentalBackendsWithoutIntrospectionEnabled,
23775
23777
  isPythonEntrypoint: () => isPythonEntrypoint,
23778
+ isPythonFramework: () => isPythonFramework,
23776
23779
  isSymbolicLink: () => isSymbolicLink,
23777
23780
  normalizePath: () => normalizePath,
23778
23781
  readConfigFile: () => readConfigFile,
@@ -25251,7 +25254,7 @@ async function getNodeVersion(destPath, fallbackVersion = process.env.VERCEL_PRO
25251
25254
  latestVersion.runtime = "nodejs";
25252
25255
  return latestVersion;
25253
25256
  }
25254
- const { packageJson } = await scanParentDirs(destPath, true);
25257
+ const { packageJson } = await findPackageJson(destPath, true);
25255
25258
  const configuredVersion = config.nodeVersion || fallbackVersion;
25256
25259
  const packageJsonVersion = packageJson?.engines?.node;
25257
25260
  const supportedNodeVersion = await getSupportedNodeVersion(
@@ -25278,7 +25281,7 @@ async function getNodeVersion(destPath, fallbackVersion = process.env.VERCEL_PRO
25278
25281
  }
25279
25282
  return supportedNodeVersion;
25280
25283
  }
25281
- async function scanParentDirs(destPath, readPackageJson = false, base = "/") {
25284
+ async function findPackageJson(destPath, readPackageJson = false, base = "/") {
25282
25285
  (0, import_assert6.default)(import_path6.default.isAbsolute(destPath));
25283
25286
  const pkgJsonPath = await walkParentDirs({
25284
25287
  base,
@@ -25295,6 +25298,18 @@ async function scanParentDirs(destPath, readPackageJson = false, base = "/") {
25295
25298
  );
25296
25299
  }
25297
25300
  }
25301
+ return {
25302
+ packageJsonPath: pkgJsonPath || void 0,
25303
+ packageJson
25304
+ };
25305
+ }
25306
+ async function scanParentDirs(destPath, readPackageJson = false, base = "/") {
25307
+ (0, import_assert6.default)(import_path6.default.isAbsolute(destPath));
25308
+ const { packageJsonPath: pkgJsonPath, packageJson } = await findPackageJson(
25309
+ destPath,
25310
+ readPackageJson,
25311
+ base
25312
+ );
25298
25313
  const {
25299
25314
  paths: [
25300
25315
  yarnLockPath,
@@ -26732,6 +26747,12 @@ var BACKEND_FRAMEWORKS = [
26732
26747
  "fastify",
26733
26748
  "elysia"
26734
26749
  ];
26750
+ var PYTHON_FRAMEWORKS = [
26751
+ "fastapi",
26752
+ "flask",
26753
+ "python"
26754
+ // Generic Python framework preset
26755
+ ];
26735
26756
  var BACKEND_BUILDERS = [
26736
26757
  "@vercel/express",
26737
26758
  "@vercel/hono",
@@ -26746,6 +26767,11 @@ function isBackendFramework(framework) {
26746
26767
  return false;
26747
26768
  return BACKEND_FRAMEWORKS.includes(framework);
26748
26769
  }
26770
+ function isPythonFramework(framework) {
26771
+ if (!framework)
26772
+ return false;
26773
+ return PYTHON_FRAMEWORKS.includes(framework);
26774
+ }
26749
26775
  function isExperimentalBackendsWithoutIntrospectionEnabled() {
26750
26776
  return process.env.VERCEL_BACKENDS_BUILDS === "1";
26751
26777
  }
@@ -26824,6 +26850,7 @@ async function isPythonEntrypoint(file) {
26824
26850
  NodeVersion,
26825
26851
  NodejsLambda,
26826
26852
  NowBuildError,
26853
+ PYTHON_FRAMEWORKS,
26827
26854
  Prerender,
26828
26855
  Span,
26829
26856
  Version,
@@ -26836,6 +26863,7 @@ async function isPythonEntrypoint(file) {
26836
26863
  download,
26837
26864
  downloadFile,
26838
26865
  execCommand,
26866
+ findPackageJson,
26839
26867
  functionsSchema,
26840
26868
  generateNodeBuilderFunctions,
26841
26869
  getDiscontinuedNodeVersions,
@@ -26869,6 +26897,7 @@ async function isPythonEntrypoint(file) {
26869
26897
  isExperimentalBackendsEnabled,
26870
26898
  isExperimentalBackendsWithoutIntrospectionEnabled,
26871
26899
  isPythonEntrypoint,
26900
+ isPythonFramework,
26872
26901
  isSymbolicLink,
26873
26902
  normalizePath,
26874
26903
  readConfigFile,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/build-utils",
3
- "version": "13.2.11",
3
+ "version": "13.2.13",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.js",