import type { Condition, MatchableValueObject, Redirect, Rewrite } from './types'; /** * Type utility to extract path parameter names from a route pattern string. * Supports :paramName syntax used in path-to-regexp patterns. * * @example * ExtractPathParams<'/users/:userId/posts/:postId'> // 'userId' | 'postId' * ExtractPathParams<'/api/(.*)'> // never */ type ExtractPathParams = T extends `${string}:${infer Param}/${infer Rest}` ? (Param extends `${infer P}(${string}` ? P : Param) | ExtractPathParams<`/${Rest}`> : T extends `${string}:${infer Param}` ? Param extends `${infer P}(${string}` ? P : Param : never; /** * Creates an object type where keys are the extracted path parameter names * and values are strings (the resolved $paramName values). */ type PathParams = { [K in ExtractPathParams]: string; }; /** * Helper function to reference a Vercel project environment variable. * These are placeholders that get resolved at request time by Vercel's routing layer. * They are set per-deployment and don't change until you redeploy. * * @example * // Usage in rewrites with type-safe path params: * routes.rewrite('/users/:userId', 'https://api.example.com/$1', ({ userId }) => ({ * requestHeaders: { * 'x-user-id': userId, * 'authorization': `Bearer ${deploymentEnv('API_KEY')}` * } * })) */ export declare function deploymentEnv(name: string): string; /** * Template literal type for durations recognized by pretty-cache-header. * * Usage examples: '10s', '1week', '2months', '12hrs' */ export type TimeUnit = 'ms' | 'milli' | 'millisecond' | 'milliseconds' | 's' | 'sec' | 'secs' | 'second' | 'seconds' | 'm' | 'min' | 'mins' | 'minute' | 'minutes' | 'h' | 'hr' | 'hrs' | 'hour' | 'hours' | 'd' | 'day' | 'days' | 'w' | 'week' | 'weeks' | 'mon' | 'mth' | 'mths' | 'month' | 'months' | 'y' | 'yr' | 'yrs' | 'year' | 'years'; export type TimeString = `${number}${TimeUnit}`; /** * Options for constructing the Cache-Control header. * All fields are optional; set only what you need. */ export interface CacheOptions { /** * Indicates that the response can be cached by any cache. * Equivalent to "public" in Cache-Control. */ public?: true; /** * Indicates that the response is intended for a single user * and must not be stored by a shared cache. */ private?: true; /** * Indicates that the resource will not be updated and, * therefore, does not need revalidation. */ immutable?: true; /** * Indicates that a response must not be stored in any cache. */ noStore?: true; /** * Indicates that the response cannot be used to satisfy a subsequent request * without validation on the origin server. */ noCache?: true; /** * Indicates that the client must revalidate the response with the origin server * before using it again. */ mustRevalidate?: true; /** * Same as must-revalidate, but specifically for shared caches. */ proxyRevalidate?: true; /** * The maximum amount of time a resource is considered fresh. * e.g. '1week', '30s', '3days'. */ maxAge?: TimeString; /** * If s-maxage is present in a response, it takes priority over max-age * when a shared cache (e.g., CDN) is satisfied. */ sMaxAge?: TimeString; /** * How long (in seconds) a resource remains fresh (beyond its max-age) * while a background revalidation is attempted. */ staleWhileRevalidate?: TimeString; /** * Allows clients to use stale data when an error is encountered * while attempting to revalidate. */ staleIfError?: TimeString; } export declare const matchers: { header: (key: string, value?: string | MatchableValueObject) => Condition; cookie: (key: string, value?: string | MatchableValueObject) => Condition; query: (key: string, value?: string | MatchableValueObject) => Condition; host: (value: string | MatchableValueObject) => Condition; }; /** * Transform type specifies the scope of what the transform will apply to. * - 'request.query': Transform query parameters in the request * - 'request.headers': Transform headers in the request * - 'response.headers': Transform headers in the response */ export type TransformType = 'request.query' | 'request.headers' | 'response.headers'; /** * Transform operation type. * - 'set': Sets the key and value if missing * - 'append': Appends args to the value of the key, and will set if missing * - 'delete': Deletes the key entirely if args is not provided; otherwise, it will delete the value of args from the matching key */ export type TransformOp = 'set' | 'append' | 'delete'; /** * Conditional matching properties for transform keys. * When the key property is an object, it can contain one or more of these properties. */ export interface TransformKeyConditions { /** Check equality on a value */ eq?: string | number; /** Check inequality on a value */ neq?: string; /** Check inclusion in an array of values */ inc?: string[]; /** Check non-inclusion in an array of values */ ninc?: string[]; /** Check if value starts with a prefix */ pre?: string; /** Check if value ends with a suffix */ suf?: string; /** Check if value is greater than */ gt?: number; /** Check if value is greater than or equal to */ gte?: number; /** Check if value is less than */ lt?: number; /** Check if value is less than or equal to */ lte?: number; } /** * Transform target specifies what key to target for the transform. * The key can be a string (exact match) or an object with conditional matching. */ export interface TransformTarget { key: string | TransformKeyConditions; } /** * A transform that targets a specific request/response header or query key. * Supports environment variables (e.g., $BEARER_TOKEN) and path parameters (e.g., $userId). */ export interface TargetTransform { /** The scope of what the transform will apply to */ type: TransformType; /** The operation to perform */ op: TransformOp; /** The target key to transform */ target: TransformTarget; /** The value(s) to use for the operation. Can include environment variables ($VAR) and path parameters ($param) */ args?: string | string[]; /** List of environment variable names that are used in args (without the $ prefix) */ env?: string[]; } /** * A transform that overrides the request path observed by the target runtime * (its `req.url`), independent of how the route was selected. * * Unlike header/query transforms there is no `target`/key: the path is a single * scalar value and only the `set` operation is supported. On a low-level * `Route`, capture groups use `$1` or `$name`. High-level rewrites instead use * path-to-regexp parameters such as `/:path*`, which are compiled before the * route is emitted. Environment variables use `$VAR` with an `env` allowlist. * * @example * { * type: 'request.path', * op: 'set', * args: '/$1' * } */ export interface RequestPathTransform { /** Discriminator. Always `request.path`. */ type: 'request.path'; /** Only `set` is supported for request path transforms. */ op: 'set'; /** The runtime-visible request path. Must be an origin-form path (leading `/`, no query or fragment). */ args: string; /** List of environment variable names that are used in args (without the $ prefix) */ env?: string[]; } /** * Transform defines a single transformation operation on request or response data. * It is either a header/query {@link TargetTransform} or a path-rewriting * {@link RequestPathTransform}. */ export type Transform = TargetTransform | RequestPathTransform; /** * Route defines a routing rule with transforms. * This is the newer, more powerful route format that supports transforms. * * @example * { * src: "^/users/([^/]+)/posts/([^/]+)$", * transforms: [ * { * type: "request.headers", * op: "set", * target: { key: "x-user-id" }, * args: "$1" * }, * { * type: "request.headers", * op: "set", * target: { key: "authorization" }, * args: "Bearer $BEARER_TOKEN" * } * ] * } */ export interface Route { /** Regular expression used by the low-level routes format */ src?: string; /** Alias for `src`. A pattern that matches each incoming pathname (excluding querystring). */ source?: string; /** Optional destination for rewrite/redirect */ dest?: string; /** Alias for `dest`. An absolute pathname to an existing resource or an external URL. */ destination?: string; /** Array of HTTP methods to match. If not provided, matches all methods */ methods?: string[]; /** Array of transforms to apply */ transforms?: Transform[]; /** Optional conditions that must be present */ has?: Condition[]; /** Optional conditions that must be absent */ missing?: Condition[]; /** Status code for the response */ status?: number; /** Alias for `status`. An optional integer to override the status code of the response. */ statusCode?: number; /** Headers to set (alternative to using transforms) */ headers?: Record; /** Environment variables referenced in dest or transforms */ env?: string[]; /** * When true (default), external rewrites will respect the Cache-Control header from the origin. * When false, caching is disabled for this rewrite. */ respectOriginCacheControl?: boolean; } /** * Represents a single HTTP header key/value pair. */ export interface Header { key: string; value: string; } /** * Options for transform operations on headers and query parameters. * These are converted internally to Vercel's transforms format. */ export interface TransformOptions { /** * Headers to set/modify on the incoming request. * Sets the key and value if missing. * * @example * requestHeaders: { * 'x-user-id': userId, * 'authorization': `Bearer ${env.API_TOKEN}` * } */ requestHeaders?: Record; /** * Headers to set/modify on the outgoing response. * Sets the key and value if missing. * * @example * responseHeaders: { * 'x-post-id': postId * } */ responseHeaders?: Record; /** * Query parameters to set/modify on the request. * Sets the key and value if missing. * * @example * requestQuery: { * 'theme': 'dark' * } */ requestQuery?: Record; /** * Headers to append to the incoming request. * Appends args to the value of the key, and will set if missing. * * @example * appendRequestHeaders: { * 'x-custom': 'value' * } */ appendRequestHeaders?: Record; /** * Headers to append to the outgoing response. * Appends args to the value of the key, and will set if missing. * * @example * appendResponseHeaders: { * 'x-custom': 'value' * } */ appendResponseHeaders?: Record; /** * Query parameters to append to the request. * Appends args to the value of the key, and will set if missing. * * @example * appendRequestQuery: { * 'tag': 'value' * } */ appendRequestQuery?: Record; /** * Headers to delete from the incoming request. * Deletes the key entirely if args is not provided; otherwise, it will delete the value of args from the matching key. * * @example * deleteRequestHeaders: ['x-remove-this', 'x-remove-that'] */ deleteRequestHeaders?: string[]; /** * Headers to delete from the outgoing response. * Deletes the key entirely if args is not provided; otherwise, it will delete the value of args from the matching key. * * @example * deleteResponseHeaders: ['x-powered-by'] */ deleteResponseHeaders?: string[]; /** * Query parameters to delete from the request. * Deletes the key entirely if args is not provided; otherwise, it will delete the value of args from the matching key. * * @example * deleteRequestQuery: ['debug', 'trace'] */ deleteRequestQuery?: string[]; } /** * HeaderRule defines one or more headers to set for requests * matching a given source pattern, plus optional "has" / "missing" conditions. */ export interface HeaderRule { /** * Pattern to match request paths using path-to-regexp syntax. * @example * "/api/(.*)" // Basic capture group * "/blog/:slug" // Named parameter * "/feedback/((?!general).*)" // Negative lookahead in a group */ source: string; /** An array of key/value pairs to set as headers. */ headers: Header[]; /** Optional conditions that must be present. */ has?: Condition[]; /** Optional conditions that must be absent. */ missing?: Condition[]; } /** * RedirectRule defines a URL rewrite in which the user is redirected * (3xx response) to a destination, with optional conditions. */ export interface RedirectRule { /** * Pattern to match request paths using path-to-regexp syntax. * @example * "/api/(.*)" // Basic capture group * "/blog/:slug" // Named parameter * "/feedback/((?!general).*)" // Negative lookahead in a group */ source: string; destination: string; /** * If true, default status code is 308; if false, 307. * Can be overridden by `statusCode`. */ permanent?: boolean; /** * Allows specifying a custom HTTP status code instead of 307 or 308. */ statusCode?: number; has?: Condition[]; missing?: Condition[]; } /** * RewriteRule defines an internal rewrite from the source pattern * to the specified destination, without exposing a redirect to the user. */ export interface RewriteRule { /** * Pattern to match request paths using path-to-regexp syntax. * @example * "/api/(.*)" // Basic capture group * "/blog/:slug" // Named parameter * "/feedback/((?!general).*)" // Negative lookahead in a group */ source: string; destination: string; /** Array of HTTP methods to match. If not provided, matches all methods */ methods?: string[]; /** Status code for the response */ status?: number; has?: Condition[]; missing?: Condition[]; /** Internal field: transforms generated from requestHeaders/responseHeaders/requestQuery */ transforms?: Transform[]; /** * When true (default), external rewrites will respect the Cache-Control header from the origin. * When false, caching is disabled for this rewrite. */ respectOriginCacheControl?: boolean; } /** * CronRule defines a scheduled function invocation on Vercel. */ export interface CronRule { /** * The URL path to invoke, must start with '/'. */ path: string; /** * Cron expression string (e.g., '0 0 * * *' for daily midnight). */ schedule: string; } /** * Providers can be used to asynchronously load sets of rules. */ export type RedirectProvider = () => Promise; export type HeaderProvider = () => Promise; export type RewriteProvider = () => Promise; export type CronProvider = () => Promise; /** * The aggregated router configuration, suitable for exporting as * a JSON or TypeScript object that can be consumed by Vercel. */ export interface RouterConfig { redirects?: RedirectRule[]; headers?: HeaderRule[]; rewrites?: RewriteRule[]; /** * Array of routes with transforms support. * This is the newer, more powerful routing format. * When routes is present, other fields (redirects, headers, rewrites, crons) are excluded. */ routes?: Route[]; /** * Array of cron definitions for scheduled invocations. */ crons?: CronRule[]; } /** * The main Router class for building a Vercel configuration object in code. * Supports synchronous or asynchronous addition of rewrites, redirects, headers, * plus convenience methods for crons, caching, and more. */ export declare class Router { private redirectRules; private headerRules; private rewriteRules; private routeRules; private cronRules; /** * Helper to extract path parameter names from a source pattern. * Path parameters are identified by :paramName syntax. * @example * extractPathParams('/users/:userId/posts/:postId') // Returns ['userId', 'postId'] */ private extractPathParams; /** * Creates a rewrite rule. Returns either a Rewrite object (simple case) or Route with transforms. * * @example * // Simple rewrite * router.rewrite('/api/(.*)', 'https://old-on-prem.com/$1') * * // With transforms but no path params * router.rewrite('/(.*)', 'https://api.example.com/$1', { * requestHeaders: { * 'authorization': `Bearer ${deploymentEnv('API_KEY')}` * } * }) * * // With type-safe path params * router.rewrite('/users/:userId', 'https://api.example.com/users/$1', ({ userId }) => ({ * requestHeaders: { * 'x-user-id': userId, * 'authorization': `Bearer ${deploymentEnv('API_KEY')}` * } * })) * * // With conditions only * router.rewrite('/admin/(.*)', 'https://admin.example.com/$1', { * has: [{ type: 'header', key: 'x-admin-token' }] * }) * * // Override the path observed by the target runtime * router.rewrite('/api/:path*', '/internal/:path*', { * requestPath: '/:path*' * }) * @internal Can return Route with transforms internally */ rewrite(source: T, destination: string): Rewrite; /** * The callback form exposes `$param` references for header and query * transforms. Use the object options form for `requestPath`, whose source * parameters use `:param` syntax. */ rewrite(source: T, destination: string, callback: (params: PathParams) => { has?: Condition[]; missing?: Condition[]; requestHeaders?: Record; responseHeaders?: Record; requestQuery?: Record; respectOriginCacheControl?: boolean; }): Rewrite | Route; rewrite(source: T, destination: string, options: { has?: Condition[]; missing?: Condition[]; requestHeaders?: Record; responseHeaders?: Record; requestQuery?: Record; requestPath?: string; respectOriginCacheControl?: boolean; } & Record): Rewrite | Route; /** * Creates a redirect rule. Returns either a Redirect object (simple case) or Route with transforms. * * @example * // Simple redirect * router.redirect('/old-path', '/new-path', { permanent: true }) * * // With transforms but no path params * router.redirect('/old', '/new', { * permanent: true, * requestHeaders: { * 'x-api-key': deploymentEnv('API_KEY') * } * }) * * // With type-safe path params * router.redirect('/users/:userId', '/new-users/$1', ({ userId }) => ({ * permanent: true, * requestHeaders: { * 'x-user-id': userId, * 'x-api-key': deploymentEnv('API_KEY') * } * })) * * // With conditions only * router.redirect('/dashboard/(.*)', '/login', { * missing: [{ type: 'cookie', key: 'auth-token' }] * }) * @internal Can return Route with transforms internally */ redirect(source: T, destination: string): Redirect; redirect(source: T, destination: string, callback: (params: PathParams) => { permanent?: boolean; statusCode?: number; has?: Condition[]; missing?: Condition[]; requestHeaders?: Record; }): Redirect | Route; redirect(source: T, destination: string, options: { permanent?: boolean; statusCode?: number; has?: Condition[]; missing?: Condition[]; requestHeaders?: Record; }): Redirect | Route; /** * Creates a header rule matching the vercel.json schema. * @example * router.header('/api/(.*)', [{ key: 'X-Custom', value: 'HelloWorld' }]) */ header(source: string, headers: Header[], options?: { has?: Condition[]; missing?: Condition[]; }): { source: string; headers: Header[]; has?: Condition[]; missing?: Condition[]; }; /** * Creates a Cache-Control header rule, leveraging `pretty-cache-header`. * Returns a HeaderRule matching the vercel.json schema. * * @example * router.cacheControl('/my-page', { * public: true, * maxAge: '1week', * staleWhileRevalidate: '1year' * }) */ cacheControl(source: string, cacheOptions: CacheOptions, options?: { has?: Condition[]; missing?: Condition[]; }): { source: string; headers: Header[]; has?: Condition[]; missing?: Condition[]; }; /** * Adds a route with transforms support. * This is the lower-level routes format. Use a regular-expression `src` and * `$1`/`$name` capture references in destinations and transform arguments. * * @example * // Add a route with transforms for path parameters and environment variables * router.route({ * src: '^/users/([^/]+)/posts/([^/]+)$', * dest: 'https://api.example.com/users/$1/posts/$2', * transforms: [ * { * type: 'request.headers', * op: 'set', * target: { key: 'x-user-id' }, * args: '$1' * }, * { * type: 'request.headers', * op: 'set', * target: { key: 'authorization' }, * args: 'Bearer $BEARER_TOKEN' * } * ] * }); * * @example * // Override the request path the target runtime observes * router.route({ * src: '^/api/(.*)$', * dest: '/internal/$1', * transforms: [{ type: 'request.path', op: 'set', args: '/$1' }], * }); */ route(config: Route): this; /** * Adds a single cron rule (synchronous). */ cron(path: string, schedule: string): this; /** * Loads cron rules asynchronously and appends them. */ crons(provider: CronProvider): Promise; /** * Returns the complete router configuration. * Typically, you'll export or return this in your build scripts, * so that Vercel can pick it up. */ getConfig(): RouterConfig; /** * Visualizes the routing tree in the order that Vercel applies routes. * Returns a formatted string showing the routing hierarchy. */ visualize(): string; private validateSourcePattern; private validateCronExpression; } /** * A simple factory function for creating a new Router instance. * @example * import { createRoutes } from '@vercel/router-sdk'; * const routes = createRoutes(); */ export declare function createRoutes(): Router; /** * Default singleton router instance for convenience. * @example * import { routes } from '@vercel/router-sdk'; * routes.redirect('/old', '/new'); */ export declare const routes: Router; export {};