@ikonintegration/ikapi 4.0.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc.cjs +81 -0
  3. package/.github/workflows/npmpublish.yml +8 -19
  4. package/.github/workflows/prs.yml +12 -0
  5. package/README.md +89 -99
  6. package/dist/index.d.ts +16 -0
  7. package/dist/index.js +27 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/package-lock.json +11881 -0
  10. package/dist/package.json +81 -0
  11. package/dist/src/API/Request.d.ts +125 -0
  12. package/dist/src/API/Request.js +185 -0
  13. package/dist/src/API/Request.js.map +1 -0
  14. package/dist/src/API/Response.d.ts +188 -0
  15. package/dist/src/API/Response.js +270 -0
  16. package/dist/src/API/Response.js.map +1 -0
  17. package/dist/src/BaseEvent/DynamoTransaction.d.ts +70 -0
  18. package/dist/src/BaseEvent/DynamoTransaction.js +104 -0
  19. package/dist/src/BaseEvent/DynamoTransaction.js.map +1 -0
  20. package/dist/src/BaseEvent/EventProcessor.d.ts +58 -0
  21. package/dist/src/BaseEvent/EventProcessor.js +101 -0
  22. package/dist/src/BaseEvent/EventProcessor.js.map +1 -0
  23. package/dist/src/BaseEvent/Process.d.ts +50 -0
  24. package/dist/src/BaseEvent/Process.js +64 -0
  25. package/dist/src/BaseEvent/Process.js.map +1 -0
  26. package/dist/src/BaseEvent/StepTransaction.d.ts +23 -0
  27. package/dist/src/BaseEvent/StepTransaction.js +27 -0
  28. package/dist/src/BaseEvent/StepTransaction.js.map +1 -0
  29. package/dist/src/BaseEvent/Transaction.d.ts +149 -0
  30. package/dist/src/BaseEvent/Transaction.js +224 -0
  31. package/dist/src/BaseEvent/Transaction.js.map +1 -0
  32. package/dist/src/Cache/Redis.d.ts +29 -0
  33. package/dist/src/Cache/Redis.js +80 -0
  34. package/dist/src/Cache/Redis.js.map +1 -0
  35. package/dist/src/Cache/types.d.ts +31 -0
  36. package/dist/src/Cache/types.js +2 -0
  37. package/dist/src/Cache/types.js.map +1 -0
  38. package/dist/src/Config/Configuration.d.ts +123 -0
  39. package/dist/src/Config/Configuration.js +109 -0
  40. package/dist/src/Config/Configuration.js.map +1 -0
  41. package/dist/src/Config/EnvironmentVar.d.ts +74 -0
  42. package/dist/src/Config/EnvironmentVar.js +138 -0
  43. package/dist/src/Config/EnvironmentVar.js.map +1 -0
  44. package/dist/src/Crypto/Crypto.d.ts +45 -0
  45. package/dist/src/Crypto/Crypto.js +72 -0
  46. package/dist/src/Crypto/Crypto.js.map +1 -0
  47. package/dist/src/Database/Database.d.ts +21 -0
  48. package/dist/src/Database/Database.js +15 -0
  49. package/dist/src/Database/Database.js.map +1 -0
  50. package/dist/src/Database/DatabaseManager.d.ts +47 -0
  51. package/dist/src/Database/DatabaseManager.js +60 -0
  52. package/dist/src/Database/DatabaseManager.js.map +1 -0
  53. package/dist/src/Database/DatabaseTransaction.d.ts +101 -0
  54. package/dist/src/Database/DatabaseTransaction.js +126 -0
  55. package/dist/src/Database/DatabaseTransaction.js.map +1 -0
  56. package/dist/src/Database/index.d.ts +10 -0
  57. package/dist/src/Database/index.js +15 -0
  58. package/dist/src/Database/index.js.map +1 -0
  59. package/dist/src/Database/integrations/dynamo/DynamoDatabase.d.ts +35 -0
  60. package/dist/src/Database/integrations/dynamo/DynamoDatabase.js +59 -0
  61. package/dist/src/Database/integrations/dynamo/DynamoDatabase.js.map +1 -0
  62. package/dist/src/Database/integrations/kysely/KyselyDatabase.d.ts +66 -0
  63. package/dist/src/Database/integrations/kysely/KyselyDatabase.js +86 -0
  64. package/dist/src/Database/integrations/kysely/KyselyDatabase.js.map +1 -0
  65. package/dist/src/Database/integrations/kysely/KyselyTransaction.d.ts +70 -0
  66. package/dist/src/Database/integrations/kysely/KyselyTransaction.js +118 -0
  67. package/dist/src/Database/integrations/kysely/KyselyTransaction.js.map +1 -0
  68. package/dist/src/Database/integrations/pgsql/PostgresDatabase.d.ts +36 -0
  69. package/dist/src/Database/integrations/pgsql/PostgresDatabase.js +54 -0
  70. package/dist/src/Database/integrations/pgsql/PostgresDatabase.js.map +1 -0
  71. package/dist/src/Database/integrations/pgsql/PostgresTransaction.d.ts +63 -0
  72. package/dist/src/Database/integrations/pgsql/PostgresTransaction.js +61 -0
  73. package/dist/src/Database/integrations/pgsql/PostgresTransaction.js.map +1 -0
  74. package/dist/src/Database/types.d.ts +76 -0
  75. package/dist/src/Database/types.js +2 -0
  76. package/dist/src/Database/types.js.map +1 -0
  77. package/dist/src/Globals.d.ts +93 -0
  78. package/dist/src/Globals.js +99 -0
  79. package/dist/src/Globals.js.map +1 -0
  80. package/dist/src/Logger/Logger.d.ts +161 -0
  81. package/dist/src/Logger/Logger.js +299 -0
  82. package/dist/src/Logger/Logger.js.map +1 -0
  83. package/dist/src/Mailer/Mailer.d.ts +78 -0
  84. package/dist/src/Mailer/Mailer.js +182 -0
  85. package/dist/src/Mailer/Mailer.js.map +1 -0
  86. package/dist/src/Publisher/Publisher.d.ts +39 -0
  87. package/dist/src/Publisher/Publisher.js +77 -0
  88. package/dist/src/Publisher/Publisher.js.map +1 -0
  89. package/dist/src/Server/RouteResolver.d.ts +33 -0
  90. package/dist/src/Server/RouteResolver.js +100 -0
  91. package/dist/src/Server/RouteResolver.js.map +1 -0
  92. package/dist/src/Server/Router.d.ts +157 -0
  93. package/dist/src/Server/Router.js +32 -0
  94. package/dist/src/Server/Router.js.map +1 -0
  95. package/dist/src/Server/lib/ContainerServer.d.ts +42 -0
  96. package/dist/src/Server/lib/ContainerServer.js +66 -0
  97. package/dist/src/Server/lib/ContainerServer.js.map +1 -0
  98. package/dist/src/Server/lib/Server.d.ts +45 -0
  99. package/dist/src/Server/lib/Server.js +93 -0
  100. package/dist/src/Server/lib/Server.js.map +1 -0
  101. package/dist/src/Server/lib/container/GenericHandler.d.ts +9 -0
  102. package/dist/src/Server/lib/container/GenericHandler.js +82 -0
  103. package/dist/src/Server/lib/container/GenericHandler.js.map +1 -0
  104. package/dist/src/Server/lib/container/GenericHandlerEvent.d.ts +52 -0
  105. package/dist/src/Server/lib/container/GenericHandlerEvent.js +132 -0
  106. package/dist/src/Server/lib/container/GenericHandlerEvent.js.map +1 -0
  107. package/dist/src/Server/lib/container/HealthHandler.d.ts +9 -0
  108. package/dist/src/Server/lib/container/HealthHandler.js +19 -0
  109. package/dist/src/Server/lib/container/HealthHandler.js.map +1 -0
  110. package/dist/src/Server/lib/container/Proxy.d.ts +67 -0
  111. package/dist/src/Server/lib/container/Proxy.js +143 -0
  112. package/dist/src/Server/lib/container/Proxy.js.map +1 -0
  113. package/dist/src/Server/lib/container/Utils.d.ts +14 -0
  114. package/dist/src/Server/lib/container/Utils.js +37 -0
  115. package/dist/src/Server/lib/container/Utils.js.map +1 -0
  116. package/dist/src/Util/AsyncSingleton.d.ts +31 -0
  117. package/dist/src/Util/AsyncSingleton.js +83 -0
  118. package/dist/src/Util/AsyncSingleton.js.map +1 -0
  119. package/dist/src/Util/Utils.d.ts +61 -0
  120. package/dist/src/Util/Utils.js +147 -0
  121. package/dist/src/Util/Utils.js.map +1 -0
  122. package/dist/src/Validation/Validator.d.ts +17 -0
  123. package/dist/src/Validation/Validator.js +39 -0
  124. package/dist/src/Validation/Validator.js.map +1 -0
  125. package/dist/tsconfig.tsbuildinfo +1 -0
  126. package/index.ts +41 -0
  127. package/jest.config.ts +37 -0
  128. package/jest.smoke.config.ts +34 -0
  129. package/package.json +66 -22
  130. package/src/API/Request.ts +214 -0
  131. package/src/API/Response.ts +370 -0
  132. package/src/BaseEvent/DynamoTransaction.ts +175 -0
  133. package/src/BaseEvent/EventProcessor.ts +140 -0
  134. package/src/BaseEvent/Process.ts +78 -0
  135. package/src/BaseEvent/StepTransaction.ts +35 -0
  136. package/src/BaseEvent/Transaction.ts +323 -0
  137. package/src/Cache/Redis.ts +89 -0
  138. package/src/Cache/types.ts +33 -0
  139. package/src/Config/Configuration.ts +199 -0
  140. package/src/Config/EnvironmentVar.ts +142 -0
  141. package/src/Crypto/Crypto.ts +89 -0
  142. package/src/Database/Database.ts +22 -0
  143. package/src/Database/DatabaseManager.ts +67 -0
  144. package/src/Database/DatabaseTransaction.ts +170 -0
  145. package/src/Database/index.ts +27 -0
  146. package/src/Database/integrations/dynamo/DynamoDatabase.ts +58 -0
  147. package/src/Database/integrations/kysely/KyselyDatabase.ts +99 -0
  148. package/src/Database/integrations/kysely/KyselyTransaction.ts +172 -0
  149. package/src/Database/integrations/pgsql/PostgresDatabase.ts +56 -0
  150. package/src/Database/integrations/pgsql/PostgresTransaction.ts +87 -0
  151. package/src/Database/types.ts +85 -0
  152. package/src/Globals.ts +103 -0
  153. package/src/Logger/Logger.ts +363 -0
  154. package/src/Mailer/Mailer.ts +217 -0
  155. package/src/Publisher/Publisher.ts +96 -0
  156. package/src/Server/RouteResolver.ts +124 -0
  157. package/src/Server/Router.ts +200 -0
  158. package/src/Server/lib/ContainerServer.ts +65 -0
  159. package/src/Server/lib/Server.ts +109 -0
  160. package/src/Server/lib/container/GenericHandler.ts +76 -0
  161. package/src/Server/lib/container/GenericHandlerEvent.ts +154 -0
  162. package/src/Server/lib/container/HealthHandler.ts +11 -0
  163. package/src/Server/lib/container/Proxy.ts +172 -0
  164. package/src/Server/lib/container/Utils.ts +33 -0
  165. package/src/Util/AsyncSingleton.ts +86 -0
  166. package/src/Util/Utils.ts +131 -0
  167. package/src/Validation/Validator.ts +45 -0
  168. package/tests/API/Request.test.ts +273 -0
  169. package/tests/API/Response.test.ts +367 -0
  170. package/tests/BaseEvent/DynamoTransaction.test.ts +272 -0
  171. package/tests/BaseEvent/EventProcessor.test.ts +263 -0
  172. package/tests/BaseEvent/Process.test.ts +47 -0
  173. package/tests/BaseEvent/StepTransaction.test.ts +44 -0
  174. package/tests/BaseEvent/Transaction.test.ts +402 -0
  175. package/tests/Cache/Redis-client.test.ts +90 -0
  176. package/tests/Cache/Redis-cluster.test.ts +100 -0
  177. package/tests/Config/Config.test.ts +205 -0
  178. package/tests/Config/EnvironmentVar.test.ts +251 -0
  179. package/tests/Crypto/Crypto.test.ts +88 -0
  180. package/tests/Database/DatabaseManager.test.ts +79 -0
  181. package/tests/Database/integrations/dynamo/DynamoDatabase.test.ts +44 -0
  182. package/tests/Database/integrations/kysely/KyselyDatabase.test.ts +113 -0
  183. package/tests/Database/integrations/kysely/KyselyTransaction.test.ts +119 -0
  184. package/tests/Database/integrations/pg/PostgresDatabase.test.ts +76 -0
  185. package/tests/Database/integrations/pg/PostgresTransaction.test.ts +118 -0
  186. package/tests/Logger/Logger.test.ts +215 -0
  187. package/tests/Mailer/Mailer.test.ts +59 -0
  188. package/tests/Publisher/Publisher.test.ts +60 -0
  189. package/tests/Server/RouteResolver.test.ts +116 -0
  190. package/tests/Server/Router.test.ts +39 -0
  191. package/tests/Server/lib/ContainerServer.test.ts +531 -0
  192. package/tests/Server/lib/Server.test.ts +12 -0
  193. package/tests/Server/lib/container/GenericHandler.test.ts +131 -0
  194. package/tests/Server/lib/container/GenericHandlerEvent.test.ts +103 -0
  195. package/tests/Server/lib/container/HealthHandler.test.ts +30 -0
  196. package/tests/Server/lib/container/Proxy.test.ts +268 -0
  197. package/tests/Server/lib/container/Utils.test.ts +47 -0
  198. package/tests/Test.utils.ts +78 -0
  199. package/tests/Utils/Utils.test.ts +229 -0
  200. package/tests/Validation/Validator.test.ts +82 -0
  201. package/tsconfig.json +26 -0
  202. package/tsconfig.smoke.json +26 -0
  203. package/index.js +0 -88
  204. package/src/API/IKRequest.js +0 -52
  205. package/src/API/IKResponse.js +0 -119
  206. package/src/API/IKUtils.js +0 -51
  207. package/src/BaseEvent/IKProcess.js +0 -77
  208. package/src/BaseEvent/IKTransaction.js +0 -139
  209. package/src/Cache/Prototype/IKCache.js +0 -17
  210. package/src/Cache/Redis/IKRedis.js +0 -148
  211. package/src/Database/DDB/IKDB.js +0 -56
  212. package/src/Database/DDB/IKDBBaseExpression.js +0 -130
  213. package/src/Database/DDB/IKDBBaseQuery.js +0 -151
  214. package/src/Database/DDB/IKDBQueryBatchGet.js +0 -37
  215. package/src/Database/DDB/IKDBQueryBatchWrite.js +0 -64
  216. package/src/Database/DDB/IKDBQueryDelete.js +0 -34
  217. package/src/Database/DDB/IKDBQueryGet.js +0 -48
  218. package/src/Database/DDB/IKDBQueryPut.js +0 -87
  219. package/src/Database/DDB/IKDBQueryScan.js +0 -45
  220. package/src/Database/DDB/IKDBQueryTransactionalWrite.js +0 -69
  221. package/src/Database/DDB/IKDBQueryUpdate.js +0 -221
  222. package/src/Database/DDB/_IKDBQueryTransactionalRead.js +0 -46
  223. package/src/Database/PSQL/IKDB.js +0 -41
  224. package/src/Database/PSQL/IKDBBaseQuery.js +0 -26
  225. package/src/Database/Prototype/IKDB.js +0 -21
  226. package/src/Database/Prototype/IKDBBaseQuery.js +0 -14
  227. package/src/IKDynamoStream.js +0 -42
  228. package/src/IKEventProcessor.js +0 -42
  229. package/src/IKGlobals.js +0 -24
  230. package/src/IKRouter.js +0 -47
  231. package/src/IKStepTransaction.js +0 -14
  232. package/src/Logger/IKLogger.js +0 -136
  233. package/src/Mailer/IKMailer.js +0 -69
  234. package/src/Publisher/IKPublisher.js +0 -44
  235. package/src/Tracker/IKExecutionTracker.js +0 -79
  236. package/src/Validation/IKValidation.js +0 -76
