@onebun/core 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/types.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { BaseMiddleware } from './module/middleware';
1
2
  import type { Type } from 'arktype';
2
3
  import type { Effect, Layer } from 'effect';
3
4
 
@@ -12,6 +13,31 @@ import type { Logger, LoggerOptions } from '@onebun/logger';
12
13
  */
13
14
  export type OneBunRequest = import('bun').BunRequest;
14
15
 
16
+ /**
17
+ * A middleware class constructor.
18
+ *
19
+ * Pass class references (not instances) to `@UseMiddleware()`,
20
+ * `ApplicationOptions.middleware`, and `OnModuleConfigure.configureMiddleware()`.
21
+ * The framework will instantiate them once at startup with DI support.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * @UseMiddleware(AuthMiddleware)
26
+ * ```
27
+ */
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ export type MiddlewareClass = new (...args: any[]) => BaseMiddleware;
30
+
31
+ /**
32
+ * Resolved middleware function — a bound `use()` method of an instantiated
33
+ * `BaseMiddleware`. Used internally by the execution pipeline.
34
+ * @internal
35
+ */
36
+ export type ResolvedMiddleware = (
37
+ req: OneBunRequest,
38
+ next: () => Promise<OneBunResponse>,
39
+ ) => Promise<OneBunResponse> | OneBunResponse;
40
+
15
41
  /**
16
42
  * HTTP Response type used in OneBun controllers.
17
43
  * Standard Web API Response.
@@ -50,6 +76,37 @@ export interface ModuleProviders {
50
76
  exports?: Function[];
51
77
  }
52
78
 
79
+ /**
80
+ * Interface for modules that configure middleware.
81
+ * Implement this interface on your `@Module()` class to apply middleware
82
+ * to all controllers within the module (including imported child modules).
83
+ *
84
+ * Module-level middleware runs after global middleware but before
85
+ * controller-level and route-level middleware.
86
+ *
87
+ * Execution order: global → module → controller → route → handler
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * @Module({
92
+ * controllers: [UserController],
93
+ * imports: [AuthModule],
94
+ * })
95
+ * export class UserModule implements OnModuleConfigure {
96
+ * configureMiddleware(): MiddlewareClass[] {
97
+ * return [TenantMiddleware, AuditMiddleware];
98
+ * }
99
+ * }
100
+ * ```
101
+ */
102
+ export interface OnModuleConfigure {
103
+ /**
104
+ * Return an array of middleware class constructors to apply to all controllers
105
+ * in this module and its imported child modules.
106
+ */
107
+ configureMiddleware(): MiddlewareClass[];
108
+ }
109
+
53
110
  /**
54
111
  * Module instance interface
55
112
  */
@@ -98,6 +155,19 @@ export interface ModuleInstance {
98
155
  * Get service instance by class
99
156
  */
100
157
  getServiceByClass?<T>(serviceClass: new (...args: unknown[]) => T): T | undefined;
158
+
159
+ /**
160
+ * Get accumulated module-level middleware (resolved bound functions)
161
+ * for a given controller class.
162
+ * Includes middleware from ancestor modules (root → child → … → owner module).
163
+ */
164
+ getModuleMiddleware?(controllerClass: Function): Function[];
165
+
166
+ /**
167
+ * Resolve middleware class constructors into bound `use()` functions
168
+ * using this module's DI scope (services + logger + config).
169
+ */
170
+ resolveMiddleware?(classes: Function[]): Function[];
101
171
  }
102
172
 
103
173
  /**
@@ -128,6 +198,14 @@ export interface ApplicationOptions {
128
198
  */
129
199
  host?: string;
130
200
 
201
+ /**
202
+ * Maximum idle time (in seconds) before the server closes a connection.
203
+ * A connection is idle when no data is sent or received.
204
+ * Set to 0 to disable the timeout entirely.
205
+ * @defaultValue 120
206
+ */
207
+ idleTimeout?: number;
208
+
131
209
  /**
132
210
  * Base path prefix for all routes
133
211
  * @example '/api/v1'
@@ -342,6 +420,25 @@ export interface ApplicationOptions {
342
420
  */
