@vercel/python 6.55.2 → 6.56.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 +650 -370
- package/package.json +5 -8
package/dist/index.js
CHANGED
|
@@ -5032,12 +5032,29 @@ var import_fs20 = __toESM(require("fs"));
|
|
|
5032
5032
|
var import_path21 = require("path");
|
|
5033
5033
|
|
|
5034
5034
|
// src/package-versions.ts
|
|
5035
|
-
var VERCEL_RUNTIME_VERSION = "0.
|
|
5035
|
+
var VERCEL_RUNTIME_VERSION = "0.19.0";
|
|
5036
5036
|
var VERCEL_WORKERS_VERSION = "0.0.25";
|
|
5037
5037
|
|
|
5038
5038
|
// src/conditional-vendoring.ts
|
|
5039
5039
|
var import_python_analysis = require("@vercel/python-analysis");
|
|
5040
5040
|
var UPSTREAM_DEPENDENCY_ADAPTERS = /* @__PURE__ */ new Map([
|
|
5041
|
+
[
|
|
5042
|
+
"apscheduler",
|
|
5043
|
+
{
|
|
5044
|
+
bundled: "vercel-apscheduler-bundle",
|
|
5045
|
+
unbundled: "vercel-apscheduler",
|
|
5046
|
+
envOverride: "VERCEL_PYTHON_APSCHEDULER_DEPENDENCY",
|
|
5047
|
+
preferUnbundledWhenPresent: ["vercel-queue"],
|
|
5048
|
+
integration: {
|
|
5049
|
+
module: "vercel.integrations.apscheduler",
|
|
5050
|
+
installer: "install_vercel_apscheduler_integration",
|
|
5051
|
+
// APScheduler jobs are declared while the subscriber module imports.
|
|
5052
|
+
// Install first so the adapter can capture those definitions.
|
|
5053
|
+
installBeforeImport: true,
|
|
5054
|
+
subscriberProbe: "is_scheduler_subscriber"
|
|
5055
|
+
}
|
|
5056
|
+
}
|
|
5057
|
+
],
|
|
5041
5058
|
[
|
|
5042
5059
|
"celery",
|
|
5043
5060
|
{
|
|
@@ -5069,31 +5086,26 @@ var UPSTREAM_DEPENDENCY_ADAPTERS = /* @__PURE__ */ new Map([
|
|
|
5069
5086
|
}
|
|
5070
5087
|
]
|
|
5071
5088
|
]);
|
|
5072
|
-
async function
|
|
5073
|
-
pythonPackage
|
|
5089
|
+
async function getQueueAdapterBootstrap({
|
|
5090
|
+
pythonPackage,
|
|
5091
|
+
env,
|
|
5092
|
+
legacyWorkersProject,
|
|
5093
|
+
hasDeclaredSubscribers
|
|
5074
5094
|
}) {
|
|
5075
|
-
const dependencies = await getDirectDependencyNames(pythonPackage);
|
|
5076
|
-
if (!dependencies)
|
|
5077
|
-
return [];
|
|
5078
5095
|
const integrations = [];
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5096
|
+
const injectedPackages = [];
|
|
5097
|
+
const bootstrap = { integrations, injectedPackages };
|
|
5098
|
+
if (legacyWorkersProject || !hasDeclaredSubscribers) {
|
|
5099
|
+
return bootstrap;
|
|
5083
5100
|
}
|
|
5084
|
-
return integrations;
|
|
5085
|
-
}
|
|
5086
|
-
async function getConditionalInjectedPackages({
|
|
5087
|
-
pythonPackage,
|
|
5088
|
-
env
|
|
5089
|
-
}) {
|
|
5090
5101
|
const dependencies = await getDirectDependencyNames(pythonPackage);
|
|
5091
|
-
if (!dependencies)
|
|
5092
|
-
return
|
|
5093
|
-
|
|
5102
|
+
if (!dependencies) {
|
|
5103
|
+
return bootstrap;
|
|
5104
|
+
}
|
|
5094
5105
|
for (const [upstream, adapter] of UPSTREAM_DEPENDENCY_ADAPTERS) {
|
|
5095
5106
|
if (!dependencies.has(upstream))
|
|
5096
5107
|
continue;
|
|
5108
|
+
integrations.push(adapter.integration);
|
|
5097
5109
|
if (dependencies.has(adapter.bundled) || dependencies.has(adapter.unbundled)) {
|
|
5098
5110
|
continue;
|
|
5099
5111
|
}
|
|
@@ -5107,7 +5119,7 @@ async function getConditionalInjectedPackages({
|
|
|
5107
5119
|
allowLocalSource: false
|
|
5108
5120
|
});
|
|
5109
5121
|
}
|
|
5110
|
-
return
|
|
5122
|
+
return bootstrap;
|
|
5111
5123
|
}
|
|
5112
5124
|
async function getDirectDependencyNames(pythonPackage) {
|
|
5113
5125
|
const dependencies = pythonPackage?.manifest?.data?.project?.dependencies;
|
|
@@ -7962,23 +7974,24 @@ function moduleColonFuncToCronPath(serviceName, moduleFunction) {
|
|
|
7962
7974
|
|
|
7963
7975
|
// src/start-dev-server.ts
|
|
7964
7976
|
var import_child_process2 = require("child_process");
|
|
7965
|
-
var
|
|
7966
|
-
var
|
|
7967
|
-
var
|
|
7977
|
+
var import_fs13 = require("fs");
|
|
7978
|
+
var import_path13 = require("path");
|
|
7979
|
+
var import_build_utils15 = require("@vercel/build-utils");
|
|
7968
7980
|
var import_get_port = __toESM(require_get_port());
|
|
7969
7981
|
var import_is_port_reachable = __toESM(require_is_port_reachable());
|
|
7970
7982
|
var import_python_analysis8 = require("@vercel/python-analysis");
|
|
7971
7983
|
|
|
7972
7984
|
// src/subscribers.ts
|
|
7973
|
-
var
|
|
7974
|
-
var
|
|
7985
|
+
var import_path12 = require("path");
|
|
7986
|
+
var import_fs12 = __toESM(require("fs"));
|
|
7975
7987
|
var import_execa6 = __toESM(require_execa());
|
|
7976
|
-
var
|
|
7988
|
+
var import_build_utils14 = require("@vercel/build-utils");
|
|
7977
7989
|
|
|
7978
7990
|
// src/module-entrypoint.ts
|
|
7979
7991
|
var import_path10 = require("path");
|
|
7980
7992
|
var import_fs10 = __toESM(require("fs"));
|
|
7981
7993
|
var MODULE_ATTR_RE = /^([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)*):([A-Za-z_][\w]*)$/;
|
|
7994
|
+
var MODULE_RE = /^[A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)*$/;
|
|
7982
7995
|
function parseModuleEntrypoint(value) {
|
|
7983
7996
|
const match = MODULE_ATTR_RE.exec(value);
|
|
7984
7997
|
if (!match) {
|
|
@@ -7990,11 +8003,21 @@ function parseModuleEntrypoint(value) {
|
|
|
7990
8003
|
filePath: `${match[1].replace(/\./g, "/")}.py`
|
|
7991
8004
|
};
|
|
7992
8005
|
}
|
|
8006
|
+
function parseBareModuleEntrypoint(value) {
|
|
8007
|
+
if (!MODULE_RE.test(value)) {
|
|
8008
|
+
return null;
|
|
8009
|
+
}
|
|
8010
|
+
return {
|
|
8011
|
+
moduleName: value,
|
|
8012
|
+
filePath: `${value.replace(/\./g, "/")}.py`
|
|
8013
|
+
};
|
|
8014
|
+
}
|
|
7993
8015
|
function getModuleEntrypointName({
|
|
7994
8016
|
moduleName,
|
|
7995
8017
|
variableName
|
|
7996
8018
|
}) {
|
|
7997
|
-
|
|
8019
|
+
const base = moduleName.replace(/\./g, "-");
|
|
8020
|
+
return variableName === void 0 ? base : `${base}_${variableName}`;
|
|
7998
8021
|
}
|
|
7999
8022
|
function safePathSegment(value) {
|
|
8000
8023
|
return [...value].map((char) => {
|
|
@@ -8018,8 +8041,97 @@ async function resolveExistingEntrypoint(workPath, filePath) {
|
|
|
8018
8041
|
return null;
|
|
8019
8042
|
}
|
|
8020
8043
|
|
|
8044
|
+
// src/workflows.ts
|
|
8045
|
+
var import_path11 = require("path");
|
|
8046
|
+
var import_fs11 = __toESM(require("fs"));
|
|
8047
|
+
var import_build_utils13 = require("@vercel/build-utils");
|
|
8048
|
+
var WORKFLOW_OUTPUT_DIR = "_py_workflows";
|
|
8049
|
+
var WORKFLOW_TOPIC_PATTERN = "__wkf_*";
|
|
8050
|
+
var WORKFLOW_DEV_TOPIC_PATTERN = "__*wkf_*";
|
|
8051
|
+
var WORKFLOW_QUEUE_TOPIC_RE = /^__(?:[a-z][a-z0-9]*_)?wkf_/;
|
|
8052
|
+
function isWorkflowQueueTopic(topic) {
|
|
8053
|
+
return WORKFLOW_QUEUE_TOPIC_RE.test(topic);
|
|
8054
|
+
}
|
|
8055
|
+
var WORKFLOW_FIELD_NAMES = /* @__PURE__ */ new Set(["entrypoint"]);
|
|
8056
|
+
function getWorkflowOutputPath(workflowName) {
|
|
8057
|
+
return `${WORKFLOW_OUTPUT_DIR}/${safePathSegment(workflowName)}`;
|
|
8058
|
+
}
|
|
8059
|
+
function getWorkflowConsumerName(workflowName) {
|
|
8060
|
+
return (0, import_build_utils13.sanitizeConsumerName)(getWorkflowOutputPath(workflowName));
|
|
8061
|
+
}
|
|
8062
|
+
async function getPyprojectWorkflows(workPath) {
|
|
8063
|
+
const pyprojectPath = (0, import_path11.join)(workPath, "pyproject.toml");
|
|
8064
|
+
if (!import_fs11.default.existsSync(pyprojectPath)) {
|
|
8065
|
+
return [];
|
|
8066
|
+
}
|
|
8067
|
+
const pyproject = await (0, import_build_utils13.readConfigFile)(pyprojectPath);
|
|
8068
|
+
const workflows = pyproject?.tool?.vercel?.workflows;
|
|
8069
|
+
if (!workflows) {
|
|
8070
|
+
return [];
|
|
8071
|
+
}
|
|
8072
|
+
if (!Array.isArray(workflows)) {
|
|
8073
|
+
throw workflowError('"tool.vercel.workflows" must be an array');
|
|
8074
|
+
}
|
|
8075
|
+
const parsedWorkflows = await Promise.all(
|
|
8076
|
+
workflows.map((config, index) => parseWorkflow(workPath, index, config))
|
|
8077
|
+
);
|
|
8078
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
8079
|
+
for (const workflow of parsedWorkflows) {
|
|
8080
|
+
if (seenNames.has(workflow.name)) {
|
|
8081
|
+
throw workflowError(
|
|
8082
|
+
`workflow "${workflow.name}" is declared more than once`
|
|
8083
|
+
);
|
|
8084
|
+
}
|
|
8085
|
+
seenNames.add(workflow.name);
|
|
8086
|
+
}
|
|
8087
|
+
return parsedWorkflows;
|
|
8088
|
+
}
|
|
8089
|
+
async function parseWorkflow(workPath, index, config) {
|
|
8090
|
+
const label = `workflow #${index + 1}`;
|
|
8091
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
8092
|
+
throw workflowError(`${label} must be an object`);
|
|
8093
|
+
}
|
|
8094
|
+
for (const key of Object.keys(config)) {
|
|
8095
|
+
if (!WORKFLOW_FIELD_NAMES.has(key)) {
|
|
8096
|
+
throw workflowError(`${label} has unrecognized field "${key}"`);
|
|
8097
|
+
}
|
|
8098
|
+
}
|
|
8099
|
+
if (typeof config.entrypoint !== "string") {
|
|
8100
|
+
throw workflowError(`${label} must define string field "entrypoint"`);
|
|
8101
|
+
}
|
|
8102
|
+
const entrypoint = parseModuleEntrypoint(config.entrypoint);
|
|
8103
|
+
if (!entrypoint) {
|
|
8104
|
+
throw workflowError(
|
|
8105
|
+
`${label} has invalid entrypoint "${config.entrypoint}". Use "module:object"`
|
|
8106
|
+
);
|
|
8107
|
+
}
|
|
8108
|
+
const name = getModuleEntrypointName(entrypoint);
|
|
8109
|
+
const existingEntrypoint = await resolveExistingEntrypoint(
|
|
8110
|
+
workPath,
|
|
8111
|
+
entrypoint.filePath
|
|
8112
|
+
);
|
|
8113
|
+
if (!existingEntrypoint) {
|
|
8114
|
+
throw workflowError(
|
|
8115
|
+
`workflow "${name}" has entrypoint "${config.entrypoint}" but file "${entrypoint.filePath}" does not exist`
|
|
8116
|
+
);
|
|
8117
|
+
}
|
|
8118
|
+
return {
|
|
8119
|
+
name,
|
|
8120
|
+
entrypoint: existingEntrypoint,
|
|
8121
|
+
moduleName: entrypoint.moduleName,
|
|
8122
|
+
variableName: entrypoint.variableName
|
|
8123
|
+
};
|
|
8124
|
+
}
|
|
8125
|
+
function workflowError(message) {
|
|
8126
|
+
return new import_build_utils13.NowBuildError({
|
|
8127
|
+
code: "PYTHON_INVALID_WORKFLOW_CONFIG",
|
|
8128
|
+
message
|
|
8129
|
+
});
|
|
8130
|
+
}
|
|
8131
|
+
|
|
8021
8132
|
// src/subscribers.ts
|
|
8022
8133
|
var SUBSCRIBER_OUTPUT_DIR = "_py_subscribers";
|
|
8134
|
+
var SUBSCRIBER_ID_ENV = "VERCEL_PYTHON_SUBSCRIBER_ID";
|
|
8023
8135
|
var TRIGGER_NUMBER_FIELDS = [
|
|
8024
8136
|
{
|
|
8025
8137
|
field: "max_attempts",
|
|
@@ -8078,11 +8190,18 @@ var LEGACY_SUBSCRIBER_FIELD_NAMES = /* @__PURE__ */ new Set([
|
|
|
8078
8190
|
"topics",
|
|
8079
8191
|
...LEGACY_TRIGGER_NUMBER_FIELDS.map(({ field }) => field)
|
|
8080
8192
|
]);
|
|
8193
|
+
var APSCHEDULER_PREVIEW_FIELD_NAMES = /* @__PURE__ */ new Set(["enabled", "idle_timeout"]);
|
|
8194
|
+
var APSCHEDULER_DURATION_UNITS = {
|
|
8195
|
+
s: 1,
|
|
8196
|
+
m: 60,
|
|
8197
|
+
h: 60 * 60,
|
|
8198
|
+
d: 24 * 60 * 60
|
|
8199
|
+
};
|
|
8081
8200
|
function getSubscriberOutputPath(subscriberName) {
|
|
8082
8201
|
return `${SUBSCRIBER_OUTPUT_DIR}/${safePathSegment(subscriberName)}`;
|
|
8083
8202
|
}
|
|
8084
8203
|
function getSubscriberConsumerName(subscriberName) {
|
|
8085
|
-
return (0,
|
|
8204
|
+
return (0, import_build_utils14.sanitizeConsumerName)(getSubscriberOutputPath(subscriberName));
|
|
8086
8205
|
}
|
|
8087
8206
|
function getGeneratedQueueHandlerPath(outputPath) {
|
|
8088
8207
|
return `_vc_queue_handlers/${outputPath.replace(/[^A-Za-z0-9_]+/g, "_")}.py`;
|
|
@@ -8090,12 +8209,21 @@ function getGeneratedQueueHandlerPath(outputPath) {
|
|
|
8090
8209
|
function generatedPythonPathToModule(filePath) {
|
|
8091
8210
|
return filePath.replace(/\.py$/, "").split(/[\\/]+/).join(".");
|
|
8092
8211
|
}
|
|
8212
|
+
async function hasPyprojectSubscribers(workPath) {
|
|
8213
|
+
const pyprojectPath = (0, import_path12.join)(workPath, "pyproject.toml");
|
|
8214
|
+
if (!import_fs12.default.existsSync(pyprojectPath)) {
|
|
8215
|
+
return false;
|
|
8216
|
+
}
|
|
8217
|
+
const pyproject = await (0, import_build_utils14.readConfigFile)(pyprojectPath);
|
|
8218
|
+
const subscribers = pyproject?.tool?.vercel?.subscribers;
|
|
8219
|
+
return Array.isArray(subscribers) && subscribers.length > 0;
|
|
8220
|
+
}
|
|
8093
8221
|
async function getPyprojectSubscribers(workPath, { legacySchema = false } = {}) {
|
|
8094
|
-
const pyprojectPath = (0,
|
|
8095
|
-
if (!
|
|
8222
|
+
const pyprojectPath = (0, import_path12.join)(workPath, "pyproject.toml");
|
|
8223
|
+
if (!import_fs12.default.existsSync(pyprojectPath)) {
|
|
8096
8224
|
return [];
|
|
8097
8225
|
}
|
|
8098
|
-
const pyproject = await (0,
|
|
8226
|
+
const pyproject = await (0, import_build_utils14.readConfigFile)(pyprojectPath);
|
|
8099
8227
|
const subscribers = pyproject?.tool?.vercel?.subscribers;
|
|
8100
8228
|
if (!subscribers) {
|
|
8101
8229
|
return [];
|
|
@@ -8119,6 +8247,63 @@ async function getPyprojectSubscribers(workPath, { legacySchema = false } = {})
|
|
|
8119
8247
|
}
|
|
8120
8248
|
return parsedSubscribers;
|
|
8121
8249
|
}
|
|
8250
|
+
async function getApschedulerPreviewConfig(workPath) {
|
|
8251
|
+
const pyprojectPath = (0, import_path12.join)(workPath, "pyproject.toml");
|
|
8252
|
+
if (!import_fs12.default.existsSync(pyprojectPath)) {
|
|
8253
|
+
return void 0;
|
|
8254
|
+
}
|
|
8255
|
+
const pyproject = await (0, import_build_utils14.readConfigFile)(pyprojectPath);
|
|
8256
|
+
const apscheduler = pyproject?.tool?.vercel?.apscheduler;
|
|
8257
|
+
if (apscheduler === void 0) {
|
|
8258
|
+
return void 0;
|
|
8259
|
+
}
|
|
8260
|
+
if (!apscheduler || typeof apscheduler !== "object" || Array.isArray(apscheduler)) {
|
|
8261
|
+
throw apschedulerError('"tool.vercel.apscheduler" must be a table');
|
|
8262
|
+
}
|
|
8263
|
+
const previews = apscheduler.previews;
|
|
8264
|
+
if (previews === void 0) {
|
|
8265
|
+
return void 0;
|
|
8266
|
+
}
|
|
8267
|
+
if (!previews || typeof previews !== "object" || Array.isArray(previews)) {
|
|
8268
|
+
throw apschedulerError(
|
|
8269
|
+
'"tool.vercel.apscheduler.previews" must be a table'
|
|
8270
|
+
);
|
|
8271
|
+
}
|
|
8272
|
+
const rawPreviews = previews;
|
|
8273
|
+
for (const key of Object.keys(rawPreviews)) {
|
|
8274
|
+
if (!APSCHEDULER_PREVIEW_FIELD_NAMES.has(key)) {
|
|
8275
|
+
throw apschedulerError(
|
|
8276
|
+
`"tool.vercel.apscheduler.previews" has unrecognized field "${key}"`
|
|
8277
|
+
);
|
|
8278
|
+
}
|
|
8279
|
+
}
|
|
8280
|
+
if (rawPreviews.enabled !== void 0 && typeof rawPreviews.enabled !== "boolean") {
|
|
8281
|
+
throw apschedulerError(
|
|
8282
|
+
'"tool.vercel.apscheduler.previews.enabled" must be a boolean'
|
|
8283
|
+
);
|
|
8284
|
+
}
|
|
8285
|
+
if (rawPreviews.enabled !== true) {
|
|
8286
|
+
return void 0;
|
|
8287
|
+
}
|
|
8288
|
+
if (typeof rawPreviews.idle_timeout !== "string") {
|
|
8289
|
+
throw apschedulerError(
|
|
8290
|
+
'"tool.vercel.apscheduler.previews.idle_timeout" must be a duration such as "30m"'
|
|
8291
|
+
);
|
|
8292
|
+
}
|
|
8293
|
+
const match = /^([1-9]\d*)([smhd])$/.exec(rawPreviews.idle_timeout);
|
|
8294
|
+
if (!match) {
|
|
8295
|
+
throw apschedulerError(
|
|
8296
|
+
'"tool.vercel.apscheduler.previews.idle_timeout" must be a positive duration using s, m, h, or d (for example "30m")'
|
|
8297
|
+
);
|
|
8298
|
+
}
|
|
8299
|
+
const idleTimeoutSeconds = Number(match[1]) * APSCHEDULER_DURATION_UNITS[match[2]];
|
|
8300
|
+
if (!Number.isSafeInteger(idleTimeoutSeconds)) {
|
|
8301
|
+
throw apschedulerError(
|
|
8302
|
+
'"tool.vercel.apscheduler.previews.idle_timeout" is too large'
|
|
8303
|
+
);
|
|
8304
|
+
}
|
|
8305
|
+
return { idleTimeoutSeconds };
|
|
8306
|
+
}
|
|
8122
8307
|
async function resolveQueueSubscribers({
|
|
8123
8308
|
declarations,
|
|
8124
8309
|
uv,
|
|
@@ -8140,10 +8325,12 @@ async function resolveQueueSubscribers({
|
|
|
8140
8325
|
const hint = kind === "workflow" ? "; ensure the entrypoint instantiates vercel.workflow.Workflows" : "";
|
|
8141
8326
|
const unmatchedTopicPatterns = getUnmatchedQueueTopicPatterns(
|
|
8142
8327
|
declaration,
|
|
8143
|
-
introspected
|
|
8328
|
+
introspected.subscriptions
|
|
8144
8329
|
);
|
|
8145
8330
|
if (unmatchedTopicPatterns.length > 0) {
|
|
8146
|
-
const introspectedTopics = introspected.map(
|
|
8331
|
+
const introspectedTopics = introspected.subscriptions.map(
|
|
8332
|
+
({ topic }) => topic
|
|
8333
|
+
);
|
|
8147
8334
|
throw subscriberError(
|
|
8148
8335
|
`${kind} "${declaration.name}" declared topics [${unmatchedTopicPatterns.join(
|
|
8149
8336
|
", "
|
|
@@ -8152,14 +8339,21 @@ async function resolveQueueSubscribers({
|
|
|
8152
8339
|
)}]${hint}`
|
|
8153
8340
|
);
|
|
8154
8341
|
}
|
|
8155
|
-
const subscriptions =
|
|
8342
|
+
const subscriptions = kind === "workflow" ? introspected.subscriptions.filter(
|
|
8343
|
+
(subscription) => isWorkflowQueueTopic(subscription.topic)
|
|
8344
|
+
) : filterQueueSubscriptions(declaration, introspected.subscriptions);
|
|
8156
8345
|
if (subscriptions.length === 0) {
|
|
8346
|
+
if (kind === "workflow") {
|
|
8347
|
+
throw subscriberError(
|
|
8348
|
+
`workflow "${declaration.name}" registered no workflow queue subscriptions${hint}`
|
|
8349
|
+
);
|
|
8350
|
+
}
|
|
8157
8351
|
const declared = declaration.topicPatterns?.join(", ") ?? "*";
|
|
8158
8352
|
throw subscriberError(
|
|
8159
8353
|
`${kind} "${declaration.name}" declared topics [${declared}] but no introspected queue subscriptions matched${hint}`
|
|
8160
8354
|
);
|
|
8161
8355
|
}
|
|
8162
|
-
result.push({ ...declaration, subscriptions });
|
|
8356
|
+
result.push({ ...declaration, subscriptions, owners: introspected.owners });
|
|
8163
8357
|
}
|
|
8164
8358
|
return result;
|
|
8165
8359
|
}
|
|
@@ -8212,8 +8406,10 @@ function createIntegrationInstallLines(integrations, { serving, beforeImport })
|
|
|
8212
8406
|
function createQueueHandlerModule(declaration, integrations) {
|
|
8213
8407
|
return [
|
|
8214
8408
|
"import importlib",
|
|
8409
|
+
"import os",
|
|
8215
8410
|
"import vercel.queue",
|
|
8216
8411
|
"",
|
|
8412
|
+
`os.environ[${JSON.stringify(SUBSCRIBER_ID_ENV)}] = ${JSON.stringify(declaration.name)}`,
|
|
8217
8413
|
...createIntegrationInstallLines(integrations, {
|
|
8218
8414
|
serving: true,
|
|
8219
8415
|
beforeImport: true
|
|
@@ -8227,14 +8423,22 @@ function createQueueHandlerModule(declaration, integrations) {
|
|
|
8227
8423
|
""
|
|
8228
8424
|
].join("\n");
|
|
8229
8425
|
}
|
|
8230
|
-
async function parseSubscriberEntrypoint(workPath, label, entrypointValue) {
|
|
8426
|
+
async function parseSubscriberEntrypoint(workPath, label, entrypointValue, { requireVariable }) {
|
|
8231
8427
|
if (typeof entrypointValue !== "string") {
|
|
8232
8428
|
throw subscriberError(`${label} must define string field "entrypoint"`);
|
|
8233
8429
|
}
|
|
8234
|
-
|
|
8430
|
+
if (!requireVariable && /\.py$/i.test(entrypointValue)) {
|
|
8431
|
+
const suggestion = parseBareModuleEntrypoint(
|
|
8432
|
+
entrypointValue.slice(0, -3).replace(/[\\/]+/g, ".").replace(/(^|\.)__init__$/, "")
|
|
8433
|
+
);
|
|
8434
|
+
throw subscriberError(
|
|
8435
|
+
`${label} has invalid entrypoint "${entrypointValue}". Use an import path, not a file path${suggestion ? `: "${suggestion.moduleName}"` : ""}`
|
|
8436
|
+
);
|
|
8437
|
+
}
|
|
8438
|
+
const entrypoint = parseModuleEntrypoint(entrypointValue) ?? (requireVariable ? null : parseBareModuleEntrypoint(entrypointValue));
|
|
8235
8439
|
if (!entrypoint) {
|
|
8236
8440
|
throw subscriberError(
|
|
8237
|
-
`${label} has invalid entrypoint "${entrypointValue}". Use "module:object"`
|
|
8441
|
+
`${label} has invalid entrypoint "${entrypointValue}". Use ${requireVariable ? '"module:object"' : '"module:object" or a module path like "pkg.module"'}`
|
|
8238
8442
|
);
|
|
8239
8443
|
}
|
|
8240
8444
|
const name = getModuleEntrypointName(entrypoint);
|
|
@@ -8247,11 +8451,12 @@ async function parseSubscriberEntrypoint(workPath, label, entrypointValue) {
|
|
|
8247
8451
|
`subscriber "${name}" has entrypoint "${entrypointValue}" but file "${entrypoint.filePath}" does not exist`
|
|
8248
8452
|
);
|
|
8249
8453
|
}
|
|
8454
|
+
const { variableName } = entrypoint;
|
|
8250
8455
|
return {
|
|
8251
8456
|
name,
|
|
8252
8457
|
entrypoint: existingEntrypoint,
|
|
8253
8458
|
moduleName: entrypoint.moduleName,
|
|
8254
|
-
variableName:
|
|
8459
|
+
...variableName === void 0 ? {} : { variableName }
|
|
8255
8460
|
};
|
|
8256
8461
|
}
|
|
8257
8462
|
async function parseSubscriber(workPath, index, config) {
|
|
@@ -8267,7 +8472,8 @@ async function parseSubscriber(workPath, index, config) {
|
|
|
8267
8472
|
const base = await parseSubscriberEntrypoint(
|
|
8268
8473
|
workPath,
|
|
8269
8474
|
label,
|
|
8270
|
-
config.entrypoint
|
|
8475
|
+
config.entrypoint,
|
|
8476
|
+
{ requireVariable: false }
|
|
8271
8477
|
);
|
|
8272
8478
|
return {
|
|
8273
8479
|
...base,
|
|
@@ -8287,7 +8493,8 @@ async function parseLegacySubscriber(workPath, index, config) {
|
|
|
8287
8493
|
const base = await parseSubscriberEntrypoint(
|
|
8288
8494
|
workPath,
|
|
8289
8495
|
label,
|
|
8290
|
-
config.entrypoint
|
|
8496
|
+
config.entrypoint,
|
|
8497
|
+
{ requireVariable: true }
|
|
8291
8498
|
);
|
|
8292
8499
|
return {
|
|
8293
8500
|
...base,
|
|
@@ -8351,14 +8558,26 @@ function parseTopicPatterns(name, value) {
|
|
|
8351
8558
|
}
|
|
8352
8559
|
return value;
|
|
8353
8560
|
}
|
|
8354
|
-
function createQueueIntrospectionScript(
|
|
8561
|
+
function createQueueIntrospectionScript(declaration, integrations) {
|
|
8562
|
+
const { variableName } = declaration;
|
|
8563
|
+
const probeLines = variableName === void 0 ? [] : integrations.filter((integration) => integration.subscriberProbe).flatMap(({ module: module2, subscriberProbe }) => [
|
|
8564
|
+
"try:",
|
|
8565
|
+
` from ${module2} import ${subscriberProbe}`,
|
|
8566
|
+
"except ImportError:",
|
|
8567
|
+
" pass",
|
|
8568
|
+
"else:",
|
|
8569
|
+
` if ${subscriberProbe}(${JSON.stringify(declaration.moduleName)}, ${JSON.stringify(variableName)}):`,
|
|
8570
|
+
` owners.append(${JSON.stringify(module2)})`
|
|
8571
|
+
]);
|
|
8355
8572
|
return [
|
|
8356
|
-
"import importlib, json, sys",
|
|
8573
|
+
"import importlib, json, os, sys",
|
|
8574
|
+
`os.environ[${JSON.stringify(SUBSCRIBER_ID_ENV)}] = ${JSON.stringify(declaration.name)}`,
|
|
8575
|
+
'os.environ["VERCEL_APSCHEDULER_DISCOVERY"] = "1"',
|
|
8357
8576
|
...createIntegrationInstallLines(integrations, {
|
|
8358
8577
|
serving: false,
|
|
8359
8578
|
beforeImport: true
|
|
8360
8579
|
}),
|
|
8361
|
-
`importlib.import_module(${JSON.stringify(moduleName)})`,
|
|
8580
|
+
`importlib.import_module(${JSON.stringify(declaration.moduleName)})`,
|
|
8362
8581
|
...createIntegrationInstallLines(integrations, {
|
|
8363
8582
|
serving: false,
|
|
8364
8583
|
beforeImport: false
|
|
@@ -8375,7 +8594,9 @@ function createQueueIntrospectionScript(moduleName, integrations) {
|
|
|
8375
8594
|
" }.items() if v is not None}",
|
|
8376
8595
|
" for s in get_subscriptions()",
|
|
8377
8596
|
"]",
|
|
8378
|
-
"
|
|
8597
|
+
"owners = []",
|
|
8598
|
+
...probeLines,
|
|
8599
|
+
"json.dump({'subscriptions': subs, 'owners': owners}, sys.stdout)"
|
|
8379
8600
|
].join("\n");
|
|
8380
8601
|
}
|
|
8381
8602
|
async function introspectQueueSubscriptions({
|
|
@@ -8386,10 +8607,7 @@ async function introspectQueueSubscriptions({
|
|
|
8386
8607
|
kind,
|
|
8387
8608
|
integrations
|
|
8388
8609
|
}) {
|
|
8389
|
-
const script3 = createQueueIntrospectionScript(
|
|
8390
|
-
declaration.moduleName,
|
|
8391
|
-
integrations
|
|
8392
|
-
);
|
|
8610
|
+
const script3 = createQueueIntrospectionScript(declaration, integrations);
|
|
8393
8611
|
try {
|
|
8394
8612
|
const { stdout } = await uv.run({
|
|
8395
8613
|
venvPath,
|
|
@@ -8410,7 +8628,7 @@ async function introspectQueueSubscriptions({
|
|
|
8410
8628
|
});
|
|
8411
8629
|
return parseIntrospectedSubscriptions(kind, declaration.name, stdout);
|
|
8412
8630
|
} catch (err) {
|
|
8413
|
-
if (err instanceof
|
|
8631
|
+
if (err instanceof import_build_utils14.NowBuildError) {
|
|
8414
8632
|
throw err;
|
|
8415
8633
|
}
|
|
8416
8634
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -8421,6 +8639,8 @@ async function introspectQueueSubscriptions({
|
|
|
8421
8639
|
}
|
|
8422
8640
|
async function introspectDevQueueSubscriptions({
|
|
8423
8641
|
moduleName,
|
|
8642
|
+
subscriberName,
|
|
8643
|
+
variableName,
|
|
8424
8644
|
pythonBin,
|
|
8425
8645
|
cwd,
|
|
8426
8646
|
env,
|
|
@@ -8429,7 +8649,13 @@ async function introspectDevQueueSubscriptions({
|
|
|
8429
8649
|
try {
|
|
8430
8650
|
const { stdout } = await (0, import_execa6.default)(
|
|
8431
8651
|
pythonBin,
|
|
8432
|
-
[
|
|
8652
|
+
[
|
|
8653
|
+
"-c",
|
|
8654
|
+
createQueueIntrospectionScript(
|
|
8655
|
+
{ moduleName, name: subscriberName, variableName },
|
|
8656
|
+
integrations
|
|
8657
|
+
)
|
|
8658
|
+
],
|
|
8433
8659
|
// Match the deployed-function environment (see
|
|
8434
8660
|
// introspectQueueSubscriptions): SDKs may need VERCEL=1,
|
|
8435
8661
|
// VERCEL_REGION, and VERCEL_DEPLOYMENT_ID to register subscriptions.
|
|
@@ -8443,12 +8669,12 @@ async function introspectDevQueueSubscriptions({
|
|
|
8443
8669
|
}
|
|
8444
8670
|
}
|
|
8445
8671
|
);
|
|
8446
|
-
const
|
|
8672
|
+
const introspected = parseIntrospectedSubscriptions(
|
|
8447
8673
|
"subscriber",
|
|
8448
8674
|
moduleName,
|
|
8449
8675
|
stdout
|
|
8450
8676
|
);
|
|
8451
|
-
|
|
8677
|
+
const subscriptions = introspected.subscriptions.map((subscription) => {
|
|
8452
8678
|
const { retryAfterSeconds, initialDelaySeconds, maxDeliveries } = subscription.triggerDefaults;
|
|
8453
8679
|
return {
|
|
8454
8680
|
topic: subscription.topic,
|
|
@@ -8458,8 +8684,9 @@ async function introspectDevQueueSubscriptions({
|
|
|
8458
8684
|
...maxDeliveries === void 0 ? {} : { maxDeliveries }
|
|
8459
8685
|
};
|
|
8460
8686
|
});
|
|
8687
|
+
return { subscriptions, owners: introspected.owners };
|
|
8461
8688
|
} catch (err) {
|
|
8462
|
-
(0,
|
|
8689
|
+
(0, import_build_utils14.debug)(
|
|
8463
8690
|
`Failed to introspect dev queue subscriptions for module "${moduleName}": ${err instanceof Error ? err.message : String(err)}`
|
|
8464
8691
|
);
|
|
8465
8692
|
return void 0;
|
|
@@ -8474,14 +8701,28 @@ function parseIntrospectedSubscriptions(kind, subscriberName, stdout) {
|
|
|
8474
8701
|
`${kind} "${subscriberName}" queue introspection did not return valid JSON`
|
|
8475
8702
|
);
|
|
8476
8703
|
}
|
|
8477
|
-
if (!Array.isArray(parsed)) {
|
|
8704
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
8478
8705
|
throw subscriberError(
|
|
8479
|
-
`${kind} "${subscriberName}" queue introspection must return an
|
|
8706
|
+
`${kind} "${subscriberName}" queue introspection must return an object`
|
|
8480
8707
|
);
|
|
8481
8708
|
}
|
|
8482
|
-
|
|
8483
|
-
|
|
8484
|
-
|
|
8709
|
+
const { subscriptions, owners = [] } = parsed;
|
|
8710
|
+
if (!Array.isArray(subscriptions)) {
|
|
8711
|
+
throw subscriberError(
|
|
8712
|
+
`${kind} "${subscriberName}" queue introspection must return a "subscriptions" array`
|
|
8713
|
+
);
|
|
8714
|
+
}
|
|
8715
|
+
if (!Array.isArray(owners) || owners.some((o) => typeof o !== "string")) {
|
|
8716
|
+
throw subscriberError(
|
|
8717
|
+
`${kind} "${subscriberName}" queue introspection "owners" must be an array of strings`
|
|
8718
|
+
);
|
|
8719
|
+
}
|
|
8720
|
+
return {
|
|
8721
|
+
subscriptions: subscriptions.map(
|
|
8722
|
+
(subscription, index) => parseIntrospectedSubscription(kind, subscriberName, index, subscription)
|
|
8723
|
+
),
|
|
8724
|
+
owners
|
|
8725
|
+
};
|
|
8485
8726
|
}
|
|
8486
8727
|
function parseIntrospectedSubscription(kind, subscriberName, index, value) {
|
|
8487
8728
|
const label = `${kind} "${subscriberName}" introspected subscription #${index + 1}`;
|
|
@@ -8525,12 +8766,27 @@ function getQueueWildcardPrefix(pattern) {
|
|
|
8525
8766
|
}
|
|
8526
8767
|
return void 0;
|
|
8527
8768
|
}
|
|
8769
|
+
var APSCHEDULER_INTEGRATION_MODULE = "vercel.integrations.apscheduler";
|
|
8770
|
+
function apschedulerSubscriberIdentities(subscribers) {
|
|
8771
|
+
return subscribers.filter(
|
|
8772
|
+
(subscriber) => subscriber.owners.includes(APSCHEDULER_INTEGRATION_MODULE)
|
|
8773
|
+
).map((subscriber) => ({
|
|
8774
|
+
id: subscriber.name,
|
|
8775
|
+
entrypoint: `${subscriber.moduleName}:${subscriber.variableName}`
|
|
8776
|
+
}));
|
|
8777
|
+
}
|
|
8528
8778
|
function subscriberError(message) {
|
|
8529
|
-
return new
|
|
8779
|
+
return new import_build_utils14.NowBuildError({
|
|
8530
8780
|
code: "PYTHON_INVALID_SUBSCRIBER_CONFIG",
|
|
8531
8781
|
message
|
|
8532
8782
|
});
|
|
8533
8783
|
}
|
|
8784
|
+
function apschedulerError(message) {
|
|
8785
|
+
return new import_build_utils14.NowBuildError({
|
|
8786
|
+
code: "PYTHON_INVALID_APSCHEDULER_CONFIG",
|
|
8787
|
+
message
|
|
8788
|
+
});
|
|
8789
|
+
}
|
|
8534
8790
|
|
|
8535
8791
|
// src/start-dev-server.ts
|
|
8536
8792
|
var DEV_SERVER_STARTUP_TIMEOUT = 5 * 6e4;
|
|
@@ -8631,17 +8887,17 @@ async function syncDependencies({
|
|
|
8631
8887
|
let { manifestPath } = installInfo;
|
|
8632
8888
|
const manifest = pythonPackage.manifest;
|
|
8633
8889
|
if (!manifestType || !manifestPath) {
|
|
8634
|
-
(0,
|
|
8890
|
+
(0, import_build_utils15.debug)("No Python project manifest found, skipping dependency sync");
|
|
8635
8891
|
return;
|
|
8636
8892
|
}
|
|
8637
8893
|
if (manifest?.origin && manifestType === "pyproject.toml") {
|
|
8638
|
-
const syncDir = (0,
|
|
8639
|
-
(0,
|
|
8640
|
-
const tempPyproject = (0,
|
|
8894
|
+
const syncDir = (0, import_path13.join)(workPath, ".vercel", "python", "sync");
|
|
8895
|
+
(0, import_fs13.mkdirSync)(syncDir, { recursive: true });
|
|
8896
|
+
const tempPyproject = (0, import_path13.join)(syncDir, "pyproject.toml");
|
|
8641
8897
|
const content = (0, import_python_analysis8.stringifyManifest)(manifest.data);
|
|
8642
|
-
(0,
|
|
8898
|
+
(0, import_fs13.writeFileSync)(tempPyproject, content, "utf8");
|
|
8643
8899
|
manifestPath = tempPyproject;
|
|
8644
|
-
(0,
|
|
8900
|
+
(0, import_build_utils15.debug)(
|
|
8645
8901
|
`Wrote converted ${manifest.origin.kind} manifest to ${tempPyproject}`
|
|
8646
8902
|
);
|
|
8647
8903
|
}
|
|
@@ -8674,7 +8930,7 @@ async function syncDependencies({
|
|
|
8674
8930
|
for (const [channel, chunk] of captured) {
|
|
8675
8931
|
(channel === "stdout" ? writeOut : writeErr)(chunk.toString());
|
|
8676
8932
|
}
|
|
8677
|
-
throw new
|
|
8933
|
+
throw new import_build_utils15.NowBuildError({
|
|
8678
8934
|
code: "PYTHON_DEPENDENCY_SYNC_FAILED",
|
|
8679
8935
|
message: `Failed to install Python dependencies from ${manifestType}: ${err instanceof Error ? err.message : String(err)}`
|
|
8680
8936
|
});
|
|
@@ -8689,14 +8945,14 @@ async function runSync({
|
|
|
8689
8945
|
onStdout,
|
|
8690
8946
|
onStderr
|
|
8691
8947
|
}) {
|
|
8692
|
-
const projectDir = (0,
|
|
8948
|
+
const projectDir = (0, import_path13.dirname)(manifestPath);
|
|
8693
8949
|
const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
|
|
8694
8950
|
let spawnCmd;
|
|
8695
8951
|
let spawnArgs;
|
|
8696
8952
|
switch (manifestType) {
|
|
8697
8953
|
case "uv.lock": {
|
|
8698
8954
|
if (!uvPath) {
|
|
8699
|
-
throw new
|
|
8955
|
+
throw new import_build_utils15.NowBuildError({
|
|
8700
8956
|
code: "PYTHON_DEPENDENCY_SYNC_FAILED",
|
|
8701
8957
|
message: "uv is required to install dependencies from uv.lock.",
|
|
8702
8958
|
link: "https://docs.astral.sh/uv/getting-started/installation/",
|
|
@@ -8718,11 +8974,11 @@ async function runSync({
|
|
|
8718
8974
|
break;
|
|
8719
8975
|
}
|
|
8720
8976
|
default:
|
|
8721
|
-
(0,
|
|
8977
|
+
(0, import_build_utils15.debug)(`Unknown manifest type: ${manifestType}`);
|
|
8722
8978
|
return;
|
|
8723
8979
|
}
|
|
8724
8980
|
await new Promise((resolve4, reject) => {
|
|
8725
|
-
(0,
|
|
8981
|
+
(0, import_build_utils15.debug)(`Running "${spawnCmd} ${spawnArgs.join(" ")}" in ${projectDir}...`);
|
|
8726
8982
|
const child = (0, import_child_process2.spawn)(spawnCmd, spawnArgs, {
|
|
8727
8983
|
cwd: projectDir,
|
|
8728
8984
|
env: getProtectedUvEnv(env),
|
|
@@ -8761,7 +9017,7 @@ var COMPLETED_INSTALLS = /* @__PURE__ */ new Set();
|
|
|
8761
9017
|
function hasInstalledDistribution(targetDir, packageName) {
|
|
8762
9018
|
const prefix = `${packageName.replace("-", "_")}-`;
|
|
8763
9019
|
try {
|
|
8764
|
-
return (0,
|
|
9020
|
+
return (0, import_fs13.readdirSync)(targetDir).some(
|
|
8765
9021
|
(entry) => entry.startsWith(prefix) && entry.endsWith(".dist-info")
|
|
8766
9022
|
);
|
|
8767
9023
|
} catch {
|
|
@@ -8769,7 +9025,7 @@ function hasInstalledDistribution(targetDir, packageName) {
|
|
|
8769
9025
|
}
|
|
8770
9026
|
}
|
|
8771
9027
|
async function installInjectedDevPackage(pkg, opts) {
|
|
8772
|
-
const targetDir = (0,
|
|
9028
|
+
const targetDir = (0, import_path13.join)(opts.workPath, ".vercel", "python");
|
|
8773
9029
|
const source = pkg.envOverride || pkg.pinnedVersion || pkg.requirement;
|
|
8774
9030
|
const key = `${targetDir}:${pkg.name}:${source}`;
|
|
8775
9031
|
if (COMPLETED_INSTALLS.has(key) && hasInstalledDistribution(targetDir, pkg.name)) {
|
|
@@ -8783,23 +9039,23 @@ async function installInjectedDevPackage(pkg, opts) {
|
|
|
8783
9039
|
}
|
|
8784
9040
|
async function doInstallInjectedDevPackage(pkg, opts) {
|
|
8785
9041
|
const { targetDir, workPath, uvPath, pythonBin, env, onStdout, onStderr } = opts;
|
|
8786
|
-
(0,
|
|
8787
|
-
const localDir = (0,
|
|
8788
|
-
const isLocalDev = (0,
|
|
9042
|
+
(0, import_fs13.mkdirSync)(targetDir, { recursive: true });
|
|
9043
|
+
const localDir = (0, import_path13.join)(__dirname, "..", "..", "..", "python", pkg.name);
|
|
9044
|
+
const isLocalDev = (0, import_fs13.existsSync)((0, import_path13.join)(localDir, "pyproject.toml"));
|
|
8789
9045
|
const requirement = pkg.pinnedVersion ? `${pkg.name}==${pkg.pinnedVersion}` : pkg.requirement ?? pkg.name;
|
|
8790
9046
|
const dep = pkg.envOverride || (isLocalDev ? localDir : requirement);
|
|
8791
9047
|
if (!isLocalDev && !pkg.envOverride && pkg.pinnedVersion) {
|
|
8792
9048
|
const distInfoName = pkg.name.replace("-", "_");
|
|
8793
|
-
const distInfo = (0,
|
|
9049
|
+
const distInfo = (0, import_path13.join)(
|
|
8794
9050
|
targetDir,
|
|
8795
9051
|
`${distInfoName}-${pkg.pinnedVersion}.dist-info`
|
|
8796
9052
|
);
|
|
8797
|
-
if ((0,
|
|
8798
|
-
(0,
|
|
9053
|
+
if ((0, import_fs13.existsSync)(distInfo)) {
|
|
9054
|
+
(0, import_build_utils15.debug)(`${pkg.name} ${pkg.pinnedVersion} already installed, skipping`);
|
|
8799
9055
|
return;
|
|
8800
9056
|
}
|
|
8801
9057
|
}
|
|
8802
|
-
(0,
|
|
9058
|
+
(0, import_build_utils15.debug)(
|
|
8803
9059
|
`Installing ${pkg.name} into ${targetDir} (type: ${isLocalDev ? "local" : "pypi"}, source: ${dep})`
|
|
8804
9060
|
);
|
|
8805
9061
|
const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
|
|
@@ -8821,14 +9077,14 @@ async function doInstallInjectedDevPackage(pkg, opts) {
|
|
|
8821
9077
|
if (onStdout) {
|
|
8822
9078
|
onStdout(data);
|
|
8823
9079
|
} else {
|
|
8824
|
-
(0,
|
|
9080
|
+
(0, import_build_utils15.debug)(data.toString());
|
|
8825
9081
|
}
|
|
8826
9082
|
});
|
|
8827
9083
|
child.stderr?.on("data", (data) => {
|
|
8828
9084
|
if (onStderr) {
|
|
8829
9085
|
onStderr(data);
|
|
8830
9086
|
} else {
|
|
8831
|
-
(0,
|
|
9087
|
+
(0, import_build_utils15.debug)(data.toString());
|
|
8832
9088
|
}
|
|
8833
9089
|
});
|
|
8834
9090
|
child.on("error", reject);
|
|
@@ -8858,12 +9114,12 @@ function installGlobalCleanupHandlers() {
|
|
|
8858
9114
|
try {
|
|
8859
9115
|
process.kill(info.pid, "SIGTERM");
|
|
8860
9116
|
} catch (err) {
|
|
8861
|
-
(0,
|
|
9117
|
+
(0, import_build_utils15.debug)(`Error sending SIGTERM to ${info.pid}: ${err}`);
|
|
8862
9118
|
}
|
|
8863
9119
|
try {
|
|
8864
9120
|
process.kill(info.pid, "SIGKILL");
|
|
8865
9121
|
} catch (err) {
|
|
8866
|
-
(0,
|
|
9122
|
+
(0, import_build_utils15.debug)(`Error sending SIGKILL to ${info.pid}: ${err}`);
|
|
8867
9123
|
}
|
|
8868
9124
|
PERSISTENT_SERVERS.delete(key);
|
|
8869
9125
|
}
|
|
@@ -8871,7 +9127,7 @@ function installGlobalCleanupHandlers() {
|
|
|
8871
9127
|
try {
|
|
8872
9128
|
restoreWarnings();
|
|
8873
9129
|
} catch (err) {
|
|
8874
|
-
(0,
|
|
9130
|
+
(0, import_build_utils15.debug)(`Error restoring warnings: ${err}`);
|
|
8875
9131
|
}
|
|
8876
9132
|
restoreWarnings = null;
|
|
8877
9133
|
}
|
|
@@ -8888,46 +9144,46 @@ function installGlobalCleanupHandlers() {
|
|
|
8888
9144
|
}
|
|
8889
9145
|
function createDevShim(workPath, entry, modulePath, serviceName, framework, variableName) {
|
|
8890
9146
|
try {
|
|
8891
|
-
const vercelPythonDir = serviceName ? (0,
|
|
8892
|
-
(0,
|
|
9147
|
+
const vercelPythonDir = serviceName ? (0, import_path13.join)(workPath, ".vercel", "python", "services", serviceName) : (0, import_path13.join)(workPath, ".vercel", "python");
|
|
9148
|
+
(0, import_fs13.mkdirSync)(vercelPythonDir, { recursive: true });
|
|
8893
9149
|
let qualifiedModule = modulePath;
|
|
8894
9150
|
let extraPythonPath;
|
|
8895
|
-
if ((0,
|
|
8896
|
-
const pkgName = (0,
|
|
9151
|
+
if ((0, import_fs13.existsSync)((0, import_path13.join)(workPath, "__init__.py"))) {
|
|
9152
|
+
const pkgName = (0, import_path13.basename)(workPath);
|
|
8897
9153
|
qualifiedModule = `${pkgName}.${modulePath}`;
|
|
8898
|
-
extraPythonPath = (0,
|
|
9154
|
+
extraPythonPath = (0, import_path13.dirname)(workPath);
|
|
8899
9155
|
}
|
|
8900
|
-
const entryAbs = (0,
|
|
8901
|
-
const shimPath = (0,
|
|
8902
|
-
const templatePath = (0,
|
|
9156
|
+
const entryAbs = (0, import_path13.join)(workPath, entry);
|
|
9157
|
+
const shimPath = (0, import_path13.join)(vercelPythonDir, `${DEV_SHIM_MODULE}.py`);
|
|
9158
|
+
const templatePath = (0, import_path13.join)(
|
|
8903
9159
|
__dirname,
|
|
8904
9160
|
"..",
|
|
8905
9161
|
"templates",
|
|
8906
9162
|
`${DEV_SHIM_MODULE}.py`
|
|
8907
9163
|
);
|
|
8908
|
-
const template = (0,
|
|
9164
|
+
const template = (0, import_fs13.readFileSync)(templatePath, "utf8");
|
|
8909
9165
|
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);
|
|
8910
|
-
(0,
|
|
8911
|
-
(0,
|
|
9166
|
+
(0, import_fs13.writeFileSync)(shimPath, shimSource, "utf8");
|
|
9167
|
+
(0, import_build_utils15.debug)(`Prepared Python dev shim at ${shimPath}`);
|
|
8912
9168
|
return {
|
|
8913
9169
|
module: DEV_SHIM_MODULE,
|
|
8914
9170
|
extraPythonPath,
|
|
8915
9171
|
shimDir: vercelPythonDir
|
|
8916
9172
|
};
|
|
8917
9173
|
} catch (err) {
|
|
8918
|
-
(0,
|
|
9174
|
+
(0, import_build_utils15.debug)(`Failed to prepare dev shim: ${err?.message || err}`);
|
|
8919
9175
|
return null;
|
|
8920
9176
|
}
|
|
8921
9177
|
}
|
|
8922
9178
|
async function getMultiServicePythonRunner(workPath, env, systemPython, uvPath) {
|
|
8923
|
-
const venvPath = (0,
|
|
9179
|
+
const venvPath = (0, import_path13.join)(workPath, ".venv");
|
|
8924
9180
|
const pendingCreation = PENDING_MANAGED_VENV_CREATIONS.get(venvPath);
|
|
8925
9181
|
if (pendingCreation) {
|
|
8926
9182
|
await pendingCreation;
|
|
8927
9183
|
}
|
|
8928
9184
|
const { pythonCmd, venvRoot } = useVirtualEnv(workPath, env, systemPython);
|
|
8929
9185
|
if (venvRoot) {
|
|
8930
|
-
(0,
|
|
9186
|
+
(0, import_build_utils15.debug)(`Using existing virtualenv at ${venvRoot} for multi-service dev`);
|
|
8931
9187
|
return { command: pythonCmd, args: [] };
|
|
8932
9188
|
}
|
|
8933
9189
|
await dedupePendingOperation(
|
|
@@ -8940,11 +9196,11 @@ async function getMultiServicePythonRunner(workPath, env, systemPython, uvPath)
|
|
|
8940
9196
|
quiet: true
|
|
8941
9197
|
})
|
|
8942
9198
|
);
|
|
8943
|
-
(0,
|
|
9199
|
+
(0, import_build_utils15.debug)(`Created virtualenv at ${venvPath} for multi-service dev`);
|
|
8944
9200
|
const pythonBin = getVenvPythonBin(venvPath);
|
|
8945
9201
|
const binDir = getVenvBinDir(venvPath);
|
|
8946
9202
|
env.VIRTUAL_ENV = venvPath;
|
|
8947
|
-
env.PATH = `${binDir}${
|
|
9203
|
+
env.PATH = `${binDir}${import_path13.delimiter}${env.PATH || ""}`;
|
|
8948
9204
|
return { command: pythonBin, args: [] };
|
|
8949
9205
|
}
|
|
8950
9206
|
var startDevServer = async (opts) => {
|
|
@@ -8992,6 +9248,7 @@ var startDevServer = async (opts) => {
|
|
|
8992
9248
|
const isPyprojectEntrypoint = entrypoint === "pyproject.toml";
|
|
8993
9249
|
let resolved;
|
|
8994
9250
|
const handlerFunction = typeof config?.handlerFunction === "string" ? config.handlerFunction : void 0;
|
|
9251
|
+
const isPyQueueSidecar = config?.pythonQueueSidecar === "subscriber" || config?.pythonQueueSidecar === "workflow";
|
|
8995
9252
|
let detected;
|
|
8996
9253
|
if (isPyprojectEntrypoint) {
|
|
8997
9254
|
const declaredEntrypoint = await getVercelToolsEntrypoint(
|
|
@@ -9007,7 +9264,7 @@ var startDevServer = async (opts) => {
|
|
|
9007
9264
|
filePath: entrypoint,
|
|
9008
9265
|
// Schedule-triggered services create their own "app" wrapper dynamically.
|
|
9009
9266
|
// Other services use handlerFunction as the entrypoint variable name.
|
|
9010
|
-
varName: service && (0,
|
|
9267
|
+
varName: service && (0, import_build_utils15.isScheduleTriggeredService)(service) ? void 0 : handlerFunction ?? (isPyQueueSidecar ? "app" : void 0)
|
|
9011
9268
|
} : void 0,
|
|
9012
9269
|
service,
|
|
9013
9270
|
opts.repoRootPath
|
|
@@ -9029,7 +9286,7 @@ var startDevServer = async (opts) => {
|
|
|
9029
9286
|
if (detected?.error) {
|
|
9030
9287
|
throw detected.error;
|
|
9031
9288
|
}
|
|
9032
|
-
throw new
|
|
9289
|
+
throw new import_build_utils15.NowBuildError({
|
|
9033
9290
|
code: isPyprojectEntrypoint ? "PYTHON_PYPROJECT_NOTHING_TO_BUILD" : "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
9034
9291
|
message: isPyprojectEntrypoint ? 'Entrypoint "pyproject.toml" does not declare a web app. Set "tool.vercel.entrypoint" in pyproject.toml.' : "No Python entrypoint could be detected. Please specify an entrypoint file."
|
|
9035
9292
|
});
|
|
@@ -9061,7 +9318,7 @@ var startDevServer = async (opts) => {
|
|
|
9061
9318
|
const yellow = "\x1B[33m";
|
|
9062
9319
|
const white = "\x1B[1m";
|
|
9063
9320
|
const reset = "\x1B[0m";
|
|
9064
|
-
throw new
|
|
9321
|
+
throw new import_build_utils15.NowBuildError({
|
|
9065
9322
|
code: "PYTHON_EXTERNAL_VENV_DETECTED",
|
|
9066
9323
|
message: `Detected activated venv at ${yellow}${venv}${reset}, ${white}vercel dev${reset} manages virtual environments automatically.
|
|
9067
9324
|
Run ${white}deactivate${reset} and try again.`
|
|
@@ -9078,11 +9335,11 @@ Run ${white}deactivate${reset} and try again.`
|
|
|
9078
9335
|
);
|
|
9079
9336
|
spawnCommand = runner.command;
|
|
9080
9337
|
spawnArgsPrefix = runner.args;
|
|
9081
|
-
(0,
|
|
9338
|
+
(0, import_build_utils15.debug)(
|
|
9082
9339
|
`Multi-service Python runner: ${spawnCommand} ${spawnArgsPrefix.join(" ")}`
|
|
9083
9340
|
);
|
|
9084
9341
|
} else if (venv) {
|
|
9085
|
-
(0,
|
|
9342
|
+
(0, import_build_utils15.debug)(`Running in virtualenv at ${venv}`);
|
|
9086
9343
|
} else {
|
|
9087
9344
|
const { pythonCmd: venvPythonCmd, venvRoot } = useVirtualEnv(
|
|
9088
9345
|
workPath,
|
|
@@ -9091,9 +9348,9 @@ Run ${white}deactivate${reset} and try again.`
|
|
|
9091
9348
|
);
|
|
9092
9349
|
spawnCommand = venvPythonCmd;
|
|
9093
9350
|
if (venvRoot) {
|
|
9094
|
-
(0,
|
|
9351
|
+
(0, import_build_utils15.debug)(`Using virtualenv at ${venvRoot}`);
|
|
9095
9352
|
} else {
|
|
9096
|
-
(0,
|
|
9353
|
+
(0, import_build_utils15.debug)("No virtualenv found");
|
|
9097
9354
|
try {
|
|
9098
9355
|
const yellow = "\x1B[33m";
|
|
9099
9356
|
const reset = "\x1B[0m";
|
|
@@ -9146,7 +9403,13 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
9146
9403
|
entrypointDir: workPath,
|
|
9147
9404
|
rootDir: workPath
|
|
9148
9405
|
});
|
|
9149
|
-
|
|
9406
|
+
const queueAdapterBootstrap = await getQueueAdapterBootstrap({
|
|
9407
|
+
pythonPackage,
|
|
9408
|
+
env,
|
|
9409
|
+
legacyWorkersProject: legacyProject,
|
|
9410
|
+
hasDeclaredSubscribers: await hasPyprojectSubscribers(workPath)
|
|
9411
|
+
});
|
|
9412
|
+
queueIntegrations = queueAdapterBootstrap.integrations;
|
|
9150
9413
|
if (queueIntegrations.length > 0) {
|
|
9151
9414
|
env.VERCEL_QUEUE_INTEGRATIONS = queueIntegrations.map(
|
|
9152
9415
|
({ module: module2, installer, servingActivator }) => `${module2}:${installer}` + (servingActivator ? `:${servingActivator}` : "")
|
|
@@ -9154,11 +9417,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
9154
9417
|
} else {
|
|
9155
9418
|
delete env.VERCEL_QUEUE_INTEGRATIONS;
|
|
9156
9419
|
}
|
|
9157
|
-
const
|
|
9158
|
-
pythonPackage,
|
|
9159
|
-
env
|
|
9160
|
-
});
|
|
9161
|
-
for (const injectedPackage of conditionalInjectedPackages) {
|
|
9420
|
+
for (const injectedPackage of queueAdapterBootstrap.injectedPackages) {
|
|
9162
9421
|
await installInjectedDevPackage(
|
|
9163
9422
|
{
|
|
9164
9423
|
name: injectedPackage.name,
|
|
@@ -9169,10 +9428,52 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
9169
9428
|
);
|
|
9170
9429
|
}
|
|
9171
9430
|
} catch (err) {
|
|
9172
|
-
(0,
|
|
9431
|
+
(0, import_build_utils15.debug)(
|
|
9173
9432
|
`Skipping conditional dev package injection: ${err instanceof Error ? err.message : String(err)}`
|
|
9174
9433
|
);
|
|
9175
9434
|
}
|
|
9435
|
+
const apschedulerSubscribers = [];
|
|
9436
|
+
if (!legacyProject) {
|
|
9437
|
+
const runtimeDir = (0, import_path13.join)(workPath, ".vercel", "python");
|
|
9438
|
+
const declaredSubscribers = await getPyprojectSubscribers(workPath);
|
|
9439
|
+
const introspectionEnv = {
|
|
9440
|
+
...env,
|
|
9441
|
+
PYTHONPATH: [runtimeDir, env.PYTHONPATH].filter(Boolean).join(import_path13.delimiter)
|
|
9442
|
+
};
|
|
9443
|
+
delete introspectionEnv.VERCEL_APSCHEDULER_SUBSCRIBERS;
|
|
9444
|
+
for (const declaration of declaredSubscribers) {
|
|
9445
|
+
const introspected = await introspectDevQueueSubscriptions({
|
|
9446
|
+
moduleName: declaration.moduleName,
|
|
9447
|
+
subscriberName: declaration.name,
|
|
9448
|
+
variableName: declaration.variableName || "app",
|
|
9449
|
+
pythonBin: spawnCommand,
|
|
9450
|
+
cwd: workPath,
|
|
9451
|
+
env: introspectionEnv,
|
|
9452
|
+
integrations: queueIntegrations
|
|
9453
|
+
});
|
|
9454
|
+
apschedulerSubscribers.push(
|
|
9455
|
+
...apschedulerSubscriberIdentities([
|
|
9456
|
+
{ ...declaration, owners: introspected?.owners ?? [] }
|
|
9457
|
+
])
|
|
9458
|
+
);
|
|
9459
|
+
}
|
|
9460
|
+
}
|
|
9461
|
+
if (apschedulerSubscribers.length > 0) {
|
|
9462
|
+
env.VERCEL_APSCHEDULER_SUBSCRIBERS = JSON.stringify(
|
|
9463
|
+
apschedulerSubscribers
|
|
9464
|
+
);
|
|
9465
|
+
const previewConfig = await getApschedulerPreviewConfig(workPath);
|
|
9466
|
+
if (previewConfig) {
|
|
9467
|
+
env.VERCEL_APSCHEDULER_PREVIEW_IDLE_TIMEOUT_SECONDS = String(
|
|
9468
|
+
previewConfig.idleTimeoutSeconds
|
|
9469
|
+
);
|
|
9470
|
+
} else {
|
|
9471
|
+
delete env.VERCEL_APSCHEDULER_PREVIEW_IDLE_TIMEOUT_SECONDS;
|
|
9472
|
+
}
|
|
9473
|
+
} else {
|
|
9474
|
+
delete env.VERCEL_APSCHEDULER_SUBSCRIBERS;
|
|
9475
|
+
delete env.VERCEL_APSCHEDULER_PREVIEW_IDLE_TIMEOUT_SECONDS;
|
|
9476
|
+
}
|
|
9176
9477
|
if (legacyProject) {
|
|
9177
9478
|
await installInjectedDevPackage(
|
|
9178
9479
|
{
|
|
@@ -9183,7 +9484,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
9183
9484
|
devOpts
|
|
9184
9485
|
);
|
|
9185
9486
|
}
|
|
9186
|
-
const queueSidecarKind = config?.pythonQueueSidecar === "subscriber" || config?.pythonQueueSidecar === "workflow" ? config.pythonQueueSidecar : service && (0,
|
|
9487
|
+
const queueSidecarKind = config?.pythonQueueSidecar === "subscriber" || config?.pythonQueueSidecar === "workflow" ? config.pythonQueueSidecar : service && (0, import_build_utils15.isQueueBackedService)(service) ? (0, import_build_utils15.isWorkflowTriggeredService)(service) ? "workflow" : "subscriber" : void 0;
|
|
9187
9488
|
let queueSubscriptions;
|
|
9188
9489
|
if (queueSidecarKind) {
|
|
9189
9490
|
let useQueueServing = !legacyProject;
|
|
@@ -9197,19 +9498,29 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
9197
9498
|
}
|
|
9198
9499
|
if (useQueueServing) {
|
|
9199
9500
|
env.VERCEL_DEV_QUEUE_SERVING = "1";
|
|
9200
|
-
const
|
|
9201
|
-
queueSubscriptions = await introspectDevQueueSubscriptions({
|
|
9501
|
+
const subscriberName = getModuleEntrypointName({
|
|
9202
9502
|
moduleName: modulePath,
|
|
9503
|
+
variableName: variableName || "app"
|
|
9504
|
+
});
|
|
9505
|
+
env.VERCEL_PYTHON_SUBSCRIBER_ID = subscriberName;
|
|
9506
|
+
const runtimeDir = (0, import_path13.join)(workPath, ".vercel", "python");
|
|
9507
|
+
const introspectionEnv = {
|
|
9508
|
+
...env,
|
|
9509
|
+
PYTHONPATH: [runtimeDir, env.PYTHONPATH].filter(Boolean).join(import_path13.delimiter)
|
|
9510
|
+
};
|
|
9511
|
+
delete introspectionEnv.VERCEL_APSCHEDULER_SUBSCRIBERS;
|
|
9512
|
+
queueSubscriptions = (await introspectDevQueueSubscriptions({
|
|
9513
|
+
moduleName: modulePath,
|
|
9514
|
+
subscriberName,
|
|
9515
|
+
variableName: variableName || "app",
|
|
9203
9516
|
pythonBin: spawnCommand,
|
|
9204
9517
|
cwd: workPath,
|
|
9205
|
-
env:
|
|
9206
|
-
...env,
|
|
9207
|
-
PYTHONPATH: [runtimeDir, env.PYTHONPATH].filter(Boolean).join(import_path12.delimiter)
|
|
9208
|
-
},
|
|
9518
|
+
env: introspectionEnv,
|
|
9209
9519
|
integrations: queueIntegrations
|
|
9210
|
-
});
|
|
9520
|
+
}))?.subscriptions;
|
|
9211
9521
|
} else {
|
|
9212
9522
|
delete env.VERCEL_DEV_QUEUE_SERVING;
|
|
9523
|
+
delete env.VERCEL_PYTHON_SUBSCRIBER_ID;
|
|
9213
9524
|
await installInjectedDevPackage(
|
|
9214
9525
|
{
|
|
9215
9526
|
name: "vercel-workers",
|
|
@@ -9235,7 +9546,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
9235
9546
|
const port = typeof meta.port === "number" ? meta.port : await (0, import_get_port.default)();
|
|
9236
9547
|
env.PORT = `${port}`;
|
|
9237
9548
|
if (entry) {
|
|
9238
|
-
env.__VC_HANDLER_ENTRYPOINT_ABS = (0,
|
|
9549
|
+
env.__VC_HANDLER_ENTRYPOINT_ABS = (0, import_path13.join)(workPath, entry);
|
|
9239
9550
|
}
|
|
9240
9551
|
const devShim = createDevShim(
|
|
9241
9552
|
workPath,
|
|
@@ -9246,8 +9557,8 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
9246
9557
|
variableName ?? ""
|
|
9247
9558
|
);
|
|
9248
9559
|
if (devShim) {
|
|
9249
|
-
const shimDir = devShim.shimDir || (0,
|
|
9250
|
-
const runtimeDir = (0,
|
|
9560
|
+
const shimDir = devShim.shimDir || (0, import_path13.join)(workPath, ".vercel", "python");
|
|
9561
|
+
const runtimeDir = (0, import_path13.join)(workPath, ".vercel", "python");
|
|
9251
9562
|
const pathParts = shimDir !== runtimeDir ? [shimDir, runtimeDir] : [shimDir];
|
|
9252
9563
|
if (devShim.extraPythonPath) {
|
|
9253
9564
|
pathParts.push(devShim.extraPythonPath);
|
|
@@ -9259,12 +9570,12 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
9259
9570
|
if (existingPythonPath) {
|
|
9260
9571
|
pathParts.push(existingPythonPath);
|
|
9261
9572
|
}
|
|
9262
|
-
env.PYTHONPATH = pathParts.join(
|
|
9573
|
+
env.PYTHONPATH = pathParts.join(import_path13.delimiter);
|
|
9263
9574
|
}
|
|
9264
9575
|
const moduleToRun = devShim?.module || modulePath;
|
|
9265
9576
|
const pythonArgs = ["-u", "-m", moduleToRun];
|
|
9266
9577
|
const argv = [...spawnArgsPrefix, ...pythonArgs];
|
|
9267
|
-
(0,
|
|
9578
|
+
(0, import_build_utils15.debug)(
|
|
9268
9579
|
`Starting Python dev server (${framework}): ${spawnCommand} ${argv.join(" ")} [PORT=${port}]`
|
|
9269
9580
|
);
|
|
9270
9581
|
if (process.stdout.columns) {
|
|
@@ -9318,7 +9629,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
9318
9629
|
};
|
|
9319
9630
|
|
|
9320
9631
|
// src/quirks/index.ts
|
|
9321
|
-
var
|
|
9632
|
+
var import_build_utils18 = require("@vercel/build-utils");
|
|
9322
9633
|
var import_python_analysis10 = require("@vercel/python-analysis");
|
|
9323
9634
|
|
|
9324
9635
|
// src/quirks/matplotlib.ts
|
|
@@ -9332,9 +9643,9 @@ var matplotlibQuirk = {
|
|
|
9332
9643
|
};
|
|
9333
9644
|
|
|
9334
9645
|
// src/quirks/litellm.ts
|
|
9335
|
-
var
|
|
9336
|
-
var
|
|
9337
|
-
var
|
|
9646
|
+
var import_fs14 = __toESM(require("fs"));
|
|
9647
|
+
var import_path14 = require("path");
|
|
9648
|
+
var import_build_utils16 = require("@vercel/build-utils");
|
|
9338
9649
|
var LAMBDA_ROOT = "/var/task";
|
|
9339
9650
|
var CONFIG_CANDIDATES = [
|
|
9340
9651
|
"litellm_config.yaml",
|
|
@@ -9344,9 +9655,9 @@ var CONFIG_CANDIDATES = [
|
|
|
9344
9655
|
];
|
|
9345
9656
|
async function findConfigFile(workPath) {
|
|
9346
9657
|
for (const name of CONFIG_CANDIDATES) {
|
|
9347
|
-
const candidate = (0,
|
|
9658
|
+
const candidate = (0, import_path14.join)(workPath, name);
|
|
9348
9659
|
try {
|
|
9349
|
-
await
|
|
9660
|
+
await import_fs14.default.promises.access(candidate);
|
|
9350
9661
|
return name;
|
|
9351
9662
|
} catch {
|
|
9352
9663
|
}
|
|
@@ -9361,32 +9672,32 @@ var litellmQuirk = {
|
|
|
9361
9672
|
const env = {};
|
|
9362
9673
|
const sitePackagesDirs = await getVenvSitePackagesDirs(ctx.venvPath);
|
|
9363
9674
|
for (const sitePackages of sitePackagesDirs) {
|
|
9364
|
-
const schemaPath = (0,
|
|
9675
|
+
const schemaPath = (0, import_path14.join)(
|
|
9365
9676
|
sitePackages,
|
|
9366
9677
|
"litellm",
|
|
9367
9678
|
"proxy",
|
|
9368
9679
|
"schema.prisma"
|
|
9369
9680
|
);
|
|
9370
9681
|
try {
|
|
9371
|
-
await
|
|
9372
|
-
(0,
|
|
9682
|
+
await import_fs14.default.promises.access(schemaPath);
|
|
9683
|
+
(0, import_build_utils16.debug)(`LiteLLM quirk: found schema at ${schemaPath}`);
|
|
9373
9684
|
buildEnv.PRISMA_SCHEMA_PATH = schemaPath;
|
|
9374
9685
|
break;
|
|
9375
9686
|
} catch {
|
|
9376
9687
|
}
|
|
9377
9688
|
}
|
|
9378
9689
|
if (!buildEnv.PRISMA_SCHEMA_PATH) {
|
|
9379
|
-
(0,
|
|
9690
|
+
(0, import_build_utils16.debug)("LiteLLM quirk: schema.prisma not found in any site-packages");
|
|
9380
9691
|
}
|
|
9381
9692
|
if (!process.env.CONFIG_FILE_PATH) {
|
|
9382
9693
|
const configName = await findConfigFile(ctx.workPath);
|
|
9383
9694
|
if (configName) {
|
|
9384
|
-
(0,
|
|
9385
|
-
buildEnv.CONFIG_FILE_PATH = (0,
|
|
9386
|
-
env.CONFIG_FILE_PATH = (0,
|
|
9695
|
+
(0, import_build_utils16.debug)(`LiteLLM quirk: found config at ${configName}`);
|
|
9696
|
+
buildEnv.CONFIG_FILE_PATH = (0, import_path14.join)(ctx.workPath, configName);
|
|
9697
|
+
env.CONFIG_FILE_PATH = (0, import_path14.join)(LAMBDA_ROOT, configName);
|
|
9387
9698
|
}
|
|
9388
9699
|
} else {
|
|
9389
|
-
(0,
|
|
9700
|
+
(0, import_build_utils16.debug)(
|
|
9390
9701
|
`LiteLLM quirk: CONFIG_FILE_PATH already set to ${process.env.CONFIG_FILE_PATH}`
|
|
9391
9702
|
);
|
|
9392
9703
|
}
|
|
@@ -9395,10 +9706,10 @@ var litellmQuirk = {
|
|
|
9395
9706
|
};
|
|
9396
9707
|
|
|
9397
9708
|
// src/quirks/prisma.ts
|
|
9398
|
-
var
|
|
9399
|
-
var
|
|
9709
|
+
var import_fs15 = __toESM(require("fs"));
|
|
9710
|
+
var import_path15 = require("path");
|
|
9400
9711
|
var import_execa7 = __toESM(require_execa());
|
|
9401
|
-
var
|
|
9712
|
+
var import_build_utils17 = require("@vercel/build-utils");
|
|
9402
9713
|
var import_python_analysis9 = require("@vercel/python-analysis");
|
|
9403
9714
|
function execErrorMessage(err) {
|
|
9404
9715
|
if (err != null && typeof err === "object" && "stderr" in err) {
|
|
@@ -9436,22 +9747,22 @@ model DummyModel {
|
|
|
9436
9747
|
async function findUserSchema(workPath) {
|
|
9437
9748
|
const envPath = process.env.PRISMA_SCHEMA_PATH;
|
|
9438
9749
|
if (envPath) {
|
|
9439
|
-
const resolved = (0,
|
|
9750
|
+
const resolved = (0, import_path15.isAbsolute)(envPath) ? envPath : (0, import_path15.join)(workPath, envPath);
|
|
9440
9751
|
try {
|
|
9441
|
-
await
|
|
9752
|
+
await import_fs15.default.promises.access(resolved);
|
|
9442
9753
|
return resolved;
|
|
9443
9754
|
} catch {
|
|
9444
|
-
(0,
|
|
9755
|
+
(0, import_build_utils17.debug)(`PRISMA_SCHEMA_PATH=${envPath} not found at ${resolved}`);
|
|
9445
9756
|
return null;
|
|
9446
9757
|
}
|
|
9447
9758
|
}
|
|
9448
9759
|
const candidates = [
|
|
9449
|
-
(0,
|
|
9450
|
-
(0,
|
|
9760
|
+
(0, import_path15.join)(workPath, "schema.prisma"),
|
|
9761
|
+
(0, import_path15.join)(workPath, "prisma", "schema.prisma")
|
|
9451
9762
|
];
|
|
9452
9763
|
for (const candidate of candidates) {
|
|
9453
9764
|
try {
|
|
9454
|
-
await
|
|
9765
|
+
await import_fs15.default.promises.access(candidate);
|
|
9455
9766
|
return candidate;
|
|
9456
9767
|
} catch {
|
|
9457
9768
|
}
|
|
@@ -9462,32 +9773,32 @@ async function collectFiles(dir, base) {
|
|
|
9462
9773
|
const result = [];
|
|
9463
9774
|
let entries;
|
|
9464
9775
|
try {
|
|
9465
|
-
entries = await
|
|
9776
|
+
entries = await import_fs15.default.promises.readdir(dir, { withFileTypes: true });
|
|
9466
9777
|
} catch {
|
|
9467
9778
|
return result;
|
|
9468
9779
|
}
|
|
9469
9780
|
for (const entry of entries) {
|
|
9470
9781
|
if (entry.name === "__pycache__")
|
|
9471
9782
|
continue;
|
|
9472
|
-
const full = (0,
|
|
9783
|
+
const full = (0, import_path15.join)(dir, entry.name);
|
|
9473
9784
|
if (entry.isDirectory()) {
|
|
9474
9785
|
result.push(...await collectFiles(full, base));
|
|
9475
9786
|
} else {
|
|
9476
|
-
result.push((0,
|
|
9787
|
+
result.push((0, import_path15.relative)(base, full));
|
|
9477
9788
|
}
|
|
9478
9789
|
}
|
|
9479
9790
|
return result;
|
|
9480
9791
|
}
|
|
9481
9792
|
async function cleanCacheArtifacts(cacheDir, extras = []) {
|
|
9482
9793
|
const paths = [
|
|
9483
|
-
(0,
|
|
9484
|
-
(0,
|
|
9485
|
-
(0,
|
|
9794
|
+
(0, import_path15.join)(cacheDir, "node_modules"),
|
|
9795
|
+
(0, import_path15.join)(cacheDir, "package.json"),
|
|
9796
|
+
(0, import_path15.join)(cacheDir, "package-lock.json"),
|
|
9486
9797
|
...extras
|
|
9487
9798
|
];
|
|
9488
9799
|
for (const p of paths) {
|
|
9489
9800
|
try {
|
|
9490
|
-
await
|
|
9801
|
+
await import_fs15.default.promises.rm(p, { recursive: true, force: true });
|
|
9491
9802
|
} catch (err) {
|
|
9492
9803
|
console.warn(
|
|
9493
9804
|
`could not clean up ${p}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -9511,7 +9822,7 @@ var prismaQuirk = {
|
|
|
9511
9822
|
async run(ctx) {
|
|
9512
9823
|
const { venvPath, pythonEnv, workPath } = ctx;
|
|
9513
9824
|
const pythonPath = getVenvPythonBin(venvPath);
|
|
9514
|
-
const runtimeCacheDir = (0,
|
|
9825
|
+
const runtimeCacheDir = (0, import_path15.join)(
|
|
9515
9826
|
LAMBDA_ROOT2,
|
|
9516
9827
|
resolveVendorDir(),
|
|
9517
9828
|
"prisma",
|
|
@@ -9521,7 +9832,7 @@ var prismaQuirk = {
|
|
|
9521
9832
|
let sitePackages;
|
|
9522
9833
|
for (const dir of sitePackagesDirs) {
|
|
9523
9834
|
try {
|
|
9524
|
-
await
|
|
9835
|
+
await import_fs15.default.promises.access((0, import_path15.join)(dir, "prisma"));
|
|
9525
9836
|
sitePackages = dir;
|
|
9526
9837
|
break;
|
|
9527
9838
|
} catch {
|
|
@@ -9533,19 +9844,19 @@ var prismaQuirk = {
|
|
|
9533
9844
|
);
|
|
9534
9845
|
return {};
|
|
9535
9846
|
}
|
|
9536
|
-
const cacheDir = (0,
|
|
9537
|
-
await
|
|
9847
|
+
const cacheDir = (0, import_path15.join)(sitePackages, "prisma", "__bincache__");
|
|
9848
|
+
await import_fs15.default.promises.mkdir(cacheDir, { recursive: true });
|
|
9538
9849
|
const generateEnv = {
|
|
9539
9850
|
...pythonEnv,
|
|
9540
9851
|
PRISMA_BINARY_CACHE_DIR: cacheDir
|
|
9541
9852
|
};
|
|
9542
|
-
const generatedDir = (0,
|
|
9543
|
-
const dummySchemaPath = (0,
|
|
9544
|
-
await
|
|
9853
|
+
const generatedDir = (0, import_path15.join)(workPath, "_prisma_generated");
|
|
9854
|
+
const dummySchemaPath = (0, import_path15.join)(workPath, DUMMY_SCHEMA_NAME);
|
|
9855
|
+
await import_fs15.default.promises.writeFile(
|
|
9545
9856
|
dummySchemaPath,
|
|
9546
9857
|
buildDummySchema(generatedDir)
|
|
9547
9858
|
);
|
|
9548
|
-
(0,
|
|
9859
|
+
(0, import_build_utils17.debug)(`Running prisma generate (dummy) with cache dir: ${cacheDir}`);
|
|
9549
9860
|
try {
|
|
9550
9861
|
const dummyResult = await (0, import_execa7.default)(
|
|
9551
9862
|
pythonPath,
|
|
@@ -9557,11 +9868,11 @@ var prismaQuirk = {
|
|
|
9557
9868
|
}
|
|
9558
9869
|
);
|
|
9559
9870
|
if (dummyResult.stdout)
|
|
9560
|
-
(0,
|
|
9871
|
+
(0, import_build_utils17.debug)(`prisma generate (dummy) stdout: ${dummyResult.stdout}`);
|
|
9561
9872
|
if (dummyResult.stderr)
|
|
9562
|
-
(0,
|
|
9873
|
+
(0, import_build_utils17.debug)(`prisma generate (dummy) stderr: ${dummyResult.stderr}`);
|
|
9563
9874
|
} catch (err) {
|
|
9564
|
-
throw new
|
|
9875
|
+
throw new import_build_utils17.NowBuildError({
|
|
9565
9876
|
code: "PRISMA_GENERATE_FAILED",
|
|
9566
9877
|
message: `Prisma engine download failed during \`prisma generate\`. Check that your prisma version is compatible with this Python version.
|
|
9567
9878
|
` + execErrorMessage(err)
|
|
@@ -9569,47 +9880,47 @@ var prismaQuirk = {
|
|
|
9569
9880
|
}
|
|
9570
9881
|
const srcBinaryPrefix = `query-engine-${getLambdaBinaryTarget()}`;
|
|
9571
9882
|
const runtimeName = `prisma-query-engine-rhel-openssl-${RUNTIME_OPENSSL_VERSION}.x`;
|
|
9572
|
-
const nodeModulesDir = (0,
|
|
9883
|
+
const nodeModulesDir = (0, import_path15.join)(cacheDir, "node_modules", "prisma");
|
|
9573
9884
|
let engineCopied = false;
|
|
9574
9885
|
try {
|
|
9575
|
-
const entries = await
|
|
9886
|
+
const entries = await import_fs15.default.promises.readdir(nodeModulesDir);
|
|
9576
9887
|
for (const entry of entries) {
|
|
9577
9888
|
if (!entry.startsWith(srcBinaryPrefix))
|
|
9578
9889
|
continue;
|
|
9579
|
-
const srcPath = (0,
|
|
9580
|
-
const destPath = (0,
|
|
9890
|
+
const srcPath = (0, import_path15.join)(nodeModulesDir, entry);
|
|
9891
|
+
const destPath = (0, import_path15.join)(cacheDir, runtimeName);
|
|
9581
9892
|
try {
|
|
9582
|
-
await
|
|
9583
|
-
(0,
|
|
9893
|
+
await import_fs15.default.promises.access(destPath);
|
|
9894
|
+
(0, import_build_utils17.debug)(`Engine binary: ${runtimeName} already exists, skipping`);
|
|
9584
9895
|
} catch {
|
|
9585
|
-
(0,
|
|
9586
|
-
await
|
|
9896
|
+
(0, import_build_utils17.debug)(`Engine binary: copying ${entry} -> ${runtimeName}`);
|
|
9897
|
+
await import_fs15.default.promises.copyFile(srcPath, destPath);
|
|
9587
9898
|
}
|
|
9588
9899
|
engineCopied = true;
|
|
9589
9900
|
}
|
|
9590
9901
|
} catch (err) {
|
|
9591
|
-
throw new
|
|
9902
|
+
throw new import_build_utils17.NowBuildError({
|
|
9592
9903
|
code: "PRISMA_ENGINE_NOT_FOUND",
|
|
9593
9904
|
message: `could not read Prisma engine directory "${nodeModulesDir}". This may indicate an incompatible prisma version.
|
|
9594
9905
|
` + (err instanceof Error ? err.message : String(err))
|
|
9595
9906
|
});
|
|
9596
9907
|
}
|
|
9597
9908
|
if (!engineCopied) {
|
|
9598
|
-
throw new
|
|
9909
|
+
throw new import_build_utils17.NowBuildError({
|
|
9599
9910
|
code: "PRISMA_ENGINE_NOT_FOUND",
|
|
9600
9911
|
message: `could not find engine binary matching "${srcBinaryPrefix}*" in "${nodeModulesDir}". This may indicate an incompatible prisma version or an unsupported platform (${process.arch}).`
|
|
9601
9912
|
});
|
|
9602
9913
|
}
|
|
9603
|
-
const shimPath = (0,
|
|
9604
|
-
await
|
|
9914
|
+
const shimPath = (0, import_path15.join)(cacheDir, "openssl");
|
|
9915
|
+
await import_fs15.default.promises.writeFile(
|
|
9605
9916
|
shimPath,
|
|
9606
9917
|
`#!/bin/sh
|
|
9607
9918
|
echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIME_OPENSSL_VERSION}.0)"
|
|
9608
9919
|
`
|
|
9609
9920
|
);
|
|
9610
|
-
await
|
|
9921
|
+
await import_fs15.default.promises.chmod(shimPath, 493);
|
|
9611
9922
|
for (const p of [generatedDir, dummySchemaPath]) {
|
|
9612
|
-
await
|
|
9923
|
+
await import_fs15.default.promises.rm(p, { recursive: true, force: true });
|
|
9613
9924
|
}
|
|
9614
9925
|
await cleanCacheArtifacts(cacheDir);
|
|
9615
9926
|
const generateMode = (process.env.VERCEL_PRISMA_GENERATE_CLIENT ?? "auto").toLowerCase();
|
|
@@ -9622,14 +9933,14 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
|
|
|
9622
9933
|
pythonEnv
|
|
9623
9934
|
);
|
|
9624
9935
|
if (clientAlreadyGenerated) {
|
|
9625
|
-
(0,
|
|
9936
|
+
(0, import_build_utils17.debug)(
|
|
9626
9937
|
"Prisma quirk: client already generated, skipping user schema generate"
|
|
9627
9938
|
);
|
|
9628
9939
|
shouldGenerate = false;
|
|
9629
9940
|
}
|
|
9630
9941
|
}
|
|
9631
9942
|
if (shouldGenerate) {
|
|
9632
|
-
(0,
|
|
9943
|
+
(0, import_build_utils17.debug)(`Running prisma generate with user schema: ${userSchema}`);
|
|
9633
9944
|
try {
|
|
9634
9945
|
const userResult = await (0, import_execa7.default)(
|
|
9635
9946
|
pythonPath,
|
|
@@ -9641,11 +9952,11 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
|
|
|
9641
9952
|
}
|
|
9642
9953
|
);
|
|
9643
9954
|
if (userResult.stdout)
|
|
9644
|
-
(0,
|
|
9955
|
+
(0, import_build_utils17.debug)(`prisma generate stdout: ${userResult.stdout}`);
|
|
9645
9956
|
if (userResult.stderr)
|
|
9646
|
-
(0,
|
|
9957
|
+
(0, import_build_utils17.debug)(`prisma generate stderr: ${userResult.stderr}`);
|
|
9647
9958
|
} catch (err) {
|
|
9648
|
-
throw new
|
|
9959
|
+
throw new import_build_utils17.NowBuildError({
|
|
9649
9960
|
code: "PRISMA_GENERATE_FAILED",
|
|
9650
9961
|
message: `\`prisma generate\` failed for schema "${userSchema}".
|
|
9651
9962
|
` + execErrorMessage(err)
|
|
@@ -9656,12 +9967,12 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
|
|
|
9656
9967
|
}
|
|
9657
9968
|
try {
|
|
9658
9969
|
const allFiles = await collectFiles(
|
|
9659
|
-
(0,
|
|
9970
|
+
(0, import_path15.join)(sitePackages, "prisma"),
|
|
9660
9971
|
sitePackages
|
|
9661
9972
|
);
|
|
9662
9973
|
const count = await (0, import_python_analysis9.extendDistRecord)(sitePackages, "prisma", allFiles);
|
|
9663
9974
|
if (count > 0) {
|
|
9664
|
-
(0,
|
|
9975
|
+
(0, import_build_utils17.debug)(`Appended ${count} entries to prisma RECORD`);
|
|
9665
9976
|
}
|
|
9666
9977
|
} catch (err) {
|
|
9667
9978
|
console.warn(
|
|
@@ -9755,13 +10066,13 @@ async function runQuirks(ctx) {
|
|
|
9755
10066
|
(0, import_python_analysis10.normalizePackageName)(quirk.dependency)
|
|
9756
10067
|
);
|
|
9757
10068
|
if (!installed) {
|
|
9758
|
-
(0,
|
|
10069
|
+
(0, import_build_utils18.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
|
|
9759
10070
|
}
|
|
9760
10071
|
return installed;
|
|
9761
10072
|
});
|
|
9762
10073
|
const sorted = toposortQuirks(activated);
|
|
9763
10074
|
for (const quirk of sorted) {
|
|
9764
|
-
(0,
|
|
10075
|
+
(0, import_build_utils18.debug)(`Quirk "${quirk.dependency}": detected, running fix-up`);
|
|
9765
10076
|
const result = await quirk.run(ctx);
|
|
9766
10077
|
if (result.env) {
|
|
9767
10078
|
Object.assign(mergedEnv, result.env);
|
|
@@ -9782,12 +10093,12 @@ async function runQuirks(ctx) {
|
|
|
9782
10093
|
}
|
|
9783
10094
|
|
|
9784
10095
|
// src/django.ts
|
|
9785
|
-
var
|
|
9786
|
-
var
|
|
10096
|
+
var import_fs16 = __toESM(require("fs"));
|
|
10097
|
+
var import_path16 = require("path");
|
|
9787
10098
|
var import_execa8 = __toESM(require_execa());
|
|
9788
|
-
var
|
|
9789
|
-
var scriptPath2 = (0,
|
|
9790
|
-
var script2 =
|
|
10099
|
+
var import_build_utils19 = require("@vercel/build-utils");
|
|
10100
|
+
var scriptPath2 = (0, import_path16.join)(__dirname, "..", "templates", "vc_django_settings.py");
|
|
10101
|
+
var script2 = import_fs16.default.readFileSync(scriptPath2, "utf-8");
|
|
9791
10102
|
async function getDjangoSettings(projectDir, env) {
|
|
9792
10103
|
const { stdout } = await (0, import_execa8.default)("python", ["-c", script2], {
|
|
9793
10104
|
env,
|
|
@@ -9815,10 +10126,10 @@ async function runDjangoCollectStatic(venvPath, workPath, djangoPath, env, outpu
|
|
|
9815
10126
|
const installedApps = djangoSettings["INSTALLED_APPS"] ?? [];
|
|
9816
10127
|
const staticfilesDirs = djangoSettings["STATICFILES_DIRS"] ?? [];
|
|
9817
10128
|
const staticSourceDirs = [
|
|
9818
|
-
...installedApps.map((app) => (0,
|
|
10129
|
+
...installedApps.map((app) => (0, import_path16.join)(djangoPath, ...app.split("."), "static")),
|
|
9819
10130
|
// TODO: Deal with optional prefixes in STATICFILES_DIRS.
|
|
9820
10131
|
...staticfilesDirs.map((d) => Array.isArray(d) ? d[1] : d)
|
|
9821
|
-
].filter((d) =>
|
|
10132
|
+
].filter((d) => import_fs16.default.existsSync(d));
|
|
9822
10133
|
if (storageBackend.startsWith("storages.backends.")) {
|
|
9823
10134
|
console.log(
|
|
9824
10135
|
"django-storages detected \u2014 running collectstatic with original settings"
|
|
@@ -9829,7 +10140,7 @@ async function runDjangoCollectStatic(venvPath, workPath, djangoPath, env, outpu
|
|
|
9829
10140
|
});
|
|
9830
10141
|
return {
|
|
9831
10142
|
staticSourceDirs,
|
|
9832
|
-
staticRoot: staticRoot ? (0,
|
|
10143
|
+
staticRoot: staticRoot ? (0, import_path16.resolve)(djangoPath, staticRoot) : null,
|
|
9833
10144
|
cdnOutputDir: null,
|
|
9834
10145
|
manifestRelPath: null
|
|
9835
10146
|
};
|
|
@@ -9841,9 +10152,9 @@ async function runDjangoCollectStatic(venvPath, workPath, djangoPath, env, outpu
|
|
|
9841
10152
|
return null;
|
|
9842
10153
|
}
|
|
9843
10154
|
const staticUrlPath = staticUrl.replace(/^\/|\/$/g, "") || "static";
|
|
9844
|
-
const staticOutputDir = (0,
|
|
9845
|
-
await
|
|
9846
|
-
const shimPath = (0,
|
|
10155
|
+
const staticOutputDir = (0, import_path16.join)(outputStaticDir, staticUrlPath);
|
|
10156
|
+
await import_fs16.default.promises.mkdir(staticOutputDir, { recursive: true });
|
|
10157
|
+
const shimPath = (0, import_path16.join)(djangoPath, "_vercel_collectstatic_settings.py");
|
|
9847
10158
|
const shimLines = [
|
|
9848
10159
|
`from ${settingsModule} import *`,
|
|
9849
10160
|
`STATIC_ROOT = ${JSON.stringify(staticOutputDir)}`
|
|
@@ -9851,7 +10162,7 @@ async function runDjangoCollectStatic(venvPath, workPath, djangoPath, env, outpu
|
|
|
9851
10162
|
if (whitenoiseUseFinders) {
|
|
9852
10163
|
shimLines.push(`WHITENOISE_USE_FINDERS = False`);
|
|
9853
10164
|
}
|
|
9854
|
-
await
|
|
10165
|
+
await import_fs16.default.promises.writeFile(shimPath, shimLines.join("\n") + "\n");
|
|
9855
10166
|
try {
|
|
9856
10167
|
console.log("Running collectstatic...");
|
|
9857
10168
|
await (0, import_execa8.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
|
|
@@ -9862,7 +10173,7 @@ async function runDjangoCollectStatic(venvPath, workPath, djangoPath, env, outpu
|
|
|
9862
10173
|
cwd: djangoPath
|
|
9863
10174
|
});
|
|
9864
10175
|
} finally {
|
|
9865
|
-
await
|
|
10176
|
+
await import_fs16.default.promises.unlink(shimPath).catch(() => {
|
|
9866
10177
|
});
|
|
9867
10178
|
}
|
|
9868
10179
|
const MANIFEST_STORAGE_BACKENDS = [
|
|
@@ -9871,38 +10182,38 @@ async function runDjangoCollectStatic(venvPath, workPath, djangoPath, env, outpu
|
|
|
9871
10182
|
];
|
|
9872
10183
|
let manifestRelPath = null;
|
|
9873
10184
|
if (MANIFEST_STORAGE_BACKENDS.includes(storageBackend) && staticRoot) {
|
|
9874
|
-
const manifestSrc = (0,
|
|
9875
|
-
const resolvedStaticRoot = (0,
|
|
9876
|
-
const manifestDest = (0,
|
|
9877
|
-
await
|
|
9878
|
-
await
|
|
9879
|
-
manifestRelPath = (0,
|
|
9880
|
-
(0,
|
|
10185
|
+
const manifestSrc = (0, import_path16.join)(staticOutputDir, "staticfiles.json");
|
|
10186
|
+
const resolvedStaticRoot = (0, import_path16.resolve)(djangoPath, staticRoot);
|
|
10187
|
+
const manifestDest = (0, import_path16.join)(resolvedStaticRoot, "staticfiles.json");
|
|
10188
|
+
await import_fs16.default.promises.mkdir(resolvedStaticRoot, { recursive: true });
|
|
10189
|
+
await import_fs16.default.promises.copyFile(manifestSrc, manifestDest);
|
|
10190
|
+
manifestRelPath = (0, import_path16.relative)(workPath, manifestDest);
|
|
10191
|
+
(0, import_build_utils19.debug)(`Copied staticfiles.json to ${manifestDest} for Lambda bundle`);
|
|
9881
10192
|
}
|
|
9882
10193
|
return {
|
|
9883
10194
|
staticSourceDirs,
|
|
9884
|
-
staticRoot: staticRoot ? (0,
|
|
10195
|
+
staticRoot: staticRoot ? (0, import_path16.resolve)(djangoPath, staticRoot) : null,
|
|
9885
10196
|
cdnOutputDir: outputStaticDir,
|
|
9886
10197
|
manifestRelPath
|
|
9887
10198
|
};
|
|
9888
10199
|
}
|
|
9889
10200
|
|
|
9890
10201
|
// src/fastapi.ts
|
|
9891
|
-
var
|
|
9892
|
-
var
|
|
10202
|
+
var import_fs17 = __toESM(require("fs"));
|
|
10203
|
+
var import_path17 = require("path");
|
|
9893
10204
|
var import_execa9 = __toESM(require_execa());
|
|
9894
|
-
var
|
|
9895
|
-
var scriptPath3 = (0,
|
|
10205
|
+
var import_build_utils20 = require("@vercel/build-utils");
|
|
10206
|
+
var scriptPath3 = (0, import_path17.join)(__dirname, "..", "templates", "vc_fastapi_static.py");
|
|
9896
10207
|
var _STATIC_FILE_COLLECTION_ERROR_MESSAGE = "Warning: FastAPI static file collection failed. Static files will not be served from the CDN.";
|
|
9897
10208
|
async function getFastAPIStaticMounts(venvPath, entrypointAbs, variableName, env, workPath) {
|
|
9898
10209
|
const pythonPath = getVenvPythonBin(venvPath);
|
|
9899
|
-
const outputPath = (0,
|
|
10210
|
+
const outputPath = (0, import_path17.join)(
|
|
9900
10211
|
workPath,
|
|
9901
10212
|
".vercel",
|
|
9902
10213
|
"python",
|
|
9903
10214
|
"vc_fastapi_static_output.json"
|
|
9904
10215
|
);
|
|
9905
|
-
await
|
|
10216
|
+
await import_fs17.default.promises.mkdir((0, import_path17.join)(workPath, ".vercel", "python"), {
|
|
9906
10217
|
recursive: true
|
|
9907
10218
|
});
|
|
9908
10219
|
try {
|
|
@@ -9912,27 +10223,27 @@ async function getFastAPIStaticMounts(venvPath, entrypointAbs, variableName, env
|
|
|
9912
10223
|
{ env, cwd: workPath }
|
|
9913
10224
|
);
|
|
9914
10225
|
if (stderr) {
|
|
9915
|
-
(0,
|
|
10226
|
+
(0, import_build_utils20.debug)(`FastAPI shim stderr:
|
|
9916
10227
|
${stderr}`);
|
|
9917
10228
|
}
|
|
9918
10229
|
} catch (err) {
|
|
9919
10230
|
console.error(_STATIC_FILE_COLLECTION_ERROR_MESSAGE);
|
|
9920
|
-
(0,
|
|
10231
|
+
(0, import_build_utils20.debug)(
|
|
9921
10232
|
`FastAPI: could not discover static mounts: ${err?.stderr ?? err?.message ?? err}`
|
|
9922
10233
|
);
|
|
9923
10234
|
return [];
|
|
9924
10235
|
}
|
|
9925
10236
|
try {
|
|
9926
|
-
const raw = await
|
|
10237
|
+
const raw = await import_fs17.default.promises.readFile(outputPath, "utf8");
|
|
9927
10238
|
const parsed = JSON.parse(raw);
|
|
9928
|
-
(0,
|
|
10239
|
+
(0, import_build_utils20.debug)(`FastAPI: discovered mounts: ${JSON.stringify(parsed)}`);
|
|
9929
10240
|
return parsed;
|
|
9930
10241
|
} catch {
|
|
9931
10242
|
console.error(_STATIC_FILE_COLLECTION_ERROR_MESSAGE);
|
|
9932
|
-
(0,
|
|
10243
|
+
(0, import_build_utils20.debug)(`FastAPI: could not read shim output file: ${outputPath}`);
|
|
9933
10244
|
return [];
|
|
9934
10245
|
} finally {
|
|
9935
|
-
await
|
|
10246
|
+
await import_fs17.default.promises.rm(outputPath, { force: true });
|
|
9936
10247
|
}
|
|
9937
10248
|
}
|
|
9938
10249
|
async function runFastAPICollectStatic(venvPath, workPath, env, outputStaticDir, entrypointAbs, variableName) {
|
|
@@ -9944,18 +10255,18 @@ async function runFastAPICollectStatic(venvPath, workPath, env, outputStaticDir,
|
|
|
9944
10255
|
workPath
|
|
9945
10256
|
);
|
|
9946
10257
|
if (mounts.length === 0) {
|
|
9947
|
-
(0,
|
|
10258
|
+
(0, import_build_utils20.debug)("FastAPI: no StaticFiles mounts found, skipping");
|
|
9948
10259
|
return null;
|
|
9949
10260
|
}
|
|
9950
|
-
(0,
|
|
10261
|
+
(0, import_build_utils20.debug)(
|
|
9951
10262
|
`Found ${mounts.length} FastAPI static mount(s): ${mounts.map((m) => m.urlPath).join(", ")}`
|
|
9952
10263
|
);
|
|
9953
10264
|
for (const mount of mounts) {
|
|
9954
10265
|
const urlSubPath = mount.urlPath.replace(/^\/|\/$/g, "");
|
|
9955
|
-
const dest = (0,
|
|
9956
|
-
await
|
|
9957
|
-
await
|
|
9958
|
-
(0,
|
|
10266
|
+
const dest = (0, import_path17.join)(outputStaticDir, urlSubPath);
|
|
10267
|
+
await import_fs17.default.promises.mkdir(dest, { recursive: true });
|
|
10268
|
+
await import_fs17.default.promises.cp(mount.directory, dest, { recursive: true });
|
|
10269
|
+
(0, import_build_utils20.debug)(`copied ${mount.directory} -> ${dest}`);
|
|
9959
10270
|
}
|
|
9960
10271
|
return {
|
|
9961
10272
|
collectedMounts: mounts.map((m) => m.urlPath),
|
|
@@ -10011,10 +10322,10 @@ function fillBytecodeWithinCapacity(files, rankedItems, capacity) {
|
|
|
10011
10322
|
|
|
10012
10323
|
// src/compileall.ts
|
|
10013
10324
|
var import_execa10 = __toESM(require_execa());
|
|
10014
|
-
var
|
|
10015
|
-
var
|
|
10325
|
+
var import_build_utils21 = require("@vercel/build-utils");
|
|
10326
|
+
var import_fs18 = __toESM(require("fs"));
|
|
10016
10327
|
var import_os3 = require("os");
|
|
10017
|
-
var
|
|
10328
|
+
var import_path18 = require("path");
|
|
10018
10329
|
var COMPILEALL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
10019
10330
|
var PYCACHE_PREFIX_DIR = "_vc_pycache";
|
|
10020
10331
|
var RUNTIME_PYCACHE_PREFIX = `/var/task/${PYCACHE_PREFIX_DIR}`;
|
|
@@ -10050,13 +10361,13 @@ async function runCompileAll({
|
|
|
10050
10361
|
}
|
|
10051
10362
|
let tempDir;
|
|
10052
10363
|
try {
|
|
10053
|
-
tempDir = await
|
|
10054
|
-
(0,
|
|
10364
|
+
tempDir = await import_fs18.default.promises.mkdtemp(
|
|
10365
|
+
(0, import_path18.join)((0, import_os3.tmpdir)(), "vercel-python-compileall-")
|
|
10055
10366
|
);
|
|
10056
|
-
const listPath = (0,
|
|
10057
|
-
await
|
|
10058
|
-
const timingsPath = (0,
|
|
10059
|
-
const scriptPath4 = (0,
|
|
10367
|
+
const listPath = (0, import_path18.join)(tempDir, "pysources.json");
|
|
10368
|
+
await import_fs18.default.promises.writeFile(listPath, JSON.stringify(uniqueSourceFiles));
|
|
10369
|
+
const timingsPath = (0, import_path18.join)(tempDir, "timings.json");
|
|
10370
|
+
const scriptPath4 = (0, import_path18.join)(__dirname, "..", "templates", "vc_compileall.py");
|
|
10060
10371
|
const baseEnv = env || process.env;
|
|
10061
10372
|
const subprocessEnv = pycachePrefix ? { ...baseEnv, PYTHONPYCACHEPREFIX: pycachePrefix } : baseEnv;
|
|
10062
10373
|
await (0, import_execa10.default)(pythonBin, [scriptPath4, listPath, timingsPath], {
|
|
@@ -10065,21 +10376,21 @@ async function runCompileAll({
|
|
|
10065
10376
|
});
|
|
10066
10377
|
let timings;
|
|
10067
10378
|
try {
|
|
10068
|
-
const raw = await
|
|
10379
|
+
const raw = await import_fs18.default.promises.readFile(timingsPath, "utf8");
|
|
10069
10380
|
timings = new Map(Object.entries(JSON.parse(raw)));
|
|
10070
10381
|
} catch (err) {
|
|
10071
|
-
(0,
|
|
10382
|
+
(0, import_build_utils21.debug)(`compileall timings unavailable: ${String(err)}`);
|
|
10072
10383
|
}
|
|
10073
10384
|
return { success: true, timings };
|
|
10074
10385
|
} catch (err) {
|
|
10075
|
-
(0,
|
|
10386
|
+
(0, import_build_utils21.debug)(`compileall error details: ${JSON.stringify(err)}`);
|
|
10076
10387
|
return { success: false };
|
|
10077
10388
|
} finally {
|
|
10078
10389
|
if (tempDir) {
|
|
10079
10390
|
try {
|
|
10080
|
-
await
|
|
10391
|
+
await import_fs18.default.promises.rm(tempDir, { recursive: true, force: true });
|
|
10081
10392
|
} catch (err) {
|
|
10082
|
-
(0,
|
|
10393
|
+
(0, import_build_utils21.debug)(`compileall temporary file cleanup error: ${String(err)}`);
|
|
10083
10394
|
}
|
|
10084
10395
|
}
|
|
10085
10396
|
}
|
|
@@ -10116,7 +10427,7 @@ function deriveStagedPycFsPath(stagingDir, srcAbsPath, pythonMajor, pythonMinor)
|
|
|
10116
10427
|
);
|
|
10117
10428
|
if (!rel)
|
|
10118
10429
|
return null;
|
|
10119
|
-
return (0,
|
|
10430
|
+
return (0, import_path18.join)(stagingDir, rel.replaceAll("/", import_path18.sep));
|
|
10120
10431
|
}
|
|
10121
10432
|
function derivePrefixPycBundlePath(runtimeAbsPath, pythonMajor, pythonMinor) {
|
|
10122
10433
|
const rel = derivePrefixPycRelPath(
|
|
@@ -10140,7 +10451,7 @@ async function collectAppPrefixBytecodeFiles({
|
|
|
10140
10451
|
for (const bundlePath of Object.keys(appFiles)) {
|
|
10141
10452
|
if (!bundlePath.endsWith(".py"))
|
|
10142
10453
|
continue;
|
|
10143
|
-
const sourceAbsPath = (0,
|
|
10454
|
+
const sourceAbsPath = (0, import_path18.join)(workPath, bundlePath.replaceAll("/", import_path18.sep));
|
|
10144
10455
|
const stagedFsPath = deriveStagedPycFsPath(
|
|
10145
10456
|
stagingDir,
|
|
10146
10457
|
sourceAbsPath,
|
|
@@ -10164,7 +10475,7 @@ async function collectAppPrefixBytecodeFiles({
|
|
|
10164
10475
|
const results = await Promise.all(
|
|
10165
10476
|
pending.map(async ({ bundlePath, srcFsPath, moduleKey, sourceAbsPath }) => {
|
|
10166
10477
|
try {
|
|
10167
|
-
const stats = await
|
|
10478
|
+
const stats = await import_fs18.default.promises.stat(srcFsPath);
|
|
10168
10479
|
return {
|
|
10169
10480
|
bundlePath,
|
|
10170
10481
|
srcFsPath,
|
|
@@ -10184,7 +10495,7 @@ async function collectAppPrefixBytecodeFiles({
|
|
|
10184
10495
|
for (const result of results) {
|
|
10185
10496
|
if (!result)
|
|
10186
10497
|
continue;
|
|
10187
|
-
const file = new
|
|
10498
|
+
const file = new import_build_utils21.FileFsRef({
|
|
10188
10499
|
fsPath: result.srcFsPath,
|
|
10189
10500
|
size: result.size
|
|
10190
10501
|
});
|
|
@@ -10214,15 +10525,15 @@ async function collectAppBytecodeFiles({
|
|
|
10214
10525
|
continue;
|
|
10215
10526
|
pending.push({
|
|
10216
10527
|
bundlePath: pycRel,
|
|
10217
|
-
srcFsPath: (0,
|
|
10528
|
+
srcFsPath: (0, import_path18.join)(workPath, pycRel.replaceAll("/", import_path18.sep)),
|
|
10218
10529
|
moduleKey: bundlePath,
|
|
10219
|
-
sourceAbsPath: (0,
|
|
10530
|
+
sourceAbsPath: (0, import_path18.join)(workPath, bundlePath.replaceAll("/", import_path18.sep))
|
|
10220
10531
|
});
|
|
10221
10532
|
}
|
|
10222
10533
|
const results = await Promise.all(
|
|
10223
10534
|
pending.map(async ({ bundlePath, srcFsPath, moduleKey, sourceAbsPath }) => {
|
|
10224
10535
|
try {
|
|
10225
|
-
const stats = await
|
|
10536
|
+
const stats = await import_fs18.default.promises.stat(srcFsPath);
|
|
10226
10537
|
return {
|
|
10227
10538
|
bundlePath,
|
|
10228
10539
|
srcFsPath,
|
|
@@ -10242,7 +10553,7 @@ async function collectAppBytecodeFiles({
|
|
|
10242
10553
|
for (const result of results) {
|
|
10243
10554
|
if (!result)
|
|
10244
10555
|
continue;
|
|
10245
|
-
const file = new
|
|
10556
|
+
const file = new import_build_utils21.FileFsRef({
|
|
10246
10557
|
fsPath: result.srcFsPath,
|
|
10247
10558
|
size: result.size
|
|
10248
10559
|
});
|
|
@@ -10261,9 +10572,9 @@ async function collectAppBytecodeFiles({
|
|
|
10261
10572
|
}
|
|
10262
10573
|
|
|
10263
10574
|
// src/installed-distributions.ts
|
|
10264
|
-
var
|
|
10265
|
-
var
|
|
10266
|
-
var
|
|
10575
|
+
var import_fs19 = __toESM(require("fs"));
|
|
10576
|
+
var import_path19 = require("path");
|
|
10577
|
+
var import_build_utils22 = require("@vercel/build-utils");
|
|
10267
10578
|
var import_python_analysis11 = require("@vercel/python-analysis");
|
|
10268
10579
|
var STRIP_BASENAMES = /* @__PURE__ */ new Set([
|
|
10269
10580
|
"py.typed",
|
|
@@ -10272,7 +10583,7 @@ var STRIP_BASENAMES = /* @__PURE__ */ new Set([
|
|
|
10272
10583
|
"direct_url.json"
|
|
10273
10584
|
]);
|
|
10274
10585
|
function shouldStripVendorFile(filePath) {
|
|
10275
|
-
const segments = filePath.split(
|
|
10586
|
+
const segments = filePath.split(import_path19.sep);
|
|
10276
10587
|
if (segments.includes("__pycache__"))
|
|
10277
10588
|
return true;
|
|
10278
10589
|
const name = segments[segments.length - 1] ?? "";
|
|
@@ -10296,19 +10607,19 @@ function getDistributionFileGroups({
|
|
|
10296
10607
|
const dirDistributions = distributions.get(dir);
|
|
10297
10608
|
if (!dirDistributions)
|
|
10298
10609
|
continue;
|
|
10299
|
-
const sitePackagesDir = (0,
|
|
10610
|
+
const sitePackagesDir = (0, import_path19.resolve)(dir);
|
|
10300
10611
|
for (const [name, distribution] of dirDistributions) {
|
|
10301
10612
|
const packageName = (0, import_python_analysis11.normalizePackageName)(name);
|
|
10302
10613
|
if (includeSet && !includeSet.has(packageName))
|
|
10303
10614
|
continue;
|
|
10304
10615
|
const files = [];
|
|
10305
10616
|
for (const record of distribution.files) {
|
|
10306
|
-
const absolutePath = (0,
|
|
10617
|
+
const absolutePath = (0, import_path19.resolve)(
|
|
10307
10618
|
sitePackagesDir,
|
|
10308
|
-
record.path.replaceAll("/",
|
|
10619
|
+
record.path.replaceAll("/", import_path19.sep)
|
|
10309
10620
|
);
|
|
10310
|
-
const relativePath = (0,
|
|
10311
|
-
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${
|
|
10621
|
+
const relativePath = (0, import_path19.relative)(sitePackagesDir, absolutePath);
|
|
10622
|
+
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${import_path19.sep}`) || (0, import_path19.isAbsolute)(relativePath)) {
|
|
10312
10623
|
continue;
|
|
10313
10624
|
}
|
|
10314
10625
|
files.push({ absolutePath, relativePath, record });
|
|
@@ -10328,7 +10639,7 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10328
10639
|
const distributions = /* @__PURE__ */ new Map();
|
|
10329
10640
|
for (const dir of sitePackageDirs) {
|
|
10330
10641
|
try {
|
|
10331
|
-
await
|
|
10642
|
+
await import_fs19.default.promises.access(dir);
|
|
10332
10643
|
} catch {
|
|
10333
10644
|
continue;
|
|
10334
10645
|
}
|
|
@@ -10369,7 +10680,7 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10369
10680
|
if (shouldStripVendorFile(relativePath))
|
|
10370
10681
|
continue;
|
|
10371
10682
|
pending.push({
|
|
10372
|
-
bundlePath: (0,
|
|
10683
|
+
bundlePath: (0, import_path19.join)(vendorDirName, relativePath).replace(/\\/g, "/"),
|
|
10373
10684
|
srcFsPath: absolutePath,
|
|
10374
10685
|
recordSize: record.size != null ? Number(record.size) : void 0
|
|
10375
10686
|
});
|
|
@@ -10379,10 +10690,10 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10379
10690
|
pending.map(async ({ bundlePath, srcFsPath, recordSize }) => {
|
|
10380
10691
|
try {
|
|
10381
10692
|
if (recordSize === void 0) {
|
|
10382
|
-
const stats = await
|
|
10693
|
+
const stats = await import_fs19.default.promises.stat(srcFsPath);
|
|
10383
10694
|
return { bundlePath, srcFsPath, size: stats.size };
|
|
10384
10695
|
}
|
|
10385
|
-
await
|
|
10696
|
+
await import_fs19.default.promises.access(srcFsPath);
|
|
10386
10697
|
return { bundlePath, srcFsPath, size: recordSize };
|
|
10387
10698
|
} catch {
|
|
10388
10699
|
return null;
|
|
@@ -10393,12 +10704,12 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10393
10704
|
for (const result of results) {
|
|
10394
10705
|
if (!result)
|
|
10395
10706
|
continue;
|
|
10396
|
-
vendorFiles[result.bundlePath] = new
|
|
10707
|
+
vendorFiles[result.bundlePath] = new import_build_utils22.FileFsRef({
|
|
10397
10708
|
fsPath: result.srcFsPath,
|
|
10398
10709
|
size: result.size
|
|
10399
10710
|
});
|
|
10400
10711
|
}
|
|
10401
|
-
(0,
|
|
10712
|
+
(0, import_build_utils22.debug)(
|
|
10402
10713
|
`Mirrored ${Object.keys(vendorFiles).length} files` + (includePackages ? ` from ${includePackages.length} packages` : "")
|
|
10403
10714
|
);
|
|
10404
10715
|
return vendorFiles;
|
|
@@ -10419,7 +10730,7 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10419
10730
|
knownSize += Number(record.size);
|
|
10420
10731
|
} else {
|
|
10421
10732
|
statPromises.push(
|
|
10422
|
-
|
|
10733
|
+
import_fs19.default.promises.stat(absolutePath).then((stats) => stats.size).catch(() => 0)
|
|
10423
10734
|
);
|
|
10424
10735
|
}
|
|
10425
10736
|
}
|
|
@@ -10462,7 +10773,7 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10462
10773
|
});
|
|
10463
10774
|
for (const { packageName, sitePackagesDir, files } of distributionGroups) {
|
|
10464
10775
|
for (const { relativePath } of files) {
|
|
10465
|
-
const moduleKey = relativePath.replaceAll(
|
|
10776
|
+
const moduleKey = relativePath.replaceAll(import_path19.sep, "/");
|
|
10466
10777
|
const pycRelativePath = derivePycPath(
|
|
10467
10778
|
moduleKey,
|
|
10468
10779
|
this.pythonMajor,
|
|
@@ -10470,18 +10781,18 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10470
10781
|
);
|
|
10471
10782
|
if (!pycRelativePath)
|
|
10472
10783
|
continue;
|
|
10473
|
-
const pycFilePath = pycRelativePath.replaceAll("/",
|
|
10784
|
+
const pycFilePath = pycRelativePath.replaceAll("/", import_path19.sep);
|
|
10474
10785
|
pending.push({
|
|
10475
|
-
bundlePath: (0,
|
|
10476
|
-
srcFsPath: (0,
|
|
10786
|
+
bundlePath: (0, import_path19.join)(vendorDirName, pycFilePath).replace(/\\/g, "/"),
|
|
10787
|
+
srcFsPath: (0, import_path19.join)(sitePackagesDir, pycFilePath),
|
|
10477
10788
|
packageName,
|
|
10478
10789
|
moduleKey,
|
|
10479
|
-
sourceAbsPath: (0,
|
|
10790
|
+
sourceAbsPath: (0, import_path19.join)(sitePackagesDir, relativePath)
|
|
10480
10791
|
});
|
|
10481
10792
|
}
|
|
10482
10793
|
}
|
|
10483
10794
|
const result = await this.collectExistingBytecode(pending);
|
|
10484
|
-
(0,
|
|
10795
|
+
(0, import_build_utils22.debug)(
|
|
10485
10796
|
`Collected ${Object.keys(result.files).length} bytecode files (${(result.totalSize / (1024 * 1024)).toFixed(2)} MB)` + (includePackages ? ` from ${includePackages.length} packages` : "")
|
|
10486
10797
|
);
|
|
10487
10798
|
return result;
|
|
@@ -10504,7 +10815,7 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10504
10815
|
for (const { absolutePath, relativePath } of files) {
|
|
10505
10816
|
if (!relativePath.endsWith(".py"))
|
|
10506
10817
|
continue;
|
|
10507
|
-
const recordPath = relativePath.replaceAll(
|
|
10818
|
+
const recordPath = relativePath.replaceAll(import_path19.sep, "/");
|
|
10508
10819
|
const srcFsPath = deriveStagedPycFsPath(
|
|
10509
10820
|
stagingDir,
|
|
10510
10821
|
absolutePath,
|
|
@@ -10528,7 +10839,7 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10528
10839
|
}
|
|
10529
10840
|
}
|
|
10530
10841
|
const result = await this.collectExistingBytecode(pending);
|
|
10531
|
-
(0,
|
|
10842
|
+
(0, import_build_utils22.debug)(
|
|
10532
10843
|
`Collected ${Object.keys(result.files).length} prefix bytecode files (${(result.totalSize / (1024 * 1024)).toFixed(2)} MB) for runtime root ${runtimeRoot}` + (includePackages ? ` from ${includePackages.length} packages` : "")
|
|
10533
10844
|
);
|
|
10534
10845
|
return result;
|
|
@@ -10544,7 +10855,7 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10544
10855
|
sourceAbsPath
|
|
10545
10856
|
}) => {
|
|
10546
10857
|
try {
|
|
10547
|
-
const stats = await
|
|
10858
|
+
const stats = await import_fs19.default.promises.stat(srcFsPath);
|
|
10548
10859
|
return {
|
|
10549
10860
|
bundlePath,
|
|
10550
10861
|
srcFsPath,
|
|
@@ -10566,7 +10877,7 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10566
10877
|
for (const result of results) {
|
|
10567
10878
|
if (!result)
|
|
10568
10879
|
continue;
|
|
10569
|
-
const file = new
|
|
10880
|
+
const file = new import_build_utils22.FileFsRef({
|
|
10570
10881
|
fsPath: result.srcFsPath,
|
|
10571
10882
|
size: result.size
|
|
10572
10883
|
});
|
|
@@ -10588,84 +10899,6 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
|
|
|
10588
10899
|
}
|
|
10589
10900
|
};
|
|
10590
10901
|
|
|
10591
|
-
// src/workflows.ts
|
|
10592
|
-
var import_path19 = require("path");
|
|
10593
|
-
var import_fs19 = __toESM(require("fs"));
|
|
10594
|
-
var import_build_utils22 = require("@vercel/build-utils");
|
|
10595
|
-
var WORKFLOW_OUTPUT_DIR = "_py_workflows";
|
|
10596
|
-
var WORKFLOW_TOPIC_PATTERN = "__wkf_*";
|
|
10597
|
-
var WORKFLOW_FIELD_NAMES = /* @__PURE__ */ new Set(["entrypoint"]);
|
|
10598
|
-
function getWorkflowOutputPath(workflowName) {
|
|
10599
|
-
return `${WORKFLOW_OUTPUT_DIR}/${safePathSegment(workflowName)}`;
|
|
10600
|
-
}
|
|
10601
|
-
function getWorkflowConsumerName(workflowName) {
|
|
10602
|
-
return (0, import_build_utils22.sanitizeConsumerName)(getWorkflowOutputPath(workflowName));
|
|
10603
|
-
}
|
|
10604
|
-
async function getPyprojectWorkflows(workPath) {
|
|
10605
|
-
const pyprojectPath = (0, import_path19.join)(workPath, "pyproject.toml");
|
|
10606
|
-
if (!import_fs19.default.existsSync(pyprojectPath)) {
|
|
10607
|
-
return [];
|
|
10608
|
-
}
|
|
10609
|
-
const pyproject = await (0, import_build_utils22.readConfigFile)(pyprojectPath);
|
|
10610
|
-
const workflows = pyproject?.tool?.vercel?.workflows;
|
|
10611
|
-
if (!workflows) {
|
|
10612
|
-
return [];
|
|
10613
|
-
}
|
|
10614
|
-
if (!Array.isArray(workflows)) {
|
|
10615
|
-
throw workflowError('"tool.vercel.workflows" must be an array');
|
|
10616
|
-
}
|
|
10617
|
-
if (workflows.length > 1) {
|
|
10618
|
-
throw workflowError(
|
|
10619
|
-
'"tool.vercel.workflows" must declare a single entrypoint that registers every workflow'
|
|
10620
|
-
);
|
|
10621
|
-
}
|
|
10622
|
-
return Promise.all(
|
|
10623
|
-
workflows.map((config, index) => parseWorkflow(workPath, index, config))
|
|
10624
|
-
);
|
|
10625
|
-
}
|
|
10626
|
-
async function parseWorkflow(workPath, index, config) {
|
|
10627
|
-
const label = `workflow #${index + 1}`;
|
|
10628
|
-
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
10629
|
-
throw workflowError(`${label} must be an object`);
|
|
10630
|
-
}
|
|
10631
|
-
for (const key of Object.keys(config)) {
|
|
10632
|
-
if (!WORKFLOW_FIELD_NAMES.has(key)) {
|
|
10633
|
-
throw workflowError(`${label} has unrecognized field "${key}"`);
|
|
10634
|
-
}
|
|
10635
|
-
}
|
|
10636
|
-
if (typeof config.entrypoint !== "string") {
|
|
10637
|
-
throw workflowError(`${label} must define string field "entrypoint"`);
|
|
10638
|
-
}
|
|
10639
|
-
const entrypoint = parseModuleEntrypoint(config.entrypoint);
|
|
10640
|
-
if (!entrypoint) {
|
|
10641
|
-
throw workflowError(
|
|
10642
|
-
`${label} has invalid entrypoint "${config.entrypoint}". Use "module:object"`
|
|
10643
|
-
);
|
|
10644
|
-
}
|
|
10645
|
-
const name = getModuleEntrypointName(entrypoint);
|
|
10646
|
-
const existingEntrypoint = await resolveExistingEntrypoint(
|
|
10647
|
-
workPath,
|
|
10648
|
-
entrypoint.filePath
|
|
10649
|
-
);
|
|
10650
|
-
if (!existingEntrypoint) {
|
|
10651
|
-
throw workflowError(
|
|
10652
|
-
`workflow "${name}" has entrypoint "${config.entrypoint}" but file "${entrypoint.filePath}" does not exist`
|
|
10653
|
-
);
|
|
10654
|
-
}
|
|
10655
|
-
return {
|
|
10656
|
-
name,
|
|
10657
|
-
entrypoint: existingEntrypoint,
|
|
10658
|
-
moduleName: entrypoint.moduleName,
|
|
10659
|
-
variableName: entrypoint.variableName
|
|
10660
|
-
};
|
|
10661
|
-
}
|
|
10662
|
-
function workflowError(message) {
|
|
10663
|
-
return new import_build_utils22.NowBuildError({
|
|
10664
|
-
code: "PYTHON_INVALID_WORKFLOW_CONFIG",
|
|
10665
|
-
message
|
|
10666
|
-
});
|
|
10667
|
-
}
|
|
10668
|
-
|
|
10669
10902
|
// src/import-closure.ts
|
|
10670
10903
|
var import_path20 = require("path");
|
|
10671
10904
|
var import_build_utils23 = require("@vercel/build-utils");
|
|
@@ -10776,7 +11009,7 @@ async function getDevSidecars({
|
|
|
10776
11009
|
use: build2.use,
|
|
10777
11010
|
src: subscriber.entrypoint,
|
|
10778
11011
|
config: {
|
|
10779
|
-
handlerFunction: subscriber.variableName,
|
|
11012
|
+
...subscriber.variableName === void 0 ? {} : { handlerFunction: subscriber.variableName },
|
|
10780
11013
|
pythonQueueSidecar: "subscriber"
|
|
10781
11014
|
}
|
|
10782
11015
|
},
|
|
@@ -10799,7 +11032,7 @@ async function getDevSidecars({
|
|
|
10799
11032
|
pythonQueueSidecar: "workflow"
|
|
10800
11033
|
}
|
|
10801
11034
|
},
|
|
10802
|
-
topics: [{ topic:
|
|
11035
|
+
topics: [{ topic: WORKFLOW_DEV_TOPIC_PATTERN }]
|
|
10803
11036
|
})
|
|
10804
11037
|
)
|
|
10805
11038
|
];
|
|
@@ -11403,11 +11636,14 @@ var build = async ({
|
|
|
11403
11636
|
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
11404
11637
|
pipPlatformArgs
|
|
11405
11638
|
});
|
|
11406
|
-
const
|
|
11639
|
+
const queueAdapterBootstrap = await getQueueAdapterBootstrap({
|
|
11407
11640
|
pythonPackage,
|
|
11408
|
-
env: baseEnv
|
|
11409
|
-
|
|
11410
|
-
|
|
11641
|
+
env: baseEnv,
|
|
11642
|
+
legacyWorkersProject,
|
|
11643
|
+
hasDeclaredSubscribers: await hasPyprojectSubscribers(workPath)
|
|
11644
|
+
});
|
|
11645
|
+
const queueAdapterInjectedPackages = usedUvManagedInstall ? queueAdapterBootstrap.injectedPackages : [];
|
|
11646
|
+
for (const injectedPackage of queueAdapterInjectedPackages) {
|
|
11411
11647
|
await installInjectedPackage({
|
|
11412
11648
|
...injectedPackage,
|
|
11413
11649
|
uv,
|
|
@@ -11424,6 +11660,12 @@ var build = async ({
|
|
|
11424
11660
|
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
11425
11661
|
uvLockPath
|
|
11426
11662
|
});
|
|
11663
|
+
if (workflowMode === "workers" && workflows.length > 1) {
|
|
11664
|
+
throw new import_build_utils24.NowBuildError({
|
|
11665
|
+
code: "PYTHON_INVALID_WORKFLOW_CONFIG",
|
|
11666
|
+
message: `"tool.vercel.workflows" declares multiple entrypoints, which requires vercel>=${MIN_QUEUE_WORKFLOW_SDK_VERSION} with a distinct namespace per Workflows registry; the installed SDK serves every workflow on the shared __wkf_* topic`
|
|
11667
|
+
});
|
|
11668
|
+
}
|
|
11427
11669
|
}
|
|
11428
11670
|
const shouldInstallVercelWorkers = legacyWorkersProject || workflows.length > 0 && workflowMode === "workers";
|
|
11429
11671
|
if (shouldInstallVercelWorkers) {
|
|
@@ -11442,7 +11684,7 @@ var build = async ({
|
|
|
11442
11684
|
if (quirksResult.buildEnv) {
|
|
11443
11685
|
Object.assign(pythonEnv, quirksResult.buildEnv);
|
|
11444
11686
|
}
|
|
11445
|
-
const queueIntegrations =
|
|
11687
|
+
const queueIntegrations = queueAdapterBootstrap.integrations;
|
|
11446
11688
|
const writeGeneratedQueueHandler = async (outputPath, declaration) => {
|
|
11447
11689
|
const generatedPath = getGeneratedQueueHandlerPath(outputPath);
|
|
11448
11690
|
await import_fs20.default.promises.mkdir((0, import_path21.dirname)((0, import_path21.join)(workPath, generatedPath)), {
|
|
@@ -11465,7 +11707,7 @@ var build = async ({
|
|
|
11465
11707
|
for (const subscriber of subscribers) {
|
|
11466
11708
|
if (!subscriber.topicPatterns) {
|
|
11467
11709
|
subscriber.subscriptions = subscriber.subscriptions.filter(
|
|
11468
|
-
(subscription) => !subscription.topic
|
|
11710
|
+
(subscription) => !isWorkflowQueueTopic(subscription.topic)
|
|
11469
11711
|
);
|
|
11470
11712
|
}
|
|
11471
11713
|
}
|
|
@@ -11484,8 +11726,7 @@ var build = async ({
|
|
|
11484
11726
|
name: workflow.name,
|
|
11485
11727
|
entrypoint: workflow.entrypoint,
|
|
11486
11728
|
moduleName: workflow.moduleName,
|
|
11487
|
-
variableName: workflow.variableName
|
|
11488
|
-
topicPatterns: [WORKFLOW_TOPIC_PATTERN]
|
|
11729
|
+
variableName: workflow.variableName
|
|
11489
11730
|
})),
|
|
11490
11731
|
uv,
|
|
11491
11732
|
venvPath,
|
|
@@ -11493,6 +11734,21 @@ var build = async ({
|
|
|
11493
11734
|
kind: "workflow",
|
|
11494
11735
|
integrations: queueIntegrations
|
|
11495
11736
|
});
|
|
11737
|
+
for (let i = 0; i < resolved2.length; i++) {
|
|
11738
|
+
for (let j = i + 1; j < resolved2.length; j++) {
|
|
11739
|
+
const overlaps = resolved2[i].subscriptions.some(
|
|
11740
|
+
(left) => resolved2[j].subscriptions.some(
|
|
11741
|
+
(right) => queueTopicPatternsOverlap(left.topic, right.topic)
|
|
11742
|
+
)
|
|
11743
|
+
);
|
|
11744
|
+
if (overlaps) {
|
|
11745
|
+
throw new import_build_utils24.NowBuildError({
|
|
11746
|
+
code: "PYTHON_INVALID_WORKFLOW_CONFIG",
|
|
11747
|
+
message: `workflow entrypoints "${resolved2[i].moduleName}:${resolved2[i].variableName}" and "${resolved2[j].moduleName}:${resolved2[j].variableName}" subscribe to overlapping queue topics; construct each vercel.workflow.Workflows registry with a distinct namespace`
|
|
11748
|
+
});
|
|
11749
|
+
}
|
|
11750
|
+
}
|
|
11751
|
+
}
|
|
11496
11752
|
for (const workflow of resolved2) {
|
|
11497
11753
|
workflowQueueSubscriptions.set(workflow.name, workflow.subscriptions);
|
|
11498
11754
|
await writeGeneratedQueueHandler(
|
|
@@ -11598,6 +11854,18 @@ var build = async ({
|
|
|
11598
11854
|
({ module: module2, installer, servingActivator }) => `${module2}:${installer}` + (servingActivator ? `:${servingActivator}` : "")
|
|
11599
11855
|
).join(",");
|
|
11600
11856
|
}
|
|
11857
|
+
const apschedulerSubscribers = apschedulerSubscriberIdentities(subscribers);
|
|
11858
|
+
if (apschedulerSubscribers.length > 0) {
|
|
11859
|
+
lambdaEnv.VERCEL_APSCHEDULER_SUBSCRIBERS = JSON.stringify(
|
|
11860
|
+
apschedulerSubscribers
|
|
11861
|
+
);
|
|
11862
|
+
const previewConfig = await getApschedulerPreviewConfig(workPath);
|
|
11863
|
+
if (previewConfig) {
|
|
11864
|
+
lambdaEnv.VERCEL_APSCHEDULER_PREVIEW_IDLE_TIMEOUT_SECONDS = String(
|
|
11865
|
+
previewConfig.idleTimeoutSeconds
|
|
11866
|
+
);
|
|
11867
|
+
}
|
|
11868
|
+
}
|
|
11601
11869
|
const globOptions = {
|
|
11602
11870
|
cwd: workPath,
|
|
11603
11871
|
ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
|
|
@@ -11934,7 +12202,9 @@ var build = async ({
|
|
|
11934
12202
|
runtime: pythonVersion.runtime,
|
|
11935
12203
|
...lambdaOptions,
|
|
11936
12204
|
architecture: target.architecture,
|
|
11937
|
-
environment:
|
|
12205
|
+
environment: {
|
|
12206
|
+
...lambdaEnv
|
|
12207
|
+
},
|
|
11938
12208
|
supportsResponseStreaming: true
|
|
11939
12209
|
});
|
|
11940
12210
|
}
|
|
@@ -11972,7 +12242,12 @@ var build = async ({
|
|
|
11972
12242
|
handler: `${handlerPyFilename}.vc_handler`,
|
|
11973
12243
|
runtime: pythonVersion.runtime,
|
|
11974
12244
|
architecture: target.architecture,
|
|
11975
|
-
environment:
|
|
12245
|
+
environment: {
|
|
12246
|
+
...lambdaEnv,
|
|
12247
|
+
// The runtime activates publish-side integrations before importing the
|
|
12248
|
+
// generated subscriber module, so the identity must already be present.
|
|
12249
|
+
VERCEL_PYTHON_SUBSCRIBER_ID: subscriber.name
|
|
12250
|
+
},
|
|
11976
12251
|
experimentalTriggers,
|
|
11977
12252
|
supportsResponseStreaming: true
|
|
11978
12253
|
});
|
|
@@ -11984,6 +12259,11 @@ var build = async ({
|
|
|
11984
12259
|
const consumer = getSubscriberConsumerName(declaration.name);
|
|
11985
12260
|
const legacy = declaration.legacy;
|
|
11986
12261
|
(0, import_assert.default)(legacy, "legacy subscriber declarations must carry legacy config");
|
|
12262
|
+
const { variableName } = declaration;
|
|
12263
|
+
(0, import_assert.default)(
|
|
12264
|
+
variableName,
|
|
12265
|
+
"legacy subscriber declarations must name an entrypoint object"
|
|
12266
|
+
);
|
|
11987
12267
|
const experimentalTriggers = legacy.topics.map((topic) => ({
|
|
11988
12268
|
type: "queue/v2beta",
|
|
11989
12269
|
topic,
|
|
@@ -11998,7 +12278,7 @@ var build = async ({
|
|
|
11998
12278
|
moduleName: declaration.moduleName,
|
|
11999
12279
|
entrypoint: declaration.entrypoint,
|
|
12000
12280
|
vendorDir,
|
|
12001
|
-
variableName
|
|
12281
|
+
variableName
|
|
12002
12282
|
})
|
|
12003
12283
|
})
|
|
12004
12284
|
},
|