quantum-flow 1.8.1 → 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 (38) hide show
  1. package/README.md +112 -36
  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/sse/decorators.d.ts +6 -0
  11. package/dist/sse/decorators.js +29 -0
  12. package/dist/sse/index.d.ts +2 -0
  13. package/dist/sse/index.js +8 -0
  14. package/dist/sse/server.d.ts +14 -0
  15. package/dist/sse/server.js +85 -0
  16. package/dist/sse/service.d.ts +17 -0
  17. package/dist/sse/service.js +39 -0
  18. package/dist/types/common.d.ts +1 -1
  19. package/dist/types/controller.d.ts +40 -4
  20. package/dist/types/http.d.ts +3 -0
  21. package/dist/types/index.d.ts +1 -0
  22. package/dist/types/index.js +1 -0
  23. package/dist/types/sse.d.ts +37 -0
  24. package/dist/types/sse.js +2 -0
  25. package/dist/types/websocket.d.ts +1 -0
  26. package/dist/utils/controller.d.ts +1 -1
  27. package/dist/utils/controller.js +13 -8
  28. package/dist/ws/decorators.d.ts +1 -1
  29. package/dist/ws/decorators.js +2 -5
  30. package/dist/ws/index.d.ts +1 -0
  31. package/dist/ws/index.js +1 -0
  32. package/dist/{app/http/websocket/WebsocketServer.d.ts → ws/server.d.ts} +3 -3
  33. package/dist/{app/http/websocket/WebsocketServer.js → ws/server.js} +5 -13
  34. package/dist/{app/http/websocket/WebsocketService.d.ts → ws/service.d.ts} +2 -2
  35. package/dist/{app/http/Socket.d.ts → ws/socket.d.ts} +1 -1
  36. package/dist/{app/http/Socket.js → ws/socket.js} +6 -6
  37. package/package.json +6 -1
  38. /package/dist/{app/http/websocket/WebsocketService.js → ws/service.js} +0 -0
package/README.md CHANGED
@@ -22,6 +22,7 @@ You can use controllers and server functionality by importing controllers and cr
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
24
  - `quantum-flow/ws` - Websocket decorators.
25
+ - `quantum-flow/sse` - Server side events decorators.
25
26
 
26
27
  ---
27
28
 
@@ -138,7 +139,8 @@ server.listen().catch(console.error);
138
139
  - Use `@Multipart` for handling multipart/form-data requests.
139
140
  - Use `@Request` to access the original request object.
140
141
  - Use `@Response` to access the original object.
141
- - Use `@InjectWS` to access the WebsocketService.
142
+ - Use `@InjectWS` to access the websocket service.
143
+ - Use `@InjectSSE()` to access the server-side-event service.
142
144
 
143
145
  # AWS Lambda Support
144
146
 
@@ -168,6 +170,18 @@ export const handler = LambdaAdapter.createHandler(RootController);
168
170
 
169
171
  Enable WebSocket in the server configuration and register WebSocket controllers.
170
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
+
171
185
  ```typescript
172
186
  import { OnConnection, Subscribe, OnMessage } from 'quantum-flow/ws';
173
187
  @Controller('socket')
@@ -231,65 +245,127 @@ export class Socket {
231
245
  }
232
246
  ```
233
247
 
234
- # 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.
251
+
252
+ ## Defining SSE Controllers
235
253
 
236
- ### Use
254
+ Use the `@Controller` decorator to define controllers with a `prefix` and optionally include sub-controllers. This allows modular organization of your API endpoints.
237
255
 
238
- Class decorator to add global middlewares to the server.
239
- Should be used only with @Server decorator
256
+ Example:
240
257
 
241
258
  ```typescript
242
- @Use(middleware)
243
- 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 {}
244
268
  ```
245
269
 
246
- ### Catch
270
+ ## Injecting SSE Service
271
+
272
+ Use the `@InjectSSE` decorator in your controller methods to create and manage SSE connections. This service allows sending events to connected clients.
247
273
 
248
- Class decorator to set a global error handler for the server.
274
+ Example method using SSE:
249
275
 
250
276
  ```typescript
251
- @Catch((error) => {
252
- return { message: 'Internal Server Error' };
253
- })
254
- 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
+ }
255
293
  ```
