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.
- package/README.md +116 -51
- package/dist/app/http/Application.d.ts +3 -2
- package/dist/app/http/Application.js +27 -19
- package/dist/app/http/index.d.ts +0 -1
- package/dist/app/http/index.js +0 -1
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +4 -1
- package/dist/core/Controller.d.ts +12 -8
- package/dist/core/Controller.js +41 -12
- package/dist/core/{utils/extractors.js → decorators.js} +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +1 -1
- package/dist/sse/decorators.d.ts +6 -0
- package/dist/sse/decorators.js +29 -0
- package/dist/sse/index.d.ts +2 -0
- package/dist/sse/index.js +8 -0
- package/dist/sse/server.d.ts +14 -0
- package/dist/sse/server.js +85 -0
- package/dist/sse/service.d.ts +17 -0
- package/dist/sse/service.js +39 -0
- package/dist/types/common.d.ts +1 -1
- package/dist/types/controller.d.ts +40 -4
- package/dist/types/http.d.ts +3 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/sse.d.ts +37 -0
- package/dist/types/sse.js +2 -0
- package/dist/types/websocket.d.ts +1 -6
- package/dist/utils/controller.d.ts +1 -1
- package/dist/utils/controller.js +13 -8
- package/dist/{core/utils/websocket.d.ts → ws/decorators.d.ts} +2 -2
- package/dist/{core/utils/websocket.js → ws/decorators.js} +3 -6
- package/dist/ws/index.d.ts +3 -0
- package/dist/{examples/controllers → ws}/index.js +2 -2
- package/dist/{app/http/websocket/WebsocketServer.d.ts → ws/server.d.ts} +3 -3
- package/dist/{app/http/websocket/WebsocketServer.js → ws/server.js} +5 -13
- package/dist/{app/http/websocket/WebsocketService.d.ts → ws/service.d.ts} +2 -2
- package/dist/{app/http/Socket.d.ts → ws/socket.d.ts} +1 -1
- package/dist/{app/http/Socket.js → ws/socket.js} +6 -6
- package/package.json +12 -2
- package/dist/core/utils/index.d.ts +0 -2
- package/dist/core/utils/index.js +0 -18
- package/dist/examples/app.d.ts +0 -4
- package/dist/examples/app.js +0 -48
- package/dist/examples/controllers/index.d.ts +0 -2
- package/dist/examples/controllers/socket.d.ts +0 -7
- package/dist/examples/controllers/socket.js +0 -62
- package/dist/examples/controllers/user.d.ts +0 -15
- package/dist/examples/controllers/user.js +0 -107
- package/dist/examples/controllers/userMetadata.d.ts +0 -8
- package/dist/examples/controllers/userMetadata.js +0 -103
- package/dist/examples/lambda.d.ts +0 -1
- package/dist/examples/lambda.js +0 -6
- package/dist/examples/mock/context.d.ts +0 -14
- package/dist/examples/mock/context.js +0 -17
- package/dist/examples/server.d.ts +0 -1
- package/dist/examples/server.js +0 -6
- /package/dist/core/{utils/extractors.d.ts → decorators.d.ts} +0 -0
- /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
|
|
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
|
-
#
|
|
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
|
-
|
|
252
|
+
## Defining SSE Controllers
|
|
248
253
|
|
|
249
|
-
|
|
250
|
-
|
|
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
|
-
@
|
|
254
|
-
|
|
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
|
-
|
|
270
|
+
## Injecting SSE Service
|
|
258
271
|
|
|
259
|
-
|
|
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
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
class
|
|
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
|
-
|
|
295
|
+
## SSE Event Decorators
|
|
296
|
+
|
|
297
|
+
The framework provides decorators to handle SSE connection lifecycle events:
|
|
269
298
|
|
|
270
|
-
|
|
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
|
-
|
|
274
|
-
|
|
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
|
-
|
|
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
|
-
|
|
334
|
+
Example:
|
|
280
335
|
|
|
281
336
|
```typescript
|
|
282
|
-
|
|
283
|
-
|
|
337
|
+
sse.sendToClient(clientId, {
|
|
338
|
+
event: 'eventName',
|
|
339
|
+
data: { key: 'value' },
|
|
340
|
+
});
|
|
284
341
|
```
|
|
285
342
|
|
|
286
|
-
|
|
343
|
+
## Enabling SSE Support in Server
|
|
287
344
|
|
|
288
|
-
|
|
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 {
|
|
292
|
-
|
|
293
|
-
@IsEmail()
|
|
294
|
-
email: string;
|
|
350
|
+
import { Server, HttpServer } from 'quantum-flow/http';
|
|
351
|
+
import { User, UserMetadata } from './controllers';
|
|
295
352
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
353
|
+
@Server({
|
|
354
|
+
controllers: [User, UserMetadata],
|
|
355
|
+
sse: { enabled: true },
|
|
356
|
+
})
|
|
357
|
+
class App {}
|
|
299
358
|
|
|
300
|
-
|
|
301
|
-
|
|
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
|
-
|
|
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
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
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.
|
|
23
|
-
this.
|
|
24
|
-
|
|
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 (
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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;
|
package/dist/app/http/index.d.ts
CHANGED
package/dist/app/http/index.js
CHANGED
|
@@ -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);
|
package/dist/constants.d.ts
CHANGED
|
@@ -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
|
-
|
|
34
|
+
lookupWS(): void;
|
|
35
|
+
lookupSSE(): void;
|
|
36
|
+
getSSEController(): {
|
|
33
37
|
instance: /*elided*/ any;
|
|
34
38
|
handlers: {
|
|
35
|
-
connection: any;
|
|
36
|
-
|
|
37
|
-
|
|
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;
|
package/dist/core/Controller.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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("
|
|
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.
|
package/dist/core/index.d.ts
CHANGED
|
@@ -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';
|
package/dist/core/index.js
CHANGED
|
@@ -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,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
|
+
}
|