quantum-flow 1.8.0 → 1.10.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 (59) hide show
  1. package/README.md +116 -51
  2. package/dist/app/http/Application.d.ts +3 -2
  3. package/dist/app/http/Application.js +27 -19
  4. package/dist/app/http/index.d.ts +0 -1
  5. package/dist/app/http/index.js +0 -1
  6. package/dist/constants.d.ts +3 -0
  7. package/dist/constants.js +4 -1
  8. package/dist/core/Controller.d.ts +12 -8
  9. package/dist/core/Controller.js +41 -12
  10. package/dist/core/{utils/extractors.js → decorators.js} +1 -1
  11. package/dist/core/index.d.ts +1 -1
  12. package/dist/core/index.js +1 -1
  13. package/dist/sse/decorators.d.ts +6 -0
  14. package/dist/sse/decorators.js +29 -0
  15. package/dist/sse/index.d.ts +2 -0
  16. package/dist/sse/index.js +8 -0
  17. package/dist/sse/server.d.ts +14 -0
  18. package/dist/sse/server.js +85 -0
  19. package/dist/sse/service.d.ts +17 -0
  20. package/dist/sse/service.js +39 -0
  21. package/dist/types/common.d.ts +1 -1
  22. package/dist/types/controller.d.ts +40 -4
  23. package/dist/types/http.d.ts +3 -0
  24. package/dist/types/index.d.ts +1 -0
  25. package/dist/types/index.js +1 -0
  26. package/dist/types/sse.d.ts +37 -0
  27. package/dist/types/sse.js +2 -0
  28. package/dist/types/websocket.d.ts +1 -6
  29. package/dist/utils/controller.d.ts +1 -1
  30. package/dist/utils/controller.js +13 -8
  31. package/dist/{core/utils/websocket.d.ts → ws/decorators.d.ts} +2 -2
  32. package/dist/{core/utils/websocket.js → ws/decorators.js} +3 -6
  33. package/dist/ws/index.d.ts +3 -0
  34. package/dist/{examples/controllers → ws}/index.js +2 -2
  35. package/dist/{app/http/websocket/WebsocketServer.d.ts → ws/server.d.ts} +3 -3
  36. package/dist/{app/http/websocket/WebsocketServer.js → ws/server.js} +5 -13
  37. package/dist/{app/http/websocket/WebsocketService.d.ts → ws/service.d.ts} +2 -2
  38. package/dist/{app/http/Socket.d.ts → ws/socket.d.ts} +1 -1
  39. package/dist/{app/http/Socket.js → ws/socket.js} +6 -6
  40. package/package.json +12 -2
  41. package/dist/core/utils/index.d.ts +0 -2
  42. package/dist/core/utils/index.js +0 -18
  43. package/dist/examples/app.d.ts +0 -4
  44. package/dist/examples/app.js +0 -48
  45. package/dist/examples/controllers/index.d.ts +0 -2
  46. package/dist/examples/controllers/socket.d.ts +0 -7
  47. package/dist/examples/controllers/socket.js +0 -62
  48. package/dist/examples/controllers/user.d.ts +0 -15
  49. package/dist/examples/controllers/user.js +0 -107
  50. package/dist/examples/controllers/userMetadata.d.ts +0 -8
  51. package/dist/examples/controllers/userMetadata.js +0 -103
  52. package/dist/examples/lambda.d.ts +0 -1
  53. package/dist/examples/lambda.js +0 -6
  54. package/dist/examples/mock/context.d.ts +0 -14
  55. package/dist/examples/mock/context.js +0 -17
  56. package/dist/examples/server.d.ts +0 -1
  57. package/dist/examples/server.js +0 -6
  58. /package/dist/core/{utils/extractors.d.ts → decorators.d.ts} +0 -0
  59. /package/dist/{app/http/websocket/WebsocketService.js → ws/service.js} +0 -0
package/README.md CHANGED
@@ -21,6 +21,8 @@ You can use controllers and server functionality by importing controllers and cr
21
21
  - `quantum-flow/aws` - Main application source code AWS Lambda.
22
22
  - `quantum-flow/core` - Core framework components like Controller and Endpoint.
23
23
  - `quantum-flow/middlewares` - Core middlewares to use within the application.
24
+ - `quantum-flow/ws` - Websocket decorators.
25
+ - `quantum-flow/sse` - Server side events decorators.
24
26
 
