blaizejs 0.5.2 → 0.6.0
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.
- package/dist/{chunk-EB3TZGU4.js → chunk-5C4WI3A7.js} +3 -3
- package/dist/chunk-EOCNAQ76.js +11 -0
- package/dist/{chunk-DN5WHXRA.js.map → chunk-EOCNAQ76.js.map} +1 -1
- package/dist/{chunk-QYXAQD7H.js → chunk-GNLJMVOB.js} +3 -3
- package/dist/{chunk-RUCGYLJ6.js → chunk-WTCIDURS.js} +3 -3
- package/dist/{chunk-4QEX5ARZ.js → chunk-YE7LYWE6.js} +3 -3
- package/dist/index.cjs +14 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1663 -1467
- package/dist/index.d.ts +1663 -1467
- package/dist/index.js +14 -14
- package/dist/index.js.map +1 -1
- package/dist/{internal-server-error-I43ZDXIR.js → internal-server-error-MFDGHZTW.js} +3 -3
- package/dist/{payload-too-large-error-OQEOP3U2.js → payload-too-large-error-JESAYGED.js} +3 -3
- package/dist/{unsupported-media-type-error-7UF4VYIN.js → unsupported-media-type-error-ZDQCGXCO.js} +3 -3
- package/dist/{validation-error-ZPBPCFKL.js → validation-error-KGPRZ5X7.js} +3 -3
- package/package.json +2 -2
- package/dist/chunk-DN5WHXRA.js +0 -11
- /package/dist/{chunk-EB3TZGU4.js.map → chunk-5C4WI3A7.js.map} +0 -0
- /package/dist/{chunk-QYXAQD7H.js.map → chunk-GNLJMVOB.js.map} +0 -0
- /package/dist/{chunk-RUCGYLJ6.js.map → chunk-WTCIDURS.js.map} +0 -0
- /package/dist/{chunk-4QEX5ARZ.js.map → chunk-YE7LYWE6.js.map} +0 -0
- /package/dist/{internal-server-error-I43ZDXIR.js.map → internal-server-error-MFDGHZTW.js.map} +0 -0
- /package/dist/{payload-too-large-error-OQEOP3U2.js.map → payload-too-large-error-JESAYGED.js.map} +0 -0
- /package/dist/{unsupported-media-type-error-7UF4VYIN.js.map → unsupported-media-type-error-ZDQCGXCO.js.map} +0 -0
- /package/dist/{validation-error-ZPBPCFKL.js.map → validation-error-KGPRZ5X7.js.map} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,1704 +1,1678 @@
|
|
|
1
1
|
import * as zod from 'zod';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import http, { IncomingMessage, ServerResponse } from 'node:http';
|
|
4
|
-
import http2, { Http2ServerRequest, Http2ServerResponse } from 'node:http2';
|
|
3
|
+
import http, { IncomingMessage, ServerResponse, Server as Server$1 } from 'node:http';
|
|
4
|
+
import http2, { Http2ServerRequest, Http2ServerResponse, Http2Server } from 'node:http2';
|
|
5
5
|
import { WriteStream } from 'node:fs';
|
|
6
6
|
import { Readable } from 'node:stream';
|
|
7
7
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
8
8
|
import { EventEmitter } from 'node:events';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
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
|
-
*
|
|
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
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
|
|
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
|
-
*
|
|
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
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* Specialized context for timeout-specific errors with timing information.
|
|
62
|
+
* Result of parsing multipart data with metadata
|
|
84
63
|
*/
|
|
85
|
-
interface
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
*
|
|
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
|
|
105
|
-
/**
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
|
|
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
|
-
*
|
|
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
|
|
129
|
-
/**
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
*
|
|
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
|
|
155
|
-
/**
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
186
|
-
/**
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
173
|
+
hasFoundValidBoundary: boolean;
|
|
303
174
|
/**
|
|
304
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
324
|
-
* Includes correlation ID for easier debugging
|
|
179
|
+
* Whether parsing has reached the end boundary
|
|
325
180
|
*/
|
|
326
|
-
|
|
181
|
+
isFinished: boolean;
|
|
327
182
|
}
|
|
183
|
+
|
|
328
184
|
/**
|
|
329
|
-
*
|
|
185
|
+
* Unified request type supporting both HTTP/1.1 and HTTP/2
|
|
330
186
|
*/
|
|
331
|
-
|
|
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
|
-
*
|
|
189
|
+
* Unified response type supporting both HTTP/1.1 and HTTP/2
|
|
342
190
|
*/
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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
|
-
*
|
|
199
|
+
* Query parameters from URL
|
|
350
200
|
*/
|
|
351
|
-
interface
|
|
352
|
-
|
|
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
|
-
*
|
|
205
|
+
* Options for streaming responses
|
|
369
206
|
*/
|
|
370
|
-
interface
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
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
|
-
*
|
|
213
|
+
* State container for storing request-scoped data
|
|
214
|
+
* Allows for proper typing with generics
|
|
386
215
|
*/
|
|
387
|
-
interface
|
|
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
|
-
*
|
|
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
|
|
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
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
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
|
-
*
|
|
451
|
-
*
|
|
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
|
|
454
|
-
/**
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
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
|
-
/**
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
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
|
-
*
|
|
311
|
+
* Options for creating a context
|
|
482
312
|
*/
|
|
483
|
-
interface
|
|
313
|
+
interface ContextOptions {
|
|
314
|
+
/**
|
|
315
|
+
* Whether to parse the request body
|
|
316
|
+
*/
|
|
317
|
+
parseBody?: boolean;
|
|
484
318
|
/**
|
|
485
|
-
*
|
|
319
|
+
* Initial state to include in the context
|
|
320
|
+
*
|
|
486
321
|
*/
|
|
487
|
-
|
|
322
|
+
initialState?: State;
|
|
488
323
|
/**
|
|
489
|
-
*
|
|
324
|
+
* Initial services to include in the context
|
|
325
|
+
*
|
|
490
326
|
*/
|
|
491
|
-
|
|
327
|
+
initialServices?: Services;
|
|
492
328
|
/**
|
|
493
|
-
*
|
|
329
|
+
* Limits for various body types to prevent abuse
|
|
494
330
|
*/
|
|
495
|
-
|
|
331
|
+
bodyLimits: BodyLimits;
|
|
496
332
|
}
|
|
497
333
|
/**
|
|
498
|
-
*
|
|
334
|
+
* Function to get the current context from AsyncLocalStorage
|
|
499
335
|
*/
|
|
500
|
-
|
|
336
|
+
type GetContextFn = <S extends State = State, Svc extends Services = Services>() => Context<S, Svc> | undefined;
|
|
501
337
|
/**
|
|
502
|
-
*
|
|
338
|
+
* Factory function for creating a new context
|
|
503
339
|
*/
|
|
504
|
-
|
|
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
|
-
*
|
|
342
|
+
* Type representing unknown function
|
|
517
343
|
*
|
|
518
|
-
*
|
|
519
|
-
*
|
|
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
|
-
*
|
|
352
|
+
* Function to pass control to the next middleware
|
|
523
353
|
*/
|
|
524
|
-
|
|
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
|
-
*
|
|
356
|
+
* Middleware function signature
|
|
538
357
|
*/
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
/**
|
|
545
|
-
|
|
546
|
-
/**
|
|
547
|
-
|
|
548
|
-
/**
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
|
|
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
|
-
*
|
|
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
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
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
|
-
*
|
|
386
|
+
* Helper type to extract TypeScript type from Zod schema
|
|
570
387
|
*/
|
|
571
|
-
|
|
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
|
-
*
|
|
390
|
+
* HTTP methods supported by the router
|
|
594
391
|
*/
|
|
595
|
-
|
|
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
|
-
*
|
|
394
|
+
* Schema for route validation with generic type parameters
|
|
611
395
|
*/
|
|
612
|
-
interface
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
/**
|
|
618
|
-
|
|
619
|
-
/**
|
|
620
|
-
|
|
621
|
-
/**
|
|
622
|
-
|
|
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
|
-
*
|
|
413
|
+
* Route handler function with strongly typed params and response
|
|
627
414
|
*/
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
readonly tempPath?: string;
|
|
643
|
-
/** SHA-256 hash of file content (if computed) */
|
|
644
|
-
readonly hash?: string;
|
|
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;
|
|
417
|
+
/**
|
|
418
|
+
* Options for a route method with schema-based type inference
|
|
419
|
+
*/
|
|
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>;
|
|
645
429
|
}
|
|
646
430
|
/**
|
|
647
|
-
*
|
|
431
|
+
* Route definition mapping HTTP methods to handlers
|
|
648
432
|
*/
|
|
649
|
-
interface
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
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>;
|
|
654
441
|
}
|
|
655
442
|
/**
|
|
656
|
-
*
|
|
443
|
+
* Route object with path
|
|
657
444
|
*/
|
|
658
|
-
interface
|
|
659
|
-
/**
|
|
660
|
-
|
|
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;
|
|
445
|
+
interface Route extends RouteDefinition {
|
|
446
|
+
/** Path of the route */
|
|
447
|
+
path: string;
|
|
675
448
|
}
|
|
676
449
|
/**
|
|
677
|
-
*
|
|
450
|
+
* Options for route creation
|
|
678
451
|
*/
|
|
679
|
-
interface
|
|
680
|
-
/**
|
|
681
|
-
|
|
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
|
-
};
|
|
452
|
+
interface RouteOptions {
|
|
453
|
+
/** Base path for the route */
|
|
454
|
+
basePath?: string;
|
|
693
455
|
}
|
|
694
456
|
/**
|
|
695
|
-
*
|
|
457
|
+
* Result type for handling success and error responses
|
|
696
458
|
*/
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
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
|
+
};
|
|
472
|
+
/**
|
|
473
|
+
* Router options
|
|
474
|
+
*/
|
|
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;
|
|
706
482
|
}
|
|
707
483
|
/**
|
|
708
|
-
*
|
|
484
|
+
* Router interface
|
|
709
485
|
*/
|
|
710
|
-
interface
|
|
711
|
-
/**
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
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[];
|
|
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[];
|
|
730
498
|
};
|
|
731
|
-
/**
|
|
732
|
-
|
|
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>;
|
|
733
510
|
}
|
|
734
511
|
/**
|
|
735
|
-
*
|
|
512
|
+
* Route match result
|
|
736
513
|
*/
|
|
737
|
-
interface
|
|
738
|
-
/**
|
|
739
|
-
|
|
740
|
-
/**
|
|
741
|
-
|
|
742
|
-
/**
|
|
743
|
-
|
|
744
|
-
/**
|
|
745
|
-
|
|
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[];
|
|
746
523
|
}
|
|
747
524
|
/**
|
|
748
|
-
*
|
|
525
|
+
* Route matcher interface
|
|
749
526
|
*/
|
|
750
|
-
interface
|
|
751
|
-
/**
|
|
752
|
-
|
|
753
|
-
/**
|
|
754
|
-
|
|
755
|
-
/**
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
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;
|
|
761
547
|
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
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;
|
|
548
|
+
interface ParsedRoute {
|
|
549
|
+
filePath: string;
|
|
550
|
+
routePath: string;
|
|
551
|
+
params: string[];
|
|
797
552
|
}
|
|
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
553
|
/**
|
|
808
|
-
*
|
|
554
|
+
* Node in the radix tree for efficient route matching
|
|
809
555
|
*/
|
|
810
|
-
interface
|
|
811
|
-
|
|
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;
|
|
812
563
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
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;
|
|
818
575
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
status?: number;
|
|
825
|
-
headers?: Record<string, string>;
|
|
576
|
+
interface ErrorHandlerOptions {
|
|
577
|
+
/** Show detailed errors in response */
|
|
578
|
+
detailed?: boolean;
|
|
579
|
+
/** Log errors to console */
|
|
580
|
+
log?: boolean;
|
|
826
581
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
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;
|
|
582
|
+
interface ProcessResponseOptions {
|
|
583
|
+
/** Status code to use if not specified */
|
|
584
|
+
defaultStatus?: number;
|
|
838
585
|
}
|
|
839
586
|
/**
|
|
840
|
-
*
|
|
841
|
-
* Allows middleware to contribute services that are accessible throughout the request lifecycle
|
|
587
|
+
* Standard error response structure
|
|
842
588
|
*/
|
|
843
|
-
interface
|
|
844
|
-
|
|
589
|
+
interface StandardErrorResponse {
|
|
590
|
+
error: string;
|
|
591
|
+
message: string;
|
|
845
592
|
}
|
|
846
|
-
interface
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
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
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
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
|
+
}>;
|
|
882
606
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
*/
|
|
890
|
-
|
|
891
|
-
/**
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
body: TBody;
|
|
896
|
-
query: TQuery;
|
|
897
|
-
};
|
|
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;
|
|
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;
|
|
911
619
|
}
|
|
912
|
-
interface
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
raw: number;
|
|
921
|
-
/** Multipart/form-data limits */
|
|
922
|
-
multipart: MultipartLimits;
|
|
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;
|
|
923
628
|
}
|
|
924
|
-
type MultipartLimits = {
|
|
925
|
-
maxFileSize?: number;
|
|
926
|
-
maxTotalSize?: number;
|
|
927
|
-
maxFiles?: number;
|
|
928
|
-
maxFieldSize?: number;
|
|
929
|
-
};
|
|
930
629
|
/**
|
|
931
|
-
*
|
|
630
|
+
* GET route creator with state and services support
|
|
631
|
+
* Now returns a higher-order function to handle generics properly
|
|
932
632
|
*/
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
* Limits for various body types to prevent abuse
|
|
950
|
-
*/
|
|
951
|
-
bodyLimits: BodyLimits;
|
|
952
|
-
}
|
|
953
|
-
/**
|
|
954
|
-
* Function to get the current context from AsyncLocalStorage
|
|
955
|
-
*/
|
|
956
|
-
type GetContextFn = <S extends State = State, Svc extends Services = Services>() => Context<S, Svc> | undefined;
|
|
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;
|
|
638
|
+
};
|
|
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;
|
|
648
|
+
};
|
|
957
649
|
/**
|
|
958
|
-
*
|
|
650
|
+
* POST route creator with state and services support
|
|
959
651
|
*/
|
|
960
|
-
type
|
|
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;
|
|
658
|
+
};
|
|
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
|
+
};
|
|
961
668
|
/**
|
|
962
|
-
*
|
|
963
|
-
*
|
|
964
|
-
* This is a generic function type that can accept any number of arguments
|
|
965
|
-
* and return any type of value. It is used for type inference in various
|
|
966
|
-
* contexts where the specific function signature is not known or not
|
|
967
|
-
* important.
|
|
669
|
+
* PUT route creator with state and services support
|
|
968
670
|
*/
|
|
969
|
-
type
|
|
970
|
-
|
|
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
|
+
};
|
|
971
687
|
/**
|
|
972
|
-
*
|
|
688
|
+
* DELETE route creator with state and services support
|
|
973
689
|
*/
|
|
974
|
-
type
|
|
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
|
+
};
|
|
975
706
|
/**
|
|
976
|
-
*
|
|
707
|
+
* PATCH route creator with state and services support
|
|
977
708
|
*/
|
|
978
|
-
type
|
|
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
|
+
};
|
|
979
725
|
/**
|
|
980
|
-
*
|
|
726
|
+
* HEAD route creator with state and services support
|
|
981
727
|
*/
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
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
|
+
};
|
|
992
744
|
/**
|
|
993
|
-
*
|
|
994
|
-
* @template TState - Type of state this middleware contributes to the context
|
|
995
|
-
* @template TServices - Type of services this middleware contributes to the context
|
|
745
|
+
* OPTIONS route creator with state and services support
|
|
996
746
|
*/
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
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
|
+
};
|
|
1004
763
|
|
|
1005
764
|
/**
|
|
1006
|
-
*
|
|
765
|
+
* Compose multiple middleware functions into a single middleware function
|
|
1007
766
|
*/
|
|
1008
|
-
|
|
767
|
+
declare function compose(middlewareStack: Middleware[]): MiddlewareFunction;
|
|
768
|
+
|
|
1009
769
|
/**
|
|
1010
|
-
*
|
|
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
|
|
1011
776
|
*/
|
|
1012
|
-
|
|
777
|
+
|
|
1013
778
|
/**
|
|
1014
|
-
*
|
|
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
|
+
* ```
|
|
1015
801
|
*/
|
|
1016
|
-
|
|
1017
|
-
Q extends z.ZodType = z.ZodType<any>, // Query parameters schema
|
|
1018
|
-
B extends z.ZodType = z.ZodType<any>, // Body schema
|
|
1019
|
-
R extends z.ZodType = z.ZodType<any>, // Response schema
|
|
1020
|
-
ED extends z.ZodType = z.ZodType<any>> {
|
|
1021
|
-
/** Parameter schema for validation */
|
|
1022
|
-
params?: P;
|
|
1023
|
-
/** Query schema for validation */
|
|
1024
|
-
query?: Q;
|
|
1025
|
-
/** Body schema for validation */
|
|
1026
|
-
body?: B;
|
|
1027
|
-
/** Response schema for validation */
|
|
1028
|
-
response?: R;
|
|
1029
|
-
/** Error Response Details schema for validation */
|
|
1030
|
-
errorResponseDetails?: ED;
|
|
1031
|
-
}
|
|
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>)>;
|
|
1032
803
|
/**
|
|
1033
|
-
*
|
|
804
|
+
* HTTP methods that can be allowed in CORS
|
|
805
|
+
* Based on W3C CORS specification
|
|
1034
806
|
*/
|
|
1035
|
-
type
|
|
1036
|
-
TServices extends Services = Services> = (ctx: Context<TState, TServices, TBody, TQuery>, params: TParams) => Promise<TResponse> | TResponse;
|
|
807
|
+
type CorsHttpMethod = HttpMethod | 'CONNECT' | 'TRACE';
|
|
1037
808
|
/**
|
|
1038
|
-
*
|
|
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
|
+
* ```
|
|
1039
820
|
*/
|
|
1040
|
-
interface
|
|
1041
|
-
/**
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
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;
|
|
1049
897
|
}
|
|
1050
898
|
/**
|
|
1051
|
-
*
|
|
899
|
+
* Internal CORS validation result
|
|
900
|
+
* Used by middleware implementation
|
|
1052
901
|
*/
|
|
1053
|
-
interface
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
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;
|
|
1061
916
|
}
|
|
1062
917
|
/**
|
|
1063
|
-
*
|
|
918
|
+
* CORS preflight request information
|
|
919
|
+
* Extracted from OPTIONS request headers
|
|
1064
920
|
*/
|
|
1065
|
-
interface
|
|
1066
|
-
/**
|
|
1067
|
-
|
|
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[];
|
|
1068
936
|
}
|
|
1069
937
|
/**
|
|
1070
|
-
*
|
|
938
|
+
* Cache entry for origin validation results
|
|
939
|
+
* Used for performance optimization
|
|
1071
940
|
*/
|
|
1072
|
-
interface
|
|
1073
|
-
/**
|
|
1074
|
-
|
|
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;
|
|
1075
954
|
}
|
|
1076
955
|
/**
|
|
1077
|
-
*
|
|
956
|
+
* Configuration for CORS origin validation cache
|
|
1078
957
|
*/
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
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;
|
|
974
|
+
}
|
|
1092
975
|
/**
|
|
1093
|
-
*
|
|
976
|
+
* Statistics for CORS middleware performance monitoring
|
|
1094
977
|
*/
|
|
1095
|
-
interface
|
|
1096
|
-
/**
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
/**
|
|
1101
|
-
|
|
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;
|
|
1102
1003
|
}
|
|
1103
1004
|
/**
|
|
1104
|
-
*
|
|
1005
|
+
* Cache entry type
|
|
1105
1006
|
*/
|
|
1106
|
-
interface
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
getRoutes: () => Route[];
|
|
1111
|
-
/** Add a route programmatically */
|
|
1112
|
-
addRoute: (route: Route) => void;
|
|
1113
|
-
/** Add multiple routes programmatically with batch processing */
|
|
1114
|
-
addRoutes: (routes: Route[]) => {
|
|
1115
|
-
added: Route[];
|
|
1116
|
-
removed: string[];
|
|
1117
|
-
changed: Route[];
|
|
1118
|
-
};
|
|
1119
|
-
/** Add a route directory for plugins */
|
|
1120
|
-
addRouteDirectory(directory: string, options?: {
|
|
1121
|
-
prefix?: string;
|
|
1122
|
-
}): Promise<void>;
|
|
1123
|
-
/** Get route conflicts */
|
|
1124
|
-
getRouteConflicts(): Array<{
|
|
1125
|
-
path: string;
|
|
1126
|
-
sources: string[];
|
|
1127
|
-
}>;
|
|
1128
|
-
/** Close watchers and cleanup resources */
|
|
1129
|
-
close?: () => Promise<void>;
|
|
1007
|
+
interface CacheEntry {
|
|
1008
|
+
allowed: boolean;
|
|
1009
|
+
expiresAt: number;
|
|
1010
|
+
lastAccessed: number;
|
|
1130
1011
|
}
|
|
1131
1012
|
/**
|
|
1132
|
-
*
|
|
1013
|
+
* Cache configuration
|
|
1133
1014
|
*/
|
|
1134
|
-
interface
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
/** Extracted route parameters */
|
|
1138
|
-
params: Record<string, string>;
|
|
1139
|
-
/** Flag indicating if the path exists but method isn't allowed */
|
|
1140
|
-
methodNotAllowed?: boolean;
|
|
1141
|
-
/** List of allowed methods for this path (when method not allowed) */
|
|
1142
|
-
allowedMethods?: HttpMethod[];
|
|
1015
|
+
interface CacheConfig {
|
|
1016
|
+
ttl: number;
|
|
1017
|
+
maxSize: number;
|
|
1143
1018
|
}
|
|
1019
|
+
|
|
1144
1020
|
/**
|
|
1145
|
-
*
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
*
|
|
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
|
+
* ```
|
|
1175
1055
|
*/
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
paramName: string | null;
|
|
1179
|
-
isWildcard: boolean;
|
|
1180
|
-
children: RouteNode[];
|
|
1181
|
-
handlers: Partial<Record<HttpMethod, RouteMethodOptions>>;
|
|
1182
|
-
pattern: RegExp | null;
|
|
1183
|
-
}
|
|
1184
|
-
interface RouteEntry {
|
|
1185
|
-
/** The route path pattern */
|
|
1186
|
-
path: string;
|
|
1187
|
-
/** The HTTP method */
|
|
1188
|
-
method: HttpMethod;
|
|
1189
|
-
/** The compiled regex pattern */
|
|
1190
|
-
pattern: RegExp;
|
|
1191
|
-
/** The parameter names in order */
|
|
1192
|
-
paramNames: string[];
|
|
1193
|
-
/** The route handler options */
|
|
1194
|
-
routeOptions: RouteMethodOptions;
|
|
1195
|
-
}
|
|
1196
|
-
interface ErrorHandlerOptions {
|
|
1197
|
-
/** Show detailed errors in response */
|
|
1198
|
-
detailed?: boolean;
|
|
1199
|
-
/** Log errors to console */
|
|
1200
|
-
log?: boolean;
|
|
1201
|
-
}
|
|
1202
|
-
interface ProcessResponseOptions {
|
|
1203
|
-
/** Status code to use if not specified */
|
|
1204
|
-
defaultStatus?: number;
|
|
1205
|
-
}
|
|
1056
|
+
declare function cors(userOptions?: CorsOptions | boolean): Middleware;
|
|
1057
|
+
|
|
1206
1058
|
/**
|
|
1207
|
-
*
|
|
1059
|
+
* Create a middleware
|
|
1208
1060
|
*/
|
|
1209
|
-
|
|
1210
|
-
error: string;
|
|
1211
|
-
message: string;
|
|
1212
|
-
}
|
|
1213
|
-
interface FileCache {
|
|
1214
|
-
routes: Route[];
|
|
1215
|
-
timestamp: number;
|
|
1216
|
-
hash: string;
|
|
1217
|
-
}
|
|
1218
|
-
interface ReloadMetrics {
|
|
1219
|
-
fileChanges: number;
|
|
1220
|
-
totalReloadTime: number;
|
|
1221
|
-
averageReloadTime: number;
|
|
1222
|
-
slowReloads: Array<{
|
|
1223
|
-
file: string;
|
|
1224
|
-
time: number;
|
|
1225
|
-
}>;
|
|
1226
|
-
}
|
|
1227
|
-
interface WatchOptions {
|
|
1228
|
-
debounceMs?: number;
|
|
1229
|
-
/** Directories to ignore */
|
|
1230
|
-
ignore?: string[];
|
|
1231
|
-
/** Callback for new routes */
|
|
1232
|
-
onRouteAdded?: (filePath: string, routes: Route[]) => void;
|
|
1233
|
-
/** Callback for changed routes */
|
|
1234
|
-
onRouteChanged?: (filePath: string, routes: Route[]) => void;
|
|
1235
|
-
/** Callback for removed routes */
|
|
1236
|
-
onRouteRemoved?: (filePath: string, routes: Route[]) => void;
|
|
1237
|
-
/** Callback for errors */
|
|
1238
|
-
onError?: (error: Error) => void;
|
|
1239
|
-
}
|
|
1240
|
-
interface RouteRegistry {
|
|
1241
|
-
routesByPath: Map<string, Route>;
|
|
1242
|
-
routesByFile: Map<string, Set<string>>;
|
|
1243
|
-
pathToFile: Map<string, string>;
|
|
1244
|
-
}
|
|
1245
|
-
interface FindRouteFilesOptions {
|
|
1246
|
-
/** Directories to ignore */
|
|
1247
|
-
ignore?: string[] | undefined;
|
|
1248
|
-
}
|
|
1061
|
+
declare function create$1<TState = {}, TServices = {}>(handlerOrOptions: MiddlewareFunction | MiddlewareOptions): Middleware<TState, TServices>;
|
|
1249
1062
|
/**
|
|
1250
|
-
*
|
|
1251
|
-
*
|
|
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
|
+
*
|
|
1252
1070
|
*/
|
|
1253
|
-
|
|
1254
|
-
schema?: {
|
|
1255
|
-
params?: P extends never ? never : P;
|
|
1256
|
-
query?: Q extends never ? never : Q;
|
|
1257
|
-
response?: R extends never ? never : R;
|
|
1258
|
-
};
|
|
1259
|
-
handler: RouteHandler<P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, never, // GET never has body
|
|
1260
|
-
[
|
|
1261
|
-
R
|
|
1262
|
-
] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
|
|
1263
|
-
middleware?: Middleware[];
|
|
1264
|
-
options?: Record<string, unknown>;
|
|
1265
|
-
}) => {
|
|
1266
|
-
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>;
|
|
1267
|
-
path: string;
|
|
1268
|
-
};
|
|
1071
|
+
declare function stateMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<T, {}>;
|
|
1269
1072
|
/**
|
|
1270
|
-
*
|
|
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
|
+
*
|
|
1271
1080
|
*/
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
params?: P extends never ? never : P;
|
|
1275
|
-
query?: Q extends never ? never : Q;
|
|
1276
|
-
body?: B extends never ? never : B;
|
|
1277
|
-
response?: R extends never ? never : R;
|
|
1278
|
-
};
|
|
1279
|
-
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, [
|
|
1280
|
-
R
|
|
1281
|
-
] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
|
|
1282
|
-
middleware?: Middleware[];
|
|
1283
|
-
options?: Record<string, unknown>;
|
|
1284
|
-
}) => {
|
|
1285
|
-
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>;
|
|
1286
|
-
path: string;
|
|
1287
|
-
};
|
|
1081
|
+
declare function serviceMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<{}, T>;
|
|
1082
|
+
|
|
1288
1083
|
/**
|
|
1289
|
-
*
|
|
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.
|
|
1290
1089
|
*/
|
|
1291
|
-
type CreatePutRoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, B = never, R = never>(config: {
|
|
1292
|
-
schema?: {
|
|
1293
|
-
params?: P extends never ? never : P;
|
|
1294
|
-
query?: Q extends never ? never : Q;
|
|
1295
|
-
body?: B extends never ? never : B;
|
|
1296
|
-
response?: R extends never ? never : R;
|
|
1297
|
-
};
|
|
1298
|
-
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, [
|
|
1299
|
-
R
|
|
1300
|
-
] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
|
|
1301
|
-
middleware?: Middleware[];
|
|
1302
|
-
options?: Record<string, unknown>;
|
|
1303
|
-
}) => {
|
|
1304
|
-
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>;
|
|
1305
|
-
path: string;
|
|
1306
|
-
};
|
|
1307
1090
|
/**
|
|
1308
|
-
*
|
|
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
|
+
* ```
|
|
1309
1109
|
*/
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
path: string;
|
|
1325
|
-
};
|
|
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
|
+
}
|
|
1326
1124
|
/**
|
|
1327
|
-
*
|
|
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.
|
|
1328
1129
|
*/
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
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;
|
|
1335
1151
|
};
|
|
1336
|
-
|
|
1337
|
-
R
|
|
1338
|
-
] extends [never] ? void : R extends z.ZodType ? Infer<R> : void, TState, TServices>;
|
|
1339
|
-
middleware?: Middleware[];
|
|
1340
|
-
options?: Record<string, unknown>;
|
|
1341
|
-
}) => {
|
|
1342
|
-
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>;
|
|
1343
|
-
path: string;
|
|
1344
|
-
};
|
|
1152
|
+
}
|
|
1345
1153
|
/**
|
|
1346
|
-
*
|
|
1154
|
+
* Context information for request timeout errors
|
|
1155
|
+
*
|
|
1156
|
+
* Specialized context for timeout-specific errors with timing information.
|
|
1347
1157
|
*/
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
path: string;
|
|
1363
|
-
};
|
|
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
|
+
}
|
|
1364
1172
|
/**
|
|
1365
|
-
*
|
|
1173
|
+
* Context information for response parsing errors
|
|
1174
|
+
*
|
|
1175
|
+
* Used when the client receives a response but cannot parse it properly.
|
|
1366
1176
|
*/
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
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
|
+
}
|
|
1384
1195
|
/**
|
|
1385
|
-
*
|
|
1196
|
+
* Validation error field details
|
|
1197
|
+
*
|
|
1198
|
+
* Structure for field-level validation errors with multiple error messages
|
|
1199
|
+
* per field.
|
|
1386
1200
|
*/
|
|
1387
|
-
|
|
1388
|
-
|
|
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
|
+
}
|
|
1389
1221
|
/**
|
|
1390
|
-
*
|
|
1391
|
-
*
|
|
1392
|
-
* Comprehensive type definitions for W3C-compliant CORS middleware
|
|
1393
|
-
* with support for string, regex, and async function origin validation.
|
|
1222
|
+
* Validation error details structure
|
|
1394
1223
|
*
|
|
1395
|
-
*
|
|
1224
|
+
* Used by ValidationError to provide structured information about
|
|
1225
|
+
* what fields failed validation and why.
|
|
1396
1226
|
*/
|
|
1397
|
-
|
|
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
|
+
}
|
|
1398
1237
|
/**
|
|
1399
|
-
*
|
|
1400
|
-
*
|
|
1401
|
-
* @example
|
|
1402
|
-
* ```typescript
|
|
1403
|
-
* // String origin (exact match)
|
|
1404
|
-
* const origin: CorsOrigin = 'https://example.com';
|
|
1405
|
-
*
|
|
1406
|
-
* // RegExp pattern
|
|
1407
|
-
* const origin: CorsOrigin = /^https:\/\/.*\.example\.com$/;
|
|
1238
|
+
* All available error types in the BlaizeJS framework
|
|
1408
1239
|
*
|
|
1409
|
-
*
|
|
1410
|
-
*
|
|
1411
|
-
* return await checkOriginAllowed(origin, ctx?.state.user);
|
|
1412
|
-
* };
|
|
1240
|
+
* This enum provides both compile-time type safety and runtime values
|
|
1241
|
+
* for error type identification across server and client packages.
|
|
1413
1242
|
*
|
|
1414
|
-
*
|
|
1415
|
-
*
|
|
1416
|
-
*
|
|
1417
|
-
*
|
|
1418
|
-
*
|
|
1419
|
-
*
|
|
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
|
+
* }
|
|
1420
1256
|
* ```
|
|
1421
1257
|
*/
|
|
1422
|
-
|
|
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
|
+
}
|
|
1423
1300
|
/**
|
|
1424
|
-
*
|
|
1425
|
-
*
|
|
1301
|
+
* Error severity levels for logging and monitoring
|
|
1302
|
+
*
|
|
1303
|
+
* Provides a way to categorize errors by their impact and urgency.
|
|
1426
1304
|
*/
|
|
1427
|
-
|
|
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
|
+
}
|
|
1428
1315
|
/**
|
|
1429
|
-
*
|
|
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.
|
|
1430
1321
|
*
|
|
1431
1322
|
* @example
|
|
1432
1323
|
* ```typescript
|
|
1433
|
-
*
|
|
1434
|
-
*
|
|
1435
|
-
*
|
|
1436
|
-
*
|
|
1437
|
-
*
|
|
1438
|
-
*
|
|
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
|
+
* }
|
|
1439
1331
|
* ```
|
|
1332
|
+
*
|
|
1333
|
+
* @template TDetails - Type for error-specific details object
|
|
1440
1334
|
*/
|
|
1441
|
-
|
|
1442
|
-
/**
|
|
1443
|
-
* Configures the Access-Control-Allow-Origin header
|
|
1444
|
-
*
|
|
1445
|
-
* Possible values:
|
|
1446
|
-
* - `true`: Allow all origins (sets to '*' unless credentials is true, then reflects origin)
|
|
1447
|
-
* - `false`: Disable CORS (no headers set)
|
|
1448
|
-
* - `string`: Specific origin to allow
|
|
1449
|
-
* - `RegExp`: Pattern to match origins
|
|
1450
|
-
* - `function`: Custom validation logic
|
|
1451
|
-
* - `array`: Multiple origin configurations
|
|
1452
|
-
*
|
|
1453
|
-
* @default false
|
|
1454
|
-
*/
|
|
1455
|
-
origin?: boolean | CorsOrigin;
|
|
1456
|
-
/**
|
|
1457
|
-
* Configures the Access-Control-Allow-Methods header
|
|
1458
|
-
*
|
|
1459
|
-
* @default ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE']
|
|
1460
|
-
* @example ['GET', 'POST']
|
|
1461
|
-
*/
|
|
1462
|
-
methods?: CorsHttpMethod[] | string;
|
|
1463
|
-
/**
|
|
1464
|
-
* Configures the Access-Control-Allow-Headers header
|
|
1465
|
-
*
|
|
1466
|
-
* Pass an array of allowed headers or a comma-delimited string.
|
|
1467
|
-
*
|
|
1468
|
-
* @default Request's Access-Control-Request-Headers header value
|
|
1469
|
-
* @example ['Content-Type', 'Authorization']
|
|
1470
|
-
*/
|
|
1471
|
-
allowedHeaders?: string[] | string;
|
|
1472
|
-
/**
|
|
1473
|
-
* Configures the Access-Control-Expose-Headers header
|
|
1474
|
-
*
|
|
1475
|
-
* Headers that the browser is allowed to access.
|
|
1476
|
-
*
|
|
1477
|
-
* @default []
|
|
1478
|
-
* @example ['Content-Range', 'X-Content-Range']
|
|
1479
|
-
*/
|
|
1480
|
-
exposedHeaders?: string[] | string;
|
|
1481
|
-
/**
|
|
1482
|
-
* Configures the Access-Control-Allow-Credentials header
|
|
1483
|
-
*
|
|
1484
|
-
* Set to true to allow credentials (cookies, authorization headers, TLS client certificates).
|
|
1485
|
-
* Note: Cannot be used with origin: '*' for security reasons.
|
|
1486
|
-
*
|
|
1487
|
-
* @default false
|
|
1488
|
-
*/
|
|
1489
|
-
credentials?: boolean;
|
|
1490
|
-
/**
|
|
1491
|
-
* Configures the Access-Control-Max-Age header in seconds
|
|
1492
|
-
*
|
|
1493
|
-
* Indicates how long browsers can cache preflight response.
|
|
1494
|
-
* Set to -1 to disable caching.
|
|
1495
|
-
*
|
|
1496
|
-
* @default undefined (browser decides)
|
|
1497
|
-
* @example 86400 // 24 hours
|
|
1498
|
-
*/
|
|
1499
|
-
maxAge?: number;
|
|
1500
|
-
/**
|
|
1501
|
-
* Whether to pass the CORS preflight response to the next handler
|
|
1502
|
-
*
|
|
1503
|
-
* When false, the preflight response is sent immediately.
|
|
1504
|
-
* When true, control passes to the next middleware/handler.
|
|
1505
|
-
*
|
|
1506
|
-
* @default false
|
|
1507
|
-
*/
|
|
1508
|
-
preflightContinue?: boolean;
|
|
1509
|
-
/**
|
|
1510
|
-
* HTTP status code for successful OPTIONS requests
|
|
1511
|
-
*
|
|
1512
|
-
* Some legacy browsers require 200, while 204 is more correct.
|
|
1513
|
-
*
|
|
1514
|
-
* @default 204
|
|
1515
|
-
*/
|
|
1516
|
-
optionsSuccessStatus?: number;
|
|
1517
|
-
}
|
|
1518
|
-
/**
|
|
1519
|
-
* Internal CORS validation result
|
|
1520
|
-
* Used by middleware implementation
|
|
1521
|
-
*/
|
|
1522
|
-
interface CorsValidationResult {
|
|
1335
|
+
declare abstract class BlaizeError<TDetails = unknown> extends Error {
|
|
1523
1336
|
/**
|
|
1524
|
-
*
|
|
1337
|
+
* Error type identifier from the ErrorType enum
|
|
1338
|
+
* Used for programmatic error handling and client-side error routing
|
|
1525
1339
|
*/
|
|
1526
|
-
|
|
1340
|
+
readonly type: ErrorType;
|
|
1527
1341
|
/**
|
|
1528
|
-
*
|
|
1529
|
-
*
|
|
1342
|
+
* Human-readable error title/message
|
|
1343
|
+
* Should be descriptive enough for debugging but safe for end users
|
|
1530
1344
|
*/
|
|
1531
|
-
|
|
1345
|
+
readonly title: string;
|
|
1532
1346
|
/**
|
|
1533
|
-
*
|
|
1347
|
+
* HTTP status code associated with this error
|
|
1348
|
+
* Used by the error boundary to set appropriate response status
|
|
1534
1349
|
*/
|
|
1535
|
-
|
|
1536
|
-
}
|
|
1537
|
-
/**
|
|
1538
|
-
* CORS preflight request information
|
|
1539
|
-
* Extracted from OPTIONS request headers
|
|
1540
|
-
*/
|
|
1541
|
-
interface CorsPreflightInfo {
|
|
1350
|
+
readonly status: number;
|
|
1542
1351
|
/**
|
|
1543
|
-
*
|
|
1352
|
+
* Correlation ID for request tracing
|
|
1353
|
+
* Links this error to the specific request that generated it
|
|
1544
1354
|
*/
|
|
1545
|
-
|
|
1355
|
+
readonly correlationId: string;
|
|
1546
1356
|
/**
|
|
1547
|
-
*
|
|
1548
|
-
*
|
|
1357
|
+
* Timestamp when the error occurred
|
|
1358
|
+
* Useful for debugging and log correlation
|
|
1549
1359
|
*/
|
|
1550
|
-
|
|
1360
|
+
readonly timestamp: Date;
|
|
1551
1361
|
/**
|
|
1552
|
-
*
|
|
1553
|
-
*
|
|
1362
|
+
* Additional error-specific details
|
|
1363
|
+
* Type-safe error context that varies by error type
|
|
1554
1364
|
*/
|
|
1555
|
-
|
|
1556
|
-
}
|
|
1557
|
-
/**
|
|
1558
|
-
* Cache entry for origin validation results
|
|
1559
|
-
* Used for performance optimization
|
|
1560
|
-
*/
|
|
1561
|
-
interface CorsOriginCacheEntry {
|
|
1365
|
+
readonly details?: TDetails | undefined;
|
|
1562
1366
|
/**
|
|
1563
|
-
*
|
|
1367
|
+
* Creates a new BlaizeError instance
|
|
1368
|
+
*
|
|
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
|
|
1564
1374
|
*/
|
|
1565
|
-
|
|
1375
|
+
protected constructor(type: ErrorType, title: string, status: number, correlationId: string, details?: TDetails | undefined);
|
|
1566
1376
|
/**
|
|
1567
|
-
*
|
|
1377
|
+
* Serializes the error to a plain object suitable for HTTP responses
|
|
1378
|
+
*
|
|
1379
|
+
* @returns Object representation of the error
|
|
1568
1380
|
*/
|
|
1569
|
-
|
|
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
|
+
};
|
|
1570
1395
|
/**
|
|
1571
|
-
*
|
|
1396
|
+
* Returns a string representation of the error
|
|
1397
|
+
* Includes correlation ID for easier debugging
|
|
1572
1398
|
*/
|
|
1573
|
-
|
|
1399
|
+
toString(): string;
|
|
1574
1400
|
}
|
|
1575
1401
|
/**
|
|
1576
|
-
*
|
|
1402
|
+
* Interface for payload too large error details
|
|
1577
1403
|
*/
|
|
1578
|
-
interface
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
* Maximum number of entries in the cache
|
|
1586
|
-
* @default 1000
|
|
1587
|
-
*/
|
|
1404
|
+
interface PayloadTooLargeErrorDetails {
|
|
1405
|
+
fileCount?: number;
|
|
1406
|
+
maxFiles?: number;
|
|
1407
|
+
filename?: string;
|
|
1408
|
+
field?: string;
|
|
1409
|
+
contentType?: string;
|
|
1410
|
+
currentSize?: number;
|
|
1588
1411
|
maxSize?: number;
|
|
1589
|
-
/**
|
|
1590
|
-
* Whether to include user ID in cache key
|
|
1591
|
-
* @default true
|
|
1592
|
-
*/
|
|
1593
|
-
includeUserId?: boolean;
|
|
1594
1412
|
}
|
|
1595
1413
|
/**
|
|
1596
|
-
*
|
|
1414
|
+
* Interface for unsupported media type error details
|
|
1597
1415
|
*/
|
|
1598
|
-
interface
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
/**
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
/**
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
/**
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
/**
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
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;
|
|
1521
|
+
}
|
|
1522
|
+
/**
|
|
1523
|
+
* Interface for NotFound error details
|
|
1524
|
+
* Provides context about the missing resource
|
|
1525
|
+
*/
|
|
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;
|
|
1623
1552
|
}
|
|
1624
1553
|
/**
|
|
1625
|
-
*
|
|
1554
|
+
* Context information for error transformation
|
|
1626
1555
|
*/
|
|
1627
|
-
interface
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
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;
|
|
1631
1566
|
}
|
|
1632
1567
|
/**
|
|
1633
|
-
*
|
|
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.
|
|
1634
1572
|
*/
|
|
1635
|
-
|
|
1636
|
-
|
|
1573
|
+
/**
|
|
1574
|
+
* Details for SSE connection errors
|
|
1575
|
+
*/
|
|
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;
|
|
1587
|
+
}
|
|
1588
|
+
/**
|
|
1589
|
+
* Details for SSE buffer overflow errors
|
|
1590
|
+
*/
|
|
1591
|
+
interface SSEBufferOverflowErrorDetails {
|
|
1592
|
+
/** Client identifier */
|
|
1593
|
+
clientId?: string;
|
|
1594
|
+
/** Current buffer size when overflow occurred */
|
|
1595
|
+
currentSize: number;
|
|
1596
|
+
/** Maximum buffer size configured */
|
|
1637
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;
|
|
1638
1604
|
}
|
|
1639
|
-
|
|
1640
1605
|
/**
|
|
1641
|
-
*
|
|
1642
|
-
*
|
|
1643
|
-
* @param userOptions - CORS configuration options or boolean
|
|
1644
|
-
* @returns Middleware function that handles CORS
|
|
1645
|
-
*
|
|
1646
|
-
* @example
|
|
1647
|
-
* ```typescript
|
|
1648
|
-
* import { cors } from '@blaize-core/middleware/cors';
|
|
1649
|
-
*
|
|
1650
|
-
* // Development mode - allow all origins
|
|
1651
|
-
* server.use(cors(true));
|
|
1652
|
-
*
|
|
1653
|
-
* // Production - specific origin
|
|
1654
|
-
* server.use(cors({
|
|
1655
|
-
* origin: 'https://app.example.com',
|
|
1656
|
-
* credentials: true,
|
|
1657
|
-
* maxAge: 86400
|
|
1658
|
-
* }));
|
|
1659
|
-
*
|
|
1660
|
-
* // Multiple origins with regex
|
|
1661
|
-
* server.use(cors({
|
|
1662
|
-
* origin: [
|
|
1663
|
-
* 'https://app.example.com',
|
|
1664
|
-
* /^https:\/\/.*\.example\.com$/
|
|
1665
|
-
* ]
|
|
1666
|
-
* }));
|
|
1667
|
-
*
|
|
1668
|
-
* // Dynamic origin validation
|
|
1669
|
-
* server.use(cors({
|
|
1670
|
-
* origin: async (origin, ctx) => {
|
|
1671
|
-
* return await checkOriginAllowed(origin, ctx.state.user);
|
|
1672
|
-
* }
|
|
1673
|
-
* }));
|
|
1674
|
-
* ```
|
|
1606
|
+
* Details for SSE stream closed errors
|
|
1675
1607
|
*/
|
|
1676
|
-
|
|
1677
|
-
|
|
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
|
+
}
|
|
1678
1620
|
/**
|
|
1679
|
-
*
|
|
1621
|
+
* Context for SSE connection errors
|
|
1680
1622
|
*/
|
|
1681
|
-
|
|
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
|
+
}
|
|
1682
1644
|
/**
|
|
1683
|
-
*
|
|
1684
|
-
* Convenience helper for state-only middleware
|
|
1685
|
-
*
|
|
1686
|
-
* @template T - Type of state to contribute
|
|
1687
|
-
* @param handler - Middleware function that adds state
|
|
1688
|
-
* @returns Middleware that contributes state only
|
|
1689
|
-
*
|
|
1645
|
+
* Context for SSE stream errors (server-sent errors)
|
|
1690
1646
|
*/
|
|
1691
|
-
|
|
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
|
+
}
|
|
1692
1661
|
/**
|
|
1693
|
-
*
|
|
1694
|
-
* Convenience helper for service-only middleware
|
|
1695
|
-
*
|
|
1696
|
-
* @template T - Type of services to contribute
|
|
1697
|
-
* @param handler - Middleware function that adds services
|
|
1698
|
-
* @returns Middleware that contributes services only
|
|
1699
|
-
*
|
|
1662
|
+
* Context for SSE heartbeat timeout errors
|
|
1700
1663
|
*/
|
|
1701
|
-
|
|
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
|
+
}
|
|
1702
1676
|
|
|
1703
1677
|
/**
|
|
1704
1678
|
* Represents a single Server-Sent Event
|
|
@@ -2496,28 +2470,179 @@ interface PluginOptions<_T = any> {
|
|
|
2496
2470
|
[key: string]: any;
|
|
2497
2471
|
}
|
|
2498
2472
|
/**
|
|
2499
|
-
* Plugin lifecycle hooks
|
|
2473
|
+
* Plugin lifecycle hooks with full type safety
|
|
2474
|
+
*
|
|
2475
|
+
* Plugins execute in this order:
|
|
2476
|
+
* 1. register() - Add middleware, routes
|
|
2477
|
+
* 2. initialize() - Create resources
|
|
2478
|
+
* 3. onServerStart() - Start background work
|
|
2479
|
+
* 4. onServerStop() - Stop background work
|
|
2480
|
+
* 5. terminate() - Cleanup resources
|
|
2481
|
+
*/
|
|
2482
|
+
interface PluginHooks<TState = {}, TServices = {}> {
|
|
2483
|
+
/**
|
|
2484
|
+
* Called when plugin is registered to server
|
|
2485
|
+
*
|
|
2486
|
+
* Use this hook to:
|
|
2487
|
+
* - Add middleware via server.use()
|
|
2488
|
+
* - Add routes via server.router.addRoute()
|
|
2489
|
+
* - Subscribe to server events
|
|
2490
|
+
*
|
|
2491
|
+
* @param server - BlaizeJS server instance
|
|
2492
|
+
* @example
|
|
2493
|
+
* ```typescript
|
|
2494
|
+
* register: async (server) => {
|
|
2495
|
+
* server.use(createMiddleware({
|
|
2496
|
+
* handler: async (ctx, next) => {
|
|
2497
|
+
* ctx.services.db = db;
|
|
2498
|
+
* await next();
|
|
2499
|
+
* },
|
|
2500
|
+
* }));
|
|
2501
|
+
* }
|
|
2502
|
+
* ```
|
|
2503
|
+
*/
|
|
2504
|
+
register?: (server: Server<TState, TServices>) => void | Promise<void>;
|
|
2505
|
+
/**
|
|
2506
|
+
* Called during server initialization
|
|
2507
|
+
*
|
|
2508
|
+
* Use this hook to:
|
|
2509
|
+
* - Create database connections
|
|
2510
|
+
* - Initialize services
|
|
2511
|
+
* - Allocate resources
|
|
2512
|
+
*
|
|
2513
|
+
* @example
|
|
2514
|
+
* ```typescript
|
|
2515
|
+
* initialize: async () => {
|
|
2516
|
+
* db = await Database.connect(config);
|
|
2517
|
+
* }
|
|
2518
|
+
* ```
|
|
2519
|
+
*/
|
|
2520
|
+
initialize?: (server: Server<TState, TServices>) => void | Promise<void>;
|
|
2521
|
+
/**
|
|
2522
|
+
* Called when server starts listening
|
|
2523
|
+
*
|
|
2524
|
+
* Use this hook to:
|
|
2525
|
+
* - Start background workers
|
|
2526
|
+
* - Start cron jobs
|
|
2527
|
+
* - Begin health checks
|
|
2528
|
+
*
|
|
2529
|
+
* @example
|
|
2530
|
+
* ```typescript
|
|
2531
|
+
* onServerStart: async () => {
|
|
2532
|
+
* worker = new BackgroundWorker();
|
|
2533
|
+
* await worker.start();
|
|
2534
|
+
* }
|
|
2535
|
+
* ```
|
|
2536
|
+
*/
|
|
2537
|
+
onServerStart?: (server: Http2Server | Server$1) => void | Promise<void>;
|
|
2538
|
+
/**
|
|
2539
|
+
* Called when server stops listening
|
|
2540
|
+
*
|
|
2541
|
+
* Use this hook to:
|
|
2542
|
+
* - Stop background workers
|
|
2543
|
+
* - Flush buffers
|
|
2544
|
+
* - Complete in-flight work
|
|
2545
|
+
*
|
|
2546
|
+
* @example
|
|
2547
|
+
* ```typescript
|
|
2548
|
+
* onServerStop: async () => {
|
|
2549
|
+
* await worker.stop({ graceful: true });
|
|
2550
|
+
* }
|
|
2551
|
+
* ```
|
|
2552
|
+
*/
|
|
2553
|
+
onServerStop?: (server: Http2Server | Server$1) => void | Promise<void>;
|
|
2554
|
+
/**
|
|
2555
|
+
* Called during server termination
|
|
2556
|
+
*
|
|
2557
|
+
* Use this hook to:
|
|
2558
|
+
* - Close database connections
|
|
2559
|
+
* - Release file handles
|
|
2560
|
+
* - Free memory
|
|
2561
|
+
*
|
|
2562
|
+
* @example
|
|
2563
|
+
* ```typescript
|
|
2564
|
+
* terminate: async () => {
|
|
2565
|
+
* await db?.close();
|
|
2566
|
+
* }
|
|
2567
|
+
* ```
|
|
2568
|
+
*/
|
|
2569
|
+
terminate?: (server: Server<TState, TServices>) => void | Promise<void>;
|
|
2570
|
+
}
|
|
2571
|
+
/**
|
|
2572
|
+
* Options for creating a plugin with createPlugin()
|
|
2573
|
+
*
|
|
2574
|
+
* @template TConfig - Plugin configuration shape
|
|
2575
|
+
* @template TState - State added to context
|
|
2576
|
+
* @template TServices - Services added to context
|
|
2500
2577
|
*/
|
|
2501
|
-
interface
|
|
2502
|
-
/**
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2578
|
+
interface CreatePluginOptions<TConfig, TState = {}, TServices = {}> {
|
|
2579
|
+
/**
|
|
2580
|
+
* Plugin name (e.g., '@blaizejs/metrics')
|
|
2581
|
+
* Must be unique within a server instance
|
|
2582
|
+
*/
|
|
2583
|
+
name: string;
|
|
2584
|
+
/**
|
|
2585
|
+
* Semantic version (e.g., '1.0.0')
|
|
2586
|
+
* Used for compatibility checks
|
|
2587
|
+
*/
|
|
2588
|
+
version: string;
|
|
2589
|
+
/**
|
|
2590
|
+
* Default configuration values
|
|
2591
|
+
* Merged with user config when plugin is created
|
|
2592
|
+
*
|
|
2593
|
+
* @example
|
|
2594
|
+
* ```typescript
|
|
2595
|
+
* defaultConfig: {
|
|
2596
|
+
* enabled: true,
|
|
2597
|
+
* timeout: 30000,
|
|
2598
|
+
* }
|
|
2599
|
+
* ```
|
|
2600
|
+
*/
|
|
2601
|
+
defaultConfig?: TConfig;
|
|
2602
|
+
/**
|
|
2603
|
+
* Setup function that returns lifecycle hooks
|
|
2604
|
+
*
|
|
2605
|
+
* Receives merged config (defaultConfig + userConfig).
|
|
2606
|
+
* Returns partial hook object - all hooks optional.
|
|
2607
|
+
*
|
|
2608
|
+
* @param config - Merged configuration
|
|
2609
|
+
* @returns Partial plugin hooks
|
|
2610
|
+
*
|
|
2611
|
+
* @example
|
|
2612
|
+
* ```typescript
|
|
2613
|
+
* setup: (config) => {
|
|
2614
|
+
* let db: Database;
|
|
2615
|
+
*
|
|
2616
|
+
* return {
|
|
2617
|
+
* initialize: async () => {
|
|
2618
|
+
* db = await Database.connect(config);
|
|
2619
|
+
* },
|
|
2620
|
+
* terminate: async () => {
|
|
2621
|
+
* await db?.close();
|
|
2622
|
+
* },
|
|
2623
|
+
* };
|
|
2624
|
+
* }
|
|
2625
|
+
* ```
|
|
2626
|
+
*/
|
|
2627
|
+
setup: (config: TConfig) => Partial<PluginHooks<TState, TServices>>;
|
|
2512
2628
|
}
|
|
2513
2629
|
/**
|
|
2514
2630
|
* Plugin interface
|
|
2515
2631
|
*/
|
|
2516
|
-
interface Plugin<TState = {}, TServices = {}> extends PluginHooks {
|
|
2632
|
+
interface Plugin<TState = {}, TServices = {}> extends PluginHooks<TState, TServices> {
|
|
2517
2633
|
/** Plugin name */
|
|
2518
2634
|
name: string;
|
|
2519
2635
|
/** Plugin version */
|
|
2520
2636
|
version: string;
|
|
2637
|
+
/**
|
|
2638
|
+
* Called when plugin is registered to server
|
|
2639
|
+
*
|
|
2640
|
+
* This hook is always present - createPlugin provides a default empty async function
|
|
2641
|
+
* if not specified by the plugin author.
|
|
2642
|
+
*
|
|
2643
|
+
* @override Makes register required (not optional like in PluginHooks)
|
|
2644
|
+
*/
|
|
2645
|
+
register: (server: Server<TState, TServices>) => void | Promise<void>;
|
|
2521
2646
|
/**
|
|
2522
2647
|
* Type carriers for compile-time type information
|
|
2523
2648
|
* These are never used at runtime but allow TypeScript to track types
|
|
@@ -2528,7 +2653,7 @@ interface Plugin<TState = {}, TServices = {}> extends PluginHooks {
|
|
|
2528
2653
|
/**
|
|
2529
2654
|
* Plugin factory function
|
|
2530
2655
|
*/
|
|
2531
|
-
type PluginFactory<TConfig = any, TState = {}, TServices = {}> = (options?: TConfig) => Plugin<TState, TServices>;
|
|
2656
|
+
type PluginFactory<TConfig = any, TState = {}, TServices = {}> = (options?: Partial<TConfig>) => Plugin<TState, TServices>;
|
|
2532
2657
|
interface PluginLifecycleManager {
|
|
2533
2658
|
initializePlugins(server: Server<any, any>): Promise<void>;
|
|
2534
2659
|
terminatePlugins(server: Server<any, any>): Promise<void>;
|
|
@@ -2788,9 +2913,80 @@ declare function createMiddlewareArray<T extends ReadonlyArray<Middleware>>(...m
|
|
|
2788
2913
|
declare function createPluginArray<T extends ReadonlyArray<Plugin<any, any>>>(...plugins: T): T;
|
|
2789
2914
|
|
|
2790
2915
|
/**
|
|
2791
|
-
* Create a plugin with
|
|
2916
|
+
* Create a type-safe plugin with full IntelliSense support
|
|
2917
|
+
*
|
|
2918
|
+
* This is the primary way to create plugins in BlaizeJS. It provides:
|
|
2919
|
+
* - IntelliSense for all lifecycle hooks
|
|
2920
|
+
* - Automatic config merging with defaults
|
|
2921
|
+
* - Full type safety for state and services
|
|
2922
|
+
* - Consistent DX with createMiddleware
|
|
2923
|
+
*
|
|
2924
|
+
* @template TConfig - Plugin configuration shape
|
|
2925
|
+
* @template TState - State added to context (default: {})
|
|
2926
|
+
* @template TServices - Services added to context (default: {})
|
|
2927
|
+
*
|
|
2928
|
+
* @param options - Plugin creation options
|
|
2929
|
+
* @returns Plugin factory function
|
|
2930
|
+
*
|
|
2931
|
+
* @example Basic plugin with config
|
|
2932
|
+
* ```typescript
|
|
2933
|
+
* const createDbPlugin = createPlugin<
|
|
2934
|
+
* { host: string; port: number },
|
|
2935
|
+
* {},
|
|
2936
|
+
* { db: Database }
|
|
2937
|
+
* >({
|
|
2938
|
+
* name: '@my-app/database',
|
|
2939
|
+
* version: '1.0.0',
|
|
2940
|
+
* defaultConfig: {
|
|
2941
|
+
* host: 'localhost',
|
|
2942
|
+
* port: 5432,
|
|
2943
|
+
* },
|
|
2944
|
+
* setup: (config) => {
|
|
2945
|
+
* let db: Database;
|
|
2946
|
+
*
|
|
2947
|
+
* return {
|
|
2948
|
+
* register: async (server) => {
|
|
2949
|
+
* // Add typed middleware
|
|
2950
|
+
* server.use(createMiddleware<{}, { db: Database }>({
|
|
2951
|
+
* handler: async (ctx, next) => {
|
|
2952
|
+
* ctx.services.db = db;
|
|
2953
|
+
* await next();
|
|
2954
|
+
* },
|
|
2955
|
+
* }));
|
|
2956
|
+
* },
|
|
2957
|
+
*
|
|
2958
|
+
* initialize: async () => {
|
|
2959
|
+
* db = await Database.connect(config);
|
|
2960
|
+
* },
|
|
2961
|
+
*
|
|
2962
|
+
* terminate: async () => {
|
|
2963
|
+
* await db?.close();
|
|
2964
|
+
* },
|
|
2965
|
+
* };
|
|
2966
|
+
* },
|
|
2967
|
+
* });
|
|
2968
|
+
*
|
|
2969
|
+
* // Usage
|
|
2970
|
+
* const plugin = createDbPlugin({ host: 'prod.db.com' });
|
|
2971
|
+
* ```
|
|
2972
|
+
*
|
|
2973
|
+
* @example Simple plugin without config
|
|
2974
|
+
* ```typescript
|
|
2975
|
+
* const loggerPlugin = createPlugin<{}, {}, { logger: Logger }>({
|
|
2976
|
+
* name: '@my-app/logger',
|
|
2977
|
+
* version: '1.0.0',
|
|
2978
|
+
* setup: () => ({
|
|
2979
|
+
* initialize: async () => {
|
|
2980
|
+
* console.log('Logger initialized');
|
|
2981
|
+
* },
|
|
2982
|
+
* }),
|
|
2983
|
+
* });
|
|
2984
|
+
*
|
|
2985
|
+
* // Usage (no config needed)
|
|
2986
|
+
* const plugin = loggerPlugin();
|
|
2987
|
+
* ```
|
|
2792
2988
|
*/
|
|
2793
|
-
declare function
|
|
2989
|
+
declare function createPlugin<TConfig = {}, TState = {}, TServices = {}>(options: CreatePluginOptions<TConfig, TState, TServices>): PluginFactory<TConfig, TState, TServices>;
|
|
2794
2990
|
|
|
2795
2991
|
/**
|
|
2796
2992
|
* Create a GET route
|
|
@@ -3381,22 +3577,22 @@ declare const RouterAPI: {
|
|
|
3381
3577
|
buildUrl: typeof buildUrl;
|
|
3382
3578
|
};
|
|
3383
3579
|
declare const MiddlewareAPI: {
|
|
3384
|
-
createMiddleware: typeof create$
|
|
3580
|
+
createMiddleware: typeof create$1;
|
|
3385
3581
|
createServiceMiddleware: typeof serviceMiddleware;
|
|
3386
3582
|
createStateMiddleware: typeof stateMiddleware;
|
|
3387
3583
|
compose: typeof compose;
|
|
3388
3584
|
cors: typeof cors;
|
|
3389
3585
|
};
|
|
3390
3586
|
declare const PluginsAPI: {
|
|
3391
|
-
createPlugin: typeof
|
|
3587
|
+
createPlugin: typeof createPlugin;
|
|
3392
3588
|
};
|
|
3393
3589
|
|
|
3394
3590
|
declare const Blaize: {
|
|
3395
3591
|
createServer: typeof create;
|
|
3396
|
-
createMiddleware: typeof create$
|
|
3592
|
+
createMiddleware: typeof create$1;
|
|
3397
3593
|
createServiceMiddleware: typeof serviceMiddleware;
|
|
3398
3594
|
createStateMiddleware: typeof stateMiddleware;
|
|
3399
|
-
createPlugin: typeof
|
|
3595
|
+
createPlugin: typeof createPlugin;
|
|
3400
3596
|
getCorrelationId: typeof getCorrelationId;
|
|
3401
3597
|
Server: {
|
|
3402
3598
|
createServer: typeof create;
|
|
@@ -3418,16 +3614,16 @@ declare const Blaize: {
|
|
|
3418
3614
|
buildUrl: typeof buildUrl;
|
|
3419
3615
|
};
|
|
3420
3616
|
Middleware: {
|
|
3421
|
-
createMiddleware: typeof create$
|
|
3617
|
+
createMiddleware: typeof create$1;
|
|
3422
3618
|
createServiceMiddleware: typeof serviceMiddleware;
|
|
3423
3619
|
createStateMiddleware: typeof stateMiddleware;
|
|
3424
3620
|
compose: typeof compose;
|
|
3425
3621
|
cors: typeof cors;
|
|
3426
3622
|
};
|
|
3427
3623
|
Plugins: {
|
|
3428
|
-
createPlugin: typeof
|
|
3624
|
+
createPlugin: typeof createPlugin;
|
|
3429
3625
|
};
|
|
3430
3626
|
VERSION: string;
|
|
3431
3627
|
};
|
|
3432
3628
|
|
|
3433
|
-
export { Blaize, BlaizeError, type BlaizeErrorResponse, type BodyLimits, type
|
|
3629
|
+
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 CreatePluginOptions, 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$1 as createMiddleware, createMiddlewareArray, createOptionsRoute, createPatchRoute, createPlugin, createPluginArray, createPostRoute, createPutRoute, createRouteFactory, create as createServer, serviceMiddleware as createServiceMiddleware, stateMiddleware as createStateMiddleware, extractParams, getCorrelationId, inferContext, isMiddleware, isPlugin, paramsToQuery };
|