@flight-framework/core 0.2.6 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,9 +2,41 @@
2
2
  * Flight Middleware - Composable request/response handlers
3
3
  *
4
4
  * Framework-agnostic middleware system inspired by Koa/Hono.
5
+ * Provides primitives for building your own middleware solutions.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // Type-safe middleware with custom variables (Hono pattern)
10
+ * interface MyLocals {
11
+ * user: { id: string; role: string };
12
+ * requestId: string;
13
+ * }
14
+ *
15
+ * const authMiddleware: Middleware<MyLocals> = async (ctx, next) => {
16
+ * ctx.locals.user = { id: '123', role: 'admin' };
17
+ * await next();
18
+ * };
19
+ * ```
5
20
  */
6
- /** Request context passed through middleware chain */
7
- interface MiddlewareContext {
21
+ /**
22
+ * Request context passed through middleware chain.
23
+ *
24
+ * Supports generic type parameter for type-safe locals (like Hono Variables).
25
+ *
26
+ * @typeParam TLocals - Type of the locals object for type-safe middleware data sharing
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * interface AppLocals {
31
+ * user: User;
32
+ * db: DatabaseClient;
33
+ * }
34
+ *
35
+ * const ctx: MiddlewareContext<AppLocals> = createContextFromRequest(request);
36
+ * ctx.locals.user = currentUser; // Type-safe!
37
+ * ```
38
+ */
39
+ interface MiddlewareContext<TLocals extends Record<string, unknown> = Record<string, unknown>> {
8
40
  /** Request URL */
9
41
  url: URL;
10
42
  /** Request method */
@@ -17,8 +49,8 @@ interface MiddlewareContext {
17
49
  query: URLSearchParams;
18
50
  /** Parsed request body (if any) */
19
51
  body?: unknown;
20
- /** Local data shared between middleware */
21
- locals: Record<string, unknown>;
52
+ /** Local data shared between middleware - type-safe with generics */
53
+ locals: TLocals;
22
54
  /** Original request (platform-specific) */
23
55
  request?: Request;
24
56
  /** Response status code */
@@ -30,8 +62,12 @@ interface MiddlewareContext {
30
62
  }
31
63
  /** Next function to call the next middleware */
32
64
  type MiddlewareNext = () => Promise<void>;
33
- /** Middleware function signature */
34
- type Middleware = (ctx: MiddlewareContext, next: MiddlewareNext) => Promise<void> | void;
65
+ /**
66
+ * Middleware function signature with optional typed locals.
67
+ *
68
+ * @typeParam TLocals - Type of the locals object for type-safe data sharing
69
+ */
70
+ type Middleware<TLocals extends Record<string, unknown> = Record<string, unknown>> = (ctx: MiddlewareContext<TLocals>, next: MiddlewareNext) => Promise<void> | void;
35
71
  /** Middleware with optional path matching */
36
72
  interface MiddlewareDefinition {
37
73
  /** Path pattern to match (undefined = match all) */
@@ -58,13 +94,52 @@ declare function createMiddlewareChain(): MiddlewareChain;
58
94
  /**
59
95
  * CORS middleware factory
60
96
  */
61
- declare function cors(options?: {
62
- origin?: string | string[] | ((origin: string) => boolean);
97
+ /**
98
+ * CORS options for configuring cross-origin requests.
99
+ */
100
+ interface CorsOptions {
101
+ /**
102
+ * Allowed origins. Can be:
103
+ * - '*' for any origin
104
+ * - A specific origin string
105
+ * - An array of allowed origins
106
+ * - A function that returns true if origin is allowed
107
+ * - An async function for dynamic origin validation
108
+ */
109
+ origin?: string | string[] | ((origin: string) => boolean | Promise<boolean>);
110
+ /** Allowed HTTP methods */
63
111
  methods?: string[];
112
+ /** Allowed headers */
64
113
  headers?: string[];
114
+ /** Whether to include credentials */
65
115
  credentials?: boolean;
116
+ /** Preflight cache duration in seconds */
66
117
  maxAge?: number;
67
- }): Middleware;
118
+ /** Exposed headers that can be accessed from the response */
119
+ exposeHeaders?: string[];
120
+ }
121
+ /**
122
+ * CORS middleware factory.
123
+ *
124
+ * Handles cross-origin resource sharing with best practices:
125
+ * - Adds Vary: Origin for dynamic origins (CDN compatibility)
126
+ * - Supports async origin validation
127
+ * - Proper preflight handling
128
+ *
129
+ * @example
130
+ * ```typescript
131
+ * // Allow specific origins
132
+ * chain.use(cors({ origin: ['https://app.example.com'] }));
133
+ *
134
+ * // Dynamic validation
135
+ * chain.use(cors({
136
+ * origin: async (origin) => {
137
+ * return await db.allowedOrigins.exists(origin);
138
+ * }
139
+ * }));
140
+ * ```
141
+ */
142
+ declare function cors(options?: CorsOptions): Middleware;
68
143
  /** Log levels in order of verbosity */
69
144
  type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
70
145
  /** Log format types */
@@ -136,6 +211,84 @@ declare function securityHeaders(options?: {
136
211
  * Compression middleware (requires implementation in adapter)
137
212
  */
138
213
  declare function compress(): Middleware;
214
+ /**
215
+ * Error information passed to error handlers.
216
+ */
217
+ interface ErrorInfo {
218
+ /** The original error */
219
+ error: Error;
220
+ /** HTTP status code (derived from error or default 500) */
221
+ status: number;
222
+ /** Error code for categorization */
223
+ code?: string;
224
+ /** Request context */
225
+ ctx: MiddlewareContext;
226
+ /** Request timestamp */
227
+ timestamp: string;
228
+ }
229
+ /**
230
+ * Error handler options.
231
+ */
232
+ interface ErrorHandlerOptions {
233
+ /**
234
+ * Custom error handler function.
235
+ * Called when an error is caught. Can modify ctx to set response.
236
+ * If not provided, a default JSON response is sent.
237
+ */
238
+ onError?: (info: ErrorInfo) => void | Promise<void>;
239
+ /**
240
+ * Whether to expose error details in response.
241
+ * Set to false in production to hide internal error messages.
242
+ * @default false
243
+ */
244
+ expose?: boolean;
245
+ /**
246
+ * Default status code for errors without a status property.
247
+ * @default 500
248
+ */
249
+ defaultStatus?: number;
250
+ /**
251
+ * Emit error events for centralized logging (Koa pattern).
252
+ * Provide a function to receive error events.
253
+ */
254
+ emit?: (error: Error, ctx: MiddlewareContext) => void;
255
+ }
256
+ /**
257
+ * Error handler middleware factory.
258
+ *
259
+ * Provides centralized error handling following Koa best practices:
260
+ * - Catches all downstream errors
261
+ * - Sets appropriate status codes
262
+ * - Supports custom error handlers
263
+ * - Supports error event emission for logging
264
+ *
265
+ * Place this as one of the FIRST middleware in your chain.
266
+ *
267
+ * @example
268
+ * ```typescript
269
+ * // Basic usage - default JSON error response
270
+ * chain.use(errorHandler());
271
+ *
272
+ * // With custom handler
273
+ * chain.use(errorHandler({
274
+ * onError: ({ error, status, ctx }) => {
275
+ * ctx.status = status;
276
+ * ctx.responseBody = JSON.stringify({
277
+ * error: error.message,
278
+ * code: 'SERVER_ERROR'
279
+ * });
280
+ * },
281
+ * emit: (error, ctx) => {
282
+ * logger.error('Request error:', error);
283
+ * errorTracker.capture(error);
284
+ * }
285
+ * }));
286
+ *
287
+ * // Production-safe (hide error details)
288
+ * chain.use(errorHandler({ expose: false }));
289
+ * ```
290
+ */
291
+ declare function errorHandler(options?: ErrorHandlerOptions): Middleware;
139
292
  /**
140
293
  * Create a middleware context from a Web Request
141
294
  */
@@ -149,4 +302,4 @@ declare function createResponseFromContext(ctx: MiddlewareContext): Response;
149
302
  */
150
303
  declare function compose(...middlewares: Middleware[]): Middleware;
151
304
 
152
- export { type LogEntry, type LogFormat, type LogLevel, type LogWriter, type LoggerOptions, type Middleware, type MiddlewareChain, type MiddlewareContext, type MiddlewareDefinition, type MiddlewareNext, compose, compress, cors, createContextFromRequest, createMiddlewareChain, createResponseFromContext, logger, securityHeaders };
305
+ export { type CorsOptions, type ErrorHandlerOptions, type ErrorInfo, type LogEntry, type LogFormat, type LogLevel, type LogWriter, type LoggerOptions, type Middleware, type MiddlewareChain, type MiddlewareContext, type MiddlewareDefinition, type MiddlewareNext, compose, compress, cors, createContextFromRequest, createMiddlewareChain, createResponseFromContext, errorHandler, logger, securityHeaders };
@@ -1,3 +1,3 @@
1
- export { compose, compress, cors, createContextFromRequest, createMiddlewareChain, createResponseFromContext, logger, securityHeaders } from '../chunk-KWFX6WHG.js';
1
+ export { compose, compress, cors, createContextFromRequest, createMiddlewareChain, createResponseFromContext, errorHandler, logger, securityHeaders } from '../chunk-OYF2OAKS.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,6 @@
1
- export { createServer, getRuntime, isFlightServer } from '../chunk-LBYDTULN.js';
1
+ export { createServer, getRuntime, isFlightServer } from '../chunk-ROJFQCGV.js';
2
2
  import '../chunk-IXMD5QH2.js';
3
3
  import '../chunk-GCQZ4FHI.js';
4
- import '../chunk-KWFX6WHG.js';
4
+ import '../chunk-OYF2OAKS.js';
5
5
  //# sourceMappingURL=index.js.map
6
6
  //# sourceMappingURL=index.js.map