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,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Server = Server;
4
+ exports.Use = Use;
5
+ exports.Intercept = Intercept;
6
+ exports.Catch = Catch;
7
+ exports.Port = Port;
8
+ exports.Host = Host;
9
+ const _constants_1 = require("@constants");
10
+ function Server(config = {}) {
11
+ return function (target) {
12
+ const existingConfig = Reflect.getMetadata(_constants_1.SERVER_CONFIG_KEY, target) || {};
13
+ const mergedConfig = {
14
+ ...existingConfig,
15
+ ...config,
16
+ controllers: [...(existingConfig.controllers || []), ...(config.controllers || [])],
17
+ globalMiddlewares: existingConfig.globalMiddlewares || config.globalMiddlewares,
18
+ globalInterceptors: existingConfig.globalInterceptors || config.globalInterceptors || [],
19
+ };
20
+ Reflect.defineMetadata(_constants_1.SERVER_CONFIG_KEY, mergedConfig, target);
21
+ if (config.controllers) {
22
+ Reflect.defineMetadata(_constants_1.SERVER_MODULES_KEY, config.controllers, target);
23
+ }
24
+ return target;
25
+ };
26
+ }
27
+ function Use(middleware) {
28
+ return function (target) {
29
+ const existingConfig = Reflect.getMetadata(_constants_1.SERVER_CONFIG_KEY, target) || {};
30
+ const middlewares = existingConfig.globalMiddlewares || [];
31
+ middlewares.push(middleware);
32
+ console.log(middlewares);
33
+ Reflect.defineMetadata(_constants_1.SERVER_CONFIG_KEY, {
34
+ ...existingConfig,
35
+ globalMiddlewares: middlewares,
36
+ }, target);
37
+ return target;
38
+ };
39
+ }
40
+ function Intercept(interceptor) {
41
+ return function (target) {
42
+ const existingConfig = Reflect.getMetadata(_constants_1.SERVER_CONFIG_KEY, target) || {};
43
+ const interceptors = existingConfig.globalInterceptors || [];
44
+ interceptors.push(interceptor);
45
+ Reflect.defineMetadata(_constants_1.SERVER_CONFIG_KEY, {
46
+ ...existingConfig,
47
+ globalInterceptors: interceptors,
48
+ }, target);
49
+ return target;
50
+ };
51
+ }
52
+ function Catch(handler) {
53
+ return function (target) {
54
+ const existingConfig = Reflect.getMetadata(_constants_1.SERVER_CONFIG_KEY, target) || {};
55
+ Reflect.defineMetadata(_constants_1.SERVER_CONFIG_KEY, {
56
+ ...existingConfig,
57
+ globalErrorHandler: handler,
58
+ }, target);
59
+ return target;
60
+ };
61
+ }
62
+ function Port(port) {
63
+ return function (target) {
64
+ const existingConfig = Reflect.getMetadata(_constants_1.SERVER_CONFIG_KEY, target) || {};
65
+ Reflect.defineMetadata(_constants_1.SERVER_CONFIG_KEY, {
66
+ ...existingConfig,
67
+ port,
68
+ }, target);
69
+ return target;
70
+ };
71
+ }
72
+ function Host(host) {
73
+ return function (target) {
74
+ const existingConfig = Reflect.getMetadata(_constants_1.SERVER_CONFIG_KEY, target) || {};
75
+ Reflect.defineMetadata(_constants_1.SERVER_CONFIG_KEY, {
76
+ ...existingConfig,
77
+ host,
78
+ }, target);
79
+ return target;
80
+ };
81
+ }
@@ -0,0 +1,3 @@
1
+ export * from './Application';
2
+ export * from './decorators';
3
+ export * from './websocket/WebsocketServer';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Application"), exports);
18
+ __exportStar(require("./decorators"), exports);
19
+ __exportStar(require("./websocket/WebsocketServer"), exports);
@@ -0,0 +1,20 @@
1
+ import { IWebSocketService } from '@types';
2
+ import { WebSocketServer } from './WebsocketServer';
3
+ export declare class WebSocketService implements IWebSocketService {
4
+ private static instance;
5
+ private wss;
6
+ private constructor();
7
+ static getInstance(): WebSocketService;
8
+ initialize(wss: WebSocketServer): void;
9
+ sendToClient(clientId: string, message: any): boolean;
10
+ publishToTopic(topic: string, data: any, exclude?: string[]): void;
11
+ broadcast(message: any, excludeClientId?: string): void;
12
+ getStats(): {
13
+ clients: number;
14
+ topics: {
15
+ topic: string;
16
+ subscribers: number;
17
+ }[];
18
+ };
19
+ isAvailable(): boolean;
20
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebSocketService = void 0;
4
+ class WebSocketService {
5
+ static instance;
6
+ wss = null;
7
+ constructor() { }
8
+ static getInstance() {
9
+ if (!WebSocketService.instance) {
10
+ WebSocketService.instance = new WebSocketService();
11
+ }
12
+ return WebSocketService.instance;
13
+ }
14
+ initialize(wss) {
15
+ this.wss = wss;
16
+ }
17
+ sendToClient(clientId, message) {
18
+ if (!this.wss)
19
+ return false;
20
+ return this.wss.sendToClient(clientId, message);
21
+ }
22
+ publishToTopic(topic, data, exclude) {
23
+ if (!this.wss)
24
+ return;
25
+ this.wss.publishToTopic(topic, data, exclude);
26
+ }
27
+ broadcast(message, excludeClientId) {
28
+ if (!this.wss)
29
+ return;
30
+ this.wss.broadcast(message, excludeClientId);
31
+ }
32
+ getStats() {
33
+ if (!this.wss)
34
+ return { clients: 0, topics: [] };
35
+ return this.wss.getStats();
36
+ }
37
+ isAvailable() {
38
+ return this.wss !== null;
39
+ }
40
+ }
41
+ exports.WebSocketService = WebSocketService;
@@ -0,0 +1,30 @@
1
+ import { WebSocketClient } from '@types';
2
+ import http from 'http';
3
+ export declare class WebSocketServer {
4
+ private wss;
5
+ private clients;
6
+ private topics;
7
+ private controllers;
8
+ private options;
9
+ constructor(server: http.Server, options?: any);
10
+ private shouldHandleWebSocket;
11
+ private ensureServer;
12
+ private handleConnection;
13
+ private handleMessage;
14
+ private handleClose;
15
+ private handleError;
16
+ private triggerHandlers;
17
+ registerControllers(controllers: any[]): void;
18
+ subscribeToTopic(client: WebSocketClient, topic: string): void;
19
+ unsubscribeFromTopic(client: WebSocketClient, topic: string): void;
20
+ publishToTopic(topic: string, data: any, exclude?: string[]): void;
21
+ sendToClient(clientId: string, message: any): boolean;
22
+ broadcast(message: any, excludeClientId?: string): void;
23
+ getStats(): {
24
+ clients: number;
25
+ topics: {
26
+ topic: string;
27
+ subscribers: number;
28
+ }[];
29
+ };
30
+ }
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WebSocketServer = void 0;
7
+ const uuid_1 = require("uuid");
8
+ const ws_1 = __importDefault(require("ws"));
9
+ class WebSocketServer {
10
+ wss = null;
11
+ clients = new Map();
12
+ topics = new Map();
13
+ controllers = [];
14
+ options;
15
+ constructor(server, options) {
16
+ this.options = options;
17
+ server.on('upgrade', (request, socket, head) => {
18
+ if (this.shouldHandleWebSocket(request.url)) {
19
+ this.ensureServer(server);
20
+ this.wss?.handleUpgrade(request, socket, head, (ws) => {
21
+ this.wss?.emit('connection', ws, request);
22
+ });
23
+ }
24
+ else {
25
+ socket.destroy();
26
+ }
27
+ });
28
+ }
29
+ shouldHandleWebSocket(url = '') {
30
+ const path = this.options?.path || '/ws';
31
+ return url.startsWith(path);
32
+ }
33
+ ensureServer(server) {
34
+ if (!this.wss) {
35
+ this.wss = new ws_1.default.Server({
36
+ server,
37
+ path: this.options?.path || '/ws',
38
+ noServer: true,
39
+ });
40
+ this.wss.on('connection', (socket, request) => {
41
+ this.handleConnection(socket, request);
42
+ });
43
+ }
44
+ }
45
+ async handleConnection(socket, request) {
46
+ const clientId = (0, uuid_1.v4)();
47
+ const client = {
48
+ id: clientId,
49
+ socket,
50
+ topics: new Set(),
51
+ data: {},
52
+ connectedAt: new Date(),
53
+ };
54
+ this.clients.set(clientId, client);
55
+ socket.on('message', (data) => {
56
+ this.handleMessage(client, data);
57
+ });
58
+ socket.on('close', () => {
59
+ this.handleClose(client);
60
+ });
61
+ socket.on('error', (error) => {
62
+ this.handleError(client, error);
63
+ });
64
+ await this.triggerHandlers('connection', { type: 'connection', client });
65
+ }
66
+ async handleMessage(client, data) {
67
+ try {
68
+ const message = JSON.parse(data.toString());
69
+ if (message.type === 'subscribe' && message.topic) {
70
+ this.subscribeToTopic(client, message.topic);
71
+ return;
72
+ }
73
+ if (message.type === 'unsubscribe' && message.topic) {
74
+ this.unsubscribeFromTopic(client, message.topic);
75
+ return;
76
+ }
77
+ if (message.type === 'topic_message' && message.topic) {
78
+ await this.triggerHandlers('message', {
79
+ type: 'message',
80
+ client,
81
+ message,
82
+ }, message.topic);
83
+ this.publishToTopic(message.topic, message.data, [client.id]);
84
+ return;
85
+ }
86
+ await this.triggerHandlers('message', {
87
+ type: 'message',
88
+ client,
89
+ message,
90
+ });
91
+ }
92
+ catch (error) {
93
+ client.socket.send(JSON.stringify({
94
+ type: 'error',
95
+ data: { message: 'Invalid message format' },
96
+ }));
97
+ }
98
+ }
99
+ async handleClose(client) {
100
+ client.topics.forEach((topic) => {
101
+ const topicClients = this.topics.get(topic);
102
+ if (topicClients) {
103
+ topicClients.delete(client.id);
104
+ if (topicClients.size === 0) {
105
+ this.topics.delete(topic);
106
+ }
107
+ }
108
+ });
109
+ this.clients.delete(client.id);
110
+ await this.triggerHandlers('close', {
111
+ type: 'close',
112
+ client,
113
+ });
114
+ }
115
+ async handleError(client, error) {
116
+ await this.triggerHandlers('error', {
117
+ type: 'error',
118
+ client,
119
+ data: error,
120
+ });
121
+ }
122
+ async triggerHandlers(eventType, event, topic) {
123
+ for (const controller of this.controllers) {
124
+ const handlers = Reflect.getMetadata('websocket:handler', controller.constructor) || [];
125
+ const matchingHandlers = handlers.filter((h) => h.type === eventType && (!h.topic || h.topic === topic));
126
+ for (const handler of matchingHandlers) {
127
+ try {
128
+ await controller[handler.method](event);
129
+ }
130
+ catch (error) {
131
+ console.error(`Error in WebSocket handler ${handler.method}:`, error);
132
+ }
133
+ }
134
+ const subscriptions = Reflect.getMetadata('websocket:topic', controller.constructor) || [];
135
+ if (eventType === 'message' && topic) {
136
+ const matchingSubs = subscriptions.filter((s) => s.topic === topic);
137
+ for (const sub of matchingSubs) {
138
+ try {
139
+ await controller[sub.method](event);
140
+ }
141
+ catch (error) {
142
+ console.error(`Error in subscription ${sub.method}:`, error);
143
+ }
144
+ }
145
+ }
146
+ }
147
+ }
148
+ registerControllers(controllers) {
149
+ this.controllers = controllers;
150
+ }
151
+ subscribeToTopic(client, topic) {
152
+ if (!this.topics.has(topic)) {
153
+ this.topics.set(topic, new Set());
154
+ }
155
+ this.topics.get(topic).add(client.id);
156
+ client.topics.add(topic);
157
+ client.socket.send(JSON.stringify({
158
+ type: 'subscribed',
159
+ topic,
160
+ data: { success: true },
161
+ }));
162
+ }
163
+ unsubscribeFromTopic(client, topic) {
164
+ const topicClients = this.topics.get(topic);
165
+ if (topicClients) {
166
+ topicClients.delete(client.id);
167
+ if (topicClients.size === 0) {
168
+ this.topics.delete(topic);
169
+ }
170
+ }
171
+ client.topics.delete(topic);
172
+ client.socket.send(JSON.stringify({
173
+ type: 'unsubscribed',
174
+ topic,
175
+ data: { success: true },
176
+ }));
177
+ }
178
+ publishToTopic(topic, data, exclude) {
179
+ const topicClients = this.topics.get(topic);
180
+ if (!topicClients)
181
+ return;
182
+ const message = JSON.stringify({
183
+ type: 'message',
184
+ topic,
185
+ data,
186
+ timestamp: new Date().toISOString(),
187
+ });
188
+ topicClients.forEach((clientId) => {
189
+ const client = this.clients.get(clientId);
190
+ if (client && exclude?.includes(client.id)) {
191
+ client.socket.send(message);
192
+ }
193
+ });
194
+ }
195
+ sendToClient(clientId, message) {
196
+ const client = this.clients.get(clientId);
197
+ if (client) {
198
+ client.socket.send(JSON.stringify(message));
199
+ return true;
200
+ }
201
+ return false;
202
+ }
203
+ broadcast(message, excludeClientId) {
204
+ const messageStr = JSON.stringify(message);
205
+ this.clients.forEach((client, clientId) => {
206
+ if (clientId !== excludeClientId) {
207
+ client.socket.send(messageStr);
208
+ }
209
+ });
210
+ }
211
+ getStats() {
212
+ return {
213
+ clients: this.clients.size,
214
+ topics: Array.from(this.topics.entries()).map(([topic, clients]) => ({
215
+ topic,
216
+ subscribers: clients.size,
217
+ })),
218
+ };
219
+ }
220
+ }
221
+ exports.WebSocketServer = WebSocketServer;
@@ -0,0 +1,16 @@
1
+ export declare const PARAM_METADATA_KEY = "design:parameters";
2
+ export declare const APP_METADATA_KEY = "app:configuration";
3
+ export declare const ROUTE_PREFIX = "route:profix";
4
+ export declare const MIDDLEWARES = "route:middlewares";
5
+ export declare const CONTROLLERS = "app:controllers";
6
+ export declare const INTERCEPTORS = "app:interceptors";
7
+ export declare const ENDPOINT = "route:endpoints";
8
+ export declare const OK_METADATA_KEY = "custom:ok";
9
+ export declare const SERVER_CONFIG_KEY = "server:config";
10
+ export declare const SERVER_MODULES_KEY = "server:modules";
11
+ export declare const WS_METADATA_KEY = "websocket:handler";
12
+ export declare const WS_TOPIC_KEY = "websocket:topic";
13
+ export declare const WS_SERVICE_KEY = "websocket:service";
14
+ export declare const STOPPED = "\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551 \uD83D\uDC4B Server stopped \u2551\n\u2551 \uD83D\uDCCA Status: STOPPED \u2551\n\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n ";
15
+ export declare const OK_STATUSES: number[];
16
+ export declare const TO_VALIDATE: string[];
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TO_VALIDATE = exports.OK_STATUSES = exports.STOPPED = exports.WS_SERVICE_KEY = exports.WS_TOPIC_KEY = exports.WS_METADATA_KEY = exports.SERVER_MODULES_KEY = exports.SERVER_CONFIG_KEY = exports.OK_METADATA_KEY = exports.ENDPOINT = exports.INTERCEPTORS = exports.CONTROLLERS = exports.MIDDLEWARES = exports.ROUTE_PREFIX = exports.APP_METADATA_KEY = exports.PARAM_METADATA_KEY = void 0;
4
+ exports.PARAM_METADATA_KEY = 'design:parameters';
5
+ exports.APP_METADATA_KEY = 'app:configuration';
6
+ exports.ROUTE_PREFIX = 'route:profix';
7
+ exports.MIDDLEWARES = 'route:middlewares';
8
+ exports.CONTROLLERS = 'app:controllers';
9
+ exports.INTERCEPTORS = 'app:interceptors';
10
+ exports.ENDPOINT = 'route:endpoints';
11
+ exports.OK_METADATA_KEY = 'custom:ok';
12
+ exports.SERVER_CONFIG_KEY = 'server:config';
13
+ exports.SERVER_MODULES_KEY = 'server:modules';
14
+ exports.WS_METADATA_KEY = 'websocket:handler';
15
+ exports.WS_TOPIC_KEY = 'websocket:topic';
16
+ exports.WS_SERVICE_KEY = 'websocket:service';
17
+ exports.STOPPED = `
18
+ ╔════════════════════════════════════════╗
19
+ ║ 👋 Server stopped ║
20
+ ║ 📊 Status: STOPPED ║
21
+ ╚════════════════════════════════════════╝
22
+ `;
23
+ exports.OK_STATUSES = [200, 201, 202, 203, 204, 205, 206, 207, 208, 226];
24
+ exports.TO_VALIDATE = ['headers', 'params', 'multipart', 'query', 'body'];
@@ -0,0 +1,43 @@
1
+ import { Interceptor, Middleware } from '@types';
2
+ import { ServerResponse } from 'http';
3
+ import 'reflect-metadata';
4
+ type ControllerClass = {
5
+ new (...args: any[]): any;
6
+ };
7
+ type ControllerInstance = InstanceType<ControllerClass>;
8
+ interface ControllerConfig {
9
+ prefix: string;
10
+ middlewares?: Array<Middleware>;
11
+ controllers?: ControllerClass[];
12
+ interceptors?: Array<(...args: any[]) => any> | ((...args: any[]) => any);
13
+ }
14
+ export declare function Controller(config: string | ControllerConfig, middlewares?: Array<Interceptor>): <T extends ControllerClass>(constructor: T) => {
15
+ new (...args: any[]): {
16
+ [x: string]: any;
17
+ executeControllerMethod: (controller: import("@types").ControllerInstance, propertyName: string, payload: any, response?: ServerResponse) => Promise<any>;
18
+ getControllerMethods: (controller: import("@types").ControllerInstance) => {
19
+ name: string;
20
+ httpMethod: string;
21
+ pattern: string;
22
+ middlewares?: Array<(req: any, res?: ServerResponse) => any>;
23
+ }[];
24
+ getResponse(data: {
25
+ controllerInstance: ControllerInstance;
26
+ name: string;
27
+ payload: any;
28
+ interceptors: Array<(...args: any[]) => any | Promise<any>>;
29
+ response?: ServerResponse;
30
+ }): Promise<{
31
+ status: any;
32
+ data: any;
33
+ }>;
34
+ handleRequest: (request: any, response?: ServerResponse) => Promise<{
35
+ status: any;
36
+ data: any;
37
+ } | {
38
+ status: number;
39
+ message: string;
40
+ }>;
41
+ };
42
+ } & T;
43
+ export {};
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Controller = Controller;
4
+ /* eslint-disable @typescript-eslint/no-explicit-any */
5
+ const _constants_1 = require("@constants");
6
+ const _utils_1 = require("@utils");
7
+ require("reflect-metadata");
8
+ function Controller(config, middlewares = []) {
9
+ // Handle both string and config object
10
+ const routePrefix = typeof config === 'string' ? config : config.prefix;
11
+ const controllers = typeof config === 'object' ? config.controllers : undefined;
12
+ const controllerMiddlewares = typeof config === 'object' ? [...(config.middlewares || []), ...middlewares] : middlewares;
13
+ const interceptors = typeof config === 'object'
14
+ ? config.interceptors
15
+ ? [].concat(config.interceptors)
16
+ : []
17
+ : [];
18
+ return function (constructor) {
19
+ const proto = constructor.prototype;
20
+ Reflect.defineMetadata(_constants_1.ROUTE_PREFIX, routePrefix, proto);
21
+ Reflect.defineMetadata(_constants_1.MIDDLEWARES, controllerMiddlewares, proto);
22
+ Reflect.defineMetadata(_constants_1.CONTROLLERS, controllers || [], proto);
23
+ Reflect.defineMetadata(_constants_1.INTERCEPTORS, interceptors, proto);
24
+ for (const key of Object.getOwnPropertyNames(proto)) {
25
+ if (key === 'constructor')
26
+ continue;
27
+ const descriptor = Object.getOwnPropertyDescriptor(proto, key);
28
+ if (!descriptor || typeof descriptor.value !== 'function')
29
+ continue;
30
+ const original = descriptor.value;
31
+ Object.defineProperty(proto, key, {
32
+ ...descriptor,
33
+ value: async function (...args) {
34
+ try {
35
+ return await original.apply(this, args);
36
+ }
37
+ catch (err) {
38
+ return {
39
+ status: err.status ?? 400,
40
+ message: err.message,
41
+ data: err,
42
+ };
43
+ }
44
+ },
45
+ });
46
+ }
47
+ return class extends constructor {
48
+ executeControllerMethod = _utils_1.executeControllerMethod;
49
+ getControllerMethods = _utils_1.getControllerMethods;
50
+ constructor(...args) {
51
+ super(...args);
52
+ }
53
+ async getResponse(data) {
54
+ try {
55
+ let response = await this.executeControllerMethod(data.controllerInstance, data.name, data.payload, data.response);
56
+ let status = response.status ?? 200;
57
+ const isError = !_constants_1.OK_STATUSES.includes(status);
58
+ for (let index = 0; index < data.interceptors?.length && !isError; index++) {
59
+ const interceptor = data.interceptors[index];
60
+ response = await interceptor(response);
61
+ }
62
+ const propertyName = data.name;
63
+ const prototype = Object.getPrototypeOf(data.controllerInstance);
64
+ const methodOkStatus = Reflect.getMetadata(_constants_1.OK_METADATA_KEY, data.controllerInstance, propertyName);
65
+ if (methodOkStatus) {
66
+ !isError && (status = methodOkStatus);
67
+ }
68
+ else {
69
+ const classOkStatus = Reflect.getMetadata(_constants_1.OK_METADATA_KEY, prototype);
70
+ !isError && classOkStatus && (status = classOkStatus);
71
+ }
72
+ return { status, data: response };
73
+ }
74
+ catch (err) {
75
+ console.error(err);
76
+ throw err;
77
+ }
78
+ }
79
+ handleRequest = async (request, response) => {
80
+ const method = request.method;
81
+ const path = (request.url.path ?? request.url.pathname ?? '').replace(/^\/+/, '');
82
+ const baseInterceptors = Reflect.getMetadata(_constants_1.INTERCEPTORS, proto);
83
+ const routePrefix = Reflect.getMetadata(_constants_1.ROUTE_PREFIX, proto) || '';
84
+ const middlewares = Reflect.getMetadata(_constants_1.MIDDLEWARES, proto) || [];
85
+ const subControllers = Reflect.getMetadata(_constants_1.CONTROLLERS, proto) || [];
86
+ // Try sub-controllers
87
+ for (const SubController of subControllers) {
88
+ const controllerInstance = new SubController(SubController);
89
+ if (!controllerInstance)
90
+ continue;
91
+ const subInterceptors = Reflect.getMetadata(_constants_1.INTERCEPTORS, controllerInstance);
92
+ const controllerPrefix = Reflect.getMetadata(_constants_1.ROUTE_PREFIX, SubController.prototype) || '';
93
+ const controllerMiddlewares = Reflect.getMetadata(_constants_1.MIDDLEWARES, SubController.prototype) || [];
94
+ const methods = this.getControllerMethods(controllerInstance);
95
+ for (const methodInfo of methods) {
96
+ if (methodInfo.httpMethod === method || methodInfo.httpMethod === 'USE') {
97
+ // Build full pattern: main prefix + controller prefix + method pattern
98
+ const fullPattern = [routePrefix, controllerPrefix, methodInfo.pattern]
99
+ .filter(Boolean)
100
+ .join('/')
101
+ .replace(/\/+/g, '/');
102
+ const pathParams = (0, _utils_1.matchRoute)(fullPattern, path);
103
+ if (pathParams) {
104
+ let payload = { ...request, params: pathParams };
105
+ // Apply all middlewares in order: main controller -> sub-controller -> method
106
+ for (const middleware of [
107
+ ...middlewares,
108
+ ...controllerMiddlewares,
109
+ ...(methodInfo.middlewares || []),
110
+ ]) {
111
+ const middlawareResponde = await middleware(payload, response);
112
+ payload = { ...payload, ...middlawareResponde };
113
+ }
114
+ return this.getResponse({
115
+ interceptors: [...subInterceptors, ...baseInterceptors],
116
+ controllerInstance,
117
+ name: methodInfo.name,
118
+ payload,
119
+ response,
120
+ });
121
+ }
122
+ }
123
+ }
124
+ }
125
+ const propertyNames = Object.getOwnPropertyNames(proto);
126
+ for (const propertyName of propertyNames) {
127
+ const fn = this[propertyName];
128
+ if (typeof fn !== 'function')
129
+ continue;
130
+ const endpointMeta = Reflect.getMetadata(_constants_1.ENDPOINT, proto, propertyName) || [];
131
+ const [httpMethod, routePattern] = endpointMeta;
132
+ if (httpMethod === method || httpMethod === 'USE') {
133
+ const fullPattern = [routePrefix, routePattern]
134
+ .filter(Boolean)
135
+ .join('/')
136
+ .replace(/\/+/g, '/');
137
+ const pathParams = (0, _utils_1.matchRoute)(fullPattern, path);
138
+ if (pathParams) {
139
+ let payload = { ...request, params: pathParams };
140
+ // Apply controller-level middlewares
141
+ for (const middleware of middlewares) {
142
+ const middlewareResponse = await middleware(payload);
143
+ payload = { ...payload, middlewareResponse };
144
+ }
145
+ return this.getResponse({
146
+ interceptors: baseInterceptors,
147
+ controllerInstance: this,
148
+ name: propertyName,
149
+ payload,
150
+ response,
151
+ });
152
+ }
153
+ }
154
+ }
155
+ return { status: 404, message: 'Method Not Found' };
156
+ };
157
+ };
158
+ };
159
+ }
@@ -0,0 +1,8 @@
1
+ import { Middleware } from '@types';
2
+ export declare function Endpoint(method: string, pathPattern?: string, middlewares?: Middleware[]): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
3
+ export declare const GET: (pathPattern?: string, middelwares?: Middleware[]) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
4
+ export declare const POST: (pathPattern?: string, middelwares?: Middleware[]) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
5
+ export declare const PUT: (pathPattern?: string, middelwares?: Middleware[]) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
6
+ export declare const PATCH: (pathPattern?: string, middelwares?: Middleware[]) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
7
+ export declare const DELETE: (pathPattern?: string, middelwares?: Middleware[]) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
8
+ export declare const USE: (pathPattern?: string, middelwares?: Middleware[]) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;