256
294
 
257
- ### Port
295
+ ## SSE Event Decorators
258
296
 
259
- Class decorator to set the server port.
297
+ The framework provides decorators to handle SSE connection lifecycle events:
298
+
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:
260
304
 
261
305
  ```typescript
262
- @Port(3000)
263
- 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
+ }
264
328
  ```
265
329
 
266
- ### Host
330
+ ## Sending SSE Events
267
331
 
268
- Class decorator to set the server host.
332
+ Use the injected SSE service to send events to clients. You can send events to all clients or specific clients by ID.
333
+
334
+ Example:
269
335
 
270
336
  ```typescript
271
- @Host('localhost')
272
- class App {}
337
+ sse.sendToClient(clientId, {
338
+ event: 'eventName',
339
+ data: { key: 'value' },
340
+ });
273
341
  ```
274
342
 
275
- ### Validate
343
+ ## Enabling SSE Support in Server
276
344
 
277
- 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:
278
348
 
279
349
  ```typescript
280
- import { IsEmail } from 'class-validator';
281
- class UserDTO {
282
- @IsEmail()
283
- email: string;
350
+ import { Server, HttpServer } from 'quantum-flow/http';
351
+ import { User, UserMetadata } from './controllers';
284
352
 
285
- @Length(6, 20)
286
- password: string;
287
- }
353
+ @Server({
354
+ controllers: [User, UserMetadata],
355
+ sse: { enabled: true },
356
+ })
357
+ class App {}
288
358
 
289
- class UserController {
290
- @POST('/')
291
- async createUser(@Body(UserDTO) user: UserDTO, @Query() query) {
292
- // Your logic here
293
- }
294
- }
359
+ const server = new HttpServer(App);
360
+ server.listen().catch(console.error);
295
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
  }
@@ -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
+ }
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SSEServer = void 0;
4
+ const uuid_1 = require("uuid");
5
+ class SSEServer {
6
+ clients = new Map();
7
+ controllers;
8
+ createConnection(res) {
9
+ const clientId = (0, uuid_1.v4)();
10
+ res.writeHead(200, {
11
+ 'Content-Type': 'text/event-stream',
12
+ 'Cache-Control': 'no-cache',
13
+ Connection: 'keep-alive',
14
+ 'Access-Control-Allow-Origin': '*',
15
+ });
16
+ res.write(': connected\n\n');
17
+ const client = {
18
+ id: clientId,
19
+ response: res,
20
+ topics: new Set(),
21
+ data: {},
22
+ connectedAt: new Date(),
23
+ };
24
+ this.clients.set(clientId, client);
25
+ this.triggerHandlers('connection', {
26
+ type: 'connection',
27
+ client,
28
+ data: res,
29
+ });
30
+ res.on('close', () => {
31
+ this.clients.delete(clientId);
32
+ this.triggerHandlers('close', { type: 'close', client });
33
+ });
34
+ return client;
35
+ }
36
+ sendToClient(clientId, message) {
37
+ const client = this.clients.get(clientId);
38
+ if (!client)
39
+ return false;
40
+ try {
41
+ let sseMessage = '';
42
+ if (message.event)
43
+ sseMessage += `event: ${message.event}\n`;
44
+ if (message.id)
45
+ sseMessage += `id: ${message.id}\n`;
46
+ if (message.retry)
47
+ sseMessage += `retry: ${message.retry}\n`;
48
+ const dataStr = typeof message.data === 'string' ? message.data : JSON.stringify(message.data);
49
+ dataStr.split('\n').forEach((line) => {
50
+ sseMessage += `data: ${line}\n`;
51
+ });
52
+ sseMessage += '\n';
53
+ client.response.write(sseMessage);
54
+ return true;
55
+ }
56
+ catch (error) {
57
+ console.error(`SSE send error to ${clientId}:`, error);
58
+ return false;
59
+ }
60
+ }
61
+ broadcast(message, excludeClientId) {
62
+ this.clients.forEach((_, clientId) => {
63
+ if (clientId !== excludeClientId) {
64
+ this.sendToClient(clientId, message);
65
+ }
66
+ });
67
+ }
68
+ getStats() {
69
+ return { clients: this.clients.size };
70
+ }
71
+ registerControllers(controllers) {
72
+ this.controllers = controllers.filter((c) => c.sse);
73
+ }
74
+ async triggerHandlers(eventType, event) {
75
+ for (const controller of this.controllers) {
76
+ if (controller.sse.handlers && controller.sse.handlers[eventType]) {
77
+ for (const handler of controller.sse.handlers[eventType]) {
78
+ console.log(handler);
79
+ await handler.fn(event).catch(console.log);
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ exports.SSEServer = SSEServer;
@@ -0,0 +1,17 @@
1
+ import { ISSEService, SSEClient, SSEMessage } from '../types/index.js';
2
+ import { ServerResponse } from 'http';
3
+ import { SSEServer } from './server';
4
+ export declare class SSEService implements ISSEService {
5
+ private static instance;
6
+ private sse;
7
+ private constructor();
8
+ static getInstance(): SSEService;
9
+ initialize(sse: SSEServer): void;
10
+ sendToClient(clientId: string, message: SSEMessage): boolean;
11
+ broadcast(message: SSEMessage, excludeClientId?: string): void;
12
+ getStats(): {
13
+ clients: number;
14
+ };
15
+ isAvailable(): boolean;
16
+ createConnection(res: ServerResponse): SSEClient;
17
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SSEService = void 0;
4
+ class SSEService {
5
+ static instance;
6
+ sse = null;
7
+ constructor() { }
8
+ static getInstance() {
9
+ if (!SSEService.instance) {
10
+ SSEService.instance = new SSEService();
11
+ }
12
+ return SSEService.instance;
13
+ }
14
+ initialize(sse) {
15
+ this.sse = sse;
16
+ }
17
+ sendToClient(clientId, message) {
18
+ if (!this.sse)
19
+ return false;
20
+ return this.sse.sendToClient(clientId, message);
21
+ }
22
+ broadcast(message, excludeClientId) {
23
+ if (!this.sse)
24
+ return;
25
+ this.sse.broadcast(message, excludeClientId);
26
+ }
27
+ getStats() {
28
+ if (!this.sse)
29
+ return { clients: 0 };
30
+ return this.sse.getStats();
31
+ }
32
+ isAvailable() {
33
+ return this.sse !== null;
34
+ }
35
+ createConnection(res) {
36
+ return this.sse.createConnection(res);
37
+ }
38
+ }
39
+ exports.SSEService = SSEService;
@@ -41,7 +41,7 @@ export interface IController {
41
41
  export type MiddlewareCB = (request: AppRequest, response: ServerResponse, next: (args?: any) => any) => void | Promise<AppRequest> | AppRequest;
42
42
  export type InterceptorCB = (data: any, req?: AppRequest, res?: ServerResponse) => Promise<unknown> | unknown;
43
43
  export type ErrorCB = (error: HttpError, req?: AppRequest, res?: ServerResponse) => Promise<ResponseWithStatus> | ResponseWithStatus;
44
- export type ParamDecoratorType = 'body' | 'params' | 'query' | 'request' | 'headers' | 'cookies' | 'response' | 'multipart' | 'event' | 'context';
44
+ export type ParamDecoratorType = 'body' | 'params' | 'query' | 'request' | 'headers' | 'cookies' | 'response' | 'multipart' | 'event' | 'context' | 'sse' | 'ws';
45
45
  export interface ParamMetadata {
46
46
  index: number;
47
47
  type: ParamDecoratorType;
@@ -1,21 +1,28 @@
1
- import { ErrorCB, HTTP_METHODS, InterceptorCB, MiddlewareCB } from './common';
1
+ import { ServerResponse } from 'http';
2
+ import { AppRequest, ErrorCB, HTTP_METHODS, InterceptorCB, MiddlewareCB } from './common';
2
3
  import { CORSConfig } from './cors';
3
4
  import { SanitizerConfig } from './sanitize';
4
5
  export type ControllerClass = {
5
6
  new (...args: any[]): any;
6
7
  };
7
- export type ControllerInstance = InstanceType<ControllerClass>;
8
8
  export type ControllerMethods = Array<{
9
9
  name: string;
10
10
  httpMethod: HTTP_METHODS;
11
11
  pattern: string;
12
12
  middlewares?: MiddlewareCB[];
13
13
  }>;
14
+ export type ControllerType = {
15
+ handleRequest?(request: AppRequest, response: ServerResponse): Promise<any>;
16
+ ws?: WsControllerHandlers;
17
+ sse?: SeeControllerHandlers;
18
+ new (...args: any[]): any;
19
+ };
20
+ export type ControllerInstance = InstanceType<ControllerType>;
14
21
  export type ControllerMetadata = {
15
22
  routePrefix: string;
16
23
  middlewares: MiddlewareCB[];
17
24
  interceptor?: InterceptorCB;
18
- subControllers: ControllerClass[];
25
+ subControllers: ControllerInstance[];
19
26
  errorHandler?: ErrorCB;
20
27
  cors?: CORSConfig;
21
28
  sanitizers: SanitizerConfig[];
@@ -23,7 +30,7 @@ export type ControllerMetadata = {
23
30
  export interface ControllerConfig {
24
31
  prefix: string;
25
32
  middlewares?: Array<MiddlewareCB>;
26
- controllers?: ControllerClass[];
33
+ controllers?: ControllerInstance[];
27
34
  interceptor?: InterceptorCB;
28
35
  }
29
36
  export type RouteContext = {
@@ -38,3 +45,32 @@ export type RouteContext = {
38
45
  subPath: string;
39
46
  sanitizersChain: SanitizerConfig[];
40
47
  };
48
+ export type SSE_HANDLER_META = {
49
+ type: string;
50
+ method: string;
51
+ };
52
+ export type HandlerMeta = {
53
+ type: 'connection';
54
+ topic: undefined;
55
+ method: 'onconnect';
56
+ fn: (...args: any[]) => any;
57
+ };
58
+ export type WsHandlerMeta = HandlerMeta & {
59
+ topic?: string;
60
+ };
61
+ export type WsControllerHandlers = {
62
+ handlers: {
63
+ connection: WsHandlerMeta[];
64
+ message: WsHandlerMeta[];
65
+ close: WsHandlerMeta[];
66
+ error: WsHandlerMeta[];
67
+ };
68
+ topics: HandlerMeta[];
69
+ };
70
+ export type SeeControllerHandlers = {
71
+ handlers: {
72
+ connection: HandlerMeta[];
73
+ close: HandlerMeta[];
74
+ error: HandlerMeta[];
75
+ };
76
+ };
@@ -15,4 +15,7 @@ export interface ServerConfig {
15
15
  path?: string;
16
16
  lazy?: boolean;
17
17
  };
18
+ sse?: {
19
+ enabled: boolean;
20
+ };
18
21
  }
@@ -5,4 +5,5 @@ export * from './http';
5
5
  export * from './lambda';
6
6
  export * from './multipart';
7
7
  export * from './sanitize';
8
+ export * from './sse';
8
9
  export * from './websocket';
@@ -21,4 +21,5 @@ __exportStar(require("./http"), exports);
21
21
  __exportStar(require("./lambda"), exports);
22
22
  __exportStar(require("./multipart"), exports);
23
23
  __exportStar(require("./sanitize"), exports);
24
+ __exportStar(require("./sse"), exports);
24
25
  __exportStar(require("./websocket"), exports);
@@ -0,0 +1,37 @@
1
+ import { ServerResponse } from 'http';
2
+ export interface SSEClient {
3
+ id: string;
4
+ response: ServerResponse;
5
+ topics: Set<string>;
6
+ data: Record<string, any>;
7
+ connectedAt: Date;
8
+ }
9
+ export interface SSEMessage {
10
+ event?: string;
11
+ id?: string;
12
+ retry?: number;
13
+ data: any;
14
+ }
15
+ export interface SSEEvent {
16
+ type: 'connection' | 'close';
17
+ client: SSEClient;
18
+ data?: any;
19
+ }
20
+ export interface ISSEServer {
21
+ createConnection(res: ServerResponse): SSEClient;
22
+ sendToClient(clientId: string, message: SSEMessage): boolean;
23
+ broadcast(message: SSEMessage, excludeClientId?: string): void;
24
+ getStats(): {
25
+ clients: number;
26
+ };
27
+ }
28
+ export interface ISSEService {
29
+ initialize(sse: ISSEServer): void;
30
+ sendToClient(clientId: string, message: SSEMessage): boolean;
31
+ broadcast(message: SSEMessage, excludeClientId?: string): void;
32
+ getStats(): {
33
+ clients: number;
34
+ };
35
+ isAvailable(): boolean;
36
+ createConnection(res: ServerResponse): SSEClient;
37
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -46,4 +46,5 @@ export interface IWebSocketServer {
46
46
  getStats(): WebSocketStats;
47
47
  subscribeToTopic(client: WebSocketClient, topic: string): void;
48
48
  unsubscribeFromTopic(client: WebSocketClient, topic: string): void;
49
+ registerControllers(controllers: any[]): void;
49
50
  }
@@ -21,7 +21,7 @@ export declare const getResponse: (data: {
21
21
  }) => Promise<{
22
22
  status: number;
23
23
  data: any;
24
- }>;
24
+ } | undefined>;
25
25
  export declare const applyMiddlewaresVsSanitizers: (request: AppRequest, response: ServerResponse, functions: {
26
26
  sanitizers: SanitizerConfig[][];
27
27
  middlewares: MiddlewareCB[][];
@@ -3,7 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.applyMiddlewaresVsSanitizers = exports.getResponse = exports.NextFN = exports.findRouteInController = exports.getAllMethods = exports.getControllerMethods = exports.executeControllerMethod = void 0;
4
4
  const _constants_1 = require("../constants.js");
5
5
  const _types_1 = require("../types/index.js");
6
- const WebsocketService_1 = require("../app/http/websocket/WebsocketService");
6
+ const service_1 = require("../sse/service");
7
+ const service_2 = require("../ws/service");
7
8
  const helper_1 = require("./helper");
8
9
  const multipart_1 = require("./multipart");
9
10
  const sanitize_1 = require("./sanitize");
@@ -41,19 +42,14 @@ const executeControllerMethod = async (controller, propertyName, request, respon
41
42
  }
42
43
  const prototype = Object.getPrototypeOf(controller);
43
44
  const paramMetadata = Reflect.getMetadata(_constants_1.PARAM_METADATA_KEY, prototype, propertyName) || [];
45
+ const sse = Reflect.getMetadata(_constants_1.SSE_METADATA_KEY, prototype, propertyName) || [];
44
46
  if (paramMetadata.length === 0) {
45
47
  return fn.call(controller, request, response);
46
48
  }
47
49
  const { body, multipart } = getBodyAndMultipart(request);
48
50
  const args = [];
49
- const wsParams = Reflect.getMetadata(_constants_1.WS_SERVICE_KEY, controller, propertyName) || [];
50
- const totalParams = Math.max(paramMetadata.length ? Math.max(...paramMetadata.map((p) => p.index)) + 1 : 0, wsParams.length ? Math.max(...wsParams.map((p) => p.index)) + 1 : 0);
51
+ const totalParams = Math.max(paramMetadata.length ? Math.max(...paramMetadata.map((p) => p.index)) + 1 : 0);
51
52
  for (let i = 0; i < totalParams; i++) {
52
- const wsParam = wsParams.find((p) => p.index === i);
53
- if (wsParam) {
54
- args[i] = WebsocketService_1.WebSocketService.getInstance();
55
- continue;
56
- }
57
53
  const param = paramMetadata.find((p) => p.index === i);
58
54
  if (!param) {
59
55
  args[i] = undefined;
@@ -65,6 +61,12 @@ const executeControllerMethod = async (controller, propertyName, request, respon
65
61
  if (param.type === 'multipart') {
66
62
  value = multipart;
67
63
  }
64
+ if (param.type === 'ws') {
65
+ value = service_2.WebSocketService.getInstance();
66
+ }
67
+ if (param.type === 'sse') {
68
+ value = service_1.SSEService.getInstance();
69
+ }
68
70
  if (param.type === 'request') {
69
71
  value = request;
70
72
  }
@@ -173,6 +175,9 @@ exports.NextFN = NextFN;
173
175
  const getResponse = async (data) => {
174
176
  try {
175
177
  let appResponse = await (0, exports.executeControllerMethod)(data.controllerInstance, data.name, data.request, data.response);
178
+ if (!appResponse) {
179
+ return;
180
+ }
176
181
  data.response.statusCode = appResponse.status ?? 200;
177
182
  const isError = !_constants_1.OK_STATUSES.includes(data.response.statusCode);
178
183
  const interceptors = data.interceptors.reverse();
@@ -30,4 +30,4 @@ export declare function Subscribe(topic: string): (target: any, propertyKey: str
30
30
  /**
31
31
  * Parameter decorator to inject WebSocket service instance.
32
32
  */
33
- export declare function InjectWS(): (target: any, propertyKey: string, parameterIndex: number) => void;
33
+ export declare function InjectWS(): (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
@@ -8,6 +8,7 @@ exports.OnError = OnError;
8
8
  exports.Subscribe = Subscribe;
9
9
  exports.InjectWS = InjectWS;
10
10
  const _constants_1 = require("../constants.js");
11
+ const _utils_1 = require("../utils/index.js");
11
12
  /**
12
13
  * Method decorator to handle WebSocket events.
13
14
  * @param type Type of WebSocket event (connection, message, close, error).
@@ -62,9 +63,5 @@ function Subscribe(topic) {
62
63
  * Parameter decorator to inject WebSocket service instance.
63
64
  */
64
65
  function InjectWS() {
65
- return function (target, propertyKey, parameterIndex) {
66
- const existingParams = Reflect.getMetadata(_constants_1.WS_SERVICE_KEY, target, propertyKey) || [];
67
- existingParams.push({ index: parameterIndex });
68
- Reflect.defineMetadata(_constants_1.WS_SERVICE_KEY, existingParams, target, propertyKey);
69
- };
66
+ return (0, _utils_1.createParamDecorator)('ws');
70
67
  }
@@ -1,2 +1,3 @@
1
1
  export { IWebSocketService, WebSocketClient, WebSocketEvent, WebSocketMessage, WebSocketStats, } from '../types/index.js';
2
2
  export * from './decorators';
3
+ export * from './service';
package/dist/ws/index.js CHANGED
@@ -15,3 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./decorators"), exports);
18
+ __exportStar(require("./service"), exports);
@@ -1,6 +1,6 @@
1
- import { WebSocketClient } from '../../../types/index.js';
1
+ import { ControllerType, IWebSocketServer, WebSocketClient } from '../types/index.js';
2
2
  import http from 'http';
3
- export declare class WebSocketServer {
3
+ export declare class WebSocketServer implements IWebSocketServer {
4
4
  private wss;
5
5
  private clients;
6
6
  private topics;
@@ -15,7 +15,7 @@ export declare class WebSocketServer {
15
15
  private handleClose;
16
16
  private handleError;
17
17
  private triggerHandlers;
18
- registerControllers(controllers: any[]): void;
18
+ registerControllers(controllers: ControllerType[]): void;
19
19
  subscribeToTopic(client: WebSocketClient, topic: string): void;
20
20
  unsubscribeFromTopic(client: WebSocketClient, topic: string): void;
21
21
  publishToTopic(topic: string, data: any, exclude?: string[]): void;
@@ -89,6 +89,7 @@ class WebSocketServer {
89
89
  });
90
90
  }
91
91
  catch (error) {
92
+ console.log(error);
92
93
  client.socket.send(JSON.stringify({
93
94
  type: 'error',
94
95
  data: { message: 'Invalid message format' },
@@ -120,7 +121,7 @@ class WebSocketServer {
120
121
  }
121
122
  async triggerHandlers(eventType, event, topic) {
122
123
  for (const controller of this.controllers) {
123
- const controllerHandlers = controller.handlers?.[eventType] ?? [];
124
+ const controllerHandlers = controller.ws?.handlers?.[eventType] ?? [];
124
125
  const matchingHandlers = controllerHandlers.filter((h) => {
125
126
  if (h.type !== eventType)
126
127
  return false;
@@ -137,7 +138,7 @@ class WebSocketServer {
137
138
  }
138
139
  }
139
140
  if (eventType === 'message' && topic) {
140
- const matchingSubs = controller.topics.filter((s) => s.topic === topic);
141
+ const matchingSubs = controller.ws?.topics.filter((s) => s.topic === topic) ?? [];
141
142
  for (const sub of matchingSubs) {
142
143
  try {
143
144
  await sub.fn(event);
@@ -150,12 +151,7 @@ class WebSocketServer {
150
151
  }
151
152
  }
152
153
  registerControllers(controllers) {
153
- this.controllers = controllers.map((controller) => {
154
- if (controller.getWebSocketController) {
155
- return controller.getWebSocketController();
156
- }
157
- return controller;
158
- });
154
+ this.controllers = controllers.filter((c) => !!c.ws);
159
155
  }
160
156
  subscribeToTopic(client, topic) {
161
157
  if (!this.topics.has(topic)) {
@@ -163,11 +159,7 @@ class WebSocketServer {
163
159
  }
164
160
  this.topics.get(topic).add(client.id);
165
161
  client.topics.add(topic);
166
- client.socket.send(JSON.stringify({
167
- type: 'subscribed',
168
- topic,
169
- data: { success: true },
170
- }));
162
+ client.socket.send(JSON.stringify({ type: 'subscribed', topic, data: { success: true } }));
171
163
  }
172
164
  unsubscribeFromTopic(client, topic) {
173
165
  const topicClients = this.topics.get(topic);
@@ -1,5 +1,5 @@
1
- import { IWebSocketService } from '../../../types/index.js';
2
- import { WebSocketServer } from './WebsocketServer';
1
+ import { IWebSocketService } from '../types/index.js';
2
+ import { WebSocketServer } from './server';
3
3
  export declare class WebSocketService implements IWebSocketService {
4
4
  private static instance;
5
5
  private wss;
@@ -1,4 +1,4 @@
1
- import { WebSocketServer } from './websocket/WebsocketServer';
1
+ import { WebSocketServer } from './server';
2
2
  export declare class Socket {
3
3
  protected wss: WebSocketServer;
4
4
  registerWebSocketControllers(controllers: any[]): this;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Socket = void 0;
4
- const WebsocketService_1 = require("./websocket/WebsocketService");
4
+ const service_1 = require("./service");
5
5
  class Socket {
6
6
  wss;
7
7
  registerWebSocketControllers(controllers) {
@@ -14,19 +14,19 @@ class Socket {
14
14
  return this;
15
15
  }
16
16
  sendToClient(clientId, message) {
17
- return WebsocketService_1.WebSocketService.getInstance().sendToClient(clientId, message);
17
+ return service_1.WebSocketService.getInstance().sendToClient(clientId, message);
18
18
  }
19
19
  publishToTopic(topic, data) {
20
- WebsocketService_1.WebSocketService.getInstance().publishToTopic(topic, data);
20
+ service_1.WebSocketService.getInstance().publishToTopic(topic, data);
21
21
  }
22
22
  broadcast(message, excludeClientId) {
23
- WebsocketService_1.WebSocketService.getInstance().broadcast(message, excludeClientId);
23
+ service_1.WebSocketService.getInstance().broadcast(message, excludeClientId);
24
24
  }
25
25
  getWebSocketStats() {
26
- return WebsocketService_1.WebSocketService.getInstance().getStats();
26
+ return service_1.WebSocketService.getInstance().getStats();
27
27
  }
28
28
  isWebSocketAvailable() {
29
- return WebsocketService_1.WebSocketService.getInstance().isAvailable();
29
+ return service_1.WebSocketService.getInstance().isAvailable();
30
30
  }
31
31
  }
32
32
  exports.Socket = Socket;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quantum-flow",
3
- "version": "1.8.1",
3
+ "version": "1.10.0",
4
4
  "description": "Decorator-based API framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -40,6 +40,11 @@
40
40
  "import": "./dist/ws/index.js",
41
41
  "require": "./dist/ws/index.js",
42
42
  "types": "./dist/ws/index.d.ts"
43
+ },
44
+ "./sse": {
45
+ "import": "./dist/sse/index.js",
46
+ "require": "./dist/sse/index.js",
47
+ "types": "./dist/sse/index.d.ts"
43
48
  }
44
49
  },
45
50
  "repository": {