blaizejs 0.6.0 → 0.7.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.
Files changed (25) hide show
  1. package/dist/{chunk-5C4WI3A7.js → chunk-CM6LIHRF.js} +3 -3
  2. package/dist/{chunk-GNLJMVOB.js → chunk-FLI2OVQ5.js} +3 -3
  3. package/dist/{chunk-YE7LYWE6.js → chunk-HQRQVJL6.js} +3 -3
  4. package/dist/{chunk-WTCIDURS.js → chunk-J5FJFX2G.js} +3 -3
  5. package/dist/{chunk-EOCNAQ76.js → chunk-MZG6O7BX.js} +2 -2
  6. package/dist/{chunk-EOCNAQ76.js.map → chunk-MZG6O7BX.js.map} +1 -1
  7. package/dist/index.cjs +16 -14
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +2509 -1406
  10. package/dist/index.d.ts +2509 -1406
  11. package/dist/index.js +17 -15
  12. package/dist/index.js.map +1 -1
  13. package/dist/{internal-server-error-MFDGHZTW.js → internal-server-error-RRNSAEYK.js} +3 -3
  14. package/dist/{payload-too-large-error-JESAYGED.js → payload-too-large-error-SQMCGPZ7.js} +3 -3
  15. package/dist/{unsupported-media-type-error-ZDQCGXCO.js → unsupported-media-type-error-6T47SVVY.js} +3 -3
  16. package/dist/{validation-error-KGPRZ5X7.js → validation-error-DRCBJ7IF.js} +3 -3
  17. package/package.json +2 -2
  18. /package/dist/{chunk-5C4WI3A7.js.map → chunk-CM6LIHRF.js.map} +0 -0
  19. /package/dist/{chunk-GNLJMVOB.js.map → chunk-FLI2OVQ5.js.map} +0 -0
  20. /package/dist/{chunk-YE7LYWE6.js.map → chunk-HQRQVJL6.js.map} +0 -0
  21. /package/dist/{chunk-WTCIDURS.js.map → chunk-J5FJFX2G.js.map} +0 -0
  22. /package/dist/{internal-server-error-MFDGHZTW.js.map → internal-server-error-RRNSAEYK.js.map} +0 -0
  23. /package/dist/{payload-too-large-error-JESAYGED.js.map → payload-too-large-error-SQMCGPZ7.js.map} +0 -0
  24. /package/dist/{unsupported-media-type-error-ZDQCGXCO.js.map → unsupported-media-type-error-6T47SVVY.js.map} +0 -0
  25. /package/dist/{validation-error-KGPRZ5X7.js.map → validation-error-DRCBJ7IF.js.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -7,6 +7,546 @@ import { Readable } from 'node:stream';
7
7
  import { AsyncLocalStorage } from 'node:async_hooks';
8
8
  import { EventEmitter } from 'node:events';
9
9
 
10
+ /**
11
+ * Logger Type Interfaces for BlaizeJS
12
+ *
13
+ * Comprehensive type definitions for the structured logging system.
14
+ * Integrates with the context system via ctx.services.log and supports
15
+ * request-scoped child loggers with automatic correlation ID propagation.
16
+ *
17
+ * @packageDocumentation
18
+ * @since 0.5.0
19
+ */
20
+ /**
21
+ * Log levels supported by the logger system
22
+ *
23
+ * Levels in order of severity (lowest to highest):
24
+ * - `debug`: Detailed diagnostic information for development
25
+ * - `info`: General informational messages about application flow
26
+ * - `warn`: Warning messages for potentially harmful situations
27
+ * - `error`: Error messages for failures that don't stop the application
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const level: LogLevel = 'info';
32
+ * ```
33
+ */
34
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error';
35
+ /**
36
+ * Arbitrary metadata that can be attached to log entries
37
+ *
38
+ * Used to add structured context to logs. Keys are strings and values
39
+ * can be any JSON-serializable data. The logger will handle Error objects
40
+ * specially by extracting message, stack, and name properties.
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * const meta: LogMetadata = {
45
+ * userId: '123',
46
+ * action: 'login',
47
+ * duration: 145,
48
+ * tags: ['auth', 'success']
49
+ * };
50
+ * ```
51
+ */
52
+ interface LogMetadata {
53
+ [key: string]: unknown;
54
+ }
55
+ /**
56
+ * Core logger interface implemented by the Logger class
57
+ *
58
+ * Provides structured logging with automatic metadata enrichment,
59
+ * child logger creation for request-scoped logging, and graceful
60
+ * shutdown support via flush().
61
+ *
62
+ * The logger is available in all route handlers via `ctx.services.log`
63
+ * and automatically includes request context (correlationId, method, path).
64
+ *
65
+ * @example Basic Usage
66
+ * ```typescript
67
+ * // In route handler
68
+ * export const GET = appRoute.get({
69
+ * handler: async (ctx) => {
70
+ * ctx.services.log.info('User requested profile', {
71
+ * userId: ctx.params.userId
72
+ * });
73
+ *
74
+ * try {
75
+ * const user = await getUser(ctx.params.userId);
76
+ * return user;
77
+ * } catch (error) {
78
+ * ctx.services.log.error('Failed to fetch user', {
79
+ * userId: ctx.params.userId,
80
+ * error
81
+ * });
82
+ * throw error;
83
+ * }
84
+ * }
85
+ * });
86
+ * ```
87
+ *
88
+ * @example Child Loggers
89
+ * ```typescript
90
+ * // Create a child logger with additional context
91
+ * const dbLogger = ctx.services.log.child({
92
+ * component: 'database',
93
+ * operation: 'user-lookup'
94
+ * });
95
+ *
96
+ * dbLogger.debug('Executing query', { query: 'SELECT * FROM users' });
97
+ * // Output includes: { component: 'database', operation: 'user-lookup', ... }
98
+ * ```
99
+ */
100
+ interface BlaizeLogger {
101
+ /**
102
+ * Log a debug message
103
+ *
104
+ * Use for detailed diagnostic information during development.
105
+ * These logs are typically disabled in production environments.
106
+ *
107
+ * @param message - The log message
108
+ * @param meta - Optional metadata to attach
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * ctx.services.log.debug('Cache lookup', {
113
+ * key: 'user:123',
114
+ * hit: true,
115
+ * ttl: 3600
116
+ * });
117
+ * ```
118
+ */
119
+ debug(message: string, meta?: LogMetadata): void;
120
+ /**
121
+ * Log an info message
122
+ *
123
+ * Use for general informational messages about application flow.
124
+ * This is the default log level for production environments.
125
+ *
126
+ * @param message - The log message
127
+ * @param meta - Optional metadata to attach
128
+ *
129
+ * @example
130
+ * ```typescript
131
+ * ctx.services.log.info('User login successful', {
132
+ * userId: '123',
133
+ * method: 'oauth',
134
+ * provider: 'google'
135
+ * });
136
+ * ```
137
+ */
138
+ info(message: string, meta?: LogMetadata): void;
139
+ /**
140
+ * Log a warning message
141
+ *
142
+ * Use for potentially harmful situations that don't prevent
143
+ * the application from functioning.
144
+ *
145
+ * @param message - The log message
146
+ * @param meta - Optional metadata to attach
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * ctx.services.log.warn('Rate limit approaching threshold', {
151
+ * userId: '123',
152
+ * currentCount: 95,
153
+ * limit: 100
154
+ * });
155
+ * ```
156
+ */
157
+ warn(message: string, meta?: LogMetadata): void;
158
+ /**
159
+ * Log an error message
160
+ *
161
+ * Use for error conditions that don't stop the application.
162
+ * The logger automatically extracts stack traces from Error objects.
163
+ *
164
+ * @param message - The log message
165
+ * @param meta - Optional metadata to attach
166
+ *
167
+ * @example
168
+ * ```typescript
169
+ * ctx.services.log.error('Database query failed', {
170
+ * query: 'SELECT * FROM users',
171
+ * error: err, // Error object - stack trace will be extracted
172
+ * retryCount: 3
173
+ * });
174
+ * ```
175
+ */
176
+ error(message: string, meta?: LogMetadata): void;
177
+ /**
178
+ * Create a child logger with inherited metadata
179
+ *
180
+ * Child loggers inherit all metadata from their parent and add
181
+ * their own. This is useful for adding component-specific context
182
+ * without polluting the parent logger.
183
+ *
184
+ * Child metadata overrides parent metadata for the same keys.
185
+ *
186
+ * @param meta - Metadata to add to all logs from this child
187
+ * @returns A new logger instance with merged metadata
188
+ *
189
+ * @example Component-Scoped Logging
190
+ * ```typescript
191
+ * // Create a child logger for a specific component
192
+ * const authLogger = ctx.services.log.child({
193
+ * component: 'auth',
194
+ * action: 'verify-token'
195
+ * });
196
+ *
197
+ * authLogger.debug('Verifying JWT token');
198
+ * // Output includes: { correlationId, method, path, component: 'auth', ... }
199
+ *
200
+ * authLogger.info('Token verified', { userId: '123' });
201
+ * // Output includes all parent + child metadata
202
+ * ```
203
+ *
204
+ * @example Nested Child Loggers
205
+ * ```typescript
206
+ * const dbLogger = ctx.services.log.child({ component: 'database' });
207
+ * const queryLogger = dbLogger.child({ operation: 'select' });
208
+ *
209
+ * queryLogger.debug('Executing query');
210
+ * // Output includes: { correlationId, component: 'database', operation: 'select', ... }
211
+ * ```
212
+ */
213
+ child(meta: LogMetadata): BlaizeLogger;
214
+ /**
215
+ * Flush any buffered logs and wait for completion
216
+ *
217
+ * Call this during graceful shutdown to ensure all logs are written
218
+ * before the process exits. This is especially important for transports
219
+ * that batch writes (e.g., sending logs to external services).
220
+ *
221
+ * If the transport doesn't implement flush(), this is a no-op.
222
+ *
223
+ * @returns Promise that resolves when all logs are flushed
224
+ *
225
+ * @example Graceful Shutdown
226
+ * ```typescript
227
+ * // In server shutdown handler
228
+ * process.on('SIGTERM', async () => {
229
+ * console.log('Shutting down gracefully...');
230
+ *
231
+ * // Flush logs before exit
232
+ * await server._logger.flush();
233
+ *
234
+ * await server.close();
235
+ * process.exit(0);
236
+ * });
237
+ * ```
238
+ */
239
+ flush(): Promise<void>;
240
+ }
241
+ /**
242
+ * Transport adapter interface for log output destinations
243
+ *
244
+ * Transports are responsible for writing log entries to a destination
245
+ * (console, file, external service, etc.). Multiple transports can be
246
+ * used simultaneously.
247
+ *
248
+ * Transports must be stateless to support concurrent logging.
249
+ *
250
+ * @example Console Transport
251
+ * ```typescript
252
+ * class ConsoleTransport implements BlaizeLogTransport {
253
+ * write(level: LogLevel, message: string, meta: LogMetadata): void {
254
+ * const timestamp = new Date().toISOString();
255
+ * const levelUpper = level.toUpperCase();
256
+ * const metaStr = JSON.stringify(meta);
257
+ *
258
+ * console.log(`[${timestamp}] ${levelUpper}: ${message} ${metaStr}`);
259
+ * }
260
+ * }
261
+ * ```
262
+ *
263
+ * @example Custom HTTP Transport
264
+ * ```typescript
265
+ * class HTTPTransport implements BlaizeLogTransport {
266
+ * constructor(private endpoint: string) {}
267
+ *
268
+ * write(level: LogLevel, message: string, meta: LogMetadata): void {
269
+ * // Non-blocking fire-and-forget
270
+ * fetch(this.endpoint, {
271
+ * method: 'POST',
272
+ * headers: { 'Content-Type': 'application/json' },
273
+ * body: JSON.stringify({ level, message, meta, timestamp: Date.now() })
274
+ * }).catch(err => console.error('Failed to send log', err));
275
+ * }
276
+ *
277
+ * async flush(): Promise<void> {
278
+ * // Optional: wait for pending requests
279
+ * }
280
+ * }
281
+ * ```
282
+ */
283
+ interface BlaizeLogTransport {
284
+ /**
285
+ * Write a log entry to the transport destination
286
+ *
287
+ * This method must be synchronous and non-blocking. For transports
288
+ * that need to perform async I/O (network, disk), use fire-and-forget
289
+ * pattern or internal buffering.
290
+ *
291
+ * @param level - The log level
292
+ * @param message - The log message
293
+ * @param meta - Structured metadata (already redacted)
294
+ */
295
+ write(level: LogLevel, message: string, meta: LogMetadata): void;
296
+ /**
297
+ * Flush any buffered logs (optional)
298
+ *
299
+ * Implement this if your transport batches writes or has pending
300
+ * async operations. Called during graceful shutdown via logger.flush().
301
+ *
302
+ * @returns Promise that resolves when all logs are written
303
+ */
304
+ flush?(): Promise<void>;
305
+ }
306
+ /**
307
+ * Configuration for the logger system
308
+ *
309
+ * Controls logging behavior including log levels, output destinations,
310
+ * sensitive data redaction, and request lifecycle logging.
311
+ *
312
+ * @example Development Configuration
313
+ * ```typescript
314
+ * import { createServer } from 'blaizejs';
315
+ *
316
+ * const server = createServer({
317
+ * port: 3000,
318
+ * logging: {
319
+ * level: 'debug',
320
+ * // Uses ConsoleTransport by default in development
321
+ * includeTimestamp: true,
322
+ * requestLogging: true,
323
+ * requestLoggerOptions: {
324
+ * includeHeaders: true,
325
+ * includeQuery: true
326
+ * }
327
+ * }
328
+ * });
329
+ * ```
330
+ *
331
+ * @example Production Configuration
332
+ * ```typescript
333
+ * import { JSONTransport } from 'blaizejs';
334
+ *
335
+ * const server = createServer({
336
+ * port: 3000,
337
+ * logging: {
338
+ * level: 'info',
339
+ * transport: new JSONTransport(), // Single-line JSON for log aggregators
340
+ * redactKeys: ['password', 'apiKey', 'secret', 'token'],
341
+ * includeTimestamp: true,
342
+ * requestLogging: true,
343
+ * requestLoggerOptions: {
344
+ * includeHeaders: true,
345
+ * headerWhitelist: ['content-type', 'user-agent']
346
+ * }
347
+ * }
348
+ * });
349
+ * ```
350
+ */
351
+ interface LoggerConfig {
352
+ /**
353
+ * Minimum log level to output
354
+ *
355
+ * Logs below this level are filtered out (zero overhead).
356
+ *
357
+ * @default 'debug' in development, 'info' in production
358
+ *
359
+ * @example
360
+ * ```typescript
361
+ * logging: {
362
+ * level: 'warn' // Only log warnings and errors
363
+ * }
364
+ * ```
365
+ */
366
+ level?: LogLevel;
367
+ /**
368
+ * Transport adapter for log output
369
+ *
370
+ * Determines where and how logs are written.
371
+ *
372
+ * @default ConsoleTransport in development, JSONTransport in production
373
+ *
374
+ * @example Multiple Transports
375
+ * ```typescript
376
+ * import { ConsoleTransport, JSONTransport } from 'blaizejs';
377
+ *
378
+ * class MultiTransport implements BlaizeLogTransport {
379
+ * private transports = [
380
+ * new ConsoleTransport(),
381
+ * new JSONTransport()
382
+ * ];
383
+ *
384
+ * write(level: LogLevel, message: string, meta: LogMetadata): void {
385
+ * this.transports.forEach(t => t.write(level, message, meta));
386
+ * }
387
+ * }
388
+ *
389
+ * logging: {
390
+ * transport: new MultiTransport()
391
+ * }
392
+ * ```
393
+ */
394
+ transport?: BlaizeLogTransport;
395
+ /**
396
+ * Keys to redact from log metadata (case-insensitive)
397
+ *
398
+ * Matching keys are replaced with '[REDACTED]' in the output.
399
+ * Redaction is shallow (only top-level keys are checked).
400
+ *
401
+ * @default []
402
+ *
403
+ * @example
404
+ * ```typescript
405
+ * logging: {
406
+ * redactKeys: ['password', 'apiKey', 'creditCard', 'ssn']
407
+ * }
408
+ *
409
+ * // Usage
410
+ * ctx.services.log.info('User created', {
411
+ * email: 'user@example.com',
412
+ * password: 'secret123' // Will be '[REDACTED]' in output
413
+ * });
414
+ * ```
415
+ */
416
+ redactKeys?: string[];
417
+ /**
418
+ * Whether to include ISO 8601 timestamps in log metadata
419
+ *
420
+ * @default true
421
+ *
422
+ * @example
423
+ * ```typescript
424
+ * logging: {
425
+ * includeTimestamp: true
426
+ * }
427
+ *
428
+ * // Output includes: { timestamp: '2025-10-20T15:30:45.123Z', ... }
429
+ * ```
430
+ */
431
+ includeTimestamp?: boolean;
432
+ }
433
+ /**
434
+ * Resolved logger configuration with all defaults applied
435
+ *
436
+ */
437
+ interface ResolvedLoggerConfig {
438
+ /** Minimum log level to output */
439
+ level: LogLevel;
440
+ /** Transport adapter for log output */
441
+ transport: BlaizeLogTransport;
442
+ /** Keys to redact from metadata (case-insensitive) */
443
+ redactKeys: string[];
444
+ /** Whether to include ISO 8601 timestamps */
445
+ includeTimestamp: boolean;
446
+ }
447
+ /**
448
+ * Serialized error structure
449
+ */
450
+ interface SerializedError {
451
+ message: string;
452
+ name: string;
453
+ stack?: string;
454
+ }
455
+ /**
456
+ * Options for request logger middleware
457
+ *
458
+ * Controls what request data is automatically included in log metadata
459
+ * for the child logger created for each request.
460
+ *
461
+ * @example Basic Configuration
462
+ * ```typescript
463
+ * requestLoggerOptions: {
464
+ * includeHeaders: true, // Include safe headers
465
+ * includeQuery: true // Include query parameters
466
+ * }
467
+ * ```
468
+ *
469
+ * @example Custom Header Whitelist
470
+ * ```typescript
471
+ * requestLoggerOptions: {
472
+ * includeHeaders: true,
473
+ * headerWhitelist: [
474
+ * 'content-type',
475
+ * 'user-agent',
476
+ * 'accept',
477
+ * 'x-custom-header'
478
+ * ]
479
+ * }
480
+ * ```
481
+ */
482
+ interface RequestLoggerOptions {
483
+ /**
484
+ * Include request headers in log metadata
485
+ *
486
+ * Only safe headers are included by default. Sensitive headers
487
+ * (authorization, cookie, x-api-key, proxy-authorization) are
488
+ * ALWAYS redacted even if included in the whitelist.
489
+ *
490
+ * @default false
491
+ *
492
+ * @example
493
+ * ```typescript
494
+ * requestLoggerOptions: {
495
+ * includeHeaders: true
496
+ * }
497
+ *
498
+ * // Default safe headers included:
499
+ * // - accept
500
+ * // - content-type
501
+ * // - user-agent
502
+ * // - x-correlation-id
503
+ * ```
504
+ */
505
+ includeHeaders?: boolean;
506
+ /**
507
+ * Whitelist of header names to include (case-insensitive)
508
+ *
509
+ * Only used when includeHeaders is true. If not specified,
510
+ * default safe headers are used. Sensitive headers are ALWAYS
511
+ * redacted regardless of this whitelist.
512
+ *
513
+ * @default ['accept', 'content-type', 'user-agent', 'x-correlation-id']
514
+ *
515
+ * @example
516
+ * ```typescript
517
+ * requestLoggerOptions: {
518
+ * includeHeaders: true,
519
+ * headerWhitelist: [
520
+ * 'content-type',
521
+ * 'user-agent',
522
+ * 'x-request-id',
523
+ * 'x-custom-header'
524
+ * ]
525
+ * }
526
+ * ```
527
+ */
528
+ headerWhitelist?: string[];
529
+ /**
530
+ * Include query parameters in log metadata
531
+ *
532
+ * Query parameters are included as a `query` object in metadata.
533
+ * Be careful with sensitive data in query strings.
534
+ *
535
+ * @default false
536
+ *
537
+ * @example
538
+ * ```typescript
539
+ * requestLoggerOptions: {
540
+ * includeQuery: true
541
+ * }
542
+ *
543
+ * // Request: GET /users?page=1&limit=10
544
+ * // Log includes: { query: { page: '1', limit: '10' }, ... }
545
+ * ```
546
+ */
547
+ includeQuery?: boolean;
548
+ }
549
+
10
550
  /**
11
551
  * Represents an uploaded file in a multipart/form-data request
12
552
  */
@@ -354,8 +894,19 @@ type UnknownFunction = (...args: unknown[]) => unknown;
354
894
  type NextFunction = () => Promise<void> | void;
355
895
  /**
356
896
  * Middleware function signature
897
+ *
898
+ * @param ctx - The Blaize context object
899
+ * @param next - Function to invoke the next middleware in the chain
900
+ * @param logger - Logger instance for logging within the middleware
901
+ *
902
+ * @example
903
+ * const myMiddleware: MiddlewareFunction = async (ctx, next, logger) => {
904
+ * logger.info('Executing my middleware');
905
+ * // Middleware logic here
906
+ * await next();
907
+ * };
357
908
  */
358
- type MiddlewareFunction = (ctx: Context, next: NextFunction) => Promise<void> | void;
909
+ type MiddlewareFunction = (ctx: Context, next: NextFunction, logger: BlaizeLogger) => Promise<void> | void;
359
910
  /**
360
911
  * Named middleware options
361
912
  */
@@ -411,9 +962,22 @@ ED extends z.ZodType = z.ZodType<any>> {
411
962
  }
412
963
  /**
413
964
  * Route handler function with strongly typed params and response
965
+ *
966
+ * @param ctx - The Blaize context object
967
+ * @param params - Extracted route parameters
968
+ * @param logger - Logger instance for logging within the handler
969
+ *
970
+ * @returns The response data of type TResponse
971
+ *
972
+ * @example
973
+ * const myRouteHandler: RouteHandler = async (ctx, params, logger) => {
974
+ * logger.info('Handling route with params:', params);
975
+ * // Handler logic here
976
+ * return { message: 'Success' }
977
+ * };
414
978
  */
415
979
  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;
980
+ TServices extends Services = Services> = (ctx: Context<TState, TServices, TBody, TQuery>, params: TParams, logger: BlaizeLogger) => Promise<TResponse> | TResponse;
417
981
  /**
418
982
  * Options for a route method with schema-based type inference
419
983
  */
@@ -485,7 +1049,7 @@ interface RouterOptions {
485
1049
  */
486
1050
  interface Router {
487
1051
  /** Handle an incoming request */
488
- handleRequest: (ctx: Context) => Promise<void>;
1052
+ handleRequest: (ctx: Context, logger: BlaizeLogger) => Promise<void>;
489
1053
  /** Get all registered routes */
490
1054
  getRoutes: () => Route[];
491
1055
  /** Add a route programmatically */
@@ -762,441 +1326,122 @@ type CreateOptionsRoute = <TState extends State = State, TServices extends Servi
762
1326
  };
763
1327
 
764
1328
  /**
765
- * Compose multiple middleware functions into a single middleware function
766
- */
767
- declare function compose(middlewareStack: Middleware[]): MiddlewareFunction;
768
-
769
- /**
770
- * CORS Types for BlaizeJS Framework
1329
+ * Error type definitions and interfaces for the BlaizeJS framework
771
1330
  *
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
1331
+ * This module contains all the type definitions used for error handling
1332
+ * across the BlaizeJS framework, including server-side errors, client-side
1333
+ * errors, and HTTP response formats.
776
1334
  */
777
-
778
1335
  /**
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$/;
1336
+ * Structure of error responses sent over HTTP
788
1337
  *
789
- * // Dynamic validation function
790
- * const origin: CorsOrigin = async (origin, ctx) => {
791
- * return await checkOriginAllowed(origin, ctx?.state.user);
792
- * };
1338
+ * This interface defines the JSON format used for all error responses
1339
+ * from BlaizeJS servers. It matches the structure returned by BlaizeError.toJSON()
793
1340
  *
794
- * // Array of mixed types
795
- * const origin: CorsOrigin = [
796
- * 'https://localhost:3000',
797
- * /^https:\/\/.*\.example\.com$/,
798
- * (origin) => origin.endsWith('.trusted.com')
799
- * ];
1341
+ * @example
1342
+ * ```json
1343
+ * {
1344
+ * "type": "VALIDATION_ERROR",
1345
+ * "title": "Request validation failed",
1346
+ * "status": 400,
1347
+ * "correlationId": "req_abc123",
1348
+ * "timestamp": "2024-01-15T10:30:00.000Z",
1349
+ * "details": {
1350
+ * "fields": ["email", "password"]
1351
+ * }
1352
+ * }
800
1353
  * ```
801
1354
  */
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>)>;
803
- /**
804
- * HTTP methods that can be allowed in CORS
805
- * Based on W3C CORS specification
806
- */
807
- type CorsHttpMethod = HttpMethod | 'CONNECT' | 'TRACE';
1355
+ interface BlaizeErrorResponse {
1356
+ /** Error type from the ErrorType enum */
1357
+ type: ErrorType;
1358
+ /** Human-readable error message */
1359
+ title: string;
1360
+ /** HTTP status code */
1361
+ status: number;
1362
+ /** Correlation ID for request tracing */
1363
+ correlationId: string;
1364
+ /** ISO timestamp when error occurred */
1365
+ timestamp: string;
1366
+ /** Optional error-specific details */
1367
+ details?: unknown;
1368
+ }
808
1369
  /**
809
- * Main CORS configuration options
1370
+ * Context information for network-related errors
810
1371
  *
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
- * ```
1372
+ * Used by client-side error classes to provide additional context
1373
+ * about network failures, timeouts, and connection issues.
820
1374
  */
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;
1375
+ interface NetworkErrorContext {
1376
+ /** The URL that failed */
1377
+ url: string;
1378
+ /** HTTP method being attempted */
1379
+ method: string;
1380
+ /** Correlation ID for tracing */
1381
+ correlationId: string;
1382
+ /** Timeout value if applicable */
1383
+ timeout?: number;
1384
+ /** The original error that caused the network failure */
1385
+ originalError: Error;
1386
+ /** Additional network-specific details */
1387
+ networkDetails?: {
1388
+ /** Whether this was a connection timeout */
1389
+ isTimeout?: boolean;
1390
+ /** Whether this was a DNS resolution failure */
1391
+ isDnsFailure?: boolean;
1392
+ /** Whether this was a connection refused error */
1393
+ isConnectionRefused?: boolean;
1394
+ /** HTTP status code if received before failure */
1395
+ statusCode?: number;
1396
+ };
897
1397
  }
898
1398
  /**
899
- * Internal CORS validation result
900
- * Used by middleware implementation
1399
+ * Context information for request timeout errors
1400
+ *
1401
+ * Specialized context for timeout-specific errors with timing information.
901
1402
  */
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;
1403
+ interface TimeoutErrorContext {
1404
+ /** The URL that timed out */
1405
+ url: string;
1406
+ /** HTTP method being attempted */
1407
+ method: string;
1408
+ /** Correlation ID for tracing */
1409
+ correlationId: string;
1410
+ /** Configured timeout value in milliseconds */
1411
+ timeoutMs: number;
1412
+ /** Actual duration before timeout in milliseconds */
1413
+ elapsedMs: number;
1414
+ /** Type of timeout (request, connection, etc.) */
1415
+ timeoutType: 'request' | 'connection' | 'response' | 'idle';
916
1416
  }
917
1417
  /**
918
- * CORS preflight request information
919
- * Extracted from OPTIONS request headers
1418
+ * Context information for response parsing errors
1419
+ *
1420
+ * Used when the client receives a response but cannot parse it properly.
920
1421
  */
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[];
1422
+ interface ParseErrorContext {
1423
+ /** The URL that returned unparseable content */
1424
+ url: string;
1425
+ /** HTTP method used */
1426
+ method: string;
1427
+ /** Correlation ID for tracing */
1428
+ correlationId: string;
1429
+ /** HTTP status code received */
1430
+ statusCode: number;
1431
+ /** Content-Type header if available */
1432
+ contentType?: string;
1433
+ /** Expected response format */
1434
+ expectedFormat: 'json' | 'text' | 'binary';
1435
+ /** Sample of the actual response content (truncated for safety) */
1436
+ responseSample?: string;
1437
+ /** The original parsing error */
1438
+ originalError: Error;
936
1439
  }
937
1440
  /**
938
- * Cache entry for origin validation results
939
- * Used for performance optimization
940
- */
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;
954
- }
955
- /**
956
- * Configuration for CORS origin validation cache
957
- */
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
- }
975
- /**
976
- * Statistics for CORS middleware performance monitoring
977
- */
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;
1003
- }
1004
- /**
1005
- * Cache entry type
1006
- */
1007
- interface CacheEntry {
1008
- allowed: boolean;
1009
- expiresAt: number;
1010
- lastAccessed: number;
1011
- }
1012
- /**
1013
- * Cache configuration
1014
- */
1015
- interface CacheConfig {
1016
- ttl: number;
1017
- maxSize: number;
1018
- }
1019
-
1020
- /**
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
- * ```
1055
- */
1056
- declare function cors(userOptions?: CorsOptions | boolean): Middleware;
1057
-
1058
- /**
1059
- * Create a middleware
1060
- */
1061
- declare function create$1<TState = {}, TServices = {}>(handlerOrOptions: MiddlewareFunction | MiddlewareOptions): Middleware<TState, TServices>;
1062
- /**
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
- *
1070
- */
1071
- declare function stateMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<T, {}>;
1072
- /**
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
- *
1080
- */
1081
- declare function serviceMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<{}, T>;
1082
-
1083
- /**
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.
1089
- */
1090
- /**
1091
- * Structure of error responses sent over HTTP
1092
- *
1093
- * This interface defines the JSON format used for all error responses
1094
- * from BlaizeJS servers. It matches the structure returned by BlaizeError.toJSON()
1095
- *
1096
- * @example
1097
- * ```json
1098
- * {
1099
- * "type": "VALIDATION_ERROR",
1100
- * "title": "Request validation failed",
1101
- * "status": 400,
1102
- * "correlationId": "req_abc123",
1103
- * "timestamp": "2024-01-15T10:30:00.000Z",
1104
- * "details": {
1105
- * "fields": ["email", "password"]
1106
- * }
1107
- * }
1108
- * ```
1109
- */
1110
- interface BlaizeErrorResponse {
1111
- /** Error type from the ErrorType enum */
1112
- type: ErrorType;
1113
- /** Human-readable error message */
1114
- title: string;
1115
- /** HTTP status code */
1116
- status: number;
1117
- /** Correlation ID for request tracing */
1118
- correlationId: string;
1119
- /** ISO timestamp when error occurred */
1120
- timestamp: string;
1121
- /** Optional error-specific details */
1122
- details?: unknown;
1123
- }
1124
- /**
1125
- * Context information for network-related errors
1126
- *
1127
- * Used by client-side error classes to provide additional context
1128
- * about network failures, timeouts, and connection issues.
1129
- */
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;
1151
- };
1152
- }
1153
- /**
1154
- * Context information for request timeout errors
1155
- *
1156
- * Specialized context for timeout-specific errors with timing information.
1157
- */
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
- }
1172
- /**
1173
- * Context information for response parsing errors
1174
- *
1175
- * Used when the client receives a response but cannot parse it properly.
1176
- */
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
- }
1195
- /**
1196
- * Validation error field details
1197
- *
1198
- * Structure for field-level validation errors with multiple error messages
1199
- * per field.
1441
+ * Validation error field details
1442
+ *
1443
+ * Structure for field-level validation errors with multiple error messages
1444
+ * per field.
1200
1445
  */
