UNPKG

@vercel/node

Version:
1,410 lines (1,388 loc) 44.3 kB
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 __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; 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 )); // ../../node_modules/.pnpm/content-type@1.0.5/node_modules/content-type/index.js var require_content_type = __commonJS({ "../../node_modules/.pnpm/content-type@1.0.5/node_modules/content-type/index.js"(exports) { "use strict"; var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g; var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/; var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/; var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g; var QUOTE_REGEXP = /([\\"])/g; var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/; exports.format = format; exports.parse = parse; function format(obj) { if (!obj || typeof obj !== "object") { throw new TypeError("argument obj is required"); } var parameters = obj.parameters; var type = obj.type; if (!type || !TYPE_REGEXP.test(type)) { throw new TypeError("invalid type"); } var string = type; if (parameters && typeof parameters === "object") { var param; var params = Object.keys(parameters).sort(); for (var i = 0; i < params.length; i++) { param = params[i]; if (!TOKEN_REGEXP.test(param)) { throw new TypeError("invalid parameter name"); } string += "; " + param + "=" + qstring(parameters[param]); } } return string; } function parse(string) { if (!string) { throw new TypeError("argument string is required"); } var header = typeof string === "object" ? getcontenttype(string) : string; if (typeof header !== "string") { throw new TypeError("argument string is required to be a string"); } var index = header.indexOf(";"); var type = index !== -1 ? header.slice(0, index).trim() : header.trim(); if (!TYPE_REGEXP.test(type)) { throw new TypeError("invalid media type"); } var obj = new ContentType(type.toLowerCase()); if (index !== -1) { var key; var match; var value; PARAM_REGEXP.lastIndex = index; while (match = PARAM_REGEXP.exec(header)) { if (match.index !== index) { throw new TypeError("invalid parameter format"); } index += match[0].length; key = match[1].toLowerCase(); value = match[2]; if (value.charCodeAt(0) === 34) { value = value.slice(1, -1); if (value.indexOf("\\") !== -1) { value = value.replace(QESC_REGEXP, "$1"); } } obj.parameters[key] = value; } if (index !== header.length) { throw new TypeError("invalid parameter format"); } } return obj; } function getcontenttype(obj) { var header; if (typeof obj.getHeader === "function") { header = obj.getHeader("content-type"); } else if (typeof obj.headers === "object") { header = obj.headers && obj.headers["content-type"]; } if (typeof header !== "string") { throw new TypeError("content-type header is missing from object"); } return header; } function qstring(val) { var str = String(val); if (TOKEN_REGEXP.test(str)) { return str; } if (str.length > 0 && !TEXT_REGEXP.test(str)) { throw new TypeError("invalid parameter value"); } return '"' + str.replace(QUOTE_REGEXP, "\\$1") + '"'; } function ContentType(type) { this.parameters = /* @__PURE__ */ Object.create(null); this.type = type; } } }); // ../../node_modules/.pnpm/cookie@0.7.0/node_modules/cookie/index.js var require_cookie = __commonJS({ "../../node_modules/.pnpm/cookie@0.7.0/node_modules/cookie/index.js"(exports) { "use strict"; exports.parse = parse; exports.serialize = serialize; var __toString = Object.prototype.toString; var cookieNameRegExp = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/; var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/; var domainValueRegExp = /^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i; var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/; function parse(str, options) { if (typeof str !== "string") { throw new TypeError("argument str must be a string"); } var obj = {}; var len = str.length; var max = len - 2; if (max < 0) return obj; var dec = options && options.decode || decode; var index = 0; var eqIdx = 0; var endIdx = 0; do { eqIdx = str.indexOf("=", index); if (eqIdx === -1) { break; } endIdx = str.indexOf(";", index); if (endIdx === -1) { endIdx = len; } else if (eqIdx > endIdx) { index = str.lastIndexOf(";", eqIdx - 1) + 1; continue; } var keyStartIdx = startIndex(str, index, eqIdx); var keyEndIdx = endIndex(str, eqIdx, keyStartIdx); var key = str.slice(keyStartIdx, keyEndIdx); if (void 0 === obj[key]) { var valStartIdx = startIndex(str, eqIdx + 1, endIdx); var valEndIdx = endIndex(str, endIdx, valStartIdx); if (str.charCodeAt(valStartIdx) === 34 && str.charCodeAt(valEndIdx - 1) === 34) { valStartIdx++; valEndIdx--; } var val = str.slice(valStartIdx, valEndIdx); obj[key] = tryDecode(val, dec); } index = endIdx + 1; } while (index < max); return obj; } function startIndex(str, index, max) { do { var code = str.charCodeAt(index); if (code !== 32 && code !== 9) return index; } while (++index < max); return max; } function endIndex(str, index, min) { while (index > min) { var code = str.charCodeAt(--index); if (code !== 32 && code !== 9) return index + 1; } return min; } function serialize(name, val, options) { var opt = options || {}; var enc = opt.encode || encode; if (typeof enc !== "function") { throw new TypeError("option encode is invalid"); } if (!cookieNameRegExp.test(name)) { throw new TypeError("argument name is invalid"); } var value = enc(val); if (value && !cookieValueRegExp.test(value)) { throw new TypeError("argument val is invalid"); } var str = name + "=" + value; if (null != opt.maxAge) { var maxAge = opt.maxAge - 0; if (!isFinite(maxAge)) { throw new TypeError("option maxAge is invalid"); } str += "; Max-Age=" + Math.floor(maxAge); } if (opt.domain) { if (!domainValueRegExp.test(opt.domain)) { throw new TypeError("option domain is invalid"); } str += "; Domain=" + opt.domain; } if (opt.path) { if (!pathValueRegExp.test(opt.path)) { throw new TypeError("option path is invalid"); } str += "; Path=" + opt.path; } if (opt.expires) { var expires = opt.expires; if (!isDate(expires) || isNaN(expires.valueOf())) { throw new TypeError("option expires is invalid"); } str += "; Expires=" + expires.toUTCString(); } if (opt.httpOnly) { str += "; HttpOnly"; } if (opt.secure) { str += "; Secure"; } if (opt.partitioned) { str += "; Partitioned"; } if (opt.priority) { var priority = typeof opt.priority === "string" ? opt.priority.toLowerCase() : opt.priority; switch (priority) { case "low": str += "; Priority=Low"; break; case "medium": str += "; Priority=Medium"; break; case "high": str += "; Priority=High"; break; default: throw new TypeError("option priority is invalid"); } } if (opt.sameSite) { var sameSite = typeof opt.sameSite === "string" ? opt.sameSite.toLowerCase() : opt.sameSite; switch (sameSite) { case true: str += "; SameSite=Strict"; break; case "lax": str += "; SameSite=Lax"; break; case "strict": str += "; SameSite=Strict"; break; case "none": str += "; SameSite=None"; break; default: throw new TypeError("option sameSite is invalid"); } } return str; } function decode(str) { return str.indexOf("%") !== -1 ? decodeURIComponent(str) : str; } function encode(val) { return encodeURIComponent(val); } function isDate(val) { return __toString.call(val) === "[object Date]" || val instanceof Date; } function tryDecode(str, decode2) { try { return decode2(str); } catch (e) { return str; } } } }); // src/serverless-functions/helpers-web.ts var helpers_web_exports = {}; __export(helpers_web_exports, { createWebExportsHandler: () => createWebExportsHandler }); import { buildToNodeHandler } from "@edge-runtime/node-utils"; function addDuplexToInit(init2) { if (typeof init2 === "undefined" || typeof init2 === "object") { return { duplex: "half", ...init2 }; } return init2; } function defaultHttpHandler(_, res) { res.statusCode = 405; res.end(); } var createWebExportsHandler; var init_helpers_web = __esm({ "src/serverless-functions/helpers-web.ts"() { "use strict"; createWebExportsHandler = (awaiter) => { const webHandlerToNodeHandler = buildToNodeHandler( { Headers, ReadableStream, // @ts-expect-error Property 'duplex' is missing in type 'Request' Request: class extends Request { constructor(input, init2) { super(input, addDuplexToInit(init2)); } }, Uint8Array, // @ts-expect-error Property 'waitUntil' is missing in type 'FetchEvent' FetchEvent: class { constructor() { this.waitUntil = (promise) => awaiter.waitUntil(promise); } } }, { defaultOrigin: "https://vercel.com" } ); function getWebExportsHandler(listener, methods) { const handlerByMethod = {}; for (const key of methods) { handlerByMethod[key] = typeof listener[key] !== "undefined" ? webHandlerToNodeHandler(listener[key]) : defaultHttpHandler; } return (req, res) => { const method = req.method ?? "GET"; handlerByMethod[method](req, res); }; } return getWebExportsHandler; }; } }); // src/dev-server.mts import { join } from "path"; import { getLambdaOptionsFromFunction } from "@vercel/build-utils"; // src/edge-functions/edge-wasm-plugin.mts import { createHash } from "crypto"; import { promises as fs } from "fs"; var WasmAssets = class { constructor() { this.assets = /* @__PURE__ */ new Map(); } /** * Declare a WebAssembly binding */ async declare(filePath) { const hash = sha1(await fs.readFile(filePath)); const name = `wasm_${hash}`; this.assets.set(name, filePath); return name; } /** * Get an object with the context needed to execute the code * built with the plugin */ async getContext() { const promises = []; const context = {}; for (const [name, filePath] of this.assets) { promises.push( (async () => { const bytes = await fs.readFile(filePath); context[name] = await WebAssembly.compile(bytes); })() ); } await Promise.all(promises); return context; } /** * Allow to iterate easily */ [Symbol.iterator]() { return this.assets[Symbol.iterator](); } }; function createEdgeWasmPlugin() { const wasmAssets = new WasmAssets(); const plugin = { name: "vercel-wasm", setup(b) { b.onResolve({ filter: /\.wasm\?module/i }, async (data) => { const wasmFile = data.path.replace(/\?module$/, ""); const resolvedPath = await b.resolve(wasmFile, { importer: data.importer, resolveDir: data.resolveDir }); if (!resolvedPath.path) { return { errors: [ { text: `WebAssembly file could not be located: ${wasmFile}` } ] }; } const name = await wasmAssets.declare(resolvedPath.path); return { path: name, namespace: "vercel-wasm" }; }); b.onLoad({ namespace: "vercel-wasm", filter: /.+/ }, (args) => { return { loader: "js", contents: `export default globalThis[${JSON.stringify(args.path)}]` }; }); } }; return { plugin, wasmAssets }; } function sha1(data) { return createHash("sha1").update(data).digest("hex"); } // src/edge-functions/edge-node-compat-plugin.mts import BufferImplementation from "buffer"; import EventsImplementation from "events"; import AsyncHooksImplementation from "async_hooks"; import AssertImplementation from "assert"; import UtilImplementation from "util"; var SUPPORTED_NODE_MODULES = [ "buffer", "events", "assert", "util", "async_hooks" ]; var getSupportedNodeModuleRegex = () => new RegExp(`^(?:node:)?(?:${SUPPORTED_NODE_MODULES.join("|")})$`); function pick(obj, keys) { const res = {}; for (const key of keys) { res[key] = obj[key]; } return res; } var NativeModuleMap = () => { const mods = { buffer: pick(BufferImplementation, [ "constants", "kMaxLength", "kStringMaxLength", "Buffer", "SlowBuffer" ]), events: pick(EventsImplementation, [ "EventEmitter", "captureRejectionSymbol", "defaultMaxListeners", "errorMonitor", "listenerCount", "on", "once" ]), async_hooks: pick(AsyncHooksImplementation, [ "AsyncLocalStorage", "AsyncResource" ]), assert: pick(AssertImplementation, [ "AssertionError", "deepEqual", "deepStrictEqual", "doesNotMatch", "doesNotReject", "doesNotThrow", "equal", "fail", "ifError", "match", "notDeepEqual", "notDeepStrictEqual", "notEqual", "notStrictEqual", "ok", "rejects", "strict", "strictEqual", "throws" ]), util: pick(UtilImplementation, [ "_extend", "callbackify", "format", "inherits", "promisify", "types" ]) }; return new Map(Object.entries(mods)); }; var NODE_COMPAT_NAMESPACE = "vercel-node-compat"; var NodeCompatBindings = class { constructor() { this.bindings = /* @__PURE__ */ new Map(); } use(modulePath) { const stripped = modulePath.replace(/^node:/, ""); const name = `__vc_node_${stripped}__`; if (!this.bindings.has(modulePath)) { const value = NativeModuleMap().get(stripped); if (value === void 0) { throw new Error(`Could not find module ${modulePath}`); } this.bindings.set(modulePath, { modulePath, name, value }); } return name; } getContext() { const context = {}; for (const binding of this.bindings.values()) { context[binding.name] = binding.value; } return context; } }; function createNodeCompatPlugin() { const bindings = new NodeCompatBindings(); const plugin = { name: "vc-node-compat", setup(b) { b.onResolve({ filter: getSupportedNodeModuleRegex() }, async (args) => { const importee = args.path.replace("node:", ""); if (!SUPPORTED_NODE_MODULES.includes(importee)) { return; } return { namespace: NODE_COMPAT_NAMESPACE, path: args.path }; }); b.onLoad( { filter: /.+/, namespace: NODE_COMPAT_NAMESPACE }, async (args) => { const fullName = args.path.startsWith("node:") ? args.path : `node:${args.path}`; const globalName = bindings.use(fullName); return { contents: `module.exports = ${globalName};`, loader: "js" }; } ); } }; return { plugin, bindings }; } // src/edge-functions/edge-handler.mts import { EdgeRuntime, runServer } from "edge-runtime"; import { Headers as Headers2, request as undiciRequest } from "undici"; import { isError } from "@vercel/error-utils"; import { readFileSync } from "fs"; // src/utils.ts import { debug, streamToBuffer } from "@vercel/build-utils"; import { extname } from "path"; import { pathToRegexp as pathToRegexpCurrent } from "path-to-regexp"; import { pathToRegexp as pathToRegexpUpdated } from "path-to-regexp-updated"; var WAIT_UNTIL_TIMEOUT = 30; var waitUntilWarning = (entrypointPath, maxDuration) => ` The function \`${entrypointPath.split("/").pop()}\` is still running after ${maxDuration}s. (hint: do you have a long-running waitUntil() promise?) `.trim(); function entrypointToOutputPath(entrypoint2, zeroConfig) { if (zeroConfig) { const ext = extname(entrypoint2); return entrypoint2.slice(0, entrypoint2.length - ext.length); } return entrypoint2; } function logError(error) { let message = error.message; if (!message.startsWith("Error:")) { message = `Error: ${message}`; } console.error(message); if (error.stack) { const errorPrefixLength = "Error: ".length; const errorMessageLength = errorPrefixLength + error.message.length; debug(error.stack.substring(errorMessageLength + 1)); } } var EdgeRuntimes = /* @__PURE__ */ ((EdgeRuntimes2) => { EdgeRuntimes2["Edge"] = "edge"; EdgeRuntimes2["ExperimentalEdge"] = "experimental-edge"; return EdgeRuntimes2; })(EdgeRuntimes || {}); function isEdgeRuntime(runtime) { return runtime !== void 0 && Object.values(EdgeRuntimes).includes(runtime); } var ALLOWED_RUNTIMES = [...Object.values(EdgeRuntimes), "nodejs"]; function validateConfiguredRuntime(runtime, entrypoint2) { if (runtime) { if (!ALLOWED_RUNTIMES.includes(runtime)) { throw new Error( `${entrypoint2}: unsupported "runtime" value in \`config\`: ${JSON.stringify( runtime )} (must be one of: ${JSON.stringify( ALLOWED_RUNTIMES )}). Learn more: https://vercel.link/creating-edge-functions` ); } } } async function serializeBody(request) { return request.method !== "GET" && request.method !== "HEAD" ? await streamToBuffer(request) : void 0; } // src/edge-functions/edge-handler.mts import esbuild from "esbuild"; import { buildToHeaders } from "@edge-runtime/node-utils"; import { fileURLToPath } from "url"; // src/awaiter.ts var Awaiter = class { constructor({ onError } = {}) { this.promises = /* @__PURE__ */ new Set(); this.awaiting = () => this.waitForBatch().then( () => this.promises.size > 0 ? this.waitForBatch() : Promise.resolve() ); this.waitUntil = (promise) => { this.promises.add(promise); }; this.waitForBatch = async () => { const promises = Array.from(this.promises); this.promises.clear(); await Promise.all( promises.map( (promise) => Promise.resolve(promise).then(() => void 0, this.onError) ) ); }; this.onError = onError ?? console.error; } }; // src/edge-functions/edge-handler.mts var NODE_VERSION_MAJOR = process.version.match(/^v(\d+)\.\d+/)?.[1]; var NODE_VERSION_IDENTIFIER = `node${NODE_VERSION_MAJOR}`; if (!NODE_VERSION_MAJOR) { throw new Error( `Unable to determine current node version: process.version=${process.version}` ); } var toHeaders = buildToHeaders({ Headers: Headers2 }); var __dirname = fileURLToPath(new URL(".", import.meta.url)); var edgeHandlerTemplate = readFileSync( `${__dirname}/edge-handler-template.js` ); async function compileUserCode(entrypointFullPath, entrypointRelativePath, isMiddleware) { const { wasmAssets, plugin: edgeWasmPlugin } = createEdgeWasmPlugin(); const nodeCompatPlugin = createNodeCompatPlugin(); try { const result = await esbuild.build({ // bundling behavior: use globals (like "browser") instead // of "require" statements for core libraries (like "node") platform: "browser", conditions: ["edge-light", "development"], // target syntax: only use syntax available on the current // version of node target: NODE_VERSION_IDENTIFIER, sourcemap: "inline", legalComments: "none", bundle: true, plugins: [ edgeWasmPlugin, nodeCompatPlugin.plugin, { name: "import.meta.url", setup({ onLoad }) { onLoad({ filter: /\.[cm]?js$/, namespace: "file" }, (args) => { let code = readFileSync(args.path, "utf8"); code = code.replace( /\bimport\.meta\.url\b/g, JSON.stringify(import.meta.url) ); return { contents: code }; }); } } ], entryPoints: [entrypointFullPath], write: false, // operate in memory format: "cjs" }); const compiledFile = result.outputFiles?.[0]; if (!compiledFile) { throw new Error( `Compilation of ${entrypointRelativePath} produced no output files.` ); } const userCode = ` // strict mode "use strict";var regeneratorRuntime; // user code (() => { ${compiledFile.text}; })(); const userModule = module.exports; // request metadata const isMiddleware = ${isMiddleware}; const entrypointLabel = '${entrypointRelativePath}'; // edge handler ${edgeHandlerTemplate}; const dependencies = { Request, Response }; const options = { isMiddleware, entrypointLabel }; registerFetchListener(userModule, options, dependencies); `; return { entrypointPath: entrypointFullPath, userCode, wasmAssets, nodeCompatBindings: nodeCompatPlugin.bindings, awaiter: new Awaiter() }; } catch (error) { console.error(`Failed to compile user code for edge runtime.`); if (isError(error)) logError(error); return void 0; } } async function createEdgeRuntimeServer(maxDuration, params) { try { if (!params) { return void 0; } const wasmBindings = await params.wasmAssets.getContext(); const nodeCompatBindings = params.nodeCompatBindings.getContext(); const runtime = new EdgeRuntime({ initialCode: params.userCode, extend: (context) => { Object.assign(context, { // This is required for esbuild wrapping logic to resolve module: {}, // This is required for environment variable access. // In production, env var access is provided by static analysis // so that only the used values are available. process: { env: process.env }, // These are the global bindings for Node.js compatibility ...nodeCompatBindings, // These are the global bindings for WebAssembly module ...wasmBindings, FetchEvent: class extends context.FetchEvent { constructor() { super(...arguments); this.waitUntil = (promise) => { params.awaiter.waitUntil(promise); }; } } }); return context; } }); const server = await runServer({ runtime }); runtime.context.globalThis[Symbol.for("@vercel/request-context")] = { get: () => ({ waitUntil: params.awaiter.waitUntil.bind(params.awaiter) }) }; const onExit2 = () => new Promise((resolve, reject) => { const timeout = setTimeout(() => { console.warn(waitUntilWarning(params.entrypointPath, maxDuration)); resolve(); }, maxDuration * 1e3); Promise.all([params.awaiter.awaiting(), server.close()]).then(() => resolve()).catch(reject).finally(() => clearTimeout(timeout)); }); return { server, onExit: onExit2 }; } catch (error) { console.error("Failed to instantiate edge runtime."); logError(error); return void 0; } } async function createEdgeEventHandler(entrypointFullPath, entrypointRelativePath, isMiddleware, isZeroConfig, maxDuration = WAIT_UNTIL_TIMEOUT) { const userCode = await compileUserCode( entrypointFullPath, entrypointRelativePath, isMiddleware ); const result = await createEdgeRuntimeServer(maxDuration, userCode); const server = result?.server; const onExit2 = result?.onExit; const handler = async function(request) { if (!server) { process.exit(1); } const body = await serializeBody(request); if (body !== void 0 && body.length) { request.headers["content-length"] = String(body.length); request.headers["transfer-encoding"] = void 0; } const url = new URL(request.url ?? "/", server.url); const response = await undiciRequest(url, { body, headers: request.headers, method: request.method || "GET" }); const resHeaders = toHeaders(response.headers); const isUserError = resHeaders.get("x-vercel-failed") === "edge-wrapper"; if (isUserError && response.statusCode >= 500) { const body2 = await response.body.text(); const fakeStackTrace = ` at (${entrypointRelativePath})`; const requestPath = entrypointToRequestPath( entrypointRelativePath, isZeroConfig ); console.log( `Error from API Route ${requestPath}: ${body2} ${fakeStackTrace}` ); process.exit(1); } return { status: response.statusCode, headers: resHeaders, body: response.body, encoding: "utf8" }; }; return { handler, onExit: onExit2 }; } function entrypointToRequestPath(entrypointRelativePath, isZeroConfig) { return "/" + entrypointToOutputPath(entrypointRelativePath, isZeroConfig); } // src/dev-server.mts import { createServer as createServer2 } from "http"; // src/serverless-functions/helpers.ts var import_content_type = __toESM(require_content_type()); import { PassThrough } from "stream"; import { parse as parseURL } from "url"; import { parse as parseQS } from "querystring"; import etag from "etag"; var ApiError = class extends Error { constructor(statusCode, message) { super(message); this.statusCode = statusCode; } }; function normalizeContentType(contentType) { if (!contentType) { return "text/plain"; } const { type } = (0, import_content_type.parse)(contentType); return type; } function getBodyParser(body, contentType) { return function parseBody() { const type = normalizeContentType(contentType); if (type === "application/json") { try { const str = body.toString(); return str ? JSON.parse(str) : {}; } catch (error) { throw new ApiError(400, "Invalid JSON"); } } if (type === "application/octet-stream") return body; if (type === "application/x-www-form-urlencoded") { return parseQS(body.toString()); } if (type === "text/plain") return body.toString(); return void 0; }; } function getQueryParser({ url = "/" }) { return function parseQuery() { return parseURL(url, true).query; }; } function getCookieParser(req) { return function parseCookie() { const header = req.headers.cookie; if (!header) return {}; const { parse } = require_cookie(); return parse(Array.isArray(header) ? header.join(";") : header); }; } function status(res, statusCode) { res.statusCode = statusCode; return res; } function setCharset(type, charset) { const { parse, format } = require_content_type(); const parsed = parse(type); parsed.parameters.charset = charset; return format(parsed); } function redirect(res, statusOrUrl, url) { if (typeof statusOrUrl === "string") { url = statusOrUrl; statusOrUrl = 307; } if (typeof statusOrUrl !== "number" || typeof url !== "string") { throw new Error( `Invalid redirect arguments. Please use a single argument URL, e.g. res.redirect('/destination') or use a status code and URL, e.g. res.redirect(307, '/destination').` ); } res.writeHead(statusOrUrl, { Location: url }).end(); return res; } function setLazyProp(req, prop, getter) { const opts = { configurable: true, enumerable: true }; const optsReset = { ...opts, writable: true }; Object.defineProperty(req, prop, { ...opts, get: () => { const value = getter(); Object.defineProperty(req, prop, { ...optsReset, value }); return value; }, set: (value) => { Object.defineProperty(req, prop, { ...optsReset, value }); } }); } function createETag(body, encoding) { const buf = !Buffer.isBuffer(body) ? Buffer.from(body, encoding) : body; return etag(buf, { weak: true }); } function json(req, res, jsonBody) { const body = JSON.stringify(jsonBody); if (!res.getHeader("content-type")) { res.setHeader("content-type", "application/json; charset=utf-8"); } return send(req, res, body); } function send(req, res, body) { let chunk = body; let encoding; switch (typeof chunk) { case "string": if (!res.getHeader("content-type")) { res.setHeader("content-type", "text/html"); } break; case "boolean": case "number": case "object": if (chunk === null) { chunk = ""; } else if (Buffer.isBuffer(chunk)) { if (!res.getHeader("content-type")) { res.setHeader("content-type", "application/octet-stream"); } } else { return json(req, res, chunk); } break; } if (typeof chunk === "string") { encoding = "utf8"; const type = res.getHeader("content-type"); if (typeof type === "string") { res.setHeader("content-type", setCharset(type, "utf-8")); } } let len; if (chunk !== void 0) { if (Buffer.isBuffer(chunk)) { len = chunk.length; } else if (typeof chunk === "string") { if (chunk.length < 1e3) { len = Buffer.byteLength(chunk, encoding); } else { const buf = Buffer.from(chunk, encoding); len = buf.length; chunk = buf; encoding = void 0; } } else { throw new Error( "`body` is not a valid string, object, boolean, number, Stream, or Buffer" ); } if (len !== void 0) { res.setHeader("content-length", len); } } let etag2; if (!res.getHeader("etag") && len !== void 0 && (etag2 = createETag(chunk, encoding))) { res.setHeader("etag", etag2); } if (204 === res.statusCode || 304 === res.statusCode) { res.removeHeader("Content-Type"); res.removeHeader("Content-Length"); res.removeHeader("Transfer-Encoding"); chunk = ""; } if (req.method === "HEAD") { res.end(); } else if (encoding) { res.end(chunk, encoding); } else { res.end(chunk); } return res; } function restoreBody(req, body) { const replicateBody = new PassThrough(); const on = replicateBody.on.bind(replicateBody); const originalOn = req.on.bind(req); req.read = replicateBody.read.bind(replicateBody); req.on = req.addListener = (name, cb) => ( // @ts-expect-error name === "data" || name === "end" ? on(name, cb) : originalOn(name, cb) ); replicateBody.write(body); replicateBody.end(); } async function readBody(req) { const body = await serializeBody(req) || Buffer.from(""); restoreBody(req, body); return body; } async function addHelpers(_req, _res) { const req = _req; const res = _res; setLazyProp(req, "cookies", getCookieParser(req)); setLazyProp(req, "query", getQueryParser(req)); const contentType = req.headers["content-type"]; const body = contentType === void 0 ? Buffer.from("") : await readBody(req); setLazyProp(req, "body", getBodyParser(body, contentType)); res.status = (statusCode) => status(res, statusCode); res.redirect = (statusOrUrl, url) => redirect(res, statusOrUrl, url); res.send = (body2) => send(req, res, body2); res.json = (jsonBody) => json(req, res, jsonBody); } // src/serverless-functions/serverless-handler.mts import { createServer } from "http"; import { Headers as Headers3, request as undiciRequest2 } from "undici"; import { listen } from "async-listen"; import { isAbsolute } from "path"; import { pathToFileURL } from "url"; import { buildToHeaders as buildToHeaders2 } from "@edge-runtime/node-utils"; import { promisify } from "util"; import http from "http"; var toHeaders2 = buildToHeaders2({ Headers: Headers3 }); var HTTP_METHODS = [ "GET", "HEAD", "OPTIONS", "POST", "PUT", "DELETE", "PATCH" ]; async function createServerlessServer(userCode) { let server; if (typeof userCode === "function") { server = createServer(userCode); } else { server = userCode; } return { url: await listen(server, { host: "127.0.0.1", port: 0 }), onExit: promisify(server.close.bind(server)) }; } async function compileUserCode2(entrypointPath, awaiter, options) { const id = isAbsolute(entrypointPath) ? pathToFileURL(entrypointPath).href : entrypointPath; let server = null; let serverFound = () => { }; const originalListen = http.Server.prototype.listen; http.Server.prototype.listen = function() { server = this; http.Server.prototype.listen = originalListen; serverFound(); return this; }; let listener = await import(id); for (let i = 0; i < 5; i++) { if (listener.default) listener = listener.default; } const shouldUseWebHandlers = options.isMiddleware || HTTP_METHODS.some((method) => typeof listener[method] === "function") || typeof listener.fetch === "function"; if (shouldUseWebHandlers) { http.Server.prototype.listen = originalListen; const { createWebExportsHandler: createWebExportsHandler2 } = await Promise.resolve().then(() => (init_helpers_web(), helpers_web_exports)); const getWebExportsHandler = createWebExportsHandler2(awaiter); let handler = listener; if (options.isMiddleware) { handler = HTTP_METHODS.reduce( (acc, method) => { acc[method] = listener; return acc; }, {} ); } if (typeof listener.fetch === "function") { handler = HTTP_METHODS.reduce( (acc, method) => { acc[method] = listener.fetch; return acc; }, {} ); } return getWebExportsHandler(handler, HTTP_METHODS); } if (typeof listener === "function") { http.Server.prototype.listen = originalListen; return async (req, res) => { if (options.shouldAddHelpers && typeof listener.listen !== "function") { await addHelpers(req, res); } return listener(req, res); }; } if (!server) { await new Promise((resolve) => { serverFound = resolve; const maxTimeToWaitForServer = 1e3; setTimeout(resolve, maxTimeToWaitForServer); }); } http.Server.prototype.listen = originalListen; if (server) { return server; } throw new Error("Can't detect way to handle request"); } async function createServerlessEventHandler(entrypointPath, options, maxDuration = WAIT_UNTIL_TIMEOUT) { const awaiter = new Awaiter(); Object.defineProperty(globalThis, Symbol.for("@vercel/request-context"), { enumerable: false, configurable: true, value: { get: () => ({ waitUntil: awaiter.waitUntil.bind(awaiter) }) } }); const userCode = await compileUserCode2(entrypointPath, awaiter, options); const server = await createServerlessServer(userCode); const isStreaming = options.mode === "streaming"; const handler = async function(request) { const url = new URL(request.url ?? "/", server.url); const response = await undiciRequest2(url, { body: await serializeBody(request), headers: { ...request.headers, host: request.headers["x-forwarded-host"] }, method: request.method || "GET" }); let body = null; let headers = toHeaders2(response.headers); if (isStreaming) { body = response.body; } else { body = Buffer.from(await response.body.arrayBuffer()); } return { status: response.statusCode, headers, body, encoding: "utf8" }; }; const onExit2 = () => new Promise((resolve, reject) => { const timeout = setTimeout(() => { console.warn(waitUntilWarning(entrypointPath, maxDuration)); resolve(); }, maxDuration * 1e3); Promise.all([awaiter.awaiting(), server.onExit()]).then(() => resolve()).catch(reject).finally(() => clearTimeout(timeout)); }); return { handler, onExit: onExit2 }; } // src/dev-server.mts import { init, parse as parseEsm } from "es-module-lexer"; import { parse as parseCjs } from "cjs-module-lexer"; import { getConfig } from "@vercel/static-config"; import { Project } from "ts-morph"; import { listen as listen2 } from "async-listen"; import { readFile } from "fs/promises"; var entrypoint = process.env.VERCEL_DEV_ENTRYPOINT; delete process.env.VERCEL_DEV_ENTRYPOINT; if (!entrypoint) { throw new Error("`VERCEL_DEV_ENTRYPOINT` must be defined"); } var parseConfig = (entryPointPath) => getConfig(new Project(), entryPointPath); async function createEventHandler(entrypoint2, config, options) { const entrypointPath = join(process.cwd(), entrypoint2); const staticConfig = parseConfig(entrypointPath); const runtime = staticConfig?.runtime; validateConfiguredRuntime(runtime, entrypoint2); const { maxDuration } = await getLambdaOptionsFromFunction({ sourceFile: entrypoint2, config }); const isMiddleware = config.middleware === true; const useEdgeRuntime = isMiddleware && !runtime || isEdgeRuntime(runtime); if (useEdgeRuntime) { return createEdgeEventHandler( entrypointPath, entrypoint2, isMiddleware, config.zeroConfig, maxDuration ); } const content = await readFile(entrypointPath, "utf8"); const isStreaming = staticConfig?.supportsResponseStreaming || isMiddleware || await hasWebHandlers(async () => parseCjs(content).exports) || await hasWebHandlers( async () => init.then(() => parseEsm(content)[1].map((specifier) => specifier.n)) ); return createServerlessEventHandler(entrypointPath, { mode: isStreaming ? "streaming" : "buffer", shouldAddHelpers: isMiddleware ? false : options.shouldAddHelpers, maxDuration, isMiddleware }); } async function hasWebHandlers(getExports) { const exports = await getExports().catch(() => []); for (const name of exports) { if (HTTP_METHODS.includes(name) || name === "default" || name === "fetch") { return true; } } return false; } var handleEvent; var handlerEventError; var onExit; async function main() { const config = JSON.parse(process.env.VERCEL_DEV_CONFIG || "{}"); delete process.env.VERCEL_DEV_CONFIG; const buildEnv = JSON.parse(process.env.VERCEL_DEV_BUILD_ENV || "{}"); delete process.env.VERCEL_DEV_BUILD_ENV; const shouldAddHelpers = !(config.helpers === false || buildEnv.NODEJS_HELPERS === "0"); const proxyServer = createServer2(onDevRequest); await listen2(proxyServer, { host: "127.0.0.1", port: 0 }); try { const result = await createEventHandler(entrypoint, config, { shouldAddHelpers }); handleEvent = result.handler; onExit = result.onExit; } catch (error) { logError(error); handlerEventError = error; } const address = proxyServer.address(); if (typeof process.send === "function") { process.send(address); } else { console.log("Dev server listening:", address); } } async function onDevRequest(req, res) { if (handlerEventError) { process.exit(1); } const publicDir = process.env.VERCEL_DEV_PUBLIC_DIR; if (publicDir && req.url) { const { join: join2 } = await import("path"); const { existsSync, statSync } = await import("fs"); const { readFile: readFile2 } = await import("fs/promises"); const staticPath = join2(process.cwd(), publicDir, req.url); if (existsSync(staticPath) && statSync(staticPath).isFile()) { try { const content = await readFile2(staticPath); const { extname: extname2 } = await import("path"); const { contentType } = await import("mime-types"); const url = new URL(req.url || "/", "http://localhost"); const ext = extname2(url.pathname); const mimeType = contentType(ext) || "application/octet-stream"; res.setHeader("Content-Type", mimeType); res.setHeader("Content-Length", content.length); res.statusCode = 200; res.end(content); return; } catch (error) { } } } if (!handleEvent) { res.statusCode = 500; res.end("Bridge is not ready, please try again"); return; } try { const { headers, body, status: status2 } = await handleEvent(req); res.statusCode = status2; headers.delete("transfer-encoding"); for (const [key, value] of headers) { if (value !== void 0) res.setHeader( key, key === "set-cookie" ? headers.getSetCookie() : value ); } if (body === null) { res.end(); } else if (body instanceof Buffer) { res.end(body); } else { body.pipe(res); } } catch (error) { res.statusCode = 500; res.end(error.stack); } } main().catch((err) => { logError(err); process.exit(1); }); process.on("message", async (m) => { switch (m) { case "shutdown": if (onExit) { await onExit(); } process.exit(0); break; default: console.error(`unknown IPC message from parent:`, m); break; } }); process.on("SIGTERM", async () => { if (onExit) { await onExit(); } process.exit(0); }); /*! Bundled license information: content-type/index.js: (*! * content-type * Copyright(c) 2015 Douglas Christopher Wilson * MIT Licensed *) cookie/index.js: (*! * cookie * Copyright(c) 2012-2014 Roman Shtylman * Copyright(c) 2015 Douglas Christopher Wilson * MIT Licensed *) */