@heliosjs/core 1.0.2

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 (152) hide show
  1. package/README.md +540 -0
  2. package/dist/Controller.d.ts +54 -0
  3. package/dist/Controller.js +168 -0
  4. package/dist/Controller.js.map +1 -0
  5. package/dist/Endpoint.d.ts +73 -0
  6. package/dist/Endpoint.js +126 -0
  7. package/dist/Endpoint.js.map +1 -0
  8. package/dist/constants.d.ts +25 -0
  9. package/dist/constants.js +34 -0
  10. package/dist/constants.js.map +1 -0
  11. package/dist/decorators.d.ts +94 -0
  12. package/dist/decorators.js +107 -0
  13. package/dist/decorators.js.map +1 -0
  14. package/dist/index.d.ts +11 -0
  15. package/dist/index.js +29 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/types/core/common.d.ts +44 -0
  18. package/dist/types/core/common.js +15 -0
  19. package/dist/types/core/common.js.map +1 -0
  20. package/dist/types/core/controller.d.ts +78 -0
  21. package/dist/types/core/controller.js +3 -0
  22. package/dist/types/core/controller.js.map +1 -0
  23. package/dist/types/core/cors.d.ts +10 -0
  24. package/dist/types/core/cors.js +3 -0
  25. package/dist/types/core/cors.js.map +1 -0
  26. package/dist/types/core/error.d.ts +72 -0
  27. package/dist/types/core/error.js +19 -0
  28. package/dist/types/core/error.js.map +1 -0
  29. package/dist/types/core/index.d.ts +9 -0
  30. package/dist/types/core/index.js +26 -0
  31. package/dist/types/core/index.js.map +1 -0
  32. package/dist/types/core/multipart.d.ts +8 -0
  33. package/dist/types/core/multipart.js +3 -0
  34. package/dist/types/core/multipart.js.map +1 -0
  35. package/dist/types/core/request.d.ts +65 -0
  36. package/dist/types/core/request.js +3 -0
  37. package/dist/types/core/request.js.map +1 -0
  38. package/dist/types/core/response.d.ts +49 -0
  39. package/dist/types/core/response.js +3 -0
  40. package/dist/types/core/response.js.map +1 -0
  41. package/dist/types/core/sanitize.d.ts +8 -0
  42. package/dist/types/core/sanitize.js +3 -0
  43. package/dist/types/core/sanitize.js.map +1 -0
  44. package/dist/types/core/sse.d.ts +37 -0
  45. package/dist/types/core/sse.js +3 -0
  46. package/dist/types/core/sse.js.map +1 -0
  47. package/dist/types/ws/index.d.ts +50 -0
  48. package/dist/types/ws/index.js +3 -0
  49. package/dist/types/ws/index.js.map +1 -0
  50. package/dist/utils/core/controller.d.ts +25 -0
  51. package/dist/utils/core/controller.js +219 -0
  52. package/dist/utils/core/controller.js.map +1 -0
  53. package/dist/utils/core/cors.d.ts +8 -0
  54. package/dist/utils/core/cors.js +128 -0
  55. package/dist/utils/core/cors.js.map +1 -0
  56. package/dist/utils/core/endpoint.d.ts +3 -0
  57. package/dist/utils/core/endpoint.js +28 -0
  58. package/dist/utils/core/endpoint.js.map +1 -0
  59. package/dist/utils/core/error/apperror.d.ts +31 -0
  60. package/dist/utils/core/error/apperror.js +131 -0
  61. package/dist/utils/core/error/apperror.js.map +1 -0
  62. package/dist/utils/core/error/authorizations.d.ts +7 -0
  63. package/dist/utils/core/error/authorizations.js +17 -0
  64. package/dist/utils/core/error/authorizations.js.map +1 -0
  65. package/dist/utils/core/error/base.d.ts +20 -0
  66. package/dist/utils/core/error/base.js +52 -0
  67. package/dist/utils/core/error/base.js.map +1 -0
  68. package/dist/utils/core/error/dependencyFailed.d.ts +7 -0
  69. package/dist/utils/core/error/dependencyFailed.js +17 -0
  70. package/dist/utils/core/error/dependencyFailed.js.map +1 -0
  71. package/dist/utils/core/error/duplicateEntry.d.ts +7 -0
  72. package/dist/utils/core/error/duplicateEntry.js +17 -0
  73. package/dist/utils/core/error/duplicateEntry.js.map +1 -0
  74. package/dist/utils/core/error/forbidden.d.ts +7 -0
  75. package/dist/utils/core/error/forbidden.js +17 -0
  76. package/dist/utils/core/error/forbidden.js.map +1 -0
  77. package/dist/utils/core/error/helpers.d.ts +8 -0
  78. package/dist/utils/core/error/helpers.js +144 -0
  79. package/dist/utils/core/error/helpers.js.map +1 -0
  80. package/dist/utils/core/error/index.d.ts +12 -0
  81. package/dist/utils/core/error/index.js +29 -0
  82. package/dist/utils/core/error/index.js.map +1 -0
  83. package/dist/utils/core/error/invalidState.d.ts +7 -0
  84. package/dist/utils/core/error/invalidState.js +17 -0
  85. package/dist/utils/core/error/invalidState.js.map +1 -0
  86. package/dist/utils/core/error/notfound.d.ts +7 -0
  87. package/dist/utils/core/error/notfound.js +18 -0
  88. package/dist/utils/core/error/notfound.js.map +1 -0
  89. package/dist/utils/core/error/rateLimit.d.ts +7 -0
  90. package/dist/utils/core/error/rateLimit.js +17 -0
  91. package/dist/utils/core/error/rateLimit.js.map +1 -0
  92. package/dist/utils/core/error/serviceUnavailable.d.ts +7 -0
  93. package/dist/utils/core/error/serviceUnavailable.js +17 -0
  94. package/dist/utils/core/error/serviceUnavailable.js.map +1 -0
  95. package/dist/utils/core/error/validation.d.ts +10 -0
  96. package/dist/utils/core/error/validation.js +20 -0
  97. package/dist/utils/core/error/validation.js.map +1 -0
  98. package/dist/utils/core/headers.d.ts +2 -0
  99. package/dist/utils/core/headers.js +10 -0
  100. package/dist/utils/core/headers.js.map +1 -0
  101. package/dist/utils/core/helper.d.ts +6 -0
  102. package/dist/utils/core/helper.js +66 -0
  103. package/dist/utils/core/helper.js.map +1 -0
  104. package/dist/utils/core/index.d.ts +10 -0
  105. package/dist/utils/core/index.js +27 -0
  106. package/dist/utils/core/index.js.map +1 -0
  107. package/dist/utils/core/multipart.d.ts +9 -0
  108. package/dist/utils/core/multipart.js +207 -0
  109. package/dist/utils/core/multipart.js.map +1 -0
  110. package/dist/utils/core/request.d.ts +100 -0
  111. package/dist/utils/core/request.js +218 -0
  112. package/dist/utils/core/request.js.map +1 -0
  113. package/dist/utils/core/response.d.ts +48 -0
  114. package/dist/utils/core/response.js +269 -0
  115. package/dist/utils/core/response.js.map +1 -0
  116. package/dist/utils/core/routeWalker.d.ts +2 -0
  117. package/dist/utils/core/routeWalker.js +115 -0
  118. package/dist/utils/core/routeWalker.js.map +1 -0
  119. package/dist/utils/core/sanitize.d.ts +30 -0
  120. package/dist/utils/core/sanitize.js +134 -0
  121. package/dist/utils/core/sanitize.js.map +1 -0
  122. package/dist/utils/shared/index.d.ts +2 -0
  123. package/dist/utils/shared/index.js +19 -0
  124. package/dist/utils/shared/index.js.map +1 -0
  125. package/dist/utils/shared/parsers.d.ts +11 -0
  126. package/dist/utils/shared/parsers.js +133 -0
  127. package/dist/utils/shared/parsers.js.map +1 -0
  128. package/dist/utils/shared/validate.d.ts +1 -0
  129. package/dist/utils/shared/validate.js +41 -0
  130. package/dist/utils/shared/validate.js.map +1 -0
  131. package/dist/utils/socket/index.d.ts +3 -0
  132. package/dist/utils/socket/index.js +20 -0
  133. package/dist/utils/socket/index.js.map +1 -0
  134. package/dist/utils/socket/server.d.ts +33 -0
  135. package/dist/utils/socket/server.js +218 -0
  136. package/dist/utils/socket/server.js.map +1 -0
  137. package/dist/utils/socket/service.d.ts +20 -0
  138. package/dist/utils/socket/service.js +42 -0
  139. package/dist/utils/socket/service.js.map +1 -0
  140. package/dist/utils/socket/socket.d.ts +16 -0
  141. package/dist/utils/socket/socket.js +33 -0
  142. package/dist/utils/socket/socket.js.map +1 -0
  143. package/dist/utils/sse/index.d.ts +2 -0
  144. package/dist/utils/sse/index.js +19 -0
  145. package/dist/utils/sse/index.js.map +1 -0
  146. package/dist/utils/sse/server.d.ts +14 -0
  147. package/dist/utils/sse/server.js +85 -0
  148. package/dist/utils/sse/server.js.map +1 -0
  149. package/dist/utils/sse/service.d.ts +17 -0
  150. package/dist/utils/sse/service.js +40 -0
  151. package/dist/utils/sse/service.js.map +1 -0
  152. package/package.json +37 -0