1201
1446
  interface ValidationFieldError {
1202
1447
  /** Field name or path (e.g., "email", "user.profile.name") */
@@ -1731,1186 +1976,2039 @@ interface SSEOptions {
1731
1976
  bufferStrategy?: SSEBufferStrategy;
1732
1977
  }
1733
1978
  /**
1734
- * Connection states for SSE streams
1979
+ * Connection states for SSE streams
1980
+ */
1981
+ type SSEConnectionState = 'connecting' | 'connected' | 'disconnected' | 'closed';
1982
+ /**
1983
+ * SSE stream interface for managing server-sent events
1984
+ *
1985
+ * @example
1986
+ * ```typescript
1987
+ * const stream: SSEStream = createSSEStream(response);
1988
+ *
1989
+ * // Send typed event
1990
+ * stream.send('notification', { type: 'info', message: 'Update available' });
1991
+ *
1992
+ * // Send error event
1993
+ * stream.sendError(new Error('Processing failed'));
1994
+ *
1995
+ * // Clean up on close
1996
+ * stream.onClose(() => {
1997
+ * console.log('Client disconnected');
1998
+ * });
1999
+ *
2000
+ * // Close stream
2001
+ * stream.close();
2002
+ * ```
2003
+ */
2004
+ interface SSEStream {
2005
+ /**
2006
+ * Send an event with typed data to the client
2007
+ * @template T - Type of the data payload
2008
+ * @param event - Event name/type
2009
+ * @param data - Event data payload
2010
+ */
2011
+ send<T>(event: string, data: T): void;
2012
+ /**
2013
+ * Send an error event to the client
2014
+ * @param error - Error object to send
2015
+ */
2016
+ sendError(error: Error): void;
2017
+ /**
2018
+ * Close the SSE stream connection
2019
+ */
2020
+ close(): void;
2021
+ /**
2022
+ * Register a callback for stream closure
2023
+ * @param cb - Callback function to execute on close
2024
+ */
2025
+ onClose(cb: () => void): void;
2026
+ }
2027
+ /**
2028
+ * Extended SSE stream with additional control methods
2029
+ */
2030
+ interface SSEStreamExtended extends SSEStream {
2031
+ readonly id: string;
2032
+ [Symbol.asyncIterator](): AsyncGenerator<BufferedEvent, void, unknown>;
2033
+ /** Current connection state */
2034
+ readonly state: SSEConnectionState;
2035
+ /** Number of events in the buffer */
2036
+ readonly bufferSize: number;
2037
+ /** Check if stream is writable */
2038
+ readonly isWritable: boolean;
2039
+ /**
2040
+ * Ping the client to keep connection alive
2041
+ * @param comment - Optional comment to include in ping
2042
+ */
2043
+ ping(comment?: string): void;
2044
+ /**
2045
+ * Set retry interval for client reconnection
2046
+ * @param milliseconds - Retry interval in milliseconds
2047
+ */
2048
+ setRetry(milliseconds: number): void;
2049
+ /**
2050
+ * Flush any buffered events immediately
2051
+ */
2052
+ flush(): void;
2053
+ getMetrics(): StreamMetrics;
2054
+ }
2055
+ /**
2056
+ * SSE event serialization format
2057
+ */
2058
+ interface SSESerializedEvent {
2059
+ /** Event ID field */
2060
+ id?: string;
2061
+ /** Event type field */
2062
+ event?: string;
2063
+ /** Data field (can be multi-line) */
2064
+ data: string;
2065
+ /** Retry field */
2066
+ retry?: number;
2067
+ /** Comment field for keep-alive */
2068
+ comment?: string;
2069
+ }
2070
+ /**
2071
+ * SSE event handler function type
2072
+ * @template T - Type of the event data
2073
+ */
2074
+ type SSEEventHandler<T = unknown> = (event: SSEEvent<T>) => void | Promise<void>;
2075
+ /**
2076
+ * SSE event listener registration
2077
+ */
2078
+ interface SSEEventListener {
2079
+ /** Event type to listen for (use '*' for all events) */
2080
+ event: string;
2081
+ /** Handler function for the event */
2082
+ handler: SSEEventHandler;
2083
+ /** Optional listener identifier for removal */
2084
+ id?: string;
2085
+ }
2086
+ /**
2087
+ * SSE metrics for monitoring stream performance
2088
+ */
2089
+ interface SSEMetrics {
2090
+ /** Total number of events sent */
2091
+ eventsSent: number;
2092
+ /** Total number of events dropped */
2093
+ eventsDropped: number;
2094
+ /** Current number of connected clients */
2095
+ activeConnections: number;
2096
+ /** Total bytes sent */
2097
+ bytesSent: number;
2098
+ /** Average event send latency in milliseconds */
2099
+ averageLatency: number;
2100
+ /** Connection duration in milliseconds */
2101
+ connectionDuration: number;
2102
+ }
2103
+ /**
2104
+ * SSE stream manager for handling multiple clients
2105
+ */
2106
+ interface SSEStreamManager {
2107
+ /**
2108
+ * Create a new SSE stream for a client
2109
+ * @param clientId - Unique identifier for the client
2110
+ * @param options - Stream configuration options
2111
+ */
2112
+ createStream(clientId: string, options?: SSEOptions): SSEStream;
2113
+ /**
2114
+ * Get an existing stream by client ID
2115
+ * @param clientId - Client identifier
2116
+ */
2117
+ getStream(clientId: string): SSEStream | undefined;
2118
+ /**
2119
+ * Broadcast an event to all connected clients
2120
+ * @template T - Type of the event data
2121
+ * @param event - Event name
2122
+ * @param data - Event data
2123
+ */
2124
+ broadcast<T>(event: string, data: T): void;
2125
+ /**
2126
+ * Broadcast to specific clients
2127
+ * @template T - Type of the event data
2128
+ * @param clientIds - Array of client IDs
2129
+ * @param event - Event name
2130
+ * @param data - Event data
2131
+ */
2132
+ multicast<T>(clientIds: string[], event: string, data: T): void;
2133
+ /**
2134
+ * Close a specific client stream
2135
+ * @param clientId - Client identifier
2136
+ */
2137
+ closeStream(clientId: string): void;
2138
+ /**
2139
+ * Close all active streams
2140
+ */
2141
+ closeAll(): void;
2142
+ /**
2143
+ * Get metrics for all streams
2144
+ */
2145
+ getMetrics(): SSEMetrics;
2146
+ }
2147
+ /**
2148
+ * Result type for operations that can fail
2149
+ */
2150
+ type RegistryResult<T> = {
2151
+ success: true;
2152
+ value: T;
2153
+ } | {
2154
+ success: false;
2155
+ error: string;
2156
+ };
2157
+ /**
2158
+ * Connection metadata stored in the registry
2159
+ */
2160
+ interface ConnectionEntry {
2161
+ stream: SSEStream;
2162
+ connectedAt: number;
2163
+ lastActivity: number;
2164
+ clientIp?: string;
2165
+ userAgent?: string;
2166
+ }
2167
+ /**
2168
+ * Internal connection registry interface
2169
+ */
2170
+ interface ConnectionRegistry {
2171
+ /** Add a new connection to the registry */
2172
+ add: (id: string, stream: SSEStream, metadata?: {
2173
+ clientIp?: string;
2174
+ userAgent?: string;
2175
+ }) => void;
2176
+ /** Remove a connection from the registry */
2177
+ remove: (id: string) => void;
2178
+ /** Get current connection count */
2179
+ count: () => number;
2180
+ /** Clean up inactive or closed connections */
2181
+ cleanup: () => void;
2182
+ /** Get connection by ID (for internal use) */
2183
+ get: (id: string) => SSEStream | undefined;
2184
+ /** Check if a connection exists */
2185
+ has: (id: string) => boolean;
2186
+ /** Get all connection IDs */
2187
+ getIds: () => string[];
2188
+ /** Shutdown the registry and close all connections */
2189
+ shutdown: () => void;
2190
+ }
2191
+ /**
2192
+ * Extended stream interface for typed events
2193
+ */
2194
+ interface TypedSSEStream<TEvents extends Record<string, z.ZodType>> extends SSEStreamExtended {
2195
+ send<K extends keyof TEvents>(event: K & string, data: z.infer<TEvents[K]>): void;
2196
+ }
2197
+ /**
2198
+ * Schema for SSE route validation with generic type parameters
2199
+ */
2200
+ interface SSERouteSchema<P extends z.ZodType = z.ZodType<any>, Q extends z.ZodType = z.ZodType<any>, E = any> {
2201
+ /** Parameter schema for validation */
2202
+ params?: P;
2203
+ /** Query schema for validation */
2204
+ query?: Q;
2205
+ /** Events schema for validation (SSE-specific, replaces response) */
2206
+ events?: E;
2207
+ }
2208
+ /**
2209
+ * SSE route handler function with stream as first parameter
2210
+ * This is the user-facing API - they write handlers with this signature
2211
+ */
2212
+ type SSERouteHandler<TStream extends SSEStreamExtended = SSEStreamExtended, TParams = Record<string, string>, TQuery = Record<string, string | string[] | undefined>, TState extends State = State, TServices extends Services = Services> = (stream: TStream, ctx: Context<TState, TServices, never, TQuery>, // SSE never has body
2213
+ params: TParams) => Promise<void> | void;
2214
+ /**
2215
+ * SSE route creator with state and services support
2216
+ * Returns a higher-order function to handle generics properly
2217
+ *
2218
+ * The return type matches what the implementation actually returns:
2219
+ * - A route object with a GET property
2220
+ * - The GET property contains the wrapped handler and schemas
2221
+ * - The wrapped handler has the standard (ctx, params) signature expected by the router
2222
+ */
2223
+ type CreateSSERoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, E = never>(config: {
2224
+ schema?: {
2225
+ params?: P extends never ? never : P;
2226
+ query?: Q extends never ? never : Q;
2227
+ events?: E extends never ? never : E;
2228
+ };
2229
+ handler: SSERouteHandler<E extends Record<string, z.ZodType> ? TypedSSEStream<E> : SSEStreamExtended, P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, TState, TServices>;
2230
+ middleware?: Middleware[];
2231
+ options?: Record<string, unknown>;
2232
+ }) => {
2233
+ GET: {
2234
+ handler: (ctx: any, params: any) => Promise<void>;
2235
+ schema?: {
2236
+ params?: P extends never ? undefined : P;
2237
+ query?: Q extends never ? undefined : Q;
2238
+ };
2239
+ middleware?: Middleware[];
2240
+ options?: Record<string, unknown>;
2241
+ };
2242
+ path: string;
2243
+ };
2244
+ /**
2245
+ * Buffered event with metadata
2246
+ */
2247
+ interface BufferedEvent {
2248
+ id: string;
2249
+ event: string;
2250
+ data: unknown;
2251
+ size: number;
2252
+ timestamp: number;
2253
+ correlationId: string;
2254
+ }
2255
+ /**
2256
+ * Stream metrics for monitoring
2257
+ */
2258
+ interface StreamMetrics {
2259
+ eventsSent: number;
2260
+ eventsDropped: number;
2261
+ bytesWritten: number;
2262
+ bufferHighWatermark: number;
2263
+ lastEventTime: number;
2264
+ }
2265
+
2266
+ /**
2267
+ * SSE Client Types for BlaizeJS
2268
+ * Location: packages/blaize-client/src/sse/types.ts
2269
+ */
2270
+
2271
+ /**
2272
+ * Event handlers map
2273
+ */
2274
+ interface EventHandlers {
2275
+ [event: string]: Set<(data: any) => void>;
2276
+ }
2277
+ /**
2278
+ * SSE connection configuration options
2279
+ */
2280
+ interface SSEClientOptions {
2281
+ headers?: Record<string, string>;
2282
+ withCredentials?: boolean;
2283
+ reconnect?: {
2284
+ enabled: boolean;
2285
+ maxAttempts?: number;
2286
+ strategy?: ReconnectStrategy;
2287
+ initialDelay?: number;
2288
+ };
2289
+ bufferMissedEvents?: boolean;
2290
+ maxMissedEvents?: number;
2291
+ heartbeatTimeout?: number;
2292
+ parseJSON?: boolean;
2293
+ /**
2294
+ * Whether to wait for connection before resolving the promise.
2295
+ * If false, returns the client immediately without waiting.
2296
+ * Default: true
2297
+ */
2298
+ waitForConnection?: boolean;
2299
+ /**
2300
+ * Optional timeout for initial connection in milliseconds.
2301
+ * If not set, no timeout is applied (relies on EventSource native timeout).
2302
+ * Only applies if waitForConnection is true.
2303
+ */
2304
+ connectionTimeout?: number;
2305
+ }
2306
+ /**
2307
+ * Metrics for SSE connection monitoring
2308
+ */
2309
+ interface SSEClientMetrics {
2310
+ eventsReceived: number;
2311
+ bytesReceived: number;
2312
+ connectionDuration: number;
2313
+ reconnectAttempts: number;
2314
+ lastEventId?: string;
2315
+ }
2316
+ /**
2317
+ * Reconnection delay calculation strategy
2318
+ */
2319
+ type ReconnectStrategy = (attempt: number) => number;
2320
+ /**
2321
+ * SSE Client interface with type-safe event handling
2322
+ */
2323
+ interface SSEClient<TEvents extends Record<string, unknown> = Record<string, unknown>> {
2324
+ on<K extends keyof TEvents>(event: K & string, handler: (data: TEvents[K]) => void): void;
2325
+ on(event: 'error', handler: (error: BlaizeError) => void): void;
2326
+ on(event: 'open', handler: () => void): void;
2327
+ on(event: 'close', handler: (event: CloseEvent) => void): void;
2328
+ off<K extends keyof TEvents>(event: K & string, handler?: (data: TEvents[K]) => void): void;
2329
+ off(event: 'error', handler?: (error: BlaizeError) => void): void;
2330
+ off(event: 'open', handler?: () => void): void;
2331
+ off(event: 'close', handler?: (event: CloseEvent) => void): void;
2332
+ once<K extends keyof TEvents>(event: K & string, handler: (data: TEvents[K]) => void): void;
2333
+ once(event: 'error', handler: (error: BlaizeError) => void): void;
2334
+ once(event: 'open', handler: () => void): void;
2335
+ once(event: 'close', handler: (event: CloseEvent) => void): void;
2336
+ close(): void;
2337
+ readonly state: SSEConnectionState;
2338
+ readonly metrics: SSEClientMetrics;
2339
+ readonly lastEventId?: string;
2340
+ }
2341
+ /**
2342
+ * Close event for SSE connections
2343
+ */
2344
+ interface CloseEvent {
2345
+ reconnect: boolean;
2346
+ reason?: string;
2347
+ }
2348
+ /**
2349
+ * Internal SSE connection factory
2350
+ * Returns a Promise that resolves to an SSEClient instance
2351
+ */
2352
+ type SSEConnectionFactory<TEvents extends Record<string, unknown> = Record<string, unknown>> = (options?: SSEClientOptions) => Promise<SSEClient<TEvents>>;
2353
+
2354
+ type ExtractMethod<T> = T extends {
2355
+ GET: any;
2356
+ } ? 'GET' : T extends {
2357
+ POST: any;
2358
+ } ? 'POST' : T extends {
2359
+ PUT: any;
2360
+ } ? 'PUT' : T extends {
2361
+ DELETE: any;
2362
+ } ? 'DELETE' : T extends {
2363
+ PATCH: any;
2364
+ } ? 'PATCH' : T extends {
2365
+ HEAD: any;
2366
+ } ? 'HEAD' : T extends {
2367
+ OPTIONS: any;
2368
+ } ? 'OPTIONS' : never;
2369
+ type BuildRoutesRegistry<TRoutes extends Record<string, any>> = {
2370
+ [Method in ExtractMethod<TRoutes[keyof TRoutes]> as `$${Lowercase<Method>}`]: {
2371
+ [K in keyof TRoutes as ExtractMethod<TRoutes[K]> extends Method ? K : never]: TRoutes[K];
2372
+ };
2373
+ };
2374
+ type GetRouteMethodOptions<TRoute> = TRoute extends {
2375
+ GET: infer M;
2376
+ } ? M : TRoute extends {
2377
+ POST: infer M;
2378
+ } ? M : TRoute extends {
2379
+ PUT: infer M;
2380
+ } ? M : TRoute extends {
2381
+ DELETE: infer M;
2382
+ } ? M : TRoute extends {
2383
+ PATCH: infer M;
2384
+ } ? M : TRoute extends {
2385
+ HEAD: infer M;
2386
+ } ? M : TRoute extends {
2387
+ OPTIONS: infer M;
2388
+ } ? M : never;
2389
+ type IsNever$1<T> = [T] extends [never] ? true : false;
2390
+ type BuildArgsObject<P, Q, B> = (IsNever$1<P> extends true ? {} : {
2391
+ params: Infer<P>;
2392
+ }) & (IsNever$1<Q> extends true ? {} : {
2393
+ query: Infer<Q>;
2394
+ }) & (IsNever$1<B> extends true ? {} : {
2395
+ body: Infer<B>;
2396
+ });
2397
+ type IsEmptyObject<T> = keyof T extends never ? true : false;
2398
+ type BuildArgs<P, Q, B> = IsEmptyObject<BuildArgsObject<P, Q, B>> extends true ? void : BuildArgsObject<P, Q, B>;
2399
+ type CreateClientMethod<TRoute> = GetRouteMethodOptions<TRoute> extends RouteMethodOptions<infer P, infer Q, infer B, infer R> ? BuildArgs<P, Q, B> extends void ? () => Promise<R extends z.ZodType ? Infer<R> : unknown> : (args: BuildArgs<P, Q, B>) => Promise<R extends z.ZodType ? Infer<R> : unknown> : never;
2400
+ type CreateClient<TRoutes extends Record<string, Record<string, any>>> = {
2401
+ [Method in keyof TRoutes]: {
2402
+ [RouteName in keyof TRoutes[Method]]: CreateClientMethod<TRoutes[Method][RouteName]>;
2403
+ };
2404
+ };
2405
+ interface ClientConfig {
2406
+ baseUrl: string;
2407
+ defaultHeaders?: Record<string, string>;
2408
+ timeout?: number;
2409
+ sse?: SSEClientOptions;
2410
+ }
2411
+ interface InternalRequestArgs {
2412
+ params?: Record<string, any>;
2413
+ query?: Record<string, any>;
2414
+ body?: any;
2415
+ }
2416
+ interface RequestOptions {
2417
+ method: string;
2418
+ url: string;
2419
+ headers: Record<string, string>;
2420
+ body?: string;
2421
+ timeout: number;
2422
+ }
2423
+ /**
2424
+ * Detect if a route has SSE support
2425
+ * SSE routes have a special 'SSE' method key
2426
+ */
2427
+ type HasSSEMethod<TRoute> = TRoute extends {
2428
+ SSE: any;
2429
+ } ? true : false;
2430
+ /**
2431
+ * Extract SSE event types from route schema
2432
+ */
2433
+ type ExtractSSEEvents<TRoute> = TRoute extends {
2434
+ SSE: {
2435
+ events?: infer E;
2436
+ };
2437
+ } ? E extends z.ZodType ? z.infer<E> : Record<string, unknown> : Record<string, unknown>;
2438
+ /**
2439
+ * Extract SSE query parameters from route
2440
+ */
2441
+ type ExtractSSEQuery<TRoute> = TRoute extends {
2442
+ SSE: {
2443
+ schema?: {
2444
+ query?: infer Q;
2445
+ };
2446
+ };
2447
+ } ? Q extends z.ZodType ? z.infer<Q> : Record<string, unknown> : never;
2448
+ /**
2449
+ * Extract SSE params from route
2450
+ */
2451
+ type ExtractSSEParams<TRoute> = TRoute extends {
2452
+ SSE: {
2453
+ schema?: {
2454
+ params?: infer P;
2455
+ };
2456
+ };
2457
+ } ? P extends z.ZodType ? z.infer<P> : Record<string, string> : never;
2458
+ /**
2459
+ * Build SSE method arguments
2460
+ */
2461
+ type BuildSSEArgs<TRoute> = ExtractSSEParams<TRoute> extends never ? ExtractSSEQuery<TRoute> extends never ? {
2462
+ options?: SSEClientOptions;
2463
+ } : {
2464
+ query: ExtractSSEQuery<TRoute>;
2465
+ options?: SSEClientOptions;
2466
+ } : ExtractSSEQuery<TRoute> extends never ? {
2467
+ params: ExtractSSEParams<TRoute>;
2468
+ options?: SSEClientOptions;
2469
+ } : {
2470
+ params: ExtractSSEParams<TRoute>;
2471
+ query: ExtractSSEQuery<TRoute>;
2472
+ options?: SSEClientOptions;
2473
+ };
2474
+ /**
2475
+ * Create SSE client method
2476
+ */
2477
+ type CreateSSEMethod<TRoute> = HasSSEMethod<TRoute> extends true ? BuildSSEArgs<TRoute> extends {
2478
+ options?: SSEClientOptions;
2479
+ } ? (args?: BuildSSEArgs<TRoute>) => Promise<SSEClient<ExtractSSEEvents<TRoute>>> : (args: BuildSSEArgs<TRoute>) => Promise<SSEClient<ExtractSSEEvents<TRoute>>> : never;
2480
+ /**
2481
+ * Extract SSE routes from registry
2482
+ */
2483
+ type ExtractSSERoutes<TRoutes extends Record<string, any>> = {
2484
+ [K in keyof TRoutes as HasSSEMethod<TRoutes[K]> extends true ? K : never]: TRoutes[K];
2485
+ };
2486
+ /**
2487
+ * Enhanced client with SSE support
2488
+ */
2489
+ type CreateEnhancedClient<TRoutes extends Record<string, any>, TRegistry> = TRegistry & {
2490
+ $sse: {
2491
+ [K in keyof ExtractSSERoutes<TRoutes>]: CreateSSEMethod<TRoutes[K]>;
2492
+ };
2493
+ };
2494
+
2495
+ /**
2496
+ * CORS Types for BlaizeJS Framework
2497
+ *
2498
+ * Comprehensive type definitions for W3C-compliant CORS middleware
2499
+ * with support for string, regex, and async function origin validation.
2500
+ *
2501
+ * @module @blaizejs/types/cors
2502
+ */
2503
+
2504
+ /**
2505
+ * Origin configuration type supporting multiple validation methods
2506
+ *
2507
+ * @example
2508
+ * ```typescript
2509
+ * // String origin (exact match)
2510
+ * const origin: CorsOrigin = 'https://example.com';
2511
+ *
2512
+ * // RegExp pattern
2513
+ * const origin: CorsOrigin = /^https:\/\/.*\.example\.com$/;
2514
+ *
2515
+ * // Dynamic validation function
2516
+ * const origin: CorsOrigin = async (origin, ctx) => {
2517
+ * return await checkOriginAllowed(origin, ctx?.state.user);
2518
+ * };
2519
+ *
2520
+ * // Array of mixed types
2521
+ * const origin: CorsOrigin = [
2522
+ * 'https://localhost:3000',
2523
+ * /^https:\/\/.*\.example\.com$/,
2524
+ * (origin) => origin.endsWith('.trusted.com')
2525
+ * ];
2526
+ * ```
2527
+ */
2528
+ 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>)>;
2529
+ /**
2530
+ * HTTP methods that can be allowed in CORS
2531
+ * Based on W3C CORS specification
2532
+ */
2533
+ type CorsHttpMethod = HttpMethod | 'CONNECT' | 'TRACE';
2534
+ /**
2535
+ * Main CORS configuration options
2536
+ *
2537
+ * @example
2538
+ * ```typescript
2539
+ * const corsOptions: CorsOptions = {
2540
+ * origin: 'https://example.com',
2541
+ * methods: ['GET', 'POST'],
2542
+ * credentials: true,
2543
+ * maxAge: 86400
2544
+ * };
2545
+ * ```
2546
+ */
2547
+ interface CorsOptions {
2548
+ /**
2549
+ * Configures the Access-Control-Allow-Origin header
2550
+ *
2551
+ * Possible values:
2552
+ * - `true`: Allow all origins (sets to '*' unless credentials is true, then reflects origin)
2553
+ * - `false`: Disable CORS (no headers set)
2554
+ * - `string`: Specific origin to allow
2555
+ * - `RegExp`: Pattern to match origins
2556
+ * - `function`: Custom validation logic
2557
+ * - `array`: Multiple origin configurations
2558
+ *
2559
+ * @default false
2560
+ */
2561
+ origin?: boolean | CorsOrigin;
2562
+ /**
2563
+ * Configures the Access-Control-Allow-Methods header
2564
+ *
2565
+ * @default ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE']
2566
+ * @example ['GET', 'POST']
2567
+ */
2568
+ methods?: CorsHttpMethod[] | string;
2569
+ /**
2570
+ * Configures the Access-Control-Allow-Headers header
2571
+ *
2572
+ * Pass an array of allowed headers or a comma-delimited string.
2573
+ *
2574
+ * @default Request's Access-Control-Request-Headers header value
2575
+ * @example ['Content-Type', 'Authorization']
2576
+ */
2577
+ allowedHeaders?: string[] | string;
2578
+ /**
2579
+ * Configures the Access-Control-Expose-Headers header
2580
+ *
2581
+ * Headers that the browser is allowed to access.
2582
+ *
2583
+ * @default []
2584
+ * @example ['Content-Range', 'X-Content-Range']
2585
+ */
2586
+ exposedHeaders?: string[] | string;
2587
+ /**
2588
+ * Configures the Access-Control-Allow-Credentials header
2589
+ *
2590
+ * Set to true to allow credentials (cookies, authorization headers, TLS client certificates).
2591
+ * Note: Cannot be used with origin: '*' for security reasons.
2592
+ *
2593
+ * @default false
2594
+ */
2595
+ credentials?: boolean;
2596
+ /**
2597
+ * Configures the Access-Control-Max-Age header in seconds
2598
+ *
2599
+ * Indicates how long browsers can cache preflight response.
2600
+ * Set to -1 to disable caching.
2601
+ *
2602
+ * @default undefined (browser decides)
2603
+ * @example 86400 // 24 hours
2604
+ */
2605
+ maxAge?: number;
2606
+ /**
2607
+ * Whether to pass the CORS preflight response to the next handler
2608
+ *
2609
+ * When false, the preflight response is sent immediately.
2610
+ * When true, control passes to the next middleware/handler.
2611
+ *
2612
+ * @default false
2613
+ */
2614
+ preflightContinue?: boolean;
2615
+ /**
2616
+ * HTTP status code for successful OPTIONS requests
2617
+ *
2618
+ * Some legacy browsers require 200, while 204 is more correct.
2619
+ *
2620
+ * @default 204
2621
+ */
2622
+ optionsSuccessStatus?: number;
2623
+ }
2624
+ /**
2625
+ * Internal CORS validation result
2626
+ * Used by middleware implementation
2627
+ */
2628
+ interface CorsValidationResult {
2629
+ /**
2630
+ * Whether the origin is allowed
2631
+ */
2632
+ allowed: boolean;
2633
+ /**
2634
+ * The origin value to set in the header
2635
+ * Can be '*', specific origin, or 'null'
2636
+ */
2637
+ origin?: string;
2638
+ /**
2639
+ * Whether to add Vary: Origin header
2640
+ */
2641
+ vary?: boolean;
2642
+ }
2643
+ /**
2644
+ * CORS preflight request information
2645
+ * Extracted from OPTIONS request headers
2646
+ */
2647
+ interface CorsPreflightInfo {
2648
+ /**
2649
+ * The origin making the request
2650
+ */
2651
+ origin?: string;
2652
+ /**
2653
+ * The method that will be used in the actual request
2654
+ * From Access-Control-Request-Method header
2655
+ */
2656
+ requestedMethod?: string;
2657
+ /**
2658
+ * The headers that will be sent in the actual request
2659
+ * From Access-Control-Request-Headers header
2660
+ */
2661
+ requestedHeaders?: string[];
2662
+ }
2663
+ /**
2664
+ * Cache entry for origin validation results
2665
+ * Used for performance optimization
2666
+ */
2667
+ interface CorsOriginCacheEntry {
2668
+ /**
2669
+ * Whether the origin is allowed
2670
+ */
2671
+ allowed: boolean;
2672
+ /**
2673
+ * When this cache entry expires (timestamp)
2674
+ */
2675
+ expiresAt: number;
2676
+ /**
2677
+ * Optional user identifier for cache key
2678
+ */
2679
+ userId?: string;
2680
+ }
2681
+ /**
2682
+ * Configuration for CORS origin validation cache
2683
+ */
2684
+ interface CorsOriginCacheConfig {
2685
+ /**
2686
+ * Time-to-live for cache entries in milliseconds
2687
+ * @default 60000 (1 minute)
2688
+ */
2689
+ ttl?: number;
2690
+ /**
2691
+ * Maximum number of entries in the cache
2692
+ * @default 1000
2693
+ */
2694
+ maxSize?: number;
2695
+ /**
2696
+ * Whether to include user ID in cache key
2697
+ * @default true
2698
+ */
2699
+ includeUserId?: boolean;
2700
+ }
2701
+ /**
2702
+ * Statistics for CORS middleware performance monitoring
2703
+ */
2704
+ interface CorsStats {
2705
+ /**
2706
+ * Total number of CORS requests processed
2707
+ */
2708
+ totalRequests: number;
2709
+ /**
2710
+ * Number of preflight requests handled
2711
+ */
2712
+ preflightRequests: number;
2713
+ /**
2714
+ * Number of allowed origins
2715
+ */
2716
+ allowedOrigins: number;
2717
+ /**
2718
+ * Number of denied origins
2719
+ */
2720
+ deniedOrigins: number;
2721
+ /**
2722
+ * Cache hit rate for origin validation
2723
+ */
2724
+ cacheHitRate: number;
2725
+ /**
2726
+ * Average origin validation time in milliseconds
2727
+ */
2728
+ avgValidationTime: number;
2729
+ }
2730
+ /**
2731
+ * Cache entry type
2732
+ */
2733
+ interface CacheEntry {
2734
+ allowed: boolean;
2735
+ expiresAt: number;
2736
+ lastAccessed: number;
2737
+ }
2738
+ /**
2739
+ * Cache configuration
2740
+ */
2741
+ interface CacheConfig {
2742
+ ttl: number;
2743
+ maxSize: number;
2744
+ }
2745
+
2746
+ /**
2747
+ * BlaizeJS Server Module - Enhanced with Correlation Configuration
2748
+ *
2749
+ * Provides the core HTTP/2 server implementation with HTTP/1.1 fallback
2750
+ * and correlation ID tracking configuration.
2751
+ */
2752
+
2753
+ type UnknownServer = Server<Record<string, unknown>, Record<string, unknown>>;
2754
+ interface Http2Options {
2755
+ enabled?: boolean | undefined;
2756
+ keyFile?: string | undefined;
2757
+ certFile?: string | undefined;
2758
+ }
2759
+ interface StartOptions {
2760
+ port?: number;
2761
+ host?: string;
2762
+ }
2763
+ interface StopOptions {
2764
+ timeout?: number;
2765
+ plugins?: Plugin[];
2766
+ onStopping?: () => Promise<void> | void;
2767
+ onStopped?: () => Promise<void> | void;
2768
+ }
2769
+ /**
2770
+ * Correlation ID configuration options
2771
+ */
2772
+ interface CorrelationOptions {
2773
+ /**
2774
+ * The HTTP header name to use for correlation IDs
2775
+ * @default 'x-correlation-id'
2776
+ */
2777
+ headerName?: string;
2778
+ /**
2779
+ * Custom correlation ID generator function
2780
+ * @default () => `req_${timestamp}_${random}`
2781
+ */
2782
+ generator?: () => string;
2783
+ }
2784
+ /**
2785
+ * Server options for configuring the BlaizeJS server
2786
+ */
2787
+ interface ServerOptionsInput {
2788
+ /** Port to listen on (default: 3000) */
2789
+ port?: number;
2790
+ /** Host to bind to (default: localhost) */
2791
+ host?: string;
2792
+ /** Directory containing route files (default: ./routes) */
2793
+ routesDir?: string;
2794
+ /** HTTP/2 options */
2795
+ http2?: {
2796
+ /** Enable HTTP/2 (default: true) */
2797
+ enabled?: boolean | undefined;
2798
+ /** Path to key file for HTTPS/HTTP2 */
2799
+ keyFile?: string | undefined;
2800
+ /** Path to certificate file for HTTPS/HTTP2 */
2801
+ certFile?: string | undefined;
2802
+ };
2803
+ /** Global middleware to apply to all routes */
2804
+ middleware?: Middleware[];
2805
+ /** Plugins to register */
2806
+ plugins?: Plugin[];
2807
+ /**
2808
+ * Correlation ID configuration
2809
+ * @since 0.4.0
2810
+ */
2811
+ correlation?: CorrelationOptions;
2812
+ /**
2813
+ * CORS configuration
2814
+ *
2815
+ * - `true`: Enable CORS with development defaults (allow all origins)
2816
+ * - `false`: Disable CORS (no headers set)
2817
+ * - `CorsOptions`: Custom CORS configuration
2818
+ *
2819
+ * @default false (CORS disabled)
2820
+ * @since 0.5.0
2821
+ *
2822
+ * @example
2823
+ * ```typescript
2824
+ * // Enable with dev defaults
2825
+ * const server = createServer({ cors: true });
2826
+ *
2827
+ * // Custom configuration
2828
+ * const server = createServer({
2829
+ * cors: {
2830
+ * origin: 'https://example.com',
2831
+ * credentials: true,
2832
+ * maxAge: 86400
2833
+ * }
2834
+ * });
2835
+ *
2836
+ * // Disable CORS
2837
+ * const server = createServer({ cors: false });
2838
+ * ```
2839
+ */
2840
+ cors?: CorsOptions | boolean;
2841
+ bodyLimits?: Partial<BodyLimits>;
2842
+ /**
2843
+ * Logger configuration
2844
+ *
2845
+ * Controls logging behavior including log levels, transports,
2846
+ * redaction, and request lifecycle logging.
2847
+ *
2848
+ * @default Development: ConsoleTransport with debug level
2849
+ * @default Production: JSONTransport with info level
2850
+ * @since 0.4.0
2851
+ *
2852
+ * @example Development Configuration
2853
+ * ```typescript
2854
+ * import { createServer } from 'blaizejs';
2855
+ *
2856
+ * const server = createServer({
2857
+ * port: 3000,
2858
+ * logging: {
2859
+ * level: 'debug',
2860
+ * includeTimestamp: true,
2861
+ * requestLogging: true
2862
+ * }
2863
+ * });
2864
+ * ```
2865
+ *
2866
+ * @example Production Configuration
2867
+ * ```typescript
2868
+ * import { createServer, JSONTransport } from 'blaizejs';
2869
+ *
2870
+ * const server = createServer({
2871
+ * port: 3000,
2872
+ * logging: {
2873
+ * level: 'info',
2874
+ * transport: new JSONTransport(),
2875
+ * redactKeys: ['password', 'apiKey', 'secret'],
2876
+ * requestLogging: true
2877
+ * }
2878
+ * });
2879
+ * ```
2880
+ */
2881
+ logging?: LoggerConfig;
2882
+ }
2883
+ /**
2884
+ * Configuration for a BlaizeJS server
2885
+ */
2886
+ interface ServerOptions {
2887
+ /** Port to listen on (default: 3000) */
2888
+ port: number;
2889
+ /** Host to bind to (default: localhost) */
2890
+ host: string;
2891
+ /** Directory containing route files (default: ./routes) */
2892
+ routesDir: string;
2893
+ /** HTTP/2 options */
2894
+ http2?: {
2895
+ /** Enable HTTP/2 (default: true) */
2896
+ enabled?: boolean | undefined;
2897
+ /** Path to key file for HTTPS/HTTP2 */
2898
+ keyFile?: string | undefined;
2899
+ /** Path to certificate file for HTTPS/HTTP2 */
2900
+ certFile?: string | undefined;
2901
+ };
2902
+ /** Global middleware to apply to all routes */
2903
+ middleware?: Middleware[];
2904
+ /** Plugins to register */
2905
+ plugins?: Plugin[];
2906
+ /**
2907
+ * Correlation ID configuration
2908
+ * @since 0.4.0
2909
+ */
2910
+ correlation?: CorrelationOptions;
2911
+ /**
2912
+ * CORS configuration
2913
+ * @since 0.5.0
2914
+ */
2915
+ cors?: CorsOptions | boolean;
2916
+ /** Body size limits for incoming requests */
2917
+ bodyLimits: BodyLimits;
2918
+ /** Logger configuration */
2919
+ logging?: LoggerConfig;
2920
+ }
2921
+ /**
2922
+ * BlaizeJS Server instance with generic type accumulation
2923
+ *
2924
+ * @template TState - The accumulated state type from middleware
2925
+ * @template TServices - The accumulated services type from middleware and plugins
2926
+ *
2927
+ */
2928
+ interface Server<TState, TServices> {
2929
+ /** The underlying HTTP or HTTP/2 server */
2930
+ server: http.Server | http2.Http2Server | undefined;
2931
+ /** The port the server is configured to listen on */
2932
+ port: number;
2933
+ /** CORS configuration for this server */
2934
+ corsOptions?: CorsOptions | boolean;
2935
+ /** Body size limits for incoming requests */
2936
+ bodyLimits: BodyLimits;
2937
+ /** The host the server is bound to */
2938
+ host: string;
2939
+ events: EventEmitter;
2940
+ /** Direct access to registered plugins */
2941
+ plugins: Plugin[];
2942
+ /** Direct access to registered plugins */
2943
+ middleware: Middleware[];
2944
+ /** Internal property for signal handlers */
2945
+ _signalHandlers?: {
2946
+ unregister: () => void;
2947
+ };
2948
+ /** Internal logger instance (for server use only) */
2949
+ _logger: BlaizeLogger;
2950
+ /** Start the server and listen for connections */
2951
+ listen: (port?: number, host?: string) => Promise<Server<TState, TServices>>;
2952
+ /** Stop the server */
2953
+ close: (stopOptions?: StopOptions) => Promise<void>;
2954
+ /**
2955
+ * Add global middleware to the server
2956
+ *
2957
+ * @param middleware - Single middleware or array of middleware to add
2958
+ * @returns New Server instance with accumulated types from the middleware
2959
+ *
2960
+ * @example
2961
+ * ```typescript
2962
+ * // Single middleware
2963
+ * const serverWithAuth = server.use(authMiddleware);
2964
+ * // serverWithAuth has type Server<{user: User}, {auth: AuthService}>
2965
+ *
2966
+ * // Array of middleware
2967
+ * const serverWithMiddleware = server.use([authMiddleware, loggerMiddleware]);
2968
+ * // serverWithMiddleware has type Server<{user, requestId}, {auth, logger}>
2969
+ * ```
2970
+ */
2971
+ use<MS, MSvc>(middleware: Middleware<MS, MSvc>): Server<TState & MS, TServices & MSvc>;
2972
+ use<MW extends readonly Middleware<any, any>[]>(middleware: MW): Server<TState & UnionToIntersection<ExtractMiddlewareState<MW[number]>>, TServices & UnionToIntersection<ExtractMiddlewareServices<MW[number]>>>;
2973
+ /**
2974
+ * Register a plugin with the server
2975
+ *
2976
+ * @param plugin - Single plugin or array of plugins to register
2977
+ * @returns Promise resolving to new Server instance with accumulated types
2978
+ *
2979
+ * @example
2980
+ * ```typescript
2981
+ * // Single plugin
2982
+ * const serverWithDb = await server.register(databasePlugin);
2983
+ * // serverWithDb has type Server<{}, {db: DatabaseService}>
2984
+ *
2985
+ * // Array of plugins
2986
+ * const serverWithPlugins = await server.register([dbPlugin, cachePlugin]);
2987
+ * // serverWithPlugins has type Server<{}, {db, cache}>
2988
+ * ```
2989
+ */
2990
+ register<PS, PSvc>(plugin: Plugin<PS, PSvc>): Promise<Server<TState & PS, TServices & PSvc>>;
2991
+ register<P extends readonly Plugin<any, any>[]>(plugin: P): Promise<Server<TState & UnionToIntersection<ExtractPluginState<P[number]>>, TServices & UnionToIntersection<ExtractPluginServices<P[number]>>>>;
2992
+ /** Access to the routing system */
2993
+ router: Router;
2994
+ /** Context storage system */
2995
+ context: AsyncLocalStorage<Context>;
2996
+ pluginManager: PluginLifecycleManager;
2997
+ }
2998
+ type RequestHandler = (req: http.IncomingMessage | http2.Http2ServerRequest, res: http.ServerResponse | http2.Http2ServerResponse) => Promise<void>;
2999
+
3000
+ /**
3001
+ * BlaizeJS Plugin Module
3002
+ *
3003
+ * Provides the plugin system for extending framework functionality.
1735
3004
  */
