@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 +463 -294
- package/package.json +4 -4
- package/templates/vc_cron_detect.py +67 -0
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
|
|
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
|
-
|
|
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(
|
|
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
|
|
91
|
+
var fs12 = require("fs");
|
|
92
92
|
function isexe(path, options, cb) {
|
|
93
|
-
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
412
|
-
|
|
413
|
-
|
|
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
|
|
1898
|
+
var fs12;
|
|
1899
1899
|
try {
|
|
1900
|
-
|
|
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 (!
|
|
1912
|
+
if (!fs12)
|
|
1913
1913
|
return false;
|
|
1914
|
-
return (stream instanceof (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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 =
|
|
2682
|
+
const fd = fs12.openSync(path, "r");
|
|
2683
2683
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
2684
|
-
const bytesRead =
|
|
2685
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2695
|
+
fs12.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
|
|
2696
2696
|
resolve3(buffer.subarray(0, bytesRead));
|
|
2697
|
-
|
|
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:
|
|
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 +
|
|
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
|
|
3229
|
-
var
|
|
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.
|
|
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
|
|
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
|
|
5109
|
-
var
|
|
5110
|
-
var
|
|
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
|
|
5116
|
-
var
|
|
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) =>
|
|
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
|
|
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,
|
|
5291
|
+
const absPath = (0, import_path9.join)(workPath, relPath);
|
|
5150
5292
|
if (!await fileExists(absPath))
|
|
5151
5293
|
return null;
|
|
5152
|
-
const content = await
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
5330
|
+
const managePath = (0, import_path9.join)(workPath, "manage.py");
|
|
5189
5331
|
try {
|
|
5190
|
-
const content = await
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
5376
|
-
(0,
|
|
5377
|
-
const tempPyproject = (0,
|
|
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,
|
|
5521
|
+
(0, import_fs9.writeFileSync)(tempPyproject, content, "utf8");
|
|
5380
5522
|
manifestPath = tempPyproject;
|
|
5381
|
-
(0,
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
5600
|
+
(0, import_build_utils11.debug)(`Unknown manifest type: ${manifestType}`);
|
|
5459
5601
|
return;
|
|
5460
5602
|
}
|
|
5461
5603
|
await new Promise((resolve3, reject) => {
|
|
5462
|
-
(0,
|
|
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,
|
|
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,
|
|
5533
|
-
const localRuntimeDir = (0,
|
|
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,
|
|
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,
|
|
5686
|
+
const distInfo = (0, import_path10.join)(
|
|
5545
5687
|
targetDir,
|
|
5546
5688
|
`vercel_runtime-${VERCEL_RUNTIME_VERSION}.dist-info`
|
|
5547
5689
|
);
|
|
5548
|
-
if ((0,
|
|
5549
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
5629
|
-
const localWorkersDir = (0,
|
|
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,
|
|
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,
|
|
5782
|
+
const distInfo = (0, import_path10.join)(
|
|
5641
5783
|
targetDir,
|
|
5642
5784
|
`vercel_workers-${VERCEL_WORKERS_VERSION}.dist-info`
|
|
5643
5785
|
);
|
|
5644
|
-
if ((0,
|
|
5645
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
5734
|
-
(0,
|
|
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,
|
|
5738
|
-
const pkgName = (0,
|
|
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,
|
|
5882
|
+
extraPythonPath = (0, import_path10.dirname)(workPath);
|
|
5741
5883
|
}
|
|
5742
|
-
const entryAbs = (0,
|
|
5743
|
-
const shimPath = (0,
|
|
5744
|
-
const templatePath = (0,
|
|
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,
|
|
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,
|
|
5753
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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}${
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
6043
|
+
(0, import_build_utils11.debug)(
|
|
5902
6044
|
`Multi-service Python runner: ${spawnCommand} ${spawnArgsPrefix.join(" ")}`
|
|
5903
6045
|
);
|
|
5904
6046
|
} else if (venv) {
|
|
5905
|
-
(0,
|
|
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,
|
|
6056
|
+
(0, import_build_utils11.debug)(`Using virtualenv at ${venvRoot}`);
|
|
5915
6057
|
} else {
|
|
5916
|
-
(0,
|
|
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,
|
|
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,
|
|
5983
|
-
const runtimeDir = (0,
|
|
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(
|
|
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,
|
|
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
|
|
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
|
|
6066
|
-
var
|
|
6067
|
-
var
|
|
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,
|
|
6228
|
+
const candidate = (0, import_path11.join)(workPath, name);
|
|
6078
6229
|
try {
|
|
6079
|
-
await
|
|
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,
|
|
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
|
|
6102
|
-
(0,
|
|
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,
|
|
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,
|
|
6115
|
-
buildEnv.CONFIG_FILE_PATH = (0,
|
|
6116
|
-
env.CONFIG_FILE_PATH = (0,
|
|
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,
|
|
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
|
|
6129
|
-
var
|
|
6130
|
-
var
|
|
6131
|
-
var
|
|
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,
|
|
6320
|
+
const resolved = (0, import_path12.isAbsolute)(envPath) ? envPath : (0, import_path12.join)(workPath, envPath);
|
|
6170
6321
|
try {
|
|
6171
|
-
await
|
|
6322
|
+
await import_fs11.default.promises.access(resolved);
|
|
6172
6323
|
return resolved;
|
|
6173
6324
|
} catch {
|
|
6174
|
-
(0,
|
|
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,
|
|
6180
|
-
(0,
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
6214
|
-
(0,
|
|
6215
|
-
(0,
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
6267
|
-
await
|
|
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,
|
|
6273
|
-
const dummySchemaPath = (0,
|
|
6274
|
-
await
|
|
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,
|
|
6429
|
+
(0, import_build_utils13.debug)(`Running prisma generate (dummy) with cache dir: ${cacheDir}`);
|
|
6279
6430
|
try {
|
|
6280
|
-
const dummyResult = await (0,
|
|
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,
|
|
6441
|
+
(0, import_build_utils13.debug)(`prisma generate (dummy) stdout: ${dummyResult.stdout}`);
|
|
6291
6442
|
if (dummyResult.stderr)
|
|
6292
|
-
(0,
|
|
6443
|
+
(0, import_build_utils13.debug)(`prisma generate (dummy) stderr: ${dummyResult.stderr}`);
|
|
6293
6444
|
} catch (err) {
|
|
6294
|
-
throw new
|
|
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,
|
|
6453
|
+
const nodeModulesDir = (0, import_path12.join)(cacheDir, "node_modules", "prisma");
|
|
6303
6454
|
let engineCopied = false;
|
|
6304
6455
|
try {
|
|
6305
|
-
const entries = await
|
|
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,
|
|
6310
|
-
const destPath = (0,
|
|
6460
|
+
const srcPath = (0, import_path12.join)(nodeModulesDir, entry);
|
|
6461
|
+
const destPath = (0, import_path12.join)(cacheDir, runtimeName);
|
|
6311
6462
|
try {
|
|
6312
|
-
await
|
|
6313
|
-
(0,
|
|
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,
|
|
6316
|
-
await
|
|
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
|
|
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
|
|
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,
|
|
6334
|
-
await
|
|
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
|
|
6491
|
+
await import_fs11.default.promises.chmod(shimPath, 493);
|
|
6341
6492
|
for (const p of [generatedDir, dummySchemaPath]) {
|
|
6342
|
-
await
|
|
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,
|
|
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,
|
|
6513
|
+
(0, import_build_utils13.debug)(`Running prisma generate with user schema: ${userSchema}`);
|
|
6363
6514
|
try {
|
|
6364
|
-
const userResult = await (0,
|
|
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,
|
|
6525
|
+
(0, import_build_utils13.debug)(`prisma generate stdout: ${userResult.stdout}`);
|
|
6375
6526
|
if (userResult.stderr)
|
|
6376
|
-
(0,
|
|
6527
|
+
(0, import_build_utils13.debug)(`prisma generate stderr: ${userResult.stderr}`);
|
|
6377
6528
|
} catch (err) {
|
|
6378
|
-
throw new
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
6516
|
-
var
|
|
6517
|
-
var
|
|
6518
|
-
var
|
|
6519
|
-
var
|
|
6520
|
-
var
|
|
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,
|
|
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,
|
|
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) =>
|
|
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,
|
|
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,
|
|
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,
|
|
6575
|
-
await
|
|
6576
|
-
const shimPath = (0,
|
|
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
|
|
6735
|
+
await import_fs12.default.promises.writeFile(shimPath, shimLines.join("\n") + "\n");
|
|
6585
6736
|
try {
|
|
6586
6737
|
console.log("Running collectstatic...");
|
|
6587
|
-
await (0,
|
|
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
|
|
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,
|
|
6605
|
-
const resolvedStaticRoot = (0,
|
|
6606
|
-
const manifestDest = (0,
|
|
6607
|
-
await
|
|
6608
|
-
await
|
|
6609
|
-
manifestRelPath = (0,
|
|
6610
|
-
(0,
|
|
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,
|
|
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 =
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
6708
|
-
let downloadedFiles = await (0,
|
|
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,
|
|
6711
|
-
const cacheKey = (0,
|
|
6712
|
-
const destCache = (0,
|
|
6713
|
-
await (0,
|
|
6714
|
-
downloadedFiles = await (0,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
6769
|
-
const entrypointAbsDir = (0,
|
|
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
|
-
|
|
6802
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
6822
|
-
spawnEnv = (0,
|
|
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(
|
|
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
|
|
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,
|
|
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,
|
|
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 &&
|
|
6917
|
-
await
|
|
6918
|
-
await
|
|
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,
|
|
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(
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
7117
|
+
(0, import_build_utils16.debug)(`Installing ${runtimeDep}`);
|
|
6965
7118
|
await uv.pip({
|
|
6966
7119
|
venvPath,
|
|
6967
|
-
projectDir: (0,
|
|
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,
|
|
7125
|
+
(0, import_build_utils16.debug)(`Installing ${workersDep}`);
|
|
6973
7126
|
await uv.pip({
|
|
6974
7127
|
venvPath,
|
|
6975
|
-
projectDir: (0,
|
|
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,
|
|
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,
|
|
6987
|
-
const source = await
|
|
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
|
|
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,
|
|
7000
|
-
const
|
|
7001
|
-
|
|
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}",${
|
|
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,
|
|
7237
|
+
const files = await (0, import_build_utils16.glob)("**", globOptions);
|
|
7071
7238
|
if (djangoStatic?.manifestRelPath) {
|
|
7072
|
-
files[djangoStatic.manifestRelPath] = new
|
|
7073
|
-
fsPath: (0,
|
|
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
|
|
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
|
|
7279
|
+
files[".sesskey"] = new import_build_utils16.FileBlob({ data: `"${SESSKEY}"` });
|
|
7113
7280
|
}
|
|
7114
|
-
const output = new
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
}
|