25
27
  ---
26
28
 
@@ -33,7 +35,6 @@ import {
33
35
  Body,
34
36
  Controller,
35
37
  Headers,
36
- InjectWS,
37
38
  IWebSocketService,
38
39
  Params,
39
40
  PUT,
@@ -45,6 +46,7 @@ import {
45
46
  } from 'quantum-flow/core';
46
47
  import {IsString} from 'class-validator'
47
48
  import { Catch, Cors, Sanitize, Use } from 'quantum-flow/middlewares';
49
+ import { InjectWS } from 'quantum-flow/ws';
48
50
 
49
51
  class UserDto {
50
52
  constructor() {}
@@ -137,7 +139,8 @@ server.listen().catch(console.error);
137
139
  - Use `@Multipart` for handling multipart/form-data requests.
138
140
  - Use `@Request` to access the original request object.
139
141
  - Use `@Response` to access the original object.
140
- - Use `@InjectWS` to access the WebsocketService.
142
+ - Use `@InjectWS` to access the websocket service.
143
+ - Use `@InjectSSE()` to access the server-side-event service.
141
144
 
142
145
  # AWS Lambda Support
143
146
 
@@ -167,18 +170,26 @@ export const handler = LambdaAdapter.createHandler(RootController);
167
170
 
168
171
  Enable WebSocket in the server configuration and register WebSocket controllers.
169
172
 
173
+ ## Enabling WebSocket Support in Server
174
+
175
+ To enable SSE support, configure your HTTP server with the `sse: true` option and register controllers that use SSE.
176
+
177
+ Example server setup:
178
+
179
+ ```typescript
180
+ @Server( {websocket: { enabled: true, path: '/ws' } })
181
+ ```
182
+
183
+ ## Injecting WebSocket events in Controller
184
+
170
185
  ```typescript
186
+ import { OnConnection, Subscribe, OnMessage } from 'quantum-flow/ws';
171
187
  @Controller('socket')
172
188
  export class Socket {
173
189
  @OnConnection()
174
190
  onConnection(event: WebSocketEvent) {
175
191
  // Send greeting ONLY to this client
176
- event.client.socket.send(
177
- JSON.stringify({
178
- type: 'welcome',
179
- data: { message: 'Welcome!' },
180
- }),
181
- );
192
+ event.client.socket.send(JSON.stringify({ type: 'welcome', data: { message: 'Welcome!' } }));
182
193
  }
183
194
 
184
195
  /**
@@ -200,14 +211,6 @@ export class Socket {
200
211
  // That's it, the message will be sent to subscribers automatically!
201
212
  }
202
213
 
203
- /**
204
- * 3. @Subscribe for another room
205
- */
206
- @Subscribe('news')
207
- onNewsMessage(event: WebSocketEvent) {
208
- // Automatic broadcast to all subscribed to 'news'
209
- }
210
-
211
214
  /**
212
215
  * 4. @OnMessage for commands (without WebSocketService)
213
216
  */
@@ -242,65 +245,127 @@ export class Socket {
242
245
  }
243
246
  ```
244
247
 
245
- # Decorators
248
+ # Server-Sent Events (SSE) Support
249
+
250
+ The framework supports Server-Sent Events (SSE) to enable real-time, one-way communication from the server to clients over HTTP.
246
251
 
247
- ### Use
252
+ ## Defining SSE Controllers
248
253
 
249
- Class decorator to add global middlewares to the server.
250
- Should be used only with @Server decorator
254
+ Use the `@Controller` decorator to define controllers with a `prefix` and optionally include sub-controllers. This allows modular organization of your API endpoints.
255
+
256
+ Example:
251
257
 
252
258
  ```typescript
253
- @Use(middleware)
254
- class App {}
259
+ @Controller({
260
+ prefix: 'user',
261
+ controllers: [UserMetadata],
262
+ middlewares: [function UserGlobalUse() {}],
263
+ interceptor: (data, req, res) => {
264
+ return { data, intercepted: true };
265
+ },
266
+ })
267
+ export class User {}
255
268
  ```
256
269
 
257
- ### Catch
270
+ ## Injecting SSE Service
258
271
 
259
- Class decorator to set a global error handler for the server.
272
+ Use the `@InjectSSE` decorator in your controller methods to create and manage SSE connections. This service allows sending events to connected clients.
273
+
274
+ Example method using SSE:
260
275
 
261
276
  ```typescript
262
- @Catch((error) => {
263
- return { message: 'Internal Server Error' };
264
- })
265
- class App {}
277
+ import { InjectSSE } from 'quantum-flow/sse';
278
+
279
+ @Controller('user')
280
+ export class UserMetadata {
281
+ @GET('/subscribesse')
282
+ async subscribesse(@InjectSSE() sse) {
283
+ const client = sse.createConnection(res);
284
+
285
+ sse.sendToClient(client.id, {
286
+ event: 'welcome message',
287
+ data: { message: 'Connected to notifications' },
288
+ });
289
+
290
+ return 'hellow';
291
+ }
292
+ }
266
293
  ```
267
294
 
268
- ### Port
295
+ ## SSE Event Decorators
296
+
297
+ The framework provides decorators to handle SSE connection lifecycle events:
269
298
 
270
- Class decorator to set the server port.
299
+ - `@OnSSEConnection()`: Decorate a method to handle new SSE connections.
300
+ - `@OnSSEError()`: Decorate a method to handle SSE errors.
301
+ - `@OnSSEClose()`: Decorate a method to handle SSE connection closures.
302
+
303
+ Example usage:
271
304
 
272
305
  ```typescript
273
- @Port(3000)
274
- class App {}
306
+ import { OnSSEConnection, OnSSEError, OnSSEClose } from 'quantum-flow/sse';
307
+
308
+ @Controller('user')
309
+ export class User {
310
+ @OnSSEConnection()
311
+ async onsseconnection(@Request() req: any, @Response() res: any) {
312
+ console.log('SSE connection established');
313
+ return req.body;
314
+ }
315
+
316
+ @OnSSEError()
317
+ async onsseerror(@Request() req: any, @Response() res: any) {
318
+ console.log('SSE error occurred');
319
+ return req.body;
320
+ }
321
+
322
+ @OnSSEClose()
323
+ async onsseclose(@Request() req: any, @Response() res: any) {
324
+ console.log('SSE connection closed');
325
+ return req.body;
326
+ }
327
+ }
275
328
  ```
276
329
 
277
- ### Host
330
+ ## Sending SSE Events
331
+
332
+ Use the injected SSE service to send events to clients. You can send events to all clients or specific clients by ID.
278
333
 
279
- Class decorator to set the server host.
334
+ Example:
280
335
 
281
336
  ```typescript
282
- @Host('localhost')
283
- class App {}
337
+ sse.sendToClient(clientId, {
338
+ event: 'eventName',
339
+ data: { key: 'value' },
340
+ });
284
341
  ```
285
342
 
286
- ### Validate
343
+ ## Enabling SSE Support in Server
287
344
 
288
- Method or class decorator to validate request parameters (query, body, params, headers) against a DTO class using class-validator.
345
+ To enable SSE support, configure your HTTP server with the `sse: true` option and register controllers that use SSE.
346
+
347
+ Example server setup:
289
348
 
290
349
  ```typescript
291
- import { IsEmail } from 'class-validator';
292
- class UserDTO {
293
- @IsEmail()
294
- email: string;
350
+ import { Server, HttpServer } from 'quantum-flow/http';
351
+ import { User, UserMetadata } from './controllers';
295
352
 
296
- @Length(6, 20)
297
- password: string;
298
- }
353
+ @Server({
354
+ controllers: [User, UserMetadata],
355
+ sse: { enabled: true },
356
+ })
357
+ class App {}
299
358
 
300
- class UserController {
301
- @POST('/')
302
- async createUser(@Body(UserDTO) user: UserDTO, @Query() query) {
303
- // Your logic here
304
- }
305
- }
359
+ const server = new HttpServer(App);
360
+ server.listen().catch(console.error);
306
361
  ```
362
+
363
+ ## Summary
364
+
365
+ - Use `@Controller` with `prefix` and `controllers` to organize your API.
366
+ - Use `@InjectSSE` to create SSE connections in controller methods.
367
+ - Use the SSE service's `send` method to push events to clients.
368
+ - Use `@OnSSEConnection`, `@OnSSEError`, and `@OnSSEClose` decorators to handle SSE lifecycle events.
369
+ - Enable SSE in your server configuration and register SSE controllers.
370
+
371
+ This setup allows you to build real-time, event-driven APIs using Server-Sent Events in a clean and modular way.
@@ -1,10 +1,11 @@
1
1
  import { ServerConfig } from '../../types/index.js';
2
2
  import http from 'http';
3
- import { Socket } from './Socket';
4
- export declare class HttpServer extends Socket {
3
+ export declare class HttpServer {
5
4
  private app;
6
5
  private config;
7
6
  private isRunning;
7
+ private sse?;
8
+ private websocket?;
8
9
  constructor(configOrClass: new (...args: any[]) => any);
9
10
  private logConfig;
10
11
  listen(port?: number, host?: string): Promise<http.Server>;
@@ -7,21 +7,29 @@ exports.HttpServer = void 0;
7
7
  const _constants_1 = require("../../constants.js");
8
8
  const _utils_1 = require("../../utils/index.js");
9
9
  const http_1 = __importDefault(require("http"));
10
- const Socket_1 = require("./Socket");
11
- const WebsocketServer_1 = require("./websocket/WebsocketServer");
12
- const WebsocketService_1 = require("./websocket/WebsocketService");
13
- class HttpServer extends Socket_1.Socket {
10
+ const server_1 = require("../../ws/server");
11
+ const service_1 = require("../../ws/service");
12
+ const server_2 = require("../../sse/server");
13
+ const service_2 = require("../../sse/service");
14
+ class HttpServer {
14
15
  app;
15
16
  config;
16
17
  isRunning = false;
18
+ sse;
19
+ websocket;
17
20
  constructor(configOrClass) {
18
- super();
19
21
  this.config = (0, _utils_1.resolveConfig)(configOrClass);
20
22
  const app = http_1.default.createServer(this.requestHandler.bind(this));
23
+ const controllers = this.getAllControllers(this.config.controllers);
21
24
  if (this.config.websocket?.enabled) {
22
- this.wss = new WebsocketServer_1.WebSocketServer(app, { path: this.config.websocket.path });
23
- this.wss.registerControllers(this.getAllControllers(this.config.controllers));
24
- WebsocketService_1.WebSocketService.getInstance().initialize(this.wss);
25
+ this.websocket = new server_1.WebSocketServer(app, { path: this.config.websocket.path });
26
+ this.websocket.registerControllers(controllers);
27
+ service_1.WebSocketService.getInstance().initialize(this.websocket);
28
+ }
29
+ if (this.config.sse?.enabled) {
30
+ this.sse = new server_2.SSEServer();
31
+ this.sse.registerControllers(controllers);
32
+ service_2.SSEService.getInstance().initialize(this.sse);
25
33
  }
26
34
  this.app = app;
27
35
  this.logConfig();
@@ -190,17 +198,17 @@ class HttpServer extends Socket_1.Socket {
190
198
  }
191
199
  async sendResponse(res, data, startTime) {
192
200
  const response = data?.data !== undefined ? data.data : data;
193
- if (!res.headersSent) {
194
- if (!res.getHeader('Content-Type')) {
195
- res.setHeader('Content-Type', 'application/json');
196
- }
197
- if (data?.headers) {
198
- Object.entries(data.headers).forEach(([key, value]) => {
199
- if (!res.getHeader(key)) {
200
- res.setHeader(key, value);
201
- }
202
- });
203
- }
201
+ if (res.headersSent)
202
+ return;
203
+ if (!res.getHeader('Content-Type')) {
204
+ res.setHeader('Content-Type', 'application/json');
205
+ }
206
+ if (data?.headers) {
207
+ Object.entries(data.headers).forEach(([key, value]) => {
208
+ if (!res.getHeader(key)) {
209
+ res.setHeader(key, value);
210
+ }
211
+ });
204
212
  }
205
213
  res.setHeader('X-Response-Time', `${Date.now() - startTime}ms`);
206
214
  res.statusCode = data.status ?? 200;
@@ -1,3 +1,2 @@
1
1
  export * from './Application';
2
2
  export * from './decorators';
3
- export * from './websocket/WebsocketServer';
@@ -16,4 +16,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./Application"), exports);
18
18
  __exportStar(require("./decorators"), exports);
19
- __exportStar(require("./websocket/WebsocketServer"), exports);
@@ -21,3 +21,6 @@ export declare const TO_VALIDATE: string[];
21
21
  export declare const STATISTIC: Record<'controllers' | 'routes', number>;
22
22
  export declare const INCREMENT_STATISTIC: (prop: "controllers" | "routes") => void;
23
23
  export declare const CORS_METADATA = "cors:config";
24
+ export declare const SSE_METADATA_KEY = "sse:handlers";
25
+ export declare const SSE_TOPIC_KEY = "sse:topics";
26
+ export declare const SSE_SERVICE_KEY = "sse:service";
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CORS_METADATA = exports.INCREMENT_STATISTIC = exports.STATISTIC = exports.TO_VALIDATE = exports.OK_STATUSES = exports.STOPPED = exports.SANITIZE = exports.CATCH = exports.INTECEPT = exports.WS_SERVICE_KEY = exports.WS_TOPIC_KEY = exports.WS_HANDLER = exports.USE_MIDDLEWARE = exports.SERVER_CONFIG_KEY = exports.OK_METADATA_KEY = exports.ENDPOINT = exports.INTERCEPTOR = exports.CONTROLLERS = exports.MIDDLEWARES = exports.ROUTE_MIDDLEWARES = exports.ROUTE_PREFIX = exports.APP_METADATA_KEY = exports.PARAM_METADATA_KEY = void 0;
3
+ exports.SSE_SERVICE_KEY = exports.SSE_TOPIC_KEY = exports.SSE_METADATA_KEY = exports.CORS_METADATA = exports.INCREMENT_STATISTIC = exports.STATISTIC = exports.TO_VALIDATE = exports.OK_STATUSES = exports.STOPPED = exports.SANITIZE = exports.CATCH = exports.INTECEPT = exports.WS_SERVICE_KEY = exports.WS_TOPIC_KEY = exports.WS_HANDLER = exports.USE_MIDDLEWARE = exports.SERVER_CONFIG_KEY = exports.OK_METADATA_KEY = exports.ENDPOINT = exports.INTERCEPTOR = exports.CONTROLLERS = exports.MIDDLEWARES = exports.ROUTE_MIDDLEWARES = exports.ROUTE_PREFIX = exports.APP_METADATA_KEY = exports.PARAM_METADATA_KEY = void 0;
4
4
  exports.PARAM_METADATA_KEY = 'design:parameters';
5
5
  exports.APP_METADATA_KEY = 'app:configuration';
6
6
  exports.ROUTE_PREFIX = 'route:prefix';
@@ -35,3 +35,6 @@ const INCREMENT_STATISTIC = (prop) => {
35
35
  };
36
36
  exports.INCREMENT_STATISTIC = INCREMENT_STATISTIC;
37
37
  exports.CORS_METADATA = 'cors:config';
38
+ exports.SSE_METADATA_KEY = 'sse:handlers';
39
+ exports.SSE_TOPIC_KEY = 'sse:topics';
40
+ exports.SSE_SERVICE_KEY = 'sse:service';
@@ -1,4 +1,4 @@
1
- import { AppRequest, ControllerClass, ControllerConfig, InterceptorCB, RouteContext } from '../types/index.js';
1
+ import { AppRequest, ControllerClass, ControllerConfig, InterceptorCB, RouteContext, SeeControllerHandlers, WsControllerHandlers } from '../types/index.js';
2
2
  import { ServerResponse } from 'http';
3
3
  import 'reflect-metadata';
4
4
  /**
@@ -25,21 +25,25 @@ import 'reflect-metadata';
25
25
  export declare function Controller(config: string | ControllerConfig, middlewares?: Array<InterceptorCB>): <T extends ControllerClass>(constructor: T) => {
26
26
  new (...args: any[]): {
27
27
  [x: string]: any;
28
+ ws?: WsControllerHandlers;
29
+ sse?: SeeControllerHandlers;
28
30
  executeControllerMethod: (controller: import("../types/index.js").ControllerInstance, propertyName: string, request: AppRequest, response: ServerResponse) => Promise<any>;
29
31
  getControllerMethods: (controller: import("../types/index.js").ControllerInstance) => import("../types/index.js").ControllerMethods;
30
32
  handleRequest: (request: AppRequest, response: ServerResponse) => Promise<any>;
31
33
  routeWalker(context: RouteContext, request: AppRequest, response: ServerResponse): Promise<any>;
32
- getWebSocketController(): {
34
+ lookupWS(): void;
35
+ lookupSSE(): void;
36
+ getSSEController(): {
33
37
  instance: /*elided*/ any;
34
38
  handlers: {
35
- connection: any;
36
- message: any;
37
- close: any;
38
- error: any;
39
+ connection: any[];
40
+ close: any[];
41
+ error: any[];
39
42
  };
40
- topics: any;
41
43
  };
42
- getWSHandlers(type: string): any;
44
+ getWSHandlers(type: string): any[];
45
+ getSSEHandlers(type: string): any[];
43
46
  getWSTopics(): any;
47
+ typedHandlers: (handlers: any[], type: string) => any[];
44
48
  };
45
49
  } & T;
@@ -64,10 +64,14 @@ function Controller(config, middlewares = []) {
64
64
  });
65
65
  }
66
66
  return class extends constructor {
67
+ ws;
68
+ sse;
67
69
  executeControllerMethod = _utils_1.executeControllerMethod;
68
70
  getControllerMethods = _utils_1.getControllerMethods;
69
71
  constructor(...args) {
70
72
  super(...args);
73
+ this.lookupWS();
74
+ this.lookupSSE();
71
75
  }
72
76
  handleRequest = async (request, response) => {
73
77
  const middlewares = []
@@ -200,26 +204,43 @@ function Controller(config, middlewares = []) {
200
204
  }
201
205
  return null;
202
206
  }
203
- getWebSocketController() {
207
+ lookupWS() {
208
+ const connection = this.getWSHandlers('connection');
209
+ const message = this.getWSHandlers('message');
210
+ const error = this.getWSHandlers('error');
211
+ const close = this.getWSHandlers('close');
212
+ const topics = this.getWSHandlers('topics');
213
+ if ([...connection, ...message, ...error, ...close, ...topics].length === 0) {
214
+ return;
215
+ }
216
+ this.ws = { handlers: { connection, message, close, error }, topics };
217
+ }
218
+ lookupSSE() {
219
+ const connection = this.getSSEHandlers('connection');
220
+ const error = this.getSSEHandlers('error');
221
+ const close = this.getSSEHandlers('close');
222
+ if ([...connection, ...error, ...close].length === 0) {
223
+ return;
224
+ }
225
+ this.sse = { handlers: { connection, close, error } };
226
+ }
227
+ getSSEController() {
204
228
  return {
205
229
  instance: this,
206
230
  handlers: {
207
- connection: this.getWSHandlers('connection'),
208
- message: this.getWSHandlers('message'),
209
- close: this.getWSHandlers('close'),
210
- error: this.getWSHandlers('error'),
231
+ connection: this.getSSEHandlers('connection'),
232
+ close: this.getSSEHandlers('close'),
233
+ error: this.getSSEHandlers('error'),
211
234
  },
212
- topics: this.getWSTopics(),
213
235
  };
214
236
  }
215
237
  getWSHandlers(type) {
216
238
  const handlers = Reflect.getMetadata(_constants_1.WS_HANDLER, this.constructor) || [];
217
- return handlers
218
- .filter((h) => h.type === type)
219
- .map((h) => ({
220
- ...h,
221
- fn: this[h.method].bind(this),
222
- }));
239
+ return this.typedHandlers(handlers, type);
240
+ }
241
+ getSSEHandlers(type) {
242
+ const handlers = Reflect.getMetadata(_constants_1.SSE_METADATA_KEY, this.constructor) || [];
243
+ return this.typedHandlers(handlers, type);
223
244
  }
224
245
  getWSTopics() {
225
246
  const topics = Reflect.getMetadata(_constants_1.WS_TOPIC_KEY, this.constructor) || [];
@@ -228,6 +249,14 @@ function Controller(config, middlewares = []) {
228
249
  fn: this[t.method].bind(this),
229
250
  }));
230
251
  }
252
+ typedHandlers = (handlers, type) => {
253
+ return handlers
254
+ .filter((h) => h.type === type)
255
+ .map((h) => ({
256
+ ...h,
257
+ fn: this[h.method].bind(this),
258
+ }));
259
+ };
231
260
  };
232
261
  };
233
262
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Response = exports.Multipart = exports.Cookies = exports.Headers = exports.Request = exports.Query = exports.Params = exports.Body = void 0;
4
- const _utils_1 = require("../../utils/index.js");
4
+ const _utils_1 = require("../utils/index.js");
5
5
  /**
6
6
  * Parameter decorator to extract and validate the request body.
7
7
  * @param dto Optional DTO class for validation and transformation.
@@ -6,5 +6,5 @@
6
6
  */
7
7
  export { AppRequest, CORSConfig, EndpointResponse, ErrorCB, HttpError, IController, InterceptorCB, IWebSocketService, MiddlewareCB, MultipartFile, ResponseWithStatus, WebSocketClient, WebSocketEvent, WebSocketMessage, } from '../types/index.js';
8
8
  export * from './Controller';
9
+ export * from './decorators';
9
10
  export * from './Endpoint';
10
- export * from './utils';
@@ -15,5 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./Controller"), exports);
18
+ __exportStar(require("./decorators"), exports);
18
19
  __exportStar(require("./Endpoint"), exports);
19
- __exportStar(require("./utils"), exports);
@@ -0,0 +1,6 @@
1
+ export type SSEHandlerType = 'connection' | 'close' | 'error';
2
+ export declare function OnSSE(type: SSEHandlerType): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
3
+ export declare function OnSSEConnection(): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
4
+ export declare function OnSSEClose(): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
5
+ export declare function OnSSEError(): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
6
+ export declare function InjectSSE(): (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OnSSE = OnSSE;
4
+ exports.OnSSEConnection = OnSSEConnection;
5
+ exports.OnSSEClose = OnSSEClose;
6
+ exports.OnSSEError = OnSSEError;
7
+ exports.InjectSSE = InjectSSE;
8
+ const _constants_1 = require("../constants.js");
9
+ const _utils_1 = require("../utils/index.js");
10
+ function OnSSE(type) {
11
+ return function (target, propertyKey, descriptor) {
12
+ const handlers = Reflect.getMetadata(_constants_1.SSE_METADATA_KEY, target.constructor) || [];
13
+ handlers.push({ type, method: propertyKey });
14
+ Reflect.defineMetadata(_constants_1.SSE_METADATA_KEY, handlers, target.constructor);
15
+ return descriptor;
16
+ };
17
+ }
18
+ function OnSSEConnection() {
19
+ return OnSSE('connection');
20
+ }
21
+ function OnSSEClose() {
22
+ return OnSSE('close');
23
+ }
24
+ function OnSSEError() {
25
+ return OnSSE('error');
26
+ }
27
+ function InjectSSE() {
28
+ return (0, _utils_1.createParamDecorator)('sse');
29
+ }
@@ -0,0 +1,2 @@
1
+ export { ISSEService, SSEClient, SSEEvent, SSEMessage } from '../types/index.js';
2
+ export { InjectSSE, OnSSEClose, OnSSEConnection, OnSSEError } from './decorators';
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OnSSEError = exports.OnSSEConnection = exports.OnSSEClose = exports.InjectSSE = void 0;
4
+ var decorators_1 = require("./decorators");
5
+ Object.defineProperty(exports, "InjectSSE", { enumerable: true, get: function () { return decorators_1.InjectSSE; } });
6
+ Object.defineProperty(exports, "OnSSEClose", { enumerable: true, get: function () { return decorators_1.OnSSEClose; } });
7
+ Object.defineProperty(exports, "OnSSEConnection", { enumerable: true, get: function () { return decorators_1.OnSSEConnection; } });
8
+ Object.defineProperty(exports, "OnSSEError", { enumerable: true, get: function () { return decorators_1.OnSSEError; } });
@@ -0,0 +1,14 @@
1
+ import { ControllerType, ISSEServer, SSEClient, SSEMessage } from '../types/index.js';
2
+ import { ServerResponse } from 'http';
3
+ export declare class SSEServer implements ISSEServer {
4
+ private clients;
5
+ controllers: any[];
6
+ createConnection(res: ServerResponse): SSEClient;
7
+ sendToClient(clientId: string, message: SSEMessage): boolean;
8
+ broadcast(message: SSEMessage, excludeClientId?: string): void;
9
+ getStats(): {
10
+ clients: number;
11
+ };
12
+ registerControllers(controllers: ControllerType[]): void;
13
+ private triggerHandlers;
14
+ }