1736
- type SSEConnectionState = 'connecting' | 'connected' | 'disconnected' | 'closed';
3005
+
1737
3006
  /**
1738
- * SSE stream interface for managing server-sent events
1739
- *
1740
- * @example
1741
- * ```typescript
1742
- * const stream: SSEStream = createSSEStream(response);
1743
- *
1744
- * // Send typed event
1745
- * stream.send('notification', { type: 'info', message: 'Update available' });
1746
- *
1747
- * // Send error event
1748
- * stream.sendError(new Error('Processing failed'));
1749
- *
1750
- * // Clean up on close
1751
- * stream.onClose(() => {
1752
- * console.log('Client disconnected');
1753
- * });
3007
+ * Plugin options
3008
+ */
3009
+ interface PluginOptions<_T = any> {
3010
+ /** Plugin configuration */
3011
+ [key: string]: any;
3012
+ }
3013
+ /**
3014
+ * Plugin lifecycle hooks with full type safety
1754
3015
  *
1755
- * // Close stream
1756
- * stream.close();
1757
- * ```
3016
+ * Plugins execute in this order:
3017
+ * 1. register() - Add middleware, routes
3018
+ * 2. initialize() - Create resources
3019
+ * 3. onServerStart() - Start background work
3020
+ * 4. onServerStop() - Stop background work
3021
+ * 5. terminate() - Cleanup resources
1758
3022
  */
