@vercel/build-utils 13.8.2 → 13.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @vercel/build-utils
2
2
 
3
+ ## 13.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [services] support multiple topics for a single worker service ([#15615](https://github.com/vercel/vercel/pull/15615))
8
+
9
+ - [services] support for specifying an env prefix for each service ([#15641](https://github.com/vercel/vercel/pull/15641))
10
+
11
+ - Simplify python runtime by always passing in app variable ([#15635](https://github.com/vercel/vercel/pull/15635))
12
+
13
+ ### Patch Changes
14
+
15
+ - Namespace diagnostics keys by builder and service workspace, and aggregate per-builder `package-manifest.json` files into a single `project-manifest.json` ([#15399](https://github.com/vercel/vercel/pull/15399))
16
+
17
+ - Updated dependencies [[`ac87d5a5ef5d79b55765e094efc957de987d7ac4`](https://github.com/vercel/vercel/commit/ac87d5a5ef5d79b55765e094efc957de987d7ac4), [`25a6a2daa46baba6e8d7dec90eb49213b8150b8c`](https://github.com/vercel/vercel/commit/25a6a2daa46baba6e8d7dec90eb49213b8150b8c)]:
18
+ - @vercel/python-analysis@0.11.0
19
+
20
+ ## 13.9.0
21
+
22
+ ### Minor Changes
23
+
24
+ - Ensure django static files are copied in build output. ([#15557](https://github.com/vercel/vercel/pull/15557))
25
+
3
26
  ## 13.8.2
4
27
 
5
28
  ### Patch Changes
@@ -12,6 +12,7 @@ export interface GetServiceUrlEnvVarsOptions {
12
12
  currentEnv?: Envs;
13
13
  deploymentUrl?: string;
14
14
  origin?: string;
15
+ envPrefix?: string;
15
16
  }
16
17
  /**
17
18
  * Generate environment variables for service URLs.
@@ -48,7 +48,8 @@ function getServiceUrlEnvVars(options) {
48
48
  frameworkList,
49
49
  currentEnv = {},
50
50
  deploymentUrl,
51
- origin
51
+ origin,
52
+ envPrefix
52
53
  } = options;
53
54
  const baseUrl = origin || deploymentUrl;
54
55
  if (!baseUrl || !services || services.length === 0) {
@@ -72,11 +73,12 @@ function getServiceUrlEnvVars(options) {
72
73
  service.routePrefix,
73
74
  !!origin
74
75
  );
75
- if (!(baseEnvVarName in currentEnv)) {
76
- envVars[baseEnvVarName] = absoluteUrl;
76
+ const effectiveBaseEnvVarName = envPrefix ? `${envPrefix}${baseEnvVarName}` : baseEnvVarName;
77
+ if (!(effectiveBaseEnvVarName in currentEnv)) {
78
+ envVars[effectiveBaseEnvVarName] = absoluteUrl;
77
79
  }
78
80
  for (const prefix of frameworkPrefixes) {
79
- const prefixedEnvVarName = `${prefix}${baseEnvVarName}`;
81
+ const prefixedEnvVarName = envPrefix ? `${prefix}${envPrefix}${baseEnvVarName}` : `${prefix}${baseEnvVarName}`;
80
82
  if (!(prefixedEnvVarName in currentEnv)) {
81
83
  envVars[prefixedEnvVarName] = service.routePrefix;
82
84
  }
package/dist/index.js CHANGED
@@ -21869,6 +21869,7 @@ __export(src_exports, {
21869
21869
  getSpawnOptions: () => getSpawnOptions,
21870
21870
  getSupportedBunVersion: () => getSupportedBunVersion,
21871
21871
  getSupportedNodeVersion: () => getSupportedNodeVersion,
21872
+ getWorkerTopics: () => getWorkerTopics,
21872
21873
  getWriteableDirectory: () => getWritableDirectory,
21873
21874
  glob: () => glob,
21874
21875
  hardLinkDir: () => hardLinkDir,
@@ -21884,6 +21885,7 @@ __export(src_exports, {
21884
21885
  isPythonFramework: () => isPythonFramework,
21885
21886
  isSymbolicLink: () => isSymbolicLink,
21886
21887
  normalizePath: () => normalizePath,
21888
+ packageManifestSchema: () => packageManifestSchema,
21887
21889
  readConfigFile: () => readConfigFile,
21888
21890
  rename: () => rename,
21889
21891
  resetCustomInstallCommandSet: () => resetCustomInstallCommandSet,
@@ -23078,6 +23080,9 @@ var NodeVersion = class extends Version {
23078
23080
  };
23079
23081
  var BunVersion = class extends Version {
23080
23082
  };
23083
+ function getWorkerTopics(config) {
23084
+ return config.topics?.length ? config.topics : ["default"];
23085
+ }
23081
23086
 
23082
23087
  // src/fs/node-version.ts
23083
23088
  var NODE_VERSIONS = [
@@ -24482,7 +24487,8 @@ function getServiceUrlEnvVars(options) {
24482
24487
  frameworkList,
24483
24488
  currentEnv = {},
24484
24489
  deploymentUrl,
24485
- origin
24490
+ origin,
24491
+ envPrefix
24486
24492
  } = options;
24487
24493
  const baseUrl = origin || deploymentUrl;
24488
24494
  if (!baseUrl || !services || services.length === 0) {
@@ -24506,11 +24512,12 @@ function getServiceUrlEnvVars(options) {
24506
24512
  service.routePrefix,
24507
24513
  !!origin
24508
24514
  );
24509
- if (!(baseEnvVarName in currentEnv)) {
24510
- envVars[baseEnvVarName] = absoluteUrl;
24515
+ const effectiveBaseEnvVarName = envPrefix ? `${envPrefix}${baseEnvVarName}` : baseEnvVarName;
24516
+ if (!(effectiveBaseEnvVarName in currentEnv)) {
24517
+ envVars[effectiveBaseEnvVarName] = absoluteUrl;
24511
24518
  }
24512
24519
  for (const prefix of frameworkPrefixes) {
24513
- const prefixedEnvVarName = `${prefix}${baseEnvVarName}`;
24520
+ const prefixedEnvVarName = envPrefix ? `${prefix}${envPrefix}${baseEnvVarName}` : `${prefix}${baseEnvVarName}`;
24514
24521
  if (!(prefixedEnvVarName in currentEnv)) {
24515
24522
  envVars[prefixedEnvVarName] = service.routePrefix;
24516
24523
  }
@@ -24826,6 +24833,73 @@ var buildsSchema = {
24826
24833
  }
24827
24834
  }
24828
24835
  };
24836
+ var packageManifestSchema = {
24837
+ type: "object",
24838
+ required: ["runtime", "dependencies"],
24839
+ additionalProperties: false,
24840
+ properties: {
24841
+ version: {
24842
+ type: "string",
24843
+ description: 'Manifest schema version, e.g. "20260304".'
24844
+ },
24845
+ runtime: {
24846
+ type: "string",
24847
+ description: 'Runtime identifier, e.g. "python", "node".'
24848
+ },
24849
+ runtimeVersion: {
24850
+ type: "object",
24851
+ additionalProperties: false,
24852
+ required: ["resolved"],
24853
+ properties: {
24854
+ requested: {
24855
+ type: "string",
24856
+ description: 'Version constraint from the project manifest, e.g. ">=3.10".'
24857
+ },
24858
+ requestedSource: {
24859
+ type: "string",
24860
+ description: 'File that declared the constraint, e.g. "pyproject.toml".'
24861
+ },
24862
+ resolved: {
24863
+ type: "string",
24864
+ description: 'Actual resolved version, e.g. "3.12".'
24865
+ }
24866
+ }
24867
+ },
24868
+ dependencies: {
24869
+ type: "array",
24870
+ items: {
24871
+ type: "object",
24872
+ required: ["name", "type", "scopes", "resolved"],
24873
+ additionalProperties: false,
24874
+ properties: {
24875
+ name: { type: "string" },
24876
+ type: { type: "string", enum: ["direct", "transitive", "peer"] },
24877
+ scopes: {
24878
+ type: "array",
24879
+ items: { type: "string" },
24880
+ description: 'Dependency groups this package belongs to, e.g. ["main", "dev"].'
24881
+ },
24882
+ requested: {
24883
+ type: "string",
24884
+ description: 'Version specifier as declared, e.g. "flask>=2.0".'
24885
+ },
24886
+ resolved: {
24887
+ type: "string",
24888
+ description: 'Resolved version, e.g. "3.1.0".'
24889
+ },
24890
+ source: {
24891
+ type: "string",
24892
+ description: 'Package source type, e.g. "registry", "git", "path".'
24893
+ },
24894
+ sourceUrl: {
24895
+ type: "string",
24896
+ description: 'Source URL, e.g. "https://pypi.org".'
24897
+ }
24898
+ }
24899
+ }
24900
+ }
24901
+ }
24902
+ };
24829
24903
 
24830
24904
  // src/trace/trace.ts
24831
24905
  var import_node_crypto = require("crypto");
@@ -25150,7 +25224,7 @@ async function isPythonEntrypoint(file) {
25150
25224
  if (!fsPath)
25151
25225
  return false;
25152
25226
  const content = await import_fs3.default.promises.readFile(fsPath, "utf-8");
25153
- return await (0, import_python_analysis.containsAppOrHandler)(content);
25227
+ return await (0, import_python_analysis.findAppOrHandler)(content) !== null;
25154
25228
  } catch (err) {
25155
25229
  debug(`Failed to check Python entrypoint: ${err}`);
25156
25230
  return false;
@@ -25210,6 +25284,7 @@ async function isPythonEntrypoint(file) {
25210
25284
  getSpawnOptions,
25211
25285
  getSupportedBunVersion,
25212
25286
  getSupportedNodeVersion,
25287
+ getWorkerTopics,
25213
25288
  getWriteableDirectory,
25214
25289
  glob,
25215
25290
  hardLinkDir,
@@ -25225,6 +25300,7 @@ async function isPythonEntrypoint(file) {
25225
25300
  isPythonFramework,
25226
25301
  isSymbolicLink,
25227
25302
  normalizePath,
25303
+ packageManifestSchema,
25228
25304
  readConfigFile,
25229
25305
  rename,
25230
25306
  resetCustomInstallCommandSet,
package/dist/python.js CHANGED
@@ -40,7 +40,7 @@ async function isPythonEntrypoint(file) {
40
40
  if (!fsPath)
41
41
  return false;
42
42
  const content = await import_fs.default.promises.readFile(fsPath, "utf-8");
43
- return await (0, import_python_analysis.containsAppOrHandler)(content);
43
+ return await (0, import_python_analysis.findAppOrHandler)(content) !== null;
44
44
  } catch (err) {
45
45
  (0, import_debug.default)(`Failed to check Python entrypoint: ${err}`);
46
46
  return false;
package/dist/schemas.d.ts CHANGED
@@ -121,3 +121,83 @@ export declare const buildsSchema: {
121
121
  };
122
122
  };
123
123
  };
124
+ /**
125
+ * JSON Schema for builder-produced `package-manifest.json` files.
126
+ *
127
+ * Each builder (e.g. @vercel/python) may emit a `package-manifest.json`
128
+ * in its diagnostics output.
129
+ */
130
+ export declare const packageManifestSchema: {
131
+ readonly type: "object";
132
+ readonly required: readonly ["runtime", "dependencies"];
133
+ readonly additionalProperties: false;
134
+ readonly properties: {
135
+ readonly version: {
136
+ readonly type: "string";
137
+ readonly description: "Manifest schema version, e.g. \"20260304\".";
138
+ };
139
+ readonly runtime: {
140
+ readonly type: "string";
141
+ readonly description: "Runtime identifier, e.g. \"python\", \"node\".";
142
+ };
143
+ readonly runtimeVersion: {
144
+ readonly type: "object";
145
+ readonly additionalProperties: false;
146
+ readonly required: readonly ["resolved"];
147
+ readonly properties: {
148
+ readonly requested: {
149
+ readonly type: "string";
150
+ readonly description: "Version constraint from the project manifest, e.g. \">=3.10\".";
151
+ };
152
+ readonly requestedSource: {
153
+ readonly type: "string";
154
+ readonly description: "File that declared the constraint, e.g. \"pyproject.toml\".";
155
+ };
156
+ readonly resolved: {
157
+ readonly type: "string";
158
+ readonly description: "Actual resolved version, e.g. \"3.12\".";
159
+ };
160
+ };
161
+ };
162
+ readonly dependencies: {
163
+ readonly type: "array";
164
+ readonly items: {
165
+ readonly type: "object";
166
+ readonly required: readonly ["name", "type", "scopes", "resolved"];
167
+ readonly additionalProperties: false;
168
+ readonly properties: {
169
+ readonly name: {
170
+ readonly type: "string";
171
+ };
172
+ readonly type: {
173
+ readonly type: "string";
174
+ readonly enum: readonly ["direct", "transitive", "peer"];
175
+ };
176
+ readonly scopes: {
177
+ readonly type: "array";
178
+ readonly items: {
179
+ readonly type: "string";
180
+ };
181
+ readonly description: "Dependency groups this package belongs to, e.g. [\"main\", \"dev\"].";
182
+ };
183
+ readonly requested: {
184
+ readonly type: "string";
185
+ readonly description: "Version specifier as declared, e.g. \"flask>=2.0\".";
186
+ };
187
+ readonly resolved: {
188
+ readonly type: "string";
189
+ readonly description: "Resolved version, e.g. \"3.1.0\".";
190
+ };
191
+ readonly source: {
192
+ readonly type: "string";
193
+ readonly description: "Package source type, e.g. \"registry\", \"git\", \"path\".";
194
+ };
195
+ readonly sourceUrl: {
196
+ readonly type: "string";
197
+ readonly description: "Source URL, e.g. \"https://pypi.org\".";
198
+ };
199
+ };
200
+ };
201
+ };
202
+ };
203
+ };
package/dist/schemas.js CHANGED
@@ -19,7 +19,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var schemas_exports = {};
20
20
  __export(schemas_exports, {
21
21
  buildsSchema: () => buildsSchema,
22
- functionsSchema: () => functionsSchema
22
+ functionsSchema: () => functionsSchema,
23
+ packageManifestSchema: () => packageManifestSchema
23
24
  });
24
25
  module.exports = __toCommonJS(schemas_exports);
25
26
  const triggerEventSchemaV1 = {
@@ -173,8 +174,76 @@ const buildsSchema = {
173
174
  }
174
175
  }
175
176
  };
177
+ const packageManifestSchema = {
178
+ type: "object",
179
+ required: ["runtime", "dependencies"],
180
+ additionalProperties: false,
181
+ properties: {
182
+ version: {
183
+ type: "string",
184
+ description: 'Manifest schema version, e.g. "20260304".'
185
+ },
186
+ runtime: {
187
+ type: "string",
188
+ description: 'Runtime identifier, e.g. "python", "node".'
189
+ },
190
+ runtimeVersion: {
191
+ type: "object",
192
+ additionalProperties: false,
193
+ required: ["resolved"],
194
+ properties: {
195
+ requested: {
196
+ type: "string",
197
+ description: 'Version constraint from the project manifest, e.g. ">=3.10".'
198
+ },
199
+ requestedSource: {
200
+ type: "string",
201
+ description: 'File that declared the constraint, e.g. "pyproject.toml".'
202
+ },
203
+ resolved: {
204
+ type: "string",
205
+ description: 'Actual resolved version, e.g. "3.12".'
206
+ }
207
+ }
208
+ },
209
+ dependencies: {
210
+ type: "array",
211
+ items: {
212
+ type: "object",
213
+ required: ["name", "type", "scopes", "resolved"],
214
+ additionalProperties: false,
215
+ properties: {
216
+ name: { type: "string" },
217
+ type: { type: "string", enum: ["direct", "transitive", "peer"] },
218
+ scopes: {
219
+ type: "array",
220
+ items: { type: "string" },
221
+ description: 'Dependency groups this package belongs to, e.g. ["main", "dev"].'
222
+ },
223
+ requested: {
224
+ type: "string",
225
+ description: 'Version specifier as declared, e.g. "flask>=2.0".'
226
+ },
227
+ resolved: {
228
+ type: "string",
229
+ description: 'Resolved version, e.g. "3.1.0".'
230
+ },
231
+ source: {
232
+ type: "string",
233
+ description: 'Package source type, e.g. "registry", "git", "path".'
234
+ },
235
+ sourceUrl: {
236
+ type: "string",
237
+ description: 'Source URL, e.g. "https://pypi.org".'
238
+ }
239
+ }
240
+ }
241
+ }
242
+ }
243
+ };
176
244
  // Annotate the CommonJS export names for ESM import in node:
177
245
  0 && (module.exports = {
178
246
  buildsSchema,
179
- functionsSchema
247
+ functionsSchema,
248
+ packageManifestSchema
180
249
  });
package/dist/types.d.ts CHANGED
@@ -110,6 +110,8 @@ export interface BuildOptions {
110
110
  service?: {
111
111
  /** The service name as declared in the project configuration. */
112
112
  name?: string;
113
+ /** The service type (e.g., "web", "cron", "worker"). */
114
+ type?: ServiceType;
113
115
  /** URL path prefix where the service is mounted (e.g., "/api"). */
114
116
  routePrefix?: string;
115
117
  /** Optional subdomain this service is mounted on (e.g., "api"). */
@@ -384,6 +386,14 @@ export interface ProjectSettings {
384
386
  gitForkProtection?: boolean;
385
387
  commandForIgnoringBuildStep?: string | null;
386
388
  }
389
+ export interface BuilderVX {
390
+ version: -1;
391
+ build: BuildVX;
392
+ diagnostics?: Diagnostics;
393
+ prepareCache?: PrepareCache;
394
+ shouldServe?: ShouldServe;
395
+ startDevServer?: StartDevServer;
396
+ }
387
397
  export interface BuilderV2 {
388
398
  version: 2;
389
399
  build: BuildV2;
@@ -491,9 +501,17 @@ export interface Service {
491
501
  subdomain?: string;
492
502
  schedule?: string;
493
503
  handlerFunction?: string;
494
- topic?: string;
504
+ topics?: string[];
495
505
  consumer?: string;
506
+ /** custom prefix to inject service URL env vars */
507
+ envPrefix?: string;
496
508
  }
509
+ /**
510
+ * Returns the topics a worker service subscribes to, defaulting to ['default'].
511
+ */
512
+ export declare function getWorkerTopics(config: {
513
+ topics?: string[];
514
+ }): [string, ...string[]];
497
515
  /** The framework which created the function */
498
516
  export interface FunctionFramework {
499
517
  slug: string;
@@ -528,11 +546,19 @@ export interface BuildResultV2Typical {
528
546
  */
529
547
  deploymentId?: string;
530
548
  }
549
+ export type BuildResultVX = {
550
+ resultVersion: 2;
551
+ result: BuildResultV2;
552
+ } | {
553
+ resultVersion: 3;
554
+ result: BuildResultV3;
555
+ };
531
556
  export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
532
557
  export interface BuildResultV3 {
533
558
  routes?: any[];
534
559
  output: Lambda | EdgeFunction;
535
560
  }
561
+ export type BuildVX = (options: BuildOptions) => Promise<BuildResultVX>;
536
562
  export type BuildV2 = (options: BuildOptions) => Promise<BuildResultV2>;
537
563
  export type BuildV3 = (options: BuildOptions) => Promise<BuildResultV3>;
538
564
  export type PrepareCache = (options: PrepareCacheOptions) => Promise<Files>;
@@ -664,8 +690,10 @@ export interface ExperimentalServiceConfig {
664
690
  subdomain?: string;
665
691
  /** Cron schedule expression (e.g., "0 0 * * *") */
666
692
  schedule?: string;
667
- topic?: string;
693
+ topics?: string[];
668
694
  consumer?: string;
695
+ /** Custom prefix to use to inject service URL env vars */
696
+ envPrefix?: string;
669
697
  }
670
698
  /**
671
699
  * Map of service name to service configuration.
package/dist/types.js CHANGED
@@ -20,7 +20,8 @@ var types_exports = {};
20
20
  __export(types_exports, {
21
21
  BunVersion: () => BunVersion,
22
22
  NodeVersion: () => NodeVersion,
23
- Version: () => Version
23
+ Version: () => Version,
24
+ getWorkerTopics: () => getWorkerTopics
24
25
  });
25
26
  module.exports = __toCommonJS(types_exports);
26
27
  class Version {
@@ -47,9 +48,13 @@ class NodeVersion extends Version {
47
48
  }
48
49
  class BunVersion extends Version {
49
50
  }
51
+ function getWorkerTopics(config) {
52
+ return config.topics?.length ? config.topics : ["default"];
53
+ }
50
54
  // Annotate the CommonJS export names for ESM import in node:
51
55
  0 && (module.exports = {
52
56
  BunVersion,
53
57
  NodeVersion,
54
- Version
58
+ Version,
59
+ getWorkerTopics
55
60
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/build-utils",
3
- "version": "13.8.2",
3
+ "version": "13.10.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.js",
@@ -11,7 +11,7 @@
11
11
  "directory": "packages/now-build-utils"
12
12
  },
13
13
  "dependencies": {
14
- "@vercel/python-analysis": "0.10.1"
14
+ "@vercel/python-analysis": "0.11.0"
15
15
  },
16
16
  "devDependencies": {
17
17
  "@iarna/toml": "2.2.3",
@@ -50,8 +50,8 @@
50
50
  "yazl": "2.5.1",
51
51
  "vitest": "2.0.1",
52
52
  "json5": "2.2.3",
53
- "@vercel/routing-utils": "6.0.2",
54
- "@vercel/error-utils": "2.0.3"
53
+ "@vercel/error-utils": "2.0.3",
54
+ "@vercel/routing-utils": "6.1.1"
55
55
  },
56
56
  "scripts": {
57
57
  "build": "node build.mjs",