package/README.md ADDED
@@ -0,0 +1,540 @@
1
+ # Project Overview
2
+
3
+ This project is a decorator-based API framework supporting both HTTP and WebSocket servers. It is designed to simplify the creation of scalable and maintainable APIs with features such as controllers, middlewares, interceptors, error handling, and WebSocket support. Additionally, it supports AWS Lambda integration for serverless deployments.
4
+
5
+ # Installation
6
+
7
+ To install dependencies and build the project, run:
8
+
9
+ ```bash
10
+ yarn install
11
+ # or npm install
12
+ ```
13
+
14
+ # Usage
15
+
16
+ You can use controllers and server functionality by importing controllers and creating server instances as shown in the examples above. Use your preferred testing framework to write unit and integration tests.
17
+
18
+ # Project Structure
19
+
20
+ - `quantum-flow/http` - Main application source code for HTTP servers.
21
+ - `quantum-flow/aws` - Main application source code for AWS Lambda.
22
+ - `quantum-flow/core` - Core framework components like Controller and Endpoint.
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.
26
+ - `quantum-flow/plugins/aws` - Exports plugins types for lambda.
27
+ - `quantum-flow/plugins/http` - Exports plugins types for http server.
28
+
29
+ ---
30
+
31
+ ## Defining Controllers
32
+
33
+ Use the `@Controller` decorator to define controllers with options such as prefix, sub-controllers, middlewares, and interceptors.
34
+
35
+ ```typescript
36
+ import {
37
+ Body,
38
+ Controller,
39
+ Headers,
40
+ IWebSocketService,
41
+ Params,
42
+ PUT,
43
+ Query,
44
+ Request,
45
+ Response,
46
+ Status,
47
+ ANY,
48
+ IRequest,
49
+ IResponse
50
+ } from 'quantum-flow/core';
51
+ import {IsString} from 'class-validator'
52
+ import { Catch, Cors, Sanitize, Use, SANITIZER } from 'quantum-flow/middlewares';
53
+ import { InjectWS } from 'quantum-flow/ws';
54
+ import { HttpRequest } from 'quantum-flow/http';
55
+ // SANITIZER - prefilled Joi schema for common data
56
+ class UserDto {
57
+ constructor() {}
58
+ @IsString()
59
+ name: string;
60
+ }
61
+
62
+ @Controller({
63
+ prefix: 'user',
64
+ controllers: [UserMetadata, ...],
65
+ interceptor: (data, req, res) => data,
66
+ })
67
+ @Cors({ origin: '*' })
68
+ @Catch((err) => ({ status: 500, err }))
69
+ @Use(()=>{})
70
+ @Sanitize({
71
+ schema: Joi.object({name: Joi.string().trim().min(2).max(50).required()}),
72
+ action: 'both',
73
+ options: { abortEarly: false },
74
+ stripUnknown: true,
75
+ type: 'body',
76
+ })
77
+ export class User {
78
+ @Status(201)
79
+ @PUT(':id',[(req, res)=>{} , ...middlewares])
80
+ @Cors({ origin: '*' })
81
+ async createUser(
82
+ @Body(UserDto) body: UserDto,
83
+ @Query() query: Record<string, string | string[]>,
84
+ @Headers() headers: Record<string, string | string[]>,
85
+ @Params(ParamDTO, 'param') params: string,
86
+ @Request() req: IResponse,
87
+ @Response() resp: IRequest,
88
+ @InjectWS() ws: IWebSocketService,
89
+ ) {}
90
+
91
+ @ANY([...middlewares])
92
+ async any(@Response() resp: any) {...}
93
+ }
94
+
95
+ @Controller(api, [...middlewares])
96
+ @Controller({
97
+ prefix: 'api',
98
+ controllers: [UserController, SocketController],
99
+ middlewares: [...middlewares],
100
+ interceptor: (data, req, res) => data,
101
+ })
102
+ @Catch((error) => ({ status: 400, error }))
103
+ class RootController {}
104
+ ```
105
+
106
+ ## Creating a http Server
107
+
108
+ Use the `@Server` decorator with configuration options like port, host, controllers, and WebSocket enablement.
109
+
110
+ ```typescript
111
+ import { Server, Port, Host, Use, Catch, HttpServer } from 'quantum-flow/http';
112
+
113
+ @Server({ controllers: [RootController], cors: { origin: '*' } })
114
+ @Port(3000)
115
+ @Host('localhost')
116
+ @Use((data) => data)
117
+ @Catch((error) => ({ status: 400, error }))
118
+ class App {}
119
+
120
+ const server = new HttpServer(App);
121
+
122
+ server.listen().catch(console.error);
123
+ ```
124
+
125
+ ## Middlewares, Interceptors, and Error Handlers
126
+
127
+ - Use `@Use` to apply middlewares.
128
+ - Use `@Catch` to handle errors.
129
+ - Use `@Port` and `@Host` to configure server port and host.
130
+ - Use `@Cors` to configure cors.
131
+ - Use `@Sanitize` to apply sanitization to reqest.
132
+
133
+ ## Request decorators
134
+
135
+ - Use `@Body` to handle request bodies.
136
+ - Use `@Headers` to access request headers.
137
+ - Use `@Query` to handle query parameters.
138
+ - Use `@Params` to access route parameters.
139
+ - Use `@Files` to access files sent within multipart/form-data requests.
140
+ Text sent as multipart/form-data is exposed with `@Body` decorators
141
+ - Use `@Request` to access the original request object.
142
+ - Use `@Response` to access the original object.
143
+ - Use `@InjectWS` to access the websocket service.
144
+ - Use `@InjectSSE` to access the server-side-event service.
145
+
146
+ # AWS Lambda Support
147
+
148
+ Use `LambdaAdapter` to convert API Gateway events to requests and responses. Create Lambda handlers from controllers.
149
+
150
+ ```typescript
151
+ Example Lambda handler creation
152
+ import { LambdaAdapter, LambdaRequest, LambdaResponse } from 'quantum-flow/aws';
153
+ import { Request, Query, Headers, Params, Response, IResponse, IRequest } from 'quantum-flow/core'
154
+
155
+ @Controller({ prefix: 'user' })
156
+ class UserController {
157
+ @Body(UserDto) body: UserDto,
158
+ @Query() query: Record<string, string | string[]>,
159
+ @Headers() headers: Record<string, string | string[]>,
160
+ @Params(ParamDTO, 'param') params: string,
161
+ @Request() req: IRequest,
162
+ @Response() res: IResponse
163
+ ) { }
164
+ }
165
+ const lambdaAdapter = new LambdaAdapter(UserController);
166
+ export const handler = lambdaAdapter.handler;
167
+ ```
168
+
169
+ You can access context and event throught @Request() decorator:
170
+ @Request() request: LambdaRequest
171
+ request.context
172
+ request.event
173
+
174
+ # WebSocket Support
175
+
176
+ Enable WebSocket in the server configuration and register WebSocket controllers.
177
+
178
+ ## Enabling WebSocket Support in Server
179
+
180
+ To enable WS support, configure your HTTP server with the `path: string` option and register controllers that use SSE.
181
+
182
+ Example server setup:
183
+
184
+ ```typescript
185
+ @Server( { websocket: { path:'/ws' } })
186
+ ```
187
+
188
+ ## Injecting WebSocket events in Controller
189
+
190
+ ```typescript
191
+ import { OnConnection, Subscribe, OnMessage } from 'quantum-flow/ws';
192
+ @Controller('socket')
193
+ export class Socket {
194
+ @OnConnection()
195
+ onConnection(event: WebSocketEvent) {
196
+ // Send greeting ONLY to this client
197
+ event.client.socket.send(JSON.stringify({ type: 'welcome', data: { message: 'Welcome!' } }));
198
+ }
199
+
200
+ /**
201
+ * 2. @Subscribe - AUTOMATIC broadcast to all subscribers
202
+ * No need to use WebSocketService!
203
+ */
204
+ @Subscribe('chat')
205
+ onChatMessage(event: WebSocketEvent) {
206
+ // This method is called for EACH subscriber
207
+ // The message is ALREADY automatically broadcast to all!
208
+
209
+ const msg = event.message?.data;
210
+ // You can add logic, but no need to broadcast
211
+ if (msg?.text.includes('bad')) {
212
+ // If return empty, the message will not be sent
213
+ return;
214
+ }
215
+
216
+ // That's it, the message will be sent to subscribers automatically!
217
+ }
218
+
219
+ /**
220
+ * 4. @OnMessage for commands (without WebSocketService)
221
+ */
222
+ @OnMessage('ping')
223
+ onPing(event: WebSocketEvent) {
224
+ // Send response only to this client
225
+ event.client.socket.send(
226
+ JSON.stringify({
227
+ type: 'pong',
228
+ data: { time: Date.now() },
229
+ }),
230
+ );
231
+ }
232
+
233
+ /**
234
+ * 5. @OnMessage for subscription
235
+ */
236
+ @OnMessage('subscribe')
237
+ onSubscribe(event: WebSocketEvent) {
238
+ const topic = event.message?.data.topic;
239
+
240
+ // Server will save the subscription automatically, no need to do anything!
241
+ // Just confirm
242
+ event.client.socket.send(
243
+ JSON.stringify({
244
+ type: 'subscribed',
245
+ topic,
246
+ data: { success: true },
247
+ }),
248
+ );
249
+ }
250
+ }
251
+ ```
252
+
253
+ # Server-Sent Events (SSE) Support
254
+
255
+ The framework supports Server-Sent Events (SSE) to enable real-time, one-way communication from the server to clients over HTTP.
256
+
257
+ ## Defining SSE Controllers
258
+
259
+ Use the `@Controller` decorator to define controllers with a `prefix` and optionally include sub-controllers. This allows modular organization of your API endpoints.
260
+
261
+ Example:
262
+
263
+ ```typescript
264
+ @Controller({
265
+ prefix: 'user',
266
+ controllers: [UserMetadata],
267
+ middlewares: [function UserGlobalUse() {}],
268
+ interceptor: (data, req, res) => {
269
+ return { data, intercepted: true };
270
+ },
271
+ })
272
+ export class User {}
273
+ ```
274
+
275
+ ## Injecting SSE Service
276
+
277
+ Use the `@InjectSSE` decorator in your controller methods to create and manage SSE connections. This service allows sending events to connected clients.
278
+
279
+ Example method using SSE:
280
+
281
+ ```typescript
282
+ import { InjectSSE } from 'quantum-flow/sse';
283
+
284
+ @Controller('user')
285
+ export class UserMetadata {
286
+ @GET('/subscribesse')
287
+ async subscribesse(@InjectSSE() sse) {
288
+ const client = sse.createConnection(res);
289
+ sse.sendToClient(client.id, {
290
+ event: 'welcome message',
291
+ data: { message: 'Connected to notifications' },
292
+ });
293
+ }
294
+ }
295
+ ```
296
+
297
+ ## SSE Event Decorators
298
+
299
+ The framework provides decorators to handle SSE connection lifecycle events:
300
+
301
+ - `@OnSSEConnection()`: Decorate a method to handle new SSE connections.
302
+ - `@OnSSEError()`: Decorate a method to handle SSE errors.
303
+ - `@OnSSEClose()`: Decorate a method to handle SSE connection closures.
304
+
305
+ Example usage:
306
+
307
+ ```typescript
308
+ import { OnSSEConnection, OnSSEError, OnSSEClose } from 'quantum-flow/sse';
309
+
310
+ @Controller('user')
311
+ export class User {
312
+ @OnSSEConnection()
313
+ async onsseconnection(@Request() req, @Response() res) {
314
+ console.log('SSE connection established');
315
+ return req.body;
316
+ }
317
+
318
+ @OnSSEError()
319
+ async onsseerror(@Request() req, @Response() res) {
320
+ console.log('SSE error occurred');
321
+ return req.body;
322
+ }
323
+
324
+ @OnSSEClose()
325
+ async onsseclose(@Request() req, @Response() res) {
326
+ console.log('SSE connection closed');
327
+ return req.body;
328
+ }
329
+ }
330
+ ```
331
+
332
+ ## Sending SSE Events
333
+
334
+ Use the injected SSE service to send events to clients. You can send events to all clients or specific clients by ID.
335
+
336
+ Example:
337
+
338
+ ```typescript
339
+ sse.sendToClient(clientId, { event: 'eventName', data: { key: 'value' } });
340
+ ```
341
+
342
+ ## Enabling SSE Support in Server
343
+
344
+ To enable SSE support, configure your HTTP server with the `sse: true` option and register controllers that use SSE.
345
+
346
+ Example server setup:
347
+
348
+ ```typescript
349
+ import { Server, HttpServer } from 'quantum-flow/http';
350
+ import { User, UserMetadata } from './controllers';
351
+
352
+ @Server({
353
+ controllers: [User, UserMetadata],
354
+ sse: { enabled: true },
355
+ })
356
+ class App {}
357
+
358
+ const server = new HttpServer(App);
359
+ server.listen().catch(console.error);
360
+ ```
361
+
362
+ ## Enabling static files
363
+
364
+ To enable serving static files, use statics option.
365
+
366
+ Example server setup:
367
+
368
+ ```typescript
369
+ import { Server, HttpServer } from 'quantum-flow/http';
370
+ import { User, UserMetadata } from './controllers';
371
+
372
+ @Server({
373
+ statics: [
374
+ {
375
+ path: path.join(__dirname, './public'),
376
+ options: {
377
+ index: 'index.html',
378
+ extensions: ['html', 'htm', 'css', 'js'],
379
+ maxAge: 86400,
380
+ immutable: true,
381
+ dotfiles: 'deny',
382
+ fallthrough: false,
383
+ setHeaders: (res, filePath, stats) => {
384
+ if (filePath.endsWith('.css')) {
385
+ res.setHeader('Content-Type', 'text/css');
386
+ }
387
+ },
388
+ },
389
+ },
390
+ ],
391
+ })
392
+ class App {}
393
+
394
+ const server = new HttpServer(App);
395
+ server.listen().catch(console.error);
396
+ ```
397
+
398
+ ## Custom plugins.
399
+
400
+ Use plugins to extend app with custom logic.
401
+
402
+ Example server setup:
403
+
404
+ ```typescript
405
+ import { Server, HttpServer } from 'quantum-flow/http';
406
+ import { User, UserMetadata } from './controllers';
407
+ import client from 'prom-client';
408
+
409
+ const register = new client.Registry();
410
+ client.collectDefaultMetrics({ register });
411
+
412
+ const httpRequestsTotal = new client.Counter({
413
+ name: 'http_requests_total',
414
+ help: 'Total number of HTTP requests',
415
+ labelNames: ['method', 'path', 'status'],
416
+ });
417
+
418
+ @Controller({ prefix: 'metrics' })
419
+ export class MetricsController {...}
420
+ @Server({...})
421
+ class App {}
422
+
423
+ const server = new HttpServer(App);
424
+ server.usePligun(metricsPlugin)
425
+ server.listen().catch(console.error);
426
+
427
+ // Lambda setup
428
+ let connection;
429
+ const dbConnectionPlugin: Plugin = {
430
+ name: 'metric',
431
+ beforeRequest: async(server) => {
432
+ if(!connection){
433
+ connection = await connetct(...)
434
+ }
435
+ },
436
+ hooks: {...},
437
+ };
438
+
439
+ const lambdaAdapter = new LambdaAdapter(Root);
440
+ lambdaAdapter.usePlugin(dbConnectionPlugin);
441
+
442
+ export const handler = lambdaAdapter.handler;
443
+ ```
444
+
445
+ ## GraphQL
446
+
447
+ Quantum Flow provides seamless GraphQL integration using the popular **TypeGraphQL** library. You can build fully typed GraphQL APIs with decorators, while the framework handles the server setup, subscriptions, and PubSub.
448
+
449
+ ### Installation
450
+
451
+ ```bash
452
+ npm install type-graphql graphql graphql-yoga @graphql-yoga/subscriptions
453
+ # or
454
+ yarn add type-graphql graphql graphql-yoga @graphql-yoga/subscriptions
455
+ ```
456
+
457
+ ```typescript
458
+ @Server({
459
+ controllers: [/* your REST controllers */],
460
+ graphql: { // GraphQL endpoint (default: '/graphql')
461
+ path: '/graphql', // Enable GraphQL Playground
462
+ resolvers: [UserResolver, MessageResolver], // Your resolver classes
463
+ pubSub: pubSub, // Your PubSub instance (required for subscriptions)
464
+ },
465
+ })
466
+ ```
467
+
468
+ ## Usage example
469
+
470
+ ```typescript
471
+ import { IsEmail, MinLength } from 'class-validator';
472
+ import {
473
+ Arg,
474
+ Ctx,
475
+ Field,
476
+ InputType,
477
+ Mutation,
478
+ ObjectType,
479
+ Query,
480
+ Resolver,
481
+ Root,
482
+ Subscription,
483
+ } from 'type-graphql';
484
+
485
+ import { createPubSub } from 'graphql-yoga';
486
+
487
+ export type PubSubChannels = {
488
+ NOTIFICATIONS: [{ id: string; userId: string; message: string }];
489
+ USER_UPDATED: [{ user: User }];
490
+ };
491
+
492
+ export const pubSub = createPubSub<PubSubChannels>();
493
+
494
+ @ObjectType()
495
+ export class User {
496
+ @Field()
497
+ id: string;
498
+ @Field()
499
+ name: string;
500
+ @Field()
501
+ email: string;
502
+ }
503
+
504
+ @InputType()
505
+ export class CreateUserInput {
506
+ @Field()
507
+ @MinLength(2)
508
+ name: string;
509
+ @Field()
510
+ @IsEmail()
511
+ email: string;
512
+ }
513
+
514
+ @Resolver()
515
+ export class UserResolver {
516
+ @Query(() => [User])
517
+ async users(): Promise<User[]> {
518
+ // pubSub.publish('USER_UPDATED', {...});
519
+ return [];
520
+ }
521
+
522
+ @Mutation(() => User)
523
+ async createUser(@Ctx() ctx: any, @Arg('input') input: CreateUserInput): Promise<User> {
524
+ const user = {
525
+ id: Date.now().toString(),
526
+ ...input,
527
+ };
528
+
529
+ return user;
530
+ }
531
+
532
+ @Subscription(() => User, {
533
+ topics: 'USER_UPDATED',
534
+ filter: ({ payload, args }) => true,
535
+ })
536
+ newUser(@Root() user: User): User {
537
+ return user;
538
+ }
539
+ }
540
+ ```
@@ -0,0 +1,54 @@
1
+ import 'reflect-metadata';
2
+ import { ControllerClass, ControllerConfig, ControllerMetadata, CORSConfig, ErorrHandler, InterceptorCB, IRequest, IResponse, MiddlewareCB, SanitizerConfig, SeeControllerHandlers, WsControllerHandlers } from './types/core';
3
+ /**
4
+ * Class decorator to define a controller with optional configuration.
5
+ *
6
+ * This decorator can be used with a string prefix or a configuration object.
7
+ * It sets up metadata for route prefix, middlewares, sub-controllers, and interceptors.
8
+ *
9
+ * It wraps all controller methods to handle errors gracefully by catching exceptions
10
+ * and returning a standardized error response.
11
+ *
12
+ * The decorated controller class is extended with methods to:
13
+ * - execute controller methods with proper context and error handling
14
+ * - retrieve controller methods metadata
15
+ * - handle incoming requests by matching routes, applying middlewares and interceptors,
16
+ * and returning appropriate responses
17
+ *
18
+ * @param config - Either a string representing the route prefix or a configuration object
19
+ * containing prefix, middlewares, sub-controllers, and interceptors.
20
+ * @param middlewares - Additional interceptors to apply at the controller level.
21
+ *
22
+ * @returns A class decorator function that enhances the controller class.
23
+ */
24
+ export declare function Controller(config: string | ControllerConfig, middlewares?: Array<InterceptorCB>): <T extends ControllerClass>(constructor: T) => {
25
+ new (...args: any[]): {
26
+ [x: string]: any;
27
+ ws?: WsControllerHandlers;
28
+ sse?: SeeControllerHandlers;
29
+ executeControllerMethod: (controller: import("./types/core").ControllerInstance, propertyName: string, request: IRequest, response: IResponse) => Promise<any>;
30
+ getControllerMethods: (controller: import("./types/core").ControllerInstance) => import("./types/core").ControllerMethods;
31
+ routePrefix?: string;
32
+ middlewares: MiddlewareCB[];
33
+ interceptor?: InterceptorCB;
34
+ subControllers: ControllerMetadata[];
35
+ errorHandler?: ErorrHandler;
36
+ cors?: CORSConfig;
37
+ sanitizers?: SanitizerConfig[];
38
+ handleRequest: (request: IRequest, response: IResponse) => Promise<boolean>;
39
+ lookupWS(): void;
40
+ lookupSSE(): void;
41
+ getSSEController(): {
42
+ instance: /*elided*/ any;
43
+ handlers: {
44
+ connection: any[];
45
+ close: any[];
46
+ error: any[];
47
+ };
48
+ };
49
+ getWSHandlers(type: string): any[];
50
+ getSSEHandlers(type: string): any[];
51
+ getWSTopics(): any;
52
+ typedHandlers: (handlers: any[], type: string) => any[];
53
+ };
54
+ } & T;