@rescale/nemo
Version:
A middleware composition library for Next.js applications that allows you to organize and chain middleware functions based on URL patterns.
226 lines (222 loc) • 8.15 kB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
import { WaitUntil } from 'next/dist/server/after/builtin-request-context';
import { StorageAdapter } from './storage/adapter.js';
declare const responseSymbol: unique symbol;
declare const passThroughSymbol: unique symbol;
declare const waitUntilSymbol: unique symbol;
declare class FetchEvent implements Omit<Event, 'composedPath'> {
readonly [waitUntilSymbol]: {
kind: "internal";
promises: Promise<any>[];
} | {
kind: "external";
function: WaitUntil;
};
private [responseSymbol];
private [passThroughSymbol];
private hasResponded;
bubbles: boolean;
cancelBubble: boolean;
cancelable: boolean;
composed: boolean;
currentTarget: null;
defaultPrevented: boolean;
eventPhase: number;
isTrusted: boolean;
returnValue: boolean;
srcElement: null;
target: null;
timeStamp: number;
type: string;
readonly NONE: 0;
readonly CAPTURING_PHASE: 1;
readonly AT_TARGET: 2;
readonly BUBBLING_PHASE: 3;
constructor(_request: Request, waitUntil?: WaitUntil);
composedPath(): EventTarget[];
initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void;
preventDefault(): void;
stopImmediatePropagation(): void;
stopPropagation(): void;
respondWith(response: Response | Promise<Response>): void;
passThroughOnException(): void;
waitUntil(promise: Promise<any>): void;
}
declare function getWaitUntilPromiseFromEvent(event: FetchEvent): Promise<void> | undefined;
declare class NextFetchEvent extends FetchEvent {
sourcePage: string;
constructor(params: {
request: NextRequest;
page: string;
context: {
waitUntil: WaitUntil;
} | undefined;
});
}
/**
* A wrapper around NextFetchEvent that allows for additional context to be passed
* through the middleware chain.
*/
declare class NemoEvent extends NextFetchEvent {
storage: StorageAdapter;
private currentMetadata?;
private readonly logger;
private shouldSkipRemaining;
private shouldSkipAfter;
constructor(params: {
request: NextRequest;
sourcePage: string;
context?: {
waitUntil: WaitUntil;
};
nemo?: Record<string, unknown>;
storage?: StorageAdapter;
debug?: boolean;
});
/**
* Log a debug message (only displayed when debug is enabled)
* @param args - Arguments to log
*/
log(...args: any[]): void;
/**
* Log an error message (always displayed)
* @param args - Arguments to log
*/
error(...args: any[]): void;
/**
* Log a warning message (always displayed)
* @param args - Arguments to log
*/
warn(...args: any[]): void;
/**
* Updates the current middleware metadata
* @param metadata - The metadata from the middleware that's currently being processed
*/
setCurrentMetadata(metadata: MiddlewareMetadata): void;
/**
* Skip the remaining middlewares in the current chain (before/main/after)
* This allows a middleware to stop the execution of subsequent middlewares
* without returning a terminating response (like redirect/rewrite).
*
* @param options - Optional configuration for skip behavior
* @param options.skipAfter - If true, also skip all after chain middlewares
*
* @example
* ```ts
* // Skip remaining middlewares in current chain only
* async (request, event) => {
* if (someCondition) {
* event.skip();
* // Remaining middlewares in this chain will not execute
* }
* }
* ```
*
* @example
* ```ts
* // Skip remaining middlewares and after chain
* async (request, event) => {
* if (someCondition) {
* event.skip({ skipAfter: true });
* // Remaining middlewares in this chain AND after chain will not execute
* }
* }
* ```
*/
skip(options?: {
skipAfter?: boolean;
}): void;
/**
* Check if skip was called
* @internal
*/
shouldSkip(): boolean;
/**
* Check if skipAfter was called
* @internal
*/
shouldSkipAfterChain(): boolean;
/**
* Reset skip flag (used internally when transitioning between chain sections)
* @internal
*/
/**
* Reset skip flag (used internally when transitioning between chain sections)
* Note: Only resets shouldSkipRemaining; shouldSkipAfter persists to honor
* the request to skip after-chain middlewares across all chain transitions.
* @internal
*/
resetSkip(): void;
/**
* Getter for route parameters from the current request path
* @returns An object containing the extracted parameters from the current route
*
* @example
* ```ts
* // For route defined as "/users/:userId"
* // When accessing "/users/123"
* const { userId } = event.params; // "123"
* ```
*/
get params(): Record<string, string | string[]>;
/**
* Extract URL parameters from a path using a route pattern
* @private
* @param routePattern - The route pattern with parameter placeholders
* @param pathname - The actual pathname to extract parameters from
* @returns An object containing the extracted parameters
*/
private extractParamsFromPath;
/**
* Extract URL parameters from a path using a route pattern
* @param options - Options for parameter extraction
* @param options.metadata - The metadata from the middleware (optional if currentMetadata is set)
* @param options.routePattern - The route pattern with parameter placeholders (optional)
* @param options.pathname - The actual pathname to extract parameters from (optional)
* @returns An object containing the extracted parameters
*/
getParams(options?: MiddlewareMetadata | {
metadata?: MiddlewareMetadata;
routePattern?: string;
pathname?: string;
}): Record<string, string | string[]>;
static from(event: NextFetchEvent, nemoContext?: Record<string, unknown>, storage?: StorageAdapter, debug?: boolean): NemoEvent;
}
type NextMiddlewareResult = NextResponse | Response | null | undefined | void;
type NextMiddleware = (request: NextRequest, event: NemoEvent) => NextMiddlewareResult | Promise<NextMiddlewareResult>;
type MiddlewareContext = Map<string, unknown>;
type ErrorHandler = (error: Error, metadata: MiddlewareMetadata) => NextMiddlewareResult | Promise<NextMiddlewareResult>;
type MiddlewareChain = NextMiddleware | NextMiddleware[];
type MiddlewareConfigValue = NextMiddleware | NextMiddleware[] | {
[key: `/${string}`]: MiddlewareConfigValue;
} | {
middleware: NextMiddleware | NextMiddleware[];
[key: `/${string}`]: MiddlewareConfigValue;
};
type MiddlewareConfig = Record<string, MiddlewareConfigValue>;
type GlobalMiddlewareConfig = Partial<Record<"before" | "after", MiddlewareChain>>;
interface Storage {
get(key: string): Promise<unknown>;
set(key: string, value: unknown): Promise<void>;
delete(key: string): Promise<void>;
clear(): Promise<void>;
}
interface NemoConfig {
debug?: boolean;
silent?: boolean;
errorHandler?: ErrorHandler;
enableTiming?: boolean;
storage?: StorageAdapter | (() => StorageAdapter);
}
type ChainType = "before" | "main" | "after";
interface MiddlewareMetadata {
chain: ChainType;
index: number;
pathname: string;
routeKey: string;
nestLevel?: number;
}
type NextMiddlewareWithMeta = NextMiddleware & {
__nemo?: MiddlewareMetadata;
};
export { type ChainType as C, type ErrorHandler as E, FetchEvent as F, type GlobalMiddlewareConfig as G, type MiddlewareConfig as M, type NemoConfig as N, type Storage as S, type NextMiddlewareResult as a, NemoEvent as b, type NextMiddleware as c, type MiddlewareContext as d, type MiddlewareChain as e, type MiddlewareConfigValue as f, type MiddlewareMetadata as g, type NextMiddlewareWithMeta as h, getWaitUntilPromiseFromEvent as i, NextFetchEvent as j };