@@ -0,0 +1,124 @@
1
+ import { AnyRoute, RouterConfig } from './Router.js'
2
+ import { HttpMethod } from '../API/Request.js'
3
+
4
+ /**
5
+ * Represents a collection of routes that can be added and resolved.
6
+ */
7
+ class Routes {
8
+ /**
9
+ * Represents the current route.
10
+ * @type {Route | undefined}
11
+ */
12
+ private current?: AnyRoute
13
+ /**
14
+ * Optional private variable that represents a collection of routes.
15
+ * @type {Routes | undefined}
16
+ */
17
+ private variable?: Routes
18
+ /**
19
+ * An object that maps string keys to Routes.
20
+ * @private
21
+ * @readonly
22
+ * @type {Object.<string, Routes>}
23
+ */
24
+ private readonly next: { [k: string]: Routes }
25
+ /**
26
+ * Initializes a new instance of the class.
27
+ * @constructor
28
+ */
29
+ constructor() {
30
+ this.next = {}
31
+ }
32
+
33
+ /**
34
+ * Adds a route to the routing system.
35
+ * @param {Route} route - The route to add.
36
+ * @param {string[]} parts - The parts of the route path.
37
+ * @returns None
38
+ * @throws {Error} If a duplicate route is detected.
39
+ */
40
+ public addRoute(route: AnyRoute, parts: string[]): void {
41
+ const first = parts.shift()
42
+ if (first) {
43
+ if (first.startsWith(':')) {
44
+ this.variable = this.variable || new Routes()
45
+ this.variable.addRoute(route, parts)
46
+ } else {
47
+ this.next[first] = this.next[first] || new Routes()
48
+ this.next[first].addRoute(route, parts)
49
+ }
50
+ } else {
51
+ if (this.current) throw new Error(`Duplicate route: ${route.method}: ${route.path}`)
52
+
53
+ this.current = route
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Resolves a route based on the given parts.
59
+ * @param {string[]} parts - An array of route parts.
60
+ * @returns {Route} The resolved route.
61
+ */
62
+ public resolveRoute(parts: string[]): AnyRoute | undefined {
63
+ const first = parts.shift()
64
+ if (first) {
65
+ if (first in this.next) {
66
+ return this.next[first].resolveRoute(parts)
67
+ }
68
+ return this.variable?.resolveRoute(parts)
69
+ }
70
+ return this.current
71
+ }
72
+ }
73
+
74
+ /**
75
+ * A class that resolves routes based on the provided configuration.
76
+ * @class RouteResolver
77
+ */
78
+ export default class RouteResolver {
79
+ /**
80
+ * An object that maps HTTP methods to their corresponding routes.
81
+ * @property {object} routes - The routes object.
82
+ * @property {Routes} routes.method - The routes for the specified HTTP method.
83
+ */
84
+ private routes: { [method in HttpMethod]?: Routes }
85
+
86
+ /**
87
+ * Constructs a new instance of the Router class with the given configuration.
88
+ * @param {RouterConfig} config - The configuration object for the router.
89
+ * @returns None
90
+ */
91
+ constructor(config: RouterConfig) {
92
+ this.routes = {}
93
+ this.buildRoutes(config)
94
+ }
95
+
96
+ /**
97
+ * Resolves a route based on the given HTTP method and path.
98
+ * @param {string} method - The HTTP method of the request.
99
+ * @param {string} path - The path of the request.
100
+ * @returns {Route | undefined} - The resolved route or undefined if no route is found.
101
+ */
102
+ public resolveRoute(method: HttpMethod, path: string): AnyRoute | undefined {
103
+ const parts = path.split('/').filter(p => p.length)
104
+ return this.routes[method]?.resolveRoute(parts)
105
+ }
106
+
107
+ /**
108
+ * Builds the routes for the router based on the given configuration.
109
+ * @param {RouterConfig} config - The router configuration object.
110
+ * @returns None
111
+ */
112
+ private buildRoutes(config: RouterConfig): void {
113
+ const addRoute = (path: string, route: AnyRoute) => {
114
+ const parts = path.split('/').filter(p => p.length)
115
+ this.routes[route.method] = this.routes[route.method] || new Routes()
116
+ this.routes[route.method]!.addRoute(route, parts)
117
+ }
118
+ for (const route of config.routes) {
119
+ if (Array.isArray(route.path)) {
120
+ for (const path of route.path) addRoute(path, route)
121
+ } else addRoute(route.path, route)
122
+ }
123
+ }
124
+ }
@@ -0,0 +1,200 @@
1
+ import { Server as HTTPServer } from 'http'
2
+
3
+ import express from 'express'
4
+ import { z } from 'zod'
5
+
6
+ import ContainerServer from './lib/ContainerServer.js'
7
+ import Server from './lib/Server.js'
8
+ import { HttpMethod } from '../API/Request.js'
9
+ import { ResponseErrorType } from '../API/Response.js'
10
+ import Transaction, {
11
+ TransactionConfig,
12
+ TransactionExecution,
13
+ StringMap,
14
+ } from '../BaseEvent/Transaction.js'
15
+ import Utils from '../Util/Utils.js'
16
+
17
+ /**
18
+ * Represents a route in an API.
19
+ * @template InputType - The type of the input data for the route.
20
+ * @template OutputType - The type of the output data for the route.
21
+ * @property {string} path - The path of the route.
22
+ * @property {string} method - The HTTP method of the route.
23
+ * @property {TransactionExecution<Transaction<InputType, OutputType | ResponseErrorType>, OutputType | ResponseErrorType>} handler - The handler function for the route.
24
+ * @property {?z.ZodObject<any> | z.ZodUnion<any> | z.ZodIntersection<any, any>}[inputSchema] - The input schema for validating the input data.
25
+ * @property {?z.ZodObject<any> | z.ZodUnion<any> | z.ZodIntersection<any, any>}[pathSchema] - The path schema for validating the path data.
26
+ * @property {?z.ZodObject<any> | z.ZodUnion<any> | z.ZodIntersection<any, any>}[querySchema] - The query schema for validating the query data.
27
+ */
28
+ export interface Route<
29
+ InputType = never,
30
+ OutputType = never,
31
+ PathParamsType = StringMap,
32
+ QueryParamsType = StringMap,
33
+ > {
34
+ /**
35
+ * Represents a file path as a string.
36
+ * @param {string} path - The file path.
37
+ * @returns None
38
+ */
39
+ path: string | string[]
40
+ /**
41
+ * Represents the method used in an API request.
42
+ * @type {string}
43
+ */
44
+ method: HttpMethod
45
+ /* If you are here to know why implementing this method
46
+ does not auto infer the param type, check long discussion on TS
47
+ - https://github.com/Microsoft/TypeScript/issues/1373
48
+ - https://github.com/microsoft/TypeScript/issues/23911#issuecomment-1351020050 (proposed solution)
49
+ - https://github.com/microsoft/TypeScript/issues/10570
50
+ */
51
+ /**
52
+ * Represents a handler for executing a transaction with the given input type and output type.
53
+ * @param {Transaction<InputType, OutputType | ResponseErrorType, PathParamsType, QueryParamsType>} transaction - The transaction to execute.
54
+ * @param {OutputType | ResponseErrorType} - The output type or response error type of the transaction.
55
+ */
56
+ handler: TransactionExecution<
57
+ Transaction<InputType, OutputType | ResponseErrorType, never, PathParamsType, QueryParamsType>,
58
+ OutputType | ResponseErrorType
59
+ >
60
+ /**
61
+ * An optional input schema for validating the structure of the input data.
62
+ *
63
+ * @type {?z.ZodObject<any> | z.ZodUnion<any> | z.ZodIntersection<any, any>}
64
+ */
65
+ inputSchema?: z.ZodObject<any> | z.ZodUnion<any> | z.ZodIntersection<any, any>
66
+
67
+ /**
68
+ * An optional input schema for validating the structure of the path params.
69
+ *
70
+ * @type {?z.ZodObject<any> | z.ZodUnion<any> | z.ZodIntersection<any, any>}
71
+ */
72
+ pathSchema?: z.ZodObject<any> | z.ZodUnion<any> | z.ZodIntersection<any, any>
73
+
74
+ /**
75
+ * An optional input schema for validating the structure of the query params.
76
+ *
77
+ * @type {?z.ZodObject<any> | z.ZodUnion<any> | z.ZodIntersection<any, any>}
78
+ */
79
+ querySchema?: z.ZodObject<any> | z.ZodUnion<any> | z.ZodIntersection<any, any>
80
+
81
+ /**
82
+ * An optional openApi object with extra metadata for docs generation.
83
+ */
84
+ openApi?: {
85
+ // Descriptive
86
+ summary: string
87
+ description: string
88
+ tags?: string[]
89
+ // Response
90
+ outputSchema?: z.ZodObject<any> | z.ZodUnion<any> | z.ZodIntersection<any, any> | z.ZodType<any>
91
+ successCode?: number /* defaults to 200 */
92
+ // Sec
93
+ security?: {
94
+ [key: string]: string[] | never[]
95
+ }[]
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Represents a route that can accept any type for its parameters and return values.
101
+ */
102
+ export type AnyRoute = Route<any | never, any | never, any | never, any | never>
103
+
104
+ /**
105
+ * Represents the configuration options for a router.
106
+ * @typedef {TransactionConfig & {
107
+ * routes: Route[]
108
+ * port?: number
109
+ * timeout?: number
110
+ * cors?: {
111
+ * origin?: string | string[]
112
+ * headers?: string[]
113
+ * allowCredentials?: boolean
114
+ * }
115
+ * healthCheckRoute?: string
116
+ * }} RouterConfig
117
+ * @property {Route[]} routes - The routes to be configured in the router.
118
+ * @property {number} [port] - The port number to listen on. If not specified, a default port will be used.
119
+ * @property {number} [timeout] - The timeout duration for requests in milliseconds. If not specified, a default timeout will be
120
+ */
121
+ export type RouterConfig = TransactionConfig & {
122
+ /**
123
+ * An array of route objects representing the available routes in the application.
124
+ * @type {Route[]}
125
+ */
126
+ routes: AnyRoute[]
127
+ /**
128
+ * The port number for the server to listen on.
129
+ * @type {number | undefined}
130
+ */
131
+ port?: number
132
+ /**
133
+ * Optional timeout value in milliseconds.
134
+ * @type {number | undefined}
135
+ */
136
+ timeout?: number
137
+ /**
138
+ * Configuration options for Cross-Origin Resource Sharing (CORS).
139
+ * @property {string | string[]} [origin] - The allowed origin(s) for CORS requests.
140
+ * @property {string[]} [headers] - The allowed headers for CORS requests.
141
+ * @property {boolean} [allowCredentials] - Whether to allow credentials (cookies, HTTP authentication, and client-side SSL certificates) to be sent in CORS requests.
142
+ */
143
+ cors?: {
144
+ origin?: string | string[]
145
+ headers?: string[]
146
+ allowCredentials?: boolean
147
+ }
148
+ /**
149
+ * The route for the health check endpoint.
150
+ * @type {string | undefined}
151
+ */
152
+ healthCheckRoute?: string
153
+ /**
154
+ * Optional hook function that sets up the container with the provided HTTP server and Express app.
155
+ * @param {HTTPServer} server - The HTTP server instance.
156
+ * @param {express.Express} app - The Express application instance.
157
+ * @returns {Promise<void>} A promise that resolves when the setup is complete.
158
+ */
159
+ containerSetupHook?: (server: HTTPServer, app: express.Express) => Promise<void>
160
+ }
161
+
162
+ /**
163
+ * Represents a router that handles routing logic for a web application.
164
+ */
165
+ export default class Router {
166
+ /**
167
+ * The configuration object for the router.
168
+ */
169
+ private readonly config: RouterConfig
170
+ /**
171
+ * The private readonly server instance.
172
+ */
173
+ private readonly server: Server
174
+
175
+ /**
176
+ * Constructs a new instance of the Router class.
177
+ * @param {RouterConfig} config - The configuration object for the router.
178
+ * @returns None
179
+ */
180
+ constructor(config: RouterConfig) {
181
+ this.config = config
182
+ this.server = this.isContainer() ? new ContainerServer(config) : new Server(config)
183
+ }
184
+
185
+ /**
186
+ * Retrieves the export function from the server.
187
+ * @returns {CallableFunction} The export function from the server.
188
+ */
189
+ public getExport(): CallableFunction {
190
+ return this.server.getExport()
191
+ }
192
+
193
+ /**
194
+ * Checks if the current element is a container.
195
+ * @returns {boolean} - True if the element is a container, false otherwise.
196
+ */
197
+ private isContainer(): boolean {
198
+ return Utils.isHybridlessContainer()
199
+ }
200
+ }
@@ -0,0 +1,65 @@
1
+ import Proxy from './container/Proxy.js'
2
+ import Server from './Server.js'
3
+ import { RouterConfig } from '../Router.js'
4
+
5
+ /**
6
+ * Represents a server container that extends the Server class and handles serverless events.
7
+ */
8
+ export default class ContainerServer extends Server {
9
+ /**
10
+ * The proxy object used for handling requests and responses.
11
+ * @type {Proxy}
12
+ * @protected
13
+ */
14
+ protected readonly proxy: Proxy
15
+
16
+ /**
17
+ * Constructs a new instance of the Router class.
18
+ * @param {RouterConfig} config - The configuration object for the router.
19
+ * @returns None
20
+ */
21
+ constructor(config: RouterConfig) {
22
+ super(config)
23
+ this.proxy = new Proxy(config, this.handleServerlessEvent.bind(this))
24
+ this.listenProcessEvents()
25
+ }
26
+
27
+ /**
28
+ * Returns a callable function that can be used to export data.
29
+ * @returns {CallableFunction} - A callable function that can be used to export data.
30
+ */
31
+ public getExport(): CallableFunction {
32
+ // start server socket
33
+ this.start()
34
+ // return empty function, we are all done
35
+ return () => {}
36
+ }
37
+
38
+ /**
39
+ * Starts the application by loading the proxy.
40
+ * @returns {Promise<void>} - A promise that resolves when the proxy is loaded.
41
+ */
42
+ public async start() {
43
+ await this.proxy.load()
44
+ }
45
+
46
+ /**
47
+ * Stops the execution of the program and unloads the proxy.
48
+ * @param {any} [err] - Optional error object to pass to the unload method.
49
+ * @returns {Promise<void>} - A promise that resolves once the proxy is unloaded.
50
+ */
51
+ public async stop(err?: any) {
52
+ await this.proxy.unload(err)
53
+ }
54
+
55
+ /**
56
+ * Listens for process events and handles them accordingly.
57
+ * @private
58
+ * @returns None
59
+ */
60
+ private listenProcessEvents() {
61
+ // start process listeners
62
+ process.on('unhandledRejection', this.stop.bind(this)) // listen to exceptions
63
+ process.on('SIGINT', this.stop.bind(this)) // listen on SIGINT signal and gracefully stop the server
64
+ }
65
+ }
@@ -0,0 +1,109 @@
1
+ import { APIGatewayProxyEvent, Context } from 'aws-lambda'
2
+ import { pathToRegexp } from 'path-to-regexp'
3
+
4
+ import Request from '../../API/Request.js'
5
+ import Response, { ResponseErrorType } from '../../API/Response.js'
6
+ import Transaction, { StringMap } from '../../BaseEvent/Transaction.js'
7
+ import Validator from '../../Validation/Validator.js'
8
+ import { RouterConfig } from '../Router.js'
9
+ import RouteResolver from '../RouteResolver.js'
10
+
11
+ /**
12
+ * Represents a server that handles serverless events and routes them to appropriate handlers.
13
+ */
14
+ export default class Server {
15
+ /**
16
+ * The configuration object for the router.
17
+ * @readonly
18
+ * @type {RouterConfig}
19
+ */
20
+ protected readonly config: RouterConfig
21
+ /**
22
+ * A protected property that holds a RouteResolver object.
23
+ * The RouteResolver is responsible for resolving routes and returning the appropriate response.
24
+ * @type {RouteResolver}
25
+ */
26
+ protected readonly routeResolver: RouteResolver
27
+
28
+ /**
29
+ * Constructs a new instance of the Router class.
30
+ * @param {RouterConfig} config - The configuration object for the router.
31
+ * @returns None
32
+ */
33
+ constructor(config: RouterConfig) {
34
+ this.config = config
35
+ this.routeResolver = new RouteResolver(config)
36
+ }
37
+
38
+ /**
39
+ * Returns a callable function that is bound to the `handleServerlessEvent` method of the current object.
40
+ * @returns {CallableFunction} - A callable function that is bound to the `handleServerlessEvent` method.
41
+ */
42
+ public getExport(): CallableFunction {
43
+ return this.handleServerlessEvent.bind(this)
44
+ }
45
+
46
+ /**
47
+ * Handles a serverless event by executing a transaction and resolving the route based on the event.
48
+ * @param {APIGatewayProxyEvent} event - The serverless event object.
49
+ * @param {Context} context - The serverless context object.
50
+ * @returns None
51
+ */
52
+ public async handleServerlessEvent(event: APIGatewayProxyEvent, context: Context) {
53
+ // init transaction
54
+ await new Transaction<never, ResponseErrorType, never, StringMap, StringMap>(
55
+ event,
56
+ context,
57
+ this.config
58
+ ).execute(async transaction => {
59
+ const request = transaction.request
60
+ const route = this.routeResolver.resolveRoute(request.getMethod(), request.getPath())
61
+ if (route) {
62
+ transaction.logger.log('Router accepted route:', route.path)
63
+ // Validate input
64
+ if (route.inputSchema) {
65
+ const validationResp = Validator.validateSchema(request.getBody(), route.inputSchema)
66
+ if (validationResp && validationResp instanceof Response) return validationResp
67
+ }
68
+
69
+ // Validate query
70
+ if (route.querySchema) {
71
+ const validationResp = Validator.validateSchema(
72
+ request.getQueryParams(),
73
+ route.querySchema
74
+ )
75
+ if (validationResp && validationResp instanceof Response) return validationResp
76
+ }
77
+
78
+ // parse before validating
79
+ for (const path of Array.isArray(route.path) ? route.path : [route.path]) {
80
+ this.parsePathParams(request, path)
81
+ }
82
+
83
+ // Validate path
84
+ if (route.pathSchema) {
85
+ const validationResp = Validator.validateSchema(request.getPathParams(), route.pathSchema)
86
+ if (validationResp && validationResp instanceof Response) return validationResp
87
+ }
88
+
89
+ // Continue to route handler
90
+ return await route.handler(transaction)
91
+ }
92
+ //No route found :/
93
+ return new Response(404, { err: 'Route not found!' })
94
+ })
95
+ }
96
+
97
+ /**
98
+ * Parses the path parameters from the request URL based on the given route path.
99
+ * @param {Request<any>} req - The request object.
100
+ * @param {string} routePath - The route path pattern to match against.
101
+ * @returns None
102
+ */
103
+ private parsePathParams(req: Request<any, any, any>, routePath: string) {
104
+ const path = req.getPath()
105
+ const regex = pathToRegexp(routePath)
106
+ const result = regex.regexp.exec(path)
107
+ if (result) req.setFixedPathParams(regex.keys, result)
108
+ }
109
+ }
@@ -0,0 +1,76 @@
1
+ import { Request, Response } from 'express'
2
+
3
+ import GenericHandlerEvent, { GenericHandlerEventResponse } from './GenericHandlerEvent.js'
4
+ import Globals from '../../../Globals.js'
5
+ import Utils from '../../../Util/Utils.js'
6
+ import Server from '../Server.js'
7
+
8
+ /**
9
+ * Creates an async function that handles serverless events and sends a response.
10
+ * @param {Server['handleServerlessEvent']} serverlessHandler - The serverless handler function.
11
+ * @returns {Function} - An async function that handles the request and sends a response.
12
+ */
13
+ export default (serverlessHandler: Server['handleServerlessEvent']) => {
14
+ /**
15
+ * Handles an HTTP request by invoking a serverless function and processing the response.
16
+ * @param {Request} request - The HTTP request object.
17
+ * @param {Response} res - The HTTP response object.
18
+ * @returns None
19
+ */
20
+ return async (request: Request, res: Response) => {
21
+ const startTime = Date.now()
22
+ try {
23
+ // Generate event with request stuff (http to serverless translation)
24
+ const event = new GenericHandlerEvent(request, serverlessHandler)
25
+ // Invoke
26
+ const invokationResp = await event.invoke()
27
+ // Respond
28
+ processServerlessResponse(invokationResp, res)
29
+ } catch (e) {
30
+ console.error('[Proxy] - Exception during execution!', e)
31
+ console.error(e.stack)
32
+ res.status(Globals.Resp_STATUSCODE_EXCEPTION).json({
33
+ ...e,
34
+ err: Globals.Resp_MSG_EXCEPTION,
35
+ errCode: Globals.Resp_CODE_EXCEPTION,
36
+ })
37
+ }
38
+ console.debug(`[Proxy] - Request took ${Date.now() - startTime}ms`)
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Processes the response received from a serverless function invocation and sends the appropriate response back to the client.
44
+ * @param {GenericHandlerEventResponse} invokation - The response object received from the serverless function invocation.
45
+ * @param {Response} res - The response object to send back to the client.
46
+ * @returns The response object to send back to the client.
47
+ */
48
+ const processServerlessResponse = (invokation: GenericHandlerEventResponse, res: Response) => {
49
+ // translate answer to http layer
50
+ if (invokation && invokation.err) {
51
+ // err came
52
+ return res.json({ err: invokation.err }).status(400)
53
+ } else if (!invokation || !invokation.data) {
54
+ // invalid response came
55
+ return res.status(Globals.Resp_STATUSCODE_INVALIDRESP).json({
56
+ err: Globals.Resp_MSG_INVALIDRESP,
57
+ errCode: Globals.Resp_CODE_INVALIDRESP,
58
+ })
59
+ } else {
60
+ // Check for headers
61
+ if (invokation.data.headers) {
62
+ for (const hKey of Object.keys(invokation.data.headers)) {
63
+ res.header(hKey, invokation.data.headers[hKey])
64
+ }
65
+ }
66
+ //
67
+ let response = res.status(invokation.data.statusCode)
68
+ // check for stream
69
+ if (invokation.data?.body?.pipe) {
70
+ invokation.data.body.pipe(response)
71
+ } else {
72
+ response = response.json(Utils.parseObjectNullIfEmpty(invokation.data.body) || {})
73
+ }
74
+ return response
75
+ }
76
+ }