quantum-flow 1.0.1

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 (102) hide show
  1. package/.prettierrc.json +9 -0
  2. package/README.md +37 -0
  3. package/dist/app/aws/index.d.ts +1 -0
  4. package/dist/app/aws/index.js +17 -0
  5. package/dist/app/aws/lambda.d.ts +13 -0
  6. package/dist/app/aws/lambda.js +241 -0
  7. package/dist/app/http/Application.d.ts +23 -0
  8. package/dist/app/http/Application.js +208 -0
  9. package/dist/app/http/Socket.d.ts +16 -0
  10. package/dist/app/http/Socket.js +32 -0
  11. package/dist/app/http/decorators.d.ts +7 -0
  12. package/dist/app/http/decorators.js +81 -0
  13. package/dist/app/http/index.d.ts +3 -0
  14. package/dist/app/http/index.js +19 -0
  15. package/dist/app/http/websocket/WebsocetService.d.ts +20 -0
  16. package/dist/app/http/websocket/WebsocetService.js +41 -0
  17. package/dist/app/http/websocket/WebsocketServer.d.ts +30 -0
  18. package/dist/app/http/websocket/WebsocketServer.js +221 -0
  19. package/dist/constants.d.ts +16 -0
  20. package/dist/constants.js +24 -0
  21. package/dist/core/Controller.d.ts +43 -0
  22. package/dist/core/Controller.js +159 -0
  23. package/dist/core/Endpoint.d.ts +8 -0
  24. package/dist/core/Endpoint.js +43 -0
  25. package/dist/core/index.d.ts +4 -0
  26. package/dist/core/index.js +19 -0
  27. package/dist/core/utils/extractors.d.ts +15 -0
  28. package/dist/core/utils/extractors.js +29 -0
  29. package/dist/core/utils/helpers.d.ts +4 -0
  30. package/dist/core/utils/helpers.js +22 -0
  31. package/dist/core/utils/index.d.ts +3 -0
  32. package/dist/core/utils/index.js +19 -0
  33. package/dist/core/utils/websocket.d.ts +8 -0
  34. package/dist/core/utils/websocket.js +45 -0
  35. package/dist/types/common.d.ts +47 -0
  36. package/dist/types/common.js +2 -0
  37. package/dist/types/controller.d.ts +4 -0
  38. package/dist/types/controller.js +2 -0
  39. package/dist/types/http.d.ts +18 -0
  40. package/dist/types/http.js +2 -0
  41. package/dist/types/index.d.ts +5 -0
  42. package/dist/types/index.js +21 -0
  43. package/dist/types/lambda.d.ts +26 -0
  44. package/dist/types/lambda.js +2 -0
  45. package/dist/types/websocket.d.ts +55 -0
  46. package/dist/types/websocket.js +2 -0
  47. package/dist/utils/controller.d.ts +9 -0
  48. package/dist/utils/controller.js +111 -0
  49. package/dist/utils/helper.d.ts +1 -0
  50. package/dist/utils/helper.js +24 -0
  51. package/dist/utils/index.d.ts +7 -0
  52. package/dist/utils/index.js +23 -0
  53. package/dist/utils/multipart.d.ts +15 -0
  54. package/dist/utils/multipart.js +109 -0
  55. package/dist/utils/parsers.d.ts +4 -0
  56. package/dist/utils/parsers.js +76 -0
  57. package/dist/utils/server.d.ts +4 -0
  58. package/dist/utils/server.js +46 -0
  59. package/dist/utils/transform.d.ts +1 -0
  60. package/dist/utils/transform.js +23 -0
  61. package/dist/utils/validate.d.ts +1 -0
  62. package/dist/utils/validate.js +46 -0
  63. package/dist/validators/Validate.d.ts +3 -0
  64. package/dist/validators/Validate.js +40 -0
  65. package/dist/validators/index.d.ts +1 -0
  66. package/dist/validators/index.js +17 -0
  67. package/eslint.config.mjs +84 -0
  68. package/nodemon.json +5 -0
  69. package/package.json +70 -0
  70. package/src/app/aws/index.ts +1 -0
  71. package/src/app/aws/lambda.ts +283 -0
  72. package/src/app/http/Application.ts +250 -0
  73. package/src/app/http/Socket.ts +38 -0
  74. package/src/app/http/decorators.ts +115 -0
  75. package/src/app/http/index.ts +3 -0
  76. package/src/app/http/websocket/WebsocetService.ts +44 -0
  77. package/src/app/http/websocket/WebsocketServer.ts +262 -0
  78. package/src/constants.ts +25 -0
  79. package/src/core/Controller.ts +229 -0
  80. package/src/core/Endpoint.ts +39 -0
  81. package/src/core/index.ts +14 -0
  82. package/src/core/utils/extractors.ts +32 -0
  83. package/src/core/utils/helpers.ts +22 -0
  84. package/src/core/utils/index.ts +3 -0
  85. package/src/core/utils/websocket.ts +45 -0
  86. package/src/types/common.ts +60 -0
  87. package/src/types/controller.ts +2 -0
  88. package/src/types/http.ts +19 -0
  89. package/src/types/index.ts +5 -0
  90. package/src/types/lambda.ts +28 -0
  91. package/src/types/websocket.ts +57 -0
  92. package/src/utils/controller.ts +143 -0
  93. package/src/utils/helper.ts +24 -0
  94. package/src/utils/index.ts +7 -0
  95. package/src/utils/multipart.ts +93 -0
  96. package/src/utils/parsers.ts +87 -0
  97. package/src/utils/server.ts +49 -0
  98. package/src/utils/transform.ts +24 -0
  99. package/src/utils/validate.ts +53 -0
  100. package/src/validators/Validate.ts +48 -0
  101. package/src/validators/index.ts +1 -0
  102. package/tsconfig.json +51 -0
