@vercel/python 6.31.0 → 6.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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
  }
@@ -4312,6 +4313,7 @@ var import_python_analysis3 = require("@vercel/python-analysis");
4312
4313
  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;
4316
+ var HIVE_LAMBDA_SIZE_BYTES = 1 * 1024 * 1024 * 1024;
4315
4317
  var PythonDependencyExternalizer = class {
4316
4318
  constructor(options) {
4317
4319
  // Populated by analyze()
@@ -4377,6 +4379,15 @@ To resolve this, either:
4377
4379
  action: "Learn More"
4378
4380
  });
4379
4381
  }
4382
+ if (pythonOnHiveEnabled && this.totalBundleSize > HIVE_LAMBDA_SIZE_BYTES) {
4383
+ const limitMB = (HIVE_LAMBDA_SIZE_BYTES / (1024 * 1024)).toFixed(0);
4384
+ throw new import_build_utils5.NowBuildError({
4385
+ code: "LAMBDA_SIZE_EXCEEDED",
4386
+ message: `Total bundle size (${totalBundleSizeMB} MB) exceeds the extended function size limit (${limitMB} MB). Consider removing unused dependencies or splitting your application into smaller functions.`,
4387
+ link: "https://vercel.com/docs/functions/runtimes/python#controlling-what-gets-bundled",
4388
+ action: "Learn More"
4389
+ });
4390
+ }
4380
4391
  return {
4381
4392
  runtimeInstallEnabled,
4382
4393
  allVendorFiles: this.allVendorFiles,
@@ -5093,20 +5104,161 @@ var diagnostics = async ({
5093
5104
  }
5094
5105
  };
5095
5106
 
5107
+ // src/crons.ts
5108
+ var import_fs7 = __toESM(require("fs"));
5109
+ var import_path8 = require("path");
5110
+ var import_execa4 = __toESM(require_execa());
5111
+ var import_build_utils7 = require("@vercel/build-utils");
5112
+ var DYNAMIC_SCHEDULE = "<dynamic>";
5113
+ function entrypointToModule(entrypoint) {
5114
+ return entrypoint.replace(/\\/g, "/").replace(/\.py$/i, "").replace(/\//g, ".");
5115
+ }
5116
+ var scriptPath = (0, import_path8.join)(__dirname, "..", "templates", "vc_cron_detect.py");
5117
+ var script = import_fs7.default.readFileSync(scriptPath, "utf-8");
5118
+ function buildCronRouteTable(crons) {
5119
+ const table = {};
5120
+ for (const cron of crons) {
5121
+ table[cron.path] = cron.resolvedHandler;
5122
+ }
5123
+ return table;
5124
+ }
5125
+ async function getServiceCrons(opts) {
5126
+ const { service, entrypoint, rawEntrypoint, handlerFunction } = opts;
5127
+ if (service?.type !== "cron" || !service.name || typeof service.schedule !== "string") {
5128
+ return void 0;
5129
+ }
5130
+ const cronEntrypoint = entrypoint || rawEntrypoint;
5131
+ if (!cronEntrypoint) {
5132
+ throw new import_build_utils7.NowBuildError({
5133
+ code: "PYTHON_CRON_NO_ENTRYPOINT",
5134
+ message: "Cron service is missing an entrypoint."
5135
+ });
5136
+ }
5137
+ if (service.schedule === DYNAMIC_SCHEDULE) {
5138
+ return getServiceCronsDynamic({
5139
+ serviceName: service.name,
5140
+ cronEntrypoint,
5141
+ handlerFunction,
5142
+ pythonBin: opts.pythonBin,
5143
+ env: opts.env,
5144
+ workPath: opts.workPath
5145
+ });
5146
+ }
5147
+ const cronPath = (0, import_build_utils7.getInternalServiceCronPath)(
5148
+ service.name,
5149
+ cronEntrypoint,
5150
+ handlerFunction || "cron"
5151
+ );
5152
+ const moduleName = entrypointToModule(cronEntrypoint);
5153
+ const resolvedHandler = handlerFunction ? `${moduleName}:${handlerFunction}` : moduleName;
5154
+ return [{ path: cronPath, schedule: service.schedule, resolvedHandler }];
5155
+ }
5156
+ async function getServiceCronsDynamic(opts) {
5157
+ const {
5158
+ serviceName,
5159
+ cronEntrypoint,
5160
+ handlerFunction,
5161
+ pythonBin,
5162
+ env,
5163
+ workPath
5164
+ } = opts;
5165
+ if (!handlerFunction) {
5166
+ throw new import_build_utils7.NowBuildError({
5167
+ code: "PYTHON_DYNAMIC_CRON_NO_HANDLER",
5168
+ message: 'Dynamic cron detection requires a "module:object" entrypoint where the object has a get_crons() method.'
5169
+ });
5170
+ }
5171
+ const moduleName = entrypointToModule(cronEntrypoint);
5172
+ const entries = await detectDynamicCrons({
5173
+ pythonBin,
5174
+ env,
5175
+ workPath,
5176
+ moduleName,
5177
+ attrName: handlerFunction
5178
+ });
5179
+ console.log(
5180
+ `Detected ${entries.length} cron entry(s): ${entries.map((e) => `${e.module_function} (${e.schedule})`).join(", ")}`
5181
+ );
5182
+ if (entries.length === 0) {
5183
+ throw new import_build_utils7.NowBuildError({
5184
+ code: "PYTHON_DYNAMIC_CRON_EMPTY",
5185
+ message: `Dynamic cron detection returned no entries. "${moduleName}.${handlerFunction}.get_crons()" returned an empty iterable.`
5186
+ });
5187
+ }
5188
+ return entries.map((entry) => {
5189
+ const cronPath = moduleColonFuncToCronPath(
5190
+ serviceName,
5191
+ entry.module_function
5192
+ );
5193
+ return {
5194
+ path: cronPath,
5195
+ schedule: entry.schedule,
5196
+ resolvedHandler: entry.module_function
5197
+ };
5198
+ });
5199
+ }
5200
+ async function detectDynamicCrons(opts) {
5201
+ const { pythonBin, env, workPath, moduleName, attrName } = opts;
5202
+ let stdout;
5203
+ try {
5204
+ const result = await (0, import_execa4.default)(
5205
+ pythonBin,
5206
+ ["-c", script, moduleName, attrName],
5207
+ { env, cwd: workPath }
5208
+ );
5209
+ stdout = result.stdout;
5210
+ } catch (err) {
5211
+ let detail = err?.stderr || err?.message || String(err);
5212
+ try {
5213
+ const parsed2 = JSON.parse(err?.stdout);
5214
+ if (parsed2.error)
5215
+ detail = parsed2.error;
5216
+ } catch {
5217
+ }
5218
+ throw new import_build_utils7.NowBuildError({
5219
+ code: "PYTHON_DYNAMIC_CRON_DETECTION_FAILED",
5220
+ message: `Failed to detect dynamic cron entries: ${detail}`
5221
+ });
5222
+ }
5223
+ let parsed;
5224
+ try {
5225
+ parsed = JSON.parse(stdout);
5226
+ } catch {
5227
+ throw new import_build_utils7.NowBuildError({
5228
+ code: "PYTHON_DYNAMIC_CRON_DETECTION_FAILED",
5229
+ message: `Dynamic cron detection returned invalid JSON: ${stdout}`
5230
+ });
5231
+ }
5232
+ return parsed.entries || [];
5233
+ }
5234
+ function moduleColonFuncToCronPath(serviceName, moduleFunction) {
5235
+ const colonIdx = moduleFunction.indexOf(":");
5236
+ if (colonIdx === -1) {
5237
+ throw new import_build_utils7.NowBuildError({
5238
+ code: "PYTHON_DYNAMIC_CRON_INVALID_FORMAT",
5239
+ message: `Dynamic cron entry must use "module:function" format, got: "${moduleFunction}"`
5240
+ });
5241
+ }
5242
+ const modulePart = moduleFunction.slice(0, colonIdx);
5243
+ const funcPart = moduleFunction.slice(colonIdx + 1);
5244
+ const entrypointPath = modulePart.replace(/\./g, "/");
5245
+ return (0, import_build_utils7.getInternalServiceCronPath)(serviceName, entrypointPath, funcPart);
5246
+ }
5247
+
5096
5248
  // src/start-dev-server.ts
5097
5249
  var import_child_process2 = require("child_process");
5098
- var import_fs8 = require("fs");
5099
- var import_path9 = require("path");
5100
- var import_build_utils10 = require("@vercel/build-utils");
5250
+ var import_fs9 = require("fs");
5251
+ var import_path10 = require("path");
5252
+ var import_build_utils11 = require("@vercel/build-utils");
5101
5253
  var import_get_port = __toESM(require_get_port());
5102
5254
  var import_is_port_reachable = __toESM(require_is_port_reachable());
5103
5255
 
5104
5256
  // src/entrypoint.ts
5105
- var import_fs7 = __toESM(require("fs"));
5106
- var import_path8 = require("path");
5107
- var import_build_utils7 = require("@vercel/build-utils");
5257
+ var import_fs8 = __toESM(require("fs"));
5258
+ var import_path9 = require("path");
5108
5259
  var import_build_utils8 = require("@vercel/build-utils");
5109
5260
  var import_build_utils9 = require("@vercel/build-utils");
5261
+ var import_build_utils10 = require("@vercel/build-utils");
5110
5262
  var import_python_analysis5 = require("@vercel/python-analysis");
5111
5263
  var PYTHON_ENTRYPOINT_FILENAMES = [
5112
5264
  "app",
@@ -5123,27 +5275,27 @@ var PYTHON_CANDIDATE_ENTRYPOINTS = getCandidateEntrypointsInDirs(
5123
5275
  function getCandidateEntrypointsInDirs(dirs) {
5124
5276
  return dirs.flatMap(
5125
5277
  (dir) => PYTHON_ENTRYPOINT_FILENAMES.map(
5126
- (filename) => import_path8.posix.join(dir, `${filename}.py`)
5278
+ (filename) => import_path9.posix.join(dir, `${filename}.py`)
5127
5279
  )
5128
5280
  );
5129
5281
  }
5130
5282
  async function fileExists(filePath) {
5131
5283
  try {
5132
- const stat = await import_fs7.default.promises.stat(filePath);
5284
+ const stat = await import_fs8.default.promises.stat(filePath);
5133
5285
  return stat.isFile();
5134
5286
  } catch {
5135
5287
  return false;
5136
5288
  }
5137
5289
  }
5138
5290
  async function checkEntrypoint(workPath, relPath) {
5139
- const absPath = (0, import_path8.join)(workPath, relPath);
5291
+ const absPath = (0, import_path9.join)(workPath, relPath);
5140
5292
  if (!await fileExists(absPath))
5141
5293
  return null;
5142
- const content = await import_fs7.default.promises.readFile(absPath, "utf-8");
5294
+ const content = await import_fs8.default.promises.readFile(absPath, "utf-8");
5143
5295
  return (0, import_python_analysis5.findAppOrHandler)(content);
5144
5296
  }
5145
5297
  async function getPyprojectEntrypoint(workPath) {
5146
- const pyprojectData = await (0, import_build_utils9.readConfigFile)((0, import_path8.join)(workPath, "pyproject.toml"));
5298
+ const pyprojectData = await (0, import_build_utils10.readConfigFile)((0, import_path9.join)(workPath, "pyproject.toml"));
5147
5299
  if (!pyprojectData)
5148
5300
  return null;
5149
5301
  const scripts = pyprojectData.project?.scripts;
@@ -5158,7 +5310,7 @@ async function getPyprojectEntrypoint(workPath) {
5158
5310
  const relPath = modulePath.replace(/\./g, "/");
5159
5311
  const candidates = [`${relPath}.py`, `${relPath}/__init__.py`];
5160
5312
  for (const candidate of candidates) {
5161
- if (await fileExists((0, import_path8.join)(workPath, candidate))) {
5313
+ if (await fileExists((0, import_path9.join)(workPath, candidate))) {
5162
5314
  return { entrypoint: candidate, variableName };
5163
5315
  }
5164
5316
  }
@@ -5168,19 +5320,19 @@ async function findValidEntrypoint(workPath, candidates) {
5168
5320
  for (const candidate of candidates) {
5169
5321
  const varName = await checkEntrypoint(workPath, candidate);
5170
5322
  if (varName) {
5171
- (0, import_build_utils8.debug)(`Detected Python entrypoint: ${candidate} (variable: ${varName})`);
5323
+ (0, import_build_utils9.debug)(`Detected Python entrypoint: ${candidate} (variable: ${varName})`);
5172
5324
  return { entrypoint: candidate, variableName: varName };
5173
5325
  }
5174
5326
  }
5175
5327
  return null;
5176
5328
  }
5177
5329
  async function checkDjangoManage(workPath) {
5178
- const managePath = (0, import_path8.join)(workPath, "manage.py");
5330
+ const managePath = (0, import_path9.join)(workPath, "manage.py");
5179
5331
  try {
5180
- const content = await import_fs7.default.promises.readFile(managePath, "utf-8");
5332
+ const content = await import_fs8.default.promises.readFile(managePath, "utf-8");
5181
5333
  if (!content.includes("DJANGO_SETTINGS_MODULE"))
5182
5334
  return false;
5183
- (0, import_build_utils8.debug)(`Found Django manage.py with DJANGO_SETTINGS_MODULE at ${workPath}`);
5335
+ (0, import_build_utils9.debug)(`Found Django manage.py with DJANGO_SETTINGS_MODULE at ${workPath}`);
5184
5336
  return true;
5185
5337
  } catch {
5186
5338
  return false;
@@ -5188,7 +5340,7 @@ async function checkDjangoManage(workPath) {
5188
5340
  }
5189
5341
  async function getSubdirectories(workPath) {
5190
5342
  try {
5191
- const entries = await import_fs7.default.promises.readdir(workPath, {
5343
+ const entries = await import_fs8.default.promises.readdir(workPath, {
5192
5344
  withFileTypes: true
5193
5345
  });
5194
5346
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).sort();
@@ -5198,7 +5350,7 @@ async function getSubdirectories(workPath) {
5198
5350
  }
5199
5351
  function makeDetectError(framework) {
5200
5352
  const searchedList = PYTHON_CANDIDATE_ENTRYPOINTS.join(", ");
5201
- return new import_build_utils7.NowBuildError({
5353
+ return new import_build_utils8.NowBuildError({
5202
5354
  code: `${framework.toUpperCase()}_ENTRYPOINT_NOT_FOUND`,
5203
5355
  message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searchedList}.`,
5204
5356
  link: `https://vercel.com/docs/frameworks/backend/${framework}#exporting-the-${framework}-application`,
@@ -5213,7 +5365,7 @@ async function detectGenericPythonEntrypoint(workPath) {
5213
5365
  );
5214
5366
  return found ? { entrypoint: found } : null;
5215
5367
  } catch {
5216
- (0, import_build_utils8.debug)("Failed to discover Python entrypoint");
5368
+ (0, import_build_utils9.debug)("Failed to discover Python entrypoint");
5217
5369
  return null;
5218
5370
  }
5219
5371
  }
@@ -5222,7 +5374,7 @@ async function detectDjangoPythonEntrypoint(workPath) {
5222
5374
  const subdirs = await getSubdirectories(workPath);
5223
5375
  const rootDirs = ["", ...subdirs];
5224
5376
  for (const rootDir of rootDirs) {
5225
- const currPath = (0, import_path8.join)(workPath, rootDir);
5377
+ const currPath = (0, import_path9.join)(workPath, rootDir);
5226
5378
  const isDjango = await checkDjangoManage(currPath);
5227
5379
  if (isDjango) {
5228
5380
  return { baseDir: rootDir, error: makeDetectError("django") };
@@ -5232,7 +5384,7 @@ async function detectDjangoPythonEntrypoint(workPath) {
5232
5384
  const found = await findValidEntrypoint(workPath, candidates);
5233
5385
  return found ? { entrypoint: found } : null;
5234
5386
  } catch {
5235
- (0, import_build_utils8.debug)("Failed to discover Django Python entrypoint");
5387
+ (0, import_build_utils9.debug)("Failed to discover Django Python entrypoint");
5236
5388
  return null;
5237
5389
  }
5238
5390
  }
@@ -5248,11 +5400,11 @@ async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint,
5248
5400
  }
5249
5401
  }
5250
5402
  if (varName) {
5251
- (0, import_build_utils8.debug)(`Using configured Python entrypoint: ${entrypoint}`);
5403
+ (0, import_build_utils9.debug)(`Using configured Python entrypoint: ${entrypoint}`);
5252
5404
  return { entrypoint: { entrypoint, variableName: varName } };
5253
5405
  } else {
5254
5406
  return {
5255
- error: new import_build_utils7.NowBuildError({
5407
+ error: new import_build_utils8.NowBuildError({
5256
5408
  code: "PYTHON_ENTRYPOINT_NOT_FOUND",
5257
5409
  message: `Could not find a top-level "app", "application", or "handler" in "${entrypoint}".`,
5258
5410
  link: "https://vercel.com/docs/functions/serverless-functions/runtimes/python",
@@ -5358,17 +5510,17 @@ async function syncDependencies({
5358
5510
  let { manifestPath } = installInfo;
5359
5511
  const manifest = pythonPackage.manifest;
5360
5512
  if (!manifestType || !manifestPath) {
5361
- (0, import_build_utils10.debug)("No Python project manifest found, skipping dependency sync");
5513
+ (0, import_build_utils11.debug)("No Python project manifest found, skipping dependency sync");
5362
5514
  return;
5363
5515
  }
5364
5516
  if (manifest?.origin && manifestType === "pyproject.toml") {
5365
- const syncDir = (0, import_path9.join)(workPath, ".vercel", "python", "sync");
5366
- (0, import_fs8.mkdirSync)(syncDir, { recursive: true });
5367
- const tempPyproject = (0, import_path9.join)(syncDir, "pyproject.toml");
5517
+ const syncDir = (0, import_path10.join)(workPath, ".vercel", "python", "sync");
5518
+ (0, import_fs9.mkdirSync)(syncDir, { recursive: true });
5519
+ const tempPyproject = (0, import_path10.join)(syncDir, "pyproject.toml");
5368
5520
  const content = (0, import_python_analysis6.stringifyManifest)(manifest.data);
5369
- (0, import_fs8.writeFileSync)(tempPyproject, content, "utf8");
5521
+ (0, import_fs9.writeFileSync)(tempPyproject, content, "utf8");
5370
5522
  manifestPath = tempPyproject;
5371
- (0, import_build_utils10.debug)(
5523
+ (0, import_build_utils11.debug)(
5372
5524
  `Wrote converted ${manifest.origin.kind} manifest to ${tempPyproject}`
5373
5525
  );
5374
5526
  }
@@ -5401,7 +5553,7 @@ async function syncDependencies({
5401
5553
  for (const [channel, chunk] of captured) {
5402
5554
  (channel === "stdout" ? writeOut : writeErr)(chunk.toString());
5403
5555
  }
5404
- throw new import_build_utils10.NowBuildError({
5556
+ throw new import_build_utils11.NowBuildError({
5405
5557
  code: "PYTHON_DEPENDENCY_SYNC_FAILED",
5406
5558
  message: `Failed to install Python dependencies from ${manifestType}: ${err instanceof Error ? err.message : String(err)}`
5407
5559
  });
@@ -5416,14 +5568,14 @@ async function runSync({
5416
5568
  onStdout,
5417
5569
  onStderr
5418
5570
  }) {
5419
- const projectDir = (0, import_path9.dirname)(manifestPath);
5571
+ const projectDir = (0, import_path10.dirname)(manifestPath);
5420
5572
  const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
5421
5573
  let spawnCmd;
5422
5574
  let spawnArgs;
5423
5575
  switch (manifestType) {
5424
5576
  case "uv.lock": {
5425
5577
  if (!uvPath) {
5426
- throw new import_build_utils10.NowBuildError({
5578
+ throw new import_build_utils11.NowBuildError({
5427
5579
  code: "PYTHON_DEPENDENCY_SYNC_FAILED",
5428
5580
  message: "uv is required to install dependencies from uv.lock.",
5429
5581
  link: "https://docs.astral.sh/uv/getting-started/installation/",
@@ -5445,11 +5597,11 @@ async function runSync({
5445
5597
  break;
5446
5598
  }
5447
5599
  default:
5448
- (0, import_build_utils10.debug)(`Unknown manifest type: ${manifestType}`);
5600
+ (0, import_build_utils11.debug)(`Unknown manifest type: ${manifestType}`);
5449
5601
  return;
5450
5602
  }
5451
5603
  await new Promise((resolve3, reject) => {
5452
- (0, import_build_utils10.debug)(`Running "${spawnCmd} ${spawnArgs.join(" ")}" in ${projectDir}...`);
5604
+ (0, import_build_utils11.debug)(`Running "${spawnCmd} ${spawnArgs.join(" ")}" in ${projectDir}...`);
5453
5605
  const child = (0, import_child_process2.spawn)(spawnCmd, spawnArgs, {
5454
5606
  cwd: projectDir,
5455
5607
  env: getProtectedUvEnv(env),
@@ -5493,7 +5645,7 @@ async function installVercelRuntime({
5493
5645
  onStdout,
5494
5646
  onStderr
5495
5647
  }) {
5496
- const targetDir = (0, import_path9.join)(workPath, ".vercel", "python");
5648
+ const targetDir = (0, import_path10.join)(workPath, ".vercel", "python");
5497
5649
  let pending = PENDING_RUNTIME_INSTALLS.get(targetDir);
5498
5650
  if (!pending) {
5499
5651
  pending = doInstallVercelRuntime({
@@ -5519,8 +5671,8 @@ async function doInstallVercelRuntime({
5519
5671
  onStdout,
5520
5672
  onStderr
5521
5673
  }) {
5522
- (0, import_fs8.mkdirSync)(targetDir, { recursive: true });
5523
- const localRuntimeDir = (0, import_path9.join)(
5674
+ (0, import_fs9.mkdirSync)(targetDir, { recursive: true });
5675
+ const localRuntimeDir = (0, import_path10.join)(
5524
5676
  __dirname,
5525
5677
  "..",
5526
5678
  "..",
@@ -5528,21 +5680,21 @@ async function doInstallVercelRuntime({
5528
5680
  "python",
5529
5681
  "vercel-runtime"
5530
5682
  );
5531
- const isLocalDev = (0, import_fs8.existsSync)((0, import_path9.join)(localRuntimeDir, "pyproject.toml"));
5683
+ const isLocalDev = (0, import_fs9.existsSync)((0, import_path10.join)(localRuntimeDir, "pyproject.toml"));
5532
5684
  const runtimeDep = env.VERCEL_RUNTIME_PYTHON || (isLocalDev ? localRuntimeDir : `vercel-runtime==${VERCEL_RUNTIME_VERSION}`);
5533
5685
  if (!isLocalDev && !env.VERCEL_RUNTIME_PYTHON) {
5534
- const distInfo = (0, import_path9.join)(
5686
+ const distInfo = (0, import_path10.join)(
5535
5687
  targetDir,
5536
5688
  `vercel_runtime-${VERCEL_RUNTIME_VERSION}.dist-info`
5537
5689
  );
5538
- if ((0, import_fs8.existsSync)(distInfo)) {
5539
- (0, import_build_utils10.debug)(
5690
+ if ((0, import_fs9.existsSync)(distInfo)) {
5691
+ (0, import_build_utils11.debug)(
5540
5692
  `vercel-runtime ${VERCEL_RUNTIME_VERSION} already installed, skipping`
5541
5693
  );
5542
5694
  return;
5543
5695
  }
5544
5696
  }
5545
- (0, import_build_utils10.debug)(
5697
+ (0, import_build_utils11.debug)(
5546
5698
  `Installing vercel-runtime into ${targetDir} (type: ${isLocalDev ? "local" : "pypi"}, source: ${runtimeDep})`
5547
5699
  );
5548
5700
  const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
@@ -5557,14 +5709,14 @@ async function doInstallVercelRuntime({
5557
5709
  if (onStdout) {
5558
5710
  onStdout(data);
5559
5711
  } else {
5560
- (0, import_build_utils10.debug)(data.toString());
5712
+ (0, import_build_utils11.debug)(data.toString());
5561
5713
  }
5562
5714
  });
5563
5715
  child.stderr?.on("data", (data) => {
5564
5716
  if (onStderr) {
5565
5717
  onStderr(data);
5566
5718
  } else {
5567
- (0, import_build_utils10.debug)(data.toString());
5719
+ (0, import_build_utils11.debug)(data.toString());
5568
5720
  }
5569
5721
  });
5570
5722
  child.on("error", reject);
@@ -5589,7 +5741,7 @@ async function installVercelWorkers({
5589
5741
  onStdout,
5590
5742
  onStderr
5591
5743
  }) {
5592
- const targetDir = (0, import_path9.join)(workPath, ".vercel", "python");
5744
+ const targetDir = (0, import_path10.join)(workPath, ".vercel", "python");
5593
5745
  let pending = PENDING_WORKERS_INSTALLS.get(targetDir);
5594
5746
  if (!pending) {
5595
5747
  pending = doInstallVercelWorkers({
@@ -5615,8 +5767,8 @@ async function doInstallVercelWorkers({
5615
5767
  onStdout,
5616
5768
  onStderr
5617
5769
  }) {
5618
- (0, import_fs8.mkdirSync)(targetDir, { recursive: true });
5619
- const localWorkersDir = (0, import_path9.join)(
5770
+ (0, import_fs9.mkdirSync)(targetDir, { recursive: true });
5771
+ const localWorkersDir = (0, import_path10.join)(
5620
5772
  __dirname,
5621
5773
  "..",
5622
5774
  "..",
@@ -5624,21 +5776,21 @@ async function doInstallVercelWorkers({
5624
5776
  "python",
5625
5777
  "vercel-workers"
5626
5778
  );
5627
- const isLocalDev = (0, import_fs8.existsSync)((0, import_path9.join)(localWorkersDir, "pyproject.toml"));
5779
+ const isLocalDev = (0, import_fs9.existsSync)((0, import_path10.join)(localWorkersDir, "pyproject.toml"));
5628
5780
  const workersDep = env.VERCEL_WORKERS_PYTHON || (isLocalDev ? localWorkersDir : `vercel-workers==${VERCEL_WORKERS_VERSION}`);
5629
5781
  if (!isLocalDev && !env.VERCEL_WORKERS_PYTHON) {
5630
- const distInfo = (0, import_path9.join)(
5782
+ const distInfo = (0, import_path10.join)(
5631
5783
  targetDir,
5632
5784
  `vercel_workers-${VERCEL_WORKERS_VERSION}.dist-info`
5633
5785
  );
5634
- if ((0, import_fs8.existsSync)(distInfo)) {
5635
- (0, import_build_utils10.debug)(
5786
+ if ((0, import_fs9.existsSync)(distInfo)) {
5787
+ (0, import_build_utils11.debug)(
5636
5788
  `vercel-workers ${VERCEL_WORKERS_VERSION} already installed, skipping`
5637
5789
  );
5638
5790
  return;
5639
5791
  }
5640
5792
  }
5641
- (0, import_build_utils10.debug)(
5793
+ (0, import_build_utils11.debug)(
5642
5794
  `Installing vercel-workers into ${targetDir} (type: ${isLocalDev ? "local" : "pypi"}, source: ${workersDep})`
5643
5795
  );
5644
5796
  const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
@@ -5653,14 +5805,14 @@ async function doInstallVercelWorkers({
5653
5805
  if (onStdout) {
5654
5806
  onStdout(data);
5655
5807
  } else {
5656
- (0, import_build_utils10.debug)(data.toString());
5808
+ (0, import_build_utils11.debug)(data.toString());
5657
5809
  }
5658
5810
  });
5659
5811
  child.stderr?.on("data", (data) => {
5660
5812
  if (onStderr) {
5661
5813
  onStderr(data);
5662
5814
  } else {
5663
- (0, import_build_utils10.debug)(data.toString());
5815
+ (0, import_build_utils11.debug)(data.toString());
5664
5816
  }
5665
5817
  });
5666
5818
  child.on("error", reject);
@@ -5690,12 +5842,12 @@ function installGlobalCleanupHandlers() {
5690
5842
  try {
5691
5843
  process.kill(info.pid, "SIGTERM");
5692
5844
  } catch (err) {
5693
- (0, import_build_utils10.debug)(`Error sending SIGTERM to ${info.pid}: ${err}`);
5845
+ (0, import_build_utils11.debug)(`Error sending SIGTERM to ${info.pid}: ${err}`);
5694
5846
  }
5695
5847
  try {
5696
5848
  process.kill(info.pid, "SIGKILL");
5697
5849
  } catch (err) {
5698
- (0, import_build_utils10.debug)(`Error sending SIGKILL to ${info.pid}: ${err}`);
5850
+ (0, import_build_utils11.debug)(`Error sending SIGKILL to ${info.pid}: ${err}`);
5699
5851
  }
5700
5852
  PERSISTENT_SERVERS.delete(key);
5701
5853
  }
@@ -5703,7 +5855,7 @@ function installGlobalCleanupHandlers() {
5703
5855
  try {
5704
5856
  restoreWarnings();
5705
5857
  } catch (err) {
5706
- (0, import_build_utils10.debug)(`Error restoring warnings: ${err}`);
5858
+ (0, import_build_utils11.debug)(`Error restoring warnings: ${err}`);
5707
5859
  }
5708
5860
  restoreWarnings = null;
5709
5861
  }
@@ -5720,55 +5872,55 @@ function installGlobalCleanupHandlers() {
5720
5872
  }
5721
5873
  function createDevShim(workPath, entry, modulePath, serviceName, framework, variableName) {
5722
5874
  try {
5723
- const vercelPythonDir = serviceName ? (0, import_path9.join)(workPath, ".vercel", "python", "services", serviceName) : (0, import_path9.join)(workPath, ".vercel", "python");
5724
- (0, import_fs8.mkdirSync)(vercelPythonDir, { recursive: true });
5875
+ const vercelPythonDir = serviceName ? (0, import_path10.join)(workPath, ".vercel", "python", "services", serviceName) : (0, import_path10.join)(workPath, ".vercel", "python");
5876
+ (0, import_fs9.mkdirSync)(vercelPythonDir, { recursive: true });
5725
5877
  let qualifiedModule = modulePath;
5726
5878
  let extraPythonPath;
5727
- if ((0, import_fs8.existsSync)((0, import_path9.join)(workPath, "__init__.py"))) {
5728
- const pkgName = (0, import_path9.basename)(workPath);
5879
+ if ((0, import_fs9.existsSync)((0, import_path10.join)(workPath, "__init__.py"))) {
5880
+ const pkgName = (0, import_path10.basename)(workPath);
5729
5881
  qualifiedModule = `${pkgName}.${modulePath}`;
5730
- extraPythonPath = (0, import_path9.dirname)(workPath);
5882
+ extraPythonPath = (0, import_path10.dirname)(workPath);
5731
5883
  }
5732
- const entryAbs = (0, import_path9.join)(workPath, entry);
5733
- const shimPath = (0, import_path9.join)(vercelPythonDir, `${DEV_SHIM_MODULE}.py`);
5734
- const templatePath = (0, import_path9.join)(
5884
+ const entryAbs = (0, import_path10.join)(workPath, entry);
5885
+ const shimPath = (0, import_path10.join)(vercelPythonDir, `${DEV_SHIM_MODULE}.py`);
5886
+ const templatePath = (0, import_path10.join)(
5735
5887
  __dirname,
5736
5888
  "..",
5737
5889
  "templates",
5738
5890
  `${DEV_SHIM_MODULE}.py`
5739
5891
  );
5740
- const template = (0, import_fs8.readFileSync)(templatePath, "utf8");
5892
+ const template = (0, import_fs9.readFileSync)(templatePath, "utf8");
5741
5893
  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);
5742
- (0, import_fs8.writeFileSync)(shimPath, shimSource, "utf8");
5743
- (0, import_build_utils10.debug)(`Prepared Python dev shim at ${shimPath}`);
5894
+ (0, import_fs9.writeFileSync)(shimPath, shimSource, "utf8");
5895
+ (0, import_build_utils11.debug)(`Prepared Python dev shim at ${shimPath}`);
5744
5896
  return {
5745
5897
  module: DEV_SHIM_MODULE,
5746
5898
  extraPythonPath,
5747
5899
  shimDir: vercelPythonDir
5748
5900
  };
5749
5901
  } catch (err) {
5750
- (0, import_build_utils10.debug)(`Failed to prepare dev shim: ${err?.message || err}`);
5902
+ (0, import_build_utils11.debug)(`Failed to prepare dev shim: ${err?.message || err}`);
5751
5903
  return null;
5752
5904
  }
5753
5905
  }
5754
5906
  async function getMultiServicePythonRunner(workPath, env, systemPython, uvPath) {
5755
5907
  const { pythonCmd, venvRoot } = useVirtualEnv(workPath, env, systemPython);
5756
5908
  if (venvRoot) {
5757
- (0, import_build_utils10.debug)(`Using existing virtualenv at ${venvRoot} for multi-service dev`);
5909
+ (0, import_build_utils11.debug)(`Using existing virtualenv at ${venvRoot} for multi-service dev`);
5758
5910
  return { command: pythonCmd, args: [] };
5759
5911
  }
5760
- const venvPath = (0, import_path9.join)(workPath, ".venv");
5912
+ const venvPath = (0, import_path10.join)(workPath, ".venv");
5761
5913
  await ensureVenv({
5762
5914
  pythonVersion: { pythonPath: systemPython },
5763
5915
  venvPath,
5764
5916
  uvPath,
5765
5917
  quiet: true
5766
5918
  });
5767
- (0, import_build_utils10.debug)(`Created virtualenv at ${venvPath} for multi-service dev`);
5919
+ (0, import_build_utils11.debug)(`Created virtualenv at ${venvPath} for multi-service dev`);
5768
5920
  const pythonBin = getVenvPythonBin(venvPath);
5769
5921
  const binDir = getVenvBinDir(venvPath);
5770
5922
  env.VIRTUAL_ENV = venvPath;
5771
- env.PATH = `${binDir}${import_path9.delimiter}${env.PATH || ""}`;
5923
+ env.PATH = `${binDir}${import_path10.delimiter}${env.PATH || ""}`;
5772
5924
  return { command: pythonBin, args: [] };
5773
5925
  }
5774
5926
  var startDevServer = async (opts) => {
@@ -5831,7 +5983,7 @@ var startDevServer = async (opts) => {
5831
5983
  } else {
5832
5984
  const hookResult = await runFrameworkHook(framework, {
5833
5985
  pythonEnv: env,
5834
- projectDir: (0, import_path9.join)(workPath, detected?.baseDir ?? ""),
5986
+ projectDir: (0, import_path10.join)(workPath, detected?.baseDir ?? ""),
5835
5987
  workPath,
5836
5988
  entrypoint,
5837
5989
  detected: detected ?? void 0
@@ -5842,7 +5994,7 @@ var startDevServer = async (opts) => {
5842
5994
  if (detected?.error) {
5843
5995
  throw detected.error;
5844
5996
  }
5845
- throw new import_build_utils10.NowBuildError({
5997
+ throw new import_build_utils11.NowBuildError({
5846
5998
  code: "PYTHON_ENTRYPOINT_NOT_FOUND",
5847
5999
  message: "No Python entrypoint could be detected. Please specify an entrypoint file."
5848
6000
  });
@@ -5871,7 +6023,7 @@ var startDevServer = async (opts) => {
5871
6023
  const yellow = "\x1B[33m";
5872
6024
  const white = "\x1B[1m";
5873
6025
  const reset = "\x1B[0m";
5874
- throw new import_build_utils10.NowBuildError({
6026
+ throw new import_build_utils11.NowBuildError({
5875
6027
  code: "PYTHON_EXTERNAL_VENV_DETECTED",
5876
6028
  message: `Detected activated venv at ${yellow}${venv}${reset}, ${white}vercel dev${reset} manages virtual environments automatically.
5877
6029
  Run ${white}deactivate${reset} and try again.`
@@ -5888,11 +6040,11 @@ Run ${white}deactivate${reset} and try again.`
5888
6040
  );
5889
6041
  spawnCommand = runner.command;
5890
6042
  spawnArgsPrefix = runner.args;
5891
- (0, import_build_utils10.debug)(
6043
+ (0, import_build_utils11.debug)(
5892
6044
  `Multi-service Python runner: ${spawnCommand} ${spawnArgsPrefix.join(" ")}`
5893
6045
  );
5894
6046
  } else if (venv) {
5895
- (0, import_build_utils10.debug)(`Running in virtualenv at ${venv}`);
6047
+ (0, import_build_utils11.debug)(`Running in virtualenv at ${venv}`);
5896
6048
  } else {
5897
6049
  const { pythonCmd: venvPythonCmd, venvRoot } = useVirtualEnv(
5898
6050
  workPath,
@@ -5901,9 +6053,9 @@ Run ${white}deactivate${reset} and try again.`
5901
6053
  );
5902
6054
  spawnCommand = venvPythonCmd;
5903
6055
  if (venvRoot) {
5904
- (0, import_build_utils10.debug)(`Using virtualenv at ${venvRoot}`);
6056
+ (0, import_build_utils11.debug)(`Using virtualenv at ${venvRoot}`);
5905
6057
  } else {
5906
- (0, import_build_utils10.debug)("No virtualenv found");
6058
+ (0, import_build_utils11.debug)("No virtualenv found");
5907
6059
  try {
5908
6060
  const yellow = "\x1B[33m";
5909
6061
  const reset = "\x1B[0m";
@@ -5952,13 +6104,22 @@ If you are using a virtual environment, activate it before running "vercel dev",
5952
6104
  onStderr
5953
6105
  });
5954
6106
  }
6107
+ const crons = await getServiceCrons({
6108
+ service,
6109
+ entrypoint,
6110
+ rawEntrypoint,
6111
+ handlerFunction,
6112
+ pythonBin: spawnCommand,
6113
+ env,
6114
+ workPath
6115
+ });
6116
+ if (crons?.length) {
6117
+ env.__VC_CRON_ROUTES = JSON.stringify(buildCronRouteTable(crons));
6118
+ }
5955
6119
  const port = typeof meta.port === "number" ? meta.port : await (0, import_get_port.default)();
5956
6120
  env.PORT = `${port}`;
5957
- if (config.handlerFunction && typeof config?.handlerFunction === "string") {
5958
- env.__VC_HANDLER_FUNC_NAME = config.handlerFunction;
5959
- }
5960
6121
  if (entry) {
5961
- env.__VC_HANDLER_ENTRYPOINT_ABS = (0, import_path9.join)(workPath, entry);
6122
+ env.__VC_HANDLER_ENTRYPOINT_ABS = (0, import_path10.join)(workPath, entry);
5962
6123
  }
5963
6124
  const devShim = createDevShim(
5964
6125
  workPath,
@@ -5969,8 +6130,8 @@ If you are using a virtual environment, activate it before running "vercel dev",
5969
6130
  variableName ?? ""
5970
6131
  );
5971
6132
  if (devShim) {
5972
- const shimDir = devShim.shimDir || (0, import_path9.join)(workPath, ".vercel", "python");
5973
- const runtimeDir = (0, import_path9.join)(workPath, ".vercel", "python");
6133
+ const shimDir = devShim.shimDir || (0, import_path10.join)(workPath, ".vercel", "python");
6134
+ const runtimeDir = (0, import_path10.join)(workPath, ".vercel", "python");
5974
6135
  const pathParts = shimDir !== runtimeDir ? [shimDir, runtimeDir] : [shimDir];
5975
6136
  if (devShim.extraPythonPath) {
5976
6137
  pathParts.push(devShim.extraPythonPath);
@@ -5979,12 +6140,12 @@ If you are using a virtual environment, activate it before running "vercel dev",
5979
6140
  if (existingPythonPath) {
5980
6141
  pathParts.push(existingPythonPath);
5981
6142
  }
5982
- env.PYTHONPATH = pathParts.join(import_path9.delimiter);
6143
+ env.PYTHONPATH = pathParts.join(import_path10.delimiter);
5983
6144
  }
5984
6145
  const moduleToRun = devShim?.module || modulePath;
5985
6146
  const pythonArgs = ["-u", "-m", moduleToRun];
5986
6147
  const argv = [...spawnArgsPrefix, ...pythonArgs];
5987
- (0, import_build_utils10.debug)(
6148
+ (0, import_build_utils11.debug)(
5988
6149
  `Starting Python dev server (${framework}): ${spawnCommand} ${argv.join(" ")} [PORT=${port}]`
5989
6150
  );
5990
6151
  if (process.stdout.columns) {
@@ -6028,7 +6189,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
6028
6189
  });
6029
6190
  const shutdown = async () => {
6030
6191
  };
6031
- return { port, pid, shutdown };
6192
+ return { port, pid, shutdown, crons };
6032
6193
  } catch (err) {
6033
6194
  rejectChildReady(err);
6034
6195
  throw err;
@@ -6038,7 +6199,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
6038
6199
  };
6039
6200
 
6040
6201
  // src/quirks/index.ts
6041
- var import_build_utils13 = require("@vercel/build-utils");
6202
+ var import_build_utils14 = require("@vercel/build-utils");
6042
6203
  var import_python_analysis8 = require("@vercel/python-analysis");
6043
6204
 
6044
6205
  // src/quirks/matplotlib.ts
@@ -6052,9 +6213,9 @@ var matplotlibQuirk = {
6052
6213
  };
6053
6214
 
6054
6215
  // src/quirks/litellm.ts
6055
- var import_fs9 = __toESM(require("fs"));
6056
- var import_path10 = require("path");
6057
- var import_build_utils11 = require("@vercel/build-utils");
6216
+ var import_fs10 = __toESM(require("fs"));
6217
+ var import_path11 = require("path");
6218
+ var import_build_utils12 = require("@vercel/build-utils");
6058
6219
  var LAMBDA_ROOT = "/var/task";
6059
6220
  var CONFIG_CANDIDATES = [
6060
6221
  "litellm_config.yaml",
@@ -6064,9 +6225,9 @@ var CONFIG_CANDIDATES = [
6064
6225
  ];
6065
6226
  async function findConfigFile(workPath) {
6066
6227
  for (const name of CONFIG_CANDIDATES) {
6067
- const candidate = (0, import_path10.join)(workPath, name);
6228
+ const candidate = (0, import_path11.join)(workPath, name);
6068
6229
  try {
6069
- await import_fs9.default.promises.access(candidate);
6230
+ await import_fs10.default.promises.access(candidate);
6070
6231
  return name;
6071
6232
  } catch {
6072
6233
  }
@@ -6081,32 +6242,32 @@ var litellmQuirk = {
6081
6242
  const env = {};
6082
6243
  const sitePackagesDirs = await getVenvSitePackagesDirs(ctx.venvPath);
6083
6244
  for (const sitePackages of sitePackagesDirs) {
6084
- const schemaPath = (0, import_path10.join)(
6245
+ const schemaPath = (0, import_path11.join)(
6085
6246
  sitePackages,
6086
6247
  "litellm",
6087
6248
  "proxy",
6088
6249
  "schema.prisma"
6089
6250
  );
6090
6251
  try {
6091
- await import_fs9.default.promises.access(schemaPath);
6092
- (0, import_build_utils11.debug)(`LiteLLM quirk: found schema at ${schemaPath}`);
6252
+ await import_fs10.default.promises.access(schemaPath);
6253
+ (0, import_build_utils12.debug)(`LiteLLM quirk: found schema at ${schemaPath}`);
6093
6254
  buildEnv.PRISMA_SCHEMA_PATH = schemaPath;
6094
6255
  break;
6095
6256
  } catch {
6096
6257
  }
6097
6258
  }
6098
6259
  if (!buildEnv.PRISMA_SCHEMA_PATH) {
6099
- (0, import_build_utils11.debug)("LiteLLM quirk: schema.prisma not found in any site-packages");
6260
+ (0, import_build_utils12.debug)("LiteLLM quirk: schema.prisma not found in any site-packages");
6100
6261
  }
6101
6262
  if (!process.env.CONFIG_FILE_PATH) {
6102
6263
  const configName = await findConfigFile(ctx.workPath);
6103
6264
  if (configName) {
6104
- (0, import_build_utils11.debug)(`LiteLLM quirk: found config at ${configName}`);
6105
- buildEnv.CONFIG_FILE_PATH = (0, import_path10.join)(ctx.workPath, configName);
6106
- env.CONFIG_FILE_PATH = (0, import_path10.join)(LAMBDA_ROOT, configName);
6265
+ (0, import_build_utils12.debug)(`LiteLLM quirk: found config at ${configName}`);
6266
+ buildEnv.CONFIG_FILE_PATH = (0, import_path11.join)(ctx.workPath, configName);
6267
+ env.CONFIG_FILE_PATH = (0, import_path11.join)(LAMBDA_ROOT, configName);
6107
6268
  }
6108
6269
  } else {
6109
- (0, import_build_utils11.debug)(
6270
+ (0, import_build_utils12.debug)(
6110
6271
  `LiteLLM quirk: CONFIG_FILE_PATH already set to ${process.env.CONFIG_FILE_PATH}`
6111
6272
  );
6112
6273
  }
@@ -6115,10 +6276,10 @@ var litellmQuirk = {
6115
6276
  };
6116
6277
 
6117
6278
  // src/quirks/prisma.ts
6118
- var import_fs10 = __toESM(require("fs"));
6119
- var import_path11 = require("path");
6120
- var import_execa4 = __toESM(require_execa());
6121
- var import_build_utils12 = require("@vercel/build-utils");
6279
+ var import_fs11 = __toESM(require("fs"));
6280
+ var import_path12 = require("path");
6281
+ var import_execa5 = __toESM(require_execa());
6282
+ var import_build_utils13 = require("@vercel/build-utils");
6122
6283
  var import_python_analysis7 = require("@vercel/python-analysis");
6123
6284
  function execErrorMessage(err) {
6124
6285
  if (err != null && typeof err === "object" && "stderr" in err) {
@@ -6156,22 +6317,22 @@ model DummyModel {
6156
6317
  async function findUserSchema(workPath) {
6157
6318
  const envPath = process.env.PRISMA_SCHEMA_PATH;
6158
6319
  if (envPath) {
6159
- const resolved = (0, import_path11.isAbsolute)(envPath) ? envPath : (0, import_path11.join)(workPath, envPath);
6320
+ const resolved = (0, import_path12.isAbsolute)(envPath) ? envPath : (0, import_path12.join)(workPath, envPath);
6160
6321
  try {
6161
- await import_fs10.default.promises.access(resolved);
6322
+ await import_fs11.default.promises.access(resolved);
6162
6323
  return resolved;
6163
6324
  } catch {
6164
- (0, import_build_utils12.debug)(`PRISMA_SCHEMA_PATH=${envPath} not found at ${resolved}`);
6325
+ (0, import_build_utils13.debug)(`PRISMA_SCHEMA_PATH=${envPath} not found at ${resolved}`);
6165
6326
  return null;
6166
6327
  }
6167
6328
  }
6168
6329
  const candidates = [
6169
- (0, import_path11.join)(workPath, "schema.prisma"),
6170
- (0, import_path11.join)(workPath, "prisma", "schema.prisma")
6330
+ (0, import_path12.join)(workPath, "schema.prisma"),
6331
+ (0, import_path12.join)(workPath, "prisma", "schema.prisma")
6171
6332
  ];
6172
6333
  for (const candidate of candidates) {
6173
6334
  try {
6174
- await import_fs10.default.promises.access(candidate);
6335
+ await import_fs11.default.promises.access(candidate);
6175
6336
  return candidate;
6176
6337
  } catch {
6177
6338
  }
@@ -6182,32 +6343,32 @@ async function collectFiles(dir, base) {
6182
6343
  const result = [];
6183
6344
  let entries;
6184
6345
  try {
6185
- entries = await import_fs10.default.promises.readdir(dir, { withFileTypes: true });
6346
+ entries = await import_fs11.default.promises.readdir(dir, { withFileTypes: true });
6186
6347
  } catch {
6187
6348
  return result;
6188
6349
  }
6189
6350
  for (const entry of entries) {
6190
6351
  if (entry.name === "__pycache__")
6191
6352
  continue;
6192
- const full = (0, import_path11.join)(dir, entry.name);
6353
+ const full = (0, import_path12.join)(dir, entry.name);
6193
6354
  if (entry.isDirectory()) {
6194
6355
  result.push(...await collectFiles(full, base));
6195
6356
  } else {
6196
- result.push((0, import_path11.relative)(base, full));
6357
+ result.push((0, import_path12.relative)(base, full));
6197
6358
  }
6198
6359
  }
6199
6360
  return result;
6200
6361
  }
6201
6362
  async function cleanCacheArtifacts(cacheDir, extras = []) {
6202
6363
  const paths = [
6203
- (0, import_path11.join)(cacheDir, "node_modules"),
6204
- (0, import_path11.join)(cacheDir, "package.json"),
6205
- (0, import_path11.join)(cacheDir, "package-lock.json"),
6364
+ (0, import_path12.join)(cacheDir, "node_modules"),
6365
+ (0, import_path12.join)(cacheDir, "package.json"),
6366
+ (0, import_path12.join)(cacheDir, "package-lock.json"),
6206
6367
  ...extras
6207
6368
  ];
6208
6369
  for (const p of paths) {
6209
6370
  try {
6210
- await import_fs10.default.promises.rm(p, { recursive: true, force: true });
6371
+ await import_fs11.default.promises.rm(p, { recursive: true, force: true });
6211
6372
  } catch (err) {
6212
6373
  console.warn(
6213
6374
  `could not clean up ${p}: ${err instanceof Error ? err.message : String(err)}`
@@ -6217,7 +6378,7 @@ async function cleanCacheArtifacts(cacheDir, extras = []) {
6217
6378
  }
6218
6379
  async function isClientGenerated(pythonPath, env) {
6219
6380
  try {
6220
- await (0, import_execa4.default)(pythonPath, ["-c", "import prisma.client"], {
6381
+ await (0, import_execa5.default)(pythonPath, ["-c", "import prisma.client"], {
6221
6382
  env,
6222
6383
  stdio: "pipe"
6223
6384
  });
@@ -6231,7 +6392,7 @@ var prismaQuirk = {
6231
6392
  async run(ctx) {
6232
6393
  const { venvPath, pythonEnv, workPath } = ctx;
6233
6394
  const pythonPath = getVenvPythonBin(venvPath);
6234
- const runtimeCacheDir = (0, import_path11.join)(
6395
+ const runtimeCacheDir = (0, import_path12.join)(
6235
6396
  LAMBDA_ROOT2,
6236
6397
  resolveVendorDir(),
6237
6398
  "prisma",
@@ -6241,7 +6402,7 @@ var prismaQuirk = {
6241
6402
  let sitePackages;
6242
6403
  for (const dir of sitePackagesDirs) {
6243
6404
  try {
6244
- await import_fs10.default.promises.access((0, import_path11.join)(dir, "prisma"));
6405
+ await import_fs11.default.promises.access((0, import_path12.join)(dir, "prisma"));
6245
6406
  sitePackages = dir;
6246
6407
  break;
6247
6408
  } catch {
@@ -6253,21 +6414,21 @@ var prismaQuirk = {
6253
6414
  );
6254
6415
  return {};
6255
6416
  }
6256
- const cacheDir = (0, import_path11.join)(sitePackages, "prisma", "__bincache__");
6257
- await import_fs10.default.promises.mkdir(cacheDir, { recursive: true });
6417
+ const cacheDir = (0, import_path12.join)(sitePackages, "prisma", "__bincache__");
6418
+ await import_fs11.default.promises.mkdir(cacheDir, { recursive: true });
6258
6419
  const generateEnv = {
6259
6420
  ...pythonEnv,
6260
6421
  PRISMA_BINARY_CACHE_DIR: cacheDir
6261
6422
  };
6262
- const generatedDir = (0, import_path11.join)(workPath, "_prisma_generated");
6263
- const dummySchemaPath = (0, import_path11.join)(workPath, DUMMY_SCHEMA_NAME);
6264
- await import_fs10.default.promises.writeFile(
6423
+ const generatedDir = (0, import_path12.join)(workPath, "_prisma_generated");
6424
+ const dummySchemaPath = (0, import_path12.join)(workPath, DUMMY_SCHEMA_NAME);
6425
+ await import_fs11.default.promises.writeFile(
6265
6426
  dummySchemaPath,
6266
6427
  buildDummySchema(generatedDir)
6267
6428
  );
6268
- (0, import_build_utils12.debug)(`Running prisma generate (dummy) with cache dir: ${cacheDir}`);
6429
+ (0, import_build_utils13.debug)(`Running prisma generate (dummy) with cache dir: ${cacheDir}`);
6269
6430
  try {
6270
- const dummyResult = await (0, import_execa4.default)(
6431
+ const dummyResult = await (0, import_execa5.default)(
6271
6432
  pythonPath,
6272
6433
  ["-m", "prisma", "generate", `--schema=${dummySchemaPath}`],
6273
6434
  {
@@ -6277,11 +6438,11 @@ var prismaQuirk = {
6277
6438
  }
6278
6439
  );
6279
6440
  if (dummyResult.stdout)
6280
- (0, import_build_utils12.debug)(`prisma generate (dummy) stdout: ${dummyResult.stdout}`);
6441
+ (0, import_build_utils13.debug)(`prisma generate (dummy) stdout: ${dummyResult.stdout}`);
6281
6442
  if (dummyResult.stderr)
6282
- (0, import_build_utils12.debug)(`prisma generate (dummy) stderr: ${dummyResult.stderr}`);
6443
+ (0, import_build_utils13.debug)(`prisma generate (dummy) stderr: ${dummyResult.stderr}`);
6283
6444
  } catch (err) {
6284
- throw new import_build_utils12.NowBuildError({
6445
+ throw new import_build_utils13.NowBuildError({
6285
6446
  code: "PRISMA_GENERATE_FAILED",
6286
6447
  message: `Prisma engine download failed during \`prisma generate\`. Check that your prisma version is compatible with this Python version.
6287
6448
  ` + execErrorMessage(err)
@@ -6289,47 +6450,47 @@ var prismaQuirk = {
6289
6450
  }
6290
6451
  const srcBinaryPrefix = `query-engine-${getLambdaBinaryTarget()}`;
6291
6452
  const runtimeName = `prisma-query-engine-rhel-openssl-${RUNTIME_OPENSSL_VERSION}.x`;
6292
- const nodeModulesDir = (0, import_path11.join)(cacheDir, "node_modules", "prisma");
6453
+ const nodeModulesDir = (0, import_path12.join)(cacheDir, "node_modules", "prisma");
6293
6454
  let engineCopied = false;
6294
6455
  try {
6295
- const entries = await import_fs10.default.promises.readdir(nodeModulesDir);
6456
+ const entries = await import_fs11.default.promises.readdir(nodeModulesDir);
6296
6457
  for (const entry of entries) {
6297
6458
  if (!entry.startsWith(srcBinaryPrefix))
6298
6459
  continue;
6299
- const srcPath = (0, import_path11.join)(nodeModulesDir, entry);
6300
- const destPath = (0, import_path11.join)(cacheDir, runtimeName);
6460
+ const srcPath = (0, import_path12.join)(nodeModulesDir, entry);
6461
+ const destPath = (0, import_path12.join)(cacheDir, runtimeName);
6301
6462
  try {
6302
- await import_fs10.default.promises.access(destPath);
6303
- (0, import_build_utils12.debug)(`Engine binary: ${runtimeName} already exists, skipping`);
6463
+ await import_fs11.default.promises.access(destPath);
6464
+ (0, import_build_utils13.debug)(`Engine binary: ${runtimeName} already exists, skipping`);
6304
6465
  } catch {
6305
- (0, import_build_utils12.debug)(`Engine binary: copying ${entry} -> ${runtimeName}`);
6306
- await import_fs10.default.promises.copyFile(srcPath, destPath);
6466
+ (0, import_build_utils13.debug)(`Engine binary: copying ${entry} -> ${runtimeName}`);
6467
+ await import_fs11.default.promises.copyFile(srcPath, destPath);
6307
6468
  }
6308
6469
  engineCopied = true;
6309
6470
  }
6310
6471
  } catch (err) {
6311
- throw new import_build_utils12.NowBuildError({
6472
+ throw new import_build_utils13.NowBuildError({
6312
6473
  code: "PRISMA_ENGINE_NOT_FOUND",
6313
6474
  message: `could not read Prisma engine directory "${nodeModulesDir}". This may indicate an incompatible prisma version.
6314
6475
  ` + (err instanceof Error ? err.message : String(err))
6315
6476
  });
6316
6477
  }
6317
6478
  if (!engineCopied) {
6318
- throw new import_build_utils12.NowBuildError({
6479
+ throw new import_build_utils13.NowBuildError({
6319
6480
  code: "PRISMA_ENGINE_NOT_FOUND",
6320
6481
  message: `could not find engine binary matching "${srcBinaryPrefix}*" in "${nodeModulesDir}". This may indicate an incompatible prisma version or an unsupported platform (${process.arch}).`
6321
6482
  });
6322
6483
  }
6323
- const shimPath = (0, import_path11.join)(cacheDir, "openssl");
6324
- await import_fs10.default.promises.writeFile(
6484
+ const shimPath = (0, import_path12.join)(cacheDir, "openssl");
6485
+ await import_fs11.default.promises.writeFile(
6325
6486
  shimPath,
6326
6487
  `#!/bin/sh
6327
6488
  echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIME_OPENSSL_VERSION}.0)"
6328
6489
  `
6329
6490
  );
6330
- await import_fs10.default.promises.chmod(shimPath, 493);
6491
+ await import_fs11.default.promises.chmod(shimPath, 493);
6331
6492
  for (const p of [generatedDir, dummySchemaPath]) {
6332
- await import_fs10.default.promises.rm(p, { recursive: true, force: true });
6493
+ await import_fs11.default.promises.rm(p, { recursive: true, force: true });
6333
6494
  }
6334
6495
  await cleanCacheArtifacts(cacheDir);
6335
6496
  const generateMode = (process.env.VERCEL_PRISMA_GENERATE_CLIENT ?? "auto").toLowerCase();
@@ -6342,16 +6503,16 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
6342
6503
  pythonEnv
6343
6504
  );
6344
6505
  if (clientAlreadyGenerated) {
6345
- (0, import_build_utils12.debug)(
6506
+ (0, import_build_utils13.debug)(
6346
6507
  "Prisma quirk: client already generated, skipping user schema generate"
6347
6508
  );
6348
6509
  shouldGenerate = false;
6349
6510
  }
6350
6511
  }
6351
6512
  if (shouldGenerate) {
6352
- (0, import_build_utils12.debug)(`Running prisma generate with user schema: ${userSchema}`);
6513
+ (0, import_build_utils13.debug)(`Running prisma generate with user schema: ${userSchema}`);
6353
6514
  try {
6354
- const userResult = await (0, import_execa4.default)(
6515
+ const userResult = await (0, import_execa5.default)(
6355
6516
  pythonPath,
6356
6517
  ["-m", "prisma", "generate", `--schema=${userSchema}`],
6357
6518
  {
@@ -6361,11 +6522,11 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
6361
6522
  }
6362
6523
  );
6363
6524
  if (userResult.stdout)
6364
- (0, import_build_utils12.debug)(`prisma generate stdout: ${userResult.stdout}`);
6525
+ (0, import_build_utils13.debug)(`prisma generate stdout: ${userResult.stdout}`);
6365
6526
  if (userResult.stderr)
6366
- (0, import_build_utils12.debug)(`prisma generate stderr: ${userResult.stderr}`);
6527
+ (0, import_build_utils13.debug)(`prisma generate stderr: ${userResult.stderr}`);
6367
6528
  } catch (err) {
6368
- throw new import_build_utils12.NowBuildError({
6529
+ throw new import_build_utils13.NowBuildError({
6369
6530
  code: "PRISMA_GENERATE_FAILED",
6370
6531
  message: `\`prisma generate\` failed for schema "${userSchema}".
6371
6532
  ` + execErrorMessage(err)
@@ -6376,12 +6537,12 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
6376
6537
  }
6377
6538
  try {
6378
6539
  const allFiles = await collectFiles(
6379
- (0, import_path11.join)(sitePackages, "prisma"),
6540
+ (0, import_path12.join)(sitePackages, "prisma"),
6380
6541
  sitePackages
6381
6542
  );
6382
6543
  const count = await (0, import_python_analysis7.extendDistRecord)(sitePackages, "prisma", allFiles);
6383
6544
  if (count > 0) {
6384
- (0, import_build_utils12.debug)(`Appended ${count} entries to prisma RECORD`);
6545
+ (0, import_build_utils13.debug)(`Appended ${count} entries to prisma RECORD`);
6385
6546
  }
6386
6547
  } catch (err) {
6387
6548
  console.warn(
@@ -6475,13 +6636,13 @@ async function runQuirks(ctx) {
6475
6636
  (0, import_python_analysis8.normalizePackageName)(quirk.dependency)
6476
6637
  );
6477
6638
  if (!installed) {
6478
- (0, import_build_utils13.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
6639
+ (0, import_build_utils14.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
6479
6640
  }
6480
6641
  return installed;
6481
6642
  });
6482
6643
  const sorted = toposortQuirks(activated);
6483
6644
  for (const quirk of sorted) {
6484
- (0, import_build_utils13.debug)(`Quirk "${quirk.dependency}": detected, running fix-up`);
6645
+ (0, import_build_utils14.debug)(`Quirk "${quirk.dependency}": detected, running fix-up`);
6485
6646
  const result = await quirk.run(ctx);
6486
6647
  if (result.env) {
6487
6648
  Object.assign(mergedEnv, result.env);
@@ -6502,14 +6663,14 @@ async function runQuirks(ctx) {
6502
6663
  }
6503
6664
 
6504
6665
  // src/django.ts
6505
- var import_fs11 = __toESM(require("fs"));
6506
- var import_path12 = require("path");
6507
- var import_execa5 = __toESM(require_execa());
6508
- var import_build_utils14 = require("@vercel/build-utils");
6509
- var scriptPath = (0, import_path12.join)(__dirname, "..", "templates", "vc_django_settings.py");
6510
- var script = import_fs11.default.readFileSync(scriptPath, "utf-8");
6666
+ var import_fs12 = __toESM(require("fs"));
6667
+ var import_path13 = require("path");
6668
+ var import_execa6 = __toESM(require_execa());
6669
+ var import_build_utils15 = require("@vercel/build-utils");
6670
+ var scriptPath2 = (0, import_path13.join)(__dirname, "..", "templates", "vc_django_settings.py");
6671
+ var script2 = import_fs12.default.readFileSync(scriptPath2, "utf-8");
6511
6672
  async function getDjangoSettings(projectDir, env) {
6512
- const { stdout } = await (0, import_execa5.default)("python", ["-c", script], {
6673
+ const { stdout } = await (0, import_execa6.default)("python", ["-c", script2], {
6513
6674
  env,
6514
6675
  cwd: projectDir
6515
6676
  });
@@ -6535,21 +6696,21 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6535
6696
  const installedApps = djangoSettings["INSTALLED_APPS"] ?? [];
6536
6697
  const staticfilesDirs = djangoSettings["STATICFILES_DIRS"] ?? [];
6537
6698
  const staticSourceDirs = [
6538
- ...installedApps.map((app) => (0, import_path12.join)(workPath, ...app.split("."), "static")),
6699
+ ...installedApps.map((app) => (0, import_path13.join)(workPath, ...app.split("."), "static")),
6539
6700
  // TODO: Deal with optional prefixes in STATICFILES_DIRS.
6540
6701
  ...staticfilesDirs.map((d) => Array.isArray(d) ? d[1] : d)
6541
- ].filter((d) => import_fs11.default.existsSync(d));
6702
+ ].filter((d) => import_fs12.default.existsSync(d));
6542
6703
  if (storageBackend.startsWith("storages.backends.")) {
6543
6704
  console.log(
6544
6705
  "django-storages detected \u2014 running collectstatic with original settings"
6545
6706
  );
6546
- await (0, import_execa5.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6707
+ await (0, import_execa6.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6547
6708
  env: { ...env, DJANGO_SETTINGS_MODULE: settingsModule },
6548
6709
  cwd: workPath
6549
6710
  });
6550
6711
  return {
6551
6712
  staticSourceDirs,
6552
- staticRoot: staticRoot ? (0, import_path12.resolve)(workPath, staticRoot) : null,
6713
+ staticRoot: staticRoot ? (0, import_path13.resolve)(workPath, staticRoot) : null,
6553
6714
  cdnOutputDir: null,
6554
6715
  manifestRelPath: null
6555
6716
  };
@@ -6561,9 +6722,9 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6561
6722
  return null;
6562
6723
  }
6563
6724
  const staticUrlPath = staticUrl.replace(/^\/|\/$/g, "") || "static";
6564
- const staticOutputDir = (0, import_path12.join)(outputStaticDir, staticUrlPath);
6565
- await import_fs11.default.promises.mkdir(staticOutputDir, { recursive: true });
6566
- const shimPath = (0, import_path12.join)(workPath, "_vercel_collectstatic_settings.py");
6725
+ const staticOutputDir = (0, import_path13.join)(outputStaticDir, staticUrlPath);
6726
+ await import_fs12.default.promises.mkdir(staticOutputDir, { recursive: true });
6727
+ const shimPath = (0, import_path13.join)(workPath, "_vercel_collectstatic_settings.py");
6567
6728
  const shimLines = [
6568
6729
  `from ${settingsModule} import *`,
6569
6730
  `STATIC_ROOT = ${JSON.stringify(staticOutputDir)}`
@@ -6571,10 +6732,10 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6571
6732
  if (whitenoiseUseFinders) {
6572
6733
  shimLines.push(`WHITENOISE_USE_FINDERS = False`);
6573
6734
  }
6574
- await import_fs11.default.promises.writeFile(shimPath, shimLines.join("\n") + "\n");
6735
+ await import_fs12.default.promises.writeFile(shimPath, shimLines.join("\n") + "\n");
6575
6736
  try {
6576
6737
  console.log("Running collectstatic...");
6577
- await (0, import_execa5.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6738
+ await (0, import_execa6.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6578
6739
  env: {
6579
6740
  ...env,
6580
6741
  DJANGO_SETTINGS_MODULE: "_vercel_collectstatic_settings"
@@ -6582,7 +6743,7 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6582
6743
  cwd: workPath
6583
6744
  });
6584
6745
  } finally {
6585
- await import_fs11.default.promises.unlink(shimPath).catch(() => {
6746
+ await import_fs12.default.promises.unlink(shimPath).catch(() => {
6586
6747
  });
6587
6748
  }
6588
6749
  const MANIFEST_STORAGE_BACKENDS = [
@@ -6591,17 +6752,17 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6591
6752
  ];
6592
6753
  let manifestRelPath = null;
6593
6754
  if (MANIFEST_STORAGE_BACKENDS.includes(storageBackend) && staticRoot) {
6594
- const manifestSrc = (0, import_path12.join)(staticOutputDir, "staticfiles.json");
6595
- const resolvedStaticRoot = (0, import_path12.resolve)(workPath, staticRoot);
6596
- const manifestDest = (0, import_path12.join)(resolvedStaticRoot, "staticfiles.json");
6597
- await import_fs11.default.promises.mkdir(resolvedStaticRoot, { recursive: true });
6598
- await import_fs11.default.promises.copyFile(manifestSrc, manifestDest);
6599
- manifestRelPath = (0, import_path12.relative)(workPath, manifestDest);
6600
- (0, import_build_utils14.debug)(`Copied staticfiles.json to ${manifestDest} for Lambda bundle`);
6755
+ const manifestSrc = (0, import_path13.join)(staticOutputDir, "staticfiles.json");
6756
+ const resolvedStaticRoot = (0, import_path13.resolve)(workPath, staticRoot);
6757
+ const manifestDest = (0, import_path13.join)(resolvedStaticRoot, "staticfiles.json");
6758
+ await import_fs12.default.promises.mkdir(resolvedStaticRoot, { recursive: true });
6759
+ await import_fs12.default.promises.copyFile(manifestSrc, manifestDest);
6760
+ manifestRelPath = (0, import_path13.relative)(workPath, manifestDest);
6761
+ (0, import_build_utils15.debug)(`Copied staticfiles.json to ${manifestDest} for Lambda bundle`);
6601
6762
  }
6602
6763
  return {
6603
6764
  staticSourceDirs,
6604
- staticRoot: staticRoot ? (0, import_path12.resolve)(workPath, staticRoot) : null,
6765
+ staticRoot: staticRoot ? (0, import_path13.resolve)(workPath, staticRoot) : null,
6605
6766
  cdnOutputDir: outputStaticDir,
6606
6767
  manifestRelPath
6607
6768
  };
@@ -6609,7 +6770,7 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6609
6770
 
6610
6771
  // src/index.ts
6611
6772
  var import_python_analysis9 = require("@vercel/python-analysis");
6612
- var writeFile = import_fs12.default.promises.writeFile;
6773
+ var writeFile = import_fs13.default.promises.writeFile;
6613
6774
  var version = -1;
6614
6775
  async function runFrameworkHook(framework, ctx) {
6615
6776
  const hook = framework ? frameworkHooks[framework] : void 0;
@@ -6624,7 +6785,7 @@ var frameworkHooks = {
6624
6785
  detected
6625
6786
  }) => {
6626
6787
  if (detected?.baseDir === void 0) {
6627
- (0, import_build_utils15.debug)("Django hook: no manage.py detected, skipping");
6788
+ (0, import_build_utils16.debug)("Django hook: no manage.py detected, skipping");
6628
6789
  return;
6629
6790
  }
6630
6791
  let settingsResult;
@@ -6638,13 +6799,13 @@ Hint: activate a venv or run with \`uv run vercel dev\``;
6638
6799
  } else {
6639
6800
  detail = err?.stderr || err?.message || String(err);
6640
6801
  }
6641
- throw new import_build_utils15.NowBuildError({
6802
+ throw new import_build_utils16.NowBuildError({
6642
6803
  code: "DJANGO_SETTINGS_FAILED",
6643
6804
  message: `Failed to read Django application settings from ${projectDir}/manage.py:
6644
6805
  ${detail}`
6645
6806
  });
6646
6807
  }
6647
- (0, import_build_utils15.debug)(`Django settings: ${JSON.stringify(settingsResult)}`);
6808
+ (0, import_build_utils16.debug)(`Django settings: ${JSON.stringify(settingsResult)}`);
6648
6809
  const { djangoSettings, settingsModule, djangoVersion } = settingsResult;
6649
6810
  if (djangoVersion) {
6650
6811
  console.log(`Django ${djangoVersion.join(".")} detected`);
@@ -6657,7 +6818,7 @@ ${detail}`
6657
6818
  const variableName = parts.at(-1);
6658
6819
  const rel = `${parts.slice(0, -1).join("/")}.py`;
6659
6820
  const ep = baseDir ? `${baseDir}/${rel}` : rel;
6660
- (0, import_build_utils15.debug)(`Django hook: ASGI entrypoint: ${ep} (variable: ${variableName})`);
6821
+ (0, import_build_utils16.debug)(`Django hook: ASGI entrypoint: ${ep} (variable: ${variableName})`);
6661
6822
  resolvedEntrypoint = { entrypoint: ep, variableName };
6662
6823
  } else {
6663
6824
  const wsgiApp = djangoSettings["WSGI_APPLICATION"];
@@ -6666,7 +6827,7 @@ ${detail}`
6666
6827
  const variableName = parts.at(-1);
6667
6828
  const rel = `${parts.slice(0, -1).join("/")}.py`;
6668
6829
  const ep = baseDir ? `${baseDir}/${rel}` : rel;
6669
- (0, import_build_utils15.debug)(
6830
+ (0, import_build_utils16.debug)(
6670
6831
  `Django hook: WSGI entrypoint: ${ep} (variable: ${variableName})`
6671
6832
  );
6672
6833
  resolvedEntrypoint = { entrypoint: ep, variableName };
@@ -6674,7 +6835,7 @@ ${detail}`
6674
6835
  }
6675
6836
  let djangoStatic = null;
6676
6837
  if (workPath && venvPath) {
6677
- const outputStaticDir = (0, import_path13.join)(workPath, ".vercel", "output", "static");
6838
+ const outputStaticDir = (0, import_path14.join)(workPath, ".vercel", "output", "static");
6678
6839
  djangoStatic = await runDjangoCollectStatic(
6679
6840
  venvPath,
6680
6841
  workPath,
@@ -6694,14 +6855,14 @@ async function downloadFilesInWorkPath({
6694
6855
  files,
6695
6856
  meta = {}
6696
6857
  }) {
6697
- (0, import_build_utils15.debug)("Downloading user files...");
6698
- let downloadedFiles = await (0, import_build_utils15.download)(files, workPath, meta);
6858
+ (0, import_build_utils16.debug)("Downloading user files...");
6859
+ let downloadedFiles = await (0, import_build_utils16.download)(files, workPath, meta);
6699
6860
  if (meta.isDev && entrypoint) {
6700
- const { devCacheDir = (0, import_path13.join)(workPath, ".now", "cache") } = meta;
6701
- const cacheKey = (0, import_path13.basename)(entrypoint).replace(/\./g, "_");
6702
- const destCache = (0, import_path13.join)(devCacheDir, cacheKey);
6703
- await (0, import_build_utils15.download)(downloadedFiles, destCache);
6704
- downloadedFiles = await (0, import_build_utils15.glob)("**", destCache);
6861
+ const { devCacheDir = (0, import_path14.join)(workPath, ".now", "cache") } = meta;
6862
+ const cacheKey = (0, import_path14.basename)(entrypoint).replace(/\./g, "_");
6863
+ const destCache = (0, import_path14.join)(devCacheDir, cacheKey);
6864
+ await (0, import_build_utils16.download)(downloadedFiles, destCache);
6865
+ downloadedFiles = await (0, import_build_utils16.glob)("**", destCache);
6705
6866
  workPath = destCache;
6706
6867
  }
6707
6868
  return workPath;
@@ -6717,13 +6878,13 @@ var build = async ({
6717
6878
  service
6718
6879
  }) => {
6719
6880
  let entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
6720
- const builderSpan = parentSpan ?? new import_build_utils15.Span({ name: "vc.builder" });
6881
+ const builderSpan = parentSpan ?? new import_build_utils16.Span({ name: "vc.builder" });
6721
6882
  const framework = config?.framework;
6722
6883
  const shouldInstallVercelWorkers = config?.hasWorkerServices === true;
6723
6884
  let spawnEnv;
6724
6885
  let projectInstallCommand;
6725
6886
  let hasCustomCommand = false;
6726
- (0, import_build_utils15.debug)(`workPath: ${workPath}`);
6887
+ (0, import_build_utils16.debug)(`workPath: ${workPath}`);
6727
6888
  workPath = await downloadFilesInWorkPath({
6728
6889
  workPath,
6729
6890
  files: originalFiles,
@@ -6732,7 +6893,7 @@ var build = async ({
6732
6893
  });
6733
6894
  try {
6734
6895
  if (meta.isDev) {
6735
- const setupCfg = (0, import_path13.join)(workPath, "setup.cfg");
6896
+ const setupCfg = (0, import_path14.join)(workPath, "setup.cfg");
6736
6897
  await writeFile(setupCfg, "[install]\nprefix=\n");
6737
6898
  }
6738
6899
  } catch (err) {
@@ -6755,8 +6916,8 @@ var build = async ({
6755
6916
  if (detected?.error && detected?.baseDir === void 0) {
6756
6917
  throw detected?.error;
6757
6918
  }
6758
- const entryDirectory = detected?.baseDir ?? (entrypoint ? (0, import_path13.dirname)(entrypoint) : ".");
6759
- const entrypointAbsDir = (0, import_path13.join)(workPath, entryDirectory);
6919
+ const entryDirectory = detected?.baseDir ?? (entrypoint ? (0, import_path14.dirname)(entrypoint) : ".");
6920
+ const entrypointAbsDir = (0, import_path14.join)(workPath, entryDirectory);
6760
6921
  const rootDir = repoRootPath ?? workPath;
6761
6922
  const pythonPackage = await builderSpan.child("vc.builder.python.discover").trace(
6762
6923
  () => discoverPackage({
@@ -6786,12 +6947,26 @@ var build = async ({
6786
6947
  `
6787
6948
  );
6788
6949
  }
6789
- const venvPath = service?.name ? (0, import_path13.join)(workPath, ".vercel", "python", "services", service.name, ".venv") : (0, import_path13.join)(workPath, ".vercel", "python", ".venv");
6790
6950
  const uvCacheDir = getUvCacheDir(workPath);
6791
- const hasCachedVenv = import_fs12.default.existsSync((0, import_path13.join)(venvPath, "pyvenv.cfg"));
6792
- const hasCachedUv = import_fs12.default.existsSync(uvCacheDir);
6951
+ let uv;
6952
+ try {
6953
+ const uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
6954
+ uv = new UvRunner(uvPath, uvCacheDir);
6955
+ const uvVersionOutput = (0, import_child_process3.execSync)(`${uvPath} --version`, {
6956
+ encoding: "utf8"
6957
+ }).trim();
6958
+ console.log(`Using ${uvVersionOutput}`);
6959
+ } catch (err) {
6960
+ console.log("Failed to install or locate uv");
6961
+ throw new Error(
6962
+ `uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
6963
+ );
6964
+ }
6965
+ const venvPath = service?.name ? (0, import_path14.join)(workPath, ".vercel", "python", "services", service.name, ".venv") : (0, import_path14.join)(workPath, ".vercel", "python", ".venv");
6966
+ const hasCachedVenv = import_fs13.default.existsSync((0, import_path14.join)(venvPath, "pyvenv.cfg"));
6967
+ const hasCachedUv = import_fs13.default.existsSync(uvCacheDir);
6793
6968
  if (hasCachedVenv || hasCachedUv) {
6794
- (0, import_build_utils15.debug)(
6969
+ (0, import_build_utils16.debug)(
6795
6970
  `Build cache detected: venv=${hasCachedVenv}, uv-cache=${hasCachedUv}`
6796
6971
  );
6797
6972
  }
@@ -6799,17 +6974,18 @@ var build = async ({
6799
6974
  await ensureVenv({
6800
6975
  pythonVersion,
6801
6976
  venvPath,
6977
+ uvPath: uv.getPath(),
6802
6978
  uvCacheDir
6803
6979
  });
6804
6980
  });
6805
- if ((0, import_build_utils15.isPythonFramework)(framework)) {
6981
+ if ((0, import_build_utils16.isPythonFramework)(framework)) {
6806
6982
  const {
6807
6983
  cliType,
6808
6984
  lockfileVersion,
6809
6985
  packageJsonPackageManager,
6810
6986
  turboSupportsCorepackHome
6811
- } = await (0, import_build_utils15.scanParentDirs)(workPath, true);
6812
- spawnEnv = (0, import_build_utils15.getEnvForPackageManager)({
6987
+ } = await (0, import_build_utils16.scanParentDirs)(workPath, true);
6988
+ spawnEnv = (0, import_build_utils16.getEnvForPackageManager)({
6813
6989
  cliType,
6814
6990
  lockfileVersion,
6815
6991
  packageJsonPackageManager,
@@ -6831,38 +7007,25 @@ var build = async ({
6831
7007
  const pythonEnv = createVenvEnv(venvPath, baseEnv, uvCacheDir);
6832
7008
  pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
6833
7009
  let assumeDepsInstalled = false;
6834
- let uv;
6835
- try {
6836
- const uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
6837
- uv = new UvRunner(uvPath, uvCacheDir);
6838
- const uvVersionOutput = (0, import_child_process3.execSync)(`${uvPath} --version`, {
6839
- encoding: "utf8"
6840
- }).trim();
6841
- console.log(`Using ${uvVersionOutput}`);
6842
- } catch (err) {
6843
- console.log("Failed to install or locate uv");
6844
- throw new Error(
6845
- `uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
6846
- );
6847
- }
6848
7010
  let uvLockPath = null;
6849
7011
  let uvProjectDir = null;
6850
7012
  let projectName;
6851
- await builderSpan.child(import_build_utils15.BUILDER_INSTALLER_STEP, {
7013
+ await builderSpan.child(import_build_utils16.BUILDER_INSTALLER_STEP, {
6852
7014
  installCommand: projectInstallCommand || void 0
6853
7015
  }).trace(async () => {
6854
7016
  if (projectInstallCommand) {
6855
- await import_fs12.default.promises.rm(venvPath, { recursive: true, force: true });
7017
+ await import_fs13.default.promises.rm(venvPath, { recursive: true, force: true });
6856
7018
  await ensureVenv({
6857
7019
  pythonVersion,
6858
7020
  venvPath,
7021
+ uvPath: uv.getPath(),
6859
7022
  uvCacheDir,
6860
7023
  quiet: true
6861
7024
  });
6862
7025
  console.log(
6863
7026
  `Running "install" command: \`${projectInstallCommand}\`...`
6864
7027
  );
6865
- await (0, import_build_utils15.execCommand)(projectInstallCommand, {
7028
+ await (0, import_build_utils16.execCommand)(projectInstallCommand, {
6866
7029
  env: pythonEnv,
6867
7030
  cwd: workPath
6868
7031
  });
@@ -6883,7 +7046,7 @@ var build = async ({
6883
7046
  }
6884
7047
  if (!assumeDepsInstalled) {
6885
7048
  const lockCacheKey = service?.name ? `uv.lock.${service.name}` : "uv.lock";
6886
- const cachedLockPath = (0, import_path13.join)(uvCacheDir, lockCacheKey);
7049
+ const cachedLockPath = (0, import_path14.join)(uvCacheDir, lockCacheKey);
6887
7050
  const { projectDir, lockPath, lockFileProvidedByUser } = await ensureUvProject({
6888
7051
  workPath,
6889
7052
  rootDir,
@@ -6903,21 +7066,21 @@ var build = async ({
6903
7066
  frozen: lockFileProvidedByUser,
6904
7067
  locked: !lockFileProvidedByUser
6905
7068
  });
6906
- if (lockPath && import_fs12.default.existsSync(lockPath)) {
6907
- await import_fs12.default.promises.mkdir(uvCacheDir, { recursive: true });
6908
- await import_fs12.default.promises.copyFile(lockPath, cachedLockPath);
7069
+ if (lockPath && import_fs13.default.existsSync(lockPath)) {
7070
+ await import_fs13.default.promises.mkdir(uvCacheDir, { recursive: true });
7071
+ await import_fs13.default.promises.copyFile(lockPath, cachedLockPath);
6909
7072
  }
6910
7073
  }
6911
7074
  });
6912
- if ((0, import_build_utils15.isPythonFramework)(framework)) {
7075
+ if ((0, import_build_utils16.isPythonFramework)(framework)) {
6913
7076
  const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
6914
7077
  config?.buildCommand;
6915
- await builderSpan.child(import_build_utils15.BUILDER_COMPILE_STEP, {
7078
+ await builderSpan.child(import_build_utils16.BUILDER_COMPILE_STEP, {
6916
7079
  buildCommand: projectBuildCommand || void 0
6917
7080
  }).trace(async () => {
6918
7081
  if (projectBuildCommand) {
6919
7082
  console.log(`Running "${projectBuildCommand}"`);
6920
- await (0, import_build_utils15.execCommand)(projectBuildCommand, {
7083
+ await (0, import_build_utils16.execCommand)(projectBuildCommand, {
6921
7084
  env: pythonEnv,
6922
7085
  cwd: workPath
6923
7086
  });
@@ -6932,7 +7095,7 @@ var build = async ({
6932
7095
  }
6933
7096
  const hookResult = await runFrameworkHook(framework, {
6934
7097
  pythonEnv,
6935
- projectDir: (0, import_path13.join)(workPath, entryDirectory),
7098
+ projectDir: (0, import_path14.join)(workPath, entryDirectory),
6936
7099
  workPath,
6937
7100
  venvPath,
6938
7101
  entrypoint,
@@ -6944,25 +7107,25 @@ var build = async ({
6944
7107
  }
6945
7108
  entrypoint = resolved?.entrypoint;
6946
7109
  if (!entrypoint) {
6947
- throw new import_build_utils15.NowBuildError({
7110
+ throw new import_build_utils16.NowBuildError({
6948
7111
  code: "PYTHON_ENTRYPOINT_NOT_FOUND",
6949
7112
  message: "No Python entrypoint could be detected. Please specify an entrypoint file."
6950
7113
  });
6951
7114
  }
6952
7115
  const djangoStatic = hookResult?.djangoStatic ?? null;
6953
7116
  const runtimeDep = baseEnv.VERCEL_RUNTIME_PYTHON || `vercel-runtime==${VERCEL_RUNTIME_VERSION}`;
6954
- (0, import_build_utils15.debug)(`Installing ${runtimeDep}`);
7117
+ (0, import_build_utils16.debug)(`Installing ${runtimeDep}`);
6955
7118
  await uv.pip({
6956
7119
  venvPath,
6957
- projectDir: (0, import_path13.join)(workPath, entryDirectory),
7120
+ projectDir: (0, import_path14.join)(workPath, entryDirectory),
6958
7121
  args: ["install", runtimeDep]
6959
7122
  });
6960
7123
  if (shouldInstallVercelWorkers) {
6961
7124
  const workersDep = baseEnv.VERCEL_WORKERS_PYTHON || `vercel-workers==${VERCEL_WORKERS_VERSION}`;
6962
- (0, import_build_utils15.debug)(`Installing ${workersDep}`);
7125
+ (0, import_build_utils16.debug)(`Installing ${workersDep}`);
6963
7126
  await uv.pip({
6964
7127
  venvPath,
6965
- projectDir: (0, import_path13.join)(workPath, entryDirectory),
7128
+ projectDir: (0, import_path14.join)(workPath, entryDirectory),
6966
7129
  args: ["install", workersDep]
6967
7130
  });
6968
7131
  }
@@ -6970,14 +7133,14 @@ var build = async ({
6970
7133
  if (quirksResult.buildEnv) {
6971
7134
  Object.assign(pythonEnv, quirksResult.buildEnv);
6972
7135
  }
6973
- (0, import_build_utils15.debug)("Entrypoint is", entrypoint);
7136
+ (0, import_build_utils16.debug)("Entrypoint is", entrypoint);
6974
7137
  const moduleName = entrypoint.replace(/\//g, ".").replace(/\.py$/i, "");
6975
7138
  if (handlerFunction) {
6976
- const entrypointPath = (0, import_path13.join)(workPath, entrypoint);
6977
- const source = await import_fs12.default.promises.readFile(entrypointPath, "utf-8");
7139
+ const entrypointPath = (0, import_path14.join)(workPath, entrypoint);
7140
+ const source = await import_fs13.default.promises.readFile(entrypointPath, "utf-8");
6978
7141
  const found = await (0, import_python_analysis9.containsTopLevelCallable)(source, handlerFunction);
6979
7142
  if (!found) {
6980
- throw new import_build_utils15.NowBuildError({
7143
+ throw new import_build_utils16.NowBuildError({
6981
7144
  code: "PYTHON_HANDLER_NOT_FOUND",
6982
7145
  message: `Handler function "${handlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
6983
7146
  });
@@ -6986,9 +7149,23 @@ var build = async ({
6986
7149
  const vendorDir = resolveVendorDir();
6987
7150
  const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
6988
7151
  const entrypointWithSuffix = `${entrypoint}${suffix}`;
6989
- (0, import_build_utils15.debug)("Entrypoint with suffix is", entrypointWithSuffix);
6990
- const handlerFuncEnvLine = handlerFunction ? `
6991
- "__VC_HANDLER_FUNC_NAME": "${handlerFunction}",` : "";
7152
+ (0, import_build_utils16.debug)("Entrypoint with suffix is", entrypointWithSuffix);
7153
+ const crons = await getServiceCrons({
7154
+ service,
7155
+ entrypoint,
7156
+ rawEntrypoint,
7157
+ handlerFunction,
7158
+ pythonBin: getVenvPythonBin(venvPath),
7159
+ env: pythonEnv,
7160
+ workPath
7161
+ });
7162
+ let cronEnvLine = "";
7163
+ if (crons?.length) {
7164
+ const json = JSON.stringify(buildCronRouteTable(crons));
7165
+ (0, import_assert.default)(!json.includes("\\"), `backslash in cron route table: ${json}`);
7166
+ cronEnvLine = `
7167
+ "__VC_CRON_ROUTES": '${json}',`;
7168
+ }
6992
7169
  const variableName = resolved?.variableName ?? "";
6993
7170
  const runtimeTrampoline = `
6994
7171
  import importlib
@@ -7004,7 +7181,7 @@ os.environ.update({
7004
7181
  "__VC_HANDLER_ENTRYPOINT": "${entrypointWithSuffix}",
7005
7182
  "__VC_HANDLER_ENTRYPOINT_ABS": os.path.join(_here, "${entrypointWithSuffix}"),
7006
7183
  "__VC_HANDLER_VENDOR_DIR": "${vendorDir}",
7007
- "__VC_HANDLER_VARIABLE_NAME": "${variableName}",${handlerFuncEnvLine}
7184
+ "__VC_HANDLER_VARIABLE_NAME": "${variableName}",${cronEnvLine}
7008
7185
  })
7009
7186
 
7010
7187
  _vendor_rel = '${vendorDir}'
@@ -7057,10 +7234,10 @@ from vercel_runtime.vc_init import vc_handler
7057
7234
  cwd: workPath,
7058
7235
  ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
7059
7236
  };
7060
- const files = await (0, import_build_utils15.glob)("**", globOptions);
7237
+ const files = await (0, import_build_utils16.glob)("**", globOptions);
7061
7238
  if (djangoStatic?.manifestRelPath) {
7062
- files[djangoStatic.manifestRelPath] = new import_build_utils15.FileFsRef({
7063
- fsPath: (0, import_path13.join)(workPath, djangoStatic.manifestRelPath)
7239
+ files[djangoStatic.manifestRelPath] = new import_build_utils16.FileFsRef({
7240
+ fsPath: (0, import_path14.join)(workPath, djangoStatic.manifestRelPath)
7064
7241
  });
7065
7242
  }
7066
7243
  const depExternalizer = new PythonDependencyExternalizer({
@@ -7096,12 +7273,12 @@ from vercel_runtime.vc_init import vc_handler
7096
7273
  }
7097
7274
  });
7098
7275
  const handlerPyFilename = "vc__handler__python";
7099
- files[`${handlerPyFilename}.py`] = new import_build_utils15.FileBlob({ data: runtimeTrampoline });
7276
+ files[`${handlerPyFilename}.py`] = new import_build_utils16.FileBlob({ data: runtimeTrampoline });
7100
7277
  if (config.framework === "fasthtml") {
7101
7278
  const { SESSKEY = "" } = process.env;
7102
- files[".sesskey"] = new import_build_utils15.FileBlob({ data: `"${SESSKEY}"` });
7279
+ files[".sesskey"] = new import_build_utils16.FileBlob({ data: `"${SESSKEY}"` });
7103
7280
  }
7104
- const output = new import_build_utils15.Lambda({
7281
+ const output = new import_build_utils16.Lambda({
7105
7282
  files,
7106
7283
  handler: `${handlerPyFilename}.vc_handler`,
7107
7284
  runtime: pythonVersion.runtime,
@@ -7117,16 +7294,20 @@ from vercel_runtime.vc_init import vc_handler
7117
7294
  uvLockPath
7118
7295
  });
7119
7296
  } catch (err) {
7120
- (0, import_build_utils15.debug)(
7297
+ (0, import_build_utils16.debug)(
7121
7298
  `Failed to write project manifest: ${err instanceof Error ? err.message : String(err)}`
7122
7299
  );
7123
7300
  }
7124
7301
  }
7125
- if (!(0, import_build_utils15.isPythonFramework)(framework)) {
7302
+ if (!(0, import_build_utils16.isPythonFramework)(framework) && !service?.name) {
7126
7303
  return { resultVersion: 3, result: { output } };
7127
7304
  }
7128
7305
  const lambdaPath = service?.name ? `_svc/${service.name}/index` : "index";
7129
- const staticFiles = djangoStatic?.cdnOutputDir ? await (0, import_build_utils15.glob)("**", { cwd: djangoStatic.cdnOutputDir }) : {};
7306
+ const staticFiles = djangoStatic?.cdnOutputDir ? await (0, import_build_utils16.glob)("**", { cwd: djangoStatic.cdnOutputDir }) : {};
7307
+ const routes = [
7308
+ { handle: "filesystem" },
7309
+ { src: "/(.*)", dest: `/${lambdaPath}` }
7310
+ ];
7130
7311
  return {
7131
7312
  resultVersion: 2,
7132
7313
  result: {
@@ -7134,10 +7315,8 @@ from vercel_runtime.vc_init import vc_handler
7134
7315
  [lambdaPath]: output,
7135
7316
  ...staticFiles
7136
7317
  },
7137
- routes: [
7138
- { handle: "filesystem" },
7139
- { src: "/(.*)", dest: `/${lambdaPath}` }
7140
- ]
7318
+ routes,
7319
+ crons
7141
7320
  }
7142
7321
  };
7143
7322
  };
@@ -7159,14 +7338,14 @@ var prepareCache = async ({
7159
7338
  }
7160
7339
  } catch {
7161
7340
  }
7162
- return (0, import_build_utils15.glob)("**/.vercel/python/{.venv,services/*/.venv,cache/uv}/**", {
7341
+ return (0, import_build_utils16.glob)("**/.vercel/python/{.venv,services/*/.venv,cache/uv}/**", {
7163
7342
  cwd: root,
7164
7343
  ignore
7165
7344
  });
7166
7345
  };
7167
7346
  var shouldServe = (opts) => {
7168
7347
  const framework = opts.config.framework;
7169
- if ((0, import_build_utils15.isPythonFramework)(framework)) {
7348
+ if ((0, import_build_utils16.isPythonFramework)(framework)) {
7170
7349
  const requestPath = opts.requestPath.replace(/\/$/, "");
7171
7350
  if (requestPath.startsWith("api") && opts.hasMatched) {
7172
7351
  return false;
@@ -7185,7 +7364,7 @@ var defaultShouldServe = ({
7185
7364
  if (entrypoint === requestPath && hasProp(files, entrypoint)) {
7186
7365
  return true;
7187
7366
  }
7188
- const { dir, name } = (0, import_path13.parse)(entrypoint);
7367
+ const { dir, name } = (0, import_path14.parse)(entrypoint);
7189
7368
  if (name === "index" && dir === requestPath && hasProp(files, entrypoint)) {
7190
7369
  return true;
7191
7370
  }