343
421
  docs?: DocsApplicationOptions;
344
422
 
423
+ /**
424
+ * Application-wide middleware applied to every route before module-level,
425
+ * controller-level and route-level middleware. Useful for cross-cutting
426
+ * concerns like request logging, authentication, CORS, or request validation.
427
+ *
428
+ * Pass class constructors (not instances). The framework will instantiate
429
+ * them once at startup with full DI support from the root module.
430
+ *
431
+ * Execution order: global → module → controller → route → handler
432
+ *
433
+ * @example
434
+ * ```typescript
435
+ * const app = new OneBunApplication(AppModule, {
436
+ * middleware: [CorsMiddleware, RequestIdMiddleware],
437
+ * });
438
+ * ```
439
+ */
440
+ middleware?: MiddlewareClass[];
441
+
345
442
  /**
346
443
  * Enable graceful shutdown on SIGTERM/SIGINT
347
444
  * When enabled, the application will cleanly shutdown on process signals,
@@ -588,6 +685,26 @@ export interface ResponseSchemaMetadata {
588
685
  description?: string;
589
686
  }
590
687
 
688
+ /**
689
+ * Options for HTTP method decorators (@Get, @Post, @Put, @Delete, @Patch, etc.)
690
+ */
691
+ export interface RouteOptions {
692
+ /**
693
+ * Per-request idle timeout in seconds.
694
+ * Overrides the global `idleTimeout` from `ApplicationOptions` for this route.
695
+ * Set to 0 to disable the timeout entirely (useful for long-running requests).
696
+ * @example
697
+ * ```typescript
698
+ * @Get('/long-task', { timeout: 300 }) // 5 minutes
699
+ * async longTask() { ... }
700
+ *
701
+ * @Get('/stream', { timeout: 0 }) // no timeout
702
+ * async stream() { ... }
703
+ * ```
704
+ */
705
+ timeout?: number;
706
+ }
707
+
591
708
  /**
592
709
  * Route metadata
593
710
  */
@@ -602,6 +719,11 @@ export interface RouteMetadata {
602
719
  * Key is HTTP status code (e.g., 200, 201, 404)
603
720
  */
604
721
  responseSchemas?: ResponseSchemaMetadata[];
722
+ /**
723
+ * Per-request idle timeout in seconds.
724
+ * When set, calls `server.timeout(req, seconds)` for this route.
725
+ */
726
+ timeout?: number;
605
727
  }
606
728
 
607
729
  /**
@@ -610,6 +732,11 @@ export interface RouteMetadata {
610
732
  export interface ControllerMetadata {
611
733
  path: string;
612
734
  routes: RouteMetadata[];
735
+ /**
736
+ * Controller-level middleware class constructors applied to all routes.
737
+ * Set by applying @UseMiddleware() as a class decorator.
738
+ */
739
+ middleware?: MiddlewareClass[];
613
740
  }
614
741
 
615
742
  // ============================================================================
@@ -662,6 +789,21 @@ export interface SseOptions {
662
789
  * at this interval to keep the connection alive.
663
790
  */
664
791
  heartbeat?: number;
792
+
793
+ /**
794
+ * Callback invoked when the client disconnects or aborts the SSE connection.
795
+ * Useful for cleanup logic when using `controller.sse()` programmatically.
796
+ *
797
+ * For `@Sse()` decorator usage, prefer `try/finally` in the generator instead.
798
+ *
799
+ * @example
800
+ * ```typescript
801
+ * return this.sse(this.generateEvents(), {
802
+ * onAbort: () => this.eventService.unsubscribe(),
803
+ * });
804
+ * ```
805
+ */
806
+ onAbort?: () => void;
665
807
  }
666
808
 
667
809
  /**