1759
- interface SSEStream {
1760
- /**
1761
- * Send an event with typed data to the client
1762
- * @template T - Type of the data payload
1763
- * @param event - Event name/type
1764
- * @param data - Event data payload
1765
- */
1766
- send<T>(event: string, data: T): void;
1767
- /**
1768
- * Send an error event to the client
1769
- * @param error - Error object to send
1770
- */
1771
- sendError(error: Error): void;
3023
+ interface PluginHooks<TState = {}, TServices = {}> {
1772
3024
  /**
1773
- * Close the SSE stream connection
3025
+ * Called when plugin is registered to server
3026
+ *
3027
+ * Use this hook to:
3028
+ * - Add middleware via server.use()
3029
+ * - Add routes via server.router.addRoute()
3030
+ * - Subscribe to server events
3031
+ *
3032
+ * @param server - BlaizeJS server instance
3033
+ * @example
3034
+ * ```typescript
3035
+ * register: async (server) => {
3036
+ * server.use(createMiddleware({
3037
+ * handler: async (ctx, next) => {
3038
+ * ctx.services.db = db;
3039
+ * await next();
3040
+ * },
3041
+ * }));
3042
+ * }
3043
+ * ```
1774
3044
  */
1775
- close(): void;
3045
+ register?: (server: Server<TState, TServices>) => void | Promise<void>;
1776
3046
  /**
1777
- * Register a callback for stream closure
1778
- * @param cb - Callback function to execute on close
3047
+ * Called during server initialization
3048
+ *
3049
+ * Use this hook to:
3050
+ * - Create database connections
3051
+ * - Initialize services
3052
+ * - Allocate resources
3053
+ *
3054
+ * @example
3055
+ * ```typescript
3056
+ * initialize: async () => {
3057
+ * db = await Database.connect(config);
3058
+ * }
3059
+ * ```
1779
3060
  */
1780
- onClose(cb: () => void): void;
1781
- }
1782
- /**
1783
- * Extended SSE stream with additional control methods
1784
- */
1785
- interface SSEStreamExtended extends SSEStream {
1786
- readonly id: string;
1787
- [Symbol.asyncIterator](): AsyncGenerator<BufferedEvent, void, unknown>;
1788
- /** Current connection state */
1789
- readonly state: SSEConnectionState;
1790
- /** Number of events in the buffer */
1791
- readonly bufferSize: number;
1792
- /** Check if stream is writable */
1793
- readonly isWritable: boolean;
3061
+ initialize?: (server: Server<TState, TServices>) => void | Promise<void>;
1794
3062
  /**
1795
- * Ping the client to keep connection alive
1796
- * @param comment - Optional comment to include in ping
3063
+ * Called when server starts listening
3064
+ *
3065
+ * Use this hook to:
3066
+ * - Start background workers
3067
+ * - Start cron jobs
3068
+ * - Begin health checks
3069
+ *
3070
+ * @example
3071
+ * ```typescript
3072
+ * onServerStart: async () => {
3073
+ * worker = new BackgroundWorker();
3074
+ * await worker.start();
3075
+ * }
3076
+ * ```
1797
3077
  */
1798
- ping(comment?: string): void;
3078
+ onServerStart?: (server: Http2Server | Server$1) => void | Promise<void>;
1799
3079
  /**
1800
- * Set retry interval for client reconnection
1801
- * @param milliseconds - Retry interval in milliseconds
3080
+ * Called when server stops listening
3081
+ *
3082
+ * Use this hook to:
3083
+ * - Stop background workers
3084
+ * - Flush buffers
3085
+ * - Complete in-flight work
3086
+ *
3087
+ * @example
3088
+ * ```typescript
3089
+ * onServerStop: async () => {
3090
+ * await worker.stop({ graceful: true });
3091
+ * }
3092
+ * ```
1802
3093
  */
1803
- setRetry(milliseconds: number): void;
3094
+ onServerStop?: (server: Http2Server | Server$1) => void | Promise<void>;
1804
3095
  /**
1805
- * Flush any buffered events immediately
3096
+ * Called during server termination
3097
+ *
3098
+ * Use this hook to:
3099
+ * - Close database connections
3100
+ * - Release file handles
3101
+ * - Free memory
3102
+ *
3103
+ * @example
3104
+ * ```typescript
3105
+ * terminate: async () => {
3106
+ * await db?.close();
3107
+ * }
3108
+ * ```
1806
3109
  */
1807
- flush(): void;
1808
- getMetrics(): StreamMetrics;
1809
- }
1810
- /**
1811
- * SSE event serialization format
1812
- */
1813
- interface SSESerializedEvent {
1814
- /** Event ID field */
1815
- id?: string;
1816
- /** Event type field */
1817
- event?: string;
1818
- /** Data field (can be multi-line) */
1819
- data: string;
1820
- /** Retry field */
1821
- retry?: number;
1822
- /** Comment field for keep-alive */
1823
- comment?: string;
1824
- }
1825
- /**
1826
- * SSE event handler function type
1827
- * @template T - Type of the event data
1828
- */
1829
- type SSEEventHandler<T = unknown> = (event: SSEEvent<T>) => void | Promise<void>;
1830
- /**
1831
- * SSE event listener registration
1832
- */
1833
- interface SSEEventListener {
1834
- /** Event type to listen for (use '*' for all events) */
1835
- event: string;
1836
- /** Handler function for the event */
1837
- handler: SSEEventHandler;
1838
- /** Optional listener identifier for removal */
1839
- id?: string;
1840
- }
1841
- /**
1842
- * SSE metrics for monitoring stream performance
1843
- */
1844
- interface SSEMetrics {
1845
- /** Total number of events sent */
1846
- eventsSent: number;
1847
- /** Total number of events dropped */
1848
- eventsDropped: number;
1849
- /** Current number of connected clients */
1850
- activeConnections: number;
1851
- /** Total bytes sent */
1852
- bytesSent: number;
1853
- /** Average event send latency in milliseconds */
1854
- averageLatency: number;
1855
- /** Connection duration in milliseconds */
1856
- connectionDuration: number;
3110
+ terminate?: (server: Server<TState, TServices>) => void | Promise<void>;
1857
3111
  }
1858
3112
  /**
1859
- * SSE stream manager for handling multiple clients
3113
+ * Options for creating a plugin with createPlugin()
3114
+ *
3115
+ * @template TConfig - Plugin configuration shape
3116
+ * @template TState - State added to context
3117
+ * @template TServices - Services added to context
1860
3118
  */
1861
- interface SSEStreamManager {
1862
- /**
1863
- * Create a new SSE stream for a client
1864
- * @param clientId - Unique identifier for the client
1865
- * @param options - Stream configuration options
1866
- */
1867
- createStream(clientId: string, options?: SSEOptions): SSEStream;
3119
+ interface CreatePluginOptions<TConfig, TState = {}, TServices = {}> {
1868
3120
  /**
1869
- * Get an existing stream by client ID
1870
- * @param clientId - Client identifier
3121
+ * Plugin name (e.g., '@blaizejs/metrics')
3122
+ * Must be unique within a server instance
1871
3123
  */
1872
- getStream(clientId: string): SSEStream | undefined;
3124
+ name: string;
1873
3125
  /**
1874
- * Broadcast an event to all connected clients
1875
- * @template T - Type of the event data
1876
- * @param event - Event name
1877
- * @param data - Event data
3126
+ * Semantic version (e.g., '1.0.0')
3127
+ * Used for compatibility checks
1878
3128
  */
1879
- broadcast<T>(event: string, data: T): void;
3129
+ version: string;
1880
3130
  /**
1881
- * Broadcast to specific clients
1882
- * @template T - Type of the event data
1883
- * @param clientIds - Array of client IDs
1884
- * @param event - Event name
1885
- * @param data - Event data
3131
+ * Default configuration values
3132
+ * Merged with user config when plugin is created
3133
+ *
3134
+ * @example
3135
+ * ```typescript
3136
+ * defaultConfig: {
3137
+ * enabled: true,
3138
+ * timeout: 30000,
3139
+ * }
3140
+ * ```
1886
3141
  */
1887
- multicast<T>(clientIds: string[], event: string, data: T): void;
3142
+ defaultConfig?: TConfig;
1888
3143
  /**
1889
- * Close a specific client stream
1890
- * @param clientId - Client identifier
3144
+ * Setup function that returns lifecycle hooks
3145
+ *
3146
+ * Receives merged config (defaultConfig + userConfig).
3147
+ * Returns partial hook object - all hooks optional.
3148
+ *
3149
+ * @param config - Merged configuration
3150
+ * @returns Partial plugin hooks
3151
+ *
3152
+ * @example
3153
+ * ```typescript
3154
+ * setup: (config) => {
3155
+ * let db: Database;
3156
+ *
3157
+ * return {
3158
+ * initialize: async () => {
3159
+ * db = await Database.connect(config);
3160
+ * },
3161
+ * terminate: async () => {
3162
+ * await db?.close();
3163
+ * },
3164
+ * };
3165
+ * }
3166
+ * ```
1891
3167
  */
1892
- closeStream(clientId: string): void;
3168
+ setup: (config: TConfig, logger: BlaizeLogger) => Partial<PluginHooks<TState, TServices>>;
3169
+ }
3170
+ /**
3171
+ * Plugin interface
3172
+ */
3173
+ interface Plugin<TState = {}, TServices = {}> extends PluginHooks<TState, TServices> {
3174
+ /** Plugin name */
3175
+ name: string;
3176
+ /** Plugin version */
3177
+ version: string;
1893
3178
  /**
1894
- * Close all active streams
3179
+ * Called when plugin is registered to server
3180
+ *
3181
+ * This hook is always present - createPlugin provides a default empty async function
3182
+ * if not specified by the plugin author.
3183
+ *
3184
+ * @override Makes register required (not optional like in PluginHooks)
1895
3185
  */
1896
- closeAll(): void;
3186
+ register: (server: Server<TState, TServices>) => void | Promise<void>;
1897
3187
  /**
1898
- * Get metrics for all streams
3188
+ * Type carriers for compile-time type information
3189
+ * These are never used at runtime but allow TypeScript to track types
1899
3190
  */
1900
- getMetrics(): SSEMetrics;
3191
+ _state?: TState;
3192
+ _services?: TServices;
1901
3193
  }
1902
3194
  /**
1903
- * Result type for operations that can fail
3195
+ * Plugin factory function
1904
3196
  */
1905
- type RegistryResult<T> = {
1906
- success: true;
1907
- value: T;
1908
- } | {
1909
- success: false;
1910
- error: string;
1911
- };
3197
+ type PluginFactory<TConfig = any, TState = {}, TServices = {}> = (options?: Partial<TConfig>) => Plugin<TState, TServices>;
3198
+ interface PluginLifecycleManager {
3199
+ initializePlugins(server: Server<any, any>): Promise<void>;
3200
+ terminatePlugins(server: Server<any, any>): Promise<void>;
3201
+ onServerStart(server: Server<any, any>, httpServer: any): Promise<void>;
3202
+ onServerStop(server: Server<any, any>, httpServer: any): Promise<void>;
3203
+ }
3204
+ interface PluginLifecycleOptions {
3205
+ /** Continue initialization even if a plugin fails */
3206
+ continueOnError?: boolean;
3207
+ /** Custom error handler for plugin failures */
3208
+ onError?: (plugin: Plugin, phase: string, error: Error) => void;
3209
+ }
3210
+
1912
3211
  /**
1913
- * Connection metadata stored in the registry
3212
+ * Type composition utilities for extracting and composing middleware type contributions
3213
+ * @module composition
3214
+ * @since v0.4.0
1914
3215
  */
1915
- interface ConnectionEntry {
1916
- stream: SSEStream;
1917
- connectedAt: number;
1918
- lastActivity: number;
1919
- clientIp?: string;
1920
- userAgent?: string;
1921
- }
3216
+
1922
3217
  /**
1923
- * Internal connection registry interface
3218
+ * Extracts the State type contribution from a middleware
3219
+ * @template T - The middleware type to extract from
3220
+ * @returns The state type if present, empty object otherwise
1924
3221
  */
1925
- interface ConnectionRegistry {
1926
- /** Add a new connection to the registry */
1927
- add: (id: string, stream: SSEStream, metadata?: {
1928
- clientIp?: string;
1929
- userAgent?: string;
1930
- }) => void;
1931
- /** Remove a connection from the registry */
1932
- remove: (id: string) => void;
1933
- /** Get current connection count */
1934
- count: () => number;
1935
- /** Clean up inactive or closed connections */
1936
- cleanup: () => void;
1937
- /** Get connection by ID (for internal use) */
1938
- get: (id: string) => SSEStream | undefined;
1939
- /** Check if a connection exists */
1940
- has: (id: string) => boolean;
1941
- /** Get all connection IDs */
1942
- getIds: () => string[];
1943
- /** Shutdown the registry and close all connections */
1944
- shutdown: () => void;
1945
- }
3222
+ type ExtractMiddlewareState<T> = T extends Middleware<infer S, any> ? S : {};
1946
3223
  /**
1947
- * Extended stream interface for typed events
3224
+ * Extracts the State type contribution from a plugin
3225
+ * @template T - The plugin type to extract from
3226
+ * @returns The state type if present, empty object otherwise
1948
3227
  */
1949
- interface TypedSSEStream<TEvents extends Record<string, z.ZodType>> extends SSEStreamExtended {
1950
- send<K extends keyof TEvents>(event: K & string, data: z.infer<TEvents[K]>): void;
1951
- }
3228
+ type ExtractPluginState<T> = T extends Plugin<infer S, any> ? S : {};
1952
3229
  /**
1953
- * Schema for SSE route validation with generic type parameters
3230
+ * Extracts the Services type contribution from a middleware
3231
+ * @template T - The middleware type to extract from
3232
+ * @returns The services type if present, empty object otherwise
1954
3233
  */
1955
- interface SSERouteSchema<P extends z.ZodType = z.ZodType<any>, Q extends z.ZodType = z.ZodType<any>, E = any> {
1956
- /** Parameter schema for validation */
1957
- params?: P;
1958
- /** Query schema for validation */
1959
- query?: Q;
1960
- /** Events schema for validation (SSE-specific, replaces response) */
1961
- events?: E;
1962
- }
3234
+ type ExtractMiddlewareServices<T> = T extends Middleware<any, infer S> ? S : {};
1963
3235
  /**
1964
- * SSE route handler function with stream as first parameter
1965
- * This is the user-facing API - they write handlers with this signature
3236
+ * Extracts the Services type contribution from a plugin
3237
+ * @template T - The plugin type to extract from
3238
+ * @returns The services type if present, empty object otherwise
1966
3239
  */
1967
- type SSERouteHandler<TStream extends SSEStreamExtended = SSEStreamExtended, TParams = Record<string, string>, TQuery = Record<string, string | string[] | undefined>, TState extends State = State, TServices extends Services = Services> = (stream: TStream, ctx: Context<TState, TServices, never, TQuery>, // SSE never has body
1968
- params: TParams) => Promise<void> | void;
3240
+ type ExtractPluginServices<T> = T extends Plugin<any, infer S> ? S : {};
1969
3241
  /**
1970
- * SSE route creator with state and services support
1971
- * Returns a higher-order function to handle generics properly
3242
+ * Utility type to convert a union type to an intersection type
3243
+ * This is the magic that allows us to compose multiple middleware contributions
3244
+ *
3245
+ * @example
3246
+ * type U = { a: string } | { b: number }
3247
+ * type I = UnionToIntersection<U> // { a: string } & { b: number }
1972
3248
  *
1973
- * The return type matches what the implementation actually returns:
1974
- * - A route object with a GET property
1975
- * - The GET property contains the wrapped handler and schemas
1976
- * - The wrapped handler has the standard (ctx, params) signature expected by the router
1977
3249
  */
1978
- type CreateSSERoute = <TState extends State = State, TServices extends Services = Services>() => <P = never, Q = never, E = never>(config: {
1979
- schema?: {
1980
- params?: P extends never ? never : P;
1981
- query?: Q extends never ? never : Q;
1982
- events?: E extends never ? never : E;
1983
- };
1984
- handler: SSERouteHandler<E extends Record<string, z.ZodType> ? TypedSSEStream<E> : SSEStreamExtended, P extends z.ZodType ? Infer<P> : Record<string, string>, Q extends z.ZodType ? Infer<Q> : QueryParams, TState, TServices>;
1985
- middleware?: Middleware[];
1986
- options?: Record<string, unknown>;
1987
- }) => {
1988
- GET: {
1989
- handler: (ctx: any, params: any) => Promise<void>;
1990
- schema?: {
1991
- params?: P extends never ? undefined : P;
1992
- query?: Q extends never ? undefined : Q;
1993
- };
1994
- middleware?: Middleware[];
1995
- options?: Record<string, unknown>;
1996
- };
1997
- path: string;
1998
- };
3250
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
1999
3251
  /**
2000
- * Buffered event with metadata
3252
+ * Composes state contributions from an array of middleware
3253
+ * Merges all state types into a single intersection type
3254
+ *
3255
+ * @template T - ReadonlyArray of Middleware
3256
+ * @returns Intersection of all state contributions
3257
+ *
3258
+ * @example
3259
+ * const middlewares = [authMiddleware, loggerMiddleware] as const;
3260
+ * type ComposedState = ComposeStates<typeof middlewares>;
3261
+ * // Result: { user: User } & { requestId: string }
2001
3262
  */
2002
- interface BufferedEvent {
2003
- id: string;
2004
- event: string;
2005
- data: unknown;
2006
- size: number;
2007
- timestamp: number;
2008
- correlationId: string;
2009
- }
3263
+ type ComposeMiddlewareStates<T extends ReadonlyArray<Middleware>> = T extends readonly [] ? {} : UnionToIntersection<ExtractMiddlewareState<T[number]>>;
2010
3264
  /**
2011
- * Stream metrics for monitoring
3265
+ * Composes state contributions from an array of plugins
3266
+ * Merges all state types into a single intersection type
3267
+ *
3268
+ * @template T - ReadonlyArray of Plugin
3269
+ * @returns Intersection of all state contributions
3270
+ *
3271
+ * @example
3272
+ * const plugins = [authPlugin, dbPlugin] as const;
3273
+ * type ComposedState = ComposePluginStates<typeof plugins>;
3274
+ * // Result: { config: AuthConfig } & { dbConnected: boolean }
2012
3275
  */
2013
- interface StreamMetrics {
2014
- eventsSent: number;
2015
- eventsDropped: number;
2016
- bytesWritten: number;
2017
- bufferHighWatermark: number;
2018
- lastEventTime: number;
2019
- }
2020
-
3276
+ type ComposePluginStates<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly [] ? {} : UnionToIntersection<ExtractPluginState<T[number]>>;
2021
3277
  /**
2022
- * SSE Client Types for BlaizeJS
2023
- * Location: packages/blaize-client/src/sse/types.ts
3278
+ * Composes service contributions from an array of middleware
3279
+ * Merges all service types into a single intersection type
3280
+ *
3281
+ * @template T - ReadonlyArray of Middleware
3282
+ * @returns Intersection of all service contributions
3283
+ *
3284
+ * @example
3285
+ * const middlewares = [dbMiddleware, cacheMiddleware] as const;
3286
+ * type ComposedServices = ComposeServices<typeof middlewares>;
3287
+ * // Result: { db: Database } & { cache: Cache }
3288
+ */
3289
+ type ComposeMiddlewareServices<T extends ReadonlyArray<Middleware>> = T extends readonly [] ? {} : UnionToIntersection<ExtractMiddlewareServices<T[number]>>;
3290
+ /**
3291
+ * Composes service contributions from an array of plugins
3292
+ * Merges all service types into a single intersection type
3293
+ *
3294
+ * @template T - ReadonlyArray of Plugin
3295
+ * @returns Intersection of all service contributions
3296
+ *
3297
+ * @example
3298
+ * const plugins = [dbPlugin, cachePlugin] as const;
3299
+ * type ComposedServices = ComposePluginServices<typeof plugins>;
3300
+ * // Result: { db: Database } & { cache: Cache }
3301
+ */
3302
+ type ComposePluginServices<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly [] ? {} : UnionToIntersection<ExtractPluginServices<T[number]>>;
3303
+ /**
3304
+ * Safe version of ExtractState that handles edge cases
3305
+ * @template T - The middleware type to extract from
3306
+ * @returns The state type, handling never/any/unknown gracefully
3307
+ */
3308
+ type SafeExtractMiddlewareState<T> = IsNever<T> extends true ? {} : IsAny<T> extends true ? {} : T extends Middleware<infer S, any> ? unknown extends S ? {} : S : {};
3309
+ /**
3310
+ * Safe version of ExtractPluginState that handles edge cases
3311
+ * @template T - The plugin type to extract from
3312
+ * @returns The state type, handling never/any/unknown gracefully
2024
3313
  */
2025
-
3314
+ type SafeExtractPluginState<T> = IsNever<T> extends true ? {} : IsAny<T> extends true ? {} : T extends Plugin<infer S, any> ? unknown extends S ? {} : S : {};
2026
3315
  /**
2027
- * Event handlers map
3316
+ * Safe version of ExtractServices that handles edge cases
3317
+ * @template T - The middleware type to extract from
3318
+ * @returns The services type, handling never/any/unknown gracefully
2028
3319
  */
2029
- interface EventHandlers {
2030
- [event: string]: Set<(data: any) => void>;
2031
- }
3320
+ type SafeExtractMiddlewareServices<T> = IsNever<T> extends true ? {} : IsAny<T> extends true ? {} : T extends Middleware<any, infer S> ? unknown extends S ? {} : S : {};
2032
3321
  /**
2033
- * SSE connection configuration options
3322
+ * Safe version of ExtractPluginServices that handles edge cases
3323
+ * @template T - The plugin type to extract from
3324
+ * @returns The services type, handling never/any/unknown gracefully
2034
3325
  */
2035
- interface SSEClientOptions {
2036
- headers?: Record<string, string>;
2037
- withCredentials?: boolean;
2038
- reconnect?: {
2039
- enabled: boolean;
2040
- maxAttempts?: number;
2041
- strategy?: ReconnectStrategy;
2042
- initialDelay?: number;
2043
- };
2044
- bufferMissedEvents?: boolean;
2045
- maxMissedEvents?: number;
2046
- heartbeatTimeout?: number;
2047
- parseJSON?: boolean;
2048
- /**
2049
- * Whether to wait for connection before resolving the promise.
2050
- * If false, returns the client immediately without waiting.
2051
- * Default: true
2052
- */
2053
- waitForConnection?: boolean;
2054
- /**
2055
- * Optional timeout for initial connection in milliseconds.
2056
- * If not set, no timeout is applied (relies on EventSource native timeout).
2057
- * Only applies if waitForConnection is true.
2058
- */
2059
- connectionTimeout?: number;
2060
- }
3326
+ type SafeExtractPluginServices<T> = IsNever<T> extends true ? {} : IsAny<T> extends true ? {} : T extends Plugin<any, infer S> ? unknown extends S ? {} : S : {};
2061
3327
  /**
2062
- * Metrics for SSE connection monitoring
3328
+ * Composes state with better edge case handling
3329
+ * @template T - ReadonlyArray of Middleware
3330
+ * @returns Safely composed state types
2063
3331
  */
2064
- interface SSEClientMetrics {
2065
- eventsReceived: number;
2066
- bytesReceived: number;
2067
- connectionDuration: number;
2068
- reconnectAttempts: number;
2069
- lastEventId?: string;
2070
- }
3332
+ type SafeComposeMiddlewareStates<T extends ReadonlyArray<Middleware>> = T extends readonly [] ? {} : T extends readonly [infer First, ...infer Rest] ? First extends Middleware ? Rest extends ReadonlyArray<Middleware> ? SafeExtractMiddlewareState<First> & SafeComposeMiddlewareStates<Rest> : SafeExtractMiddlewareState<First> : {} : UnionToIntersection<SafeExtractMiddlewareState<T[number]>>;
2071
3333
  /**
2072
- * Reconnection delay calculation strategy
3334
+ * Composes plugin state with better edge case handling
3335
+ * @template T - ReadonlyArray of Plugin
3336
+ * @returns Safely composed state types
2073
3337
  */
2074
- type ReconnectStrategy = (attempt: number) => number;
3338
+ type SafeComposePluginStates<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly [] ? {} : T extends readonly [infer First, ...infer Rest] ? First extends Plugin<any, any> ? Rest extends ReadonlyArray<Plugin<any, any>> ? SafeExtractPluginState<First> & SafeComposePluginStates<Rest> : SafeExtractPluginState<First> : {} : UnionToIntersection<SafeExtractPluginState<T[number]>>;
2075
3339
  /**
2076
- * SSE Client interface with type-safe event handling
3340
+ * Composes services with better edge case handling
3341
+ * @template T - ReadonlyArray of Middleware
3342
+ * @returns Safely composed service types
2077
3343
  */
2078
- interface SSEClient<TEvents extends Record<string, unknown> = Record<string, unknown>> {
2079
- on<K extends keyof TEvents>(event: K & string, handler: (data: TEvents[K]) => void): void;
2080
- on(event: 'error', handler: (error: BlaizeError) => void): void;
2081
- on(event: 'open', handler: () => void): void;
2082
- on(event: 'close', handler: (event: CloseEvent) => void): void;
2083
- off<K extends keyof TEvents>(event: K & string, handler?: (data: TEvents[K]) => void): void;
2084
- off(event: 'error', handler?: (error: BlaizeError) => void): void;
2085
- off(event: 'open', handler?: () => void): void;
2086
- off(event: 'close', handler?: (event: CloseEvent) => void): void;
2087
- once<K extends keyof TEvents>(event: K & string, handler: (data: TEvents[K]) => void): void;
2088
- once(event: 'error', handler: (error: BlaizeError) => void): void;
2089
- once(event: 'open', handler: () => void): void;
2090
- once(event: 'close', handler: (event: CloseEvent) => void): void;
2091
- close(): void;
2092
- readonly state: SSEConnectionState;
2093
- readonly metrics: SSEClientMetrics;
2094
- readonly lastEventId?: string;
2095
- }
3344
+ type SafeComposeMiddlewareServices<T extends ReadonlyArray<Middleware>> = T extends readonly [] ? {} : T extends readonly [infer First, ...infer Rest] ? First extends Middleware ? Rest extends ReadonlyArray<Middleware> ? SafeExtractMiddlewareServices<First> & SafeComposeMiddlewareServices<Rest> : SafeExtractMiddlewareServices<First> : {} : UnionToIntersection<SafeExtractMiddlewareServices<T[number]>>;
2096
3345
  /**
2097
- * Close event for SSE connections
3346
+ * Composes plugin services with better edge case handling
3347
+ * @template T - ReadonlyArray of Plugin
3348
+ * @returns Safely composed service types
2098
3349
  */
2099
- interface CloseEvent {
2100
- reconnect: boolean;
2101
- reason?: string;
2102
- }
3350
+ type SafeComposePluginServices<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly [] ? {} : T extends readonly [infer First, ...infer Rest] ? First extends Plugin<any, any> ? Rest extends ReadonlyArray<Plugin<any, any>> ? SafeExtractPluginServices<First> & SafeComposePluginServices<Rest> : SafeExtractPluginServices<First> : {} : UnionToIntersection<SafeExtractPluginServices<T[number]>>;
2103
3351
  /**
2104
- * Internal SSE connection factory
2105
- * Returns a Promise that resolves to an SSEClient instance
3352
+ * Utility to merge two state types
3353
+ * Handles conflicts by using the rightmost (latest) type
3354
+ *
3355
+ * @template A - First state type
3356
+ * @template B - Second state type
3357
+ * @returns Merged state with B taking precedence
2106
3358
  */
2107
- type SSEConnectionFactory<TEvents extends Record<string, unknown> = Record<string, unknown>> = (options?: SSEClientOptions) => Promise<SSEClient<TEvents>>;
2108
-
2109
- type ExtractMethod<T> = T extends {
2110
- GET: any;
2111
- } ? 'GET' : T extends {
2112
- POST: any;
2113
- } ? 'POST' : T extends {
2114
- PUT: any;
2115
- } ? 'PUT' : T extends {
2116
- DELETE: any;
2117
- } ? 'DELETE' : T extends {
2118
- PATCH: any;
2119
- } ? 'PATCH' : T extends {
2120
- HEAD: any;
2121
- } ? 'HEAD' : T extends {
2122
- OPTIONS: any;
2123
- } ? 'OPTIONS' : never;
2124
- type BuildRoutesRegistry<TRoutes extends Record<string, any>> = {
2125
- [Method in ExtractMethod<TRoutes[keyof TRoutes]> as `$${Lowercase<Method>}`]: {
2126
- [K in keyof TRoutes as ExtractMethod<TRoutes[K]> extends Method ? K : never]: TRoutes[K];
2127
- };
2128
- };
2129
- type GetRouteMethodOptions<TRoute> = TRoute extends {
2130
- GET: infer M;
2131
- } ? M : TRoute extends {
2132
- POST: infer M;
2133
- } ? M : TRoute extends {
2134
- PUT: infer M;
2135
- } ? M : TRoute extends {
2136
- DELETE: infer M;
2137
- } ? M : TRoute extends {
2138
- PATCH: infer M;
2139
- } ? M : TRoute extends {
2140
- HEAD: infer M;
2141
- } ? M : TRoute extends {
2142
- OPTIONS: infer M;
2143
- } ? M : never;
2144
- type IsNever$1<T> = [T] extends [never] ? true : false;
2145
- type BuildArgsObject<P, Q, B> = (IsNever$1<P> extends true ? {} : {
2146
- params: Infer<P>;
2147
- }) & (IsNever$1<Q> extends true ? {} : {
2148
- query: Infer<Q>;
2149
- }) & (IsNever$1<B> extends true ? {} : {
2150
- body: Infer<B>;
2151
- });
2152
- type IsEmptyObject<T> = keyof T extends never ? true : false;
2153
- type BuildArgs<P, Q, B> = IsEmptyObject<BuildArgsObject<P, Q, B>> extends true ? void : BuildArgsObject<P, Q, B>;
2154
- type CreateClientMethod<TRoute> = GetRouteMethodOptions<TRoute> extends RouteMethodOptions<infer P, infer Q, infer B, infer R> ? BuildArgs<P, Q, B> extends void ? () => Promise<R extends z.ZodType ? Infer<R> : unknown> : (args: BuildArgs<P, Q, B>) => Promise<R extends z.ZodType ? Infer<R> : unknown> : never;
2155
- type CreateClient<TRoutes extends Record<string, Record<string, any>>> = {
2156
- [Method in keyof TRoutes]: {
2157
- [RouteName in keyof TRoutes[Method]]: CreateClientMethod<TRoutes[Method][RouteName]>;
2158
- };
2159
- };
2160
- interface ClientConfig {
2161
- baseUrl: string;
2162
- defaultHeaders?: Record<string, string>;
2163
- timeout?: number;
2164
- sse?: SSEClientOptions;
2165
- }
2166
- interface InternalRequestArgs {
2167
- params?: Record<string, any>;
2168
- query?: Record<string, any>;
2169
- body?: any;
2170
- }
2171
- interface RequestOptions {
2172
- method: string;
2173
- url: string;
2174
- headers: Record<string, string>;
2175
- body?: string;
2176
- timeout: number;
2177
- }
3359
+ type MergeStates<A, B> = Omit<A, keyof B> & B;
2178
3360
  /**
2179
- * Detect if a route has SSE support
2180
- * SSE routes have a special 'SSE' method key
3361
+ * Utility to merge two service types
3362
+ * Handles conflicts by using the rightmost (latest) type
3363
+ *
3364
+ * @template A - First services type
3365
+ * @template B - Second services type
3366
+ * @returns Merged services with B taking precedence
2181
3367
  */
2182
- type HasSSEMethod<TRoute> = TRoute extends {
2183
- SSE: any;
2184
- } ? true : false;
3368
+ type MergeServices<A, B> = Omit<A, keyof B> & B;
2185
3369
  /**
2186
- * Extract SSE event types from route schema
3370
+ * Extract both state and services from a middleware at once
3371
+ * @template T - The middleware type
3372
+ * @returns Object with state and services types
2187
3373
  */
2188
- type ExtractSSEEvents<TRoute> = TRoute extends {
2189
- SSE: {
2190
- events?: infer E;
2191
- };
2192
- } ? E extends z.ZodType ? z.infer<E> : Record<string, unknown> : Record<string, unknown>;
3374
+ type ExtractMiddlewareTypes<T> = {
3375
+ state: ExtractMiddlewareState<T>;
3376
+ services: ExtractMiddlewareServices<T>;
3377
+ };
2193
3378
  /**
2194
- * Extract SSE query parameters from route
3379
+ * Extract both state and services from a plugin at once
3380
+ * @template T - The plugin type
3381
+ * @returns Object with state and services types
2195
3382
  */
2196
- type ExtractSSEQuery<TRoute> = TRoute extends {
2197
- SSE: {
2198
- schema?: {
2199
- query?: infer Q;
2200
- };
2201
- };
2202
- } ? Q extends z.ZodType ? z.infer<Q> : Record<string, unknown> : never;
3383
+ type ExtractPluginTypes<T> = {
3384
+ state: ExtractPluginState<T>;
3385
+ services: ExtractPluginServices<T>;
3386
+ };
2203
3387
  /**
2204
- * Extract SSE params from route
3388
+ * Compose both state and services from middleware array at once
3389
+ * @template T - ReadonlyArray of Middleware
3390
+ * @returns Object with composed state and services
2205
3391
  */
2206
- type ExtractSSEParams<TRoute> = TRoute extends {
2207
- SSE: {
2208
- schema?: {
2209
- params?: infer P;
2210
- };
2211
- };
2212
- } ? P extends z.ZodType ? z.infer<P> : Record<string, string> : never;
3392
+ type ComposeMiddlewareTypes<T extends ReadonlyArray<Middleware>> = {
3393
+ state: ComposeMiddlewareStates<T>;
3394
+ services: ComposeMiddlewareServices<T>;
3395
+ };
2213
3396
  /**
2214
- * Build SSE method arguments
3397
+ * Compose both state and services from plugin array at once
3398
+ * @template T - ReadonlyArray of Plugin
3399
+ * @returns Object with composed state and services
2215
3400
  */
2216
- type BuildSSEArgs<TRoute> = ExtractSSEParams<TRoute> extends never ? ExtractSSEQuery<TRoute> extends never ? {
2217
- options?: SSEClientOptions;
2218
- } : {
2219
- query: ExtractSSEQuery<TRoute>;
2220
- options?: SSEClientOptions;
2221
- } : ExtractSSEQuery<TRoute> extends never ? {
2222
- params: ExtractSSEParams<TRoute>;
2223
- options?: SSEClientOptions;
2224
- } : {
2225
- params: ExtractSSEParams<TRoute>;
2226
- query: ExtractSSEQuery<TRoute>;
2227
- options?: SSEClientOptions;
3401
+ type ComposePluginTypes<T extends ReadonlyArray<Plugin<any, any>>> = {
3402
+ state: ComposePluginStates<T>;
3403
+ services: ComposePluginServices<T>;
2228
3404
  };
2229
3405
  /**
2230
- * Create SSE client method
3406
+ * Type guard to check if a value is a Middleware
3407
+ * @param value - Value to check
3408
+ * @returns True if value is a Middleware
3409
+ */
3410
+ declare function isMiddleware(value: unknown): value is Middleware;
3411
+ /**
3412
+ * Type guard to check if a value is a Plugin
3413
+ * @param value - Value to check
3414
+ * @returns True if value is a Plugin
3415
+ */
3416
+ declare function isPlugin(value: unknown): value is Plugin;
3417
+ /**
3418
+ * Type helper for middleware arrays
3419
+ * Ensures proper readonly array typing for composition
3420
+ *
3421
+ * @example
3422
+ * const middlewares = asMiddlewareArray([auth, logger, cache]);
3423
+ * type State = ComposeStates<typeof middlewares>;
2231
3424
  */
2232
- type CreateSSEMethod<TRoute> = HasSSEMethod<TRoute> extends true ? BuildSSEArgs<TRoute> extends {
2233
- options?: SSEClientOptions;
2234
- } ? (args?: BuildSSEArgs<TRoute>) => Promise<SSEClient<ExtractSSEEvents<TRoute>>> : (args: BuildSSEArgs<TRoute>) => Promise<SSEClient<ExtractSSEEvents<TRoute>>> : never;
3425
+ declare function asMiddlewareArray<T extends ReadonlyArray<Middleware>>(middlewares: T): T;
2235
3426
  /**
2236
- * Extract SSE routes from registry
3427
+ * Type helper for plugin arrays
3428
+ * Ensures proper readonly array typing for composition
3429
+ *
3430
+ * @example
3431
+ * const plugins = asPluginArray([dbPlugin, cachePlugin]);
3432
+ * type Services = ComposePluginServices<typeof plugins>;
2237
3433
  */
2238
- type ExtractSSERoutes<TRoutes extends Record<string, any>> = {
2239
- [K in keyof TRoutes as HasSSEMethod<TRoutes[K]> extends true ? K : never]: TRoutes[K];
2240
- };
3434
+ declare function asPluginArray<T extends ReadonlyArray<Plugin<any, any>>>(plugins: T): T;
2241
3435
  /**
2242
- * Enhanced client with SSE support
3436
+ * Create a typed middleware array with inferred types
3437
+ * Useful for getting proper const assertions
3438
+ *
3439
+ * @example
3440
+ * const middlewares = createMiddlewareArray(auth, logger, cache);
3441
+ * type State = ComposeStates<typeof middlewares>;
2243
3442
  */
2244
- type CreateEnhancedClient<TRoutes extends Record<string, any>, TRegistry> = TRegistry & {
2245
- $sse: {
2246
- [K in keyof ExtractSSERoutes<TRoutes>]: CreateSSEMethod<TRoutes[K]>;
2247
- };
2248
- };
2249
-
3443
+ declare function createMiddlewareArray<T extends ReadonlyArray<Middleware>>(...middlewares: T): T;
2250
3444
  /**
2251
- * BlaizeJS Server Module - Enhanced with Correlation Configuration
3445
+ * Create a typed plugin array with inferred types
3446
+ * Useful for getting proper const assertions
2252
3447
  *
2253
- * Provides the core HTTP/2 server implementation with HTTP/1.1 fallback
2254
- * and correlation ID tracking configuration.
3448
+ * @example
3449
+ * const plugins = createPluginArray(dbPlugin, cachePlugin);
3450
+ * type Services = ComposePluginServices<typeof plugins>;
2255
3451
  */
3452
+ declare function createPluginArray<T extends ReadonlyArray<Plugin<any, any>>>(...plugins: T): T;
2256
3453
 
2257
- type UnknownServer = Server<Record<string, unknown>, Record<string, unknown>>;
2258
- interface Http2Options {
2259
- enabled?: boolean | undefined;
2260
- keyFile?: string | undefined;
2261
- certFile?: string | undefined;
2262
- }
2263
- interface StartOptions {
2264
- port?: number;
2265
- host?: string;
2266
- }
2267
- interface StopOptions {
2268
- timeout?: number;
2269
- plugins?: Plugin[];
2270
- onStopping?: () => Promise<void> | void;
2271
- onStopped?: () => Promise<void> | void;
2272
- }
2273
3454
  /**
2274
- * Correlation ID configuration options
3455
+ * Console Transport for Development
3456
+ *
3457
+ * Pretty-prints logs with colors for human-readable development output.
3458
+ * Uses Node.js built-in util.inspect for metadata formatting.
3459
+ *
3460
+ * @packageDocumentation
2275
3461
  */
2276
- interface CorrelationOptions {
2277
- /**
2278
- * The HTTP header name to use for correlation IDs
2279
- * @default 'x-correlation-id'
2280
- */
2281
- headerName?: string;
2282
- /**
2283
- * Custom correlation ID generator function
2284
- * @default () => `req_${timestamp}_${random}`
2285
- */
2286
- generator?: () => string;
2287
- }
3462
+
2288
3463
  /**
2289
- * Server options for configuring the BlaizeJS server
3464
+ * Console transport for development logging
3465
+ *
3466
+ * Outputs colorized, human-readable logs to the console.
3467
+ * Uses console.log/warn/error appropriately based on log level.
3468
+ *
3469
+ * Features:
3470
+ * - Colorized log levels (debug=gray, info=blue, warn=yellow, error=red)
3471
+ * - Pretty-printed metadata with util.inspect
3472
+ * - Error objects automatically serialized with stack traces
3473
+ * - Stateless - safe for concurrent logging
3474
+ *
3475
+ * @example
3476
+ * ```typescript
3477
+ * import { ConsoleTransport } from './transports';
3478
+ *
3479
+ * const transport = new ConsoleTransport();
3480
+ *
3481
+ * transport.write('info', 'User login', {
3482
+ * userId: '123',
3483
+ * method: 'oauth',
3484
+ * timestamp: '2025-10-20T15:30:00Z'
3485
+ * });
3486
+ *
3487
+ * // Output:
3488
+ * // [INFO] User login
3489
+ * // {
3490
+ * // userId: '123',
3491
+ * // method: 'oauth',
3492
+ * // timestamp: '2025-10-20T15:30:00Z'
3493
+ * // }
3494
+ * ```
2290
3495
  */
2291
- interface ServerOptionsInput {
2292
- /** Port to listen on (default: 3000) */
2293
- port?: number;
2294
- /** Host to bind to (default: localhost) */
2295
- host?: string;
2296
- /** Directory containing route files (default: ./routes) */
2297
- routesDir?: string;
2298
- /** HTTP/2 options */
2299
- http2?: {
2300
- /** Enable HTTP/2 (default: true) */
2301
- enabled?: boolean | undefined;
2302
- /** Path to key file for HTTPS/HTTP2 */
2303
- keyFile?: string | undefined;
2304
- /** Path to certificate file for HTTPS/HTTP2 */
2305
- certFile?: string | undefined;
2306
- };
2307
- /** Global middleware to apply to all routes */
2308
- middleware?: Middleware[];
2309
- /** Plugins to register */
2310
- plugins?: Plugin[];
2311
- /**
2312
- * Correlation ID configuration
2313
- * @since 0.4.0
2314
- */
2315
- correlation?: CorrelationOptions;
3496
+ declare class ConsoleTransport implements BlaizeLogTransport {
2316
3497
  /**
2317
- * CORS configuration
2318
- *
2319
- * - `true`: Enable CORS with development defaults (allow all origins)
2320
- * - `false`: Disable CORS (no headers set)
2321
- * - `CorsOptions`: Custom CORS configuration
2322
- *
2323
- * @default false (CORS disabled)
2324
- * @since 0.5.0
2325
- *
2326
- * @example
2327
- * ```typescript
2328
- * // Enable with dev defaults
2329
- * const server = createServer({ cors: true });
3498
+ * Write a log entry to the console
2330
3499
  *
2331
- * // Custom configuration
2332
- * const server = createServer({
2333
- * cors: {
2334
- * origin: 'https://example.com',
2335
- * credentials: true,
2336
- * maxAge: 86400
2337
- * }
2338
- * });
2339
- *
2340
- * // Disable CORS
2341
- * const server = createServer({ cors: false });
2342
- * ```
3500
+ * @param level - Log level
3501
+ * @param message - Log message
3502
+ * @param meta - Structured metadata
2343
3503
  */
2344
- cors?: CorsOptions | boolean;
2345
- bodyLimits?: Partial<BodyLimits>;
3504
+ write(level: LogLevel, message: string, meta: LogMetadata): void;
2346
3505
  }
3506
+
2347
3507
  /**
2348
- * Configuration for a BlaizeJS server
3508
+ * JSON Transport for Production
3509
+ *
3510
+ * Outputs single-line JSON logs for log aggregators and monitoring systems.
3511
+ * Handles circular references and serializes Error objects.
3512
+ *
3513
+ * @packageDocumentation
2349
3514
  */
2350
- interface ServerOptions {
2351
- /** Port to listen on (default: 3000) */
2352
- port: number;
2353
- /** Host to bind to (default: localhost) */
2354
- host: string;
2355
- /** Directory containing route files (default: ./routes) */
2356
- routesDir: string;
2357
- /** HTTP/2 options */
2358
- http2?: {
2359
- /** Enable HTTP/2 (default: true) */
2360
- enabled?: boolean | undefined;
2361
- /** Path to key file for HTTPS/HTTP2 */
2362
- keyFile?: string | undefined;
2363
- /** Path to certificate file for HTTPS/HTTP2 */
2364
- certFile?: string | undefined;
2365
- };
2366
- /** Global middleware to apply to all routes */
2367
- middleware?: Middleware[];
2368
- /** Plugins to register */
2369
- plugins?: Plugin[];
2370
- /**
2371
- * Correlation ID configuration
2372
- * @since 0.4.0
2373
- */
2374
- correlation?: CorrelationOptions;
2375
- /**
2376
- * CORS configuration
2377
- * @since 0.5.0
2378
- */
2379
- cors?: CorsOptions | boolean;
2380
- bodyLimits: BodyLimits;
2381
- }
3515
+
2382
3516
  /**
2383
- * BlaizeJS Server instance with generic type accumulation
3517
+ * JSON transport for production logging
2384
3518
  *
2385
- * @template TState - The accumulated state type from middleware
2386
- * @template TServices - The accumulated services type from middleware and plugins
3519
+ * Outputs single-line JSON to stdout for log aggregators (CloudWatch,
3520
+ * Datadog, Splunk, etc.). Handles circular references safely and
3521
+ * serializes Error objects with stack traces.
3522
+ *
3523
+ * Features:
3524
+ * - Single-line JSON output (no pretty-printing)
3525
+ * - Circular reference handling via replacer function
3526
+ * - Error objects serialized with message, name, and stack
3527
+ * - Stateless - safe for concurrent logging
3528
+ * - All metadata flattened into top-level JSON object
3529
+ *
3530
+ * @example
3531
+ * ```typescript
3532
+ * import { JSONTransport } from './transports';
3533
+ *
3534
+ * const transport = new JSONTransport();
3535
+ *
3536
+ * transport.write('info', 'User login', {
3537
+ * userId: '123',
3538
+ * method: 'oauth',
3539
+ * timestamp: '2025-10-20T15:30:00Z',
3540
+ * correlationId: 'req_abc123'
3541
+ * });
3542
+ *
3543
+ * // Output (single line):
3544
+ * // {"level":"info","message":"User login","userId":"123","method":"oauth","timestamp":"2025-10-20T15:30:00Z","correlationId":"req_abc123"}
3545
+ * ```
3546
+ *
3547
+ * @example With Error Object
3548
+ * ```typescript
3549
+ * const error = new Error('Database connection failed');
3550
+ *
3551
+ * transport.write('error', 'Operation failed', {
3552
+ * error,
3553
+ * retryCount: 3
3554
+ * });
2387
3555
  *
3556
+ * // Output:
3557
+ * // {"level":"error","message":"Operation failed","error":{"message":"Database connection failed","name":"Error","stack":"Error: Database..."},"retryCount":3}
3558
+ * ```
2388
3559
  */
2389
- interface Server<TState, TServices> {
2390
- /** The underlying HTTP or HTTP/2 server */
2391
- server: http.Server | http2.Http2Server | undefined;
2392
- /** The port the server is configured to listen on */
2393
- port: number;
2394
- /** CORS configuration for this server */
2395
- corsOptions?: CorsOptions | boolean;
2396
- /** Body size limits for incoming requests */
2397
- bodyLimits: BodyLimits;
2398
- /** The host the server is bound to */
2399
- host: string;
2400
- events: EventEmitter;
2401
- /** Direct access to registered plugins */
2402
- plugins: Plugin[];
2403
- /** Direct access to registered plugins */
2404
- middleware: Middleware[];
2405
- /** Internal property for signal hanlders */
2406
- _signalHandlers?: {
2407
- unregister: () => void;
2408
- };
2409
- /** Start the server and listen for connections */
2410
- listen: (port?: number, host?: string) => Promise<Server<TState, TServices>>;
2411
- /** Stop the server */
2412
- close: (stopOptions?: StopOptions) => Promise<void>;
3560
+ declare class JSONTransport implements BlaizeLogTransport {
2413
3561
  /**
2414
- * Add global middleware to the server
2415
- *
2416
- * @param middleware - Single middleware or array of middleware to add
2417
- * @returns New Server instance with accumulated types from the middleware
2418
- *
2419
- * @example
2420
- * ```typescript
2421
- * // Single middleware
2422
- * const serverWithAuth = server.use(authMiddleware);
2423
- * // serverWithAuth has type Server<{user: User}, {auth: AuthService}>
3562
+ * Write a log entry as single-line JSON to stdout
2424
3563
  *
2425
- * // Array of middleware
2426
- * const serverWithMiddleware = server.use([authMiddleware, loggerMiddleware]);
2427
- * // serverWithMiddleware has type Server<{user, requestId}, {auth, logger}>
2428
- * ```
3564
+ * @param level - Log level
3565
+ * @param message - Log message
3566
+ * @param meta - Structured metadata
2429
3567
  */
2430
- use<MS, MSvc>(middleware: Middleware<MS, MSvc>): Server<TState & MS, TServices & MSvc>;
2431
- use<MW extends readonly Middleware<any, any>[]>(middleware: MW): Server<TState & UnionToIntersection<ExtractMiddlewareState<MW[number]>>, TServices & UnionToIntersection<ExtractMiddlewareServices<MW[number]>>>;
3568
+ write(level: LogLevel, message: string, meta: LogMetadata): void;
2432
3569
  /**
2433
- * Register a plugin with the server
3570
+ * Flush any buffered logs (optional)
2434
3571
  *
2435
- * @param plugin - Single plugin or array of plugins to register
2436
- * @returns Promise resolving to new Server instance with accumulated types
2437
- *
2438
- * @example
2439
- * ```typescript
2440
- * // Single plugin
2441
- * const serverWithDb = await server.register(databasePlugin);
2442
- * // serverWithDb has type Server<{}, {db: DatabaseService}>
3572
+ * Currently a no-op since we write directly to stdout.
3573
+ * Can be implemented for batching in the future if needed.
2443
3574
  *
2444
- * // Array of plugins
2445
- * const serverWithPlugins = await server.register([dbPlugin, cachePlugin]);
2446
- * // serverWithPlugins has type Server<{}, {db, cache}>
2447
- * ```
3575
+ * @returns Promise that resolves immediately
2448
3576
  */
2449
- register<PS, PSvc>(plugin: Plugin<PS, PSvc>): Promise<Server<TState & PS, TServices & PSvc>>;
2450
- register<P extends readonly Plugin<any, any>[]>(plugin: P): Promise<Server<TState & UnionToIntersection<ExtractPluginState<P[number]>>, TServices & UnionToIntersection<ExtractPluginServices<P[number]>>>>;
2451
- /** Access to the routing system */
2452
- router: Router;
2453
- /** Context storage system */
2454
- context: AsyncLocalStorage<Context>;
2455
- pluginManager: PluginLifecycleManager;
3577
+ flush(): Promise<void>;
2456
3578
  }
2457
- type RequestHandler = (req: http.IncomingMessage | http2.Http2ServerRequest, res: http.ServerResponse | http2.Http2ServerResponse) => Promise<void>;
2458
3579
 
2459
3580
  /**
2460
- * BlaizeJS Plugin Module
3581
+ * Null Transport for Testing
2461
3582
  *
2462
- * Provides the plugin system for extending framework functionality.
3583
+ * Silent transport that discards all logs. Used in tests to suppress output.
3584
+ *
3585
+ * @packageDocumentation
2463
3586
  */
2464
3587
 
2465
3588
  /**
2466
- * Plugin options
2467
- */
2468
- interface PluginOptions<_T = any> {
2469
- /** Plugin configuration */
2470
- [key: string]: any;
2471
- }
2472
- /**
2473
- * Plugin lifecycle hooks with full type safety
3589
+ * Null transport for testing and silent logging
2474
3590
  *
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
3591
+ * Discards all log entries without producing any output. Useful for:
3592
+ * - Unit tests that don't care about log output
3593
+ * - Benchmarks where logging overhead should be minimal
3594
+ * - Temporarily disabling logging without changing code
3595
+ *
3596
+ * Features:
3597
+ * - Zero overhead - no processing or I/O
3598
+ * - Stateless - safe for concurrent logging
3599
+ * - No output to stdout, stderr, or files
3600
+ *
3601
+ * @example In Tests
3602
+ * ```typescript
3603
+ * import { NullTransport } from './transports';
3604
+ * import { createLogger } from './Logger';
3605
+ *
3606
+ * describe('MyService', () => {
3607
+ * const logger = createLogger({
3608
+ * transport: new NullTransport() // Suppress logs in tests
3609
+ * });
3610
+ *
3611
+ * test('performs operation', () => {
3612
+ * const service = new MyService(logger);
3613
+ * service.doWork(); // No log output
3614
+ * });
3615
+ * });
3616
+ * ```
3617
+ *
3618
+ * @example Temporary Disable
3619
+ * ```typescript
3620
+ * // Temporarily disable logging without changing business logic
3621
+ * const logger = createLogger({
3622
+ * transport: new NullTransport()
3623
+ * });
3624
+ *
3625
+ * logger.info('This message is discarded');
3626
+ * logger.error('This error is discarded');
3627
+ * ```
2481
3628
  */
2482
- interface PluginHooks<TState = {}, TServices = {}> {
3629
+ declare class NullTransport implements BlaizeLogTransport {
2483
3630
  /**
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
3631
+ * Discard a log entry (no-op)
2490
3632
  *
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
- * ```
3633
+ * @param _level - Log level (unused)
3634
+ * @param _message - Log message (unused)
3635
+ * @param _meta - Structured metadata (unused)
2503
3636
  */
2504
- register?: (server: Server<TState, TServices>) => void | Promise<void>;
3637
+ write(_level: LogLevel, _message: string, _meta: LogMetadata): void;
2505
3638
  /**
2506
- * Called during server initialization
3639
+ * Flush any buffered logs (no-op)
2507
3640
  *
2508
- * Use this hook to:
2509
- * - Create database connections
2510
- * - Initialize services
2511
- * - Allocate resources
3641
+ * Since no logs are written, there's nothing to flush.
2512
3642
  *
2513
- * @example
2514
- * ```typescript
2515
- * initialize: async () => {
2516
- * db = await Database.connect(config);
2517
- * }
2518
- * ```
3643
+ * @returns Promise that resolves immediately
2519
3644
  */
2520
- initialize?: (server: Server<TState, TServices>) => void | Promise<void>;
3645
+ flush(): Promise<void>;
3646
+ }
3647
+
3648
+ /**
3649
+ * Core Logger Implementation
3650
+ *
3651
+ * Production-ready structured logger with level filtering, metadata redaction,
3652
+ * child loggers, and zero-overhead filtering for disabled log levels.
3653
+ *
3654
+ * @packageDocumentation
3655
+ */
3656
+
3657
+ /**
3658
+ * Core Logger class implementing ILogger interface
3659
+ *
3660
+ * Thread-safe via immutable inherited metadata. Supports zero-overhead
3661
+ * filtering - logs below the configured level return immediately with
3662
+ * no processing overhead.
3663
+ *
3664
+ * @example Basic Usage
3665
+ * ```typescript
3666
+ * const logger = new Logger({
3667
+ * level: 'info',
3668
+ * transport: new ConsoleTransport(),
3669
+ * redactKeys: ['password', 'apiKey'],
3670
+ * includeTimestamp: true
3671
+ * });
3672
+ *
3673
+ * logger.info('User login', { userId: '123', method: 'oauth' });
3674
+ * ```
3675
+ *
3676
+ * @example Child Logger
3677
+ * ```typescript
3678
+ * const parentLogger = createLogger({ level: 'info' });
3679
+ * const childLogger = parentLogger.child({ component: 'auth' });
3680
+ *
3681
+ * childLogger.info('Token verified');
3682
+ * // Output includes inherited metadata: { component: 'auth', ... }
3683
+ * ```
3684
+ */
3685
+ declare class Logger implements BlaizeLogger {
3686
+ private readonly config;
3687
+ private readonly inheritedMeta;
3688
+ private readonly minLevelPriority;
2521
3689
  /**
2522
- * Called when server starts listening
2523
- *
2524
- * Use this hook to:
2525
- * - Start background workers
2526
- * - Start cron jobs
2527
- * - Begin health checks
3690
+ * Create a new Logger instance
2528
3691
  *
2529
- * @example
2530
- * ```typescript
2531
- * onServerStart: async () => {
2532
- * worker = new BackgroundWorker();
2533
- * await worker.start();
2534
- * }
2535
- * ```
3692
+ * @param config - Resolved logger configuration
3693
+ * @param inheritedMeta - Metadata inherited from parent logger (optional)
2536
3694
  */
2537
- onServerStart?: (server: Http2Server | Server$1) => void | Promise<void>;
3695
+ constructor(config: ResolvedLoggerConfig, inheritedMeta?: LogMetadata);
2538
3696
  /**
2539
- * Called when server stops listening
2540
- *
2541
- * Use this hook to:
2542
- * - Stop background workers
2543
- * - Flush buffers
2544
- * - Complete in-flight work
3697
+ * Log a debug message
2545
3698
  *
2546
- * @example
2547
- * ```typescript
2548
- * onServerStop: async () => {
2549
- * await worker.stop({ graceful: true });
2550
- * }
2551
- * ```
3699
+ * @param message - The log message
3700
+ * @param meta - Optional metadata to attach
2552
3701
  */
2553
- onServerStop?: (server: Http2Server | Server$1) => void | Promise<void>;
3702
+ debug(message: string, meta?: LogMetadata): void;
2554
3703
  /**
2555
- * Called during server termination
2556
- *
2557
- * Use this hook to:
2558
- * - Close database connections
2559
- * - Release file handles
2560
- * - Free memory
3704
+ * Log an info message
2561
3705
  *
2562
- * @example
2563
- * ```typescript
2564
- * terminate: async () => {
2565
- * await db?.close();
2566
- * }
2567
- * ```
3706
+ * @param message - The log message
3707
+ * @param meta - Optional metadata to attach
2568
3708
  */
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
2577
- */
2578
- interface CreatePluginOptions<TConfig, TState = {}, TServices = {}> {
3709
+ info(message: string, meta?: LogMetadata): void;
2579
3710
  /**
2580
- * Plugin name (e.g., '@blaizejs/metrics')
2581
- * Must be unique within a server instance
3711
+ * Log a warning message
3712
+ *
3713
+ * @param message - The log message
3714
+ * @param meta - Optional metadata to attach
2582
3715
  */
2583
- name: string;
3716
+ warn(message: string, meta?: LogMetadata): void;
2584
3717
  /**
2585
- * Semantic version (e.g., '1.0.0')
2586
- * Used for compatibility checks
3718
+ * Log an error message
3719
+ *
3720
+ * @param message - The log message
3721
+ * @param meta - Optional metadata to attach
2587
3722
  */
2588
- version: string;
3723
+ error(message: string, meta?: LogMetadata): void;
2589
3724
  /**
2590
- * Default configuration values
2591
- * Merged with user config when plugin is created
3725
+ * Create a child logger with additional metadata
3726
+ *
3727
+ * Child loggers inherit all parent metadata and add their own.
3728
+ * Child metadata overrides parent metadata for the same keys.
3729
+ *
3730
+ * @param meta - Additional metadata for the child logger
3731
+ * @returns A new logger instance with merged metadata
2592
3732
  *
2593
3733
  * @example
2594
3734
  * ```typescript
2595
- * defaultConfig: {
2596
- * enabled: true,
2597
- * timeout: 30000,
2598
- * }
3735
+ * const parent = createLogger({ level: 'info' });
3736
+ * const child = parent.child({ component: 'database' });
3737
+ *
3738
+ * child.info('Query executed');
3739
+ * // Output includes: { component: 'database', ...parent metadata }
2599
3740
  * ```
2600
3741
  */
2601
- defaultConfig?: TConfig;
3742
+ child(meta: LogMetadata): BlaizeLogger;
2602
3743
  /**
2603
- * Setup function that returns lifecycle hooks
3744
+ * Flush any buffered logs and wait for completion
2604
3745
  *
2605
- * Receives merged config (defaultConfig + userConfig).
2606
- * Returns partial hook object - all hooks optional.
3746
+ * Delegates to the transport's flush method if it exists.
3747
+ * Use this during graceful shutdown to ensure all logs are written.
2607
3748
  *
2608
- * @param config - Merged configuration
2609
- * @returns Partial plugin hooks
3749
+ * @returns Promise that resolves when all logs are flushed
2610
3750
  *
2611
3751
  * @example
2612
3752
  * ```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
- * }
3753
+ * process.on('SIGTERM', async () => {
3754
+ * await logger.flush();
3755
+ * process.exit(0);
3756
+ * });
2625
3757
  * ```
2626
3758
  */
2627
- setup: (config: TConfig) => Partial<PluginHooks<TState, TServices>>;
2628
- }
2629
- /**
2630
- * Plugin interface
2631
- */
2632
- interface Plugin<TState = {}, TServices = {}> extends PluginHooks<TState, TServices> {
2633
- /** Plugin name */
2634
- name: string;
2635
- /** Plugin version */
2636
- version: string;
3759
+ flush(): Promise<void>;
2637
3760
  /**
2638
- * Called when plugin is registered to server
3761
+ * Internal log method that handles all log levels
2639
3762
  *
2640
- * This hook is always present - createPlugin provides a default empty async function
2641
- * if not specified by the plugin author.
3763
+ * Fast-path: Returns immediately if log level is filtered.
3764
+ * This ensures zero overhead for disabled log levels.
2642
3765
  *
2643
- * @override Makes register required (not optional like in PluginHooks)
3766
+ * @param level - The log level
3767
+ * @param message - The log message
3768
+ * @param meta - Optional metadata to attach
2644
3769
  */
2645
- register: (server: Server<TState, TServices>) => void | Promise<void>;
3770
+ private log;
2646
3771
  /**
2647
- * Type carriers for compile-time type information
2648
- * These are never used at runtime but allow TypeScript to track types
3772
+ * Check if a log level should be output
3773
+ *
3774
+ * @param level - The log level to check
3775
+ * @returns true if the level should be logged
2649
3776
  */
2650
- _state?: TState;
2651
- _services?: TServices;
2652
- }
2653
- /**
2654
- * Plugin factory function
2655
- */
2656
- type PluginFactory<TConfig = any, TState = {}, TServices = {}> = (options?: Partial<TConfig>) => Plugin<TState, TServices>;
2657
- interface PluginLifecycleManager {
2658
- initializePlugins(server: Server<any, any>): Promise<void>;
2659
- terminatePlugins(server: Server<any, any>): Promise<void>;
2660
- onServerStart(server: Server<any, any>, httpServer: any): Promise<void>;
2661
- onServerStop(server: Server<any, any>, httpServer: any): Promise<void>;
2662
- }
2663
- interface PluginLifecycleOptions {
2664
- /** Continue initialization even if a plugin fails */
2665
- continueOnError?: boolean;
2666
- /** Log plugin lifecycle events */
2667
- debug?: boolean;
2668
- /** Custom error handler for plugin failures */
2669
- onError?: (plugin: Plugin, phase: string, error: Error) => void;
3777
+ private shouldLog;
3778
+ /**
3779
+ * Redact sensitive keys from metadata
3780
+ *
3781
+ * Performs case-insensitive shallow redaction. Only top-level keys
3782
+ * are checked and redacted - nested objects are not traversed.
3783
+ *
3784
+ * Matching keys are replaced with the string '[REDACTED]'.
3785
+ *
3786
+ * @param meta - The metadata to redact
3787
+ * @returns New metadata object with sensitive values redacted
3788
+ */
3789
+ private redact;
2670
3790
  }
2671
-
2672
- /**
2673
- * Type composition utilities for extracting and composing middleware type contributions
2674
- * @module composition
2675
- * @since v0.4.0
2676
- */
2677
-
2678
- /**
2679
- * Extracts the State type contribution from a middleware
2680
- * @template T - The middleware type to extract from
2681
- * @returns The state type if present, empty object otherwise
2682
- */
2683
- type ExtractMiddlewareState<T> = T extends Middleware<infer S, any> ? S : {};
2684
- /**
2685
- * Extracts the State type contribution from a plugin
2686
- * @template T - The plugin type to extract from
2687
- * @returns The state type if present, empty object otherwise
2688
- */
2689
- type ExtractPluginState<T> = T extends Plugin<infer S, any> ? S : {};
2690
- /**
2691
- * Extracts the Services type contribution from a middleware
2692
- * @template T - The middleware type to extract from
2693
- * @returns The services type if present, empty object otherwise
2694
- */
2695
- type ExtractMiddlewareServices<T> = T extends Middleware<any, infer S> ? S : {};
2696
- /**
2697
- * Extracts the Services type contribution from a plugin
2698
- * @template T - The plugin type to extract from
2699
- * @returns The services type if present, empty object otherwise
2700
- */
2701
- type ExtractPluginServices<T> = T extends Plugin<any, infer S> ? S : {};
2702
3791
  /**
2703
- * Utility type to convert a union type to an intersection type
2704
- * This is the magic that allows us to compose multiple middleware contributions
3792
+ * Create a logger with default configuration
2705
3793
  *
2706
- * @example
2707
- * type U = { a: string } | { b: number }
2708
- * type I = UnionToIntersection<U> // { a: string } & { b: number }
3794
+ * Resolves defaults based on environment:
3795
+ * - Development: debug level, ConsoleTransport
3796
+ * - Production: info level, JSONTransport
2709
3797
  *
2710
- */
2711
- type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
2712
- /**
2713
- * Composes state contributions from an array of middleware
2714
- * Merges all state types into a single intersection type
3798
+ * Core transports (ConsoleTransport, JSONTransport) are lazy-loaded by
3799
+ * the logger itself. Custom transports should be provided by application code.
2715
3800
  *
2716
- * @template T - ReadonlyArray of Middleware
2717
- * @returns Intersection of all state contributions
3801
+ * @param config - Partial logger configuration (all fields optional)
3802
+ * @returns A new Logger instance
3803
+ *
3804
+ * @example Development Logger (Default)
3805
+ * ```typescript
3806
+ * const logger = createLogger();
3807
+ * // Uses: level='debug', ConsoleTransport, timestamp=true, no redaction
3808
+ *
3809
+ * logger.debug('Starting application');
3810
+ * ```
3811
+ *
3812
+ * @example Production Logger (Default)
3813
+ * ```typescript
3814
+ * process.env.NODE_ENV = 'production';
2718
3815
  *
2719
- * @example
2720
- * const middlewares = [authMiddleware, loggerMiddleware] as const;
2721
- * type ComposedState = ComposeStates<typeof middlewares>;
2722
- * // Result: { user: User } & { requestId: string }
2723
- */
2724
- type ComposeMiddlewareStates<T extends ReadonlyArray<Middleware>> = T extends readonly [] ? {} : UnionToIntersection<ExtractMiddlewareState<T[number]>>;
2725
- /**
2726
- * Composes state contributions from an array of plugins
2727
- * Merges all state types into a single intersection type
3816
+ * const logger = createLogger({
3817
+ * redactKeys: ['password', 'apiKey', 'secret']
3818
+ * });
3819
+ * // Uses: level='info', JSONTransport, timestamp=true, redaction enabled
3820
+ * ```
2728
3821
  *
2729
- * @template T - ReadonlyArray of Plugin
2730
- * @returns Intersection of all state contributions
3822
+ * @example Custom Transport (Application Code)
3823
+ * ```typescript
3824
+ * import { CustomTransport } from './my-transports';
2731
3825
  *
2732
- * @example
2733
- * const plugins = [authPlugin, dbPlugin] as const;
2734
- * type ComposedState = ComposePluginStates<typeof plugins>;
2735
- * // Result: { config: AuthConfig } & { dbConnected: boolean }
3826
+ * const logger = createLogger({
3827
+ * level: 'warn',
3828
+ * transport: new CustomTransport(), // Application provides custom transport
3829
+ * redactKeys: ['ssn', 'creditCard'],
3830
+ * includeTimestamp: false
3831
+ * });
3832
+ * ```
2736
3833
  */
2737
- type ComposePluginStates<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly [] ? {} : UnionToIntersection<ExtractPluginState<T[number]>>;
3834
+ declare function createLogger(config?: Partial<ResolvedLoggerConfig>): Logger;
3835
+
2738
3836
  /**
2739
- * Composes service contributions from an array of middleware
2740
- * Merges all service types into a single intersection type
3837
+ * Global logger singleton instance
2741
3838
  *
2742
- * @template T - ReadonlyArray of Middleware
2743
- * @returns Intersection of all service contributions
3839
+ * This instance is available before server creation and can be used
3840
+ * anywhere in your application. When the server starts, it will be
3841
+ * configured with the server's logging options.
2744
3842
  *
2745
3843
  * @example
2746
- * const middlewares = [dbMiddleware, cacheMiddleware] as const;
2747
- * type ComposedServices = ComposeServices<typeof middlewares>;
2748
- * // Result: { db: Database } & { cache: Cache }
3844
+ * ```typescript
3845
+ * import { logger } from '@blaizejs/logger';
3846
+ *
3847
+ * logger.info('Application starting');
3848
+ * ```
2749
3849
  */
2750
- type ComposeMiddlewareServices<T extends ReadonlyArray<Middleware>> = T extends readonly [] ? {} : UnionToIntersection<ExtractMiddlewareServices<T[number]>>;
3850
+ declare const logger: BlaizeLogger;
2751
3851
  /**
2752
- * Composes service contributions from an array of plugins
2753
- * Merges all service types into a single intersection type
3852
+ * Configure the global logger instance
2754
3853
  *
2755
- * @template T - ReadonlyArray of Plugin
2756
- * @returns Intersection of all service contributions
3854
+ * This function updates the global logger in-place so that all existing
3855
+ * imports automatically receive the new configuration. Called internally
3856
+ * by the server during creation.
3857
+ *
3858
+ * @param config - Partial logger configuration
2757
3859
  *
2758
3860
  * @example
2759
- * const plugins = [dbPlugin, cachePlugin] as const;
2760
- * type ComposedServices = ComposePluginServices<typeof plugins>;
2761
- * // Result: { db: Database } & { cache: Cache }
2762
- */
2763
- type ComposePluginServices<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly [] ? {} : UnionToIntersection<ExtractPluginServices<T[number]>>;
2764
- /**
2765
- * Safe version of ExtractState that handles edge cases
2766
- * @template T - The middleware type to extract from
2767
- * @returns The state type, handling never/any/unknown gracefully
2768
- */
2769
- type SafeExtractMiddlewareState<T> = IsNever<T> extends true ? {} : IsAny<T> extends true ? {} : T extends Middleware<infer S, any> ? unknown extends S ? {} : S : {};
2770
- /**
2771
- * Safe version of ExtractPluginState that handles edge cases
2772
- * @template T - The plugin type to extract from
2773
- * @returns The state type, handling never/any/unknown gracefully
2774
- */
2775
- type SafeExtractPluginState<T> = IsNever<T> extends true ? {} : IsAny<T> extends true ? {} : T extends Plugin<infer S, any> ? unknown extends S ? {} : S : {};
2776
- /**
2777
- * Safe version of ExtractServices that handles edge cases
2778
- * @template T - The middleware type to extract from
2779
- * @returns The services type, handling never/any/unknown gracefully
2780
- */
2781
- type SafeExtractMiddlewareServices<T> = IsNever<T> extends true ? {} : IsAny<T> extends true ? {} : T extends Middleware<any, infer S> ? unknown extends S ? {} : S : {};
2782
- /**
2783
- * Safe version of ExtractPluginServices that handles edge cases
2784
- * @template T - The plugin type to extract from
2785
- * @returns The services type, handling never/any/unknown gracefully
2786
- */
2787
- type SafeExtractPluginServices<T> = IsNever<T> extends true ? {} : IsAny<T> extends true ? {} : T extends Plugin<any, infer S> ? unknown extends S ? {} : S : {};
2788
- /**
2789
- * Composes state with better edge case handling
2790
- * @template T - ReadonlyArray of Middleware
2791
- * @returns Safely composed state types
2792
- */
2793
- type SafeComposeMiddlewareStates<T extends ReadonlyArray<Middleware>> = T extends readonly [] ? {} : T extends readonly [infer First, ...infer Rest] ? First extends Middleware ? Rest extends ReadonlyArray<Middleware> ? SafeExtractMiddlewareState<First> & SafeComposeMiddlewareStates<Rest> : SafeExtractMiddlewareState<First> : {} : UnionToIntersection<SafeExtractMiddlewareState<T[number]>>;
2794
- /**
2795
- * Composes plugin state with better edge case handling
2796
- * @template T - ReadonlyArray of Plugin
2797
- * @returns Safely composed state types
2798
- */
2799
- type SafeComposePluginStates<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly [] ? {} : T extends readonly [infer First, ...infer Rest] ? First extends Plugin<any, any> ? Rest extends ReadonlyArray<Plugin<any, any>> ? SafeExtractPluginState<First> & SafeComposePluginStates<Rest> : SafeExtractPluginState<First> : {} : UnionToIntersection<SafeExtractPluginState<T[number]>>;
2800
- /**
2801
- * Composes services with better edge case handling
2802
- * @template T - ReadonlyArray of Middleware
2803
- * @returns Safely composed service types
3861
+ * ```typescript
3862
+ * import { configureGlobalLogger } from '@blaizejs/logger';
3863
+ *
3864
+ * configureGlobalLogger({
3865
+ * level: 'warn',
3866
+ * redactKeys: ['password', 'apiKey']
3867
+ * });
3868
+ * ```
2804
3869
  */
2805
- type SafeComposeMiddlewareServices<T extends ReadonlyArray<Middleware>> = T extends readonly [] ? {} : T extends readonly [infer First, ...infer Rest] ? First extends Middleware ? Rest extends ReadonlyArray<Middleware> ? SafeExtractMiddlewareServices<First> & SafeComposeMiddlewareServices<Rest> : SafeExtractMiddlewareServices<First> : {} : UnionToIntersection<SafeExtractMiddlewareServices<T[number]>>;
3870
+ declare function configureGlobalLogger(config: Partial<LoggerConfig>): void;
3871
+
2806
3872
  /**
2807
- * Composes plugin services with better edge case handling
2808
- * @template T - ReadonlyArray of Plugin
2809
- * @returns Safely composed service types
3873
+ * Compose multiple middleware functions into a single middleware function
2810
3874
  */
2811
- type SafeComposePluginServices<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly [] ? {} : T extends readonly [infer First, ...infer Rest] ? First extends Plugin<any, any> ? Rest extends ReadonlyArray<Plugin<any, any>> ? SafeExtractPluginServices<First> & SafeComposePluginServices<Rest> : SafeExtractPluginServices<First> : {} : UnionToIntersection<SafeExtractPluginServices<T[number]>>;
3875
+ declare function compose(middlewareStack: Middleware[]): MiddlewareFunction;
3876
+
2812
3877
  /**
2813
- * Utility to merge two state types
2814
- * Handles conflicts by using the rightmost (latest) type
3878
+ * Create CORS middleware with the specified options
2815
3879
  *
2816
- * @template A - First state type
2817
- * @template B - Second state type
2818
- * @returns Merged state with B taking precedence
2819
- */
2820
- type MergeStates<A, B> = Omit<A, keyof B> & B;
2821
- /**
2822
- * Utility to merge two service types
2823
- * Handles conflicts by using the rightmost (latest) type
3880
+ * @param userOptions - CORS configuration options or boolean
3881
+ * @returns Middleware function that handles CORS
2824
3882
  *
2825
- * @template A - First services type
2826
- * @template B - Second services type
2827
- * @returns Merged services with B taking precedence
2828
- */
2829
- type MergeServices<A, B> = Omit<A, keyof B> & B;
2830
- /**
2831
- * Extract both state and services from a middleware at once
2832
- * @template T - The middleware type
2833
- * @returns Object with state and services types
2834
- */
2835
- type ExtractMiddlewareTypes<T> = {
2836
- state: ExtractMiddlewareState<T>;
2837
- services: ExtractMiddlewareServices<T>;
2838
- };
2839
- /**
2840
- * Extract both state and services from a plugin at once
2841
- * @template T - The plugin type
2842
- * @returns Object with state and services types
2843
- */
2844
- type ExtractPluginTypes<T> = {
2845
- state: ExtractPluginState<T>;
2846
- services: ExtractPluginServices<T>;
2847
- };
2848
- /**
2849
- * Compose both state and services from middleware array at once
2850
- * @template T - ReadonlyArray of Middleware
2851
- * @returns Object with composed state and services
2852
- */
2853
- type ComposeMiddlewareTypes<T extends ReadonlyArray<Middleware>> = {
2854
- state: ComposeMiddlewareStates<T>;
2855
- services: ComposeMiddlewareServices<T>;
2856
- };
2857
- /**
2858
- * Compose both state and services from plugin array at once
2859
- * @template T - ReadonlyArray of Plugin
2860
- * @returns Object with composed state and services
2861
- */
2862
- type ComposePluginTypes<T extends ReadonlyArray<Plugin<any, any>>> = {
2863
- state: ComposePluginStates<T>;
2864
- services: ComposePluginServices<T>;
2865
- };
2866
- /**
2867
- * Type guard to check if a value is a Middleware
2868
- * @param value - Value to check
2869
- * @returns True if value is a Middleware
3883
+ * @example
3884
+ * ```typescript
3885
+ * import { cors } from '@blaize-core/middleware/cors';
3886
+ *
3887
+ * // Development mode - allow all origins
3888
+ * server.use(cors(true));
3889
+ *
3890
+ * // Production - specific origin
3891
+ * server.use(cors({
3892
+ * origin: 'https://app.example.com',
3893
+ * credentials: true,
3894
+ * maxAge: 86400
3895
+ * }));
3896
+ *
3897
+ * // Multiple origins with regex
3898
+ * server.use(cors({
3899
+ * origin: [
3900
+ * 'https://app.example.com',
3901
+ * /^https:\/\/.*\.example\.com$/
3902
+ * ]
3903
+ * }));
3904
+ *
3905
+ * // Dynamic origin validation
3906
+ * server.use(cors({
3907
+ * origin: async (origin, ctx) => {
3908
+ * return await checkOriginAllowed(origin, ctx.state.user);
3909
+ * }
3910
+ * }));
3911
+ * ```
2870
3912
  */
2871
- declare function isMiddleware(value: unknown): value is Middleware;
3913
+ declare function cors(userOptions?: CorsOptions | boolean): Middleware;
3914
+
2872
3915
  /**
2873
- * Type guard to check if a value is a Plugin
2874
- * @param value - Value to check
2875
- * @returns True if value is a Plugin
3916
+ * Create a middleware
2876
3917
  */
2877
- declare function isPlugin(value: unknown): value is Plugin;
3918
+ declare function create$1<TState = {}, TServices = {}>(handlerOrOptions: MiddlewareFunction | MiddlewareOptions): Middleware<TState, TServices>;
2878
3919
  /**
2879
- * Type helper for middleware arrays
2880
- * Ensures proper readonly array typing for composition
3920
+ * Create a middleware that only contributes state (no services)
3921
+ * Convenience helper for state-only middleware
3922
+ *
3923
+ * @template T - Type of state to contribute
3924
+ * @param handler - Middleware function that adds state
3925
+ * @returns Middleware that contributes state only
2881
3926
  *
2882
- * @example
2883
- * const middlewares = asMiddlewareArray([auth, logger, cache]);
2884
- * type State = ComposeStates<typeof middlewares>;
2885
3927
  */
2886
- declare function asMiddlewareArray<T extends ReadonlyArray<Middleware>>(middlewares: T): T;
3928
+ declare function stateMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<T, {}>;
2887
3929
  /**
2888
- * Type helper for plugin arrays
2889
- * Ensures proper readonly array typing for composition
3930
+ * Create a middleware that only contributes services (no state)
3931
+ * Convenience helper for service-only middleware
3932
+ *
3933
+ * @template T - Type of services to contribute
3934
+ * @param handler - Middleware function that adds services
3935
+ * @returns Middleware that contributes services only
2890
3936
  *
2891
- * @example
2892
- * const plugins = asPluginArray([dbPlugin, cachePlugin]);
2893
- * type Services = ComposePluginServices<typeof plugins>;
2894
3937
  */
2895
- declare function asPluginArray<T extends ReadonlyArray<Plugin<any, any>>>(plugins: T): T;
3938
+ declare function serviceMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<{}, T>;
3939
+
2896
3940
  /**
2897
- * Create a typed middleware array with inferred types
2898
- * Useful for getting proper const assertions
3941
+ * Request Logger Middleware
2899
3942
  *
2900
- * @example
2901
- * const middlewares = createMiddlewareArray(auth, logger, cache);
2902
- * type State = ComposeStates<typeof middlewares>;
3943
+ * Creates a child logger with request context and optionally logs request lifecycle events.
3944
+ * This middleware ALWAYS runs FIRST in the middleware chain to ensure all logs have request context.
3945
+ *
3946
+ * @packageDocumentation
2903
3947
  */
2904
- declare function createMiddlewareArray<T extends ReadonlyArray<Middleware>>(...middlewares: T): T;
3948
+
2905
3949
  /**
2906
- * Create a typed plugin array with inferred types
2907
- * Useful for getting proper const assertions
3950
+ * Request logger middleware factory
2908
3951
  *
2909
- * @example
2910
- * const plugins = createPluginArray(dbPlugin, cachePlugin);
2911
- * type Services = ComposePluginServices<typeof plugins>;
3952
+ * Creates middleware that:
3953
+ * 1. ALWAYS creates a child logger with request context (correlationId, method, path, ip)
3954
+ * 2. Replaces ctx.services.log with the child logger
3955
+ * 3. Optionally logs request lifecycle events if requestLogging is true
3956
+ *
3957
+ * The child logger ensures that all logs during the request lifecycle automatically
3958
+ * include request context, even if requestLogging is false.
3959
+ *
3960
+ * @param options - Request logger options (headers, query, etc.)
3961
+ * @returns Middleware function
3962
+ *
3963
+ * @example Basic Usage (with lifecycle logging)
3964
+ * ```typescript
3965
+ * import { createServer } from 'blaizejs';
3966
+ * import { requestLoggerMiddleware } from './logger/middleware';
3967
+ *
3968
+ * const server = createServer({
3969
+ * port: 3000,
3970
+ * logging: {
3971
+ * level: 'info',
3972
+ * requestLogging: true, // Enable lifecycle logs
3973
+ * requestLoggerOptions: {
3974
+ * includeHeaders: true,
3975
+ * includeQuery: true
3976
+ * }
3977
+ * }
3978
+ * });
3979
+ * ```
3980
+ *
3981
+ * @example Without Lifecycle Logging
3982
+ * ```typescript
3983
+ * const server = createServer({
3984
+ * logging: {
3985
+ * level: 'info',
3986
+ * requestLogging: false // No automatic logs, but ctx.services.log still has request context
3987
+ * }
3988
+ * });
3989
+ *
3990
+ * // In route handler:
3991
+ * export const GET = appRoute.get({
3992
+ * handler: async (ctx) => {
3993
+ * // ctx.services.log still includes correlationId, method, path automatically
3994
+ * ctx.services.log.info('Custom log message');
3995
+ * return { data: 'response' };
3996
+ * }
3997
+ * });
3998
+ * ```
3999
+ *
4000
+ * @example With Header Filtering
4001
+ * ```typescript
4002
+ * const middleware = requestLoggerMiddleware({
4003
+ * includeHeaders: true,
4004
+ * headerWhitelist: ['content-type', 'user-agent', 'accept']
4005
+ * }, true);
4006
+ *
4007
+ * // Logs will include only whitelisted headers
4008
+ * // Sensitive headers (authorization, cookie) are ALWAYS redacted
4009
+ * ```
2912
4010
  */
2913
- declare function createPluginArray<T extends ReadonlyArray<Plugin<any, any>>>(...plugins: T): T;
4011
+ declare function requestLoggerMiddleware(options?: RequestLoggerOptions): Middleware;
2914
4012
 
2915
4013
  /**
2916
4014
  * Create a type-safe plugin with full IntelliSense support
@@ -3582,6 +4680,7 @@ declare const MiddlewareAPI: {
3582
4680
  createStateMiddleware: typeof stateMiddleware;
3583
4681
  compose: typeof compose;
3584
4682
  cors: typeof cors;
4683
+ requestLoggerMiddleware: typeof requestLoggerMiddleware;
3585
4684
  };
3586
4685
  declare const PluginsAPI: {
3587
4686
  createPlugin: typeof createPlugin;
@@ -3594,6 +4693,9 @@ declare const Blaize: {
3594
4693
  createStateMiddleware: typeof stateMiddleware;
3595
4694
  createPlugin: typeof createPlugin;
3596
4695
  getCorrelationId: typeof getCorrelationId;
4696
+ configureGlobalLogger: typeof configureGlobalLogger;
4697
+ createLogger: typeof createLogger;
4698
+ logger: BlaizeLogger;
3597
4699
  Server: {
3598
4700
  createServer: typeof create;
3599
4701
  inferContext: typeof inferContext;
@@ -3619,6 +4721,7 @@ declare const Blaize: {
3619
4721
  createStateMiddleware: typeof stateMiddleware;
3620
4722
  compose: typeof compose;
3621
4723
  cors: typeof cors;
4724
+ requestLoggerMiddleware: typeof requestLoggerMiddleware;
3622
4725
  };
3623
4726
  Plugins: {
3624
4727
  createPlugin: typeof createPlugin;
@@ -3626,4 +4729,4 @@ declare const Blaize: {
3626
4729
  VERSION: string;
3627
4730
  };
3628
4731
 
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 };
4732
+ export { Blaize, BlaizeError, type BlaizeErrorResponse, type BlaizeLogTransport, type BlaizeLogger, 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, ConsoleTransport, 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, JSONTransport, type LogLevel, type LogMetadata, Logger, type LoggerConfig, 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, NullTransport, 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 RequestLoggerOptions, type RequestOptions, type RequestParams, RequestTimeoutError, type ResolvedLoggerConfig, 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 SerializedError, 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, configureGlobalLogger, cors, createDeleteRoute, createGetRoute, createHeadRoute, createLogger, 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, logger, paramsToQuery, requestLoggerMiddleware };