Node.js runtime for Vercel Functions that enables serverless execution of JavaScript and TypeScript code with automatic dependency bundling and TypeScript compilation
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The API handler types provide enhanced request and response objects for Vercel serverless functions, extending Node.js's standard HTTP interfaces with automatic parsing and convenience methods.
import { NowRequest, NowResponse, NowApiHandler } from "@vercel/node";Enhanced IncomingMessage with automatic parsing of query parameters, cookies, and request body.
type NowRequest = IncomingMessage & {
query: NowRequestQuery;
cookies: NowRequestCookies;
body: NowRequestBody;
};Automatically parsed URL query parameters.
type NowRequestQuery = { [key: string]: string | string[] };export default function handler(req: NowRequest, res: NowResponse) {
// Single value: ?name=john -> { name: "john" }
const name = req.query.name as string;
// Multiple values: ?tags=a&tags=b -> { tags: ["a", "b"] }
const tags = req.query.tags;
// Handle both cases
const tagsArray = Array.isArray(tags) ? tags : [tags];
}Automatically parsed HTTP cookies.
type NowRequestCookies = { [key: string]: string };export default function handler(req: NowRequest, res: NowResponse) {
// Access cookies directly
const authToken = req.cookies.auth_token;
const userId = req.cookies.user_id;
if (!authToken) {
return res.status(401).json({ error: "Authentication required" });
}
}Automatically parsed request body based on Content-Type header.
type NowRequestBody = any;Supported content types:
application/json: Parsed as JavaScript objectapplication/x-www-form-urlencoded: Parsed as key-value objectapplication/octet-stream: Raw Buffertext/plain: Stringundefinedexport default function handler(req: NowRequest, res: NowResponse) {
if (req.method === "POST") {
// JSON body
const { name, email } = req.body;
// Form data body
const formData = req.body; // { field1: "value1", field2: "value2" }
// Raw body (when Content-Type is application/octet-stream)
const buffer = req.body as Buffer;
}
}Enhanced ServerResponse with convenience methods for common response patterns.
type NowResponse = ServerResponse & {
send: (body: any) => NowResponse;
json: (jsonBody: any) => NowResponse;
status: (statusCode: number) => NowResponse;
redirect: (statusOrUrl: string | number, url?: string) => NowResponse;
};Sends response body with automatic content-type detection.
send(body: any): NowResponse;export default function handler(req: NowRequest, res: NowResponse) {
// Send string (Content-Type: text/html)
res.send("Hello World");
// Send object (automatically calls res.json)
res.send({ message: "Hello World" });
// Send Buffer (Content-Type: application/octet-stream)
res.send(Buffer.from("binary data"));
// Send number or boolean (converted to JSON)
res.send(42);
res.send(true);
}Sends JSON response with proper content-type.
json(jsonBody: any): NowResponse;export default function handler(req: NowRequest, res: NowResponse) {
// Send JSON object
res.json({
users: [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
]
});
// Send JSON array
res.json(["apple", "banana", "cherry"]);
// Send primitive values as JSON
res.json("hello"); // "hello"
res.json(123); // 123
}Sets HTTP status code. Can be chained with other methods.
status(statusCode: number): NowResponse;export default function handler(req: NowRequest, res: NowResponse) {
// Set status and send JSON
res.status(201).json({ message: "Created successfully" });
// Set status and send text
res.status(404).send("Not Found");
// Just set status (must call end() manually)
res.status(204);
res.end();
}Performs HTTP redirect with optional status code.
redirect(statusOrUrl: string | number, url?: string): NowResponse;export default function handler(req: NowRequest, res: NowResponse) {
// Simple redirect (uses 307 status)
res.redirect("/login");
// Redirect with custom status
res.redirect(301, "/new-location");
// Permanent redirect
res.redirect(301, "https://example.com/moved");
// Temporary redirect
res.redirect(302, "/temporary-page");
}Standard function signature for Vercel API route handlers.
type NowApiHandler = (req: NowRequest, res: NowResponse) => void;import { NowRequest, NowResponse } from "@vercel/node";
const handler: NowApiHandler = (req, res) => {
if (req.method === "GET") {
res.json({ message: "Hello GET" });
} else if (req.method === "POST") {
const data = req.body;
res.status(201).json({ received: data });
} else {
res.status(405).json({ error: "Method not allowed" });
}
};
export default handler;Handlers can also be async functions:
import { NowRequest, NowResponse } from "@vercel/node";
export default async function handler(req: NowRequest, res: NowResponse) {
try {
const data = await fetchDataFromDatabase();
res.json(data);
} catch (error) {
res.status(500).json({ error: "Internal server error" });
}
}Response methods can be chained for concise code:
export default function handler(req: NowRequest, res: NowResponse) {
const { id } = req.query;
if (!id) {
return res
.status(400)
.json({ error: "ID parameter is required" });
}
// Process the request...
res
.status(200)
.json({ id, message: "Success" });
}The response methods automatically set appropriate Content-Type headers:
res.json(): application/json; charset=utf-8res.send(string): text/html; charset=utf-8res.send(Buffer): application/octet-streamres.send(object): Calls res.json() internallyFor proper error responses, use status codes with descriptive messages:
export default function handler(req: NowRequest, res: NowResponse) {
try {
// Your handler logic
} catch (error) {
console.error("Handler error:", error);
res
.status(500)
.json({
error: "Internal server error",
message: process.env.NODE_ENV === "development" ? error.message : undefined
});
}
}Install with Tessl CLI
npx tessl i tessl/npm-vercel--node