cmux/node_modules/@vercel/rust/dist/index.js
2026-01-29 17:36:26 -08:00

443 lines
16 KiB
JavaScript

"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
build: () => build,
prepareCache: () => prepareCache,
shouldServe: () => shouldServe,
startDevServer: () => startDevServer2,
version: () => version
});
module.exports = __toCommonJS(src_exports);
var import_node_path4 = __toESM(require("path"));
var import_build_utils6 = require("@vercel/build-utils");
var import_execa4 = __toESM(require("execa"));
// src/lib/rust-toolchain.ts
var import_build_utils = require("@vercel/build-utils");
var import_execa = __toESM(require("execa"));
async function downloadRustToolchain() {
try {
await (0, import_execa.default)(
`curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y`,
[],
{ shell: true, stdio: "inherit" }
);
} catch (err) {
let message = "Unknown Error";
if (err instanceof Error) {
message = err.message;
}
throw new Error(`Installing Rust Toolchain via rustup failed: ${message}`);
}
}
var installRustToolchain = async () => {
try {
await (0, import_execa.default)(`rustup -V`, [], { shell: true, stdio: "ignore" });
(0, import_build_utils.debug)("Rust Toolchain is already installed, skipping download");
} catch (err) {
await downloadRustToolchain();
}
};
// src/lib/cargo.ts
var import_node_fs = __toESM(require("fs"));
var import_node_path = __toESM(require("path"));
var import_toml = __toESM(require("@iarna/toml"));
var import_execa2 = __toESM(require("execa"));
async function getCargoMetadata(options) {
const { stdout: cargoMetaData } = await (0, import_execa2.default)(
"cargo",
["metadata", "--format-version", "1"],
options
);
return JSON.parse(cargoMetaData);
}
async function findCargoWorkspace(config) {
const { stdout: projectDescriptionStr } = await (0, import_execa2.default)(
"cargo",
["locate-project"],
config
);
const projectDescription = JSON.parse(projectDescriptionStr);
return {
toml: await import_toml.default.parse.stream(import_node_fs.default.createReadStream(projectDescription.root)),
root: projectDescription.root
};
}
async function findCargoBuildConfiguration(workspace) {
const configPath = import_node_path.default.join(
import_node_path.default.dirname(workspace.root),
".cargo/config.toml"
);
if (!import_node_fs.default.existsSync(configPath)) {
return null;
}
const config = await import_toml.default.parse.stream(import_node_fs.default.createReadStream(configPath));
return config;
}
function findBinaryName(workspace, entryPath) {
const { bin } = workspace.toml;
if (bin) {
const relativePath = import_node_path.default.relative(import_node_path.default.dirname(workspace.root), entryPath);
const entry = bin.find((binEntry) => binEntry.path === relativePath);
if (entry?.name) {
return entry.name;
}
}
return import_node_path.default.basename(entryPath, ".rs").replace("[", "_").replace("]", "_");
}
// src/lib/utils.ts
var import_node_fs2 = __toESM(require("fs"));
var import_node_path2 = __toESM(require("path"));
var import_build_utils2 = require("@vercel/build-utils");
function getExecutableName(binName) {
return process.platform === "win32" ? `${binName}.exe` : binName;
}
function assertEnv(name) {
if (!process.env[name]) {
throw new Error(`Missing ENV variable process.env.${name}`);
}
return process.env[name];
}
async function runUserScripts(dir) {
const buildScriptPath = import_node_path2.default.join(dir, "build.sh");
const buildScriptExists = import_node_fs2.default.existsSync(buildScriptPath);
if (buildScriptExists) {
(0, import_build_utils2.debug)("Running `build.sh`");
await (0, import_build_utils2.runShellScript)(buildScriptPath);
}
}
async function gatherExtraFiles(globMatcher, workPath) {
if (!globMatcher)
return {};
(0, import_build_utils2.debug)(
`Gathering extra files for glob \`${JSON.stringify(
globMatcher
)}\` in ${workPath}`
);
if (Array.isArray(globMatcher)) {
const allMatches = await Promise.all(
globMatcher.map((pattern) => (0, import_build_utils2.glob)(pattern, workPath))
);
return allMatches.reduce((acc, matches) => ({ ...acc, ...matches }), {});
}
return (0, import_build_utils2.glob)(globMatcher, workPath);
}
// src/lib/start-dev-server.ts
var import_child_process = require("child_process");
var import_events = require("events");
var import_build_utils5 = require("@vercel/build-utils");
// src/lib/dev-build.ts
var import_node_path3 = __toESM(require("path"));
var import_execa3 = __toESM(require("execa"));
var import_build_utils3 = require("@vercel/build-utils");
async function buildExecutableForDev(workPath, entrypoint) {
(0, import_build_utils3.debug)(`Building executable for development: ${entrypoint}`);
const HOME = process.platform === "win32" ? assertEnv("USERPROFILE") : assertEnv("HOME");
const PATH = assertEnv("PATH");
const rustEnv = {
PATH: `${import_node_path3.default.join(HOME, ".cargo/bin")}${import_node_path3.default.delimiter}${PATH}`,
RUSTFLAGS: [process.env.RUSTFLAGS].filter(Boolean).join(" ")
};
const entryPath = import_node_path3.default.join(workPath, entrypoint);
const cargoWorkspace = await findCargoWorkspace({
env: rustEnv,
cwd: import_node_path3.default.dirname(entryPath)
});
const binaryName = findBinaryName(cargoWorkspace, entryPath);
(0, import_build_utils3.debug)(`Building binary "${binaryName}" in debug mode for dev server`);
try {
await (0, import_execa3.default)(
"cargo",
[
"build",
"--bin",
binaryName,
"--message-format=json-diagnostic-rendered-ansi"
],
{
cwd: workPath,
env: rustEnv,
stdio: "pipe"
}
);
} catch (err) {
(0, import_build_utils3.debug)(`Cargo build failed for ${binaryName}`);
throw new Error(`Failed to build Rust binary for development: ${err}`);
}
const { target_directory: targetDirectory } = await getCargoMetadata({
cwd: workPath,
env: rustEnv
});
const executablePath = import_node_path3.default.join(
targetDirectory,
"debug",
getExecutableName(binaryName)
);
(0, import_build_utils3.debug)(`Built executable at: ${executablePath}`);
return executablePath;
}
// src/lib/dev-server.ts
var import_build_utils4 = require("@vercel/build-utils");
function createDevServerEnv(baseEnv, meta = {}) {
const devEnv = {
// Base environment
...Object.fromEntries(
Object.entries(baseEnv).filter(([, value]) => value !== void 0)
),
// Development-specific variables
VERCEL_DEV: "1",
RUST_LOG: process.env.RUST_LOG || "info",
// Runtime environment from meta
...meta.env || {}
};
Object.keys(devEnv).forEach((key) => {
if (devEnv[key] === void 0) {
delete devEnv[key];
}
});
(0, import_build_utils4.debug)(`Dev server environment: ${Object.keys(devEnv).join(", ")}`);
return devEnv;
}
// src/lib/start-dev-server.ts
var startDevServer = async (opts) => {
const { entrypoint, workPath, meta = {} } = opts;
try {
await installRustToolchain();
const executablePath = await buildExecutableForDev(workPath, entrypoint);
(0, import_build_utils5.debug)(`Starting Rust dev server: ${executablePath}`);
const devEnv = createDevServerEnv(process.env, meta);
const child = (0, import_child_process.spawn)(executablePath, [], {
cwd: workPath,
env: devEnv,
stdio: ["pipe", "pipe", "pipe"]
});
if (!child.pid) {
throw new Error("Failed to start dev server process");
}
(0, import_build_utils5.debug)(`Dev server process started with PID: ${child.pid}`);
let buffer = "";
let portEmitted = false;
child.stdout?.on("data", (data) => {
const output = data.toString();
buffer += output;
if (!portEmitted && buffer.includes("Dev server listening:")) {
const portMatch = buffer.match(/Dev server listening: (\d+)/);
if (portMatch) {
const port = parseInt(portMatch[1], 10);
(0, import_build_utils5.debug)(
`Rust dev server detected port ${port}, emitting message event`
);
child.emit("message", { port }, null);
portEmitted = true;
}
buffer = "";
}
console.log(output);
});
child.stderr?.on("data", (data) => {
console.error(data.toString());
});
child.on("error", (err) => {
(0, import_build_utils5.debug)(`Dev server error: ${err}`);
});
child.on("exit", (code, signal) => {
(0, import_build_utils5.debug)(`Dev server exited with code ${code}, signal ${signal}`);
});
const onMessage = (0, import_events.once)(child, "message");
const onExit = (0, import_events.once)(child, "close");
const result = await Promise.race([
onMessage.then((args) => {
const [messageData] = args;
return { state: "message", value: messageData };
}),
onExit.then((args) => {
const [code, signal] = args;
return { state: "exit", value: [code, signal] };
})
]);
if (result.state === "message") {
const { port } = result.value;
(0, import_build_utils5.debug)(`Rust dev server ready on port ${port}`);
if (!child.pid) {
throw new Error("Child process has no PID");
}
const shutdown = async () => {
try {
process.kill(child.pid, "SIGTERM");
} catch (err) {
(0, import_build_utils5.debug)(`Error terminating Rust dev server: ${err}`);
}
};
return { port, pid: child.pid, shutdown };
} else {
const [exitCode, signal] = result.value;
const reason = signal ? `"${signal}" signal` : `exit code ${exitCode}`;
throw new Error(`Rust dev server failed with ${reason}`);
}
} catch (error) {
(0, import_build_utils5.debug)(`Failed to start dev server: ${error}`);
return null;
}
};
// src/index.ts
async function buildHandler(options) {
const BUILDER_DEBUG = Boolean(process.env.VERCEL_BUILDER_DEBUG ?? false);
const isVercelBuild = Boolean(process.env.VERCEL_BUILD_IMAGE ?? false);
const { files, entrypoint, workPath, config, meta } = options;
const crossCompilationEnabled = !isVercelBuild && !meta?.isDev;
if (crossCompilationEnabled && process.platform === "win32") {
throw new Error(
"Production prebuilt deployments for @vercel/rust are not yet supported on Windows. Please use a Linux or macOS environment, or deploy directly on Vercel."
);
}
await installRustToolchain();
(0, import_build_utils6.debug)("Creating file system");
const downloadedFiles = await (0, import_build_utils6.download)(files, workPath, meta);
const entryPath = downloadedFiles[entrypoint].fsPath;
const HOME = process.platform === "win32" ? assertEnv("USERPROFILE") : assertEnv("HOME");
const PATH = assertEnv("PATH");
const rustEnv = {
PATH: `${import_node_path4.default.join(HOME, ".cargo/bin")}${import_node_path4.default.delimiter}${PATH}`,
RUSTFLAGS: [process.env.RUSTFLAGS].filter(Boolean).join(" ")
};
const cargoWorkspace = await findCargoWorkspace({
env: rustEnv,
cwd: import_node_path4.default.dirname(entryPath)
});
const binaryName = findBinaryName(cargoWorkspace, entryPath);
const cargoBuildConfiguration = await findCargoBuildConfiguration(cargoWorkspace);
await runUserScripts(workPath);
const extraFiles = await gatherExtraFiles(config.includeFiles, workPath);
const lambdaOptions = await (0, import_build_utils6.getLambdaOptionsFromFunction)({
sourceFile: entrypoint,
config
});
const architecture = lambdaOptions?.architecture || "x86_64";
const buildVariant = meta?.isDev ? "debug" : "release";
const buildTarget = cargoBuildConfiguration?.build.target ?? "";
try {
const args = crossCompilationEnabled ? [
"zigbuild",
"--target",
architecture === "x86_64" ? "x86_64-unknown-linux-gnu" : "aarch64-unknown-linux-gnu",
"--bin",
binaryName
].concat(BUILDER_DEBUG ? ["--verbose"] : ["--quiet"], ["--release"]) : ["build", "--bin", binaryName].concat(
BUILDER_DEBUG ? ["--verbose"] : ["--quiet"],
meta?.isDev ? [] : ["--release"]
);
(0, import_build_utils6.debug)(
`Running \`cargo build\` for \`${binaryName}\` (\`${architecture}\`)`
);
await (0, import_execa4.default)("cargo", args, {
cwd: workPath,
env: rustEnv
});
} catch (err) {
(0, import_build_utils6.debug)(`Running \`cargo build\` for \`${binaryName}\` failed`);
throw err;
}
(0, import_build_utils6.debug)(
`Building \`${binaryName}\` for \`${process.platform}\` (\`${architecture}\`) completed`
);
let { target_directory: targetDirectory } = await getCargoMetadata({
cwd: workPath,
env: rustEnv
});
if (crossCompilationEnabled) {
targetDirectory = import_node_path4.default.join(
targetDirectory,
architecture === "x86_64" ? "x86_64-unknown-linux-gnu" : "aarch64-unknown-linux-gnu"
);
}
targetDirectory = import_node_path4.default.join(targetDirectory, buildTarget);
const bin = import_node_path4.default.join(
targetDirectory,
buildVariant,
getExecutableName(binaryName)
);
const handler = getExecutableName("executable");
const executableFile = new import_build_utils6.FileFsRef({ mode: 493, fsPath: bin });
const lambda = new import_build_utils6.Lambda({
...lambdaOptions,
files: {
...extraFiles,
[handler]: executableFile
},
handler,
supportsResponseStreaming: true,
architecture,
runtime: "executable",
runtimeLanguage: "rust"
});
lambda.zipBuffer = await lambda.createZip();
(0, import_build_utils6.debug)(`generating function for \`${entrypoint}\``);
return {
output: lambda
};
}
var runtime = {
version: 3,
build: buildHandler,
prepareCache: async ({ workPath }) => {
(0, import_build_utils6.debug)(`Caching \`${workPath}\``);
const cacheFiles = await (0, import_build_utils6.glob)("target/**", workPath);
for (const f of Object.keys(cacheFiles)) {
const accept = /(?:^|\/)target\/release\/\.fingerprint\//.test(f) || /(?:^|\/)target\/release\/build\//.test(f) || /(?:^|\/)target\/release\/deps\//.test(f) || /(?:^|\/)target\/debug\/\.fingerprint\//.test(f) || /(?:^|\/)target\/debug\/build\//.test(f) || /(?:^|\/)target\/debug\/deps\//.test(f);
if (!accept) {
delete cacheFiles[f];
}
}
return cacheFiles;
},
startDevServer,
shouldServe: async (options) => {
(0, import_build_utils6.debug)(`Requested ${options.requestPath} for ${options.entrypoint}`);
return Promise.resolve(options.requestPath === options.entrypoint);
}
};
var { version, build, prepareCache, startDevServer: startDevServer2, shouldServe } = runtime;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
build,
prepareCache,
shouldServe,
startDevServer,
version
});