API Reference
Types API Reference
Complete TypeScript type definitions for MoroJS. Build type-safe applications with full IntelliSense support and compile-time validation.
Core Types
Essential TypeScript interfaces and types for building MoroJS applications.
Application Typestypescript
1import type {
2 Moro,
3 MoroConfig,
4 MoroOptions,
5 RuntimeAdapter
6} from '@morojs/moro';
7
8// Main application interface
9interface Moro {
10 // HTTP methods. Called with a path only, they return a chainable route
11 // builder; called with a handler, they register the route directly.
12 // The handler may be a function, the response body itself
13 // (StaticBody: a string or Buffer), or param(name) (ParamEcho) - see
14 // Literal Handlers.
15 get(path: string): UnifiedRouteBuilder;
16 get(path: string, handler: RouteHandler | StaticBody | ParamEcho, options?: RouteOptions): this;
17 post(path: string): UnifiedRouteBuilder;
18 post(path: string, handler: RouteHandler | StaticBody | ParamEcho, options?: RouteOptions): this;
19 put(path: string): UnifiedRouteBuilder;
20 put(path: string, handler: RouteHandler | StaticBody | ParamEcho, options?: RouteOptions): this;
21 delete(path: string): UnifiedRouteBuilder;
22 delete(path: string, handler: RouteHandler | StaticBody | ParamEcho, options?: RouteOptions): this;
23 patch(path: string): UnifiedRouteBuilder;
24 patch(path: string, handler: RouteHandler | StaticBody | ParamEcho, options?: RouteOptions): this;
25
26 // Schema-first registration
27 route(schema: RouteSchema): void;
28
29 // Application methods
30 use(...middleware: MiddlewareFunction[]): void;
31 group(prefix: string, callback: (group: Moro) => void): void;
32 listen(port: number, host?: string, callback?: () => void): void;
33 close(): Promise<void>;
34
35 // Configuration
36 configure(config: Partial<MoroConfig>): void;
37 getConfig(): MoroConfig;
38 getConfig<K extends keyof MoroConfig>(key: K): MoroConfig[K];
39
40 // Environment
41 env(): Record<string, string>;
42 env<T = Record<string, string>>(): T;
43 env(key: string): string | undefined;
44 env(schema: EnvSchema): void;
45}
46
47// Configuration interface
48interface MoroConfig {
49 server?: ServerConfig;
50 security?: SecurityConfig;
51 database?: DatabaseConfig;
52 logging?: LoggingConfig;
53 features?: FeaturesConfig;
54}
55
56// Runtime adapter interface
57interface RuntimeAdapter {
58 name: 'node' | 'edge' | 'lambda' | 'worker';
59 createHandler(app: Moro): any;
60 transformRequest(request: any): Request;
61 transformResponse(response: Response): any;
62}Request/Response Types
Handler and Context Typestypescript
1// Route handler: the request and the response, the same on every
2// server MoroJS runs on. A returned value other than undefined is sent
3// as JSON; use res directly for anything else.
4type RouteHandler<T = any> = (req: HttpRequest, res: HttpResponse) => T | Promise<T>;
5
6// What .handler() accepts in place of a function: the response body itself
7type StaticBody = string | Buffer;
8
9// The reply a literal handler sends, in the engine's shape. Set on the
10// RouteSchema by the framework when a literal handler has nothing else
11// configured, so a server that can answer it natively (@morojs/engine
12// >= 1.1.6) does so without calling into JS.
13interface StaticResponse {
14 status: number;
15 headers: string[] | null; // [name, value, name, value, ...]
16 body: string | Buffer | null;
17}
18
19// The marker param(name) produces: "answer with this path parameter as
20// the body", as res.end(req.params[name]) would
21interface ParamEcho {
22 readonly [PARAM_ECHO]: true; // brand, set by param()
23 readonly name: string;
24}
25
26// The engine shape of a param(name) handler on a bare route with exactly
27// that one parameter: the path segment between prefix and suffix is the
28// body. Framework-set; @morojs/engine >= 1.1.9 (paramRoutes) answers it
29// without calling into JS, every other server runs the equivalent handler.
30interface ParamRouteReply {
31 name: string;
32 prefix: string;
33 suffix: string;
34 status: number;
35 headers: string[] | null; // [name, value, name, value, ...]
36}
37
38// The request: Node's IncomingMessage plus what MoroJS parses and attaches
39interface HttpRequest extends IncomingMessage {
40 params: Record<string, string>;
41 query: Record<string, string>;
42 body: any;
43 rawBody: Buffer | null; // the undecoded body bytes (JSON included), null when none
44 path: string;
45 headers: Record<string, string>;
46 ip: string;
47 requestId: string;
48 cookies?: Record<string, string>;
49 signedCookies?: Record<string, string>; // verified signatures only; needs a cookie secret
50 files?: Record<string, any>;
51
52 // Per-request typed context: pass data between middlewares without patching req
53 context: Record<string, any>;
54
55 // Express-compatible helpers
56 get(name: string): string | undefined;
57 header(name: string): string | undefined;
58 is(type: string): boolean;
59 accepts(types?: string | string[]): string | false;
60 acceptsLanguages(langs?: string | string[]): string | false;
61 hostname: string;
62 protocol: string;
63 secure: boolean;
64 xhr: boolean;
65 originalUrl: string;
66 ips: string[];
67 subdomains: string[];
68}
69
70// The response: Node's ServerResponse plus MoroJS's helpers
71type HttpResponse = ServerResponse & MoroResponseMethods;
72
73interface MoroResponseMethods {
74 json(data: any): void;
75 status(code: number): HttpResponse;
76 send(data: string | Buffer): void;
77 cookie(name: string, value: string, options?: CookieOptions): HttpResponse;
78 clearCookie(name: string, options?: CookieOptions): HttpResponse;
79 redirect(url: string, status?: number): void;
80 sendFile(filePath: string): Promise<void>;
81 render?(template: string, data?: any): Promise<void>;
82 locals: Record<string, any>; // per-response state bag (Express-compatible)
83
84 // Express-compatible helpers
85 set(field: string | Record<string, string | string[] | number>, value?: string | string[] | number): HttpResponse;
86 get(field: string): string | number | string[] | undefined;
87 append(field: string, value: string | string[]): HttpResponse;
88 type(contentType: string): HttpResponse;
89 sendStatus(code: number): void;
90 location(url: string): HttpResponse;
91 vary(field: string | string[]): HttpResponse;
92 links(links: Record<string, string>): HttpResponse;
93 attachment(filename?: string): HttpResponse;
94 download(filePath: string, filename?: string): Promise<void>;
95 format(handlers: Record<string, () => any | Promise<any>>): void;
96
97 // Header and state utilities
98 hasHeader(name: string): boolean;
99 setBulkHeaders(headers: Record<string, string | number>): HttpResponse;
100 appendHeader(name: string, value: string | string[]): HttpResponse;
101 canSetHeaders(): boolean;
102 getResponseState(): ResponseState;
103
104 // Standardized helpers (see Response Helpers)
105 success<T = any>(data: T, message?: string): void;
106 error(error: string, code?: string, message?: string): void;
107 unauthorized(message?: string): void;
108 forbidden(message?: string): void;
109 notFound(resource?: string): void;
110 badRequest(message?: string): void;
111 conflict(message: string): void;
112 internalError(message?: string): void;
113 validationError(errors: Array<{ field: string; message: string; code?: string }>): void;
114 rateLimited(retryAfter?: number): void;
115 created<T = any>(data: T, location?: string): void;
116 noContent(): void;
117 paginated<T = any>(data: T[], pagination: { page: number; limit: number; total: number }): void;
118}
119
120// HTTP method type
121type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
122
123// Cookie options
124interface CookieOptions {
125 maxAge?: number;
126 expires?: Date;
127 httpOnly?: boolean;
128 secure?: boolean;
129 sameSite?: 'strict' | 'lax' | 'none';
130 domain?: string;
131 path?: string;
132 signed?: boolean; // sign the value; needs a cookie middleware secret
133 critical?: boolean; // mark as critical: throws if set after headers were sent
134 throwOnLateSet?: boolean; // force a throw if headers were already sent
135}Route Configuration Types
Route Configuration Interfacetypescript
1// The chainable route builder returned by app.get('/path') etc.
2// Every method returns the builder, so calls chain in any order -
3// execution order is fixed by the pipeline, not by chain order.
4interface UnifiedRouteBuilder {
5 // Validation
6 body(schema: ValidationSchema): this;
7 query(schema: ValidationSchema): this;
8 params(schema: ValidationSchema): this;
9 headers(schema: ValidationSchema): this;
10 validate(config: ValidationConfig): this;
11
12 // Route features
13 auth(config: AuthConfig): this;
14 rateLimit(config: RateLimitConfig): this;
15 cache(config: CacheConfig): this;
16
17 // Custom middleware, by phase
18 before(...middleware: Middleware[]): this;
19 transform(...middleware: Middleware[]): this;
20 after(...middleware: Middleware[]): this;
21 use(...middleware: Middleware[]): this; // alias for after()
22
23 // Metadata
24 describe(description: string): this;
25 tag(...tags: string[]): this;
26
27 // Terminal - registers the route. A function handles the request;
28 // a string or Buffer IS the response body (as res.send would send it);
29 // param(name) echoes that path parameter (as res.end would send it)
30 handler(fn: RouteHandler | StaticBody | ParamEcho): void;
31}
32
33// Options accepted by the direct form: app.get(path, handler, options)
34interface RouteOptions {
35 middleware?: Middleware[];
36 validation?: ValidationConfig;
37 rateLimit?: RateLimitConfig;
38 cache?: CacheConfig;
39}
40
41// The schema behind app.route({ ... }) and the chainable builder.
42// Chainable calls populate exactly these fields.
43interface RouteSchema {
44 method: HttpMethod;
45 path: string;
46 handler: RouteHandler | StaticBody | ParamEcho; // a function, the body itself, or param(name)
47 static?: StaticResponse; // fixed reply of a literal handler (framework-set)
48 paramEcho?: ParamRouteReply; // engine shape of a param(name) handler (framework-set)
49
50 validation?: ValidationConfig; // .body() / .query() / .params() / .headers() / .validate()
51 auth?: AuthConfig; // .auth()
52 rateLimit?: RateLimitConfig; // .rateLimit()
53 cache?: CacheConfig; // .cache()
54 middleware?: MiddlewarePhases; // .before() / .transform() / .after() / .use()
55 description?: string; // .describe()
56 tags?: string[]; // .tag()
57}
58
59interface ValidationConfig {
60 body?: ValidationSchema;
61 query?: ValidationSchema;
62 params?: ValidationSchema;
63 headers?: ValidationSchema;
64 // Shapes the 4xx when a schema rejects the request. Route-level handler
65 // wins over the global one passed to createApp().
66 onValidationError?: (
67 errors: ValidationErrorDetail[],
68 context: ValidationErrorContext
69 ) => ValidationErrorResponse;
70}
71
72interface AuthConfig {
73 roles?: string[];
74 permissions?: string[];
75 optional?: boolean;
76}
77
78interface RateLimitConfig {
79 requests: number; // allowed requests per window
80 window: number; // window length in milliseconds
81 skipSuccessfulRequests?: boolean;
82}
83
84interface CacheConfig {
85 ttl: number; // SECONDS (note: rateLimit.window is milliseconds)
86 key?: string; // static cache key (not a function)
87 tags?: string[];
88}
89
90// Custom middleware is placed by phase, then runs in declaration order
91// within that phase.
92interface MiddlewarePhases {
93 before?: Middleware[]; // ahead of rate limiting and auth
94 transform?: Middleware[]; // after validation, before the cache check
95 after?: Middleware[]; // just before the handler (.use() lands here)
96}
97
98interface ValidationErrorDetail {
99 field: string;
100 message: string;
101 code?: string;
102 value?: any;
103 path?: (string | number)[];
104}
105
106interface ValidationErrorResponse {
107 status: number;
108 body: any;
109 headers?: Record<string, string>;
110}
111
112type ValidationSchema = z.ZodSchema<any>;Middleware Types
Middleware Function Typestypescript
1// Middleware function type
2type MiddlewareFunction = (
3 context: RequestContext,
4 next: NextFunction
5) => void | Promise<void>;
6
7// Next function type
8type NextFunction = () => void | Promise<void>;
9
10// Middleware factory type (for configurable middleware)
11type MiddlewareFactory<T = any> = (options?: T) => MiddlewareFunction;
12
13// Built-in middleware options
14interface CorsOptions {
15 origin?: string | string[] | ((origin: string) => boolean);
16 methods?: string[];
17 allowedHeaders?: string[];
18 exposedHeaders?: string[];
19 credentials?: boolean;
20 maxAge?: number;
21 preflightContinue?: boolean;
22 optionsSuccessStatus?: number;
23}
24
25interface RateLimitOptions {
26 requests?: number; // or max
27 max?: number;
28 window?: number; // milliseconds; or windowMs
29 windowMs?: number;
30 message?: string;
31 statusCode?: number; // default 429
32 skipSuccessfulRequests?: boolean;
33 skipFailedRequests?: boolean;
34}
35
36interface HelmetOptions {
37 contentSecurityPolicy?: {
38 directives?: Record<string, string[]>;
39 reportOnly?: boolean;
40 };
41 crossOriginEmbedderPolicy?: boolean;
42 crossOriginOpenerPolicy?: boolean;
43 crossOriginResourcePolicy?: { policy: 'same-site' | 'same-origin' | 'cross-origin' };
44 dnsPrefetchControl?: boolean;
45 frameguard?: { action: 'deny' | 'sameorigin' };
46 hidePoweredBy?: boolean;
47 hsts?: {
48 maxAge?: number;
49 includeSubDomains?: boolean;
50 preload?: boolean;
51 };
52 ieNoOpen?: boolean;
53 noSniff?: boolean;
54 originAgentCluster?: boolean;
55 permittedCrossDomainPolicies?: boolean;
56 referrerPolicy?: string;
57 xssFilter?: boolean;
58}
59
60// Rate limit store interface
61interface RateLimitStore {
62 get(key: string): Promise<number | null>;
63 set(key: string, value: number, ttl: number): Promise<void>;
64 increment(key: string, ttl: number): Promise<number>;
65 reset(key: string): Promise<void>;
66}Configuration Types
Configuration Interfacestypescript
1// Server configuration
2interface ServerConfig {
3 port?: number;
4 host?: string;
5 environment?: 'development' | 'staging' | 'production';
6 gracefulShutdown?: {
7 timeout?: number;
8 signals?: string[];
9 };
10 keepAlive?: boolean;
11 bodyLimit?: string;
12}
13
14// Security configuration
15interface SecurityConfig {
16 cors?: CorsOptions;
17 helmet?: HelmetOptions;
18 rateLimit?: {
19 global?: RateLimitOptions;
20 api?: RateLimitOptions;
21 };
22 csrf?: {
23 enabled?: boolean;
24 secret?: string;
25 cookie?: CookieOptions;
26 };
27}
28
29// Database configuration
30interface DatabaseConfig {
31 default?: {
32 type?: 'postgresql' | 'mysql' | 'sqlite' | 'mongodb';
33 url?: string;
34 pool?: {
35 min?: number;
36 max?: number;
37 acquireTimeoutMillis?: number;
38 idleTimeoutMillis?: number;
39 createTimeoutMillis?: number;
40 };
41 migrations?: {
42 directory?: string;
43 autoRun?: boolean;
44 table?: string;
45 };
46 ssl?: boolean | {
47 rejectUnauthorized?: boolean;
48 ca?: string;
49 key?: string;
50 cert?: string;
51 };
52 };
53 cache?: {
54 type?: 'redis' | 'memory' | 'file';
55 url?: string;
56 ttl?: string;
57 prefix?: string;
58 maxSize?: number;
59 };
60}
61
62// Logging configuration
63interface LoggingConfig {
64 level?: 'debug' | 'info' | 'warn' | 'error';
65 format?: 'json' | 'pretty';
66 destinations?: Array<{
67 type: 'console' | 'file' | 'http';
68 path?: string;
69 url?: string;
70 level?: string;
71 }>;
72 requestLogging?: {
73 enabled?: boolean;
74 skipHealthChecks?: boolean;
75 skipPaths?: string[];
76 format?: string;
77 };
78}
79
80// Features configuration
81interface FeaturesConfig {
82 websockets?: boolean | {
83 enabled?: boolean;
84 path?: string;
85 cors?: CorsOptions;
86 };
87 fileUploads?: {
88 enabled?: boolean;
89 maxSize?: string;
90 allowedTypes?: string[];
91 destination?: string;
92 };
93 apiDocs?: {
94 enabled?: boolean;
95 path?: string;
96 title?: string;
97 version?: string;
98 description?: string;
99 };
100 clustering?: {
101 enabled?: boolean;
102 workers?: number | 'auto';
103 memoryPerWorkerGB?: number;
104 };
105}
106
107// Environment schema
108interface EnvSchema {
109 [key: string]: {
110 required?: boolean;
111 type?: 'string' | 'number' | 'boolean';
112 default?: any;
113 enum?: string[];
114 minLength?: number;
115 maxLength?: number;
116 min?: number;
117 max?: number;
118 };
119}Utility Types
Helper Types and Utilitiestypescript
1// Generic utility types
2type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
3type Required<T, K extends keyof T> = T & Required<Pick<T, K>>;
4
5// Route parameter extraction
6type ExtractParams<T extends string> = T extends `${infer Start}:${infer Param}/${infer Rest}`
7 ? { [K in Param]: string } & ExtractParams<Rest>
8 : T extends `${infer Start}:${infer Param}`
9 ? { [K in Param]: string }
10 : {};
11
12// Type-safe route handler with parameter inference
13type TypedRouteHandler<TPath extends string, TBody = any, TResponse = any> = (
14 context: RequestContext & {
15 params: ExtractParams<TPath>;
16 body: TBody;
17 }
18) => TResponse | Promise<TResponse>;
19
20// WebSocket types
21interface WebSocketConnection {
22 id: string;
23 send(data: any): void;
24 close(code?: number, reason?: string): void;
25 ping(data?: Buffer): void;
26 pong(data?: Buffer): void;
27 on(event: 'message' | 'close' | 'error' | 'ping' | 'pong', handler: Function): void;
28 off(event: string, handler: Function): void;
29}
30
31interface WebSocketManager {
32 connections: Map<string, WebSocketConnection>;
33 broadcast(data: any, filter?: (connection: WebSocketConnection) => boolean): void;
34 getConnection(id: string): WebSocketConnection | undefined;
35 closeConnection(id: string): void;
36 closeAll(): void;
37}
38
39// Event system types
40interface EventBus {
41 emit(event: string, data?: any): void;
42 on(event: string, handler: (data: any) => void): void;
43 off(event: string, handler: (data: any) => void): void;
44 once(event: string, handler: (data: any) => void): void;
45 removeAllListeners(event?: string): void;
46}
47
48// Cache types
49interface CacheStore {
50 get<T = any>(key: string): Promise<T | null>;
51 set<T = any>(key: string, value: T, options?: { ttl?: string | number }): Promise<void>;
52 delete(key: string): Promise<boolean>;
53 clear(): Promise<void>;
54 has(key: string): Promise<boolean>;
55 keys(pattern?: string): Promise<string[]>;
56}
57
58// Logger types
59interface Logger {
60 debug(message: string, meta?: any): void;
61 info(message: string, meta?: any): void;
62 warn(message: string, meta?: any): void;
63 error(message: string, meta?: any): void;
64 child(meta: any): Logger;
65}Type Safety Benefits
- Full IntelliSense and autocomplete support
- Compile-time type checking for routes and handlers
- Automatic parameter type inference from route paths
- Schema-based request/response validation
- Type-safe configuration and environment variables