@@ -0,0 +1,283 @@
1
+ import { OK_STATUSES } from '@constants';
2
+ import { ParseBody } from '@utils';
3
+ import {
4
+ APIGatewayProxyEvent,
5
+ APIGatewayProxyEventHeaders,
6
+ APIGatewayProxyEventPathParameters,
7
+ APIGatewayProxyResult,
8
+ Context,
9
+ Handler,
10
+ } from 'aws-lambda';
11
+
12
+ import { LambdaRequest, LambdaResponse } from '@types';
13
+
14
+ export class LambdaAdapter {
15
+ private static getHeaderValue(headers: any, headerName: string): string | undefined {
16
+ const value = headers?.[headerName] || headers?.[headerName.toLowerCase()];
17
+
18
+ if (!value) return undefined;
19
+
20
+ if (Array.isArray(value)) {
21
+ return value[0];
22
+ }
23
+
24
+ return value;
25
+ }
26
+ static toRequest(event: APIGatewayProxyEvent, context: Context): LambdaRequest {
27
+ const query: Record<string, string | string[]> = {};
28
+ if (event.queryStringParameters) {
29
+ Object.entries(event.queryStringParameters).forEach(([key, value]) => {
30
+ if (event.multiValueQueryStringParameters?.[key]) {
31
+ query[key] = event.multiValueQueryStringParameters[key];
32
+ } else {
33
+ query[key] = value || '';
34
+ }
35
+ });
36
+ }
37
+
38
+ const cookies: Record<string, string> = {};
39
+ const cookieHeader = event.headers?.Cookie || event.headers?.cookie;
40
+ if (cookieHeader) {
41
+ cookieHeader.split(';').forEach((cookie) => {
42
+ const [name, value] = cookie.trim().split('=');
43
+ if (name && value) {
44
+ cookies[name] = decodeURIComponent(value);
45
+ }
46
+ });
47
+ }
48
+
49
+ let body = ParseBody(event);
50
+ const protocol = event.headers?.['x-forwarded-proto'] || 'http';
51
+ const host = event.headers?.host || 'localhost';
52
+
53
+ const cleanPath = event.path.split('?')[0];
54
+
55
+ const fullUrl = `${protocol}://${host}${cleanPath.startsWith('/') ? '' : '/'}${cleanPath}`;
56
+
57
+ let url: URL;
58
+ try {
59
+ url = new URL(fullUrl);
60
+
61
+ if (event.queryStringParameters) {
62
+ Object.entries(event.queryStringParameters).forEach(([key, value]) => {
63
+ if (value) url.searchParams.append(key, value);
64
+ });
65
+ }
66
+ } catch (error) {
67
+ console.error('❌ Failed to create URL:', fullUrl, error);
68
+ url = new URL('http://localhost/');
69
+ }
70
+
71
+ return {
72
+ method: event.httpMethod,
73
+ path: cleanPath,
74
+ url,
75
+ headers: this.safeHeaders(event.headers),
76
+ query,
77
+ body,
78
+ params: this.safeParams(event.pathParameters),
79
+ cookies,
80
+ raw: event,
81
+ context,
82
+ isBase64Encoded: event.isBase64Encoded || false,
83
+ requestId: context.awsRequestId,
84
+ stage: event.requestContext?.stage || '$default',
85
+ sourceIp: this.getSourceIp(event),
86
+ userAgent: this.getUserAgent(event),
87
+ };
88
+ }
89
+
90
+ static createResponseBody(response: any) {
91
+ let body = response;
92
+ if (response && typeof response === 'object') {
93
+ if ('data' in response) {
94
+ body = {
95
+ data: response.data,
96
+ timestamp: new Date().toISOString(),
97
+ };
98
+ } else if (response.body) {
99
+ return response as LambdaResponse;
100
+ } else {
101
+ body = {
102
+ data: response,
103
+ timestamp: new Date().toISOString(),
104
+ };
105
+ }
106
+ }
107
+
108
+ return body;
109
+ }
110
+
111
+ static toLambdaResponse(response: any, request?: LambdaRequest): LambdaResponse {
112
+ let statusCode = response.status ?? 200;
113
+
114
+ let body: any = this.createResponseBody(response);
115
+ let headers: Record<string, string> = {
116
+ 'Content-Type': 'application/json',
117
+ 'X-Request-Id': request?.requestId || 'unknown',
118
+ 'X-Powered-By': 'Lambda Decorators',
119
+ };
120
+
121
+ const cookies: string[] = [];
122
+
123
+ if (response && typeof response === 'object') {
124
+ if ('data' in response) {
125
+ body = {
126
+ success: OK_STATUSES.includes(statusCode),
127
+ data: response.data,
128
+ timestamp: new Date().toISOString(),
129
+ requestId: request?.requestId,
130
+ };
131
+ } else if (response.body) {
132
+ return response as LambdaResponse;
133
+ } else {
134
+ body = {
135
+ success: OK_STATUSES.includes(statusCode),
136
+ data: response,
137
+ timestamp: new Date().toISOString(),
138
+ requestId: request?.requestId,
139
+ };
140
+ }
141
+ }
142
+ let originHeader = LambdaAdapter.getHeaderValue(request?.headers, 'origin');
143
+
144
+ if (originHeader) {
145
+ if (Array.isArray(originHeader)) {
146
+ origin = originHeader[0];
147
+ } else {
148
+ origin = originHeader;
149
+ }
150
+ }
151
+
152
+ if (request?.cookies && Object.keys(request.cookies).length > 0) {
153
+ Object.entries(request.cookies).forEach(([name, value]) => {
154
+ cookies.push(`${name}=${encodeURIComponent(value)}; Path=/; HttpOnly`);
155
+ });
156
+ }
157
+
158
+ const lambdaResponse: LambdaResponse = {
159
+ statusCode,
160
+ headers,
161
+ body: JSON.stringify(body),
162
+ isBase64Encoded: false,
163
+ };
164
+
165
+ if (cookies.length > 0) {
166
+ lambdaResponse.cookies = cookies;
167
+ }
168
+
169
+ if (cookies.length > 0) {
170
+ lambdaResponse.multiValueHeaders = {
171
+ 'Set-Cookie': cookies,
172
+ };
173
+ }
174
+
175
+ return lambdaResponse;
176
+ }
177
+
178
+ static createHandler(Contoller: any) {
179
+ const handler: Handler<APIGatewayProxyEvent, APIGatewayProxyResult> = async (
180
+ event,
181
+ context,
182
+ ) => {
183
+ const instance = new Contoller();
184
+
185
+ try {
186
+ const request = LambdaAdapter.toRequest(event, context);
187
+
188
+ if (typeof instance.handleRequest === 'function') {
189
+ const response = await instance.handleRequest(request);
190
+
191
+ return LambdaAdapter.toLambdaResponse(response, request);
192
+ } else {
193
+ throw new Error('Controller must have handleRequest method');
194
+ }
195
+ } catch (error: any) {
196
+ console.error('❌ Lambda error:', error);
197
+
198
+ const errorResponse: any = {
199
+ statusCode: error.status || 500,
200
+ headers: {
201
+ 'Content-Type': 'application/json',
202
+ 'X-Request-Id': context.awsRequestId,
203
+ 'Access-Control-Allow-Origin': event.headers?.origin || event.headers?.Origin || '*',
204
+ 'Access-Control-Allow-Credentials': 'true',
205
+ },
206
+ body: JSON.stringify({
207
+ success: false,
208
+ message: error.message || 'Internal Server Error',
209
+ requestId: context.awsRequestId,
210
+ }),
211
+ };
212
+
213
+ if (error.cookies) {
214
+ errorResponse.cookies = error.cookies;
215
+ }
216
+
217
+ return errorResponse;
218
+ }
219
+ };
220
+
221
+ return handler;
222
+ }
223
+
224
+ private static safeHeaders(
225
+ headers: APIGatewayProxyEventHeaders,
226
+ ): Record<string, string | string[]> {
227
+ const result: Record<string, string | string[]> = {};
228
+
229
+ if (!headers) return result;
230
+
231
+ Object.entries(headers).forEach(([key, value]) => {
232
+ if (value !== undefined) {
233
+ result[key] = value;
234
+ }
235
+ });
236
+
237
+ return result;
238
+ }
239
+
240
+ private static safeParams(
241
+ params: APIGatewayProxyEventPathParameters | null,
242
+ ): Record<string, string> {
243
+ const result: Record<string, string> = {};
244
+
245
+ if (!params) return result;
246
+
247
+ Object.entries(params).forEach(([key, value]) => {
248
+ if (value !== undefined) {
249
+ result[key] = value;
250
+ }
251
+ });
252
+
253
+ return result;
254
+ }
255
+
256
+ private static getSourceIp(event: APIGatewayProxyEvent): string {
257
+ if (event.requestContext?.identity?.sourceIp) {
258
+ return event.requestContext.identity.sourceIp;
259
+ }
260
+
261
+ const forwardedFor: any = event.headers?.['x-forwarded-for'];
262
+ if (forwardedFor) {
263
+ if (typeof forwardedFor === 'string') {
264
+ return forwardedFor.split(',')[0].trim();
265
+ }
266
+ if (Array.isArray(forwardedFor) && forwardedFor.length > 0) {
267
+ return forwardedFor[0].split(',')[0].trim();
268
+ }
269
+ }
270
+
271
+ return '0.0.0.0';
272
+ }
273
+
274
+ private static getUserAgent(event: APIGatewayProxyEvent): string {
275
+ const ua: any = event.headers?.['user-agent'];
276
+ if (!ua) return 'unknown';
277
+
278
+ if (typeof ua === 'string') return ua;
279
+ if (Array.isArray(ua) && ua.length > 0) return ua[0];
280
+
281
+ return 'unknown';
282
+ }
283
+ }
@@ -0,0 +1,250 @@
1
+ import { STOPPED } from '@constants';
2
+ import { ServerConfig } from '@types';
3
+ import { collectRawBody, ParseBody, ParseCookies, ParseQuery, resolveConfig } from '@utils';
4
+ import http, { ServerResponse } from 'http';
5
+ import { Socket } from './Socket';
6
+ import { WebSocketService } from './websocket/WebsocetService';
7
+ import { WebSocketServer } from './websocket/WebsocketServer';
8
+
9
+ export class HttpServer extends Socket {
10
+ private app: http.Server;
11
+ private config: ServerConfig;
12
+ private isRunning: boolean = false;
13
+
14
+ constructor(configOrClass: new (...args: any[]) => any) {
15
+ super();
16
+ this.config = resolveConfig(configOrClass);
17
+
18
+ const app = http.createServer(this.requestHandler.bind(this));
19
+
20
+ if (this.config.websocket?.enabled) {
21
+ this.wss = new WebSocketServer(app, {
22
+ path: this.config.websocket.path || '/',
23
+ });
24
+ WebSocketService.getInstance().initialize(this.wss);
25
+ }
26
+
27
+ this.app = app;
28
+
29
+ this.logConfig();
30
+ }
31
+
32
+ private logConfig() {
33
+ console.log(`
34
+ ╔════════════════════════════════════════╗
35
+ ║ 🚀 Server Configuration
36
+ ╠════════════════════════════════════════╣
37
+ ║ 📍 Host: ${this.config.host}
38
+ ║ 🔌 Port: ${this.config.port}
39
+ ║ 🔌 Websocket: ${!!this.config.websocket}
40
+ ║ 🔧 Middlewares: ${this.config.globalMiddlewares?.length || 0}
41
+ ║ 🎯 Interceptors: ${this.config.globalInterceptors?.length || 0}
42
+ ║ 📦 Controllers: ${this.config.controllers?.length || 0}
43
+ ╚════════════════════════════════════════╝
44
+ `);
45
+ }
46
+
47
+ public async listen(port?: number, host?: string): Promise<http.Server> {
48
+ if (this.isRunning) {
49
+ console.log('⚠️ Server is already running');
50
+ return this.app;
51
+ }
52
+
53
+ const listenPort = port || this.config.port || 3000;
54
+ const listenHost = host || this.config.host || 'localhost';
55
+
56
+ return new Promise((resolve, reject) => {
57
+ try {
58
+ this.app.listen(listenPort, listenHost, () => {
59
+ this.isRunning = true;
60
+ console.log(`
61
+ ╔════════════════════════════════════════╗
62
+ ║ 🎉 Server started successfully!
63
+ ║ 📍 http://${listenHost}:${listenPort}
64
+ ║ 📊 Status: RUNNING
65
+ ╚════════════════════════════════════════╝
66
+ `);
67
+ resolve(this.app);
68
+ });
69
+
70
+ this.app.on('error', (error) => {
71
+ console.error('❌ Server error:', error);
72
+ reject(error);
73
+ });
74
+ } catch (error) {
75
+ reject(error);
76
+ }
77
+ });
78
+ }
79
+
80
+ public async close(): Promise<void> {
81
+ return new Promise((resolve, reject) => {
82
+ if (!this.isRunning) {
83
+ resolve();
84
+ return;
85
+ }
86
+
87
+ this.app.close((err) => {
88
+ if (err) {
89
+ reject(err);
90
+ } else {
91
+ this.isRunning = false;
92
+ console.log(STOPPED);
93
+ resolve();
94
+ }
95
+ });
96
+ });
97
+ }
98
+
99
+ public status(): { running: boolean; config: ServerConfig } {
100
+ return {
101
+ running: this.isRunning,
102
+ config: this.config,
103
+ };
104
+ }
105
+
106
+ private async requestHandler(req: http.IncomingMessage, res: ServerResponse) {
107
+ const startTime = Date.now();
108
+
109
+ try {
110
+ const request = await this.createRequest(req);
111
+
112
+ let processedRequest = await this.applyMiddlewares(request, res);
113
+ const data = await this.findController(processedRequest, res);
114
+
115
+ const finalResponse = await this.applyInterceptors(data, request, res);
116
+
117
+ await this.sendResponse(res, finalResponse, startTime);
118
+ } catch (error) {
119
+ await this.handleError(error, req, res, startTime);
120
+ }
121
+ }
122
+
123
+ private async createRequest(req: http.IncomingMessage): Promise<any> {
124
+ const rawBody = await collectRawBody(req);
125
+
126
+ const parseRequest = {
127
+ body: rawBody,
128
+ headers: req.headers,
129
+ isBase64Encoded: false,
130
+ };
131
+
132
+ const parsedBody = ParseBody(parseRequest);
133
+
134
+ const protocol = req.headers['x-forwarded-proto'] || 'http';
135
+ const host = req.headers.host || 'localhost';
136
+ const fullUrl = `${protocol}://${host}${req.url}`;
137
+
138
+ const whatwgUrl = new URL(fullUrl);
139
+
140
+ return {
141
+ method: req.method,
142
+ url: whatwgUrl,
143
+ path: whatwgUrl.pathname,
144
+ headers: req.headers,
145
+ body: parsedBody,
146
+ rawBody: rawBody,
147
+ query: ParseQuery(whatwgUrl),
148
+ params: {},
149
+ cookies: ParseCookies(req),
150
+ isBase64Encoded: false,
151
+ _startTime: Date.now(),
152
+ };
153
+ }
154
+
155
+ private async applyMiddlewares(request: any, res: http.ServerResponse): Promise<any> {
156
+ let processed = request;
157
+
158
+ for (const middleware of this.config.globalMiddlewares || []) {
159
+ const result = await middleware(processed, res);
160
+ if (result) {
161
+ processed = { ...processed, ...result };
162
+ }
163
+ }
164
+
165
+ return processed;
166
+ }
167
+
168
+ private async findController(request: any, response?: ServerResponse): Promise<any> {
169
+ for (const ControllerClass of this.config.controllers || []) {
170
+ const instance = new ControllerClass();
171
+ if (typeof instance.handleRequest === 'function') {
172
+ const data = await instance.handleRequest(request, response);
173
+ if (data && data.status !== 404) {
174
+ return data;
175
+ }
176
+ }
177
+ }
178
+
179
+ return {
180
+ status: 404,
181
+ data: { message: `Route ${request.method} ${request.path} not found` },
182
+ };
183
+ }
184
+
185
+ private async applyInterceptors(
186
+ data: any,
187
+ request: Request,
188
+ response: ServerResponse,
189
+ ): Promise<any> {
190
+ let processed = data;
191
+
192
+ for (const interceptor of this.config.globalInterceptors || []) {
193
+ processed = await interceptor(processed, request, response);
194
+ }
195
+
196
+ return processed;
197
+ }
198
+
199
+ private async sendResponse(
200
+ res: http.ServerResponse,
201
+ data: any,
202
+ startTime: number,
203
+ ): Promise<void> {
204
+ const resp = data?.data !== undefined ? data.data : data;
205
+ if (!res.headersSent) {
206
+ if (!res.getHeader('Content-Type')) {
207
+ res.setHeader('Content-Type', 'application/json');
208
+ }
209
+
210
+ if (data?.headers) {
211
+ Object.entries(data.headers).forEach(([key, value]) => {
212
+ if (!res.getHeader(key)) {
213
+ res.setHeader(key, value as string);
214
+ }
215
+ });
216
+ }
217
+ }
218
+ res.setHeader('X-Response-Time', `${Date.now() - startTime}ms`);
219
+ res.statusCode = data.status ?? 200;
220
+
221
+ res.end(JSON.stringify(resp));
222
+ }
223
+
224
+ private async handleError(
225
+ error: any,
226
+ req: http.IncomingMessage,
227
+ res: http.ServerResponse,
228
+ startTime: number,
229
+ ): Promise<void> {
230
+ let errorResponse = {
231
+ status: error.status || 500,
232
+ data: {
233
+ message: error.message || 'Internal Server Error',
234
+ errors: error.errors || [],
235
+ },
236
+ };
237
+
238
+ if (!this.config.globalErrorHandler) {
239
+ return this.sendResponse(res, errorResponse, startTime);
240
+ }
241
+
242
+ try {
243
+ const intercepted = await this.config.globalErrorHandler(error, req, res);
244
+ errorResponse = { ...errorResponse, ...intercepted };
245
+ } catch (cathed) {
246
+ Object.assign(errorResponse, cathed);
247
+ }
248
+ return this.sendResponse(res, errorResponse, startTime);
249
+ }
250
+ }
@@ -0,0 +1,38 @@
1
+ import { WebSocketService } from './websocket/WebsocetService';
2
+ import { WebSocketServer } from './websocket/WebsocketServer';
3
+
4
+ export class Socket {
5
+ protected wss: WebSocketServer;
6
+
7
+ public registerWebSocketControllers(controllers: any[]) {
8
+ if (!this.wss) {
9
+ console.warn(
10
+ '⚠️ WebSocket is disabled. Enable it in config: { websocket: { enabled: true } }',
11
+ );
12
+ return this;
13
+ }
14
+ this.wss.registerControllers(controllers);
15
+ console.log(`📝 Registered ${controllers.length} WebSocket controllers`);
16
+ return this;
17
+ }
18
+
19
+ public sendToClient(clientId: string, message: any): boolean {
20
+ return WebSocketService.getInstance().sendToClient(clientId, message);
21
+ }
22
+
23
+ public publishToTopic(topic: string, data: any) {
24
+ WebSocketService.getInstance().publishToTopic(topic, data);
25
+ }
26
+
27
+ public broadcast(message: any, excludeClientId?: string) {
28
+ WebSocketService.getInstance().broadcast(message, excludeClientId);
29
+ }
30
+
31
+ public getWebSocketStats() {
32
+ return WebSocketService.getInstance().getStats();
33
+ }
34
+
35
+ public isWebSocketAvailable(): boolean {
36
+ return WebSocketService.getInstance().isAvailable();
37
+ }
38
+ }
@@ -0,0 +1,115 @@
1
+ import { SERVER_CONFIG_KEY, SERVER_MODULES_KEY } from '@constants';
2
+
3
+ import { Conf, Interceptor } from '@types';
4
+
5
+ export function Server(config: Conf = {}) {
6
+ return function (target: any) {
7
+ const existingConfig = Reflect.getMetadata(SERVER_CONFIG_KEY, target) || {};
8
+
9
+ const mergedConfig = {
10
+ ...existingConfig,
11
+ ...config,
12
+ controllers: [...(existingConfig.controllers || []), ...(config.controllers || [])],
13
+ globalMiddlewares: existingConfig.globalMiddlewares || config.globalMiddlewares,
14
+ globalInterceptors: existingConfig.globalInterceptors || config.globalInterceptors || [],
15
+ };
16
+
17
+ Reflect.defineMetadata(SERVER_CONFIG_KEY, mergedConfig, target);
18
+
19
+ if (config.controllers) {
20
+ Reflect.defineMetadata(SERVER_MODULES_KEY, config.controllers, target);
21
+ }
22
+
23
+ return target;
24
+ };
25
+ }
26
+
27
+ export function Use(middleware: any) {
28
+ return function (target: any) {
29
+ const existingConfig = Reflect.getMetadata(SERVER_CONFIG_KEY, target) || {};
30
+ const middlewares = existingConfig.globalMiddlewares || [];
31
+
32
+ middlewares.push(middleware);
33
+ console.log(middlewares);
34
+ Reflect.defineMetadata(
35
+ SERVER_CONFIG_KEY,
36
+ {
37
+ ...existingConfig,
38
+ globalMiddlewares: middlewares,
39
+ },
40
+ target,
41
+ );
42
+
43
+ return target;
44
+ };
45
+ }
46
+
47
+ export function Intercept(interceptor: Interceptor) {
48
+ return function (target: any) {
49
+ const existingConfig = Reflect.getMetadata(SERVER_CONFIG_KEY, target) || {};
50
+ const interceptors = existingConfig.globalInterceptors || [];
51
+
52
+ interceptors.push(interceptor);
53
+
54
+ Reflect.defineMetadata(
55
+ SERVER_CONFIG_KEY,
56
+ {
57
+ ...existingConfig,
58
+ globalInterceptors: interceptors,
59
+ },
60
+ target,
61
+ );
62
+
63
+ return target;
64
+ };
65
+ }
66
+
67
+ export function Catch(handler: any) {
68
+ return function (target: any) {
69
+ const existingConfig = Reflect.getMetadata(SERVER_CONFIG_KEY, target) || {};
70
+
71
+ Reflect.defineMetadata(
72
+ SERVER_CONFIG_KEY,
73
+ {
74
+ ...existingConfig,
75
+ globalErrorHandler: handler,
76
+ },
77
+ target,
78
+ );
79
+
80
+ return target;
81
+ };
82
+ }
83
+
84
+ export function Port(port: number) {
85
+ return function (target: any) {
86
+ const existingConfig = Reflect.getMetadata(SERVER_CONFIG_KEY, target) || {};
87
+
88
+ Reflect.defineMetadata(
89
+ SERVER_CONFIG_KEY,
90
+ {
91
+ ...existingConfig,
92
+ port,
93
+ },
94
+ target,
95
+ );
96
+
97
+ return target;
98
+ };
99
+ }
100
+ export function Host(host: string) {
101
+ return function (target: any) {
102
+ const existingConfig = Reflect.getMetadata(SERVER_CONFIG_KEY, target) || {};
103
+
104
+ Reflect.defineMetadata(
105
+ SERVER_CONFIG_KEY,
106
+ {
107
+ ...existingConfig,
108
+ host,
109
+ },
110
+ target,
111
+ );
112
+
113
+ return target;
114
+ };
115
+ }
@@ -0,0 +1,3 @@
1
+ export * from './Application';
2
+ export * from './decorators';
3
+ export * from './websocket/WebsocketServer';