@vercel/python 6.32.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
  }
@@ -5103,20 +5104,161 @@ var diagnostics = async ({
5103
5104
  }
5104
5105
  };
5105
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
+
5106
5248
  // src/start-dev-server.ts
5107
5249
  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");
5250
+ var import_fs9 = require("fs");
5251
+ var import_path10 = require("path");
5252
+ var import_build_utils11 = require("@vercel/build-utils");
5111
5253
  var import_get_port = __toESM(require_get_port());
5112
5254
  var import_is_port_reachable = __toESM(require_is_port_reachable());
5113
5255
 
5114
5256
  // 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");
5257
+ var import_fs8 = __toESM(require("fs"));
5258
+ var import_path9 = require("path");
5118
5259
  var import_build_utils8 = require("@vercel/build-utils");
5119
5260
  var import_build_utils9 = require("@vercel/build-utils");
5261
+ var import_build_utils10 = require("@vercel/build-utils");
5120
5262
  var import_python_analysis5 = require("@vercel/python-analysis");
5121
5263
  var PYTHON_ENTRYPOINT_FILENAMES = [
5122
5264
  "app",
@@ -5133,27 +5275,27 @@ var PYTHON_CANDIDATE_ENTRYPOINTS = getCandidateEntrypointsInDirs(
5133
5275
  function getCandidateEntrypointsInDirs(dirs) {
5134
5276
  return dirs.flatMap(
5135
5277
  (dir) => PYTHON_ENTRYPOINT_FILENAMES.map(
5136
- (filename) => import_path8.posix.join(dir, `${filename}.py`)
5278
+ (filename) => import_path9.posix.join(dir, `${filename}.py`)
5137
5279
  )
5138
5280
  );
5139
5281
  }
5140
5282
  async function fileExists(filePath) {
5141
5283
  try {
5142
- const stat = await import_fs7.default.promises.stat(filePath);
5284
+ const stat = await import_fs8.default.promises.stat(filePath);
5143
5285
  return stat.isFile();
5144
5286
  } catch {
5145
5287
  return false;
5146
5288
  }
5147
5289
  }
5148
5290
  async function checkEntrypoint(workPath, relPath) {
5149
- const absPath = (0, import_path8.join)(workPath, relPath);
5291
+ const absPath = (0, import_path9.join)(workPath, relPath);
5150
5292
  if (!await fileExists(absPath))
5151
5293
  return null;
5152
- const content = await import_fs7.default.promises.readFile(absPath, "utf-8");
5294
+ const content = await import_fs8.default.promises.readFile(absPath, "utf-8");
5153
5295
  return (0, import_python_analysis5.findAppOrHandler)(content);
5154
5296
  }
5155
5297
  async function getPyprojectEntrypoint(workPath) {
5156
- 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"));
5157
5299
  if (!pyprojectData)
5158
5300
  return null;
5159
5301
  const scripts = pyprojectData.project?.scripts;
@@ -5168,7 +5310,7 @@ async function getPyprojectEntrypoint(workPath) {
5168
5310
  const relPath = modulePath.replace(/\./g, "/");
5169
5311
  const candidates = [`${relPath}.py`, `${relPath}/__init__.py`];
5170
5312
  for (const candidate of candidates) {
5171
- if (await fileExists((0, import_path8.join)(workPath, candidate))) {
5313
+ if (await fileExists((0, import_path9.join)(workPath, candidate))) {
5172
5314
  return { entrypoint: candidate, variableName };
5173
5315
  }
5174
5316
  }
@@ -5178,19 +5320,19 @@ async function findValidEntrypoint(workPath, candidates) {
5178
5320
  for (const candidate of candidates) {
5179
5321
  const varName = await checkEntrypoint(workPath, candidate);
5180
5322
  if (varName) {
5181
- (0, import_build_utils8.debug)(`Detected Python entrypoint: ${candidate} (variable: ${varName})`);
5323
+ (0, import_build_utils9.debug)(`Detected Python entrypoint: ${candidate} (variable: ${varName})`);
5182
5324
  return { entrypoint: candidate, variableName: varName };
5183
5325
  }
5184
5326
  }
5185
5327
  return null;
5186
5328
  }
5187
5329
  async function checkDjangoManage(workPath) {
5188
- const managePath = (0, import_path8.join)(workPath, "manage.py");
5330
+ const managePath = (0, import_path9.join)(workPath, "manage.py");
5189
5331
  try {
5190
- const content = await import_fs7.default.promises.readFile(managePath, "utf-8");
5332
+ const content = await import_fs8.default.promises.readFile(managePath, "utf-8");
5191
5333
  if (!content.includes("DJANGO_SETTINGS_MODULE"))
5192
5334
  return false;
5193
- (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}`);
5194
5336
  return true;
5195
5337
  } catch {
5196
5338
  return false;
@@ -5198,7 +5340,7 @@ async function checkDjangoManage(workPath) {
5198
5340
  }
5199
5341
  async function getSubdirectories(workPath) {
5200
5342
  try {
5201
- const entries = await import_fs7.default.promises.readdir(workPath, {
5343
+ const entries = await import_fs8.default.promises.readdir(workPath, {
5202
5344
  withFileTypes: true
5203
5345
  });
5204
5346
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).sort();
@@ -5208,7 +5350,7 @@ async function getSubdirectories(workPath) {
5208
5350
  }
5209
5351
  function makeDetectError(framework) {
5210
5352
  const searchedList = PYTHON_CANDIDATE_ENTRYPOINTS.join(", ");
5211
- return new import_build_utils7.NowBuildError({
5353
+ return new import_build_utils8.NowBuildError({
5212
5354
  code: `${framework.toUpperCase()}_ENTRYPOINT_NOT_FOUND`,
5213
5355
  message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searchedList}.`,
5214
5356
  link: `https://vercel.com/docs/frameworks/backend/${framework}#exporting-the-${framework}-application`,
@@ -5223,7 +5365,7 @@ async function detectGenericPythonEntrypoint(workPath) {
5223
5365
  );
5224
5366
  return found ? { entrypoint: found } : null;
5225
5367
  } catch {
5226
- (0, import_build_utils8.debug)("Failed to discover Python entrypoint");
5368
+ (0, import_build_utils9.debug)("Failed to discover Python entrypoint");
5227
5369
  return null;
5228
5370
  }
5229
5371
  }
@@ -5232,7 +5374,7 @@ async function detectDjangoPythonEntrypoint(workPath) {
5232
5374
  const subdirs = await getSubdirectories(workPath);
5233
5375
  const rootDirs = ["", ...subdirs];
5234
5376
  for (const rootDir of rootDirs) {
5235
- const currPath = (0, import_path8.join)(workPath, rootDir);
5377
+ const currPath = (0, import_path9.join)(workPath, rootDir);
5236
5378
  const isDjango = await checkDjangoManage(currPath);
5237
5379
  if (isDjango) {
5238
5380
  return { baseDir: rootDir, error: makeDetectError("django") };
@@ -5242,7 +5384,7 @@ async function detectDjangoPythonEntrypoint(workPath) {
5242
5384
  const found = await findValidEntrypoint(workPath, candidates);
5243
5385
  return found ? { entrypoint: found } : null;
5244
5386
  } catch {
5245
- (0, import_build_utils8.debug)("Failed to discover Django Python entrypoint");
5387
+ (0, import_build_utils9.debug)("Failed to discover Django Python entrypoint");
5246
5388
  return null;
5247
5389
  }
5248
5390
  }
@@ -5258,11 +5400,11 @@ async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint,
5258
5400
  }
5259
5401
  }
5260
5402
  if (varName) {
5261
- (0, import_build_utils8.debug)(`Using configured Python entrypoint: ${entrypoint}`);
5403
+ (0, import_build_utils9.debug)(`Using configured Python entrypoint: ${entrypoint}`);
5262
5404
  return { entrypoint: { entrypoint, variableName: varName } };
5263
5405
  } else {
5264
5406
  return {
5265
- error: new import_build_utils7.NowBuildError({
5407
+ error: new import_build_utils8.NowBuildError({
5266
5408
  code: "PYTHON_ENTRYPOINT_NOT_FOUND",
5267
5409
  message: `Could not find a top-level "app", "application", or "handler" in "${entrypoint}".`,
5268
5410
  link: "https://vercel.com/docs/functions/serverless-functions/runtimes/python",
@@ -5368,17 +5510,17 @@ async function syncDependencies({
5368
5510
  let { manifestPath } = installInfo;
5369
5511
  const manifest = pythonPackage.manifest;
5370
5512
  if (!manifestType || !manifestPath) {
5371
- (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");
5372
5514
  return;
5373
5515
  }
5374
5516
  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");
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");
5378
5520
  const content = (0, import_python_analysis6.stringifyManifest)(manifest.data);
5379
- (0, import_fs8.writeFileSync)(tempPyproject, content, "utf8");
5521
+ (0, import_fs9.writeFileSync)(tempPyproject, content, "utf8");
5380
5522
  manifestPath = tempPyproject;
5381
- (0, import_build_utils10.debug)(
5523
+ (0, import_build_utils11.debug)(
5382
5524
  `Wrote converted ${manifest.origin.kind} manifest to ${tempPyproject}`
5383
5525
  );
5384
5526
  }
@@ -5411,7 +5553,7 @@ async function syncDependencies({
5411
5553
  for (const [channel, chunk] of captured) {
5412
5554
  (channel === "stdout" ? writeOut : writeErr)(chunk.toString());
5413
5555
  }
5414
- throw new import_build_utils10.NowBuildError({
5556
+ throw new import_build_utils11.NowBuildError({
5415
5557
  code: "PYTHON_DEPENDENCY_SYNC_FAILED",
5416
5558
  message: `Failed to install Python dependencies from ${manifestType}: ${err instanceof Error ? err.message : String(err)}`
5417
5559
  });
@@ -5426,14 +5568,14 @@ async function runSync({
5426
5568
  onStdout,
5427
5569
  onStderr
5428
5570
  }) {
5429
- const projectDir = (0, import_path9.dirname)(manifestPath);
5571
+ const projectDir = (0, import_path10.dirname)(manifestPath);
5430
5572
  const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
5431
5573
  let spawnCmd;
5432
5574
  let spawnArgs;
5433
5575
  switch (manifestType) {
5434
5576
  case "uv.lock": {
5435
5577
  if (!uvPath) {
5436
- throw new import_build_utils10.NowBuildError({
5578
+ throw new import_build_utils11.NowBuildError({
5437
5579
  code: "PYTHON_DEPENDENCY_SYNC_FAILED",
5438
5580
  message: "uv is required to install dependencies from uv.lock.",
5439
5581
  link: "https://docs.astral.sh/uv/getting-started/installation/",
@@ -5455,11 +5597,11 @@ async function runSync({
5455
5597
  break;
5456
5598
  }
5457
5599
  default:
5458
- (0, import_build_utils10.debug)(`Unknown manifest type: ${manifestType}`);
5600
+ (0, import_build_utils11.debug)(`Unknown manifest type: ${manifestType}`);
5459
5601
  return;
5460
5602
  }
5461
5603
  await new Promise((resolve3, reject) => {
5462
- (0, import_build_utils10.debug)(`Running "${spawnCmd} ${spawnArgs.join(" ")}" in ${projectDir}...`);
5604
+ (0, import_build_utils11.debug)(`Running "${spawnCmd} ${spawnArgs.join(" ")}" in ${projectDir}...`);
5463
5605
  const child = (0, import_child_process2.spawn)(spawnCmd, spawnArgs, {
5464
5606
  cwd: projectDir,
5465
5607
  env: getProtectedUvEnv(env),
@@ -5503,7 +5645,7 @@ async function installVercelRuntime({
5503
5645
  onStdout,
5504
5646
  onStderr
5505
5647
  }) {
5506
- const targetDir = (0, import_path9.join)(workPath, ".vercel", "python");
5648
+ const targetDir = (0, import_path10.join)(workPath, ".vercel", "python");
5507
5649
  let pending = PENDING_RUNTIME_INSTALLS.get(targetDir);
5508
5650
  if (!pending) {
5509
5651
  pending = doInstallVercelRuntime({
@@ -5529,8 +5671,8 @@ async function doInstallVercelRuntime({
5529
5671
  onStdout,
5530
5672
  onStderr
5531
5673
  }) {
5532
- (0, import_fs8.mkdirSync)(targetDir, { recursive: true });
5533
- const localRuntimeDir = (0, import_path9.join)(
5674
+ (0, import_fs9.mkdirSync)(targetDir, { recursive: true });
5675
+ const localRuntimeDir = (0, import_path10.join)(
5534
5676
  __dirname,
5535
5677
  "..",
5536
5678
  "..",
@@ -5538,21 +5680,21 @@ async function doInstallVercelRuntime({
5538
5680
  "python",
5539
5681
  "vercel-runtime"
5540
5682
  );
5541
- 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"));
5542
5684
  const runtimeDep = env.VERCEL_RUNTIME_PYTHON || (isLocalDev ? localRuntimeDir : `vercel-runtime==${VERCEL_RUNTIME_VERSION}`);
5543
5685
  if (!isLocalDev && !env.VERCEL_RUNTIME_PYTHON) {
5544
- const distInfo = (0, import_path9.join)(
5686
+ const distInfo = (0, import_path10.join)(
5545
5687
  targetDir,
5546
5688
  `vercel_runtime-${VERCEL_RUNTIME_VERSION}.dist-info`
5547
5689
  );
5548
- if ((0, import_fs8.existsSync)(distInfo)) {
5549
- (0, import_build_utils10.debug)(
5690
+ if ((0, import_fs9.existsSync)(distInfo)) {
5691
+ (0, import_build_utils11.debug)(
5550
5692
  `vercel-runtime ${VERCEL_RUNTIME_VERSION} already installed, skipping`
5551
5693
  );
5552
5694
  return;
5553
5695
  }
5554
5696
  }
5555
- (0, import_build_utils10.debug)(
5697
+ (0, import_build_utils11.debug)(
5556
5698
  `Installing vercel-runtime into ${targetDir} (type: ${isLocalDev ? "local" : "pypi"}, source: ${runtimeDep})`
5557
5699
  );
5558
5700
  const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
@@ -5567,14 +5709,14 @@ async function doInstallVercelRuntime({
5567
5709
  if (onStdout) {
5568
5710
  onStdout(data);
5569
5711
  } else {
5570
- (0, import_build_utils10.debug)(data.toString());
5712
+ (0, import_build_utils11.debug)(data.toString());
5571
5713
  }
5572
5714
  });
5573
5715
  child.stderr?.on("data", (data) => {
5574
5716
  if (onStderr) {
5575
5717
  onStderr(data);
5576
5718
  } else {
5577
- (0, import_build_utils10.debug)(data.toString());
5719
+ (0, import_build_utils11.debug)(data.toString());
5578
5720
  }
5579
5721
  });
5580
5722
  child.on("error", reject);
@@ -5599,7 +5741,7 @@ async function installVercelWorkers({
5599
5741
  onStdout,
5600
5742
  onStderr
5601
5743
  }) {
5602
- const targetDir = (0, import_path9.join)(workPath, ".vercel", "python");
5744
+ const targetDir = (0, import_path10.join)(workPath, ".vercel", "python");
5603
5745
  let pending = PENDING_WORKERS_INSTALLS.get(targetDir);
5604
5746
  if (!pending) {
5605
5747
  pending = doInstallVercelWorkers({
@@ -5625,8 +5767,8 @@ async function doInstallVercelWorkers({
5625
5767
  onStdout,
5626
5768
  onStderr
5627
5769
  }) {
5628
- (0, import_fs8.mkdirSync)(targetDir, { recursive: true });
5629
- const localWorkersDir = (0, import_path9.join)(
5770
+ (0, import_fs9.mkdirSync)(targetDir, { recursive: true });
5771
+ const localWorkersDir = (0, import_path10.join)(
5630
5772
  __dirname,
5631
5773
  "..",
5632
5774
  "..",
@@ -5634,21 +5776,21 @@ async function doInstallVercelWorkers({
5634
5776
  "python",
5635
5777
  "vercel-workers"
5636
5778
  );
5637
- 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"));
5638
5780
  const workersDep = env.VERCEL_WORKERS_PYTHON || (isLocalDev ? localWorkersDir : `vercel-workers==${VERCEL_WORKERS_VERSION}`);
5639
5781
  if (!isLocalDev && !env.VERCEL_WORKERS_PYTHON) {
5640
- const distInfo = (0, import_path9.join)(
5782
+ const distInfo = (0, import_path10.join)(
5641
5783
  targetDir,
5642
5784
  `vercel_workers-${VERCEL_WORKERS_VERSION}.dist-info`
5643
5785
  );
5644
- if ((0, import_fs8.existsSync)(distInfo)) {
5645
- (0, import_build_utils10.debug)(
5786
+ if ((0, import_fs9.existsSync)(distInfo)) {
5787
+ (0, import_build_utils11.debug)(
5646
5788
  `vercel-workers ${VERCEL_WORKERS_VERSION} already installed, skipping`
5647
5789
  );
5648
5790
  return;
5649
5791
  }
5650
5792
  }
5651
- (0, import_build_utils10.debug)(
5793
+ (0, import_build_utils11.debug)(
5652
5794
  `Installing vercel-workers into ${targetDir} (type: ${isLocalDev ? "local" : "pypi"}, source: ${workersDep})`
5653
5795
  );
5654
5796
  const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
@@ -5663,14 +5805,14 @@ async function doInstallVercelWorkers({
5663
5805
  if (onStdout) {
5664
5806
  onStdout(data);
5665
5807
  } else {
5666
- (0, import_build_utils10.debug)(data.toString());
5808
+ (0, import_build_utils11.debug)(data.toString());
5667
5809
  }
5668
5810
  });
5669
5811
  child.stderr?.on("data", (data) => {
5670
5812
  if (onStderr) {
5671
5813
  onStderr(data);
5672
5814
  } else {
5673
- (0, import_build_utils10.debug)(data.toString());
5815
+ (0, import_build_utils11.debug)(data.toString());
5674
5816
  }
5675
5817
  });
5676
5818
  child.on("error", reject);
@@ -5700,12 +5842,12 @@ function installGlobalCleanupHandlers() {
5700
5842
  try {
5701
5843
  process.kill(info.pid, "SIGTERM");
5702
5844
  } catch (err) {
5703
- (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}`);
5704
5846
  }
5705
5847
  try {
5706
5848
  process.kill(info.pid, "SIGKILL");
5707
5849
  } catch (err) {
5708
- (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}`);
5709
5851
  }
5710
5852
  PERSISTENT_SERVERS.delete(key);
5711
5853
  }
@@ -5713,7 +5855,7 @@ function installGlobalCleanupHandlers() {
5713
5855
  try {
5714
5856
  restoreWarnings();
5715
5857
  } catch (err) {
5716
- (0, import_build_utils10.debug)(`Error restoring warnings: ${err}`);
5858
+ (0, import_build_utils11.debug)(`Error restoring warnings: ${err}`);
5717
5859
  }
5718
5860
  restoreWarnings = null;
5719
5861
  }
@@ -5730,55 +5872,55 @@ function installGlobalCleanupHandlers() {
5730
5872
  }
5731
5873
  function createDevShim(workPath, entry, modulePath, serviceName, framework, variableName) {
5732
5874
  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 });
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 });
5735
5877
  let qualifiedModule = modulePath;
5736
5878
  let extraPythonPath;
5737
- if ((0, import_fs8.existsSync)((0, import_path9.join)(workPath, "__init__.py"))) {
5738
- 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);
5739
5881
  qualifiedModule = `${pkgName}.${modulePath}`;
5740
- extraPythonPath = (0, import_path9.dirname)(workPath);
5882
+ extraPythonPath = (0, import_path10.dirname)(workPath);
5741
5883
  }
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)(
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)(
5745
5887
  __dirname,
5746
5888
  "..",
5747
5889
  "templates",
5748
5890
  `${DEV_SHIM_MODULE}.py`
5749
5891
  );
5750
- const template = (0, import_fs8.readFileSync)(templatePath, "utf8");
5892
+ const template = (0, import_fs9.readFileSync)(templatePath, "utf8");
5751
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);
5752
- (0, import_fs8.writeFileSync)(shimPath, shimSource, "utf8");
5753
- (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}`);
5754
5896
  return {
5755
5897
  module: DEV_SHIM_MODULE,
5756
5898
  extraPythonPath,
5757
5899
  shimDir: vercelPythonDir
5758
5900
  };
5759
5901
  } catch (err) {
5760
- (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}`);
5761
5903
  return null;
5762
5904
  }
5763
5905
  }
5764
5906
  async function getMultiServicePythonRunner(workPath, env, systemPython, uvPath) {
5765
5907
  const { pythonCmd, venvRoot } = useVirtualEnv(workPath, env, systemPython);
5766
5908
  if (venvRoot) {
5767
- (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`);
5768
5910
  return { command: pythonCmd, args: [] };
5769
5911
  }
5770
- const venvPath = (0, import_path9.join)(workPath, ".venv");
5912
+ const venvPath = (0, import_path10.join)(workPath, ".venv");
5771
5913
  await ensureVenv({
5772
5914
  pythonVersion: { pythonPath: systemPython },
5773
5915
  venvPath,
5774
5916
  uvPath,
5775
5917
  quiet: true
5776
5918
  });
5777
- (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`);
5778
5920
  const pythonBin = getVenvPythonBin(venvPath);
5779
5921
  const binDir = getVenvBinDir(venvPath);
5780
5922
  env.VIRTUAL_ENV = venvPath;
5781
- env.PATH = `${binDir}${import_path9.delimiter}${env.PATH || ""}`;
5923
+ env.PATH = `${binDir}${import_path10.delimiter}${env.PATH || ""}`;
5782
5924
  return { command: pythonBin, args: [] };
5783
5925
  }
5784
5926
  var startDevServer = async (opts) => {
@@ -5841,7 +5983,7 @@ var startDevServer = async (opts) => {
5841
5983
  } else {
5842
5984
  const hookResult = await runFrameworkHook(framework, {
5843
5985
  pythonEnv: env,
5844
- projectDir: (0, import_path9.join)(workPath, detected?.baseDir ?? ""),
5986
+ projectDir: (0, import_path10.join)(workPath, detected?.baseDir ?? ""),
5845
5987
  workPath,
5846
5988
  entrypoint,
5847
5989
  detected: detected ?? void 0
@@ -5852,7 +5994,7 @@ var startDevServer = async (opts) => {
5852
5994
  if (detected?.error) {
5853
5995
  throw detected.error;
5854
5996
  }
5855
- throw new import_build_utils10.NowBuildError({
5997
+ throw new import_build_utils11.NowBuildError({
5856
5998
  code: "PYTHON_ENTRYPOINT_NOT_FOUND",
5857
5999
  message: "No Python entrypoint could be detected. Please specify an entrypoint file."
5858
6000
  });
@@ -5881,7 +6023,7 @@ var startDevServer = async (opts) => {
5881
6023
  const yellow = "\x1B[33m";
5882
6024
  const white = "\x1B[1m";
5883
6025
  const reset = "\x1B[0m";
5884
- throw new import_build_utils10.NowBuildError({
6026
+ throw new import_build_utils11.NowBuildError({
5885
6027
  code: "PYTHON_EXTERNAL_VENV_DETECTED",
5886
6028
  message: `Detected activated venv at ${yellow}${venv}${reset}, ${white}vercel dev${reset} manages virtual environments automatically.
5887
6029
  Run ${white}deactivate${reset} and try again.`
@@ -5898,11 +6040,11 @@ Run ${white}deactivate${reset} and try again.`
5898
6040
  );
5899
6041
  spawnCommand = runner.command;
5900
6042
  spawnArgsPrefix = runner.args;
5901
- (0, import_build_utils10.debug)(
6043
+ (0, import_build_utils11.debug)(
5902
6044
  `Multi-service Python runner: ${spawnCommand} ${spawnArgsPrefix.join(" ")}`
5903
6045
  );
5904
6046
  } else if (venv) {
5905
- (0, import_build_utils10.debug)(`Running in virtualenv at ${venv}`);
6047
+ (0, import_build_utils11.debug)(`Running in virtualenv at ${venv}`);
5906
6048
  } else {
5907
6049
  const { pythonCmd: venvPythonCmd, venvRoot } = useVirtualEnv(
5908
6050
  workPath,
@@ -5911,9 +6053,9 @@ Run ${white}deactivate${reset} and try again.`
5911
6053
  );
5912
6054
  spawnCommand = venvPythonCmd;
5913
6055
  if (venvRoot) {
5914
- (0, import_build_utils10.debug)(`Using virtualenv at ${venvRoot}`);
6056
+ (0, import_build_utils11.debug)(`Using virtualenv at ${venvRoot}`);
5915
6057
  } else {
5916
- (0, import_build_utils10.debug)("No virtualenv found");
6058
+ (0, import_build_utils11.debug)("No virtualenv found");
5917
6059
  try {
5918
6060
  const yellow = "\x1B[33m";
5919
6061
  const reset = "\x1B[0m";
@@ -5962,13 +6104,22 @@ If you are using a virtual environment, activate it before running "vercel dev",
5962
6104
  onStderr
5963
6105
  });
5964
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
+ }
5965
6119
  const port = typeof meta.port === "number" ? meta.port : await (0, import_get_port.default)();
5966
6120
  env.PORT = `${port}`;
5967
- if (config.handlerFunction && typeof config?.handlerFunction === "string") {
5968
- env.__VC_HANDLER_FUNC_NAME = config.handlerFunction;
5969
- }
5970
6121
  if (entry) {
5971
- env.__VC_HANDLER_ENTRYPOINT_ABS = (0, import_path9.join)(workPath, entry);
6122
+ env.__VC_HANDLER_ENTRYPOINT_ABS = (0, import_path10.join)(workPath, entry);
5972
6123
  }
5973
6124
  const devShim = createDevShim(
5974
6125
  workPath,
@@ -5979,8 +6130,8 @@ If you are using a virtual environment, activate it before running "vercel dev",
5979
6130
  variableName ?? ""
5980
6131
  );
5981
6132
  if (devShim) {
5982
- const shimDir = devShim.shimDir || (0, import_path9.join)(workPath, ".vercel", "python");
5983
- 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");
5984
6135
  const pathParts = shimDir !== runtimeDir ? [shimDir, runtimeDir] : [shimDir];
5985
6136
  if (devShim.extraPythonPath) {
5986
6137
  pathParts.push(devShim.extraPythonPath);
@@ -5989,12 +6140,12 @@ If you are using a virtual environment, activate it before running "vercel dev",
5989
6140
  if (existingPythonPath) {
5990
6141
  pathParts.push(existingPythonPath);
5991
6142
  }
5992
- env.PYTHONPATH = pathParts.join(import_path9.delimiter);
6143
+ env.PYTHONPATH = pathParts.join(import_path10.delimiter);
5993
6144
  }
5994
6145
  const moduleToRun = devShim?.module || modulePath;
5995
6146
  const pythonArgs = ["-u", "-m", moduleToRun];
5996
6147
  const argv = [...spawnArgsPrefix, ...pythonArgs];
5997
- (0, import_build_utils10.debug)(
6148
+ (0, import_build_utils11.debug)(
5998
6149
  `Starting Python dev server (${framework}): ${spawnCommand} ${argv.join(" ")} [PORT=${port}]`
5999
6150
  );
6000
6151
  if (process.stdout.columns) {
@@ -6038,7 +6189,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
6038
6189
  });
6039
6190
  const shutdown = async () => {
6040
6191
  };
6041
- return { port, pid, shutdown };
6192
+ return { port, pid, shutdown, crons };
6042
6193
  } catch (err) {
6043
6194
  rejectChildReady(err);
6044
6195
  throw err;
@@ -6048,7 +6199,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
6048
6199
  };
6049
6200
 
6050
6201
  // src/quirks/index.ts
6051
- var import_build_utils13 = require("@vercel/build-utils");
6202
+ var import_build_utils14 = require("@vercel/build-utils");
6052
6203
  var import_python_analysis8 = require("@vercel/python-analysis");
6053
6204
 
6054
6205
  // src/quirks/matplotlib.ts
@@ -6062,9 +6213,9 @@ var matplotlibQuirk = {
6062
6213
  };
6063
6214
 
6064
6215
  // 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");
6216
+ var import_fs10 = __toESM(require("fs"));
6217
+ var import_path11 = require("path");
6218
+ var import_build_utils12 = require("@vercel/build-utils");
6068
6219
  var LAMBDA_ROOT = "/var/task";
6069
6220
  var CONFIG_CANDIDATES = [
6070
6221
  "litellm_config.yaml",
@@ -6074,9 +6225,9 @@ var CONFIG_CANDIDATES = [
6074
6225
  ];
6075
6226
  async function findConfigFile(workPath) {
6076
6227
  for (const name of CONFIG_CANDIDATES) {
6077
- const candidate = (0, import_path10.join)(workPath, name);
6228
+ const candidate = (0, import_path11.join)(workPath, name);
6078
6229
  try {
6079
- await import_fs9.default.promises.access(candidate);
6230
+ await import_fs10.default.promises.access(candidate);
6080
6231
  return name;
6081
6232
  } catch {
6082
6233
  }
@@ -6091,32 +6242,32 @@ var litellmQuirk = {
6091
6242
  const env = {};
6092
6243
  const sitePackagesDirs = await getVenvSitePackagesDirs(ctx.venvPath);
6093
6244
  for (const sitePackages of sitePackagesDirs) {
6094
- const schemaPath = (0, import_path10.join)(
6245
+ const schemaPath = (0, import_path11.join)(
6095
6246
  sitePackages,
6096
6247
  "litellm",
6097
6248
  "proxy",
6098
6249
  "schema.prisma"
6099
6250
  );
6100
6251
  try {
6101
- await import_fs9.default.promises.access(schemaPath);
6102
- (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}`);
6103
6254
  buildEnv.PRISMA_SCHEMA_PATH = schemaPath;
6104
6255
  break;
6105
6256
  } catch {
6106
6257
  }
6107
6258
  }
6108
6259
  if (!buildEnv.PRISMA_SCHEMA_PATH) {
6109
- (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");
6110
6261
  }
6111
6262
  if (!process.env.CONFIG_FILE_PATH) {
6112
6263
  const configName = await findConfigFile(ctx.workPath);
6113
6264
  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);
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);
6117
6268
  }
6118
6269
  } else {
6119
- (0, import_build_utils11.debug)(
6270
+ (0, import_build_utils12.debug)(
6120
6271
  `LiteLLM quirk: CONFIG_FILE_PATH already set to ${process.env.CONFIG_FILE_PATH}`
6121
6272
  );
6122
6273
  }
@@ -6125,10 +6276,10 @@ var litellmQuirk = {
6125
6276
  };
6126
6277
 
6127
6278
  // 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");
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");
6132
6283
  var import_python_analysis7 = require("@vercel/python-analysis");
6133
6284
  function execErrorMessage(err) {
6134
6285
  if (err != null && typeof err === "object" && "stderr" in err) {
@@ -6166,22 +6317,22 @@ model DummyModel {
6166
6317
  async function findUserSchema(workPath) {
6167
6318
  const envPath = process.env.PRISMA_SCHEMA_PATH;
6168
6319
  if (envPath) {
6169
- 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);
6170
6321
  try {
6171
- await import_fs10.default.promises.access(resolved);
6322
+ await import_fs11.default.promises.access(resolved);
6172
6323
  return resolved;
6173
6324
  } catch {
6174
- (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}`);
6175
6326
  return null;
6176
6327
  }
6177
6328
  }
6178
6329
  const candidates = [
6179
- (0, import_path11.join)(workPath, "schema.prisma"),
6180
- (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")
6181
6332
  ];
6182
6333
  for (const candidate of candidates) {
6183
6334
  try {
6184
- await import_fs10.default.promises.access(candidate);
6335
+ await import_fs11.default.promises.access(candidate);
6185
6336
  return candidate;
6186
6337
  } catch {
6187
6338
  }
@@ -6192,32 +6343,32 @@ async function collectFiles(dir, base) {
6192
6343
  const result = [];
6193
6344
  let entries;
6194
6345
  try {
6195
- entries = await import_fs10.default.promises.readdir(dir, { withFileTypes: true });
6346
+ entries = await import_fs11.default.promises.readdir(dir, { withFileTypes: true });
6196
6347
  } catch {
6197
6348
  return result;
6198
6349
  }
6199
6350
  for (const entry of entries) {
6200
6351
  if (entry.name === "__pycache__")
6201
6352
  continue;
6202
- const full = (0, import_path11.join)(dir, entry.name);
6353
+ const full = (0, import_path12.join)(dir, entry.name);
6203
6354
  if (entry.isDirectory()) {
6204
6355
  result.push(...await collectFiles(full, base));
6205
6356
  } else {
6206
- result.push((0, import_path11.relative)(base, full));
6357
+ result.push((0, import_path12.relative)(base, full));
6207
6358
  }
6208
6359
  }
6209
6360
  return result;
6210
6361
  }
6211
6362
  async function cleanCacheArtifacts(cacheDir, extras = []) {
6212
6363
  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"),
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"),
6216
6367
  ...extras
6217
6368
  ];
6218
6369
  for (const p of paths) {
6219
6370
  try {
6220
- await import_fs10.default.promises.rm(p, { recursive: true, force: true });
6371
+ await import_fs11.default.promises.rm(p, { recursive: true, force: true });
6221
6372
  } catch (err) {
6222
6373
  console.warn(
6223
6374
  `could not clean up ${p}: ${err instanceof Error ? err.message : String(err)}`
@@ -6227,7 +6378,7 @@ async function cleanCacheArtifacts(cacheDir, extras = []) {
6227
6378
  }
6228
6379
  async function isClientGenerated(pythonPath, env) {
6229
6380
  try {
6230
- await (0, import_execa4.default)(pythonPath, ["-c", "import prisma.client"], {
6381
+ await (0, import_execa5.default)(pythonPath, ["-c", "import prisma.client"], {
6231
6382
  env,
6232
6383
  stdio: "pipe"
6233
6384
  });
@@ -6241,7 +6392,7 @@ var prismaQuirk = {
6241
6392
  async run(ctx) {
6242
6393
  const { venvPath, pythonEnv, workPath } = ctx;
6243
6394
  const pythonPath = getVenvPythonBin(venvPath);
6244
- const runtimeCacheDir = (0, import_path11.join)(
6395
+ const runtimeCacheDir = (0, import_path12.join)(
6245
6396
  LAMBDA_ROOT2,
6246
6397
  resolveVendorDir(),
6247
6398
  "prisma",
@@ -6251,7 +6402,7 @@ var prismaQuirk = {
6251
6402
  let sitePackages;
6252
6403
  for (const dir of sitePackagesDirs) {
6253
6404
  try {
6254
- 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"));
6255
6406
  sitePackages = dir;
6256
6407
  break;
6257
6408
  } catch {
@@ -6263,21 +6414,21 @@ var prismaQuirk = {
6263
6414
  );
6264
6415
  return {};
6265
6416
  }
6266
- const cacheDir = (0, import_path11.join)(sitePackages, "prisma", "__bincache__");
6267
- 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 });
6268
6419
  const generateEnv = {
6269
6420
  ...pythonEnv,
6270
6421
  PRISMA_BINARY_CACHE_DIR: cacheDir
6271
6422
  };
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(
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(
6275
6426
  dummySchemaPath,
6276
6427
  buildDummySchema(generatedDir)
6277
6428
  );
6278
- (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}`);
6279
6430
  try {
6280
- const dummyResult = await (0, import_execa4.default)(
6431
+ const dummyResult = await (0, import_execa5.default)(
6281
6432
  pythonPath,
6282
6433
  ["-m", "prisma", "generate", `--schema=${dummySchemaPath}`],
6283
6434
  {
@@ -6287,11 +6438,11 @@ var prismaQuirk = {
6287
6438
  }
6288
6439
  );
6289
6440
  if (dummyResult.stdout)
6290
- (0, import_build_utils12.debug)(`prisma generate (dummy) stdout: ${dummyResult.stdout}`);
6441
+ (0, import_build_utils13.debug)(`prisma generate (dummy) stdout: ${dummyResult.stdout}`);
6291
6442
  if (dummyResult.stderr)
6292
- (0, import_build_utils12.debug)(`prisma generate (dummy) stderr: ${dummyResult.stderr}`);
6443
+ (0, import_build_utils13.debug)(`prisma generate (dummy) stderr: ${dummyResult.stderr}`);
6293
6444
  } catch (err) {
6294
- throw new import_build_utils12.NowBuildError({
6445
+ throw new import_build_utils13.NowBuildError({
6295
6446
  code: "PRISMA_GENERATE_FAILED",
6296
6447
  message: `Prisma engine download failed during \`prisma generate\`. Check that your prisma version is compatible with this Python version.
6297
6448
  ` + execErrorMessage(err)
@@ -6299,47 +6450,47 @@ var prismaQuirk = {
6299
6450
  }
6300
6451
  const srcBinaryPrefix = `query-engine-${getLambdaBinaryTarget()}`;
6301
6452
  const runtimeName = `prisma-query-engine-rhel-openssl-${RUNTIME_OPENSSL_VERSION}.x`;
6302
- const nodeModulesDir = (0, import_path11.join)(cacheDir, "node_modules", "prisma");
6453
+ const nodeModulesDir = (0, import_path12.join)(cacheDir, "node_modules", "prisma");
6303
6454
  let engineCopied = false;
6304
6455
  try {
6305
- const entries = await import_fs10.default.promises.readdir(nodeModulesDir);
6456
+ const entries = await import_fs11.default.promises.readdir(nodeModulesDir);
6306
6457
  for (const entry of entries) {
6307
6458
  if (!entry.startsWith(srcBinaryPrefix))
6308
6459
  continue;
6309
- const srcPath = (0, import_path11.join)(nodeModulesDir, entry);
6310
- 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);
6311
6462
  try {
6312
- await import_fs10.default.promises.access(destPath);
6313
- (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`);
6314
6465
  } catch {
6315
- (0, import_build_utils12.debug)(`Engine binary: copying ${entry} -> ${runtimeName}`);
6316
- 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);
6317
6468
  }
6318
6469
  engineCopied = true;
6319
6470
  }
6320
6471
  } catch (err) {
6321
- throw new import_build_utils12.NowBuildError({
6472
+ throw new import_build_utils13.NowBuildError({
6322
6473
  code: "PRISMA_ENGINE_NOT_FOUND",
6323
6474
  message: `could not read Prisma engine directory "${nodeModulesDir}". This may indicate an incompatible prisma version.
6324
6475
  ` + (err instanceof Error ? err.message : String(err))
6325
6476
  });
6326
6477
  }
6327
6478
  if (!engineCopied) {
6328
- throw new import_build_utils12.NowBuildError({
6479
+ throw new import_build_utils13.NowBuildError({
6329
6480
  code: "PRISMA_ENGINE_NOT_FOUND",
6330
6481
  message: `could not find engine binary matching "${srcBinaryPrefix}*" in "${nodeModulesDir}". This may indicate an incompatible prisma version or an unsupported platform (${process.arch}).`
6331
6482
  });
6332
6483
  }
6333
- const shimPath = (0, import_path11.join)(cacheDir, "openssl");
6334
- await import_fs10.default.promises.writeFile(
6484
+ const shimPath = (0, import_path12.join)(cacheDir, "openssl");
6485
+ await import_fs11.default.promises.writeFile(
6335
6486
  shimPath,
6336
6487
  `#!/bin/sh
6337
6488
  echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIME_OPENSSL_VERSION}.0)"
6338
6489
  `
6339
6490
  );
6340
- await import_fs10.default.promises.chmod(shimPath, 493);
6491
+ await import_fs11.default.promises.chmod(shimPath, 493);
6341
6492
  for (const p of [generatedDir, dummySchemaPath]) {
6342
- await import_fs10.default.promises.rm(p, { recursive: true, force: true });
6493
+ await import_fs11.default.promises.rm(p, { recursive: true, force: true });
6343
6494
  }
6344
6495
  await cleanCacheArtifacts(cacheDir);
6345
6496
  const generateMode = (process.env.VERCEL_PRISMA_GENERATE_CLIENT ?? "auto").toLowerCase();
@@ -6352,16 +6503,16 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
6352
6503
  pythonEnv
6353
6504
  );
6354
6505
  if (clientAlreadyGenerated) {
6355
- (0, import_build_utils12.debug)(
6506
+ (0, import_build_utils13.debug)(
6356
6507
  "Prisma quirk: client already generated, skipping user schema generate"
6357
6508
  );
6358
6509
  shouldGenerate = false;
6359
6510
  }
6360
6511
  }
6361
6512
  if (shouldGenerate) {
6362
- (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}`);
6363
6514
  try {
6364
- const userResult = await (0, import_execa4.default)(
6515
+ const userResult = await (0, import_execa5.default)(
6365
6516
  pythonPath,
6366
6517
  ["-m", "prisma", "generate", `--schema=${userSchema}`],
6367
6518
  {
@@ -6371,11 +6522,11 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
6371
6522
  }
6372
6523
  );
6373
6524
  if (userResult.stdout)
6374
- (0, import_build_utils12.debug)(`prisma generate stdout: ${userResult.stdout}`);
6525
+ (0, import_build_utils13.debug)(`prisma generate stdout: ${userResult.stdout}`);
6375
6526
  if (userResult.stderr)
6376
- (0, import_build_utils12.debug)(`prisma generate stderr: ${userResult.stderr}`);
6527
+ (0, import_build_utils13.debug)(`prisma generate stderr: ${userResult.stderr}`);
6377
6528
  } catch (err) {
6378
- throw new import_build_utils12.NowBuildError({
6529
+ throw new import_build_utils13.NowBuildError({
6379
6530
  code: "PRISMA_GENERATE_FAILED",
6380
6531
  message: `\`prisma generate\` failed for schema "${userSchema}".
6381
6532
  ` + execErrorMessage(err)
@@ -6386,12 +6537,12 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
6386
6537
  }
6387
6538
  try {
6388
6539
  const allFiles = await collectFiles(
6389
- (0, import_path11.join)(sitePackages, "prisma"),
6540
+ (0, import_path12.join)(sitePackages, "prisma"),
6390
6541
  sitePackages
6391
6542
  );
6392
6543
  const count = await (0, import_python_analysis7.extendDistRecord)(sitePackages, "prisma", allFiles);
6393
6544
  if (count > 0) {
6394
- (0, import_build_utils12.debug)(`Appended ${count} entries to prisma RECORD`);
6545
+ (0, import_build_utils13.debug)(`Appended ${count} entries to prisma RECORD`);
6395
6546
  }
6396
6547
  } catch (err) {
6397
6548
  console.warn(
@@ -6485,13 +6636,13 @@ async function runQuirks(ctx) {
6485
6636
  (0, import_python_analysis8.normalizePackageName)(quirk.dependency)
6486
6637
  );
6487
6638
  if (!installed) {
6488
- (0, import_build_utils13.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
6639
+ (0, import_build_utils14.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
6489
6640
  }
6490
6641
  return installed;
6491
6642
  });
6492
6643
  const sorted = toposortQuirks(activated);
6493
6644
  for (const quirk of sorted) {
6494
- (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`);
6495
6646
  const result = await quirk.run(ctx);
6496
6647
  if (result.env) {
6497
6648
  Object.assign(mergedEnv, result.env);
@@ -6512,14 +6663,14 @@ async function runQuirks(ctx) {
6512
6663
  }
6513
6664
 
6514
6665
  // 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");
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");
6521
6672
  async function getDjangoSettings(projectDir, env) {
6522
- const { stdout } = await (0, import_execa5.default)("python", ["-c", script], {
6673
+ const { stdout } = await (0, import_execa6.default)("python", ["-c", script2], {
6523
6674
  env,
6524
6675
  cwd: projectDir
6525
6676
  });
@@ -6545,21 +6696,21 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6545
6696
  const installedApps = djangoSettings["INSTALLED_APPS"] ?? [];
6546
6697
  const staticfilesDirs = djangoSettings["STATICFILES_DIRS"] ?? [];
6547
6698
  const staticSourceDirs = [
6548
- ...installedApps.map((app) => (0, import_path12.join)(workPath, ...app.split("."), "static")),
6699
+ ...installedApps.map((app) => (0, import_path13.join)(workPath, ...app.split("."), "static")),
6549
6700
  // TODO: Deal with optional prefixes in STATICFILES_DIRS.
6550
6701
  ...staticfilesDirs.map((d) => Array.isArray(d) ? d[1] : d)
6551
- ].filter((d) => import_fs11.default.existsSync(d));
6702
+ ].filter((d) => import_fs12.default.existsSync(d));
6552
6703
  if (storageBackend.startsWith("storages.backends.")) {
6553
6704
  console.log(
6554
6705
  "django-storages detected \u2014 running collectstatic with original settings"
6555
6706
  );
6556
- await (0, import_execa5.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6707
+ await (0, import_execa6.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6557
6708
  env: { ...env, DJANGO_SETTINGS_MODULE: settingsModule },
6558
6709
  cwd: workPath
6559
6710
  });
6560
6711
  return {
6561
6712
  staticSourceDirs,
6562
- staticRoot: staticRoot ? (0, import_path12.resolve)(workPath, staticRoot) : null,
6713
+ staticRoot: staticRoot ? (0, import_path13.resolve)(workPath, staticRoot) : null,
6563
6714
  cdnOutputDir: null,
6564
6715
  manifestRelPath: null
6565
6716
  };
@@ -6571,9 +6722,9 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6571
6722
  return null;
6572
6723
  }
6573
6724
  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");
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");
6577
6728
  const shimLines = [
6578
6729
  `from ${settingsModule} import *`,
6579
6730
  `STATIC_ROOT = ${JSON.stringify(staticOutputDir)}`
@@ -6581,10 +6732,10 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6581
6732
  if (whitenoiseUseFinders) {
6582
6733
  shimLines.push(`WHITENOISE_USE_FINDERS = False`);
6583
6734
  }
6584
- await import_fs11.default.promises.writeFile(shimPath, shimLines.join("\n") + "\n");
6735
+ await import_fs12.default.promises.writeFile(shimPath, shimLines.join("\n") + "\n");
6585
6736
  try {
6586
6737
  console.log("Running collectstatic...");
6587
- await (0, import_execa5.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6738
+ await (0, import_execa6.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
6588
6739
  env: {
6589
6740
  ...env,
6590
6741
  DJANGO_SETTINGS_MODULE: "_vercel_collectstatic_settings"
@@ -6592,7 +6743,7 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6592
6743
  cwd: workPath
6593
6744
  });
6594
6745
  } finally {
6595
- await import_fs11.default.promises.unlink(shimPath).catch(() => {
6746
+ await import_fs12.default.promises.unlink(shimPath).catch(() => {
6596
6747
  });
6597
6748
  }
6598
6749
  const MANIFEST_STORAGE_BACKENDS = [
@@ -6601,17 +6752,17 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6601
6752
  ];
6602
6753
  let manifestRelPath = null;
6603
6754
  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`);
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`);
6611
6762
  }
6612
6763
  return {
6613
6764
  staticSourceDirs,
6614
- staticRoot: staticRoot ? (0, import_path12.resolve)(workPath, staticRoot) : null,
6765
+ staticRoot: staticRoot ? (0, import_path13.resolve)(workPath, staticRoot) : null,
6615
6766
  cdnOutputDir: outputStaticDir,
6616
6767
  manifestRelPath
6617
6768
  };
@@ -6619,7 +6770,7 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
6619
6770
 
6620
6771
  // src/index.ts
6621
6772
  var import_python_analysis9 = require("@vercel/python-analysis");
6622
- var writeFile = import_fs12.default.promises.writeFile;
6773
+ var writeFile = import_fs13.default.promises.writeFile;
6623
6774
  var version = -1;
6624
6775
  async function runFrameworkHook(framework, ctx) {
6625
6776
  const hook = framework ? frameworkHooks[framework] : void 0;
@@ -6634,7 +6785,7 @@ var frameworkHooks = {
6634
6785
  detected
6635
6786
  }) => {
6636
6787
  if (detected?.baseDir === void 0) {
6637
- (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");
6638
6789
  return;
6639
6790
  }
6640
6791
  let settingsResult;
@@ -6648,13 +6799,13 @@ Hint: activate a venv or run with \`uv run vercel dev\``;
6648
6799
  } else {
6649
6800
  detail = err?.stderr || err?.message || String(err);
6650
6801
  }
6651
- throw new import_build_utils15.NowBuildError({
6802
+ throw new import_build_utils16.NowBuildError({
6652
6803
  code: "DJANGO_SETTINGS_FAILED",
6653
6804
  message: `Failed to read Django application settings from ${projectDir}/manage.py:
6654
6805
  ${detail}`
6655
6806
  });
6656
6807
  }
6657
- (0, import_build_utils15.debug)(`Django settings: ${JSON.stringify(settingsResult)}`);
6808
+ (0, import_build_utils16.debug)(`Django settings: ${JSON.stringify(settingsResult)}`);
6658
6809
  const { djangoSettings, settingsModule, djangoVersion } = settingsResult;
6659
6810
  if (djangoVersion) {
6660
6811
  console.log(`Django ${djangoVersion.join(".")} detected`);
@@ -6667,7 +6818,7 @@ ${detail}`
6667
6818
  const variableName = parts.at(-1);
6668
6819
  const rel = `${parts.slice(0, -1).join("/")}.py`;
6669
6820
  const ep = baseDir ? `${baseDir}/${rel}` : rel;
6670
- (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})`);
6671
6822
  resolvedEntrypoint = { entrypoint: ep, variableName };
6672
6823
  } else {
6673
6824
  const wsgiApp = djangoSettings["WSGI_APPLICATION"];
@@ -6676,7 +6827,7 @@ ${detail}`
6676
6827
  const variableName = parts.at(-1);
6677
6828
  const rel = `${parts.slice(0, -1).join("/")}.py`;
6678
6829
  const ep = baseDir ? `${baseDir}/${rel}` : rel;
6679
- (0, import_build_utils15.debug)(
6830
+ (0, import_build_utils16.debug)(
6680
6831
  `Django hook: WSGI entrypoint: ${ep} (variable: ${variableName})`
6681
6832
  );
6682
6833
  resolvedEntrypoint = { entrypoint: ep, variableName };
@@ -6684,7 +6835,7 @@ ${detail}`
6684
6835
  }
6685
6836
  let djangoStatic = null;
6686
6837
  if (workPath && venvPath) {
6687
- const outputStaticDir = (0, import_path13.join)(workPath, ".vercel", "output", "static");
6838
+ const outputStaticDir = (0, import_path14.join)(workPath, ".vercel", "output", "static");
6688
6839
  djangoStatic = await runDjangoCollectStatic(
6689
6840
  venvPath,
6690
6841
  workPath,
@@ -6704,14 +6855,14 @@ async function downloadFilesInWorkPath({
6704
6855
  files,
6705
6856
  meta = {}
6706
6857
  }) {
6707
- (0, import_build_utils15.debug)("Downloading user files...");
6708
- 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);
6709
6860
  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);
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);
6715
6866
  workPath = destCache;
6716
6867
  }
6717
6868
  return workPath;
@@ -6727,13 +6878,13 @@ var build = async ({
6727
6878
  service
6728
6879
  }) => {
6729
6880
  let entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
6730
- const builderSpan = parentSpan ?? new import_build_utils15.Span({ name: "vc.builder" });
6881
+ const builderSpan = parentSpan ?? new import_build_utils16.Span({ name: "vc.builder" });
6731
6882
  const framework = config?.framework;
6732
6883
  const shouldInstallVercelWorkers = config?.hasWorkerServices === true;
6733
6884
  let spawnEnv;
6734
6885
  let projectInstallCommand;
6735
6886
  let hasCustomCommand = false;
6736
- (0, import_build_utils15.debug)(`workPath: ${workPath}`);
6887
+ (0, import_build_utils16.debug)(`workPath: ${workPath}`);
6737
6888
  workPath = await downloadFilesInWorkPath({
6738
6889
  workPath,
6739
6890
  files: originalFiles,
@@ -6742,7 +6893,7 @@ var build = async ({
6742
6893
  });
6743
6894
  try {
6744
6895
  if (meta.isDev) {
6745
- const setupCfg = (0, import_path13.join)(workPath, "setup.cfg");
6896
+ const setupCfg = (0, import_path14.join)(workPath, "setup.cfg");
6746
6897
  await writeFile(setupCfg, "[install]\nprefix=\n");
6747
6898
  }
6748
6899
  } catch (err) {
@@ -6765,8 +6916,8 @@ var build = async ({
6765
6916
  if (detected?.error && detected?.baseDir === void 0) {
6766
6917
  throw detected?.error;
6767
6918
  }
6768
- const entryDirectory = detected?.baseDir ?? (entrypoint ? (0, import_path13.dirname)(entrypoint) : ".");
6769
- 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);
6770
6921
  const rootDir = repoRootPath ?? workPath;
6771
6922
  const pythonPackage = await builderSpan.child("vc.builder.python.discover").trace(
6772
6923
  () => discoverPackage({
@@ -6796,12 +6947,26 @@ var build = async ({
6796
6947
  `
6797
6948
  );
6798
6949
  }
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
6950
  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);
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);
6803
6968
  if (hasCachedVenv || hasCachedUv) {
6804
- (0, import_build_utils15.debug)(
6969
+ (0, import_build_utils16.debug)(
6805
6970
  `Build cache detected: venv=${hasCachedVenv}, uv-cache=${hasCachedUv}`
6806
6971
  );
6807
6972
  }
@@ -6809,17 +6974,18 @@ var build = async ({
6809
6974
  await ensureVenv({
6810
6975
  pythonVersion,
6811
6976
  venvPath,
6977
+ uvPath: uv.getPath(),
6812
6978
  uvCacheDir
6813
6979
  });
6814
6980
  });
6815
- if ((0, import_build_utils15.isPythonFramework)(framework)) {
6981
+ if ((0, import_build_utils16.isPythonFramework)(framework)) {
6816
6982
  const {
6817
6983
  cliType,
6818
6984
  lockfileVersion,
6819
6985
  packageJsonPackageManager,
6820
6986
  turboSupportsCorepackHome
6821
- } = await (0, import_build_utils15.scanParentDirs)(workPath, true);
6822
- spawnEnv = (0, import_build_utils15.getEnvForPackageManager)({
6987
+ } = await (0, import_build_utils16.scanParentDirs)(workPath, true);
6988
+ spawnEnv = (0, import_build_utils16.getEnvForPackageManager)({
6823
6989
  cliType,
6824
6990
  lockfileVersion,
6825
6991
  packageJsonPackageManager,
@@ -6841,38 +7007,25 @@ var build = async ({
6841
7007
  const pythonEnv = createVenvEnv(venvPath, baseEnv, uvCacheDir);
6842
7008
  pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
6843
7009
  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
7010
  let uvLockPath = null;
6859
7011
  let uvProjectDir = null;
6860
7012
  let projectName;
6861
- await builderSpan.child(import_build_utils15.BUILDER_INSTALLER_STEP, {
7013
+ await builderSpan.child(import_build_utils16.BUILDER_INSTALLER_STEP, {
6862
7014
  installCommand: projectInstallCommand || void 0
6863
7015
  }).trace(async () => {
6864
7016
  if (projectInstallCommand) {
6865
- await import_fs12.default.promises.rm(venvPath, { recursive: true, force: true });
7017
+ await import_fs13.default.promises.rm(venvPath, { recursive: true, force: true });
6866
7018
  await ensureVenv({
6867
7019
  pythonVersion,
6868
7020
  venvPath,
7021
+ uvPath: uv.getPath(),
6869
7022
  uvCacheDir,
6870
7023
  quiet: true
6871
7024
  });
6872
7025
  console.log(
6873
7026
  `Running "install" command: \`${projectInstallCommand}\`...`
6874
7027
  );
6875
- await (0, import_build_utils15.execCommand)(projectInstallCommand, {
7028
+ await (0, import_build_utils16.execCommand)(projectInstallCommand, {
6876
7029
  env: pythonEnv,
6877
7030
  cwd: workPath
6878
7031
  });
@@ -6893,7 +7046,7 @@ var build = async ({
6893
7046
  }
6894
7047
  if (!assumeDepsInstalled) {
6895
7048
  const lockCacheKey = service?.name ? `uv.lock.${service.name}` : "uv.lock";
6896
- const cachedLockPath = (0, import_path13.join)(uvCacheDir, lockCacheKey);
7049
+ const cachedLockPath = (0, import_path14.join)(uvCacheDir, lockCacheKey);
6897
7050
  const { projectDir, lockPath, lockFileProvidedByUser } = await ensureUvProject({
6898
7051
  workPath,
6899
7052
  rootDir,
@@ -6913,21 +7066,21 @@ var build = async ({
6913
7066
  frozen: lockFileProvidedByUser,
6914
7067
  locked: !lockFileProvidedByUser
6915
7068
  });
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);
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);
6919
7072
  }
6920
7073
  }
6921
7074
  });
6922
- if ((0, import_build_utils15.isPythonFramework)(framework)) {
7075
+ if ((0, import_build_utils16.isPythonFramework)(framework)) {
6923
7076
  const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
6924
7077
  config?.buildCommand;
6925
- await builderSpan.child(import_build_utils15.BUILDER_COMPILE_STEP, {
7078
+ await builderSpan.child(import_build_utils16.BUILDER_COMPILE_STEP, {
6926
7079
  buildCommand: projectBuildCommand || void 0
6927
7080
  }).trace(async () => {
6928
7081
  if (projectBuildCommand) {
6929
7082
  console.log(`Running "${projectBuildCommand}"`);
6930
- await (0, import_build_utils15.execCommand)(projectBuildCommand, {
7083
+ await (0, import_build_utils16.execCommand)(projectBuildCommand, {
6931
7084
  env: pythonEnv,
6932
7085
  cwd: workPath
6933
7086
  });
@@ -6942,7 +7095,7 @@ var build = async ({
6942
7095
  }
6943
7096
  const hookResult = await runFrameworkHook(framework, {
6944
7097
  pythonEnv,
6945
- projectDir: (0, import_path13.join)(workPath, entryDirectory),
7098
+ projectDir: (0, import_path14.join)(workPath, entryDirectory),
6946
7099
  workPath,
6947
7100
  venvPath,
6948
7101
  entrypoint,
@@ -6954,25 +7107,25 @@ var build = async ({
6954
7107
  }
6955
7108
  entrypoint = resolved?.entrypoint;
6956
7109
  if (!entrypoint) {
6957
- throw new import_build_utils15.NowBuildError({
7110
+ throw new import_build_utils16.NowBuildError({
6958
7111
  code: "PYTHON_ENTRYPOINT_NOT_FOUND",
6959
7112
  message: "No Python entrypoint could be detected. Please specify an entrypoint file."
6960
7113
  });
6961
7114
  }
6962
7115
  const djangoStatic = hookResult?.djangoStatic ?? null;
6963
7116
  const runtimeDep = baseEnv.VERCEL_RUNTIME_PYTHON || `vercel-runtime==${VERCEL_RUNTIME_VERSION}`;
6964
- (0, import_build_utils15.debug)(`Installing ${runtimeDep}`);
7117
+ (0, import_build_utils16.debug)(`Installing ${runtimeDep}`);
6965
7118
  await uv.pip({
6966
7119
  venvPath,
6967
- projectDir: (0, import_path13.join)(workPath, entryDirectory),
7120
+ projectDir: (0, import_path14.join)(workPath, entryDirectory),
6968
7121
  args: ["install", runtimeDep]
6969
7122
  });
6970
7123
  if (shouldInstallVercelWorkers) {
6971
7124
  const workersDep = baseEnv.VERCEL_WORKERS_PYTHON || `vercel-workers==${VERCEL_WORKERS_VERSION}`;
6972
- (0, import_build_utils15.debug)(`Installing ${workersDep}`);
7125
+ (0, import_build_utils16.debug)(`Installing ${workersDep}`);
6973
7126
  await uv.pip({
6974
7127
  venvPath,
6975
- projectDir: (0, import_path13.join)(workPath, entryDirectory),
7128
+ projectDir: (0, import_path14.join)(workPath, entryDirectory),
6976
7129
  args: ["install", workersDep]
6977
7130
  });
6978
7131
  }
@@ -6980,14 +7133,14 @@ var build = async ({
6980
7133
  if (quirksResult.buildEnv) {
6981
7134
  Object.assign(pythonEnv, quirksResult.buildEnv);
6982
7135
  }
6983
- (0, import_build_utils15.debug)("Entrypoint is", entrypoint);
7136
+ (0, import_build_utils16.debug)("Entrypoint is", entrypoint);
6984
7137
  const moduleName = entrypoint.replace(/\//g, ".").replace(/\.py$/i, "");
6985
7138
  if (handlerFunction) {
6986
- const entrypointPath = (0, import_path13.join)(workPath, entrypoint);
6987
- 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");
6988
7141
  const found = await (0, import_python_analysis9.containsTopLevelCallable)(source, handlerFunction);
6989
7142
  if (!found) {
6990
- throw new import_build_utils15.NowBuildError({
7143
+ throw new import_build_utils16.NowBuildError({
6991
7144
  code: "PYTHON_HANDLER_NOT_FOUND",
6992
7145
  message: `Handler function "${handlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
6993
7146
  });
@@ -6996,9 +7149,23 @@ var build = async ({
6996
7149
  const vendorDir = resolveVendorDir();
6997
7150
  const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
6998
7151
  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}",` : "";
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
+ }
7002
7169
  const variableName = resolved?.variableName ?? "";
7003
7170
  const runtimeTrampoline = `
7004
7171
  import importlib
@@ -7014,7 +7181,7 @@ os.environ.update({
7014
7181
  "__VC_HANDLER_ENTRYPOINT": "${entrypointWithSuffix}",
7015
7182
  "__VC_HANDLER_ENTRYPOINT_ABS": os.path.join(_here, "${entrypointWithSuffix}"),
7016
7183
  "__VC_HANDLER_VENDOR_DIR": "${vendorDir}",
7017
- "__VC_HANDLER_VARIABLE_NAME": "${variableName}",${handlerFuncEnvLine}
7184
+ "__VC_HANDLER_VARIABLE_NAME": "${variableName}",${cronEnvLine}
7018
7185
  })
7019
7186
 
7020
7187
  _vendor_rel = '${vendorDir}'
@@ -7067,10 +7234,10 @@ from vercel_runtime.vc_init import vc_handler
7067
7234
  cwd: workPath,
7068
7235
  ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
7069
7236
  };
7070
- const files = await (0, import_build_utils15.glob)("**", globOptions);
7237
+ const files = await (0, import_build_utils16.glob)("**", globOptions);
7071
7238
  if (djangoStatic?.manifestRelPath) {
7072
- files[djangoStatic.manifestRelPath] = new import_build_utils15.FileFsRef({
7073
- 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)
7074
7241
  });
7075
7242
  }
7076
7243
  const depExternalizer = new PythonDependencyExternalizer({
@@ -7106,12 +7273,12 @@ from vercel_runtime.vc_init import vc_handler
7106
7273
  }
7107
7274
  });
7108
7275
  const handlerPyFilename = "vc__handler__python";
7109
- files[`${handlerPyFilename}.py`] = new import_build_utils15.FileBlob({ data: runtimeTrampoline });
7276
+ files[`${handlerPyFilename}.py`] = new import_build_utils16.FileBlob({ data: runtimeTrampoline });
7110
7277
  if (config.framework === "fasthtml") {
7111
7278
  const { SESSKEY = "" } = process.env;
7112
- files[".sesskey"] = new import_build_utils15.FileBlob({ data: `"${SESSKEY}"` });
7279
+ files[".sesskey"] = new import_build_utils16.FileBlob({ data: `"${SESSKEY}"` });
7113
7280
  }
7114
- const output = new import_build_utils15.Lambda({
7281
+ const output = new import_build_utils16.Lambda({
7115
7282
  files,
7116
7283
  handler: `${handlerPyFilename}.vc_handler`,
7117
7284
  runtime: pythonVersion.runtime,
@@ -7127,16 +7294,20 @@ from vercel_runtime.vc_init import vc_handler
7127
7294
  uvLockPath
7128
7295
  });
7129
7296
  } catch (err) {
7130
- (0, import_build_utils15.debug)(
7297
+ (0, import_build_utils16.debug)(
7131
7298
  `Failed to write project manifest: ${err instanceof Error ? err.message : String(err)}`
7132
7299
  );
7133
7300
  }
7134
7301
  }
7135
- if (!(0, import_build_utils15.isPythonFramework)(framework)) {
7302
+ if (!(0, import_build_utils16.isPythonFramework)(framework) && !service?.name) {
7136
7303
  return { resultVersion: 3, result: { output } };
7137
7304
  }
7138
7305
  const lambdaPath = service?.name ? `_svc/${service.name}/index` : "index";
7139
- 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
+ ];
7140
7311
  return {
7141
7312
  resultVersion: 2,
7142
7313
  result: {
@@ -7144,10 +7315,8 @@ from vercel_runtime.vc_init import vc_handler
7144
7315
  [lambdaPath]: output,
7145
7316
  ...staticFiles
7146
7317
  },
7147
- routes: [
7148
- { handle: "filesystem" },
7149
- { src: "/(.*)", dest: `/${lambdaPath}` }
7150
- ]
7318
+ routes,
7319
+ crons
7151
7320
  }
7152
7321
  };
7153
7322
  };
@@ -7169,14 +7338,14 @@ var prepareCache = async ({
7169
7338
  }
7170
7339
  } catch {
7171
7340
  }
7172
- 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}/**", {
7173
7342
  cwd: root,
7174
7343
  ignore
7175
7344
  });
7176
7345
  };
7177
7346
  var shouldServe = (opts) => {
7178
7347
  const framework = opts.config.framework;
7179
- if ((0, import_build_utils15.isPythonFramework)(framework)) {
7348
+ if ((0, import_build_utils16.isPythonFramework)(framework)) {
7180
7349
  const requestPath = opts.requestPath.replace(/\/$/, "");
7181
7350
  if (requestPath.startsWith("api") && opts.hasMatched) {
7182
7351
  return false;
@@ -7195,7 +7364,7 @@ var defaultShouldServe = ({
7195
7364
  if (entrypoint === requestPath && hasProp(files, entrypoint)) {
7196
7365
  return true;
7197
7366
  }
7198
- const { dir, name } = (0, import_path13.parse)(entrypoint);
7367
+ const { dir, name } = (0, import_path14.parse)(entrypoint);
7199
7368
  if (name === "index" && dir === requestPath && hasProp(files, entrypoint)) {
7200
7369
  return true;
7201
7370
  }