@onebun/core 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +233 -0
- package/package.json +1 -1
- package/src/{application.test.ts → application/application.test.ts} +125 -5
- package/src/{application.ts → application/application.ts} +239 -13
- package/src/application/index.ts +9 -0
- package/src/{multi-service-application.test.ts → application/multi-service-application.test.ts} +2 -1
- package/src/{multi-service-application.ts → application/multi-service-application.ts} +2 -1
- package/src/{multi-service.types.ts → application/multi-service.types.ts} +1 -1
- package/src/{decorators.test.ts → decorators/decorators.test.ts} +2 -1
- package/src/{decorators.ts → decorators/decorators.ts} +3 -2
- package/src/decorators/index.ts +15 -0
- package/src/docs-examples.test.ts +753 -0
- package/src/index.ts +50 -41
- package/src/module/index.ts +12 -0
- package/src/{module.test.ts → module/module.test.ts} +3 -2
- package/src/{module.ts → module/module.ts} +15 -8
- package/src/queue/adapters/index.ts +8 -0
- package/src/queue/adapters/memory.adapter.test.ts +405 -0
- package/src/queue/adapters/memory.adapter.ts +509 -0
- package/src/queue/adapters/redis.adapter.ts +673 -0
- package/src/queue/cron-expression.test.ts +145 -0
- package/src/queue/cron-expression.ts +115 -0
- package/src/queue/cron-parser.test.ts +185 -0
- package/src/queue/cron-parser.ts +287 -0
- package/src/queue/decorators.test.ts +292 -0
- package/src/queue/decorators.ts +493 -0
- package/src/queue/docs-examples.test.ts +449 -0
- package/src/queue/guards.test.ts +309 -0
- package/src/queue/guards.ts +307 -0
- package/src/queue/index.ts +118 -0
- package/src/queue/pattern-matcher.test.ts +191 -0
- package/src/queue/pattern-matcher.ts +252 -0
- package/src/queue/queue.service.ts +421 -0
- package/src/queue/scheduler.test.ts +235 -0
- package/src/queue/scheduler.ts +379 -0
- package/src/queue/types.ts +502 -0
- package/src/redis/index.ts +8 -0
- package/src/redis/redis-client.ts +502 -0
- package/src/redis/shared-redis.ts +231 -0
- package/src/{env-resolver.ts → service-client/env-resolver.ts} +1 -1
- package/src/service-client/index.ts +10 -0
- package/src/{service-client.test.ts → service-client/service-client.test.ts} +3 -2
- package/src/{service-client.ts → service-client/service-client.ts} +1 -1
- package/src/{service-definition.test.ts → service-client/service-definition.test.ts} +3 -2
- package/src/{service-definition.ts → service-client/service-definition.ts} +2 -2
- package/src/testing/index.ts +7 -0
- package/src/types.ts +84 -5
- package/src/websocket/index.ts +50 -0
- package/src/websocket/ws-base-gateway.test.ts +479 -0
- package/src/websocket/ws-base-gateway.ts +514 -0
- package/src/websocket/ws-client.test.ts +511 -0
- package/src/websocket/ws-client.ts +628 -0
- package/src/websocket/ws-client.types.ts +129 -0
- package/src/websocket/ws-decorators.test.ts +331 -0
- package/src/websocket/ws-decorators.ts +418 -0
- package/src/websocket/ws-guards.test.ts +334 -0
- package/src/websocket/ws-guards.ts +298 -0
- package/src/websocket/ws-handler.ts +658 -0
- package/src/websocket/ws-integration.test.ts +518 -0
- package/src/websocket/ws-pattern-matcher.test.ts +152 -0
- package/src/websocket/ws-pattern-matcher.ts +240 -0
- package/src/websocket/ws-service-definition.ts +224 -0
- package/src/websocket/ws-socketio-protocol.test.ts +344 -0
- package/src/websocket/ws-socketio-protocol.ts +567 -0
- package/src/websocket/ws-storage-memory.test.ts +246 -0
- package/src/websocket/ws-storage-memory.ts +222 -0
- package/src/websocket/ws-storage-redis.ts +302 -0
- package/src/websocket/ws-storage.ts +210 -0
- package/src/websocket/ws.types.ts +342 -0
- /package/src/{metadata.test.ts → decorators/metadata.test.ts} +0 -0
- /package/src/{metadata.ts → decorators/metadata.ts} +0 -0
- /package/src/{config.service.test.ts → module/config.service.test.ts} +0 -0
- /package/src/{config.service.ts → module/config.service.ts} +0 -0
- /package/src/{controller.test.ts → module/controller.test.ts} +0 -0
- /package/src/{controller.ts → module/controller.ts} +0 -0
- /package/src/{service.test.ts → module/service.test.ts} +0 -0
- /package/src/{service.ts → module/service.ts} +0 -0
- /package/src/{env-resolver.test.ts → service-client/env-resolver.test.ts} +0 -0
- /package/src/{service-client.types.ts → service-client/service-client.types.ts} +0 -0
- /package/src/{test-utils.test.ts → testing/test-utils.test.ts} +0 -0
- /package/src/{test-utils.ts → testing/test-utils.ts} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Effect, type Layer } from 'effect';
|
|
2
2
|
|
|
3
|
-
import type { Controller } from '
|
|
3
|
+
import type { Controller } from '../module/controller';
|
|
4
|
+
import type { WsClientData } from '../websocket/ws.types';
|
|
4
5
|
|
|
5
6
|
import { TypedEnv } from '@onebun/envs';
|
|
6
7
|
import {
|
|
@@ -19,18 +20,24 @@ import {
|
|
|
19
20
|
} from '@onebun/requests';
|
|
20
21
|
import { makeTraceService, TraceService } from '@onebun/trace';
|
|
21
22
|
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import { OneBunModule } from '
|
|
23
|
+
import { getControllerMetadata } from '../decorators/decorators';
|
|
24
|
+
import { ConfigServiceImpl } from '../module/config.service';
|
|
25
|
+
import { OneBunModule } from '../module/module';
|
|
26
|
+
import { QueueService, type QueueAdapter } from '../queue';
|
|
27
|
+
import { InMemoryQueueAdapter } from '../queue/adapters/memory.adapter';
|
|
28
|
+
import { RedisQueueAdapter } from '../queue/adapters/redis.adapter';
|
|
29
|
+
import { hasQueueDecorators } from '../queue/decorators';
|
|
30
|
+
import { SharedRedisProvider } from '../redis/shared-redis';
|
|
25
31
|
import {
|
|
26
32
|
type ApplicationOptions,
|
|
27
33
|
type HttpMethod,
|
|
28
|
-
type
|
|
34
|
+
type ModuleInstance,
|
|
29
35
|
type ParamMetadata,
|
|
30
36
|
ParamType,
|
|
31
37
|
type RouteMetadata,
|
|
32
|
-
} from '
|
|
33
|
-
import { validateOrThrow } from '
|
|
38
|
+
} from '../types';
|
|
39
|
+
import { validateOrThrow } from '../validation';
|
|
40
|
+
import { WsHandler, isWebSocketGateway } from '../websocket/ws-handler';
|
|
34
41
|
|
|
35
42
|
// Conditionally import metrics
|
|
36
43
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -60,7 +67,7 @@ function clearGlobalTraceContext(): void {
|
|
|
60
67
|
* OneBun Application
|
|
61
68
|
*/
|
|
62
69
|
export class OneBunApplication {
|
|
63
|
-
private rootModule:
|
|
70
|
+
private rootModule: ModuleInstance;
|
|
64
71
|
private server: ReturnType<typeof Bun.serve> | null = null;
|
|
65
72
|
private options: ApplicationOptions = {
|
|
66
73
|
port: 3000,
|
|
@@ -75,6 +82,9 @@ export class OneBunApplication {
|
|
|
75
82
|
private metricsService: any = null;
|
|
76
83
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
84
|
private traceService: any = null;
|
|
85
|
+
private wsHandler: WsHandler | null = null;
|
|
86
|
+
private queueService: QueueService | null = null;
|
|
87
|
+
private queueAdapter: QueueAdapter | null = null;
|
|
78
88
|
|
|
79
89
|
/**
|
|
80
90
|
* Create application instance
|
|
@@ -260,6 +270,23 @@ export class OneBunApplication {
|
|
|
260
270
|
const controllers = this.rootModule.getControllers();
|
|
261
271
|
this.logger.debug(`Loaded ${controllers.length} controllers`);
|
|
262
272
|
|
|
273
|
+
// Initialize WebSocket handler and detect gateways
|
|
274
|
+
this.wsHandler = new WsHandler(this.logger, this.options.websocket);
|
|
275
|
+
|
|
276
|
+
// Register WebSocket gateways (they are in controllers array but decorated with @WebSocketGateway)
|
|
277
|
+
for (const controllerClass of controllers) {
|
|
278
|
+
if (isWebSocketGateway(controllerClass)) {
|
|
279
|
+
const instance = this.rootModule.getControllerInstance?.(controllerClass);
|
|
280
|
+
if (instance) {
|
|
281
|
+
this.wsHandler.registerGateway(controllerClass, instance as import('../websocket/ws-base-gateway').BaseWebSocketGateway);
|
|
282
|
+
this.logger.info(`Registered WebSocket gateway: ${controllerClass.name}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Initialize Queue system if configured or handlers exist
|
|
288
|
+
await this.initializeQueue(controllers);
|
|
289
|
+
|
|
263
290
|
// Create a map of routes with metadata
|
|
264
291
|
const routes = new Map<
|
|
265
292
|
string,
|
|
@@ -359,15 +386,48 @@ export class OneBunApplication {
|
|
|
359
386
|
|
|
360
387
|
// Create server with proper context binding
|
|
361
388
|
const app = this;
|
|
362
|
-
|
|
389
|
+
const hasWebSocketGateways = this.wsHandler?.hasGateways() ?? false;
|
|
390
|
+
|
|
391
|
+
// Prepare WebSocket handlers if gateways exist
|
|
392
|
+
// When no gateways, use no-op handlers (required by Bun.serve)
|
|
393
|
+
const wsHandlers = hasWebSocketGateways ? this.wsHandler!.createWebSocketHandlers() : {
|
|
394
|
+
|
|
395
|
+
open() { /* no-op */ },
|
|
396
|
+
|
|
397
|
+
message() { /* no-op */ },
|
|
398
|
+
|
|
399
|
+
close() { /* no-op */ },
|
|
400
|
+
|
|
401
|
+
drain() { /* no-op */ },
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
this.server = Bun.serve<WsClientData>({
|
|
363
405
|
port: this.options.port,
|
|
364
406
|
hostname: this.options.host,
|
|
365
|
-
|
|
407
|
+
// WebSocket handlers
|
|
408
|
+
websocket: wsHandlers,
|
|
409
|
+
async fetch(req, server) {
|
|
366
410
|
const url = new URL(req.url);
|
|
367
411
|
const path = url.pathname;
|
|
368
412
|
const method = req.method;
|
|
369
413
|
const startTime = Date.now();
|
|
370
414
|
|
|
415
|
+
// Handle WebSocket upgrade if gateways exist
|
|
416
|
+
if (hasWebSocketGateways && app.wsHandler) {
|
|
417
|
+
const upgradeHeader = req.headers.get('upgrade')?.toLowerCase();
|
|
418
|
+
|
|
419
|
+
// Check for WebSocket upgrade or Socket.IO polling
|
|
420
|
+
if (upgradeHeader === 'websocket' || path.startsWith('/socket.io')) {
|
|
421
|
+
const response = await app.wsHandler.handleUpgrade(req, server);
|
|
422
|
+
if (response === undefined) {
|
|
423
|
+
return undefined; // Successfully upgraded
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Return response if upgrade failed
|
|
427
|
+
return response;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
371
431
|
// Setup tracing context if available and enabled
|
|
372
432
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
373
433
|
let traceSpan: any = null;
|
|
@@ -675,6 +735,12 @@ export class OneBunApplication {
|
|
|
675
735
|
},
|
|
676
736
|
});
|
|
677
737
|
|
|
738
|
+
// Initialize WebSocket gateways with server
|
|
739
|
+
if (hasWebSocketGateways && this.wsHandler && this.server) {
|
|
740
|
+
this.wsHandler.initializeGateways(this.server);
|
|
741
|
+
this.logger.info(`WebSocket server enabled at ws://${this.options.host}:${this.options.port}`);
|
|
742
|
+
}
|
|
743
|
+
|
|
678
744
|
this.logger.info(`Server started on http://${this.options.host}:${this.options.port}`);
|
|
679
745
|
if (this.metricsService) {
|
|
680
746
|
this.logger.info(
|
|
@@ -685,6 +751,11 @@ export class OneBunApplication {
|
|
|
685
751
|
'Metrics enabled but @onebun/metrics module not available. Install with: bun add @onebun/metrics',
|
|
686
752
|
);
|
|
687
753
|
}
|
|
754
|
+
|
|
755
|
+
// Enable graceful shutdown by default (can be disabled with gracefulShutdown: false)
|
|
756
|
+
if (this.options.gracefulShutdown !== false) {
|
|
757
|
+
this.enableGracefulShutdown();
|
|
758
|
+
}
|
|
688
759
|
} catch (error) {
|
|
689
760
|
this.logger.error(
|
|
690
761
|
'Failed to start application:',
|
|
@@ -910,14 +981,169 @@ export class OneBunApplication {
|
|
|
910
981
|
}
|
|
911
982
|
|
|
912
983
|
/**
|
|
913
|
-
* Stop the application
|
|
984
|
+
* Stop the application with graceful shutdown
|
|
985
|
+
* @param options - Shutdown options
|
|
914
986
|
*/
|
|
915
|
-
stop(): void {
|
|
987
|
+
async stop(options?: { closeSharedRedis?: boolean }): Promise<void> {
|
|
988
|
+
const closeRedis = options?.closeSharedRedis ?? true;
|
|
989
|
+
|
|
990
|
+
this.logger.info('Stopping OneBun application...');
|
|
991
|
+
|
|
992
|
+
// Cleanup WebSocket resources
|
|
993
|
+
if (this.wsHandler) {
|
|
994
|
+
this.logger.debug('Cleaning up WebSocket handler');
|
|
995
|
+
await this.wsHandler.cleanup();
|
|
996
|
+
this.wsHandler = null;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// Stop queue service
|
|
1000
|
+
if (this.queueService) {
|
|
1001
|
+
this.logger.debug('Stopping queue service');
|
|
1002
|
+
await this.queueService.stop();
|
|
1003
|
+
this.queueService = null;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
// Disconnect queue adapter
|
|
1007
|
+
if (this.queueAdapter) {
|
|
1008
|
+
this.logger.debug('Disconnecting queue adapter');
|
|
1009
|
+
await this.queueAdapter.disconnect();
|
|
1010
|
+
this.queueAdapter = null;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
// Stop HTTP server
|
|
916
1014
|
if (this.server) {
|
|
917
1015
|
this.server.stop();
|
|
918
1016
|
this.server = null;
|
|
919
|
-
this.logger.
|
|
1017
|
+
this.logger.debug('HTTP server stopped');
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
// Close shared Redis connection if configured and requested
|
|
1021
|
+
if (closeRedis && SharedRedisProvider.isConnected()) {
|
|
1022
|
+
this.logger.debug('Disconnecting shared Redis');
|
|
1023
|
+
await SharedRedisProvider.disconnect();
|
|
920
1024
|
}
|
|
1025
|
+
|
|
1026
|
+
this.logger.info('OneBun application stopped');
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* Initialize the queue system based on configuration and detected handlers
|
|
1031
|
+
*/
|
|
1032
|
+
private async initializeQueue(controllers: Function[]): Promise<void> {
|
|
1033
|
+
const queueOptions = this.options.queue;
|
|
1034
|
+
|
|
1035
|
+
// Check if any controller has queue-related decorators
|
|
1036
|
+
const hasQueueHandlers = controllers.some(controller => {
|
|
1037
|
+
const instance = this.rootModule.getControllerInstance?.(controller);
|
|
1038
|
+
if (!instance) {
|
|
1039
|
+
return false;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
return hasQueueDecorators(instance.constructor);
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
// Determine if queue should be enabled
|
|
1046
|
+
const shouldEnableQueue = queueOptions?.enabled ?? hasQueueHandlers;
|
|
1047
|
+
if (!shouldEnableQueue) {
|
|
1048
|
+
this.logger.debug('Queue system not enabled (no handlers detected or explicitly disabled)');
|
|
1049
|
+
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
// Create the appropriate adapter
|
|
1054
|
+
const adapterType = queueOptions?.adapter ?? 'memory';
|
|
1055
|
+
|
|
1056
|
+
if (adapterType === 'memory') {
|
|
1057
|
+
this.queueAdapter = new InMemoryQueueAdapter();
|
|
1058
|
+
this.logger.info('Queue system initialized with in-memory adapter');
|
|
1059
|
+
} else if (adapterType === 'redis') {
|
|
1060
|
+
const redisOptions = queueOptions?.redis ?? {};
|
|
1061
|
+
if (redisOptions.useSharedProvider !== false) {
|
|
1062
|
+
// Use shared Redis provider
|
|
1063
|
+
this.queueAdapter = new RedisQueueAdapter({
|
|
1064
|
+
useSharedClient: true,
|
|
1065
|
+
keyPrefix: redisOptions.prefix ?? 'onebun:queue:',
|
|
1066
|
+
});
|
|
1067
|
+
this.logger.info('Queue system initialized with Redis adapter (shared provider)');
|
|
1068
|
+
} else if (redisOptions.url) {
|
|
1069
|
+
// Create dedicated Redis connection
|
|
1070
|
+
this.queueAdapter = new RedisQueueAdapter({
|
|
1071
|
+
useSharedClient: false,
|
|
1072
|
+
url: redisOptions.url,
|
|
1073
|
+
keyPrefix: redisOptions.prefix ?? 'onebun:queue:',
|
|
1074
|
+
});
|
|
1075
|
+
this.logger.info('Queue system initialized with Redis adapter (dedicated connection)');
|
|
1076
|
+
} else {
|
|
1077
|
+
throw new Error('Redis queue adapter requires either useSharedProvider: true or a url');
|
|
1078
|
+
}
|
|
1079
|
+
} else {
|
|
1080
|
+
throw new Error(`Unknown queue adapter type: ${adapterType}`);
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
// Connect the adapter
|
|
1084
|
+
await this.queueAdapter.connect();
|
|
1085
|
+
|
|
1086
|
+
// Create queue service with config
|
|
1087
|
+
this.queueService = new QueueService({
|
|
1088
|
+
adapter: adapterType,
|
|
1089
|
+
options: queueOptions?.redis,
|
|
1090
|
+
});
|
|
1091
|
+
|
|
1092
|
+
// Initialize with the adapter
|
|
1093
|
+
await this.queueService.initialize(this.queueAdapter);
|
|
1094
|
+
|
|
1095
|
+
// Register handlers from controllers using registerService
|
|
1096
|
+
for (const controllerClass of controllers) {
|
|
1097
|
+
const instance = this.rootModule.getControllerInstance?.(controllerClass);
|
|
1098
|
+
if (!instance) {
|
|
1099
|
+
continue;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
// Only register if the controller has queue decorators
|
|
1103
|
+
if (hasQueueDecorators(controllerClass)) {
|
|
1104
|
+
await this.queueService.registerService(
|
|
1105
|
+
instance,
|
|
1106
|
+
controllerClass as new (...args: unknown[]) => unknown,
|
|
1107
|
+
);
|
|
1108
|
+
this.logger.debug(`Registered queue handlers for controller: ${controllerClass.name}`);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
// Start the queue service
|
|
1113
|
+
await this.queueService.start();
|
|
1114
|
+
this.logger.info('Queue service started');
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
/**
|
|
1118
|
+
* Get the queue service instance
|
|
1119
|
+
* @returns The queue service or null if not enabled
|
|
1120
|
+
*/
|
|
1121
|
+
getQueueService(): QueueService | null {
|
|
1122
|
+
return this.queueService;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* Register signal handlers for graceful shutdown
|
|
1127
|
+
* Call this after start() to enable automatic shutdown on SIGTERM/SIGINT
|
|
1128
|
+
*
|
|
1129
|
+
* @example
|
|
1130
|
+
* ```typescript
|
|
1131
|
+
* const app = new OneBunApplication(AppModule, options);
|
|
1132
|
+
* await app.start();
|
|
1133
|
+
* app.enableGracefulShutdown();
|
|
1134
|
+
* ```
|
|
1135
|
+
*/
|
|
1136
|
+
enableGracefulShutdown(): void {
|
|
1137
|
+
const shutdown = async (signal: string) => {
|
|
1138
|
+
this.logger.info(`Received ${signal}, initiating graceful shutdown...`);
|
|
1139
|
+
await this.stop();
|
|
1140
|
+
process.exit(0);
|
|
1141
|
+
};
|
|
1142
|
+
|
|
1143
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
1144
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
1145
|
+
|
|
1146
|
+
this.logger.debug('Graceful shutdown handlers registered');
|
|
921
1147
|
}
|
|
922
1148
|
|
|
923
1149
|
/**
|
|
@@ -15,8 +15,9 @@ import {
|
|
|
15
15
|
type SyncLogger,
|
|
16
16
|
} from '@onebun/logger';
|
|
17
17
|
|
|
18
|
+
import { resolveEnvOverrides } from '../service-client/env-resolver';
|
|
19
|
+
|
|
18
20
|
import { OneBunApplication } from './application';
|
|
19
|
-
import { resolveEnvOverrides } from './env-resolver';
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* ENV schema for service filtering
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
beforeEach,
|
|
13
13
|
} from 'bun:test';
|
|
14
14
|
|
|
15
|
+
import { HttpMethod, ParamType } from '../types';
|
|
16
|
+
|
|
15
17
|
import {
|
|
16
18
|
injectable,
|
|
17
19
|
Controller,
|
|
@@ -39,7 +41,6 @@ import {
|
|
|
39
41
|
getModuleMetadata,
|
|
40
42
|
ApiResponse,
|
|
41
43
|
} from './decorators';
|
|
42
|
-
import { HttpMethod, ParamType } from './types';
|
|
43
44
|
|
|
44
45
|
describe('decorators', () => {
|
|
45
46
|
beforeEach(() => {
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import './metadata'; // Import polyfill first
|
|
2
2
|
import type { Type } from 'arktype';
|
|
3
3
|
|
|
4
|
-
import { getConstructorParamTypes as getDesignParamTypes, Reflect } from './metadata';
|
|
5
4
|
import {
|
|
6
5
|
type ControllerMetadata,
|
|
7
6
|
HttpMethod,
|
|
8
7
|
type ParamMetadata,
|
|
9
8
|
ParamType,
|
|
10
|
-
} from '
|
|
9
|
+
} from '../types';
|
|
10
|
+
|
|
11
|
+
import { getConstructorParamTypes as getDesignParamTypes, Reflect } from './metadata';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Metadata storage for controllers
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decorators Module
|
|
3
|
+
*
|
|
4
|
+
* HTTP decorators and metadata utilities.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Export metadata utilities (excluding getConstructorParamTypes which is re-exported from decorators)
|
|
8
|
+
export {
|
|
9
|
+
defineMetadata,
|
|
10
|
+
getMetadata,
|
|
11
|
+
Reflect,
|
|
12
|
+
} from './metadata';
|
|
13
|
+
|
|
14
|
+
// Export all decorators (including getConstructorParamTypes)
|
|
15
|
+
export * from './decorators';
|