@onebun/core 0.2.0 → 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/package.json +1 -1
- package/src/application/application.test.ts +36 -0
- package/src/application/application.ts +258 -6
- package/src/application/multi-service-application.ts +2 -0
- package/src/application/multi-service.types.ts +1 -1
- package/src/decorators/decorators.test.ts +202 -12
- package/src/decorators/decorators.ts +228 -7
- package/src/docs-examples.test.ts +1339 -254
- package/src/file/index.ts +8 -0
- package/src/file/onebun-file.test.ts +315 -0
- package/src/file/onebun-file.ts +304 -0
- package/src/index.ts +20 -0
- package/src/module/controller.ts +96 -10
- package/src/module/index.ts +2 -1
- package/src/module/lifecycle.ts +13 -0
- package/src/module/middleware.ts +76 -0
- package/src/module/module.test.ts +138 -1
- package/src/module/module.ts +127 -2
- package/src/types.ts +169 -0
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,
|
|
@@ -523,6 +620,9 @@ export enum ParamType {
|
|
|
523
620
|
COOKIE = 'cookie',
|
|
524
621
|
REQUEST = 'request',
|
|
525
622
|
RESPONSE = 'response',
|
|
623
|
+
FILE = 'file',
|
|
624
|
+
FILES = 'files',
|
|
625
|
+
FORM_FIELD = 'formField',
|
|
526
626
|
}
|
|
527
627
|
|
|
528
628
|
/**
|
|
@@ -538,6 +638,26 @@ export interface ParamDecoratorOptions {
|
|
|
538
638
|
required?: boolean;
|
|
539
639
|
}
|
|
540
640
|
|
|
641
|
+
/**
|
|
642
|
+
* Options for file upload decorators (@UploadedFile, @UploadedFiles)
|
|
643
|
+
*/
|
|
644
|
+
export interface FileUploadOptions {
|
|
645
|
+
/** Maximum file size in bytes */
|
|
646
|
+
maxSize?: number;
|
|
647
|
+
/** Allowed MIME types, supports wildcards like 'image/*'. Use MimeType enum for convenience. */
|
|
648
|
+
mimeTypes?: string[];
|
|
649
|
+
/** Whether the file is required (default: true for @UploadedFile/@UploadedFiles) */
|
|
650
|
+
required?: boolean;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Options for multiple file upload decorator (@UploadedFiles)
|
|
655
|
+
*/
|
|
656
|
+
export interface FilesUploadOptions extends FileUploadOptions {
|
|
657
|
+
/** Maximum number of files allowed */
|
|
658
|
+
maxCount?: number;
|
|
659
|
+
}
|
|
660
|
+
|
|
541
661
|
/**
|
|
542
662
|
* Parameter metadata
|
|
543
663
|
*/
|
|
@@ -550,6 +670,10 @@ export interface ParamMetadata {
|
|
|
550
670
|
* ArkType schema for validation
|
|
551
671
|
*/
|
|
552
672
|
schema?: Type<unknown>;
|
|
673
|
+
/**
|
|
674
|
+
* File upload options (only for FILE/FILES param types)
|
|
675
|
+
*/
|
|
676
|
+
fileOptions?: FileUploadOptions & { maxCount?: number };
|
|
553
677
|
}
|
|
554
678
|
|
|
555
679
|
/**
|
|
@@ -561,6 +685,26 @@ export interface ResponseSchemaMetadata {
|
|
|
561
685
|
description?: string;
|
|
562
686
|
}
|
|
563
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
|
+
|
|
564
708
|
/**
|
|
565
709
|
* Route metadata
|
|
566
710
|
*/
|
|
@@ -575,6 +719,11 @@ export interface RouteMetadata {
|
|
|
575
719
|
* Key is HTTP status code (e.g., 200, 201, 404)
|
|
576
720
|
*/
|
|
577
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;
|
|
578
727
|
}
|
|
579
728
|
|
|
580
729
|
/**
|
|
@@ -583,6 +732,11 @@ export interface RouteMetadata {
|
|
|
583
732
|
export interface ControllerMetadata {
|
|
584
733
|
path: string;
|
|
585
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[];
|
|
586
740
|
}
|
|
587
741
|
|
|
588
742
|
// ============================================================================
|
|
@@ -635,6 +789,21 @@ export interface SseOptions {
|
|
|
635
789
|
* at this interval to keep the connection alive.
|
|
636
790
|
*/
|
|
637
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;
|
|
638
807
|
}
|
|
639
808
|
|
|
640
809
|
/**
|