blaizejs 0.5.1 → 0.5.3

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.
Files changed (26) hide show
  1. package/dist/{chunk-NA2GUVHF.js → chunk-BOFAGA5B.js} +3 -3
  2. package/dist/chunk-JMYOXYX4.js +11 -0
  3. package/dist/{chunk-VAD7G4RR.js.map → chunk-JMYOXYX4.js.map} +1 -1
  4. package/dist/{chunk-6G464Q37.js → chunk-NXPSLUP5.js} +3 -3
  5. package/dist/{chunk-Y7KAZMOI.js → chunk-VVEKNV22.js} +3 -3
  6. package/dist/{chunk-XZOKQ5VF.js → chunk-ZBJU7ZOM.js} +3 -3
  7. package/dist/index.cjs +14 -14
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +1417 -1433
  10. package/dist/index.d.ts +1417 -1433
  11. package/dist/index.js +15 -15
  12. package/dist/index.js.map +1 -1
  13. package/dist/{internal-server-error-4S64KATC.js → internal-server-error-MIWZOL6G.js} +3 -3
  14. package/dist/{payload-too-large-error-BC6YVP2R.js → payload-too-large-error-INCZ2WM7.js} +3 -3
  15. package/dist/{unsupported-media-type-error-FV554WCH.js → unsupported-media-type-error-BVGBPGOM.js} +3 -3
  16. package/dist/{validation-error-ZLDRDHW5.js → validation-error-BQK2BTX6.js} +3 -3
  17. package/package.json +2 -2
  18. package/dist/chunk-VAD7G4RR.js +0 -11
  19. /package/dist/{chunk-NA2GUVHF.js.map → chunk-BOFAGA5B.js.map} +0 -0
  20. /package/dist/{chunk-6G464Q37.js.map → chunk-NXPSLUP5.js.map} +0 -0
  21. /package/dist/{chunk-Y7KAZMOI.js.map → chunk-VVEKNV22.js.map} +0 -0
  22. /package/dist/{chunk-XZOKQ5VF.js.map → chunk-ZBJU7ZOM.js.map} +0 -0
  23. /package/dist/{internal-server-error-4S64KATC.js.map → internal-server-error-MIWZOL6G.js.map} +0 -0
  24. /package/dist/{payload-too-large-error-BC6YVP2R.js.map → payload-too-large-error-INCZ2WM7.js.map} +0 -0
  25. /package/dist/{unsupported-media-type-error-FV554WCH.js.map → unsupported-media-type-error-BVGBPGOM.js.map} +0 -0
  26. /package/dist/{validation-error-ZLDRDHW5.js.map → validation-error-BQK2BTX6.js.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -8,1691 +8,1671 @@ import { AsyncLocalStorage } from 'node:async_hooks';
8
8
  import { EventEmitter } from 'node:events';
9
9
 
10
10
  /**
11
- * Error type definitions and interfaces for the BlaizeJS framework
12
- *
13
- * This module contains all the type definitions used for error handling
14
- * across the BlaizeJS framework, including server-side errors, client-side
15
- * errors, and HTTP response formats.
11
+ * Represents an uploaded file in a multipart/form-data request
16
12
  */
13
+ interface UploadedFile {
14
+ /** Original filename provided by the client (may be undefined) */
15
+ readonly filename: string | undefined;
16
+ /** Form field name this file was uploaded under */
17
+ readonly fieldname: string;
18
+ /** MIME type of the uploaded file */
19
+ readonly mimetype: string;
20
+ /** Size of the file in bytes */
21
+ readonly size: number;
22
+ /** Stream containing the file data (always available) */
23
+ readonly stream: Readable;
24
+ /** Buffer containing file data (only available with 'memory' strategy) */
25
+ readonly buffer?: Buffer;
26
+ /** Path to temporary file (only available with 'temp' strategy) */
27
+ readonly tempPath?: string;
28
+ /** SHA-256 hash of file content (if computed) */
29
+ readonly hash?: string;
30
+ }
17
31
  /**
18
- * Structure of error responses sent over HTTP
19
- *
20
- * This interface defines the JSON format used for all error responses
21
- * from BlaizeJS servers. It matches the structure returned by BlaizeError.toJSON()
22
- *
23
- * @example
24
- * ```json
25
- * {
26
- * "type": "VALIDATION_ERROR",
27
- * "title": "Request validation failed",
28
- * "status": 400,
29
- * "correlationId": "req_abc123",
30
- * "timestamp": "2024-01-15T10:30:00.000Z",
31
- * "details": {
32
- * "fields": ["email", "password"]
33
- * }
34
- * }
35
- * ```
32
+ * Complete multipart/form-data parsed content
36
33
  */
37
- interface BlaizeErrorResponse {
38
- /** Error type from the ErrorType enum */
39
- type: ErrorType;
40
- /** Human-readable error message */
41
- title: string;
42
- /** HTTP status code */
43
- status: number;
44
- /** Correlation ID for request tracing */
45
- correlationId: string;
46
- /** ISO timestamp when error occurred */
47
- timestamp: string;
48
- /** Optional error-specific details */
49
- details?: unknown;
34
+ interface MultipartData {
35
+ /** Form fields (non-file inputs) */
36
+ readonly fields: Record<string, string | string[]>;
37
+ /** Uploaded files */
38
+ readonly files: Record<string, UploadedFile | UploadedFile[]>;
50
39
  }
51
40
  /**
52
- * Context information for network-related errors
53
- *
54
- * Used by client-side error classes to provide additional context
55
- * about network failures, timeouts, and connection issues.
41
+ * Options for parsing multipart/form-data
56
42
  */
57
- interface NetworkErrorContext {
58
- /** The URL that failed */
59
- url: string;
60
- /** HTTP method being attempted */
61
- method: string;
62
- /** Correlation ID for tracing */
63
- correlationId: string;
64
- /** Timeout value if applicable */
65
- timeout?: number;
66
- /** The original error that caused the network failure */
67
- originalError: Error;
68
- /** Additional network-specific details */
69
- networkDetails?: {
70
- /** Whether this was a connection timeout */
71
- isTimeout?: boolean;
72
- /** Whether this was a DNS resolution failure */
73
- isDnsFailure?: boolean;
74
- /** Whether this was a connection refused error */
75
- isConnectionRefused?: boolean;
76
- /** HTTP status code if received before failure */
77
- statusCode?: number;
78
- };
43
+ interface ParseOptions {
44
+ /** Maximum size for individual files in bytes (default: 10MB) */
45
+ readonly maxFileSize?: number;
46
+ /** Maximum number of files per request (default: 10) */
47
+ readonly maxFiles?: number;
48
+ /** Maximum size for form fields in bytes (default: 1MB) */
49
+ readonly maxFieldSize?: number;
50
+ /** Allowed MIME types (empty array = allow all) */
51
+ readonly allowedMimeTypes?: readonly string[];
52
+ /** Allowed file extensions (empty array = allow all) */
53
+ readonly allowedExtensions?: readonly string[];
54
+ /** Processing strategy for file data */
55
+ readonly strategy: 'memory' | 'stream' | 'temp';
56
+ /** Directory for temporary files (strategy: 'temp' only) */
57
+ readonly tempDir?: string;
58
+ /** Whether to compute SHA-256 hash of files */
59
+ readonly computeHash?: boolean;
79
60
  }
80
61
  /**
81
- * Context information for request timeout errors
82
- *
83
- * Specialized context for timeout-specific errors with timing information.
62
+ * Result of parsing multipart data with metadata
84
63
  */
85
- interface TimeoutErrorContext {
86
- /** The URL that timed out */
87
- url: string;
88
- /** HTTP method being attempted */
89
- method: string;
90
- /** Correlation ID for tracing */
91
- correlationId: string;
92
- /** Configured timeout value in milliseconds */
93
- timeoutMs: number;
94
- /** Actual duration before timeout in milliseconds */
95
- elapsedMs: number;
96
- /** Type of timeout (request, connection, etc.) */
97
- timeoutType: 'request' | 'connection' | 'response' | 'idle';
64
+ interface ParseResult {
65
+ /** Parsed multipart data */
66
+ readonly data: MultipartData;
67
+ /** Parsing metadata */
68
+ readonly metadata: {
69
+ /** Total time spent parsing (milliseconds) */
70
+ readonly parseTime: number;
71
+ /** Total size of all uploaded content */
72
+ readonly totalSize: number;
73
+ /** Number of files processed */
74
+ readonly fileCount: number;
75
+ /** Number of fields processed */
76
+ readonly fieldCount: number;
77
+ };
98
78
  }
99
79
  /**
100
- * Context information for response parsing errors
101
- *
102
- * Used when the client receives a response but cannot parse it properly.
80
+ * Error information for multipart parsing failures
103
81
  */
104
- interface ParseErrorContext {
105
- /** The URL that returned unparseable content */
106
- url: string;
107
- /** HTTP method used */
108
- method: string;
109
- /** Correlation ID for tracing */
110
- correlationId: string;
111
- /** HTTP status code received */
112
- statusCode: number;
113
- /** Content-Type header if available */
114
- contentType?: string;
115
- /** Expected response format */
116
- expectedFormat: 'json' | 'text' | 'binary';
117
- /** Sample of the actual response content (truncated for safety) */
118
- responseSample?: string;
119
- /** The original parsing error */
120
- originalError: Error;
82
+ interface MultipartError {
83
+ /** Error type/code */
84
+ readonly type: 'boundary_missing' | 'size_exceeded' | 'file_limit_exceeded' | 'mime_type_forbidden' | 'extension_forbidden' | 'parse_error' | 'stream_error' | 'temp_file_error';
85
+ /** Human-readable error message */
86
+ readonly message: string;
87
+ /** Additional context (field name, file name, etc.) */
88
+ readonly context?: Record<string, unknown>;
89
+ /** Original error if available */
90
+ readonly cause?: Error;
121
91
  }
122
92
  /**
123
- * Validation error field details
124
- *
125
- * Structure for field-level validation errors with multiple error messages
126
- * per field.
93
+ * Configuration for file upload validation
127
94
  */
128
- interface ValidationFieldError {
129
- /** Field name or path (e.g., "email", "user.profile.name") */
130
- field: string;
131
- /** Array of error messages for this field */
132
- messages: string[];
133
- /** The invalid value that caused the error */
134
- rejectedValue?: unknown;
135
- /** Expected type or format */
136
- expectedType?: string;
137
- }
138
- interface ServiceNotAvailableDetails {
139
- /** Service that's unavailable */
140
- service?: string;
141
- /** Seconds to wait before retry */
142
- retryAfter?: number;
143
- /** Why service is unavailable */
144
- reason?: 'maintenance' | 'overload' | 'circuit_breaker' | 'dependency_down';
145
- /** Additional context */
146
- [key: string]: unknown;
95
+ interface ValidationConfig {
96
+ /** File size constraints */
97
+ readonly size?: {
98
+ readonly min?: number;
99
+ readonly max?: number;
100
+ };
101
+ /** File count constraints */
102
+ readonly count?: {
103
+ readonly min?: number;
104
+ readonly max?: number;
105
+ };
106
+ /** MIME type constraints */
107
+ readonly mimeTypes?: {
108
+ readonly allowed?: readonly string[];
109
+ readonly forbidden?: readonly string[];
110
+ };
111
+ /** File extension constraints */
112
+ readonly extensions?: {
113
+ readonly allowed?: readonly string[];
114
+ readonly forbidden?: readonly string[];
115
+ };
116
+ /** Custom validation function */
117
+ readonly custom?: (file: UploadedFile) => Promise<boolean> | boolean;
147
118
  }
148
119
  /**
149
- * Validation error details structure
150
- *
151
- * Used by ValidationError to provide structured information about
152
- * what fields failed validation and why.
120
+ * File processing configuration
153
121
  */
154
- interface ValidationErrorDetails {
155
- /** Array of field-level errors */
156
- fields: ValidationFieldError[];
157
- /** Total number of validation errors */
158
- errorCount: number;
159
- /** The section that failed validation */
160
- section: 'params' | 'query' | 'body' | 'response';
161
- /** Schema name if available */
162
- schemaName?: string;
122
+ interface ProcessingConfig {
123
+ /** Whether to process files concurrently */
124
+ readonly concurrent?: boolean;
125
+ /** Maximum concurrent processing operations */
126
+ readonly maxConcurrency?: number;
127
+ /** Processing timeout in milliseconds */
128
+ readonly timeout?: number;
129
+ /** Whether to preserve original files during processing */
130
+ readonly preserveOriginal?: boolean;
163
131
  }
164
132
  /**
165
- * All available error types in the BlaizeJS framework
166
- *
167
- * This enum provides both compile-time type safety and runtime values
168
- * for error type identification across server and client packages.
169
- *
170
- * @example Type-safe error handling:
171
- * ```typescript
172
- * function handleError(errorType: ErrorType) {
173
- * switch (errorType) {
174
- * case ErrorType.VALIDATION_ERROR:
175
- * // Handle validation error
176
- * break;
177
- * case ErrorType.NOT_FOUND:
178
- * // Handle not found error
179
- * break;
180
- * // TypeScript ensures all cases are covered
181
- * }
182
- * }
183
- * ```
133
+ * Upload progress information (for future streaming uploads)
184
134
  */
185
- declare enum ErrorType {
186
- /** Request validation failed (400) */
187
- VALIDATION_ERROR = "VALIDATION_ERROR",
188
- /** Resource not found (404) */
189
- NOT_FOUND = "NOT_FOUND",
190
- /** Authentication required (401) */
191
- UNAUTHORIZED = "UNAUTHORIZED",
192
- /** Access forbidden (403) */
193
- FORBIDDEN = "FORBIDDEN",
194
- /** SSE Not Acceptable (406) */
195
- SSE_NOT_ACCEPTABLE = "SSE_NOT_ACCEPTABLE",
196
- /** Resource conflict (409) */
197
- CONFLICT = "CONFLICT",
198
- /** Rate limit exceeded (429) */
199
- RATE_LIMITED = "RATE_LIMITED",
200
- /** Internal server error (500) */
201
- INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR",
202
- /** File/Request Too Large (413) */
203
- PAYLOAD_TOO_LARGE = "PAYLOAD_TOO_LARGE",
204
- /** Wrong Content Type (415) */
205
- UNSUPPORTED_MEDIA_TYPE = "UNSUPPORTED_MEDIA_TYPE",
206
- /** Upload Timeout (408) */
207
- UPLOAD_TIMEOUT = "UPLOAD_TIMEOUT",
208
- /** Valid Format Invalid Semantics (422) */
209
- UNPROCESSABLE_ENTITY = "UNPROCESSABLE_ENTITY",
210
- /** Network connectivity failure (0) */
211
- NETWORK_ERROR = "NETWORK_ERROR",
212
- /** Request or response timeout (0) */
213
- TIMEOUT_ERROR = "TIMEOUT_ERROR",
214
- /** Response parsing failure (0) */
215
- PARSE_ERROR = "PARSE_ERROR",
216
- /** Generic HTTP error (varies) */
217
- HTTP_ERROR = "HTTP_ERROR",
218
- /** SSE connection failed (502) */
219
- SSE_CONNECTION_ERROR = "SSE_CONNECTION_ERROR",
220
- /** SSE buffer overflow (503) */
221
- SSE_BUFFER_OVERFLOW = "SSE_BUFFER_OVERFLOW",
222
- /** SSE stream closed (410) */
223
- SSE_STREAM_CLOSED = "SSE_STREAM_CLOSED",
224
- /** Service temporarily unavailable (503) */
225
- SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE"
226
- }
227
- /**
228
- * Error severity levels for logging and monitoring
229
- *
230
- * Provides a way to categorize errors by their impact and urgency.
231
- */
232
- declare enum ErrorSeverity {
233
- /** Low impact, often user errors */
234
- LOW = "low",
235
- /** Medium impact, application errors */
236
- MEDIUM = "medium",
237
- /** High impact, system errors */
238
- HIGH = "high",
239
- /** Critical impact, service disruption */
240
- CRITICAL = "critical"
135
+ interface UploadProgress {
136
+ /** Bytes uploaded so far */
137
+ readonly bytesUploaded: number;
138
+ /** Total bytes to upload */
139
+ readonly totalBytes: number;
140
+ /** Upload percentage (0-100) */
141
+ readonly percentage: number;
142
+ /** Upload speed in bytes per second */
143
+ readonly speed: number;
144
+ /** Estimated time remaining in milliseconds */
145
+ readonly eta: number;
241
146
  }
242
147
  /**
243
- * Abstract base class for all BlaizeJS errors
244
- *
245
- * This class provides the foundation for all error types in the BlaizeJS framework.
246
- * It extends JavaScript's built-in Error class and adds framework-specific properties
247
- * for consistent error handling across server and client.
248
- *
249
- * @example
250
- * ```typescript
251
- * import { ErrorType } from './types';
252
- *
253
- * class NotFoundError extends BlaizeError<{ resourceId: string }> {
254
- * constructor(message = 'Resource not found', details?: { resourceId: string }) {
255
- * super(ErrorType.NOT_FOUND, message, 404, getCurrentCorrelationId(), details);
256
- * }
257
- * }
258
- * ```
259
- *
260
- * @template TDetails - Type for error-specific details object
148
+ * Internal state for multipart parser state machine
261
149
  */
262
- declare abstract class BlaizeError<TDetails = unknown> extends Error {
263
- /**
264
- * Error type identifier from the ErrorType enum
265
- * Used for programmatic error handling and client-side error routing
266
- */
267
- readonly type: ErrorType;
268
- /**
269
- * Human-readable error title/message
270
- * Should be descriptive enough for debugging but safe for end users
271
- */
272
- readonly title: string;
273
- /**
274
- * HTTP status code associated with this error
275
- * Used by the error boundary to set appropriate response status
276
- */
277
- readonly status: number;
278
- /**
279
- * Correlation ID for request tracing
280
- * Links this error to the specific request that generated it
281
- */
282
- readonly correlationId: string;
283
- /**
284
- * Timestamp when the error occurred
285
- * Useful for debugging and log correlation
286
- */
287
- readonly timestamp: Date;
288
- /**
289
- * Additional error-specific details
290
- * Type-safe error context that varies by error type
291
- */
292
- readonly details?: TDetails | undefined;
150
+ interface ParserState {
151
+ boundary: Buffer;
152
+ options: Required<ParseOptions>;
153
+ fields: Map<string, string[]>;
154
+ files: Map<string, UploadedFile[]>;
155
+ buffer: Buffer;
156
+ stage: 'boundary' | 'headers' | 'content';
157
+ currentHeaders: string;
158
+ currentField: string | null;
159
+ currentFilename: string | undefined;
160
+ currentMimetype: string;
161
+ currentContentLength: number;
162
+ fileCount: number;
163
+ fieldCount: number;
164
+ currentBufferChunks: Buffer[];
165
+ currentStream: Readable | null;
166
+ currentTempPath: string | null;
167
+ currentWriteStream: WriteStream | null;
168
+ streamController: ReadableStreamDefaultController<Uint8Array> | null;
169
+ cleanupTasks: Array<() => Promise<void>>;
293
170
  /**
294
- * Creates a new BlaizeError instance
295
- *
296
- * @param type - Error type from the ErrorType enum
297
- * @param title - Human-readable error message
298
- * @param status - HTTP status code
299
- * @param correlationId - Request correlation ID for tracing
300
- * @param details - Optional error-specific details
171
+ * Whether we've found at least one valid boundary marker
301
172
  */
302
- protected constructor(type: ErrorType, title: string, status: number, correlationId: string, details?: TDetails | undefined);
173
+ hasFoundValidBoundary: boolean;
303
174
  /**
304
- * Serializes the error to a plain object suitable for HTTP responses
305
- *
306
- * @returns Object representation of the error
175
+ * Whether we've successfully processed at least one complete part (field or file)
307
176
  */
308
- toJSON(): {
309
- type: ErrorType;
310
- title: string;
311
- status: number;
312
- correlationId: string;
313
- timestamp: string;
314
- } | {
315
- details: TDetails & ({} | null);
316
- type: ErrorType;
317
- title: string;
318
- status: number;
319
- correlationId: string;
320
- timestamp: string;
321
- };
177
+ hasProcessedAnyPart: boolean;
322
178
  /**
323
- * Returns a string representation of the error
324
- * Includes correlation ID for easier debugging
179
+ * Whether parsing has reached the end boundary
325
180
  */
326
- toString(): string;
181
+ isFinished: boolean;
327
182
  }
183
+
328
184
  /**
329
- * Interface for payload too large error details
185
+ * Unified request type supporting both HTTP/1.1 and HTTP/2
330
186
  */
331
- interface PayloadTooLargeErrorDetails {
332
- fileCount?: number;
333
- maxFiles?: number;
334
- filename?: string;
335
- field?: string;
336
- contentType?: string;
337
- currentSize?: number;
338
- maxSize?: number;
339
- }
187
+ type UnifiedRequest = IncomingMessage | Http2ServerRequest;
340
188
  /**
341
- * Interface for unsupported media type error details
189
+ * Unified response type supporting both HTTP/1.1 and HTTP/2
342
190
  */
343
- interface UnsupportedMediaTypeErrorDetails {
344
- receivedMimeType?: string;
345
- allowedMimeTypes?: string[];
346
- filename?: string;
191
+ type UnifiedResponse = ServerResponse | Http2ServerResponse;
192
+ /**
193
+ * Request parameters extracted from URL path
194
+ */
195
+ interface RequestParams {
196
+ [key: string]: string;
347
197
  }
348
198
  /**
349
- * Interface for authentication error details
199
+ * Query parameters from URL
350
200
  */
351
- interface UnauthorizedErrorDetails {
352
- /** Reason for authentication failure */
353
- reason?: 'missing_token' | 'invalid_token' | 'expired_token' | 'malformed_token' | 'insufficient_scope' | string;
354
- /** Authentication scheme (Bearer, Basic, etc.) */
355
- authScheme?: string;
356
- /** Authentication realm */
357
- realm?: string;
358
- /** Detailed error description */
359
- error_description?: string;
360
- /** Required scopes or permissions */
361
- requiredScopes?: string[];
362
- /** Login URL for interactive authentication */
363
- loginUrl?: string;
364
- /** Additional context */
365
- [key: string]: unknown;
201
+ interface QueryParams {
202
+ [key: string]: string | string[] | undefined;
366
203
  }
367
204
  /**
368
- * Interface for authorization/permission error details
205
+ * Options for streaming responses
369
206
  */
370
- interface ForbiddenErrorDetails {
371
- /** Required permission or role */
372
- requiredPermission?: string;
373
- /** User's current permissions */
374
- userPermissions?: string[];
375
- /** Resource being accessed */
376
- resource?: string;
377
- /** Action being attempted */
378
- action?: string;
379
- /** Reason for access denial */
380
- reason?: 'insufficient_permissions' | 'account_suspended' | 'resource_locked' | 'origin_not_allowed' | string;
381
- /** Additional context */
382
- [key: string]: unknown;
207
+ interface StreamOptions {
208
+ contentType?: string;
209
+ status?: number;
210
+ headers?: Record<string, string>;
383
211
  }
384
212
  /**
385
- * Interface for resource conflict error details
213
+ * State container for storing request-scoped data
214
+ * Allows for proper typing with generics
386
215
  */
387
- interface ConflictErrorDetails {
388
- /** Type of conflict */
389
- conflictType?: 'duplicate_key' | 'version_mismatch' | 'concurrent_modification' | 'business_rule' | string;
390
- /** Field that caused the conflict */
391
- field?: string;
392
- /** Existing value that conflicts */
393
- existingValue?: unknown;
394
- /** Provided value that conflicts */
395
- providedValue?: unknown;
396
- /** Resource that has the conflicting value */
397
- conflictingResource?: string;
398
- /** Current version/etag of the resource */
399
- currentVersion?: string;
400
- /** Expected version/etag */
401
- expectedVersion?: string;
402
- /** Suggested resolution */
403
- resolution?: string;
404
- /** Additional context */
216
+ interface State {
405
217
  [key: string]: unknown;
406
218
  }
407
219
  /**
408
- * Interface for rate limiting error details
220
+ * Services container for storing injectable services/dependencies
221
+ * Allows middleware to contribute services that are accessible throughout the request lifecycle
409
222
  */
410
- interface RateLimitErrorDetails {
411
- /** Maximum requests allowed in the time window */
412
- limit?: number;
413
- /** Remaining requests in current window */
414
- remaining?: number;
415
- /** When the rate limit resets */
416
- resetTime?: Date;
417
- /** Seconds until the rate limit resets */
418
- retryAfter?: number;
419
- /** Time window for the rate limit */
420
- window?: string;
421
- /** Identifier used for rate limiting (IP, user ID, etc.) */
422
- identifier?: string;
423
- /** Type of rate limit hit */
424
- limitType?: 'global' | 'per_user' | 'per_ip' | 'per_endpoint' | string;
425
- /** Additional context */
223
+ interface Services {
426
224
  [key: string]: unknown;
427
225
  }
428
- /**
429
- * Interface for internal server error details
430
- */
431
- interface InternalServerErrorDetails {
432
- /** Original error message (for debugging) */
433
- originalError?: string;
434
- /** Stack trace (for debugging) */
435
- stackTrace?: string;
436
- /** Component where the error occurred */
437
- component?: string;
438
- /** Operation being performed */
439
- operation?: string;
440
- /** Internal error code */
441
- internalErrorCode?: string;
442
- /** When the error occurred */
443
- timestamp?: Date;
444
- /** Whether this error should be retryable */
445
- retryable?: boolean;
446
- /** Additional debugging context */
447
- [key: string]: unknown;
226
+ interface ContextResponse<S extends State = State> {
227
+ raw: UnifiedResponse;
228
+ sent: boolean;
229
+ statusCode: number;
230
+ status: (code: number) => ContextResponse<S>;
231
+ header: (name: string, value: string) => ContextResponse<S>;
232
+ headers: (headers: Record<string, string>) => ContextResponse<S>;
233
+ type: (contentType: string) => ContextResponse<S>;
234
+ json: (body: unknown, status?: number) => void;
235
+ text: (body: string, status?: number) => void;
236
+ html: (body: string, status?: number) => void;
237
+ redirect: (url: string, status?: number) => void;
238
+ stream: (readable: NodeJS.ReadableStream, options?: StreamOptions) => void;
239
+ }
240
+ interface ContextRequest<TBody = unknown> {
241
+ raw: UnifiedRequest;
242
+ method: string;
243
+ path: string;
244
+ url: URL | null;
245
+ query: QueryParams;
246
+ params: RequestParams;
247
+ protocol: string;
248
+ isHttp2: boolean;
249
+ body?: TBody;
250
+ /**
251
+ * Uploaded files from multipart/form-data requests
252
+ * Available when Content-Type is multipart/form-data
253
+ */
254
+ files?: Record<string, UploadedFile | UploadedFile[]>;
255
+ /**
256
+ * Complete multipart data (files + fields)
257
+ * Available when Content-Type is multipart/form-data
258
+ */
259
+ multipart?: MultipartData;
260
+ header: (name: string) => string | undefined;
261
+ headers: (names?: string[]) => Record<string, string | undefined>;
448
262
  }
449
263
  /**
450
- * Interface for NotFound error details
451
- * Provides context about the missing resource
264
+ * Context object representing a request/response cycle
265
+ * @template S - Type of the state object
266
+ * @template Svc - Type of the services object
267
+ * @template TBody - Type of the request body
268
+ * @template TQuery - Type of the query parameters
452
269
  */
453
- interface NotFoundErrorDetails {
454
- /** Type of resource that was not found */
455
- resourceType?: string;
456
- /** ID or identifier of the resource */
457
- resourceId?: string;
458
- /** Collection or table where the resource was searched */
459
- collection?: string;
460
- /** Search criteria that was used */
461
- query?: Record<string, unknown>;
462
- /** Search criteria that was used (for backward compatibility) */
463
- searchCriteria?: Record<string, unknown>;
464
- /** The path that was attempted */
465
- path?: string;
466
- /** HTTP method used (for API endpoints) */
467
- method?: string;
468
- /** The path that was attempted (for backward compatibility) */
469
- attemptedPath?: string;
470
- /** Parent resource information for nested resources */
471
- parentResource?: {
472
- type: string;
473
- id: string;
270
+ interface Context<S extends State = State, Svc extends Services = Services, TBody = unknown, TQuery = QueryParams> {
271
+ /**
272
+ * Request information
273
+ */
274
+ request: Omit<ContextRequest, 'body' | 'query'> & {
275
+ body: TBody;
276
+ query: TQuery;
474
277
  };
475
- /** Helpful suggestion for the user */
476
- suggestion?: string;
477
- /** Additional context */
478
- [key: string]: unknown;
278
+ /**
279
+ * Response handling
280
+ */
281
+ response: ContextResponse<S>;
282
+ /**
283
+ * Request-scoped state for storing data during the request lifecycle
284
+ */
285
+ state: S;
286
+ /**
287
+ * Services container for accessing injected services/dependencies
288
+ * Populated by middleware that contribute services
289
+ */
290
+ services: Svc;
479
291
  }
292
+ interface BodyLimits {
293
+ /** Maximum JSON body size in bytes (default: 512KB) */
294
+ json: number;
295
+ /** Maximum form data size in bytes (default: 1MB) */
296
+ form: number;
297
+ /** Maximum text body size in bytes (default: 5MB) */
298
+ text: number;
299
+ /** Maximum raw/binary body size in bytes (default: 10MB) */
300
+ raw: number;
301
+ /** Multipart/form-data limits */
302
+ multipart: MultipartLimits;
303
+ }
304
+ type MultipartLimits = {
305
+ maxFileSize?: number;
306
+ maxTotalSize?: number;
307
+ maxFiles?: number;
308
+ maxFieldSize?: number;
309
+ };
480
310
  /**
481
- * Interface for body parsing errors stored in context state
311
+ * Options for creating a context
482
312
  */
483
- interface BodyParseError {
313
+ interface ContextOptions {
484
314
  /**
485
- * Type of parsing error that occurred
315
+ * Whether to parse the request body
486
316
  */
487
- readonly type: 'json_parse_error' | 'form_parse_error' | 'multipart_parse_error' | 'body_read_error';
317
+ parseBody?: boolean;
488
318
  /**
489
- * Human-readable error message
319
+ * Initial state to include in the context
320
+ *
490
321
  */
491
- readonly message: string;
322
+ initialState?: State;
323
+ /**
324
+ * Initial services to include in the context
325
+ *
326
+ */
327
+ initialServices?: Services;
492
328
  /**
493
- * Original error object or details
329
+ * Limits for various body types to prevent abuse
494
330
  */
495
- readonly error: unknown;
331
+ bodyLimits: BodyLimits;
496
332
  }
497
333
  /**
498
- * Type guard to check if an object is a BodyParseError
334
+ * Function to get the current context from AsyncLocalStorage
499
335
  */
500
- declare function isBodyParseError(error: unknown): error is BodyParseError;
336
+ type GetContextFn = <S extends State = State, Svc extends Services = Services>() => Context<S, Svc> | undefined;
501
337
  /**
502
- * Context information for error transformation
338
+ * Factory function for creating a new context
503
339
  */
504
- interface ErrorTransformContext {
505
- url: string;
506
- method: string;
507
- correlationId: string;
508
- timeoutMs?: number;
509
- elapsedMs?: number;
510
- statusCode?: number;
511
- contentType?: string;
512
- responseSample?: string;
513
- [key: string]: unknown;
514
- }
340
+ type CreateContextFn = (req: UnifiedRequest, res: UnifiedResponse, options?: ContextOptions) => Promise<Context>;
515
341
  /**
516
- * SSE-specific error detail interfaces for BlaizeJS framework
342
+ * Type representing unknown function
517
343
  *
518
- * These interfaces define the structure of details for SSE errors.
519
- * The actual error classes are implemented in blaize-core.
344
+ * This is a generic function type that can accept any number of arguments
345
+ * and return any type of value. It is used for type inference in various
346
+ * contexts where the specific function signature is not known or not
347
+ * important.
520
348
  */
349
+ type UnknownFunction = (...args: unknown[]) => unknown;
350
+
521
351
  /**
522
- * Details for SSE connection errors
352
+ * Function to pass control to the next middleware
523
353
  */
524
- interface SSEConnectionErrorDetails {
525
- /** Client identifier if available */
526
- clientId?: string;
527
- /** Connection attempt number */
528
- attemptNumber?: number;
529
- /** Maximum retry attempts configured */
530
- maxRetries?: number;
531
- /** The underlying error that caused connection failure */
532
- cause?: string;
533
- /** Suggested resolution */
534
- suggestion?: string;
535
- }
354
+ type NextFunction = () => Promise<void> | void;
536
355
  /**
537
- * Details for SSE buffer overflow errors
356
+ * Middleware function signature
538
357
  */
539
- interface SSEBufferOverflowErrorDetails {
540
- /** Client identifier */
541
- clientId?: string;
542
- /** Current buffer size when overflow occurred */
543
- currentSize: number;
544
- /** Maximum buffer size configured */
545
- maxSize: number;
546
- /** Number of events dropped */
547
- eventsDropped?: number;
548
- /** Buffer strategy that was applied */
549
- strategy: 'drop-oldest' | 'drop-newest' | 'close';
550
- /** Event that triggered the overflow */
551
- triggeringEvent?: string;
358
+ type MiddlewareFunction = (ctx: Context, next: NextFunction) => Promise<void> | void;
359
+ /**
360
+ * Named middleware options
361
+ */
362
+ interface MiddlewareOptions {
363
+ /** Name of the middleware for debugging and logging */
364
+ name?: string;
365
+ /** The middleware handler function */
366
+ handler: MiddlewareFunction;
367
+ /** Skip function to conditionally bypass middleware */
368
+ skip?: ((ctx: Context<any, any>) => boolean) | undefined;
369
+ /** Enable debugging for this middleware */
370
+ debug?: boolean;
552
371
  }
553
372
  /**
554
- * Details for SSE stream closed errors
373
+ * Middleware type with generic parameters for type-safe state and service contributions
374
+ * @template TState - Type of state this middleware contributes to the context
375
+ * @template TServices - Type of services this middleware contributes to the context
555
376
  */
556
- interface SSEStreamClosedErrorDetails {
557
- /** Client identifier */
558
- clientId?: string;
559
- /** When the stream was closed */
560
- closedAt?: string;
561
- /** Reason for closure */
562
- closeReason?: 'client-disconnect' | 'server-close' | 'timeout' | 'error' | 'buffer-overflow';
563
- /** Whether reconnection is possible */
564
- canReconnect?: boolean;
565
- /** Suggested retry interval in milliseconds */
566
- retryAfter?: number;
377
+ interface Middleware<TState = {}, TServices = {}> {
378
+ name: string;
379
+ execute: MiddlewareFunction;
380
+ skip?: ((ctx: Context) => boolean) | undefined;
381
+ debug?: boolean | undefined;
382
+ _services?: TServices;
567
383
  }
384
+
568
385
  /**
569
- * Context for SSE connection errors
386
+ * Helper type to extract TypeScript type from Zod schema
570
387
  */
571
- interface SSEConnectionErrorContext {
572
- /** The SSE endpoint URL */
573
- url: string;
574
- /** Correlation ID for tracing */
575
- correlationId: string;
576
- /** Connection state when error occurred */
577
- state: 'connecting' | 'connected' | 'disconnected' | 'closed';
578
- /** Number of reconnection attempts made */
579
- reconnectAttempts?: number;
580
- /** The original error if available */
581
- originalError?: Error;
582
- /** Additional SSE-specific details */
583
- sseDetails?: {
584
- /** Whether credentials were included */
585
- withCredentials?: boolean;
586
- /** Last received event ID */
587
- lastEventId?: string;
588
- /** EventSource ready state */
589
- readyState?: number;
590
- };
591
- }
388
+ type Infer<T> = T extends z.ZodType ? z.output<T> : unknown;
592
389
  /**
593
- * Context for SSE stream errors (server-sent errors)
390
+ * HTTP methods supported by the router
594
391
  */
595
- interface SSEStreamErrorContext {
596
- /** The SSE endpoint URL */
597
- url: string;
598
- /** Correlation ID from server or client */
599
- correlationId: string;
600
- /** Error message from server */
601
- message: string;
602
- /** Error code if provided */
603
- code?: string;
604
- /** Error name/type from server */
605
- name?: string;
606
- /** Raw error data from server */
607
- rawData?: any;
608
- }
392
+ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
609
393
  /**
610
- * Context for SSE heartbeat timeout errors
394
+ * Schema for route validation with generic type parameters
611
395
  */
612
- interface SSEHeartbeatErrorContext {
613
- /** The SSE endpoint URL */
614
- url: string;
615
- /** Correlation ID for tracing */
616
- correlationId: string;
617
- /** Configured heartbeat timeout in ms */
618
- heartbeatTimeout: number;
619
- /** Time since last event in ms */
620
- timeSinceLastEvent?: number;
621
- /** Last event ID received */
622
- lastEventId?: string;
396
+ interface RouteSchema<P extends z.ZodType = z.ZodType<any>, // URL parameters schema
397
+ Q extends z.ZodType = z.ZodType<any>, // Query parameters schema
398
+ B extends z.ZodType = z.ZodType<any>, // Body schema
399
+ R extends z.ZodType = z.ZodType<any>, // Response schema
400
+ ED extends z.ZodType = z.ZodType<any>> {
401
+ /** Parameter schema for validation */
402
+ params?: P;
403
+ /** Query schema for validation */
404
+ query?: Q;
405
+ /** Body schema for validation */
406
+ body?: B;
407
+ /** Response schema for validation */
408
+ response?: R;
409
+ /** Error Response Details schema for validation */
410
+ errorResponseDetails?: ED;
623
411
  }
624
-
625
412
  /**
626
- * Represents an uploaded file in a multipart/form-data request
413
+ * Route handler function with strongly typed params and response
627
414
  */
628
- interface UploadedFile {
629
- /** Original filename provided by the client (may be undefined) */
630
- readonly filename: string | undefined;
631
- /** Form field name this file was uploaded under */
632
- readonly fieldname: string;
633
- /** MIME type of the uploaded file */
634
- readonly mimetype: string;
635
- /** Size of the file in bytes */
636
- readonly size: number;
637
- /** Stream containing the file data (always available) */
638
- readonly stream: Readable;
639
- /** Buffer containing file data (only available with 'memory' strategy) */
640
- readonly buffer?: Buffer;
641
- /** Path to temporary file (only available with 'temp' strategy) */
642
- readonly tempPath?: string;
643
- /** SHA-256 hash of file content (if computed) */
644
- readonly hash?: string;
645
- }
415
+ type RouteHandler<TParams = Record<string, string>, TQuery = Record<string, string | string[] | undefined>, TBody = unknown, TResponse = unknown, TState extends State = State, // NEW in v0.4.0
416
+ TServices extends Services = Services> = (ctx: Context<TState, TServices, TBody, TQuery>, params: TParams) => Promise<TResponse> | TResponse;
646
417
  /**
647
- * Complete multipart/form-data parsed content
418
+ * Options for a route method with schema-based type inference
648
419
  */
649
- interface MultipartData {
650
- /** Form fields (non-file inputs) */
651
- readonly fields: Record<string, string | string[]>;
652
- /** Uploaded files */
653
- readonly files: Record<string, UploadedFile | UploadedFile[]>;
420
+ interface RouteMethodOptions<P extends z.ZodType = z.ZodType<any>, Q extends z.ZodType = z.ZodType<any>, B extends z.ZodType = z.ZodType<any>, R extends z.ZodType = z.ZodType<any>, ED extends z.ZodType = z.ZodType<any>> {
421
+ /** Schema for request/response validation */
422
+ schema?: RouteSchema<P, Q, B, R, ED>;
423
+ /** Handler function for the route */
424
+ handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, B extends z.ZodType ? Infer<B> : unknown, R extends z.ZodType ? Infer<R> : unknown>;
425
+ /** Middleware to apply to this route */
426
+ middleware?: Middleware[];
427
+ /** Route-specific options */
428
+ options?: Record<string, unknown>;
654
429
  }
655
430
  /**
656
- * Options for parsing multipart/form-data
431
+ * Route definition mapping HTTP methods to handlers
657
432
  */
658
- interface ParseOptions {
659
- /** Maximum size for individual files in bytes (default: 10MB) */
660
- readonly maxFileSize?: number;
661
- /** Maximum number of files per request (default: 10) */
662
- readonly maxFiles?: number;
663
- /** Maximum size for form fields in bytes (default: 1MB) */
664
- readonly maxFieldSize?: number;
665
- /** Allowed MIME types (empty array = allow all) */
666
- readonly allowedMimeTypes?: readonly string[];
667
- /** Allowed file extensions (empty array = allow all) */
668
- readonly allowedExtensions?: readonly string[];
669
- /** Processing strategy for file data */
670
- readonly strategy: 'memory' | 'stream' | 'temp';
671
- /** Directory for temporary files (strategy: 'temp' only) */
672
- readonly tempDir?: string;
673
- /** Whether to compute SHA-256 hash of files */
674
- readonly computeHash?: boolean;
433
+ interface RouteDefinition {
434
+ GET?: RouteMethodOptions<any, any, never, any, any>;
435
+ POST?: RouteMethodOptions<any, any, any, any, any>;
436
+ PUT?: RouteMethodOptions<any, any, any, any, any>;
437
+ DELETE?: RouteMethodOptions<any, any, never, any, any>;
438
+ PATCH?: RouteMethodOptions<any, any, any, any, any>;
439
+ HEAD?: RouteMethodOptions<any, any, never, any, any>;
440
+ OPTIONS?: RouteMethodOptions<any, any, never, any, any>;
675
441
  }
676
442
  /**
677
- * Result of parsing multipart data with metadata
443
+ * Route object with path
678
444
  */
679
- interface ParseResult {
680
- /** Parsed multipart data */
681
- readonly data: MultipartData;
682
- /** Parsing metadata */
683
- readonly metadata: {
684
- /** Total time spent parsing (milliseconds) */
685
- readonly parseTime: number;
686
- /** Total size of all uploaded content */
687
- readonly totalSize: number;
688
- /** Number of files processed */
689
- readonly fileCount: number;
690
- /** Number of fields processed */
691
- readonly fieldCount: number;
692
- };
445
+ interface Route extends RouteDefinition {
446
+ /** Path of the route */
447
+ path: string;
693
448
  }
694
449
  /**
695
- * Error information for multipart parsing failures
450
+ * Options for route creation
696
451
  */
697
- interface MultipartError {
698
- /** Error type/code */
699
- readonly type: 'boundary_missing' | 'size_exceeded' | 'file_limit_exceeded' | 'mime_type_forbidden' | 'extension_forbidden' | 'parse_error' | 'stream_error' | 'temp_file_error';
700
- /** Human-readable error message */
701
- readonly message: string;
702
- /** Additional context (field name, file name, etc.) */
703
- readonly context?: Record<string, unknown>;
704
- /** Original error if available */
705
- readonly cause?: Error;
452
+ interface RouteOptions {
453
+ /** Base path for the route */
454
+ basePath?: string;
706
455
  }
707
456
  /**
708
- * Configuration for file upload validation
457
+ * Result type for handling success and error responses
709
458
  */
710
- interface ValidationConfig {
711
- /** File size constraints */
712
- readonly size?: {
713
- readonly min?: number;
714
- readonly max?: number;
715
- };
716
- /** File count constraints */
717
- readonly count?: {
718
- readonly min?: number;
719
- readonly max?: number;
720
- };
721
- /** MIME type constraints */
722
- readonly mimeTypes?: {
723
- readonly allowed?: readonly string[];
724
- readonly forbidden?: readonly string[];
725
- };
726
- /** File extension constraints */
727
- readonly extensions?: {
728
- readonly allowed?: readonly string[];
729
- readonly forbidden?: readonly string[];
730
- };
731
- /** Custom validation function */
732
- readonly custom?: (file: UploadedFile) => Promise<boolean> | boolean;
733
- }
459
+ type Result<T, E = {
460
+ error: string;
461
+ message: string;
462
+ details?: unknown;
463
+ }> = {
464
+ success: true;
465
+ data: T;
466
+ status?: number;
467
+ } | {
468
+ success: false;
469
+ error: E;
470
+ status?: number;
471
+ };
734
472
  /**
735
- * File processing configuration
473
+ * Router options
736
474
  */
737
- interface ProcessingConfig {
738
- /** Whether to process files concurrently */
739
- readonly concurrent?: boolean;
740
- /** Maximum concurrent processing operations */
741
- readonly maxConcurrency?: number;
742
- /** Processing timeout in milliseconds */
743
- readonly timeout?: number;
744
- /** Whether to preserve original files during processing */
745
- readonly preserveOriginal?: boolean;
475
+ interface RouterOptions {
476
+ /** Directory containing route files */
477
+ routesDir: string;
478
+ /** Base path for all routes */
479
+ basePath?: string;
480
+ /** Watch for file changes in development */
481
+ watchMode?: boolean;
746
482
  }
747
483
  /**
748
- * Upload progress information (for future streaming uploads)
484
+ * Router interface
749
485
  */
750
- interface UploadProgress {
751
- /** Bytes uploaded so far */
752
- readonly bytesUploaded: number;
753
- /** Total bytes to upload */
754
- readonly totalBytes: number;
755
- /** Upload percentage (0-100) */
756
- readonly percentage: number;
757
- /** Upload speed in bytes per second */
758
- readonly speed: number;
759
- /** Estimated time remaining in milliseconds */
760
- readonly eta: number;
486
+ interface Router {
487
+ /** Handle an incoming request */
488
+ handleRequest: (ctx: Context) => Promise<void>;
489
+ /** Get all registered routes */
490
+ getRoutes: () => Route[];
491
+ /** Add a route programmatically */
492
+ addRoute: (route: Route) => void;
493
+ /** Add multiple routes programmatically with batch processing */
494
+ addRoutes: (routes: Route[]) => {
495
+ added: Route[];
496
+ removed: string[];
497
+ changed: Route[];
498
+ };
499
+ /** Add a route directory for plugins */
500
+ addRouteDirectory(directory: string, options?: {
501
+ prefix?: string;
502
+ }): Promise<void>;
503
+ /** Get route conflicts */
504
+ getRouteConflicts(): Array<{
505
+ path: string;
506
+ sources: string[];
507
+ }>;
508
+ /** Close watchers and cleanup resources */
509
+ close?: () => Promise<void>;
761
510
  }
762
511
  /**
763
- * Internal state for multipart parser state machine
512
+ * Route match result
764
513
  */
765
- interface ParserState {
766
- boundary: Buffer;
767
- options: Required<ParseOptions>;
768
- fields: Map<string, string[]>;
769
- files: Map<string, UploadedFile[]>;
770
- buffer: Buffer;
771
- stage: 'boundary' | 'headers' | 'content';
772
- currentHeaders: string;
773
- currentField: string | null;
774
- currentFilename: string | undefined;
775
- currentMimetype: string;
776
- currentContentLength: number;
777
- fileCount: number;
778
- fieldCount: number;
779
- currentBufferChunks: Buffer[];
780
- currentStream: Readable | null;
781
- currentTempPath: string | null;
782
- currentWriteStream: WriteStream | null;
783
- streamController: ReadableStreamDefaultController<Uint8Array> | null;
784
- cleanupTasks: Array<() => Promise<void>>;
785
- /**
786
- * Whether we've found at least one valid boundary marker
787
- */
788
- hasFoundValidBoundary: boolean;
789
- /**
790
- * Whether we've successfully processed at least one complete part (field or file)
791
- */
792
- hasProcessedAnyPart: boolean;
793
- /**
794
- * Whether parsing has reached the end boundary
795
- */
796
- isFinished: boolean;
514
+ interface RouteMatch {
515
+ /** The matched route handler (null if method not allowed) */
516
+ route: RouteMethodOptions | null;
517
+ /** Extracted route parameters */
518
+ params: Record<string, string>;
519
+ /** Flag indicating if the path exists but method isn't allowed */
520
+ methodNotAllowed?: boolean;
521
+ /** List of allowed methods for this path (when method not allowed) */
522
+ allowedMethods?: HttpMethod[];
797
523
  }
798
-
799
- /**
800
- * Unified request type supporting both HTTP/1.1 and HTTP/2
801
- */
802
- type UnifiedRequest = IncomingMessage | Http2ServerRequest;
803
- /**
804
- * Unified response type supporting both HTTP/1.1 and HTTP/2
805
- */
806
- type UnifiedResponse = ServerResponse | Http2ServerResponse;
807
524
  /**
808
- * Request parameters extracted from URL path
525
+ * Route matcher interface
809
526
  */
810
- interface RequestParams {
811
- [key: string]: string;
527
+ interface Matcher {
528
+ /** Add a route to the matcher */
529
+ add: (path: string, method: HttpMethod, route: RouteMethodOptions) => void;
530
+ /** Match a URL path to a route */
531
+ match: (path: string, method: HttpMethod) => RouteMatch | null;
532
+ /** Get all registered routes */
533
+ getRoutes: () => {
534
+ path: string;
535
+ method: HttpMethod;
536
+ }[];
537
+ /** Find routes matching a specific path */
538
+ findRoutes: (path: string) => {
539
+ path: string;
540
+ method: HttpMethod;
541
+ params: Record<string, string>;
542
+ }[];
543
+ /** Remove a route from the matcher (optional for compatibility) */
544
+ remove: (path: string) => void;
545
+ /** Clear all routes from the matcher (optional for compatibility) */
546
+ clear: () => void;
812
547
  }
813
- /**
814
- * Query parameters from URL
815
- */
816
- interface QueryParams {
817
- [key: string]: string | string[] | undefined;
548
+ interface ParsedRoute {
549
+ filePath: string;
550
+ routePath: string;
551
+ params: string[];
818
552
  }
819
553
  /**
820
- * Options for streaming responses
554
+ * Node in the radix tree for efficient route matching
821
555
  */
822
- interface StreamOptions {
823
- contentType?: string;
824
- status?: number;
825
- headers?: Record<string, string>;
556
+ interface RouteNode {
557
+ segment: string;
558
+ paramName: string | null;
559
+ isWildcard: boolean;
560
+ children: RouteNode[];
561
+ handlers: Partial<Record<HttpMethod, RouteMethodOptions>>;
562
+ pattern: RegExp | null;
826
563
  }
827
- /**
828
- * State container for storing request-scoped data
829
- * Allows for proper typing with generics
830
- */
831
- interface State {
832
- [key: string]: unknown;
833
- /**
834
- * Body parsing error information
835
- * Set when body parsing fails during request processing
836
- */
837
- _bodyError?: BodyParseError;
564
+ interface RouteEntry {
565
+ /** The route path pattern */
566
+ path: string;
567
+ /** The HTTP method */
568
+ method: HttpMethod;
569
+ /** The compiled regex pattern */
570
+ pattern: RegExp;
571
+ /** The parameter names in order */
572
+ paramNames: string[];
573
+ /** The route handler options */
574
+ routeOptions: RouteMethodOptions;
575
+ }
576
+ interface ErrorHandlerOptions {
577
+ /** Show detailed errors in response */
578
+ detailed?: boolean;
579
+ /** Log errors to console */
580
+ log?: boolean;
581
+ }
582
+ interface ProcessResponseOptions {
583
+ /** Status code to use if not specified */
584
+ defaultStatus?: number;
838
585
  }
839
586
  /**
840
- * Services container for storing injectable services/dependencies
841
- * Allows middleware to contribute services that are accessible throughout the request lifecycle
587
+ * Standard error response structure
842
588
  */
843
- interface Services {
844
- [key: string]: unknown;
589
+ interface StandardErrorResponse {
590
+ error: string;
591
+ message: string;
845
592
  }
846
- interface ContextResponse<S extends State = State> {
847
- raw: UnifiedResponse;
848
- sent: boolean;
849
- statusCode: number;
850
- status: (code: number) => ContextResponse<S>;
851
- header: (name: string, value: string) => ContextResponse<S>;
852
- headers: (headers: Record<string, string>) => ContextResponse<S>;
853
- type: (contentType: string) => ContextResponse<S>;
854
- json: (body: unknown, status?: number) => void;
855
- text: (body: string, status?: number) => void;
856
- html: (body: string, status?: number) => void;
857
- redirect: (url: string, status?: number) => void;
858
- stream: (readable: NodeJS.ReadableStream, options?: StreamOptions) => void;
593
+ interface FileCache {
594
+ routes: Route[];
595
+ timestamp: number;
596
+ hash: string;
859
597
  }
860
- interface ContextRequest<TBody = unknown> {
861
- raw: UnifiedRequest;
862
- method: string;
863
- path: string;
864
- url: URL | null;
865
- query: QueryParams;
866
- params: RequestParams;
867
- protocol: string;
868
- isHttp2: boolean;
869
- body?: TBody;
870
- /**
871
- * Uploaded files from multipart/form-data requests
872
- * Available when Content-Type is multipart/form-data
873
- */
874
- files?: Record<string, UploadedFile | UploadedFile[]>;
875
- /**
876
- * Complete multipart data (files + fields)
877
- * Available when Content-Type is multipart/form-data
878
- */
879
- multipart?: MultipartData;
880
- header: (name: string) => string | undefined;
881
- headers: (names?: string[]) => Record<string, string | undefined>;
598
+ interface ReloadMetrics {
599
+ fileChanges: number;
600
+ totalReloadTime: number;
601
+ averageReloadTime: number;
602
+ slowReloads: Array<{
603
+ file: string;
604
+ time: number;
605
+ }>;
606
+ }
607
+ interface WatchOptions {
608
+ debounceMs?: number;
609
+ /** Directories to ignore */
610
+ ignore?: string[];
611
+ /** Callback for new routes */
612
+ onRouteAdded?: (filePath: string, routes: Route[]) => void;
613
+ /** Callback for changed routes */
614
+ onRouteChanged?: (filePath: string, routes: Route[]) => void;
615
+ /** Callback for removed routes */
616
+ onRouteRemoved?: (filePath: string, routes: Route[]) => void;
617
+ /** Callback for errors */
618
+ onError?: (error: Error) => void;
619
+ }
620
+ interface RouteRegistry {
621
+ routesByPath: Map<string, Route>;
622
+ routesByFile: Map<string, Set<string>>;
623
+ pathToFile: Map<string, string>;
624
+ }
625
+ interface FindRouteFilesOptions {
626
+ /** Directories to ignore */
627
+ ignore?: string[] | undefined;
882
628
  }
883
629
  /**
884
- * Context object representing a request/response cycle
885
- * @template S - Type of the state object
886
- * @template Svc - Type of the services object
887
- * @template TBody - Type of the request body
888
- * @template TQuery - Type of the query parameters
630
+ * GET route creator with state and services support
631
+ * Now returns a higher-order function to handle generics properly
889
632
  */
890
- interface Context<S extends State = State, Svc extends Services = Services, TBody = unknown, TQuery = QueryParams> {
891
- /**
892
- * Request information
893
- */
894
- request: Omit<ContextRequest, 'body' | 'query'> & {
895
- body: TBody;
896
- query: TQuery;
633
+ type CreateGetRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, R = never>(config: {
634
+ schema?: {
635
+ params?: P extends never ? never : P;
636
+ query?: Q extends never ? never : Q;
637
+ response?: R extends never ? never : R;
897
638
  };
898
- /**
899
- * Response handling
900
- */
901
- response: ContextResponse<S>;
902
- /**
903
- * Request-scoped state for storing data during the request lifecycle
904
- */
905
- state: S;
906
- /**
907
- * Services container for accessing injected services/dependencies
908
- * Populated by middleware that contribute services
909
- */
910
- services: Svc;
911
- }
912
- type MultipartLimits = {
913
- maxFileSize?: number;
914
- maxTotalSize?: number;
915
- maxFiles?: number;
916
- maxFieldSize?: number;
639
+ handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, never, // GET never has body
640
+ [
641
+ R
642
+ ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
643
+ middleware?: Middleware[];
644
+ options?: Record<string, unknown>;
645
+ }) => {
646
+ GET: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, never, R extends never ? never : R extends z.ZodType ? R : never>;
647
+ path: string;
917
648
  };
918
649
  /**
919
- * Options for creating a context
650
+ * POST route creator with state and services support
920
651
  */
921
- interface ContextOptions {
922
- /**
923
- * Whether to parse the request body
924
- */
925
- parseBody?: boolean;
926
- /**
927
- * Initial state to include in the context
928
- *
929
- */
930
- initialState?: State;
931
- /**
932
- * Initial services to include in the context
933
- *
934
- */
935
- initialServices?: Services;
936
- /**
937
- * Limits for various body types to prevent abuse
938
- */
939
- bodyLimits?: {
940
- json?: number;
941
- form?: number;
942
- text?: number;
943
- multipart?: MultipartLimits;
944
- raw?: number;
652
+ type CreatePostRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, B = never, R = never>(config: {
653
+ schema?: {
654
+ params?: P extends never ? never : P;
655
+ query?: Q extends never ? never : Q;
656
+ body?: B extends never ? never : B;
657
+ response?: R extends never ? never : R;
945
658
  };
946
- }
947
- /**
948
- * Function to get the current context from AsyncLocalStorage
949
- */
950
- type GetContextFn = <S extends State = State, Svc extends Services = Services>() => Context<S, Svc> | undefined;
951
- /**
952
- * Factory function for creating a new context
953
- */
954
- type CreateContextFn = (req: UnifiedRequest, res: UnifiedResponse, options?: ContextOptions) => Promise<Context>;
659
+ handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, B extends z.ZodType ? Infer<B> : unknown, [
660
+ R
661
+ ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
662
+ middleware?: Middleware[];
663
+ options?: Record<string, unknown>;
664
+ }) => {
665
+ POST: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, B extends never ? never : B extends z.ZodType ? B : never, R extends never ? never : R extends z.ZodType ? R : never>;
666
+ path: string;
667
+ };
955
668
  /**
956
- * Type representing unknown function
957
- *
958
- * This is a generic function type that can accept any number of arguments
959
- * and return any type of value. It is used for type inference in various
960
- * contexts where the specific function signature is not known or not
961
- * important.
669
+ * PUT route creator with state and services support
962
670
  */
963
- type UnknownFunction = (...args: unknown[]) => unknown;
964
-
671
+ type CreatePutRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, B = never, R = never>(config: {
672
+ schema?: {
673
+ params?: P extends never ? never : P;
674
+ query?: Q extends never ? never : Q;
675
+ body?: B extends never ? never : B;
676
+ response?: R extends never ? never : R;
677
+ };
678
+ handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, B extends z.ZodType ? Infer<B> : unknown, [
679
+ R
680
+ ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
681
+ middleware?: Middleware[];
682
+ options?: Record<string, unknown>;
683
+ }) => {
684
+ PUT: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, B extends never ? never : B extends z.ZodType ? B : never, R extends never ? never : R extends z.ZodType ? R : never>;
685
+ path: string;
686
+ };
965
687
  /**
966
- * Function to pass control to the next middleware
688
+ * DELETE route creator with state and services support
967
689
  */
968
- type NextFunction = () => Promise<void> | void;
690
+ type CreateDeleteRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, R = never>(config: {
691
+ schema?: {
692
+ params?: P extends never ? never : P;
693
+ query?: Q extends never ? never : Q;
694
+ response?: R extends never ? never : R;
695
+ };
696
+ handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, never, // DELETE never has body
697
+ [
698
+ R
699
+ ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
700
+ middleware?: Middleware[];
701
+ options?: Record<string, unknown>;
702
+ }) => {
703
+ DELETE: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, never, R extends never ? never : R extends z.ZodType ? R : never>;
704
+ path: string;
705
+ };
969
706
  /**
970
- * Middleware function signature
707
+ * PATCH route creator with state and services support
971
708
  */
972
- type MiddlewareFunction = (ctx: Context, next: NextFunction) => Promise<void> | void;
709
+ type CreatePatchRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, B = never, R = never>(config: {
710
+ schema?: {
711
+ params?: P extends never ? never : P;
712
+ query?: Q extends never ? never : Q;
713
+ body?: B extends never ? never : B;
714
+ response?: R extends never ? never : R;
715
+ };
716
+ handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, B extends z.ZodType ? Infer<B> : unknown, [
717
+ R
718
+ ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
719
+ middleware?: Middleware[];
720
+ options?: Record<string, unknown>;
721
+ }) => {
722
+ PATCH: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, B extends never ? never : B extends z.ZodType ? B : never, R extends never ? never : R extends z.ZodType ? R : never>;
723
+ path: string;
724
+ };
973
725
  /**
974
- * Named middleware options
726
+ * HEAD route creator with state and services support
975
727
  */
976
- interface MiddlewareOptions {
977
- /** Name of the middleware for debugging and logging */
978
- name?: string;
979
- /** The middleware handler function */
980
- handler: MiddlewareFunction;
981
- /** Skip function to conditionally bypass middleware */
982
- skip?: ((ctx: Context<any, any>) => boolean) | undefined;
983
- /** Enable debugging for this middleware */
984
- debug?: boolean;
985
- }
728
+ type CreateHeadRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, R = never>(config: {
729
+ schema?: {
730
+ params?: P extends never ? never : P;
731
+ query?: Q extends never ? never : Q;
732
+ response?: R extends never ? never : R;
733
+ };
734
+ handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, never, // HEAD never has body
735
+ [
736
+ R
737
+ ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
738
+ middleware?: Middleware[];
739
+ options?: Record<string, unknown>;
740
+ }) => {
741
+ HEAD: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, never, R extends never ? never : R extends z.ZodType ? R : never>;
742
+ path: string;
743
+ };
986
744
  /**
987
- * Middleware type with generic parameters for type-safe state and service contributions
988
- * @template TState - Type of state this middleware contributes to the context
989
- * @template TServices - Type of services this middleware contributes to the context
745
+ * OPTIONS route creator with state and services support
990
746
  */
991
- interface Middleware<TState = {}, TServices = {}> {
992
- name: string;
993
- execute: MiddlewareFunction;
994
- skip?: ((ctx: Context) => boolean) | undefined;
995
- debug?: boolean | undefined;
996
- _services?: TServices;
997
- }
747
+ type CreateOptionsRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, R = never>(config: {
748
+ schema?: {
749
+ params?: P extends never ? never : P;
750
+ query?: Q extends never ? never : Q;
751
+ response?: R extends never ? never : R;
752
+ };
753
+ handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, never, // OPTIONS never has body
754
+ [
755
+ R
756
+ ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
757
+ middleware?: Middleware[];
758
+ options?: Record<string, unknown>;
759
+ }) => {
760
+ OPTIONS: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, never, R extends never ? never : R extends z.ZodType ? R : never>;
761
+ path: string;
762
+ };
998
763
 
999
764
  /**
1000
- * Helper type to extract TypeScript type from Zod schema
1001
- */
1002
- type Infer<T> = T extends z.ZodType ? z.output<T> : unknown;
1003
- /**
1004
- * HTTP methods supported by the router
1005
- */
1006
- type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
1007
- /**
1008
- * Schema for route validation with generic type parameters
1009
- */
1010
- interface RouteSchema<P extends z.ZodType = z.ZodType<any>, // URL parameters schema
1011
- Q extends z.ZodType = z.ZodType<any>, // Query parameters schema
1012
- B extends z.ZodType = z.ZodType<any>, // Body schema
1013
- R extends z.ZodType = z.ZodType<any>, // Response schema
1014
- ED extends z.ZodType = z.ZodType<any>> {
1015
- /** Parameter schema for validation */
1016
- params?: P;
1017
- /** Query schema for validation */
1018
- query?: Q;
1019
- /** Body schema for validation */
1020
- body?: B;
1021
- /** Response schema for validation */
1022
- response?: R;
1023
- /** Error Response Details schema for validation */
1024
- errorResponseDetails?: ED;
1025
- }
1026
- /**
1027
- * Route handler function with strongly typed params and response
765
+ * Compose multiple middleware functions into a single middleware function
1028
766
  */
1029
- type RouteHandler<TParams = Record<string, string>, TQuery = Record<string, string | string[] | undefined>, TBody = unknown, TResponse = unknown, TState extends State = State, // NEW in v0.4.0
1030
- TServices extends Services = Services> = (ctx: Context<TState, TServices, TBody, TQuery>, params: TParams) => Promise<TResponse> | TResponse;
767
+ declare function compose(middlewareStack: Middleware[]): MiddlewareFunction;
768
+
1031
769
  /**
1032
- * Options for a route method with schema-based type inference
770
+ * CORS Types for BlaizeJS Framework
771
+ *
772
+ * Comprehensive type definitions for W3C-compliant CORS middleware
773
+ * with support for string, regex, and async function origin validation.
774
+ *
775
+ * @module @blaizejs/types/cors
1033
776
  */
1034
- interface RouteMethodOptions<P extends z.ZodType = z.ZodType<any>, Q extends z.ZodType = z.ZodType<any>, B extends z.ZodType = z.ZodType<any>, R extends z.ZodType = z.ZodType<any>, ED extends z.ZodType = z.ZodType<any>> {
1035
- /** Schema for request/response validation */
1036
- schema?: RouteSchema<P, Q, B, R, ED>;
1037
- /** Handler function for the route */
1038
- handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, B extends z.ZodType ? Infer<B> : unknown, R extends z.ZodType ? Infer<R> : unknown>;
1039
- /** Middleware to apply to this route */
1040
- middleware?: Middleware[];
1041
- /** Route-specific options */
1042
- options?: Record<string, unknown>;
1043
- }
777
+
1044
778
  /**
1045
- * Route definition mapping HTTP methods to handlers
779
+ * Origin configuration type supporting multiple validation methods
780
+ *
781
+ * @example
782
+ * ```typescript
783
+ * // String origin (exact match)
784
+ * const origin: CorsOrigin = 'https://example.com';
785
+ *
786
+ * // RegExp pattern
787
+ * const origin: CorsOrigin = /^https:\/\/.*\.example\.com$/;
788
+ *
789
+ * // Dynamic validation function
790
+ * const origin: CorsOrigin = async (origin, ctx) => {
791
+ * return await checkOriginAllowed(origin, ctx?.state.user);
792
+ * };
793
+ *
794
+ * // Array of mixed types
795
+ * const origin: CorsOrigin = [
796
+ * 'https://localhost:3000',
797
+ * /^https:\/\/.*\.example\.com$/,
798
+ * (origin) => origin.endsWith('.trusted.com')
799
+ * ];
800
+ * ```
1046
801
  */
1047
- interface RouteDefinition {
1048
- GET?: RouteMethodOptions<any, any, never, any, any>;
1049
- POST?: RouteMethodOptions<any, any, any, any, any>;
1050
- PUT?: RouteMethodOptions<any, any, any, any, any>;
1051
- DELETE?: RouteMethodOptions<any, any, never, any, any>;
1052
- PATCH?: RouteMethodOptions<any, any, any, any, any>;
1053
- HEAD?: RouteMethodOptions<any, any, never, any, any>;
1054
- OPTIONS?: RouteMethodOptions<any, any, never, any, any>;
1055
- }
802
+ type CorsOrigin = string | RegExp | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>) | Array<string | RegExp | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>)>;
1056
803
  /**
1057
- * Route object with path
804
+ * HTTP methods that can be allowed in CORS
805
+ * Based on W3C CORS specification
1058
806
  */
1059
- interface Route extends RouteDefinition {
1060
- /** Path of the route */
1061
- path: string;
1062
- }
807
+ type CorsHttpMethod = HttpMethod | 'CONNECT' | 'TRACE';
1063
808
  /**
1064
- * Options for route creation
809
+ * Main CORS configuration options
810
+ *
811
+ * @example
812
+ * ```typescript
813
+ * const corsOptions: CorsOptions = {
814
+ * origin: 'https://example.com',
815
+ * methods: ['GET', 'POST'],
816
+ * credentials: true,
817
+ * maxAge: 86400
818
+ * };
819
+ * ```
1065
820
  */
1066
- interface RouteOptions {
1067
- /** Base path for the route */
1068
- basePath?: string;
1069
- }
1070
- /**
1071
- * Result type for handling success and error responses
1072
- */
1073
- type Result<T, E = {
1074
- error: string;
1075
- message: string;
1076
- details?: unknown;
1077
- }> = {
1078
- success: true;
1079
- data: T;
1080
- status?: number;
1081
- } | {
1082
- success: false;
1083
- error: E;
1084
- status?: number;
1085
- };
821
+ interface CorsOptions {
822
+ /**
823
+ * Configures the Access-Control-Allow-Origin header
824
+ *
825
+ * Possible values:
826
+ * - `true`: Allow all origins (sets to '*' unless credentials is true, then reflects origin)
827
+ * - `false`: Disable CORS (no headers set)
828
+ * - `string`: Specific origin to allow
829
+ * - `RegExp`: Pattern to match origins
830
+ * - `function`: Custom validation logic
831
+ * - `array`: Multiple origin configurations
832
+ *
833
+ * @default false
834
+ */
835
+ origin?: boolean | CorsOrigin;
836
+ /**
837
+ * Configures the Access-Control-Allow-Methods header
838
+ *
839
+ * @default ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE']
840
+ * @example ['GET', 'POST']
841
+ */
842
+ methods?: CorsHttpMethod[] | string;
843
+ /**
844
+ * Configures the Access-Control-Allow-Headers header
845
+ *
846
+ * Pass an array of allowed headers or a comma-delimited string.
847
+ *
848
+ * @default Request's Access-Control-Request-Headers header value
849
+ * @example ['Content-Type', 'Authorization']
850
+ */
851
+ allowedHeaders?: string[] | string;
852
+ /**
853
+ * Configures the Access-Control-Expose-Headers header
854
+ *
855
+ * Headers that the browser is allowed to access.
856
+ *
857
+ * @default []
858
+ * @example ['Content-Range', 'X-Content-Range']
859
+ */
860
+ exposedHeaders?: string[] | string;
861
+ /**
862
+ * Configures the Access-Control-Allow-Credentials header
863
+ *
864
+ * Set to true to allow credentials (cookies, authorization headers, TLS client certificates).
865
+ * Note: Cannot be used with origin: '*' for security reasons.
866
+ *
867
+ * @default false
868
+ */
869
+ credentials?: boolean;
870
+ /**
871
+ * Configures the Access-Control-Max-Age header in seconds
872
+ *
873
+ * Indicates how long browsers can cache preflight response.
874
+ * Set to -1 to disable caching.
875
+ *
876
+ * @default undefined (browser decides)
877
+ * @example 86400 // 24 hours
878
+ */
879
+ maxAge?: number;
880
+ /**
881
+ * Whether to pass the CORS preflight response to the next handler
882
+ *
883
+ * When false, the preflight response is sent immediately.
884
+ * When true, control passes to the next middleware/handler.
885
+ *
886
+ * @default false
887
+ */
888
+ preflightContinue?: boolean;
889
+ /**
890
+ * HTTP status code for successful OPTIONS requests
891
+ *
892
+ * Some legacy browsers require 200, while 204 is more correct.
893
+ *
894
+ * @default 204
895
+ */
896
+ optionsSuccessStatus?: number;
897
+ }
1086
898
  /**
1087
- * Router options
899
+ * Internal CORS validation result
900
+ * Used by middleware implementation
1088
901
  */
1089
- interface RouterOptions {
1090
- /** Directory containing route files */
1091
- routesDir: string;
1092
- /** Base path for all routes */
1093
- basePath?: string;
1094
- /** Watch for file changes in development */
1095
- watchMode?: boolean;
902
+ interface CorsValidationResult {
903
+ /**
904
+ * Whether the origin is allowed
905
+ */
906
+ allowed: boolean;
907
+ /**
908
+ * The origin value to set in the header
909
+ * Can be '*', specific origin, or 'null'
910
+ */
911
+ origin?: string;
912
+ /**
913
+ * Whether to add Vary: Origin header
914
+ */
915
+ vary?: boolean;
1096
916
  }
1097
917
  /**
1098
- * Router interface
918
+ * CORS preflight request information
919
+ * Extracted from OPTIONS request headers
1099
920
  */
1100
- interface Router {
1101
- /** Handle an incoming request */
1102
- handleRequest: (ctx: Context) => Promise<void>;
1103
- /** Get all registered routes */
1104
- getRoutes: () => Route[];
1105
- /** Add a route programmatically */
1106
- addRoute: (route: Route) => void;
1107
- /** Add multiple routes programmatically with batch processing */
1108
- addRoutes: (routes: Route[]) => {
1109
- added: Route[];
1110
- removed: string[];
1111
- changed: Route[];
1112
- };
1113
- /** Add a route directory for plugins */
1114
- addRouteDirectory(directory: string, options?: {
1115
- prefix?: string;
1116
- }): Promise<void>;
1117
- /** Get route conflicts */
1118
- getRouteConflicts(): Array<{
1119
- path: string;
1120
- sources: string[];
1121
- }>;
1122
- /** Close watchers and cleanup resources */
1123
- close?: () => Promise<void>;
921
+ interface CorsPreflightInfo {
922
+ /**
923
+ * The origin making the request
924
+ */
925
+ origin?: string;
926
+ /**
927
+ * The method that will be used in the actual request
928
+ * From Access-Control-Request-Method header
929
+ */
930
+ requestedMethod?: string;
931
+ /**
932
+ * The headers that will be sent in the actual request
933
+ * From Access-Control-Request-Headers header
934
+ */
935
+ requestedHeaders?: string[];
1124
936
  }
1125
937
  /**
1126
- * Route match result
938
+ * Cache entry for origin validation results
939
+ * Used for performance optimization
1127
940
  */
1128
- interface RouteMatch {
1129
- /** The matched route handler (null if method not allowed) */
1130
- route: RouteMethodOptions | null;
1131
- /** Extracted route parameters */
1132
- params: Record<string, string>;
1133
- /** Flag indicating if the path exists but method isn't allowed */
1134
- methodNotAllowed?: boolean;
1135
- /** List of allowed methods for this path (when method not allowed) */
1136
- allowedMethods?: HttpMethod[];
941
+ interface CorsOriginCacheEntry {
942
+ /**
943
+ * Whether the origin is allowed
944
+ */
945
+ allowed: boolean;
946
+ /**
947
+ * When this cache entry expires (timestamp)
948
+ */
949
+ expiresAt: number;
950
+ /**
951
+ * Optional user identifier for cache key
952
+ */
953
+ userId?: string;
1137
954
  }
1138
955
  /**
1139
- * Route matcher interface
956
+ * Configuration for CORS origin validation cache
1140
957
  */
1141
- interface Matcher {
1142
- /** Add a route to the matcher */
1143
- add: (path: string, method: HttpMethod, route: RouteMethodOptions) => void;
1144
- /** Match a URL path to a route */
1145
- match: (path: string, method: HttpMethod) => RouteMatch | null;
1146
- /** Get all registered routes */
1147
- getRoutes: () => {
1148
- path: string;
1149
- method: HttpMethod;
1150
- }[];
1151
- /** Find routes matching a specific path */
1152
- findRoutes: (path: string) => {
1153
- path: string;
1154
- method: HttpMethod;
1155
- params: Record<string, string>;
1156
- }[];
1157
- /** Remove a route from the matcher (optional for compatibility) */
1158
- remove: (path: string) => void;
1159
- /** Clear all routes from the matcher (optional for compatibility) */
1160
- clear: () => void;
1161
- }
1162
- interface ParsedRoute {
1163
- filePath: string;
1164
- routePath: string;
1165
- params: string[];
958
+ interface CorsOriginCacheConfig {
959
+ /**
960
+ * Time-to-live for cache entries in milliseconds
961
+ * @default 60000 (1 minute)
962
+ */
963
+ ttl?: number;
964
+ /**
965
+ * Maximum number of entries in the cache
966
+ * @default 1000
967
+ */
968
+ maxSize?: number;
969
+ /**
970
+ * Whether to include user ID in cache key
971
+ * @default true
972
+ */
973
+ includeUserId?: boolean;
1166
974
  }
1167
975
  /**
1168
- * Node in the radix tree for efficient route matching
976
+ * Statistics for CORS middleware performance monitoring
1169
977
  */
1170
- interface RouteNode {
1171
- segment: string;
1172
- paramName: string | null;
1173
- isWildcard: boolean;
1174
- children: RouteNode[];
1175
- handlers: Partial<Record<HttpMethod, RouteMethodOptions>>;
1176
- pattern: RegExp | null;
1177
- }
1178
- interface RouteEntry {
1179
- /** The route path pattern */
1180
- path: string;
1181
- /** The HTTP method */
1182
- method: HttpMethod;
1183
- /** The compiled regex pattern */
1184
- pattern: RegExp;
1185
- /** The parameter names in order */
1186
- paramNames: string[];
1187
- /** The route handler options */
1188
- routeOptions: RouteMethodOptions;
1189
- }
1190
- interface ErrorHandlerOptions {
1191
- /** Show detailed errors in response */
1192
- detailed?: boolean;
1193
- /** Log errors to console */
1194
- log?: boolean;
1195
- }
1196
- interface ProcessResponseOptions {
1197
- /** Status code to use if not specified */
1198
- defaultStatus?: number;
978
+ interface CorsStats {
979
+ /**
980
+ * Total number of CORS requests processed
981
+ */
982
+ totalRequests: number;
983
+ /**
984
+ * Number of preflight requests handled
985
+ */
986
+ preflightRequests: number;
987
+ /**
988
+ * Number of allowed origins
989
+ */
990
+ allowedOrigins: number;
991
+ /**
992
+ * Number of denied origins
993
+ */
994
+ deniedOrigins: number;
995
+ /**
996
+ * Cache hit rate for origin validation
997
+ */
998
+ cacheHitRate: number;
999
+ /**
1000
+ * Average origin validation time in milliseconds
1001
+ */
1002
+ avgValidationTime: number;
1199
1003
  }
1200
1004
  /**
1201
- * Standard error response structure
1005
+ * Cache entry type
1202
1006
  */
1203
- interface StandardErrorResponse {
1204
- error: string;
1205
- message: string;
1206
- }
1207
- interface FileCache {
1208
- routes: Route[];
1209
- timestamp: number;
1210
- hash: string;
1211
- }
1212
- interface ReloadMetrics {
1213
- fileChanges: number;
1214
- totalReloadTime: number;
1215
- averageReloadTime: number;
1216
- slowReloads: Array<{
1217
- file: string;
1218
- time: number;
1219
- }>;
1220
- }
1221
- interface WatchOptions {
1222
- debounceMs?: number;
1223
- /** Directories to ignore */
1224
- ignore?: string[];
1225
- /** Callback for new routes */
1226
- onRouteAdded?: (filePath: string, routes: Route[]) => void;
1227
- /** Callback for changed routes */
1228
- onRouteChanged?: (filePath: string, routes: Route[]) => void;
1229
- /** Callback for removed routes */
1230
- onRouteRemoved?: (filePath: string, routes: Route[]) => void;
1231
- /** Callback for errors */
1232
- onError?: (error: Error) => void;
1233
- }
1234
- interface RouteRegistry {
1235
- routesByPath: Map<string, Route>;
1236
- routesByFile: Map<string, Set<string>>;
1237
- pathToFile: Map<string, string>;
1007
+ interface CacheEntry {
1008
+ allowed: boolean;
1009
+ expiresAt: number;
1010
+ lastAccessed: number;
1238
1011
  }
1239
- interface FindRouteFilesOptions {
1240
- /** Directories to ignore */
1241
- ignore?: string[] | undefined;
1012
+ /**
1013
+ * Cache configuration
1014
+ */
1015
+ interface CacheConfig {
1016
+ ttl: number;
1017
+ maxSize: number;
1242
1018
  }
1019
+
1243
1020
  /**
1244
- * GET route creator with state and services support
1245
- * Now returns a higher-order function to handle generics properly
1021
+ * Create CORS middleware with the specified options
1022
+ *
1023
+ * @param userOptions - CORS configuration options or boolean
1024
+ * @returns Middleware function that handles CORS
1025
+ *
1026
+ * @example
1027
+ * ```typescript
1028
+ * import { cors } from '@blaize-core/middleware/cors';
1029
+ *
1030
+ * // Development mode - allow all origins
1031
+ * server.use(cors(true));
1032
+ *
1033
+ * // Production - specific origin
1034
+ * server.use(cors({
1035
+ * origin: 'https://app.example.com',
1036
+ * credentials: true,
1037
+ * maxAge: 86400
1038
+ * }));
1039
+ *
1040
+ * // Multiple origins with regex
1041
+ * server.use(cors({
1042
+ * origin: [
1043
+ * 'https://app.example.com',
1044
+ * /^https:\/\/.*\.example\.com$/
1045
+ * ]
1046
+ * }));
1047
+ *
1048
+ * // Dynamic origin validation
1049
+ * server.use(cors({
1050
+ * origin: async (origin, ctx) => {
1051
+ * return await checkOriginAllowed(origin, ctx.state.user);
1052
+ * }
1053
+ * }));
1054
+ * ```
1246
1055
  */
1247
- type CreateGetRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, R = never>(config: {
1248
- schema?: {
1249
- params?: P extends never ? never : P;
1250
- query?: Q extends never ? never : Q;
1251
- response?: R extends never ? never : R;
1252
- };
1253
- handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, never, // GET never has body
1254
- [
1255
- R
1256
- ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
1257
- middleware?: Middleware[];
1258
- options?: Record<string, unknown>;
1259
- }) => {
1260
- GET: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, never, R extends never ? never : R extends z.ZodType ? R : never>;
1261
- path: string;
1262
- };
1056
+ declare function cors(userOptions?: CorsOptions | boolean): Middleware;
1057
+
1263
1058
  /**
1264
- * POST route creator with state and services support
1059
+ * Create a middleware
1265
1060
  */
1266
- type CreatePostRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, B = never, R = never>(config: {
1267
- schema?: {
1268
- params?: P extends never ? never : P;
1269
- query?: Q extends never ? never : Q;
1270
- body?: B extends never ? never : B;
1271
- response?: R extends never ? never : R;
1272
- };
1273
- handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, B extends z.ZodType ? Infer<B> : unknown, [
1274
- R
1275
- ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
1276
- middleware?: Middleware[];
1277
- options?: Record<string, unknown>;
1278
- }) => {
1279
- POST: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, B extends never ? never : B extends z.ZodType ? B : never, R extends never ? never : R extends z.ZodType ? R : never>;
1280
- path: string;
1281
- };
1061
+ declare function create$2<TState = {}, TServices = {}>(handlerOrOptions: MiddlewareFunction | MiddlewareOptions): Middleware<TState, TServices>;
1282
1062
  /**
1283
- * PUT route creator with state and services support
1063
+ * Create a middleware that only contributes state (no services)
1064
+ * Convenience helper for state-only middleware
1065
+ *
1066
+ * @template T - Type of state to contribute
1067
+ * @param handler - Middleware function that adds state
1068
+ * @returns Middleware that contributes state only
1069
+ *
1284
1070
  */
1285
- type CreatePutRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, B = never, R = never>(config: {
1286
- schema?: {
1287
- params?: P extends never ? never : P;
1288
- query?: Q extends never ? never : Q;
1289
- body?: B extends never ? never : B;
1290
- response?: R extends never ? never : R;
1291
- };
1292
- handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, B extends z.ZodType ? Infer<B> : unknown, [
1293
- R
1294
- ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
1295
- middleware?: Middleware[];
1296
- options?: Record<string, unknown>;
1297
- }) => {
1298
- PUT: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, B extends never ? never : B extends z.ZodType ? B : never, R extends never ? never : R extends z.ZodType ? R : never>;
1299
- path: string;
1300
- };
1071
+ declare function stateMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<T, {}>;
1301
1072
  /**
1302
- * DELETE route creator with state and services support
1073
+ * Create a middleware that only contributes services (no state)
1074
+ * Convenience helper for service-only middleware
1075
+ *
1076
+ * @template T - Type of services to contribute
1077
+ * @param handler - Middleware function that adds services
1078
+ * @returns Middleware that contributes services only
1079
+ *
1303
1080
  */
1304
- type CreateDeleteRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, R = never>(config: {
1305
- schema?: {
1306
- params?: P extends never ? never : P;
1307
- query?: Q extends never ? never : Q;
1308
- response?: R extends never ? never : R;
1309
- };
1310
- handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, never, // DELETE never has body
1311
- [
1312
- R
1313
- ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
1314
- middleware?: Middleware[];
1315
- options?: Record<string, unknown>;
1316
- }) => {
1317
- DELETE: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, never, R extends never ? never : R extends z.ZodType ? R : never>;
1318
- path: string;
1319
- };
1081
+ declare function serviceMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<{}, T>;
1082
+
1320
1083
  /**
1321
- * PATCH route creator with state and services support
1084
+ * Error type definitions and interfaces for the BlaizeJS framework
1085
+ *
1086
+ * This module contains all the type definitions used for error handling
1087
+ * across the BlaizeJS framework, including server-side errors, client-side
1088
+ * errors, and HTTP response formats.
1322
1089
  */
1323
- type CreatePatchRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, B = never, R = never>(config: {
1324
- schema?: {
1325
- params?: P extends never ? never : P;
1326
- query?: Q extends never ? never : Q;
1327
- body?: B extends never ? never : B;
1328
- response?: R extends never ? never : R;
1329
- };
1330
- handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, B extends z.ZodType ? Infer<B> : unknown, [
1331
- R
1332
- ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
1333
- middleware?: Middleware[];
1334
- options?: Record<string, unknown>;
1335
- }) => {
1336
- PATCH: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, B extends never ? never : B extends z.ZodType ? B : never, R extends never ? never : R extends z.ZodType ? R : never>;
1337
- path: string;
1338
- };
1339
1090
  /**
1340
- * HEAD route creator with state and services support
1091
+ * Structure of error responses sent over HTTP
1092
+ *
1093
+ * This interface defines the JSON format used for all error responses
1094
+ * from BlaizeJS servers. It matches the structure returned by BlaizeError.toJSON()
1095
+ *
1096
+ * @example
1097
+ * ```json
1098
+ * {
1099
+ * "type": "VALIDATION_ERROR",
1100
+ * "title": "Request validation failed",
1101
+ * "status": 400,
1102
+ * "correlationId": "req_abc123",
1103
+ * "timestamp": "2024-01-15T10:30:00.000Z",
1104
+ * "details": {
1105
+ * "fields": ["email", "password"]
1106
+ * }
1107
+ * }
1108
+ * ```
1109
+ */
1110
+ interface BlaizeErrorResponse {
1111
+ /** Error type from the ErrorType enum */
1112
+ type: ErrorType;
1113
+ /** Human-readable error message */
1114
+ title: string;
1115
+ /** HTTP status code */
1116
+ status: number;
1117
+ /** Correlation ID for request tracing */
1118
+ correlationId: string;
1119
+ /** ISO timestamp when error occurred */
1120
+ timestamp: string;
1121
+ /** Optional error-specific details */
1122
+ details?: unknown;
1123
+ }
1124
+ /**
1125
+ * Context information for network-related errors
1126
+ *
1127
+ * Used by client-side error classes to provide additional context
1128
+ * about network failures, timeouts, and connection issues.
1341
1129
  */
1342
- type CreateHeadRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, R = never>(config: {
1343
- schema?: {
1344
- params?: P extends never ? never : P;
1345
- query?: Q extends never ? never : Q;
1346
- response?: R extends never ? never : R;
1130
+ interface NetworkErrorContext {
1131
+ /** The URL that failed */
1132
+ url: string;
1133
+ /** HTTP method being attempted */
1134
+ method: string;
1135
+ /** Correlation ID for tracing */
1136
+ correlationId: string;
1137
+ /** Timeout value if applicable */
1138
+ timeout?: number;
1139
+ /** The original error that caused the network failure */
1140
+ originalError: Error;
1141
+ /** Additional network-specific details */
1142
+ networkDetails?: {
1143
+ /** Whether this was a connection timeout */
1144
+ isTimeout?: boolean;
1145
+ /** Whether this was a DNS resolution failure */
1146
+ isDnsFailure?: boolean;
1147
+ /** Whether this was a connection refused error */
1148
+ isConnectionRefused?: boolean;
1149
+ /** HTTP status code if received before failure */
1150
+ statusCode?: number;
1347
1151
  };
1348
- handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, never, // HEAD never has body
1349
- [
1350
- R
1351
- ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
1352
- middleware?: Middleware[];
1353
- options?: Record<string, unknown>;
1354
- }) => {
1355
- HEAD: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, never, R extends never ? never : R extends z.ZodType ? R : never>;
1356
- path: string;
1357
- };
1152
+ }
1358
1153
  /**
1359
- * OPTIONS route creator with state and services support
1154
+ * Context information for request timeout errors
1155
+ *
1156
+ * Specialized context for timeout-specific errors with timing information.
1360
1157
  */
1361
- type CreateOptionsRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, R = never>(config: {
1362
- schema?: {
1363
- params?: P extends never ? never : P;
1364
- query?: Q extends never ? never : Q;
1365
- response?: R extends never ? never : R;
1366
- };
1367
- handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, never, // OPTIONS never has body
1368
- [
1369
- R
1370
- ] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
1371
- middleware?: Middleware[];
1372
- options?: Record<string, unknown>;
1373
- }) => {
1374
- OPTIONS: RouteMethodOptions<P extends never ? never : P extends z.ZodType ? P : never, Q extends never ? never : Q extends z.ZodType ? Q : never, never, R extends never ? never : R extends z.ZodType ? R : never>;
1375
- path: string;
1376
- };
1377
-
1158
+ interface TimeoutErrorContext {
1159
+ /** The URL that timed out */
1160
+ url: string;
1161
+ /** HTTP method being attempted */
1162
+ method: string;
1163
+ /** Correlation ID for tracing */
1164
+ correlationId: string;
1165
+ /** Configured timeout value in milliseconds */
1166
+ timeoutMs: number;
1167
+ /** Actual duration before timeout in milliseconds */
1168
+ elapsedMs: number;
1169
+ /** Type of timeout (request, connection, etc.) */
1170
+ timeoutType: 'request' | 'connection' | 'response' | 'idle';
1171
+ }
1378
1172
  /**
1379
- * Compose multiple middleware functions into a single middleware function
1173
+ * Context information for response parsing errors
1174
+ *
1175
+ * Used when the client receives a response but cannot parse it properly.
1380
1176
  */
1381
- declare function compose(middlewareStack: Middleware[]): MiddlewareFunction;
1382
-
1177
+ interface ParseErrorContext {
1178
+ /** The URL that returned unparseable content */
1179
+ url: string;
1180
+ /** HTTP method used */
1181
+ method: string;
1182
+ /** Correlation ID for tracing */
1183
+ correlationId: string;
1184
+ /** HTTP status code received */
1185
+ statusCode: number;
1186
+ /** Content-Type header if available */
1187
+ contentType?: string;
1188
+ /** Expected response format */
1189
+ expectedFormat: 'json' | 'text' | 'binary';
1190
+ /** Sample of the actual response content (truncated for safety) */
1191
+ responseSample?: string;
1192
+ /** The original parsing error */
1193
+ originalError: Error;
1194
+ }
1383
1195
  /**
1384
- * CORS Types for BlaizeJS Framework
1385
- *
1386
- * Comprehensive type definitions for W3C-compliant CORS middleware
1387
- * with support for string, regex, and async function origin validation.
1196
+ * Validation error field details
1388
1197
  *
1389
- * @module @blaizejs/types/cors
1198
+ * Structure for field-level validation errors with multiple error messages
1199
+ * per field.
1390
1200
  */
1391
-
1201
+ interface ValidationFieldError {
1202
+ /** Field name or path (e.g., "email", "user.profile.name") */
1203
+ field: string;
1204
+ /** Array of error messages for this field */
1205
+ messages: string[];
1206
+ /** The invalid value that caused the error */
1207
+ rejectedValue?: unknown;
1208
+ /** Expected type or format */
1209
+ expectedType?: string;
1210
+ }
1211
+ interface ServiceNotAvailableDetails {
1212
+ /** Service that's unavailable */
1213
+ service?: string;
1214
+ /** Seconds to wait before retry */
1215
+ retryAfter?: number;
1216
+ /** Why service is unavailable */
1217
+ reason?: 'maintenance' | 'overload' | 'circuit_breaker' | 'dependency_down';
1218
+ /** Additional context */
1219
+ [key: string]: unknown;
1220
+ }
1392
1221
  /**
1393
- * Origin configuration type supporting multiple validation methods
1394
- *
1395
- * @example
1396
- * ```typescript
1397
- * // String origin (exact match)
1398
- * const origin: CorsOrigin = 'https://example.com';
1222
+ * Validation error details structure
1399
1223
  *
1400
- * // RegExp pattern
1401
- * const origin: CorsOrigin = /^https:\/\/.*\.example\.com$/;
1224
+ * Used by ValidationError to provide structured information about
1225
+ * what fields failed validation and why.
1226
+ */
1227
+ interface ValidationErrorDetails {
1228
+ /** Array of field-level errors */
1229
+ fields: ValidationFieldError[];
1230
+ /** Total number of validation errors */
1231
+ errorCount: number;
1232
+ /** The section that failed validation */
1233
+ section: 'params' | 'query' | 'body' | 'response';
1234
+ /** Schema name if available */
1235
+ schemaName?: string;
1236
+ }
1237
+ /**
1238
+ * All available error types in the BlaizeJS framework
1402
1239
  *
1403
- * // Dynamic validation function
1404
- * const origin: CorsOrigin = async (origin, ctx) => {
1405
- * return await checkOriginAllowed(origin, ctx?.state.user);
1406
- * };
1240
+ * This enum provides both compile-time type safety and runtime values
1241
+ * for error type identification across server and client packages.
1407
1242
  *
1408
- * // Array of mixed types
1409
- * const origin: CorsOrigin = [
1410
- * 'https://localhost:3000',
1411
- * /^https:\/\/.*\.example\.com$/,
1412
- * (origin) => origin.endsWith('.trusted.com')
1413
- * ];
1243
+ * @example Type-safe error handling:
1244
+ * ```typescript
1245
+ * function handleError(errorType: ErrorType) {
1246
+ * switch (errorType) {
1247
+ * case ErrorType.VALIDATION_ERROR:
1248
+ * // Handle validation error
1249
+ * break;
1250
+ * case ErrorType.NOT_FOUND:
1251
+ * // Handle not found error
1252
+ * break;
1253
+ * // TypeScript ensures all cases are covered
1254
+ * }
1255
+ * }
1414
1256
  * ```
1415
1257
  */
1416
- type CorsOrigin = string | RegExp | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>) | Array<string | RegExp | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>)>;
1258
+ declare enum ErrorType {
1259
+ /** Request validation failed (400) */
1260
+ VALIDATION_ERROR = "VALIDATION_ERROR",
1261
+ /** Resource not found (404) */
1262
+ NOT_FOUND = "NOT_FOUND",
1263
+ /** Authentication required (401) */
1264
+ UNAUTHORIZED = "UNAUTHORIZED",
1265
+ /** Access forbidden (403) */
1266
+ FORBIDDEN = "FORBIDDEN",
1267
+ /** SSE Not Acceptable (406) */
1268
+ SSE_NOT_ACCEPTABLE = "SSE_NOT_ACCEPTABLE",
1269
+ /** Resource conflict (409) */
1270
+ CONFLICT = "CONFLICT",
1271
+ /** Rate limit exceeded (429) */
1272
+ RATE_LIMITED = "RATE_LIMITED",
1273
+ /** Internal server error (500) */
1274
+ INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR",
1275
+ /** File/Request Too Large (413) */
1276
+ PAYLOAD_TOO_LARGE = "PAYLOAD_TOO_LARGE",
1277
+ /** Wrong Content Type (415) */
1278
+ UNSUPPORTED_MEDIA_TYPE = "UNSUPPORTED_MEDIA_TYPE",
1279
+ /** Upload Timeout (408) */
1280
+ UPLOAD_TIMEOUT = "UPLOAD_TIMEOUT",
1281
+ /** Valid Format Invalid Semantics (422) */
1282
+ UNPROCESSABLE_ENTITY = "UNPROCESSABLE_ENTITY",
1283
+ /** Network connectivity failure (0) */
1284
+ NETWORK_ERROR = "NETWORK_ERROR",
1285
+ /** Request or response timeout (0) */
1286
+ TIMEOUT_ERROR = "TIMEOUT_ERROR",
1287
+ /** Response parsing failure (0) */
1288
+ PARSE_ERROR = "PARSE_ERROR",
1289
+ /** Generic HTTP error (varies) */
1290
+ HTTP_ERROR = "HTTP_ERROR",
1291
+ /** SSE connection failed (502) */
1292
+ SSE_CONNECTION_ERROR = "SSE_CONNECTION_ERROR",
1293
+ /** SSE buffer overflow (503) */
1294
+ SSE_BUFFER_OVERFLOW = "SSE_BUFFER_OVERFLOW",
1295
+ /** SSE stream closed (410) */
1296
+ SSE_STREAM_CLOSED = "SSE_STREAM_CLOSED",
1297
+ /** Service temporarily unavailable (503) */
1298
+ SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE"
1299
+ }
1417
1300
  /**
1418
- * HTTP methods that can be allowed in CORS
1419
- * Based on W3C CORS specification
1301
+ * Error severity levels for logging and monitoring
1302
+ *
1303
+ * Provides a way to categorize errors by their impact and urgency.
1420
1304
  */
1421
- type CorsHttpMethod = HttpMethod | 'CONNECT' | 'TRACE';
1305
+ declare enum ErrorSeverity {
1306
+ /** Low impact, often user errors */
1307
+ LOW = "low",
1308
+ /** Medium impact, application errors */
1309
+ MEDIUM = "medium",
1310
+ /** High impact, system errors */
1311
+ HIGH = "high",
1312
+ /** Critical impact, service disruption */
1313
+ CRITICAL = "critical"
1314
+ }
1422
1315
  /**
1423
- * Main CORS configuration options
1316
+ * Abstract base class for all BlaizeJS errors
1317
+ *
1318
+ * This class provides the foundation for all error types in the BlaizeJS framework.
1319
+ * It extends JavaScript's built-in Error class and adds framework-specific properties
1320
+ * for consistent error handling across server and client.
1424
1321
  *
1425
1322
  * @example
1426
1323
  * ```typescript
1427
- * const corsOptions: CorsOptions = {
1428
- * origin: 'https://example.com',
1429
- * methods: ['GET', 'POST'],
1430
- * credentials: true,
1431
- * maxAge: 86400
1432
- * };
1324
+ * import { ErrorType } from './types';
1325
+ *
1326
+ * class NotFoundError extends BlaizeError<{ resourceId: string }> {
1327
+ * constructor(message = 'Resource not found', details?: { resourceId: string }) {
1328
+ * super(ErrorType.NOT_FOUND, message, 404, getCurrentCorrelationId(), details);
1329
+ * }
1330
+ * }
1433
1331
  * ```
1332
+ *
1333
+ * @template TDetails - Type for error-specific details object
1434
1334
  */
1435
- interface CorsOptions {
1335
+ declare abstract class BlaizeError<TDetails = unknown> extends Error {
1436
1336
  /**
1437
- * Configures the Access-Control-Allow-Origin header
1438
- *
1439
- * Possible values:
1440
- * - `true`: Allow all origins (sets to '*' unless credentials is true, then reflects origin)
1441
- * - `false`: Disable CORS (no headers set)
1442
- * - `string`: Specific origin to allow
1443
- * - `RegExp`: Pattern to match origins
1444
- * - `function`: Custom validation logic
1445
- * - `array`: Multiple origin configurations
1446
- *
1447
- * @default false
1337
+ * Error type identifier from the ErrorType enum
1338
+ * Used for programmatic error handling and client-side error routing
1448
1339
  */
1449
- origin?: boolean | CorsOrigin;
1340
+ readonly type: ErrorType;
1450
1341
  /**
1451
- * Configures the Access-Control-Allow-Methods header
1452
- *
1453
- * @default ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE']
1454
- * @example ['GET', 'POST']
1342
+ * Human-readable error title/message
1343
+ * Should be descriptive enough for debugging but safe for end users
1455
1344
  */
1456
- methods?: CorsHttpMethod[] | string;
1345
+ readonly title: string;
1457
1346
  /**
1458
- * Configures the Access-Control-Allow-Headers header
1459
- *
1460
- * Pass an array of allowed headers or a comma-delimited string.
1461
- *
1462
- * @default Request's Access-Control-Request-Headers header value
1463
- * @example ['Content-Type', 'Authorization']
1347
+ * HTTP status code associated with this error
1348
+ * Used by the error boundary to set appropriate response status
1464
1349
  */
1465
- allowedHeaders?: string[] | string;
1350
+ readonly status: number;
1466
1351
  /**
1467
- * Configures the Access-Control-Expose-Headers header
1468
- *
1469
- * Headers that the browser is allowed to access.
1470
- *
1471
- * @default []
1472
- * @example ['Content-Range', 'X-Content-Range']
1352
+ * Correlation ID for request tracing
1353
+ * Links this error to the specific request that generated it
1473
1354
  */
1474
- exposedHeaders?: string[] | string;
1355
+ readonly correlationId: string;
1475
1356
  /**
1476
- * Configures the Access-Control-Allow-Credentials header
1477
- *
1478
- * Set to true to allow credentials (cookies, authorization headers, TLS client certificates).
1479
- * Note: Cannot be used with origin: '*' for security reasons.
1480
- *
1481
- * @default false
1357
+ * Timestamp when the error occurred
1358
+ * Useful for debugging and log correlation
1482
1359
  */
1483
- credentials?: boolean;
1360
+ readonly timestamp: Date;
1484
1361
  /**
1485
- * Configures the Access-Control-Max-Age header in seconds
1486
- *
1487
- * Indicates how long browsers can cache preflight response.
1488
- * Set to -1 to disable caching.
1489
- *
1490
- * @default undefined (browser decides)
1491
- * @example 86400 // 24 hours
1362
+ * Additional error-specific details
1363
+ * Type-safe error context that varies by error type
1492
1364
  */
1493
- maxAge?: number;
1365
+ readonly details?: TDetails | undefined;
1494
1366
  /**
1495
- * Whether to pass the CORS preflight response to the next handler
1496
- *
1497
- * When false, the preflight response is sent immediately.
1498
- * When true, control passes to the next middleware/handler.
1367
+ * Creates a new BlaizeError instance
1499
1368
  *
1500
- * @default false
1369
+ * @param type - Error type from the ErrorType enum
1370
+ * @param title - Human-readable error message
1371
+ * @param status - HTTP status code
1372
+ * @param correlationId - Request correlation ID for tracing
1373
+ * @param details - Optional error-specific details
1501
1374
  */
1502
- preflightContinue?: boolean;
1375
+ protected constructor(type: ErrorType, title: string, status: number, correlationId: string, details?: TDetails | undefined);
1503
1376
  /**
1504
- * HTTP status code for successful OPTIONS requests
1505
- *
1506
- * Some legacy browsers require 200, while 204 is more correct.
1377
+ * Serializes the error to a plain object suitable for HTTP responses
1507
1378
  *
1508
- * @default 204
1379
+ * @returns Object representation of the error
1509
1380
  */
1510
- optionsSuccessStatus?: number;
1381
+ toJSON(): {
1382
+ type: ErrorType;
1383
+ title: string;
1384
+ status: number;
1385
+ correlationId: string;
1386
+ timestamp: string;
1387
+ } | {
1388
+ details: TDetails & ({} | null);
1389
+ type: ErrorType;
1390
+ title: string;
1391
+ status: number;
1392
+ correlationId: string;
1393
+ timestamp: string;
1394
+ };
1395
+ /**
1396
+ * Returns a string representation of the error
1397
+ * Includes correlation ID for easier debugging
1398
+ */
1399
+ toString(): string;
1511
1400
  }
1512
1401
  /**
1513
- * Internal CORS validation result
1514
- * Used by middleware implementation
1402
+ * Interface for payload too large error details
1515
1403
  */
1516
- interface CorsValidationResult {
1517
- /**
1518
- * Whether the origin is allowed
1519
- */
1520
- allowed: boolean;
1521
- /**
1522
- * The origin value to set in the header
1523
- * Can be '*', specific origin, or 'null'
1524
- */
1525
- origin?: string;
1526
- /**
1527
- * Whether to add Vary: Origin header
1528
- */
1529
- vary?: boolean;
1404
+ interface PayloadTooLargeErrorDetails {
1405
+ fileCount?: number;
1406
+ maxFiles?: number;
1407
+ filename?: string;
1408
+ field?: string;
1409
+ contentType?: string;
1410
+ currentSize?: number;
1411
+ maxSize?: number;
1530
1412
  }
1531
1413
  /**
1532
- * CORS preflight request information
1533
- * Extracted from OPTIONS request headers
1414
+ * Interface for unsupported media type error details
1534
1415
  */
1535
- interface CorsPreflightInfo {
1536
- /**
1537
- * The origin making the request
1538
- */
1539
- origin?: string;
1540
- /**
1541
- * The method that will be used in the actual request
1542
- * From Access-Control-Request-Method header
1543
- */
1544
- requestedMethod?: string;
1545
- /**
1546
- * The headers that will be sent in the actual request
1547
- * From Access-Control-Request-Headers header
1548
- */
1549
- requestedHeaders?: string[];
1416
+ interface UnsupportedMediaTypeErrorDetails {
1417
+ receivedMimeType?: string;
1418
+ allowedMimeTypes?: string[];
1419
+ filename?: string;
1420
+ }
1421
+ /**
1422
+ * Interface for authentication error details
1423
+ */
1424
+ interface UnauthorizedErrorDetails {
1425
+ /** Reason for authentication failure */
1426
+ reason?: 'missing_token' | 'invalid_token' | 'expired_token' | 'malformed_token' | 'insufficient_scope' | string;
1427
+ /** Authentication scheme (Bearer, Basic, etc.) */
1428
+ authScheme?: string;
1429
+ /** Authentication realm */
1430
+ realm?: string;
1431
+ /** Detailed error description */
1432
+ error_description?: string;
1433
+ /** Required scopes or permissions */
1434
+ requiredScopes?: string[];
1435
+ /** Login URL for interactive authentication */
1436
+ loginUrl?: string;
1437
+ /** Additional context */
1438
+ [key: string]: unknown;
1439
+ }
1440
+ /**
1441
+ * Interface for authorization/permission error details
1442
+ */
1443
+ interface ForbiddenErrorDetails {
1444
+ /** Required permission or role */
1445
+ requiredPermission?: string;
1446
+ /** User's current permissions */
1447
+ userPermissions?: string[];
1448
+ /** Resource being accessed */
1449
+ resource?: string;
1450
+ /** Action being attempted */
1451
+ action?: string;
1452
+ /** Reason for access denial */
1453
+ reason?: 'insufficient_permissions' | 'account_suspended' | 'resource_locked' | 'origin_not_allowed' | string;
1454
+ /** Additional context */
1455
+ [key: string]: unknown;
1456
+ }
1457
+ /**
1458
+ * Interface for resource conflict error details
1459
+ */
1460
+ interface ConflictErrorDetails {
1461
+ /** Type of conflict */
1462
+ conflictType?: 'duplicate_key' | 'version_mismatch' | 'concurrent_modification' | 'business_rule' | string;
1463
+ /** Field that caused the conflict */
1464
+ field?: string;
1465
+ /** Existing value that conflicts */
1466
+ existingValue?: unknown;
1467
+ /** Provided value that conflicts */
1468
+ providedValue?: unknown;
1469
+ /** Resource that has the conflicting value */
1470
+ conflictingResource?: string;
1471
+ /** Current version/etag of the resource */
1472
+ currentVersion?: string;
1473
+ /** Expected version/etag */
1474
+ expectedVersion?: string;
1475
+ /** Suggested resolution */
1476
+ resolution?: string;
1477
+ /** Additional context */
1478
+ [key: string]: unknown;
1479
+ }
1480
+ /**
1481
+ * Interface for rate limiting error details
1482
+ */
1483
+ interface RateLimitErrorDetails {
1484
+ /** Maximum requests allowed in the time window */
1485
+ limit?: number;
1486
+ /** Remaining requests in current window */
1487
+ remaining?: number;
1488
+ /** When the rate limit resets */
1489
+ resetTime?: Date;
1490
+ /** Seconds until the rate limit resets */
1491
+ retryAfter?: number;
1492
+ /** Time window for the rate limit */
1493
+ window?: string;
1494
+ /** Identifier used for rate limiting (IP, user ID, etc.) */
1495
+ identifier?: string;
1496
+ /** Type of rate limit hit */
1497
+ limitType?: 'global' | 'per_user' | 'per_ip' | 'per_endpoint' | string;
1498
+ /** Additional context */
1499
+ [key: string]: unknown;
1500
+ }
1501
+ /**
1502
+ * Interface for internal server error details
1503
+ */
1504
+ interface InternalServerErrorDetails {
1505
+ /** Original error message (for debugging) */
1506
+ originalError?: string;
1507
+ /** Stack trace (for debugging) */
1508
+ stackTrace?: string;
1509
+ /** Component where the error occurred */
1510
+ component?: string;
1511
+ /** Operation being performed */
1512
+ operation?: string;
1513
+ /** Internal error code */
1514
+ internalErrorCode?: string;
1515
+ /** When the error occurred */
1516
+ timestamp?: Date;
1517
+ /** Whether this error should be retryable */
1518
+ retryable?: boolean;
1519
+ /** Additional debugging context */
1520
+ [key: string]: unknown;
1550
1521
  }
1551
1522
  /**
1552
- * Cache entry for origin validation results
1553
- * Used for performance optimization
1523
+ * Interface for NotFound error details
1524
+ * Provides context about the missing resource
1554
1525
  */
1555
- interface CorsOriginCacheEntry {
1556
- /**
1557
- * Whether the origin is allowed
1558
- */
1559
- allowed: boolean;
1560
- /**
1561
- * When this cache entry expires (timestamp)
1562
- */
1563
- expiresAt: number;
1564
- /**
1565
- * Optional user identifier for cache key
1566
- */
1567
- userId?: string;
1526
+ interface NotFoundErrorDetails {
1527
+ /** Type of resource that was not found */
1528
+ resourceType?: string;
1529
+ /** ID or identifier of the resource */
1530
+ resourceId?: string;
1531
+ /** Collection or table where the resource was searched */
1532
+ collection?: string;
1533
+ /** Search criteria that was used */
1534
+ query?: Record<string, unknown>;
1535
+ /** Search criteria that was used (for backward compatibility) */
1536
+ searchCriteria?: Record<string, unknown>;
1537
+ /** The path that was attempted */
1538
+ path?: string;
1539
+ /** HTTP method used (for API endpoints) */
1540
+ method?: string;
1541
+ /** The path that was attempted (for backward compatibility) */
1542
+ attemptedPath?: string;
1543
+ /** Parent resource information for nested resources */
1544
+ parentResource?: {
1545
+ type: string;
1546
+ id: string;
1547
+ };
1548
+ /** Helpful suggestion for the user */
1549
+ suggestion?: string;
1550
+ /** Additional context */
1551
+ [key: string]: unknown;
1568
1552
  }
1569
1553
  /**
1570
- * Configuration for CORS origin validation cache
1554
+ * Context information for error transformation
1571
1555
  */
1572
- interface CorsOriginCacheConfig {
1573
- /**
1574
- * Time-to-live for cache entries in milliseconds
1575
- * @default 60000 (1 minute)
1576
- */
1577
- ttl?: number;
1578
- /**
1579
- * Maximum number of entries in the cache
1580
- * @default 1000
1581
- */
1582
- maxSize?: number;
1583
- /**
1584
- * Whether to include user ID in cache key
1585
- * @default true
1586
- */
1587
- includeUserId?: boolean;
1556
+ interface ErrorTransformContext {
1557
+ url: string;
1558
+ method: string;
1559
+ correlationId: string;
1560
+ timeoutMs?: number;
1561
+ elapsedMs?: number;
1562
+ statusCode?: number;
1563
+ contentType?: string;
1564
+ responseSample?: string;
1565
+ [key: string]: unknown;
1588
1566
  }
1589
1567
  /**
1590
- * Statistics for CORS middleware performance monitoring
1568
+ * SSE-specific error detail interfaces for BlaizeJS framework
1569
+ *
1570
+ * These interfaces define the structure of details for SSE errors.
1571
+ * The actual error classes are implemented in blaize-core.
1591
1572
  */
1592
- interface CorsStats {
1593
- /**
1594
- * Total number of CORS requests processed
1595
- */
1596
- totalRequests: number;
1597
- /**
1598
- * Number of preflight requests handled
1599
- */
1600
- preflightRequests: number;
1601
- /**
1602
- * Number of allowed origins
1603
- */
1604
- allowedOrigins: number;
1605
- /**
1606
- * Number of denied origins
1607
- */
1608
- deniedOrigins: number;
1609
- /**
1610
- * Cache hit rate for origin validation
1611
- */
1612
- cacheHitRate: number;
1613
- /**
1614
- * Average origin validation time in milliseconds
1615
- */
1616
- avgValidationTime: number;
1617
- }
1618
1573
  /**
1619
- * Cache entry type
1574
+ * Details for SSE connection errors
1620
1575
  */
1621
- interface CacheEntry {
1622
- allowed: boolean;
1623
- expiresAt: number;
1624
- lastAccessed: number;
1576
+ interface SSEConnectionErrorDetails {
1577
+ /** Client identifier if available */
1578
+ clientId?: string;
1579
+ /** Connection attempt number */
1580
+ attemptNumber?: number;
1581
+ /** Maximum retry attempts configured */
1582
+ maxRetries?: number;
1583
+ /** The underlying error that caused connection failure */
1584
+ cause?: string;
1585
+ /** Suggested resolution */
1586
+ suggestion?: string;
1625
1587
  }
1626
1588
  /**
1627
- * Cache configuration
1589
+ * Details for SSE buffer overflow errors
1628
1590
  */
1629
- interface CacheConfig {
1630
- ttl: number;
1591
+ interface SSEBufferOverflowErrorDetails {
1592
+ /** Client identifier */
1593
+ clientId?: string;
1594
+ /** Current buffer size when overflow occurred */
1595
+ currentSize: number;
1596
+ /** Maximum buffer size configured */
1631
1597
  maxSize: number;
1598
+ /** Number of events dropped */
1599
+ eventsDropped?: number;
1600
+ /** Buffer strategy that was applied */
1601
+ strategy: 'drop-oldest' | 'drop-newest' | 'close';
1602
+ /** Event that triggered the overflow */
1603
+ triggeringEvent?: string;
1632
1604
  }
1633
-
1634
1605
  /**
1635
- * Create CORS middleware with the specified options
1636
- *
1637
- * @param userOptions - CORS configuration options or boolean
1638
- * @returns Middleware function that handles CORS
1639
- *
1640
- * @example
1641
- * ```typescript
1642
- * import { cors } from '@blaize-core/middleware/cors';
1643
- *
1644
- * // Development mode - allow all origins
1645
- * server.use(cors(true));
1646
- *
1647
- * // Production - specific origin
1648
- * server.use(cors({
1649
- * origin: 'https://app.example.com',
1650
- * credentials: true,
1651
- * maxAge: 86400
1652
- * }));
1653
- *
1654
- * // Multiple origins with regex
1655
- * server.use(cors({
1656
- * origin: [
1657
- * 'https://app.example.com',
1658
- * /^https:\/\/.*\.example\.com$/
1659
- * ]
1660
- * }));
1661
- *
1662
- * // Dynamic origin validation
1663
- * server.use(cors({
1664
- * origin: async (origin, ctx) => {
1665
- * return await checkOriginAllowed(origin, ctx.state.user);
1666
- * }
1667
- * }));
1668
- * ```
1606
+ * Details for SSE stream closed errors
1669
1607
  */
1670
- declare function cors(userOptions?: CorsOptions | boolean): Middleware;
1671
-
1608
+ interface SSEStreamClosedErrorDetails {
1609
+ /** Client identifier */
1610
+ clientId?: string;
1611
+ /** When the stream was closed */
1612
+ closedAt?: string;
1613
+ /** Reason for closure */
1614
+ closeReason?: 'client-disconnect' | 'server-close' | 'timeout' | 'error' | 'buffer-overflow';
1615
+ /** Whether reconnection is possible */
1616
+ canReconnect?: boolean;
1617
+ /** Suggested retry interval in milliseconds */
1618
+ retryAfter?: number;
1619
+ }
1672
1620
  /**
1673
- * Create a middleware
1621
+ * Context for SSE connection errors
1674
1622
  */
1675
- declare function create$2<TState = {}, TServices = {}>(handlerOrOptions: MiddlewareFunction | MiddlewareOptions): Middleware<TState, TServices>;
1623
+ interface SSEConnectionErrorContext {
1624
+ /** The SSE endpoint URL */
1625
+ url: string;
1626
+ /** Correlation ID for tracing */
1627
+ correlationId: string;
1628
+ /** Connection state when error occurred */
1629
+ state: 'connecting' | 'connected' | 'disconnected' | 'closed';
1630
+ /** Number of reconnection attempts made */
1631
+ reconnectAttempts?: number;
1632
+ /** The original error if available */
1633
+ originalError?: Error;
1634
+ /** Additional SSE-specific details */
1635
+ sseDetails?: {
1636
+ /** Whether credentials were included */
1637
+ withCredentials?: boolean;
1638
+ /** Last received event ID */
1639
+ lastEventId?: string;
1640
+ /** EventSource ready state */
1641
+ readyState?: number;
1642
+ };
1643
+ }
1676
1644
  /**
1677
- * Create a middleware that only contributes state (no services)
1678
- * Convenience helper for state-only middleware
1679
- *
1680
- * @template T - Type of state to contribute
1681
- * @param handler - Middleware function that adds state
1682
- * @returns Middleware that contributes state only
1683
- *
1645
+ * Context for SSE stream errors (server-sent errors)
1684
1646
  */
1685
- declare function stateMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<T, {}>;
1647
+ interface SSEStreamErrorContext {
1648
+ /** The SSE endpoint URL */
1649
+ url: string;
1650
+ /** Correlation ID from server or client */
1651
+ correlationId: string;
1652
+ /** Error message from server */
1653
+ message: string;
1654
+ /** Error code if provided */
1655
+ code?: string;
1656
+ /** Error name/type from server */
1657
+ name?: string;
1658
+ /** Raw error data from server */
1659
+ rawData?: any;
1660
+ }
1686
1661
  /**
1687
- * Create a middleware that only contributes services (no state)
1688
- * Convenience helper for service-only middleware
1689
- *
1690
- * @template T - Type of services to contribute
1691
- * @param handler - Middleware function that adds services
1692
- * @returns Middleware that contributes services only
1693
- *
1662
+ * Context for SSE heartbeat timeout errors
1694
1663
  */
1695
- declare function serviceMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<{}, T>;
1664
+ interface SSEHeartbeatErrorContext {
1665
+ /** The SSE endpoint URL */
1666
+ url: string;
1667
+ /** Correlation ID for tracing */
1668
+ correlationId: string;
1669
+ /** Configured heartbeat timeout in ms */
1670
+ heartbeatTimeout: number;
1671
+ /** Time since last event in ms */
1672
+ timeSinceLastEvent?: number;
1673
+ /** Last event ID received */
1674
+ lastEventId?: string;
1675
+ }
1696
1676
 
1697
1677
  /**
1698
1678
  * Represents a single Server-Sent Event
@@ -2362,6 +2342,7 @@ interface ServerOptionsInput {
2362
2342
  * ```
2363
2343
  */
2364
2344
  cors?: CorsOptions | boolean;
2345
+ bodyLimits?: Partial<BodyLimits>;
2365
2346
  }
2366
2347
  /**
2367
2348
  * Configuration for a BlaizeJS server
@@ -2396,6 +2377,7 @@ interface ServerOptions {
2396
2377
  * @since 0.5.0
2397
2378
  */
2398
2379
  cors?: CorsOptions | boolean;
2380
+ bodyLimits: BodyLimits;
2399
2381
  }
2400
2382
  /**
2401
2383
  * BlaizeJS Server instance with generic type accumulation
@@ -2411,6 +2393,8 @@ interface Server<TState, TServices> {
2411
2393
  port: number;
2412
2394
  /** CORS configuration for this server */
2413
2395
  corsOptions?: CorsOptions | boolean;
2396
+ /** Body size limits for incoming requests */
2397
+ bodyLimits: BodyLimits;
2414
2398
  /** The host the server is bound to */
2415
2399
  host: string;
2416
2400
  events: EventEmitter;
@@ -3420,4 +3404,4 @@ declare const Blaize: {
3420
3404
  VERSION: string;
3421
3405
  };
3422
3406
 
3423
- export { Blaize, BlaizeError, type BlaizeErrorResponse, type BodyParseError, type BufferedEvent, type BuildRoutesRegistry, type BuildSSEArgs, type CacheConfig, type CacheEntry, type ClientConfig, type CloseEvent, type ComposeMiddlewareServices, type ComposeMiddlewareStates, type ComposeMiddlewareTypes, type ComposePluginServices, type ComposePluginStates, type ComposePluginTypes, ConflictError, type ConflictErrorDetails, type ConnectionEntry, type ConnectionRegistry, type Context, type ContextOptions, type ContextRequest, type ContextResponse, type CorrelationOptions, type CorsHttpMethod, type CorsOptions, type CorsOrigin, type CorsOriginCacheConfig, type CorsOriginCacheEntry, type CorsPreflightInfo, type CorsStats, type CorsValidationResult, type CreateClient, type CreateContextFn, type CreateDeleteRoute, type CreateEnhancedClient, type CreateGetRoute, type CreateHeadRoute, type CreateOptionsRoute, type CreatePatchRoute, type CreatePostRoute, type CreatePutRoute, type CreateSSEMethod, type CreateSSERoute, type ErrorHandlerOptions, ErrorSeverity, type ErrorTransformContext, ErrorType, type EventHandlers, type ExtractMethod, type ExtractMiddlewareServices, type ExtractMiddlewareState, type ExtractMiddlewareTypes, type ExtractPluginServices, type ExtractPluginState, type ExtractPluginTypes, type ExtractSSEEvents, type ExtractSSEParams, type ExtractSSEQuery, type ExtractSSERoutes, type FileCache, type FindRouteFilesOptions, ForbiddenError, type ForbiddenErrorDetails, type GetContextFn, type HasSSEMethod, type Http2Options, type HttpMethod, type Infer, type InferContext, type InternalRequestArgs, InternalServerError, type InternalServerErrorDetails, type Matcher, type MergeServices, type MergeStates, type Middleware, MiddlewareAPI, type MiddlewareFunction, type MiddlewareOptions, type MultipartData, type MultipartError, type MultipartLimits, type NetworkErrorContext, type NextFunction, NotFoundError, type NotFoundErrorDetails, type ParseErrorContext, type ParseOptions, type ParseResult, type ParsedRoute, type ParserState, PayloadTooLargeError, type PayloadTooLargeErrorDetails, type Plugin, type PluginFactory, type PluginHooks, type PluginLifecycleManager, type PluginLifecycleOptions, type PluginOptions, PluginsAPI, type ProcessResponseOptions, type ProcessingConfig, type QueryParams, RateLimitError, type RateLimitErrorDetails, type ReconnectStrategy, type RegistryResult, type ReloadMetrics, type RequestHandler, type RequestOptions, type RequestParams, RequestTimeoutError, type Result, type Route, type RouteDefinition, type RouteEntry, type RouteHandler, type RouteMatch, type RouteMethodOptions, type RouteNode, type RouteOptions, type RouteRegistry, type RouteSchema, type Router, RouterAPI, type RouterOptions, type SSEBufferOverflowErrorDetails, type SSEBufferStrategy, type SSEClient, type SSEClientMetrics, type SSEClientOptions, type SSEConnectionErrorContext, type SSEConnectionErrorDetails, type SSEConnectionFactory, type SSEConnectionState, type SSEEvent, type SSEEventHandler, type SSEEventListener, type SSEHeartbeatErrorContext, type SSEMetrics, type SSEOptions, type SSERouteHandler, type SSERouteSchema, type SSESerializedEvent, type SSEStream, type SSEStreamClosedErrorDetails, type SSEStreamErrorContext, type SSEStreamExtended, type SSEStreamManager, type SafeComposeMiddlewareServices, type SafeComposeMiddlewareStates, type SafeComposePluginServices, type SafeComposePluginStates, type SafeExtractMiddlewareServices, type SafeExtractMiddlewareState, type SafeExtractPluginServices, type SafeExtractPluginState, type Server, ServerAPI, type ServerOptions, type ServerOptionsInput, type ServiceNotAvailableDetails, ServiceNotAvailableError, type Services, type StandardErrorResponse, type StartOptions, type State, type StopOptions, type StreamMetrics, type StreamOptions, type TimeoutErrorContext, type TypedSSEStream, UnauthorizedError, type UnauthorizedErrorDetails, type UnifiedRequest, type UnifiedResponse, type UnionToIntersection, type UnknownFunction, type UnknownServer, UnprocessableEntityError, UnsupportedMediaTypeError, type UnsupportedMediaTypeErrorDetails, type UploadProgress, type UploadedFile, VERSION, type ValidationConfig, ValidationError, type ValidationErrorDetails, type ValidationFieldError, type WatchOptions, asMiddlewareArray, asPluginArray, buildUrl, compilePathPattern, compose, cors, createDeleteRoute, createGetRoute, createHeadRoute, createMatcher, create$2 as createMiddleware, createMiddlewareArray, createOptionsRoute, createPatchRoute, create$1 as createPlugin, createPluginArray, createPostRoute, createPutRoute, createRouteFactory, create as createServer, serviceMiddleware as createServiceMiddleware, stateMiddleware as createStateMiddleware, extractParams, getCorrelationId, inferContext, isBodyParseError, isMiddleware, isPlugin, paramsToQuery };
3407
+ export { Blaize, BlaizeError, type BlaizeErrorResponse, type BodyLimits, type BufferedEvent, type BuildRoutesRegistry, type BuildSSEArgs, type CacheConfig, type CacheEntry, type ClientConfig, type CloseEvent, type ComposeMiddlewareServices, type ComposeMiddlewareStates, type ComposeMiddlewareTypes, type ComposePluginServices, type ComposePluginStates, type ComposePluginTypes, ConflictError, type ConflictErrorDetails, type ConnectionEntry, type ConnectionRegistry, type Context, type ContextOptions, type ContextRequest, type ContextResponse, type CorrelationOptions, type CorsHttpMethod, type CorsOptions, type CorsOrigin, type CorsOriginCacheConfig, type CorsOriginCacheEntry, type CorsPreflightInfo, type CorsStats, type CorsValidationResult, type CreateClient, type CreateContextFn, type CreateDeleteRoute, type CreateEnhancedClient, type CreateGetRoute, type CreateHeadRoute, type CreateOptionsRoute, type CreatePatchRoute, type CreatePostRoute, type CreatePutRoute, type CreateSSEMethod, type CreateSSERoute, type ErrorHandlerOptions, ErrorSeverity, type ErrorTransformContext, ErrorType, type EventHandlers, type ExtractMethod, type ExtractMiddlewareServices, type ExtractMiddlewareState, type ExtractMiddlewareTypes, type ExtractPluginServices, type ExtractPluginState, type ExtractPluginTypes, type ExtractSSEEvents, type ExtractSSEParams, type ExtractSSEQuery, type ExtractSSERoutes, type FileCache, type FindRouteFilesOptions, ForbiddenError, type ForbiddenErrorDetails, type GetContextFn, type HasSSEMethod, type Http2Options, type HttpMethod, type Infer, type InferContext, type InternalRequestArgs, InternalServerError, type InternalServerErrorDetails, type Matcher, type MergeServices, type MergeStates, type Middleware, MiddlewareAPI, type MiddlewareFunction, type MiddlewareOptions, type MultipartData, type MultipartError, type MultipartLimits, type NetworkErrorContext, type NextFunction, NotFoundError, type NotFoundErrorDetails, type ParseErrorContext, type ParseOptions, type ParseResult, type ParsedRoute, type ParserState, PayloadTooLargeError, type PayloadTooLargeErrorDetails, type Plugin, type PluginFactory, type PluginHooks, type PluginLifecycleManager, type PluginLifecycleOptions, type PluginOptions, PluginsAPI, type ProcessResponseOptions, type ProcessingConfig, type QueryParams, RateLimitError, type RateLimitErrorDetails, type ReconnectStrategy, type RegistryResult, type ReloadMetrics, type RequestHandler, type RequestOptions, type RequestParams, RequestTimeoutError, type Result, type Route, type RouteDefinition, type RouteEntry, type RouteHandler, type RouteMatch, type RouteMethodOptions, type RouteNode, type RouteOptions, type RouteRegistry, type RouteSchema, type Router, RouterAPI, type RouterOptions, type SSEBufferOverflowErrorDetails, type SSEBufferStrategy, type SSEClient, type SSEClientMetrics, type SSEClientOptions, type SSEConnectionErrorContext, type SSEConnectionErrorDetails, type SSEConnectionFactory, type SSEConnectionState, type SSEEvent, type SSEEventHandler, type SSEEventListener, type SSEHeartbeatErrorContext, type SSEMetrics, type SSEOptions, type SSERouteHandler, type SSERouteSchema, type SSESerializedEvent, type SSEStream, type SSEStreamClosedErrorDetails, type SSEStreamErrorContext, type SSEStreamExtended, type SSEStreamManager, type SafeComposeMiddlewareServices, type SafeComposeMiddlewareStates, type SafeComposePluginServices, type SafeComposePluginStates, type SafeExtractMiddlewareServices, type SafeExtractMiddlewareState, type SafeExtractPluginServices, type SafeExtractPluginState, type Server, ServerAPI, type ServerOptions, type ServerOptionsInput, type ServiceNotAvailableDetails, ServiceNotAvailableError, type Services, type StandardErrorResponse, type StartOptions, type State, type StopOptions, type StreamMetrics, type StreamOptions, type TimeoutErrorContext, type TypedSSEStream, UnauthorizedError, type UnauthorizedErrorDetails, type UnifiedRequest, type UnifiedResponse, type UnionToIntersection, type UnknownFunction, type UnknownServer, UnprocessableEntityError, UnsupportedMediaTypeError, type UnsupportedMediaTypeErrorDetails, type UploadProgress, type UploadedFile, VERSION, type ValidationConfig, ValidationError, type ValidationErrorDetails, type ValidationFieldError, type WatchOptions, asMiddlewareArray, asPluginArray, buildUrl, compilePathPattern, compose, cors, createDeleteRoute, createGetRoute, createHeadRoute, createMatcher, create$2 as createMiddleware, createMiddlewareArray, createOptionsRoute, createPatchRoute, create$1 as createPlugin, createPluginArray, createPostRoute, createPutRoute, createRouteFactory, create as createServer, serviceMiddleware as createServiceMiddleware, stateMiddleware as createStateMiddleware, extractParams, getCorrelationId, inferContext, isMiddleware, isPlugin, paramsToQuery };