@vercel/python 6.32.0 → 6.33.1

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/dist/index.js CHANGED
@@ -48,7 +48,7 @@ var require_windows = __commonJS({
48
48
  "../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js"(exports, module2) {
49
49
  module2.exports = isexe;
50
50
  isexe.sync = sync;
51
- var fs11 = require("fs");
51
+ var fs12 = require("fs");
52
52
  function checkPathExt(path, options) {
53
53
  var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
54
54
  if (!pathext) {
@@ -73,12 +73,12 @@ var require_windows = __commonJS({
73
73
  return checkPathExt(path, options);
74
74
  }
75
75
  function isexe(path, options, cb) {
76
- fs11.stat(path, function(er, stat) {
76
+ fs12.stat(path, function(er, stat) {
77
77
  cb(er, er ? false : checkStat(stat, path, options));
78
78
  });
79
79
  }
80
80
  function sync(path, options) {
81
- return checkStat(fs11.statSync(path), path, options);
81
+ return checkStat(fs12.statSync(path), path, options);
82
82
  }
83
83
  }
84
84
  });
@@ -88,14 +88,14 @@ var require_mode = __commonJS({
88
88
  "../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js"(exports, module2) {
89
89
  module2.exports = isexe;
90
90
  isexe.sync = sync;
91
- var fs11 = require("fs");
91
+ var fs12 = require("fs");
92
92
  function isexe(path, options, cb) {
93
- fs11.stat(path, function(er, stat) {
93
+ fs12.stat(path, function(er, stat) {
94
94
  cb(er, er ? false : checkStat(stat, options));
95
95
  });
96
96
  }
97
97
  function sync(path, options) {
98
- return checkStat(fs11.statSync(path), options);
98
+ return checkStat(fs12.statSync(path), options);
99
99
  }
100
100
  function checkStat(stat, options) {
101
101
  return stat.isFile() && checkMode(stat, options);
@@ -119,7 +119,7 @@ var require_mode = __commonJS({
119
119
  // ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js
120
120
  var require_isexe = __commonJS({
121
121
  "../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports, module2) {
122
- var fs11 = require("fs");
122
+ var fs12 = require("fs");
123
123
  var core;
124
124
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
125
125
  core = require_windows();
@@ -395,7 +395,7 @@ var require_shebang_command = __commonJS({
395
395
  var require_readShebang = __commonJS({
396
396
  "../../node_modules/.pnpm/cross-spawn@6.0.5/node_modules/cross-spawn/lib/util/readShebang.js"(exports, module2) {
397
397
  "use strict";
398
- var fs11 = require("fs");
398
+ var fs12 = require("fs");
399
399
  var shebangCommand = require_shebang_command();
400
400
  function readShebang(command) {
401
401
  const size = 150;
@@ -408,9 +408,9 @@ var require_readShebang = __commonJS({
408
408
  }
409
409
  let fd;
410
410
  try {
411
- fd = fs11.openSync(command, "r");
412
- fs11.readSync(fd, buffer, 0, size, 0);
413
- fs11.closeSync(fd);
411
+ fd = fs12.openSync(command, "r");
412
+ fs12.readSync(fd, buffer, 0, size, 0);
413
+ fs12.closeSync(fd);
414
414
  } catch (e) {
415
415
  }
416
416
  return shebangCommand(buffer.toString());
@@ -1895,9 +1895,9 @@ var require_pump = __commonJS({
1895
1895
  "../../node_modules/.pnpm/pump@3.0.2/node_modules/pump/index.js"(exports, module2) {
1896
1896
  var once = require_once();
1897
1897
  var eos = require_end_of_stream();
1898
- var fs11;
1898
+ var fs12;
1899
1899
  try {
1900
- fs11 = require("fs");
1900
+ fs12 = require("fs");
1901
1901
  } catch (e) {
1902
1902
  }
1903
1903
  var noop = function() {
@@ -1909,9 +1909,9 @@ var require_pump = __commonJS({
1909
1909
  var isFS = function(stream) {
1910
1910
  if (!ancient)
1911
1911
  return false;
1912
- if (!fs11)
1912
+ if (!fs12)
1913
1913
  return false;
1914
- return (stream instanceof (fs11.ReadStream || noop) || stream instanceof (fs11.WriteStream || noop)) && isFn(stream.close);
1914
+ return (stream instanceof (fs12.ReadStream || noop) || stream instanceof (fs12.WriteStream || noop)) && isFn(stream.close);
1915
1915
  };
1916
1916
  var isRequest = function(stream) {
1917
1917
  return stream.setHeader && isFn(stream.abort);
@@ -2141,7 +2141,7 @@ var require_signal_exit = __commonJS({
2141
2141
  };
2142
2142
  };
2143
2143
  } else {
2144
- assert = require("assert");
2144
+ assert2 = require("assert");
2145
2145
  signals = require_signals();
2146
2146
  isWin3 = /^win/i.test(process2.platform);
2147
2147
  EE = require("events");
@@ -2164,7 +2164,7 @@ var require_signal_exit = __commonJS({
2164
2164
  return function() {
2165
2165
  };
2166
2166
  }
2167
- assert.equal(typeof cb, "function", "a callback must be provided for exit handler");
2167
+ assert2.equal(typeof cb, "function", "a callback must be provided for exit handler");
2168
2168
  if (loaded === false) {
2169
2169
  load();
2170
2170
  }
@@ -2270,7 +2270,7 @@ var require_signal_exit = __commonJS({
2270
2270
  }
2271
2271
  };
2272
2272
  }
2273
- var assert;
2273
+ var assert2;
2274
2274
  var signals;
2275
2275
  var isWin3;
2276
2276
  var EE;
@@ -2674,27 +2674,27 @@ var require_process = __commonJS({
2674
2674
  var require_filesystem = __commonJS({
2675
2675
  "../../node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/filesystem.js"(exports, module2) {
2676
2676
  "use strict";
2677
- var fs11 = require("fs");
2677
+ var fs12 = require("fs");
2678
2678
  var LDD_PATH = "/usr/bin/ldd";
2679
2679
  var SELF_PATH = "/proc/self/exe";
2680
2680
  var MAX_LENGTH = 2048;
2681
2681
  var readFileSync2 = (path) => {
2682
- const fd = fs11.openSync(path, "r");
2682
+ const fd = fs12.openSync(path, "r");
2683
2683
  const buffer = Buffer.alloc(MAX_LENGTH);
2684
- const bytesRead = fs11.readSync(fd, buffer, 0, MAX_LENGTH, 0);
2685
- fs11.close(fd, () => {
2684
+ const bytesRead = fs12.readSync(fd, buffer, 0, MAX_LENGTH, 0);
2685
+ fs12.close(fd, () => {
2686
2686
  });
2687
2687
  return buffer.subarray(0, bytesRead);
2688
2688
  };
2689
2689
  var readFile2 = (path) => new Promise((resolve3, reject) => {
2690
- fs11.open(path, "r", (err, fd) => {
2690
+ fs12.open(path, "r", (err, fd) => {
2691
2691
  if (err) {
2692
2692
  reject(err);
2693
2693
  } else {
2694
2694
  const buffer = Buffer.alloc(MAX_LENGTH);
2695
- fs11.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
2695
+ fs12.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
2696
2696
  resolve3(buffer.subarray(0, bytesRead));
2697
- fs11.close(fd, () => {
2697
+ fs12.close(fd, () => {
2698
2698
  });
2699
2699
  });
2700
2700
  }
@@ -3005,7 +3005,7 @@ var require_detect_libc = __commonJS({
3005
3005
  var require_lib = __commonJS({
3006
3006
  "../../node_modules/.pnpm/which@3.0.0/node_modules/which/lib/index.js"(exports, module2) {
3007
3007
  var isexe = require_isexe();
3008
- var { join: join13, delimiter: delimiter2, sep: sep2, posix } = require("path");
3008
+ var { join: join14, delimiter: delimiter2, sep: sep2, posix } = require("path");
3009
3009
  var isWindows = process.platform === "win32";
3010
3010
  var rSlash = new RegExp(`[${posix.sep}${sep2 === posix.sep ? "" : sep2}]`.replace(/(\\)/g, "\\$1"));
3011
3011
  var rRel = new RegExp(`^\\.${rSlash.source}`);
@@ -3034,7 +3034,7 @@ var require_lib = __commonJS({
3034
3034
  var getPathPart = (raw, cmd) => {
3035
3035
  const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
3036
3036
  const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : "";
3037
- return prefix + join13(pathPart, cmd);
3037
+ return prefix + join14(pathPart, cmd);
3038
3038
  };
3039
3039
  var which2 = async (cmd, opt = {}) => {
3040
3040
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
@@ -3224,16 +3224,17 @@ __export(src_exports, {
3224
3224
  version: () => version
3225
3225
  });
3226
3226
  module.exports = __toCommonJS(src_exports);
3227
+ var import_assert = __toESM(require("assert"));
3227
3228
  var import_child_process3 = require("child_process");
3228
- var import_fs12 = __toESM(require("fs"));
3229
- var import_path13 = require("path");
3229
+ var import_fs13 = __toESM(require("fs"));
3230
+ var import_path14 = require("path");
3230
3231
 
3231
3232
  // src/package-versions.ts
3232
- var VERCEL_RUNTIME_VERSION = "0.12.0";
3233
+ var VERCEL_RUNTIME_VERSION = "0.13.0";
3233
3234
  var VERCEL_WORKERS_VERSION = "0.0.16";
3234
3235
 
3235
3236
  // src/index.ts
3236
- var import_build_utils15 = require("@vercel/build-utils");
3237
+ var import_build_utils16 = require("@vercel/build-utils");
3237
3238
 
3238
3239
  // src/install.ts
3239
3240
  var import_execa3 = __toESM(require_execa());
@@ -3636,7 +3637,7 @@ async function ensureVenv({
3636
3637
  }
3637
3638
  }
3638
3639
  if (uvPath) {
3639
- const args = ["venv", venvPath, "--allow-existing"];
3640
+ const args = ["venv", venvPath, "--allow-existing", "--seed"];
3640
3641
  if (pythonVersion.major != null && pythonVersion.minor != null) {
3641
3642
  args.push("--python", `${pythonVersion.major}.${pythonVersion.minor}`);
3642
3643
  }
@@ -4313,6 +4314,11 @@ var readFile = (0, import_util.promisify)(import_fs5.default.readFile);
4313
4314
  var LAMBDA_SIZE_THRESHOLD_BYTES = 245 * 1024 * 1024;
4314
4315
  var LAMBDA_EPHEMERAL_STORAGE_BYTES = 500 * 1024 * 1024;
4315
4316
  var HIVE_LAMBDA_SIZE_BYTES = 1 * 1024 * 1024 * 1024;
4317
+ var FUNCTIONS_BETA_CTA = "Run `vercel deploy --functions-beta` to use extended function limits (up to 1 GB), or reduce your dependency footprint.";
4318
+ function shouldShowFunctionsBetaHint() {
4319
+ const v = process.env.VERCEL_FUNCTIONS_BETA_HINT;
4320
+ return v === "1" || v === "true";
4321
+ }
4316
4322
  var PythonDependencyExternalizer = class {
4317
4323
  constructor(options) {
4318
4324
  // Populated by analyze()
@@ -4367,7 +4373,9 @@ var PythonDependencyExternalizer = class {
4367
4373
  const limitMB = (LAMBDA_SIZE_THRESHOLD_BYTES / (1024 * 1024)).toFixed(0);
4368
4374
  throw new import_build_utils5.NowBuildError({
4369
4375
  code: "LAMBDA_SIZE_EXCEEDED",
4370
- message: `Total bundle size (${totalBundleSizeMB} MB) exceeds the Lambda size limit (${limitMB} MB).
4376
+ message: shouldShowFunctionsBetaHint() ? `Total bundle size (${totalBundleSizeMB} MB) exceeds the size limit (${limitMB} MB).
4377
+
4378
+ ` + FUNCTIONS_BETA_CTA : `Total bundle size (${totalBundleSizeMB} MB) exceeds the Lambda size limit (${limitMB} MB).
4371
4379
 
4372
4380
  Runtime dependency installation is not available for projects that use a custom build or install command, because custom commands may install dependencies that are not tracked in uv.lock.
4373
4381
 
@@ -4419,7 +4427,9 @@ To resolve this, either:
4419
4427
  const ephemeralLimitMB = (LAMBDA_EPHEMERAL_STORAGE_BYTES / (1024 * 1024)).toFixed(0);
4420
4428
  throw new import_build_utils5.NowBuildError({
4421
4429
  code: "LAMBDA_SIZE_EXCEEDED",
4422
- message: `Total dependency size (${totalBundleSizeMB} MB) exceeds Lambda ephemeral storage limit (${ephemeralLimitMB} MB). Even with runtime dependency installation, all packages must fit within the ${ephemeralLimitMB} MB ephemeral storage available to Lambda functions. Consider removing unused dependencies or splitting your application into smaller functions.`,
4430
+ message: shouldShowFunctionsBetaHint() ? `Total dependency size (${totalBundleSizeMB} MB) exceeds the size limit (${ephemeralLimitMB} MB).
4431
+
4432
+ ` + FUNCTIONS_BETA_CTA : `Total dependency size (${totalBundleSizeMB} MB) exceeds Lambda ephemeral storage limit (${ephemeralLimitMB} MB). Even with runtime dependency installation, all packages must fit within the ${ephemeralLimitMB} MB ephemeral storage available to Lambda functions. Consider removing unused dependencies or splitting your application into smaller functions.`,
4423
4433
  link: "https://vercel.com/docs/functions/runtimes/python#controlling-what-gets-bundled",
4424
4434
  action: "Learn More"
4425
4435
  });
@@ -4613,7 +4623,9 @@ To fix this, either:
4613
4623
  const limitMB = (LAMBDA_SIZE_THRESHOLD_BYTES / (1024 * 1024)).toFixed(0);
4614
4624
  throw new import_build_utils5.NowBuildError({
4615
4625
  code: "LAMBDA_SIZE_EXCEEDED",
4616
- message: `Bundle size (${finalSizeMB} MB) exceeds Lambda limit (${limitMB} MB) even after deferring public packages to runtime installation. This usually means your private packages or source code are too large. Consider reducing the size of private dependencies or splitting your application.`,
4626
+ message: shouldShowFunctionsBetaHint() ? `Bundle size (${finalSizeMB} MB) exceeds the size limit (${limitMB} MB).
4627
+
4628
+ ` + FUNCTIONS_BETA_CTA : `Bundle size (${finalSizeMB} MB) exceeds Lambda limit (${limitMB} MB) even after deferring public packages to runtime installation. This usually means your private packages or source code are too large. Consider reducing the size of private dependencies or splitting your application.`,
4617
4629
  link: "https://vercel.com/docs/functions/runtimes/python#controlling-what-gets-bundled",
4618
4630
  action: "Learn More"
4619
4631
  });
@@ -5103,20 +5115,161 @@ var diagnostics = async ({
5103
5115
  }
5104
5116
  };
5105
5117
 
5118
+ // src/crons.ts
5119
+ var import_fs7 = __toESM(require("fs"));
5120
+ var import_path8 = require("path");
5121
+ var import_execa4 = __toESM(require_execa());
5122
+ var import_build_utils7 = require("@vercel/build-utils");
5123
+ var DYNAMIC_SCHEDULE = "<dynamic>";
5124
+ function entrypointToModule(entrypoint) {
5125
+ return entrypoint.replace(/\\/g, "/").replace(/\.py$/i, "").replace(/\//g, ".");
5126
+ }
5127
+ var scriptPath = (0, import_path8.join)(__dirname, "..", "templates", "vc_cron_detect.py");
5128
+ var script = import_fs7.default.readFileSync(scriptPath, "utf-8");
5129
+ function buildCronRouteTable(crons) {
5130
+ const table = {};
5131
+ for (const cron of crons) {
5132
+ table[cron.path] = cron.resolvedHandler;
5133
+ }
5134
+ return table;
5135
+ }
5136
+ async function getServiceCrons(opts) {
5137
+ const { service, entrypoint, rawEntrypoint, handlerFunction } = opts;
5138
+ if (service?.type !== "cron" || !service.name || typeof service.schedule !== "string") {
5139
+ return void 0;
5140
+ }
5141
+ const cronEntrypoint = entrypoint || rawEntrypoint;
5142
+ if (!cronEntrypoint) {
5143
+ throw new import_build_utils7.NowBuildError({
5144
+ code: "PYTHON_CRON_NO_ENTRYPOINT",
5145
+ message: "Cron service is missing an entrypoint."
5146
+ });
5147
+ }
5148
+ if (service.schedule === DYNAMIC_SCHEDULE) {
5149
+ return getServiceCronsDynamic({
5150
+ serviceName: service.name,
5151
+ cronEntrypoint,
5152
+ handlerFunction,
5153
+ pythonBin: opts.pythonBin,
5154
+ env: opts.env,
5155
+ workPath: opts.workPath
5156
+ });
5157
+ }
5158
+ const cronPath = (0, import_build_utils7.getInternalServiceCronPath)(
5159
+ service.name,
5160
+ cronEntrypoint,
5161
+ handlerFunction || "cron"
5162
+ );
5163
+ const moduleName = entrypointToModule(cronEntrypoint);
5164
+ const resolvedHandler = handlerFunction ? `${moduleName}:${handlerFunction}` : moduleName;
5165
+ return [{ path: cronPath, schedule: service.schedule, resolvedHandler }];
5166
+ }
5167
+ async function getServiceCronsDynamic(opts) {
5168
+ const {
5169
+ serviceName,
5170
+ cronEntrypoint,
5171
+ handlerFunction,
5172
+ pythonBin,
5173
+ env,
5174
+ workPath
5175
+ } = opts;
5176
+ if (!handlerFunction) {
5177
+ throw new import_build_utils7.NowBuildError({
5178
+ code: "PYTHON_DYNAMIC_CRON_NO_HANDLER",
5179
+ message: 'Dynamic cron detection requires a "module:object" entrypoint where the object has a get_crons() method.'
5180
+ });
5181
+ }
5182
+ const moduleName = entrypointToModule(cronEntrypoint);
5183
+ const entries = await detectDynamicCrons({
5184
+ pythonBin,
5185
+ env,
5186
+ workPath,
5187
+ moduleName,
5188
+ attrName: handlerFunction
5189
+ });
5190
+ console.log(
5191
+ `Detected ${entries.length} cron entry(s): ${entries.map((e) => `${e.module_function} (${e.schedule})`).join(", ")}`
5192
+ );
5193
+ if (entries.length === 0) {
5194
+ throw new import_build_utils7.NowBuildError({
5195
+ code: "PYTHON_DYNAMIC_CRON_EMPTY",
5196
+ message: `Dynamic cron detection returned no entries. "${moduleName}.${handlerFunction}.get_crons()" returned an empty iterable.`
5197
+ });
5198
+ }
5199
+ return entries.map((entry) => {
5200
+ const cronPath = moduleColonFuncToCronPath(
5201
+ serviceName,
5202
+ entry.module_function
5203
+ );
5204
+ return {
5205
+ path: cronPath,
5206
+ schedule: entry.schedule,
5207
+ resolvedHandler: entry.module_function
5208
+ };
5209
+ });
5210
+ }
5211
+ async function detectDynamicCrons(opts) {
5212
+ const { pythonBin, env, workPath, moduleName, attrName } = opts;
5213
+ let stdout;
5214
+ try {
5215
+ const result = await (0, import_execa4.default)(
5216
+ pythonBin,
5217
+ ["-c", script, moduleName, attrName],
5218
+ { env, cwd: workPath }
5219
+ );
5220
+ stdout = result.stdout;
5221
+ } catch (err) {
5222
+ let detail = err?.stderr || err?.message || String(err);
5223
+ try {
5224
+ const parsed2 = JSON.parse(err?.stdout);
5225
+ if (parsed2.error)
5226
+ detail = parsed2.error;
5227
+ } catch {
5228
+ }
5229
+ throw new import_build_utils7.NowBuildError({
5230
+ code: "PYTHON_DYNAMIC_CRON_DETECTION_FAILED",
5231
+ message: `Failed to detect dynamic cron entries: ${detail}`
5232
+ });
5233
+ }
5234
+ let parsed;
5235
+ try {
5236
+ parsed = JSON.parse(stdout);
5237
+ } catch {
5238
+ throw new import_build_utils7.NowBuildError({
5239
+ code: "PYTHON_DYNAMIC_CRON_DETECTION_FAILED",
5240
+ message: `Dynamic cron detection returned invalid JSON: ${stdout}`
5241
+ });
5242
+ }
5243
+ return parsed.entries || [];
5244
+ }
5245
+ function moduleColonFuncToCronPath(serviceName, moduleFunction) {
5246
+ const colonIdx = moduleFunction.indexOf(":");
5247
+ if (colonIdx === -1) {
5248
+ throw new import_build_utils7.NowBuildError({
5249
+ code: "PYTHON_DYNAMIC_CRON_INVALID_FORMAT",
5250
+ message: `Dynamic cron entry must use "module:function" format, got: "${moduleFunction}"`
5251
+ });
5252
+ }
5253
+ const modulePart = moduleFunction.slice(0, colonIdx);
5254
+ const funcPart = moduleFunction.slice(colonIdx + 1);
5255
+ const entrypointPath = modulePart.replace(/\./g, "/");
5256
+ return (0, import_build_utils7.getInternalServiceCronPath)(serviceName, entrypointPath, funcPart);
5257
+ }
5258
+
5106
5259
  // src/start-dev-server.ts
5107
5260
  var import_child_process2 = require("child_process");
5108
- var import_fs8 = require("fs");
5109
- var import_path9 = require("path");
5110
- var import_build_utils10 = require("@vercel/build-utils");
5261
+ var import_fs9 = require("fs");
5262
+ var import_path10 = require("path");
5263
+ var import_build_utils11 = require("@vercel/build-utils");
5111
5264
  var import_get_port = __toESM(require_get_port());
5112
5265
  var import_is_port_reachable = __toESM(require_is_port_reachable());
5113
5266
 
5114
5267
  // src/entrypoint.ts
5115
- var import_fs7 = __toESM(require("fs"));
5116
- var import_path8 = require("path");
5117
- var import_build_utils7 = require("@vercel/build-utils");
5268
+ var import_fs8 = __toESM(require("fs"));
5269
+ var import_path9 = require("path");
5118
5270
  var import_build_utils8 = require("@vercel/build-utils");
5119
5271
  var import_build_utils9 = require("@vercel/build-utils");
5272
+ var import_build_utils10 = require("@vercel/build-utils");
5120
5273
  var import_python_analysis5 = require("@vercel/python-analysis");
5121
5274
  var PYTHON_ENTRYPOINT_FILENAMES = [
5122
5275
  "app",
@@ -5133,27 +5286,27 @@ var PYTHON_CANDIDATE_ENTRYPOINTS = getCandidateEntrypointsInDirs(
5133
5286
  function getCandidateEntrypointsInDirs(dirs) {
5134
5287
  return dirs.flatMap(
5135
5288
  (dir) => PYTHON_ENTRYPOINT_FILENAMES.map(
5136
- (filename) => import_path8.posix.join(dir, `${filename}.py`)
5289
+ (filename) => import_path9.posix.join(dir, `${filename}.py`)
5137
5290
  )
5138
5291
  );
5139
5292
  }
5140
5293
  async function fileExists(filePath) {
5141
5294
  try {
5142
- const stat = await import_fs7.default.promises.stat(filePath);
5295
+ const stat = await import_fs8.default.promises.stat(filePath);
5143
5296
  return stat.isFile();
5144
5297
  } catch {
5145
5298
  return false;
5146
5299
  }
5147
5300
  }
5148
5301
  async function checkEntrypoint(workPath, relPath) {
5149
- const absPath = (0, import_path8.join)(workPath, relPath);
5302
+ const absPath = (0, import_path9.join)(workPath, relPath);
5150
5303
  if (!await fileExists(absPath))
5151
5304
  return null;
5152
- const content = await import_fs7.default.promises.readFile(absPath, "utf-8");
5305
+ const content = await import_fs8.default.promises.readFile(absPath, "utf-8");
5153
5306
  return (0, import_python_analysis5.findAppOrHandler)(content);
5154
5307
  }
5155
5308
  async function getPyprojectEntrypoint(workPath) {
5156
- const pyprojectData = await (0, import_build_utils9.readConfigFile)((0, import_path8.join)(workPath, "pyproject.toml"));
5309
+ const pyprojectData = await (0, import_build_utils10.readConfigFile)((0, import_path9.join)(workPath, "pyproject.toml"));
5157
5310
  if (!pyprojectData)
5158
5311
  return null;
5159
5312
  const scripts = pyprojectData.project?.scripts;
@@ -5168,7 +5321,7 @@ async function getPyprojectEntrypoint(workPath) {
5168
5321
  const relPath = modulePath.replace(/\./g, "/");
5169
5322
  const candidates = [`${relPath}.py`, `${relPath}/__init__.py`];
5170
5323
  for (const candidate of candidates) {
5171
- if (await fileExists((0, import_path8.join)(workPath, candidate))) {
5324
+ if (await fileExists((0, import_path9.join)(workPath, candidate))) {
5172
5325
  return { entrypoint: candidate, variableName };
5173
5326
  }
5174
5327
  }
@@ -5178,19 +5331,19 @@ async function findValidEntrypoint(workPath, candidates) {
5178
5331
  for (const candidate of candidates) {
5179
5332
  const varName = await checkEntrypoint(workPath, candidate);
5180
5333
  if (varName) {
5181
- (0, import_build_utils8.debug)(`Detected Python entrypoint: ${candidate} (variable: ${varName})`);
5334
+ (0, import_build_utils9.debug)(`Detected Python entrypoint: ${candidate} (variable: ${varName})`);
5182
5335
  return { entrypoint: candidate, variableName: varName };
5183
5336
  }
5184
5337
  }
5185
5338
  return null;
5186
5339
  }
5187
5340
  async function checkDjangoManage(workPath) {
5188
- const managePath = (0, import_path8.join)(workPath, "manage.py");
5341
+ const managePath = (0, import_path9.join)(workPath, "manage.py");
5189
5342
  try {
5190
- const content = await import_fs7.default.promises.readFile(managePath, "utf-8");
5343
+ const content = await import_fs8.default.promises.readFile(managePath, "utf-8");
5191
5344
  if (!content.includes("DJANGO_SETTINGS_MODULE"))
5192
5345
  return false;
5193
- (0, import_build_utils8.debug)(`Found Django manage.py with DJANGO_SETTINGS_MODULE at ${workPath}`);
5346
+ (0, import_build_utils9.debug)(`Found Django manage.py with DJANGO_SETTINGS_MODULE at ${workPath}`);
5194
5347
  return true;
5195
5348
  } catch {
5196
5349
  return false;
@@ -5198,7 +5351,7 @@ async function checkDjangoManage(workPath) {
5198
5351
  }
5199
5352
  async function getSubdirectories(workPath) {
5200
5353
  try {
5201
- const entries = await import_fs7.default.promises.readdir(workPath, {
5354
+ const entries = await import_fs8.default.promises.readdir(workPath, {
5202
5355
  withFileTypes: true
5203
5356
  });
5204
5357
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).sort();
@@ -5208,7 +5361,7 @@ async function getSubdirectories(workPath) {
5208
5361
  }
5209
5362
  function makeDetectError(framework) {
5210
5363
  const searchedList = PYTHON_CANDIDATE_ENTRYPOINTS.join(", ");
5211
- return new import_build_utils7.NowBuildError({
5364
+ return new import_build_utils8.NowBuildError({
5212
5365
  code: `${framework.toUpperCase()}_ENTRYPOINT_NOT_FOUND`,
5213
5366
  message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searchedList}.`,
5214
5367
  link: `https://vercel.com/docs/frameworks/backend/${framework}#exporting-the-${framework}-application`,
@@ -5223,7 +5376,7 @@ async function detectGenericPythonEntrypoint(workPath) {
5223
5376
  );
5224
5377
  return found ? { entrypoint: found } : null;
5225
5378
  } catch {
5226
- (0, import_build_utils8.debug)("Failed to discover Python entrypoint");
5379
+ (0, import_build_utils9.debug)("Failed to discover Python entrypoint");
5227
5380
  return null;
5228
5381
  }
5229
5382
  }
@@ -5232,7 +5385,7 @@ async function detectDjangoPythonEntrypoint(workPath) {
5232
5385
  const subdirs = await getSubdirectories(workPath);
5233
5386
  const rootDirs = ["", ...subdirs];
5234
5387
  for (const rootDir of rootDirs) {
5235
- const currPath = (0, import_path8.join)(workPath, rootDir);
5388
+ const currPath = (0, import_path9.join)(workPath, rootDir);
5236
5389
  const isDjango = await checkDjangoManage(currPath);
5237
5390
  if (isDjango) {
5238
5391
  return { baseDir: rootDir, error: makeDetectError("django") };
@@ -5242,7 +5395,7 @@ async function detectDjangoPythonEntrypoint(workPath) {
5242
5395
  const found = await findValidEntrypoint(workPath, candidates);
5243
5396
  return found ? { entrypoint: found } : null;
5244
5397
  } catch {
5245
- (0, import_build_utils8.debug)("Failed to discover Django Python entrypoint");
5398
+ (0, import_build_utils9.debug)("Failed to discover Django Python entrypoint");
5246
5399
  return null;
5247
5400
  }
5248
5401
  }
@@ -5258,11 +5411,11 @@ async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint,
5258
5411
  }
5259
5412
  }
5260
5413
  if (varName) {
5261
- (0, import_build_utils8.debug)(`Using configured Python entrypoint: ${entrypoint}`);
5414
+ (0, import_build_utils9.debug)(`Using configured Python entrypoint: ${entrypoint}`);
5262
5415
  return { entrypoint: { entrypoint, variableName: varName } };
5263
5416
  } else {
5264
5417
  return {
5265
- error: new import_build_utils7.NowBuildError({
5418
+ error: new import_build_utils8.NowBuildError({
5266
5419
  code: "PYTHON_ENTRYPOINT_NOT_FOUND",
5267
5420
  message: `Could not find a top-level "app", "application", or "handler" in "${entrypoint}".`,
5268
5421
  link: "https://vercel.com/docs/functions/serverless-functions/runtimes/python",
@@ -5368,17 +5521,17 @@ async function syncDependencies({
5368
5521
  let { manifestPath } = installInfo;
5369
5522
  const manifest = pythonPackage.manifest;
5370
5523
  if (!manifestType || !manifestPath) {
5371
- (0, import_build_utils10.debug)("No Python project manifest found, skipping dependency sync");
5524
+ (0, import_build_utils11.debug)("No Python project manifest found, skipping dependency sync");
5372
5525
  return;
5373
5526
  }
5374
5527
  if (manifest?.origin && manifestType === "pyproject.toml") {
5375
- const syncDir = (0, import_path9.join)(workPath, ".vercel", "python", "sync");
5376
- (0, import_fs8.mkdirSync)(syncDir, { recursive: true });
5377
- const tempPyproject = (0, import_path9.join)(syncDir, "pyproject.toml");
5528
+ const syncDir = (0, import_path10.join)(workPath, ".vercel", "python", "sync");
5529
+ (0, import_fs9.mkdirSync)(syncDir, { recursive: true });
5530
+ const tempPyproject = (0, import_path10.join)(syncDir, "pyproject.toml");
5378
5531
  const content = (0, import_python_analysis6.stringifyManifest)(manifest.data);
5379
- (0, import_fs8.writeFileSync)(tempPyproject, content, "utf8");
5532
+ (0, import_fs9.writeFileSync)(tempPyproject, content, "utf8");
5380
5533
  manifestPath = tempPyproject;
5381
- (0, import_build_utils10.debug)(
5534
+ (0, import_build_utils11.debug)(
5382
5535
  `Wrote converted ${manifest.origin.kind} manifest to ${tempPyproject}`
5383
5536
  );
5384
5537
  }
@@ -5411,7 +5564,7 @@ async function syncDependencies({
5411
5564
  for (const [channel, chunk] of captured) {
5412
5565
  (channel === "stdout" ? writeOut : writeErr)(chunk.toString());
5413
5566
  }
5414
- throw new import_build_utils10.NowBuildError({
5567
+ throw new import_build_utils11.NowBuildError({
5415
5568
  code: "PYTHON_DEPENDENCY_SYNC_FAILED",
5416
5569
  message: `Failed to install Python dependencies from ${manifestType}: ${err instanceof Error ? err.message : String(err)}`
5417
5570
  });
@@ -5426,14 +5579,14 @@ async function runSync({
5426
5579
  onStdout,
5427
5580
  onStderr
5428
5581
  }) {
5429
- const projectDir = (0, import_path9.dirname)(manifestPath);
5582
+ const projectDir = (0, import_path10.dirname)(manifestPath);
5430
5583
  const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
5431
5584
  let spawnCmd;
5432
5585
  let spawnArgs;
5433
5586
  switch (manifestType) {
5434
5587
  case "uv.lock": {
5435
5588
  if (!uvPath) {
5436
- throw new import_build_utils10.NowBuildError({
5589
+ throw new import_build_utils11.NowBuildError({
5437
5590
  code: "PYTHON_DEPENDENCY_SYNC_FAILED",
5438
5591
  message: "uv is required to install dependencies from uv.lock.",
5439
5592
  link: "https://docs.astral.sh/uv/getting-started/installation/",
@@ -5455,11 +5608,11 @@ async function runSync({
5455
5608
  break;
5456
5609
  }
5457
5610
  default:
5458
- (0, import_build_utils10.debug)(`Unknown manifest type: ${manifestType}`);
5611
+ (0, import_build_utils11.debug)(`Unknown manifest type: ${manifestType}`);
5459
5612
  return;
5460
5613
  }
5461
5614
  await new Promise((resolve3, reject) => {
5462
- (0, import_build_utils10.debug)(`Running "${spawnCmd} ${spawnArgs.join(" ")}" in ${projectDir}...`);
5615
+ (0, import_build_utils11.debug)(`Running "${spawnCmd} ${spawnArgs.join(" ")}" in ${projectDir}...`);
5463
5616
  const child = (0, import_child_process2.spawn)(spawnCmd, spawnArgs, {
5464
5617
  cwd: projectDir,
5465
5618
  env: getProtectedUvEnv(env),
@@ -5503,7 +5656,7 @@ async function installVercelRuntime({
5503
5656
  onStdout,
5504
5657
  onStderr
5505
5658
  }) {
5506
- const targetDir = (0, import_path9.join)(workPath, ".vercel", "python");
5659
+ const targetDir = (0, import_path10.join)(workPath, ".vercel", "python");
5507
5660
  let pending = PENDING_RUNTIME_INSTALLS.get(targetDir);
5508
5661
  if (!pending) {
5509
5662
  pending = doInstallVercelRuntime({
@@ -5529,8 +5682,8 @@ async function doInstallVercelRuntime({
5529
5682
  onStdout,
5530
5683
  onStderr
5531
5684
  }) {
5532
- (0, import_fs8.mkdirSync)(targetDir, { recursive: true });
5533
- const localRuntimeDir = (0, import_path9.join)(
5685
+ (0, import_fs9.mkdirSync)(targetDir, { recursive: true });
5686
+ const localRuntimeDir = (0, import_path10.join)(
5534
5687
  __dirname,
5535
5688
  "..",
5536
5689
  "..",
@@ -5538,21 +5691,21 @@ async function doInstallVercelRuntime({
5538
5691
  "python",
5539
5692
  "vercel-runtime"
5540
5693
  );
5541
- const isLocalDev = (0, import_fs8.existsSync)((0, import_path9.join)(localRuntimeDir, "pyproject.toml"));
5694
+ const isLocalDev = (0, import_fs9.existsSync)((0, import_path10.join)(localRuntimeDir, "pyproject.toml"));
5542
5695
  const runtimeDep = env.VERCEL_RUNTIME_PYTHON || (isLocalDev ? localRuntimeDir : `vercel-runtime==${VERCEL_RUNTIME_VERSION}`);
5543
5696
  if (!isLocalDev && !env.VERCEL_RUNTIME_PYTHON) {
5544
- const distInfo = (0, import_path9.join)(
5697
+ const distInfo = (0, import_path10.join)(
5545
5698
  targetDir,
5546
5699
  `vercel_runtime-${VERCEL_RUNTIME_VERSION}.dist-info`
5547
5700
  );
5548
- if ((0, import_fs8.existsSync)(distInfo)) {
5549
- (0, import_build_utils10.debug)(
5701
+ if ((0, import_fs9.existsSync)(distInfo)) {
5702
+ (0, import_build_utils11.debug)(
5550
5703
  `vercel-runtime ${VERCEL_RUNTIME_VERSION} already installed, skipping`
5551
5704
  );
5552
5705
  return;
5553
5706
  }
5554
5707
  }
5555
- (0, import_build_utils10.debug)(
5708
+ (0, import_build_utils11.debug)(
5556
5709
  `Installing vercel-runtime into ${targetDir} (type: ${isLocalDev ? "local" : "pypi"}, source: ${runtimeDep})`
5557
5710
  );
5558
5711
  const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
@@ -5567,14 +5720,14 @@ async function doInstallVercelRuntime({
5567
5720
  if (onStdout) {
5568
5721
  onStdout(data);
5569
5722
  } else {
5570
- (0, import_build_utils10.debug)(data.toString());
5723
+ (0, import_build_utils11.debug)(data.toString());
5571
5724
  }
5572
5725
  });
5573
5726
  child.stderr?.on("data", (data) => {
5574
5727
  if (onStderr) {
5575
5728
  onStderr(data);
5576
5729
  } else {
5577
- (0, import_build_utils10.debug)(data.toString());
5730
+ (0, import_build_utils11.debug)(data.toString());
5578
5731
  }
5579
5732
  });
5580
5733
  child.on("error", reject);
@@ -5599,7 +5752,7 @@ async function installVercelWorkers({
5599
5752
  onStdout,
5600
5753
  onStderr
5601
5754
  }) {
5602
- const targetDir = (0, import_path9.join)(workPath, ".vercel", "python");
5755
+ const targetDir = (0, import_path10.join)(workPath, ".vercel", "python");
5603
5756
  let pending = PENDING_WORKERS_INSTALLS.get(targetDir);
5604
5757
  if (!pending) {
5605
5758
  pending = doInstallVercelWorkers({
@@ -5625,8 +5778,8 @@ async function doInstallVercelWorkers({
5625
5778
  onStdout,
5626
5779
  onStderr
5627
5780
  }) {
5628
- (0, import_fs8.mkdirSync)(targetDir, { recursive: true });
5629
- const localWorkersDir = (0, import_path9.join)(
5781
+ (0, import_fs9.mkdirSync)(targetDir, { recursive: true });
5782
+ const localWorkersDir = (0, import_path10.join)(
5630
5783
  __dirname,
5631
5784
  "..",
5632
5785
  "..",
@@ -5634,21 +5787,21 @@ async function doInstallVercelWorkers({
5634
5787
  "python",
5635
5788
  "vercel-workers"
5636
5789
  );
5637
- const isLocalDev = (0, import_fs8.existsSync)((0, import_path9.join)(localWorkersDir, "pyproject.toml"));
5790
+ const isLocalDev = (0, import_fs9.existsSync)((0, import_path10.join)(localWorkersDir, "pyproject.toml"));
5638
5791
  const workersDep = env.VERCEL_WORKERS_PYTHON || (isLocalDev ? localWorkersDir : `vercel-workers==${VERCEL_WORKERS_VERSION}`);
5639
5792
  if (!isLocalDev && !env.VERCEL_WORKERS_PYTHON) {
5640
- const distInfo = (0, import_path9.join)(
5793
+ const distInfo = (0, import_path10.join)(
5641
5794
  targetDir,
5642
5795
  `vercel_workers-${VERCEL_WORKERS_VERSION}.dist-info`
5643
5796
  );
5644
- if ((0, import_fs8.existsSync)(distInfo)) {
5645
- (0, import_build_utils10.debug)(
5797
+ if ((0, import_fs9.existsSync)(distInfo)) {
5798
+ (0, import_build_utils11.debug)(
5646
5799
  `vercel-workers ${VERCEL_WORKERS_VERSION} already installed, skipping`
5647
5800
  );
5648
5801
  return;
5649
5802
  }
5650
5803
  }
5651
- (0, import_build_utils10.debug)(
5804
+ (0, import_build_utils11.debug)(
5652
5805
  `Installing vercel-workers into ${targetDir} (type: ${isLocalDev ? "local" : "pypi"}, source: ${workersDep})`
5653
5806
  );
5654
5807
  const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
@@ -5663,14 +5816,14 @@ async function doInstallVercelWorkers({
5663
5816
  if (onStdout) {
5664
5817
  onStdout(data);
5665
5818
  } else {
5666
- (0, import_build_utils10.debug)(data.toString());
5819
+ (0, import_build_utils11.debug)(data.toString());
5667
5820
  }
5668
5821
  });
5669
5822
  child.stderr?.on("data", (data) => {
5670
5823
  if (onStderr) {
5671
5824
  onStderr(data);
5672
5825
  } else {
5673
- (0, import_build_utils10.debug)(data.toString());
5826
+ (0, import_build_utils11.debug)(data.toString());
5674
5827
  }
5675
5828
  });
5676
5829
  child.on("error", reject);
@@ -5700,12 +5853,12 @@ function installGlobalCleanupHandlers() {
5700
5853
  try {
5701
5854
  process.kill(info.pid, "SIGTERM");
5702
5855
  } catch (err) {
5703
- (0, import_build_utils10.debug)(`Error sending SIGTERM to ${info.pid}: ${err}`);
5856
+ (0, import_build_utils11.debug)(`Error sending SIGTERM to ${info.pid}: ${err}`);
5704
5857
  }
5705
5858
  try {
5706
5859
  process.kill(info.pid, "SIGKILL");
5707
5860
  } catch (err) {
5708
- (0, import_build_utils10.debug)(`Error sending SIGKILL to ${info.pid}: ${err}`);
5861
+ (0, import_build_utils11.debug)(`Error sending SIGKILL to ${info.pid}: ${err}`);
5709
5862
  }
5710
5863
  PERSISTENT_SERVERS.delete(key);
5711
5864
  }
@@ -5713,7 +5866,7 @@ function installGlobalCleanupHandlers() {
5713
5866
  try {
5714
5867
  restoreWarnings();
5715
5868
  } catch (err) {
5716
- (0, import_build_utils10.debug)(`Error restoring warnings: ${err}`);
5869
+ (0, import_build_utils11.debug)(`Error restoring warnings: ${err}`);
5717
5870
  }
5718
5871
  restoreWarnings = null;
5719
5872
  }
@@ -5730,55 +5883,55 @@ function installGlobalCleanupHandlers() {
5730
5883
  }
5731
5884
  function createDevShim(workPath, entry, modulePath, serviceName, framework, variableName) {
5732
5885
  try {
5733
- const vercelPythonDir = serviceName ? (0, import_path9.join)(workPath, ".vercel", "python", "services", serviceName) : (0, import_path9.join)(workPath, ".vercel", "python");
5734
- (0, import_fs8.mkdirSync)(vercelPythonDir, { recursive: true });
5886
+ const vercelPythonDir = serviceName ? (0, import_path10.join)(workPath, ".vercel", "python", "services", serviceName) : (0, import_path10.join)(workPath, ".vercel", "python");
5887
+ (0, import_fs9.mkdirSync)(vercelPythonDir, { recursive: true });
5735
5888
  let qualifiedModule = modulePath;
5736
5889
  let extraPythonPath;
5737
- if ((0, import_fs8.existsSync)((0, import_path9.join)(workPath, "__init__.py"))) {
5738
- const pkgName = (0, import_path9.basename)(workPath);
5890
+ if ((0, import_fs9.existsSync)((0, import_path10.join)(workPath, "__init__.py"))) {
5891
+ const pkgName = (0, import_path10.basename)(workPath);
5739
5892
  qualifiedModule = `${pkgName}.${modulePath}`;
5740
- extraPythonPath = (0, import_path9.dirname)(workPath);
5893
+ extraPythonPath = (0, import_path10.dirname)(workPath);
5741
5894
  }
5742
- const entryAbs = (0, import_path9.join)(workPath, entry);
5743
- const shimPath = (0, import_path9.join)(vercelPythonDir, `${DEV_SHIM_MODULE}.py`);
5744
- const templatePath = (0, import_path9.join)(
5895
+ const entryAbs = (0, import_path10.join)(workPath, entry);
5896
+ const shimPath = (0, import_path10.join)(vercelPythonDir, `${DEV_SHIM_MODULE}.py`);
5897
+ const templatePath = (0, import_path10.join)(
5745
5898
  __dirname,
5746
5899
  "..",
5747
5900
  "templates",
5748
5901
  `${DEV_SHIM_MODULE}.py`
5749
5902
  );
5750
- const template = (0, import_fs8.readFileSync)(templatePath, "utf8");
5903
+ const template = (0, import_fs9.readFileSync)(templatePath, "utf8");
5751
5904
  const shimSource = template.replace(/__VC_DEV_MODULE_NAME__/g, qualifiedModule).replace(/__VC_DEV_ENTRY_ABS__/g, entryAbs).replace(/__VC_DEV_FRAMEWORK__/g, framework).replace(/__VC_DEV_VARIABLE_NAME__/g, variableName);
5752
- (0, import_fs8.writeFileSync)(shimPath, shimSource, "utf8");
5753
- (0, import_build_utils10.debug)(`Prepared Python dev shim at ${shimPath}`);
5905
+ (0, import_fs9.writeFileSync)(shimPath, shimSource, "utf8");
5906
+ (0, import_build_utils11.debug)(`Prepared Python dev shim at ${shimPath}`);
5754
5907
  return {
5755
5908
  module: DEV_SHIM_MODULE,
5756
5909
  extraPythonPath,
5757
5910
  shimDir: vercelPythonDir
5758
5911
  };
5759
5912
  } catch (err) {
5760
- (0, import_build_utils10.debug)(`Failed to prepare dev shim: ${err?.message || err}`);
5913
+ (0, import_build_utils11.debug)(`Failed to prepare dev shim: ${err?.message || err}`);
5761
5914
  return null;
5762
5915
  }
5763
5916
  }
5764
5917
  async function getMultiServicePythonRunner(workPath, env, systemPython, uvPath) {
5765
5918
  const { pythonCmd, venvRoot } = useVirtualEnv(workPath, env, systemPython);
5766
5919
  if (venvRoot) {
5767
- (0, import_build_utils10.debug)(`Using existing virtualenv at ${venvRoot} for multi-service dev`);
5920
+ (0, import_build_utils11.debug)(`Using existing virtualenv at ${venvRoot} for multi-service dev`);
5768
5921
  return { command: pythonCmd, args: [] };
5769
5922
  }
5770
- const venvPath = (0, import_path9.join)(workPath, ".venv");
5923
+ const venvPath = (0, import_path10.join)(workPath, ".venv");
5771
5924
  await ensureVenv({
5772
5925
  pythonVersion: { pythonPath: systemPython },
5773
5926
  venvPath,
5774
5927
  uvPath,
5775
5928
  quiet: true
5776
5929
  });
5777
- (0, import_build_utils10.debug)(`Created virtualenv at ${venvPath} for multi-service dev`);
5930
+ (0, import_build_utils11.debug)(`Created virtualenv at ${venvPath} for multi-service dev`);
5778
5931
  const pythonBin = getVenvPythonBin(venvPath);
5779
5932
  const binDir = getVenvBinDir(venvPath);
5780
5933
  env.VIRTUAL_ENV = venvPath;
5781
- env.PATH = `${binDir}${import_path9.delimiter}${env.PATH || ""}`;
5934
+ env.PATH = `${binDir}${import_path10.delimiter}${env.PATH || ""}`;
5782
5935
  return { command: pythonBin, args: [] };
5783
5936
  }
5784
5937
  var startDevServer = async (opts) => {
@@ -5841,7 +5994,7 @@ var startDevServer = async (opts) => {
5841
5994
  } else {
5842
5995
  const hookResult = await runFrameworkHook(framework, {
5843
5996
  pythonEnv: env,
5844
- projectDir: (0, import_path9.join)(workPath, detected?.baseDir ?? ""),
5997
+ projectDir: (0, import_path10.join)(workPath, detected?.baseDir ?? ""),
5845
5998
  workPath,
5846
5999
  entrypoint,
5847
6000
  detected: detected ?? void 0
@@ -5852,7 +6005,7 @@ var startDevServer = async (opts) => {
5852
6005
  if (detected?.error) {
5853
6006
  throw detected.error;
5854
6007
  }
5855
- throw new import_build_utils10.NowBuildError({
6008
+ throw new import_build_utils11.NowBuildError({
5856
6009
  code: "PYTHON_ENTRYPOINT_NOT_FOUND",
5857
6010
  message: "No Python entrypoint could be detected. Please specify an entrypoint file."
5858
6011
  });
@@ -5881,7 +6034,7 @@ var startDevServer = async (opts) => {
5881
6034
  const yellow = "\x1B[33m";
5882
6035
  const white = "\x1B[1m";
5883
6036
  const reset = "\x1B[0m";
5884
- throw new import_build_utils10.NowBuildError({
6037
+ throw new import_build_utils11.NowBuildError({
5885
6038
  code: "PYTHON_EXTERNAL_VENV_DETECTED",
5886
6039
  message: `Detected activated venv at ${yellow}${venv}${reset}, ${white}vercel dev${reset} manages virtual environments automatically.
5887
6040
  Run ${white}deactivate${reset} and try again.`
@@ -5898,11 +6051,11 @@ Run ${white}deactivate${reset} and try again.`
5898
6051
  );
5899
6052
  spawnCommand = runner.command;
5900
6053
  spawnArgsPrefix = runner.args;
5901
- (0, import_build_utils10.debug)(
6054
+ (0, import_build_utils11.debug)(
5902
6055
  `Multi-service Python runner: ${spawnCommand} ${spawnArgsPrefix.join(" ")}`
5903
6056
  );
5904
6057
  } else if (venv) {
5905
- (0, import_build_utils10.debug)(`Running in virtualenv at ${venv}`);
6058
+ (0, import_build_utils11.debug)(`Running in virtualenv at ${venv}`);
5906
6059
  } else {
5907
6060
  const { pythonCmd: venvPythonCmd, venvRoot } = useVirtualEnv(
5908
6061
  workPath,
@@ -5911,9 +6064,9 @@ Run ${white}deactivate${reset} and try again.`
5911
6064
  );
5912
6065
  spawnCommand = venvPythonCmd;
5913
6066
  if (venvRoot) {
5914
- (0, import_build_utils10.debug)(`Using virtualenv at ${venvRoot}`);
6067
+ (0, import_build_utils11.debug)(`Using virtualenv at ${venvRoot}`);
5915
6068
  } else {
5916
- (0, import_build_utils10.debug)("No virtualenv found");
6069
+ (0, import_build_utils11.debug)("No virtualenv found");
5917
6070
  try {
5918
6071
  const yellow = "\x1B[33m";
5919
6072
  const reset = "\x1B[0m";
@@ -5962,13 +6115,22 @@ If you are using a virtual environment, activate it before running "vercel dev",
5962
6115
  onStderr
5963
6116
  });
5964
6117
  }
6118
+ const crons = await getServiceCrons({
6119
+ service,
6120
+ entrypoint,
6121
+ rawEntrypoint,
6122
+ handlerFunction,
6123
+ pythonBin: spawnCommand,
6124
+ env,
6125
+ workPath
6126
+ });
6127
+ if (crons?.length) {
6128
+ env.__VC_CRON_ROUTES = JSON.stringify(buildCronRouteTable(crons));
6129
+ }
5965
6130
  const port = typeof meta.port === "number" ? meta.port : await (0, import_get_port.default)();
5966
6131
  env.PORT = `${port}`;
5967
- if (config.handlerFunction && typeof config?.handlerFunction === "string") {
5968
- env.__VC_HANDLER_FUNC_NAME = config.handlerFunction;
5969
- }
5970
6132
  if (entry) {
5971
- env.__VC_HANDLER_ENTRYPOINT_ABS = (0, import_path9.join)(workPath, entry);
6133
+ env.__VC_HANDLER_ENTRYPOINT_ABS = (0, import_path10.join)(workPath, entry);
5972
6134
  }
5973
6135
  const devShim = createDevShim(
5974
6136
  workPath,
@@ -5979,8 +6141,8 @@ If you are using a virtual environment, activate it before running "vercel dev",
5979
6141
  variableName ?? ""
5980
6142
  );
5981
6143
  if (devShim) {
5982
- const shimDir = devShim.shimDir || (0, import_path9.join)(workPath, ".vercel", "python");
5983
- const runtimeDir = (0, import_path9.join)(workPath, ".vercel", "python");
6144
+ const shimDir = devShim.shimDir || (0, import_path10.join)(workPath, ".vercel", "python");
6145
+ const runtimeDir = (0, import_path10.join)(workPath, ".vercel", "python");
5984
6146
  const pathParts = shimDir !== runtimeDir ? [shimDir, runtimeDir] : [shimDir];
5985
6147
  if (devShim.extraPythonPath) {
5986
6148
  pathParts.push(devShim.extraPythonPath);
@@ -5989,12 +6151,12 @@ If you are using a virtual environment, activate it before running "vercel dev",
5989
6151
  if (existingPythonPath) {
5990
6152
  pathParts.push(existingPythonPath);
5991
6153
  }
5992
- env.PYTHONPATH = pathParts.join(import_path9.delimiter);
6154
+ env.PYTHONPATH = pathParts.join(import_path10.delimiter);
5993
6155
  }
5994
6156
  const moduleToRun = devShim?.module || modulePath;
5995
6157
  const pythonArgs = ["-u", "-m", moduleToRun];
5996
6158
  const argv = [...spawnArgsPrefix, ...pythonArgs];
5997
- (0, import_build_utils10.debug)(
6159
+ (0, import_build_utils11.debug)(
5998
6160
  `Starting Python dev server (${framework}): ${spawnCommand} ${argv.join(" ")} [PORT=${port}]`
5999
6161
  );
6000
6162
  if (process.stdout.columns) {
@@ -6038,7 +6200,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
6038
6200
  });
6039
6201
  const shutdown = async () => {
6040
6202
  };
6041
- return { port, pid, shutdown };
6203
+ return { port, pid, shutdown, crons };
6042
6204
  } catch (err) {
6043
6205
  rejectChildReady(err);
6044
6206
  throw err;
@@ -6048,7 +6210,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
6048
6210
  };
6049
6211
 
6050
6212
  // src/quirks/index.ts
6051
- var import_build_utils13 = require("@vercel/build-utils");
6213
+ var import_build_utils14 = require("@vercel/build-utils");
6052
6214
  var import_python_analysis8 = require("@vercel/python-analysis");
6053
6215
 
6054
6216
  // src/quirks/matplotlib.ts
@@ -6062,9 +6224,9 @@ var matplotlibQuirk = {
6062
6224
  };
6063
6225
 
6064
6226
  // src/quirks/litellm.ts
6065
- var import_fs9 = __toESM(require("fs"));
6066
- var import_path10 = require("path");
6067
- var import_build_utils11 = require("@vercel/build-utils");
6227
+ var import_fs10 = __toESM(require("fs"));
6228
+ var import_path11 = require("path");
6229
+ var import_build_utils12 = require("@vercel/build-utils");
6068
6230
  var LAMBDA_ROOT = "/var/task";
6069
6231
  var CONFIG_CANDIDATES = [
6070
6232
  "litellm_config.yaml",
@@ -6074,9 +6236,9 @@ var CONFIG_CANDIDATES = [
6074
6236
  ];
6075
6237
  async function findConfigFile(workPath) {
6076
6238
  for (const name of CONFIG_CANDIDATES) {
6077
- const candidate = (0, import_path10.join)(workPath, name);
6239
+ const candidate = (0, import_path11.join)(workPath, name);
6078
6240
  try {
6079
- await import_fs9.default.promises.access(candidate);
6241
+ await import_fs10.default.promises.access(candidate);
6080
6242
  return name;
6081
6243
  } catch {
6082
6244
  }
@@ -6091,32 +6253,32 @@ var litellmQuirk = {
6091
6253
  const env = {};
6092
6254
  const sitePackagesDirs = await getVenvSitePackagesDirs(ctx.venvPath);
6093
6255
  for (const sitePackages of sitePackagesDirs) {
6094
- const schemaPath = (0, import_path10.join)(
6256
+ const schemaPath = (0, import_path11.join)(
6095
6257
  sitePackages,
6096
6258
  "litellm",
6097
6259
  "proxy",
6098
6260
  "schema.prisma"
6099
6261
  );
6100
6262
  try {
6101
- await import_fs9.default.promises.access(schemaPath);
6102
- (0, import_build_utils11.debug)(`LiteLLM quirk: found schema at ${schemaPath}`);
6263
+ await import_fs10.default.promises.access(schemaPath);
6264
+ (0, import_build_utils12.debug)(`LiteLLM quirk: found schema at ${schemaPath}`);
6103
6265
  buildEnv.PRISMA_SCHEMA_PATH = schemaPath;
6104
6266
  break;
6105
6267
  } catch {
6106
6268
  }
6107
6269
  }
6108
6270
  if (!buildEnv.PRISMA_SCHEMA_PATH) {
6109
- (0, import_build_utils11.debug)("LiteLLM quirk: schema.prisma not found in any site-packages");
6271
+ (0, import_build_utils12.debug)("LiteLLM quirk: schema.prisma not found in any site-packages");
6110
6272
  }
6111
6273
  if (!process.env.CONFIG_FILE_PATH) {
6112
6274
  const configName = await findConfigFile(ctx.workPath);
6113
6275
  if (configName) {
6114
- (0, import_build_utils11.debug)(`LiteLLM quirk: found config at ${configName}`);
6115
- buildEnv.CONFIG_FILE_PATH = (0, import_path10.join)(ctx.workPath, configName);
6116
- env.CONFIG_FILE_PATH = (0, import_path10.join)(LAMBDA_ROOT, configName);
6276
+ (0, import_build_utils12.debug)(`LiteLLM quirk: found config at ${configName}`);
6277
+ buildEnv.CONFIG_FILE_PATH = (0, import_path11.join)(ctx.workPath, configName);
6278
+ env.CONFIG_FILE_PATH = (0, import_path11.join)(LAMBDA_ROOT, configName);
6117
6279
  }
6118
6280
  } else {
6119
- (0, import_build_utils11.debug)(
6281
+ (0, import_build_utils12.debug)(
6120
6282
  `LiteLLM quirk: CONFIG_FILE_PATH already set to ${process.env.CONFIG_FILE_PATH}`
6121
6283
  );
6122
6284
  }
@@ -6125,10 +6287,10 @@ var litellmQuirk = {
6125
6287
  };
6126
6288
 
6127
6289
  // src/quirks/prisma.ts
6128
- var import_fs10 = __toESM(require("fs"));
6129
- var import_path11 = require("path");
6130
- var import_execa4 = __toESM(require_execa());
6131
- var import_build_utils12 = require("@vercel/build-utils");
6290
+ var import_fs11 = __toESM(require("fs"));
6291
+ var import_path12 = require("path");
6292
+ var import_execa5 = __toESM(require_execa());
6293
+ var import_build_utils13 = require("@vercel/build-utils");
6132
6294
  var import_python_analysis7 = require("@vercel/python-analysis");
6133
6295
  function execErrorMessage(err) {
6134
6296
  if (err != null && typeof err === "object" && "stderr" in err) {
@@ -6166,22 +6328,22 @@ model DummyModel {
6166
6328
  async function findUserSchema(workPath) {
6167
6329
  const envPath = process.env.PRISMA_SCHEMA_PATH;
6168
6330
  if (envPath) {
6169
- const resolved = (0, import_path11.isAbsolute)(envPath) ? envPath : (0, import_path11.join)(workPath, envPath);
6331
+ const resolved = (0, import_path12.isAbsolute)(envPath) ? envPath : (0, import_path12.join)(workPath, envPath);
6170
6332
  try {
6171
- await import_fs10.default.promises.access(resolved);
6333
+ await import_fs11.default.promises.access(resolved);
6172
6334
  return resolved;
6173
6335
  } catch {
6174
- (0, import_build_utils12.debug)(`PRISMA_SCHEMA_PATH=${envPath} not found at ${resolved}`);
6336
+ (0, import_build_utils13.debug)(`PRISMA_SCHEMA_PATH=${envPath} not found at ${resolved}`);
6175
6337
  return null;
6176
6338
  }
6177
6339
  }
6178
6340
  const candidates = [
6179
- (0, import_path11.join)(workPath, "schema.prisma"),
6180
- (0, import_path11.join)(workPath, "prisma", "schema.prisma")
6341
+ (0, import_path12.join)(workPath, "schema.prisma"),
6342
+ (0, import_path12.join)(workPath, "prisma", "schema.prisma")
6181
6343
  ];
6182
6344
  for (const candidate of candidates) {
6183
6345
  try {
6184
- await import_fs10.default.promises.access(candidate);
6346
+ await import_fs11.default.promises.access(candidate);
6185
6347
  return candidate;
6186
6348
  } catch {
6187
6349
  }
@@ -6192,32 +6354,32 @@ async function collectFiles(dir, base) {
6192
6354
  const result = [];
6193
6355
  let entries;
6194
6356
  try {
6195
- entries = await import_fs10.default.promises.readdir(dir, { withFileTypes: true });
6357
+ entries = await import_fs11.default.promises.readdir(dir, { withFileTypes: true });
6196
6358
  } catch {
6197
6359
  return result;
6198
6360
  }
6199
6361
  for (const entry of entries) {
6200
6362
  if (entry.name === "__pycache__")
6201
6363
  continue;
6202
- const full = (0, import_path11.join)(dir, entry.name);
6364
+ const full = (0, import_path12.join)(dir, entry.name);
6203
6365
  if (entry.isDirectory()) {
6204
6366
  result.push(...await collectFiles(full, base));
6205
6367
  } else {
6206
- result.push((0, import_path11.relative)(base, full));
6368
+ result.push((0, import_path12.relative)(base, full));
6207
6369
  }
6208
6370
  }
6209
6371
  return result;
6210
6372
  }
6211
6373
  async function cleanCacheArtifacts(cacheDir, extras = []) {
6212
6374
  const paths = [
6213
- (0, import_path11.join)(cacheDir, "node_modules"),
6214
- (0, import_path11.join)(cacheDir, "package.json"),
6215
- (0, import_path11.join)(cacheDir, "package-lock.json"),
6375
+ (0, import_path12.join)(cacheDir, "node_modules"),
6376
+ (0, import_path12.join)(cacheDir, "package.json"),
6377
+ (0, import_path12.join)(cacheDir, "package-lock.json"),
6216
6378
  ...extras
6217
6379
  ];
6218
6380
  for (const p of paths) {
6219
6381
  try {
6220
- await import_fs10.default.promises.rm(p, { recursive: true, force: true });
6382
+ await import_fs11.default.promises.rm(p, { recursive: true, force: true });
6221
6383
  } catch (err) {
6222
6384
  console.warn(
6223
6385
  `could not clean up ${p}: ${err instanceof Error ? err.message : String(err)}`
@@ -6227,7 +6389,7 @@ async function cleanCacheArtifacts(cacheDir, extras = []) {
6227
6389
  }
6228
6390
  async function isClientGenerated(pythonPath, env) {
6229
6391
  try {
6230
- await (0, import_execa4.default)(pythonPath, ["-c", "import prisma.client"], {
6392
+ await (0, import_execa5.default)(pythonPath, ["-c", "import prisma.client"], {
6231
6393
  env,
6232
6394
  stdio: "pipe"
6233
6395
  });
@@ -6241,7 +6403,7 @@ var prismaQuirk = {
6241
6403
  async run(ctx) {
6242
6404
  const { venvPath, pythonEnv, workPath } = ctx;
6243
6405
  const pythonPath = getVenvPythonBin(venvPath);
6244
- const runtimeCacheDir = (0, import_path11.join)(
6406
+ const runtimeCacheDir = (0, import_path12.join)(
6245
6407
  LAMBDA_ROOT2,
6246
6408
  resolveVendorDir(),
6247
6409
  "prisma",
@@ -6251,7 +6413,7 @@ var prismaQuirk = {
6251
6413
  let sitePackages;
6252
6414
  for (const dir of sitePackagesDirs) {
6253
6415
  try {
6254
- await import_fs10.default.promises.access((0, import_path11.join)(dir, "prisma"));
6416
+ await import_fs11.default.promises.access((0, import_path12.join)(dir, "prisma"));
6255
6417
  sitePackages = dir;
6256
6418
  break;
6257
6419
  } catch {
@@ -6263,21 +6425,21 @@ var prismaQuirk = {
6263
6425
  );
6264
6426
  return {};
6265
6427
  }
6266
- const cacheDir = (0, import_path11.join)(sitePackages, "prisma", "__bincache__");
6267
- await import_fs10.default.promises.mkdir(cacheDir, { recursive: true });
6428
+ const cacheDir = (0, import_path12.join)(sitePackages, "prisma", "__bincache__");
6429
+ await import_fs11.default.promises.mkdir(cacheDir, { recursive: true });
6268
6430
  const generateEnv = {
6269
6431
  ...pythonEnv,
6270
6432
  PRISMA_BINARY_CACHE_DIR: cacheDir
6271
6433
  };
6272
- const generatedDir = (0, import_path11.join)(workPath, "_prisma_generated");
6273
- const dummySchemaPath = (0, import_path11.join)(workPath, DUMMY_SCHEMA_NAME);
6274
- await import_fs10.default.promises.writeFile(
6434
+ const generatedDir = (0, import_path12.join)(workPath, "_prisma_generated");
6435
+ const dummySchemaPath = (0, import_path12.join)(workPath, DUMMY_SCHEMA_NAME);
6436
+ await import_fs11.default.promises.writeFile(
6275
6437
  dummySchemaPath,
6276
6438
  buildDummySchema(generatedDir)
6277
6439
  );
6278
- (0, import_build_utils12.debug)(`Running prisma generate (dummy) with cache dir: ${cacheDir}`);
6440
+ (0, import_build_utils13.debug)(`Running prisma generate (dummy) with cache dir: ${cacheDir}`);
6279
6441
  try {
6280
- const dummyResult = await (0, import_execa4.default)(
6442
+ const dummyResult = await (0, import_execa5.default)(
6281
6443
  pythonPath,
6282
6444
  ["-m", "prisma", "generate", `--schema=${dummySchemaPath}`],
6283
6445
  {
@@ -6287,11 +6449,11 @@ var prismaQuirk = {
6287
6449
  }
6288
6450
  );
6289
6451
  if (dummyResult.stdout)
6290
- (0, import_build_utils12.debug)(`prisma generate (dummy) stdout: ${dummyResult.stdout}`);
6452
+ (0, import_build_utils13.debug)(`prisma generate (dummy) stdout: ${dummyResult.stdout}`);
6291
6453
  if (dummyResult.stderr)
6292
- (0, import_build_utils12.debug)(`prisma generate (dummy) stderr: ${dummyResult.stderr}`);
6454
+ (0, import_build_utils13.debug)(`prisma generate (dummy) stderr: ${dummyResult.stderr}`);
6293
6455
  } catch (err) {
6294
- throw new import_build_utils12.NowBuildError({
6456
+ throw new import_build_utils13.NowBuildError({
6295
6457
  code: "PRISMA_GENERATE_FAILED",
6296
6458
  message: `Prisma engine download failed during \`prisma generate\`. Check that your prisma version is compatible with this Python version.
6297
6459
  ` + execErrorMessage(err)
@@ -6299,47 +6461,47 @@ var prismaQuirk = {
6299
6461
  }
6300
6462
  const srcBinaryPrefix = `query-engine-${getLambdaBinaryTarget()}`;
6301
6463
  const runtimeName = `prisma-query-engine-rhel-openssl-${RUNTIME_OPENSSL_VERSION}.x`;
6302
- const nodeModulesDir = (0, import_path11.join)(cacheDir, "node_modules", "prisma");
6464
+ const nodeModulesDir = (0, import_path12.join)(cacheDir, "node_modules", "prisma");
6303
6465
  let engineCopied = false;
6304
6466
  try {
6305
- const entries = await import_fs10.default.promises.readdir(nodeModulesDir);
6467
+ const entries = await import_fs11.default.promises.readdir(nodeModulesDir);
6306
6468
  for (const entry of entries) {
6307
6469
  if (!entry.startsWith(srcBinaryPrefix))
6308
6470
  continue;
6309
- const srcPath = (0, import_path11.join)(nodeModulesDir, entry);
6310
- const destPath = (0, import_path11.join)(cacheDir, runtimeName);
6471
+ const srcPath = (0, import_path12.join)(nodeModulesDir, entry);
6472
+ const destPath = (0, import_path12.join)(cacheDir, runtimeName);
6311
6473
  try {
6312
- await import_fs10.default.promises.access(destPath);
6313
- (0, import_build_utils12.debug)(`Engine binary: ${runtimeName} already exists, skipping`);
6474
+ await import_fs11.default.promises.access(destPath);
6475
+ (0, import_build_utils13.debug)(`Engine binary: ${runtimeName} already exists, skipping`);
6314
6476
  } catch {
6315
- (0, import_build_utils12.debug)(`Engine binary: copying ${entry} -> ${runtimeName}`);
6316
- await import_fs10.default.promises.copyFile(srcPath, destPath);
6477
+ (0, import_build_utils13.debug)(`Engine binary: copying ${entry} -> ${runtimeName}`);
6478
+ await import_fs11.default.promises.copyFile(srcPath, destPath);
6317
6479
  }
6318
6480
  engineCopied = true;
6319
6481
  }
6320
6482
  } catch (err) {
6321
- throw new import_build_utils12.NowBuildError({
6483
+ throw new import_build_utils13.NowBuildError({
6322
6484
  code: "PRISMA_ENGINE_NOT_FOUND",
6323
6485
  message: `could not read Prisma engine directory "${nodeModulesDir}". This may indicate an incompatible prisma version.
6324
6486
  ` + (err instanceof Error ? err.message : String(err))
6325
6487
  });
6326
6488
  }
6327
6489
  if (!engineCopied) {
6328
- throw new import_build_utils12.NowBuildError({
6490
+ throw new import_build_utils13.NowBuildError({
6329
6491
  code: "PRISMA_ENGINE_NOT_FOUND",
6330
6492
  message: `could not find engine binary matching "${srcBinaryPrefix}*" in "${nodeModulesDir}". This may indicate an incompatible prisma version or an unsupported platform (${process.arch}).`
6331
6493
  });
6332
6494
  }
6333
- const shimPath = (0, import_path11.join)(cacheDir, "openssl");
6334
- await import_fs10.default.promises.writeFile(
6495
+ const shimPath = (0, import_path12.join)(cacheDir, "openssl");
6496
+ await import_fs11.default.promises.writeFile(
6335
6497
  shimPath,
6336
6498
  `#!/bin/sh
6337
6499
  echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIME_OPENSSL_VERSION}.0)"
6338
6500
  `
6339
6501
  );
6340
- await import_fs10.default.promises.chmod(shimPath, 493);
6502
+ await import_fs11.default.promises.chmod(shimPath, 493);
6341
6503
  for (const p of [generatedDir, dummySchemaPath]) {
6342
- await import_fs10.default.promises.rm(p, { recursive: true, force: true });
6504
+ await import_fs11.default.promises.rm(p, { recursive: true, force: true });
6343
6505
  }
6344
6506
  await cleanCacheArtifacts(cacheDir);
6345
6507
  const generateMode = (process.env.VERCEL_PRISMA_GENERATE_CLIENT ?? "auto").toLowerCase();
@@ -6352,16 +6514,16 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
6352
6514
  pythonEnv
6353
6515
  );
6354
6516
  if (clientAlreadyGenerated) {
6355
- (0, import_build_utils12.debug)(
6517
+ (0, import_build_utils13.debug)(
6356
6518
  "Prisma quirk: client already generated, skipping user schema generate"
6357
6519
  );
6358
6520
  shouldGenerate = false;
6359
6521
  }
6360
6522
  }
6361
6523
  if (shouldGenerate) {
6362
- (0, import_build_utils12.debug)(`Running prisma generate with user schema: ${userSchema}`);
6524
+ (0, import_build_utils13.debug)(`Running prisma generate with user schema: ${userSchema}`);
6363
6525
  try {
6364
- const userResult = await (0, import_execa4.default)(
6526
+ const userResult = await (0, import_execa5.default)(
6365
6527
  pythonPath,
6366
6528
  ["-m", "prisma", "generate", `--schema=${userSchema}`],
6367
6529
  {
@@ -6371,11 +6533,11 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
6371
6533
  }
6372
6534
  );
6373
6535
  if (userResult.stdout)
6374
- (0, import_build_utils12.debug)(`prisma generate stdout: ${userResult.stdout}`);
6536
+ (0, import_build_utils13.debug)(`prisma generate stdout: ${userResult.stdout}`);
6375
6537
  if (userResult.stderr)
6376
- (0, import_build_utils12.debug)(`prisma generate stderr: ${userResult.stderr}`);
6538
+ (0, import_build_utils13.debug)(`prisma generate stderr: ${userResult.stderr}`);
6377
6539
  } catch (err) {
6378
- throw new import_build_utils12.NowBuildError({
6540
+ throw new import_build_utils13.NowBuildError({
6379
6541
  code: "PRISMA_GENERATE_FAILED",
6380
6542
  message: `\`prisma generate\` failed for schema "${userSchema}".
6381
6543
  ` + execErrorMessage(err)
@@ -6386,12 +6548,12 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
6386
6548
  }
6387
6549
  try {
6388
6550
  const allFiles = await collectFiles(
6389
- (0, import_path11.join)(sitePackages, "prisma"),
6551
+ (0, import_path12.join)(sitePackages, "prisma"),
6390
6552
  sitePackages
6391
6553
  );
6392
6554
  const count = await (0, import_python_analysis7.extendDistRecord)(sitePackages, "prisma", allFiles);
6393
6555
  if (count > 0) {
6394
- (0, import_build_utils12.debug)(`Appended ${count} entries to prisma RECORD`);
6556
+ (0, import_build_utils13.debug)(`Appended ${count} entries to prisma RECORD`);
6395
6557
  }
6396
6558
  } catch (err) {
6397
6559
  console.warn(
@@ -6485,13 +6647,13 @@ async function runQuirks(ctx) {
6485
6647
  (0, import_python_analysis8.normalizePackageName)(quirk.dependency)
6486
6648
  );
6487
6649
  if (!installed) {
6488
- (0, import_build_utils13.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
6650
+ (0, import_build_utils14.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
6489
6651
  }
6490
6652
  return installed;
6491
6653
  });
6492
6654
  const sorted = toposortQuirks(activated);
6493
6655
  for (const quirk of sorted) {
6494
- (0, import_build_utils13.debug)(`Quirk "${quirk.dependency}": detected, running fix-up`);
6656
+ (0, import_build_utils14.debug)(`Quirk "${quirk.dependency}": detected, running fix-up`);
6495
6657
  const result = await quirk.run(ctx);
6496
6658
  if (result.env) {
6497
6659
  Object.assign(mergedEnv, result.env);
@@ -6512,14 +6674,14 @@ async function runQuirks(ctx) {
6512
6674
  }
6513
6675
 
6514
6676
  // src/django.ts
6515
- var import_fs11 = __toESM(require("fs"));
6516
- var import_path12 = require("path");
6517
- var import_execa5 = __toESM(require_execa());
6518
- var import_build_utils14 = require("@vercel/build-utils");
6519
- var scriptPath = (0, import_path12.join)(__dirname, "..", "templates", "vc_django_settings.py");
6520
- var script = import_fs11.default.readFileSync(scriptPath, "utf-8");
6677
+ var import_fs12 = __toESM(require("fs"));
6678
+ var import_path13 = require("path");
6679
+ var import_execa6 = __toESM(require_execa());
6680
+ var import_build_utils15 = require("@vercel/build-utils");
6681
+ var scriptPath2 = (0, import_path13.join)(__dirname, "..", "templates", "vc_django_settings.py");
6682
+ var script2 = import_fs12.default.readFileSync(scriptPath2, "utf-8");
6521
6683
  async function getDjangoSettings(projectDir, env) {
6522
- const { stdout } = await (0, import_execa5.default)("python", ["-c", script], {
6684
+ const { stdout } = await (0, import_execa6.default)("python", ["-c", script2], {
6523
6685
  env,
6524
6686
  cwd: projectDir
6525
6687
  });
@@ -6545,21 +6707,21 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6545
6707
  const installedApps = djangoSettings["INSTALLED_APPS"] ?? [];
6546
6708
  const staticfilesDirs = djangoSettings["STATICFILES_DIRS"] ?? [];
6547
6709
  const staticSourceDirs = [
6548
- ...installedApps.map((app) => (0, import_path12.join)(workPath, ...app.split("."), "static")),
6710
+ ...installedApps.map((app) => (0, import_path13.join)(workPath, ...app.split("."), "static")),
6549
6711
  // TODO: Deal with optional prefixes in STATICFILES_DIRS.
6550
6712
  ...staticfilesDirs.map((d) => Array.isArray(d) ? d[1] : d)
6551
- ].filter((d) => import_fs11.default.existsSync(d));
6713
+ ].filter((d) => import_fs12.default.existsSync(d));
6552
6714
  if (storageBackend.startsWith("storages.backends.")) {
6553
6715
  console.log(
6554
6716
  "django-storages detected \u2014 running collectstatic with original settings"
6555
6717
  );
6556
- await (0, import_execa5.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6718
+ await (0, import_execa6.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6557
6719
  env: { ...env, DJANGO_SETTINGS_MODULE: settingsModule },
6558
6720
  cwd: workPath
6559
6721
  });
6560
6722
  return {
6561
6723
  staticSourceDirs,
6562
- staticRoot: staticRoot ? (0, import_path12.resolve)(workPath, staticRoot) : null,
6724
+ staticRoot: staticRoot ? (0, import_path13.resolve)(workPath, staticRoot) : null,
6563
6725
  cdnOutputDir: null,
6564
6726
  manifestRelPath: null
6565
6727
  };
@@ -6571,9 +6733,9 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6571
6733
  return null;
6572
6734
  }
6573
6735
  const staticUrlPath = staticUrl.replace(/^\/|\/$/g, "") || "static";
6574
- const staticOutputDir = (0, import_path12.join)(outputStaticDir, staticUrlPath);
6575
- await import_fs11.default.promises.mkdir(staticOutputDir, { recursive: true });
6576
- const shimPath = (0, import_path12.join)(workPath, "_vercel_collectstatic_settings.py");
6736
+ const staticOutputDir = (0, import_path13.join)(outputStaticDir, staticUrlPath);
6737
+ await import_fs12.default.promises.mkdir(staticOutputDir, { recursive: true });
6738
+ const shimPath = (0, import_path13.join)(workPath, "_vercel_collectstatic_settings.py");
6577
6739
  const shimLines = [
6578
6740
  `from ${settingsModule} import *`,
6579
6741
  `STATIC_ROOT = ${JSON.stringify(staticOutputDir)}`
@@ -6581,10 +6743,10 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6581
6743
  if (whitenoiseUseFinders) {
6582
6744
  shimLines.push(`WHITENOISE_USE_FINDERS = False`);
6583
6745
  }
6584
- await import_fs11.default.promises.writeFile(shimPath, shimLines.join("\n") + "\n");
6746
+ await import_fs12.default.promises.writeFile(shimPath, shimLines.join("\n") + "\n");
6585
6747
  try {
6586
6748
  console.log("Running collectstatic...");
6587
- await (0, import_execa5.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6749
+ await (0, import_execa6.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6588
6750
  env: {
6589
6751
  ...env,
6590
6752
  DJANGO_SETTINGS_MODULE: "_vercel_collectstatic_settings"
@@ -6592,7 +6754,7 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6592
6754
  cwd: workPath
6593
6755
  });
6594
6756
  } finally {
6595
- await import_fs11.default.promises.unlink(shimPath).catch(() => {
6757
+ await import_fs12.default.promises.unlink(shimPath).catch(() => {
6596
6758
  });
6597
6759
  }
6598
6760
  const MANIFEST_STORAGE_BACKENDS = [
@@ -6601,17 +6763,17 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6601
6763
  ];
6602
6764
  let manifestRelPath = null;
6603
6765
  if (MANIFEST_STORAGE_BACKENDS.includes(storageBackend) && staticRoot) {
6604
- const manifestSrc = (0, import_path12.join)(staticOutputDir, "staticfiles.json");
6605
- const resolvedStaticRoot = (0, import_path12.resolve)(workPath, staticRoot);
6606
- const manifestDest = (0, import_path12.join)(resolvedStaticRoot, "staticfiles.json");
6607
- await import_fs11.default.promises.mkdir(resolvedStaticRoot, { recursive: true });
6608
- await import_fs11.default.promises.copyFile(manifestSrc, manifestDest);
6609
- manifestRelPath = (0, import_path12.relative)(workPath, manifestDest);
6610
- (0, import_build_utils14.debug)(`Copied staticfiles.json to ${manifestDest} for Lambda bundle`);
6766
+ const manifestSrc = (0, import_path13.join)(staticOutputDir, "staticfiles.json");
6767
+ const resolvedStaticRoot = (0, import_path13.resolve)(workPath, staticRoot);
6768
+ const manifestDest = (0, import_path13.join)(resolvedStaticRoot, "staticfiles.json");
6769
+ await import_fs12.default.promises.mkdir(resolvedStaticRoot, { recursive: true });
6770
+ await import_fs12.default.promises.copyFile(manifestSrc, manifestDest);
6771
+ manifestRelPath = (0, import_path13.relative)(workPath, manifestDest);
6772
+ (0, import_build_utils15.debug)(`Copied staticfiles.json to ${manifestDest} for Lambda bundle`);
6611
6773
  }
6612
6774
  return {
6613
6775
  staticSourceDirs,
6614
- staticRoot: staticRoot ? (0, import_path12.resolve)(workPath, staticRoot) : null,
6776
+ staticRoot: staticRoot ? (0, import_path13.resolve)(workPath, staticRoot) : null,
6615
6777
  cdnOutputDir: outputStaticDir,
6616
6778
  manifestRelPath
6617
6779
  };
@@ -6619,7 +6781,7 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6619
6781
 
6620
6782
  // src/index.ts
6621
6783
  var import_python_analysis9 = require("@vercel/python-analysis");
6622
- var writeFile = import_fs12.default.promises.writeFile;
6784
+ var writeFile = import_fs13.default.promises.writeFile;
6623
6785
  var version = -1;
6624
6786
  async function runFrameworkHook(framework, ctx) {
6625
6787
  const hook = framework ? frameworkHooks[framework] : void 0;
@@ -6634,7 +6796,7 @@ var frameworkHooks = {
6634
6796
  detected
6635
6797
  }) => {
6636
6798
  if (detected?.baseDir === void 0) {
6637
- (0, import_build_utils15.debug)("Django hook: no manage.py detected, skipping");
6799
+ (0, import_build_utils16.debug)("Django hook: no manage.py detected, skipping");
6638
6800
  return;
6639
6801
  }
6640
6802
  let settingsResult;
@@ -6648,13 +6810,13 @@ Hint: activate a venv or run with \`uv run vercel dev\``;
6648
6810
  } else {
6649
6811
  detail = err?.stderr || err?.message || String(err);
6650
6812
  }
6651
- throw new import_build_utils15.NowBuildError({
6813
+ throw new import_build_utils16.NowBuildError({
6652
6814
  code: "DJANGO_SETTINGS_FAILED",
6653
6815
  message: `Failed to read Django application settings from ${projectDir}/manage.py:
6654
6816
  ${detail}`
6655
6817
  });
6656
6818
  }
6657
- (0, import_build_utils15.debug)(`Django settings: ${JSON.stringify(settingsResult)}`);
6819
+ (0, import_build_utils16.debug)(`Django settings: ${JSON.stringify(settingsResult)}`);
6658
6820
  const { djangoSettings, settingsModule, djangoVersion } = settingsResult;
6659
6821
  if (djangoVersion) {
6660
6822
  console.log(`Django ${djangoVersion.join(".")} detected`);
@@ -6667,7 +6829,7 @@ ${detail}`
6667
6829
  const variableName = parts.at(-1);
6668
6830
  const rel = `${parts.slice(0, -1).join("/")}.py`;
6669
6831
  const ep = baseDir ? `${baseDir}/${rel}` : rel;
6670
- (0, import_build_utils15.debug)(`Django hook: ASGI entrypoint: ${ep} (variable: ${variableName})`);
6832
+ (0, import_build_utils16.debug)(`Django hook: ASGI entrypoint: ${ep} (variable: ${variableName})`);
6671
6833
  resolvedEntrypoint = { entrypoint: ep, variableName };
6672
6834
  } else {
6673
6835
  const wsgiApp = djangoSettings["WSGI_APPLICATION"];
@@ -6676,7 +6838,7 @@ ${detail}`
6676
6838
  const variableName = parts.at(-1);
6677
6839
  const rel = `${parts.slice(0, -1).join("/")}.py`;
6678
6840
  const ep = baseDir ? `${baseDir}/${rel}` : rel;
6679
- (0, import_build_utils15.debug)(
6841
+ (0, import_build_utils16.debug)(
6680
6842
  `Django hook: WSGI entrypoint: ${ep} (variable: ${variableName})`
6681
6843
  );
6682
6844
  resolvedEntrypoint = { entrypoint: ep, variableName };
@@ -6684,7 +6846,7 @@ ${detail}`
6684
6846
  }
6685
6847
  let djangoStatic = null;
6686
6848
  if (workPath && venvPath) {
6687
- const outputStaticDir = (0, import_path13.join)(workPath, ".vercel", "output", "static");
6849
+ const outputStaticDir = (0, import_path14.join)(workPath, ".vercel", "output", "static");
6688
6850
  djangoStatic = await runDjangoCollectStatic(
6689
6851
  venvPath,
6690
6852
  workPath,
@@ -6704,14 +6866,14 @@ async function downloadFilesInWorkPath({
6704
6866
  files,
6705
6867
  meta = {}
6706
6868
  }) {
6707
- (0, import_build_utils15.debug)("Downloading user files...");
6708
- let downloadedFiles = await (0, import_build_utils15.download)(files, workPath, meta);
6869
+ (0, import_build_utils16.debug)("Downloading user files...");
6870
+ let downloadedFiles = await (0, import_build_utils16.download)(files, workPath, meta);
6709
6871
  if (meta.isDev && entrypoint) {
6710
- const { devCacheDir = (0, import_path13.join)(workPath, ".now", "cache") } = meta;
6711
- const cacheKey = (0, import_path13.basename)(entrypoint).replace(/\./g, "_");
6712
- const destCache = (0, import_path13.join)(devCacheDir, cacheKey);
6713
- await (0, import_build_utils15.download)(downloadedFiles, destCache);
6714
- downloadedFiles = await (0, import_build_utils15.glob)("**", destCache);
6872
+ const { devCacheDir = (0, import_path14.join)(workPath, ".now", "cache") } = meta;
6873
+ const cacheKey = (0, import_path14.basename)(entrypoint).replace(/\./g, "_");
6874
+ const destCache = (0, import_path14.join)(devCacheDir, cacheKey);
6875
+ await (0, import_build_utils16.download)(downloadedFiles, destCache);
6876
+ downloadedFiles = await (0, import_build_utils16.glob)("**", destCache);
6715
6877
  workPath = destCache;
6716
6878
  }
6717
6879
  return workPath;
@@ -6727,13 +6889,13 @@ var build = async ({
6727
6889
  service
6728
6890
  }) => {
6729
6891
  let entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
6730
- const builderSpan = parentSpan ?? new import_build_utils15.Span({ name: "vc.builder" });
6892
+ const builderSpan = parentSpan ?? new import_build_utils16.Span({ name: "vc.builder" });
6731
6893
  const framework = config?.framework;
6732
6894
  const shouldInstallVercelWorkers = config?.hasWorkerServices === true;
6733
6895
  let spawnEnv;
6734
6896
  let projectInstallCommand;
6735
6897
  let hasCustomCommand = false;
6736
- (0, import_build_utils15.debug)(`workPath: ${workPath}`);
6898
+ (0, import_build_utils16.debug)(`workPath: ${workPath}`);
6737
6899
  workPath = await downloadFilesInWorkPath({
6738
6900
  workPath,
6739
6901
  files: originalFiles,
@@ -6742,7 +6904,7 @@ var build = async ({
6742
6904
  });
6743
6905
  try {
6744
6906
  if (meta.isDev) {
6745
- const setupCfg = (0, import_path13.join)(workPath, "setup.cfg");
6907
+ const setupCfg = (0, import_path14.join)(workPath, "setup.cfg");
6746
6908
  await writeFile(setupCfg, "[install]\nprefix=\n");
6747
6909
  }
6748
6910
  } catch (err) {
@@ -6765,8 +6927,8 @@ var build = async ({
6765
6927
  if (detected?.error && detected?.baseDir === void 0) {
6766
6928
  throw detected?.error;
6767
6929
  }
6768
- const entryDirectory = detected?.baseDir ?? (entrypoint ? (0, import_path13.dirname)(entrypoint) : ".");
6769
- const entrypointAbsDir = (0, import_path13.join)(workPath, entryDirectory);
6930
+ const entryDirectory = detected?.baseDir ?? (entrypoint ? (0, import_path14.dirname)(entrypoint) : ".");
6931
+ const entrypointAbsDir = (0, import_path14.join)(workPath, entryDirectory);
6770
6932
  const rootDir = repoRootPath ?? workPath;
6771
6933
  const pythonPackage = await builderSpan.child("vc.builder.python.discover").trace(
6772
6934
  () => discoverPackage({
@@ -6796,12 +6958,26 @@ var build = async ({
6796
6958
  `
6797
6959
  );
6798
6960
  }
6799
- const venvPath = service?.name ? (0, import_path13.join)(workPath, ".vercel", "python", "services", service.name, ".venv") : (0, import_path13.join)(workPath, ".vercel", "python", ".venv");
6800
6961
  const uvCacheDir = getUvCacheDir(workPath);
6801
- const hasCachedVenv = import_fs12.default.existsSync((0, import_path13.join)(venvPath, "pyvenv.cfg"));
6802
- const hasCachedUv = import_fs12.default.existsSync(uvCacheDir);
6962
+ let uv;
6963
+ try {
6964
+ const uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
6965
+ uv = new UvRunner(uvPath, uvCacheDir);
6966
+ const uvVersionOutput = (0, import_child_process3.execSync)(`${uvPath} --version`, {
6967
+ encoding: "utf8"
6968
+ }).trim();
6969
+ console.log(`Using ${uvVersionOutput}`);
6970
+ } catch (err) {
6971
+ console.log("Failed to install or locate uv");
6972
+ throw new Error(
6973
+ `uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
6974
+ );
6975
+ }
6976
+ const venvPath = service?.name ? (0, import_path14.join)(workPath, ".vercel", "python", "services", service.name, ".venv") : (0, import_path14.join)(workPath, ".vercel", "python", ".venv");
6977
+ const hasCachedVenv = import_fs13.default.existsSync((0, import_path14.join)(venvPath, "pyvenv.cfg"));
6978
+ const hasCachedUv = import_fs13.default.existsSync(uvCacheDir);
6803
6979
  if (hasCachedVenv || hasCachedUv) {
6804
- (0, import_build_utils15.debug)(
6980
+ (0, import_build_utils16.debug)(
6805
6981
  `Build cache detected: venv=${hasCachedVenv}, uv-cache=${hasCachedUv}`
6806
6982
  );
6807
6983
  }
@@ -6809,17 +6985,18 @@ var build = async ({
6809
6985
  await ensureVenv({
6810
6986
  pythonVersion,
6811
6987
  venvPath,
6988
+ uvPath: uv.getPath(),
6812
6989
  uvCacheDir
6813
6990
  });
6814
6991
  });
6815
- if ((0, import_build_utils15.isPythonFramework)(framework)) {
6992
+ if ((0, import_build_utils16.isPythonFramework)(framework)) {
6816
6993
  const {
6817
6994
  cliType,
6818
6995
  lockfileVersion,
6819
6996
  packageJsonPackageManager,
6820
6997
  turboSupportsCorepackHome
6821
- } = await (0, import_build_utils15.scanParentDirs)(workPath, true);
6822
- spawnEnv = (0, import_build_utils15.getEnvForPackageManager)({
6998
+ } = await (0, import_build_utils16.scanParentDirs)(workPath, true);
6999
+ spawnEnv = (0, import_build_utils16.getEnvForPackageManager)({
6823
7000
  cliType,
6824
7001
  lockfileVersion,
6825
7002
  packageJsonPackageManager,
@@ -6841,38 +7018,25 @@ var build = async ({
6841
7018
  const pythonEnv = createVenvEnv(venvPath, baseEnv, uvCacheDir);
6842
7019
  pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
6843
7020
  let assumeDepsInstalled = false;
6844
- let uv;
6845
- try {
6846
- const uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
6847
- uv = new UvRunner(uvPath, uvCacheDir);
6848
- const uvVersionOutput = (0, import_child_process3.execSync)(`${uvPath} --version`, {
6849
- encoding: "utf8"
6850
- }).trim();
6851
- console.log(`Using ${uvVersionOutput}`);
6852
- } catch (err) {
6853
- console.log("Failed to install or locate uv");
6854
- throw new Error(
6855
- `uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
6856
- );
6857
- }
6858
7021
  let uvLockPath = null;
6859
7022
  let uvProjectDir = null;
6860
7023
  let projectName;
6861
- await builderSpan.child(import_build_utils15.BUILDER_INSTALLER_STEP, {
7024
+ await builderSpan.child(import_build_utils16.BUILDER_INSTALLER_STEP, {
6862
7025
  installCommand: projectInstallCommand || void 0
6863
7026
  }).trace(async () => {
6864
7027
  if (projectInstallCommand) {
6865
- await import_fs12.default.promises.rm(venvPath, { recursive: true, force: true });
7028
+ await import_fs13.default.promises.rm(venvPath, { recursive: true, force: true });
6866
7029
  await ensureVenv({
6867
7030
  pythonVersion,
6868
7031
  venvPath,
7032
+ uvPath: uv.getPath(),
6869
7033
  uvCacheDir,
6870
7034
  quiet: true
6871
7035
  });
6872
7036
  console.log(
6873
7037
  `Running "install" command: \`${projectInstallCommand}\`...`
6874
7038
  );
6875
- await (0, import_build_utils15.execCommand)(projectInstallCommand, {
7039
+ await (0, import_build_utils16.execCommand)(projectInstallCommand, {
6876
7040
  env: pythonEnv,
6877
7041
  cwd: workPath
6878
7042
  });
@@ -6893,7 +7057,7 @@ var build = async ({
6893
7057
  }
6894
7058
  if (!assumeDepsInstalled) {
6895
7059
  const lockCacheKey = service?.name ? `uv.lock.${service.name}` : "uv.lock";
6896
- const cachedLockPath = (0, import_path13.join)(uvCacheDir, lockCacheKey);
7060
+ const cachedLockPath = (0, import_path14.join)(uvCacheDir, lockCacheKey);
6897
7061
  const { projectDir, lockPath, lockFileProvidedByUser } = await ensureUvProject({
6898
7062
  workPath,
6899
7063
  rootDir,
@@ -6913,21 +7077,21 @@ var build = async ({
6913
7077
  frozen: lockFileProvidedByUser,
6914
7078
  locked: !lockFileProvidedByUser
6915
7079
  });
6916
- if (lockPath && import_fs12.default.existsSync(lockPath)) {
6917
- await import_fs12.default.promises.mkdir(uvCacheDir, { recursive: true });
6918
- await import_fs12.default.promises.copyFile(lockPath, cachedLockPath);
7080
+ if (lockPath && import_fs13.default.existsSync(lockPath)) {
7081
+ await import_fs13.default.promises.mkdir(uvCacheDir, { recursive: true });
7082
+ await import_fs13.default.promises.copyFile(lockPath, cachedLockPath);
6919
7083
  }
6920
7084
  }
6921
7085
  });
6922
- if ((0, import_build_utils15.isPythonFramework)(framework)) {
7086
+ if ((0, import_build_utils16.isPythonFramework)(framework)) {
6923
7087
  const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
6924
7088
  config?.buildCommand;
6925
- await builderSpan.child(import_build_utils15.BUILDER_COMPILE_STEP, {
7089
+ await builderSpan.child(import_build_utils16.BUILDER_COMPILE_STEP, {
6926
7090
  buildCommand: projectBuildCommand || void 0
6927
7091
  }).trace(async () => {
6928
7092
  if (projectBuildCommand) {
6929
7093
  console.log(`Running "${projectBuildCommand}"`);
6930
- await (0, import_build_utils15.execCommand)(projectBuildCommand, {
7094
+ await (0, import_build_utils16.execCommand)(projectBuildCommand, {
6931
7095
  env: pythonEnv,
6932
7096
  cwd: workPath
6933
7097
  });
@@ -6942,7 +7106,7 @@ var build = async ({
6942
7106
  }
6943
7107
  const hookResult = await runFrameworkHook(framework, {
6944
7108
  pythonEnv,
6945
- projectDir: (0, import_path13.join)(workPath, entryDirectory),
7109
+ projectDir: (0, import_path14.join)(workPath, entryDirectory),
6946
7110
  workPath,
6947
7111
  venvPath,
6948
7112
  entrypoint,
@@ -6954,25 +7118,25 @@ var build = async ({
6954
7118
  }
6955
7119
  entrypoint = resolved?.entrypoint;
6956
7120
  if (!entrypoint) {
6957
- throw new import_build_utils15.NowBuildError({
7121
+ throw new import_build_utils16.NowBuildError({
6958
7122
  code: "PYTHON_ENTRYPOINT_NOT_FOUND",
6959
7123
  message: "No Python entrypoint could be detected. Please specify an entrypoint file."
6960
7124
  });
6961
7125
  }
6962
7126
  const djangoStatic = hookResult?.djangoStatic ?? null;
6963
7127
  const runtimeDep = baseEnv.VERCEL_RUNTIME_PYTHON || `vercel-runtime==${VERCEL_RUNTIME_VERSION}`;
6964
- (0, import_build_utils15.debug)(`Installing ${runtimeDep}`);
7128
+ (0, import_build_utils16.debug)(`Installing ${runtimeDep}`);
6965
7129
  await uv.pip({
6966
7130
  venvPath,
6967
- projectDir: (0, import_path13.join)(workPath, entryDirectory),
7131
+ projectDir: (0, import_path14.join)(workPath, entryDirectory),
6968
7132
  args: ["install", runtimeDep]
6969
7133
  });
6970
7134
  if (shouldInstallVercelWorkers) {
6971
7135
  const workersDep = baseEnv.VERCEL_WORKERS_PYTHON || `vercel-workers==${VERCEL_WORKERS_VERSION}`;
6972
- (0, import_build_utils15.debug)(`Installing ${workersDep}`);
7136
+ (0, import_build_utils16.debug)(`Installing ${workersDep}`);
6973
7137
  await uv.pip({
6974
7138
  venvPath,
6975
- projectDir: (0, import_path13.join)(workPath, entryDirectory),
7139
+ projectDir: (0, import_path14.join)(workPath, entryDirectory),
6976
7140
  args: ["install", workersDep]
6977
7141
  });
6978
7142
  }
@@ -6980,14 +7144,14 @@ var build = async ({
6980
7144
  if (quirksResult.buildEnv) {
6981
7145
  Object.assign(pythonEnv, quirksResult.buildEnv);
6982
7146
  }
6983
- (0, import_build_utils15.debug)("Entrypoint is", entrypoint);
7147
+ (0, import_build_utils16.debug)("Entrypoint is", entrypoint);
6984
7148
  const moduleName = entrypoint.replace(/\//g, ".").replace(/\.py$/i, "");
6985
7149
  if (handlerFunction) {
6986
- const entrypointPath = (0, import_path13.join)(workPath, entrypoint);
6987
- const source = await import_fs12.default.promises.readFile(entrypointPath, "utf-8");
7150
+ const entrypointPath = (0, import_path14.join)(workPath, entrypoint);
7151
+ const source = await import_fs13.default.promises.readFile(entrypointPath, "utf-8");
6988
7152
  const found = await (0, import_python_analysis9.containsTopLevelCallable)(source, handlerFunction);
6989
7153
  if (!found) {
6990
- throw new import_build_utils15.NowBuildError({
7154
+ throw new import_build_utils16.NowBuildError({
6991
7155
  code: "PYTHON_HANDLER_NOT_FOUND",
6992
7156
  message: `Handler function "${handlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
6993
7157
  });
@@ -6996,9 +7160,23 @@ var build = async ({
6996
7160
  const vendorDir = resolveVendorDir();
6997
7161
  const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
6998
7162
  const entrypointWithSuffix = `${entrypoint}${suffix}`;
6999
- (0, import_build_utils15.debug)("Entrypoint with suffix is", entrypointWithSuffix);
7000
- const handlerFuncEnvLine = handlerFunction ? `
7001
- "__VC_HANDLER_FUNC_NAME": "${handlerFunction}",` : "";
7163
+ (0, import_build_utils16.debug)("Entrypoint with suffix is", entrypointWithSuffix);
7164
+ const crons = await getServiceCrons({
7165
+ service,
7166
+ entrypoint,
7167
+ rawEntrypoint,
7168
+ handlerFunction,
7169
+ pythonBin: getVenvPythonBin(venvPath),
7170
+ env: pythonEnv,
7171
+ workPath
7172
+ });
7173
+ let cronEnvLine = "";
7174
+ if (crons?.length) {
7175
+ const json = JSON.stringify(buildCronRouteTable(crons));
7176
+ (0, import_assert.default)(!json.includes("\\"), `backslash in cron route table: ${json}`);
7177
+ cronEnvLine = `
7178
+ "__VC_CRON_ROUTES": '${json}',`;
7179
+ }
7002
7180
  const variableName = resolved?.variableName ?? "";
7003
7181
  const runtimeTrampoline = `
7004
7182
  import importlib
@@ -7014,7 +7192,7 @@ os.environ.update({
7014
7192
  "__VC_HANDLER_ENTRYPOINT": "${entrypointWithSuffix}",
7015
7193
  "__VC_HANDLER_ENTRYPOINT_ABS": os.path.join(_here, "${entrypointWithSuffix}"),
7016
7194
  "__VC_HANDLER_VENDOR_DIR": "${vendorDir}",
7017
- "__VC_HANDLER_VARIABLE_NAME": "${variableName}",${handlerFuncEnvLine}
7195
+ "__VC_HANDLER_VARIABLE_NAME": "${variableName}",${cronEnvLine}
7018
7196
  })
7019
7197
 
7020
7198
  _vendor_rel = '${vendorDir}'
@@ -7067,10 +7245,10 @@ from vercel_runtime.vc_init import vc_handler
7067
7245
  cwd: workPath,
7068
7246
  ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
7069
7247
  };
7070
- const files = await (0, import_build_utils15.glob)("**", globOptions);
7248
+ const files = await (0, import_build_utils16.glob)("**", globOptions);
7071
7249
  if (djangoStatic?.manifestRelPath) {
7072
- files[djangoStatic.manifestRelPath] = new import_build_utils15.FileFsRef({
7073
- fsPath: (0, import_path13.join)(workPath, djangoStatic.manifestRelPath)
7250
+ files[djangoStatic.manifestRelPath] = new import_build_utils16.FileFsRef({
7251
+ fsPath: (0, import_path14.join)(workPath, djangoStatic.manifestRelPath)
7074
7252
  });
7075
7253
  }
7076
7254
  const depExternalizer = new PythonDependencyExternalizer({
@@ -7106,12 +7284,12 @@ from vercel_runtime.vc_init import vc_handler
7106
7284
  }
7107
7285
  });
7108
7286
  const handlerPyFilename = "vc__handler__python";
7109
- files[`${handlerPyFilename}.py`] = new import_build_utils15.FileBlob({ data: runtimeTrampoline });
7287
+ files[`${handlerPyFilename}.py`] = new import_build_utils16.FileBlob({ data: runtimeTrampoline });
7110
7288
  if (config.framework === "fasthtml") {
7111
7289
  const { SESSKEY = "" } = process.env;
7112
- files[".sesskey"] = new import_build_utils15.FileBlob({ data: `"${SESSKEY}"` });
7290
+ files[".sesskey"] = new import_build_utils16.FileBlob({ data: `"${SESSKEY}"` });
7113
7291
  }
7114
- const output = new import_build_utils15.Lambda({
7292
+ const output = new import_build_utils16.Lambda({
7115
7293
  files,
7116
7294
  handler: `${handlerPyFilename}.vc_handler`,
7117
7295
  runtime: pythonVersion.runtime,
@@ -7127,16 +7305,17 @@ from vercel_runtime.vc_init import vc_handler
7127
7305
  uvLockPath
7128
7306
  });
7129
7307
  } catch (err) {
7130
- (0, import_build_utils15.debug)(
7308
+ (0, import_build_utils16.debug)(
7131
7309
  `Failed to write project manifest: ${err instanceof Error ? err.message : String(err)}`
7132
7310
  );
7133
7311
  }
7134
7312
  }
7135
- if (!(0, import_build_utils15.isPythonFramework)(framework)) {
7313
+ if (!(0, import_build_utils16.isPythonFramework)(framework) && !service?.name) {
7136
7314
  return { resultVersion: 3, result: { output } };
7137
7315
  }
7138
7316
  const lambdaPath = service?.name ? `_svc/${service.name}/index` : "index";
7139
- const staticFiles = djangoStatic?.cdnOutputDir ? await (0, import_build_utils15.glob)("**", { cwd: djangoStatic.cdnOutputDir }) : {};
7317
+ const staticFiles = djangoStatic?.cdnOutputDir ? await (0, import_build_utils16.glob)("**", { cwd: djangoStatic.cdnOutputDir }) : {};
7318
+ const routes = service?.name ? void 0 : [{ handle: "filesystem" }, { src: "/(.*)", dest: `/${lambdaPath}` }];
7140
7319
  return {
7141
7320
  resultVersion: 2,
7142
7321
  result: {
@@ -7144,10 +7323,8 @@ from vercel_runtime.vc_init import vc_handler
7144
7323
  [lambdaPath]: output,
7145
7324
  ...staticFiles
7146
7325
  },
7147
- routes: [
7148
- { handle: "filesystem" },
7149
- { src: "/(.*)", dest: `/${lambdaPath}` }
7150
- ]
7326
+ ...routes ? { routes } : {},
7327
+ crons
7151
7328
  }
7152
7329
  };
7153
7330
  };
@@ -7169,14 +7346,14 @@ var prepareCache = async ({
7169
7346
  }
7170
7347
  } catch {
7171
7348
  }
7172
- return (0, import_build_utils15.glob)("**/.vercel/python/{.venv,services/*/.venv,cache/uv}/**", {
7349
+ return (0, import_build_utils16.glob)("**/.vercel/python/{.venv,services/*/.venv,cache/uv}/**", {
7173
7350
  cwd: root,
7174
7351
  ignore
7175
7352
  });
7176
7353
  };
7177
7354
  var shouldServe = (opts) => {
7178
7355
  const framework = opts.config.framework;
7179
- if ((0, import_build_utils15.isPythonFramework)(framework)) {
7356
+ if ((0, import_build_utils16.isPythonFramework)(framework)) {
7180
7357
  const requestPath = opts.requestPath.replace(/\/$/, "");
7181
7358
  if (requestPath.startsWith("api") && opts.hasMatched) {
7182
7359
  return false;
@@ -7195,7 +7372,7 @@ var defaultShouldServe = ({
7195
7372
  if (entrypoint === requestPath && hasProp(files, entrypoint)) {
7196
7373
  return true;
7197
7374
  }
7198
- const { dir, name } = (0, import_path13.parse)(entrypoint);
7375
+ const { dir, name } = (0, import_path14.parse)(entrypoint);
7199
7376
  if (name === "index" && dir === requestPath && hasProp(files, entrypoint)) {
7200
7377
  return true;
7201
7378
  }