@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,78 @@
1
+ import { TransactionConfig } from './Transaction.js'
2
+ import Logger from '../Logger/Logger.js'
3
+ import Publisher from '../Publisher/Publisher.js'
4
+
5
+ /**
6
+ * A type that represents a modified version of the TransactionConfig type, excluding the 'throwOnErrors' and 'syncReturn' properties.
7
+ */
8
+ export type ProcessConfig = Omit<TransactionConfig, 'throwOnErrors' | 'syncReturn'>
9
+
10
+ /**
11
+ * Represents a long-running process that executes a given function at a specified interval.
12
+ */
13
+ export default class Process {
14
+ /**
15
+ * Private member variable representing the interval value.
16
+ * @type {number}
17
+ * @private
18
+ */
19
+ private interval: number
20
+ /**
21
+ * A logger object used for logging messages, errors, and other information.
22
+ * @readonly
23
+ */
24
+ public readonly logger: Logger
25
+ /**
26
+ * The publisher of the content.
27
+ */
28
+ public readonly publisher: Publisher
29
+ /**
30
+ * A reference to the NodeJS.Timeout object representing the interval timer.
31
+ */
32
+ public timeout: NodeJS.Timeout
33
+
34
+ /**
35
+ * Constructs a new instance of the LongRunningProcess class.
36
+ * @param {ProcessConfig} config - The configuration object for the process.
37
+ * @param {number} interval - The interval at which the process should run.
38
+ * @returns None
39
+ */
40
+ constructor(config: ProcessConfig, interval: number) {
41
+ this.interval = interval
42
+ this.logger = new Logger(config.logger, 'long-running-process')
43
+ this.publisher = new Publisher(config.publisher)
44
+ }
45
+
46
+ /**
47
+ * Executes the provided execution function at a specified interval.
48
+ * @param {Function} executionFunc - The function to execute.
49
+ * @returns None
50
+ */
51
+ public async execute(executionFunc) {
52
+ this.logger.debug('Starting main process code')
53
+ //Program loop
54
+ this.timeout = setInterval(async () => {
55
+ await this.iexecute(executionFunc)
56
+ }, this.interval)
57
+ }
58
+
59
+ /**
60
+ * Executes the given execution function asynchronously and handles any exceptions that occur.
61
+ * @param {Function} executionFunc - The function to execute.
62
+ * @returns {boolean} - Returns true if the execution failed, false otherwise.
63
+ */
64
+ private async iexecute(executionFunc) {
65
+ let executionFailed = true //failed til we say no!
66
+ // safe execution handler
67
+ try {
68
+ // Execute
69
+ await executionFunc(this)
70
+ executionFailed = false
71
+ } catch (e) {
72
+ /* EXECUTION FAIL */
73
+ this.logger.error('Exception when executing main process code. Rolling back DB!')
74
+ this.logger.exception(e)
75
+ }
76
+ return executionFailed
77
+ }
78
+ }
@@ -0,0 +1,35 @@
1
+ import type { Context } from 'aws-lambda'
2
+
3
+ import Transaction, { TransactionConfig } from './Transaction.js'
4
+ import Response, { ResponseErrorType } from '../API/Response.js'
5
+
6
+ /**
7
+ * Represents a step transaction that extends the Transaction class.
8
+ */
9
+ export default class StepTransaction extends Transaction {
10
+ /**
11
+ * Constructor for creating a new Transaction object.
12
+ * @param {any} event - The event object.
13
+ * @param {Context} context - The context object.
14
+ * @param {TransactionConfig} [config] - Optional configuration for the transaction.
15
+ * @returns None
16
+ */
17
+ constructor(event: any, context: Context, config?: TransactionConfig) {
18
+ super(event, context, {
19
+ syncReturn: true,
20
+ throwOnErrors: true,
21
+ // allow override
22
+ ...(config || {}),
23
+ })
24
+ }
25
+
26
+ /**
27
+ * Generates an error response with the provided error message and error code.
28
+ * @param {string} error - The error message to include in the response.
29
+ * @param {string} code - The error code associated with the error.
30
+ * @returns {Response<ResponseErrorType>} - The error response object.
31
+ */
32
+ protected getErrorResponse(error: string, code: string): Response<ResponseErrorType> {
33
+ return Response.StepFunctionResponse({ err: error, errCode: code }, 400)
34
+ }
35
+ }
@@ -0,0 +1,323 @@
1
+ import type { APIGatewayEvent, Context, DynamoDBStreamEvent, SQSEvent } from 'aws-lambda'
2
+
3
+ import Request from '../API/Request.js'
4
+ import Response, { ResponseErrorType } from '../API/Response.js'
5
+ import { DatabaseManager } from '../Database/DatabaseManager.js'
6
+ import { DatabaseTransaction } from '../Database/DatabaseTransaction.js'
7
+ import type {
8
+ DatabaseImplType,
9
+ DatabaseTransactionType,
10
+ DatabaseType,
11
+ DbConfig,
12
+ } from '../Database/types.js'
13
+ import Globals from '../Globals.js'
14
+ import Logger, { LoggerConfig } from '../Logger/Logger.js'
15
+ import Publisher, { PublisherConfig } from '../Publisher/Publisher.js'
16
+
17
+ /**
18
+ * Defines a type for executing a transaction and returning a promise with the response.
19
+ * @param {TransactionType} transaction - The transaction to execute.
20
+ * @returns A promise that resolves to the response of the transaction.
21
+ */
22
+ export type TransactionExecution<TransactionType, ResponseInnerType, MiscRespType = never> = (
23
+ transaction: TransactionType
24
+ ) => Promise<Response<ResponseInnerType> | Response<ResponseErrorType> | MiscRespType>
25
+
26
+ /**
27
+ * Represents the configuration options for a transaction.
28
+ * @typedef {Object} TransactionConfig
29
+ * @property {boolean} [throwOnErrors] - Whether to throw an error if there are any errors during the transaction.
30
+ * @property {boolean} [syncReturn] - Whether to return the result of the transaction synchronously.
31
+ * @property {boolean} [skipCleanTmp] - Whether to skip cleaning the temporary folder, in EventProcessor.
32
+ * @property {LoggerConfig} [logger] - The configuration options for the logger.
33
+ * @property {PublisherConfig} [publisher] - The configuration options for the publisher.
34
+ */
35
+ export type TransactionConfig = {
36
+ throwOnErrors?: boolean
37
+ syncReturn?: boolean
38
+ skipCleanTmp?: boolean
39
+ //
40
+ logger?: LoggerConfig
41
+ publisher?: PublisherConfig
42
+ }
43
+
44
+ /**
45
+ * Represents a simple string dictionary with string values
46
+ */
47
+ export type StringMap = { [key: string]: string | null }
48
+
49
+ /**
50
+ * Represents a transaction object that handles the execution of a request and manages the response.
51
+ * @template InputType - The type of the input data for the transaction.
52
+ * @template ResponseInnerType - The type of the inner response data for the transaction.
53
+ * @template MiscRespType - The type of miscellaneous response data for the transaction.
54
+ */
55
+ export default class Transaction<
56
+ InputType = never,
57
+ ResponseInnerType = null,
58
+ MiscRespType = never,
59
+ PathParamsType = StringMap,
60
+ QueryParamsType = StringMap,
61
+ > {
62
+ /**
63
+ * The instance of the DatabaseManager class used for managing the database.
64
+ */
65
+ private databaseManager: DatabaseManager = DatabaseManager.INSTANCE
66
+ /**
67
+ * An array of database transactions.
68
+ * @type {DatabaseTransaction[]}
69
+ */
70
+ private transactions: DatabaseTransaction[] = []
71
+ /**
72
+ * Represents an event object.
73
+ * @private
74
+ * @type {any}
75
+ */
76
+ private event: any
77
+ /**
78
+ * The context object for the current instance.
79
+ */
80
+ private context: Context
81
+ /**
82
+ * The response object that can hold different types of responses.
83
+ * @type {Response<ResponseInnerType | ResponseErrorType> | MiscRespType | null}
84
+ */
85
+ private response: Response<ResponseInnerType | ResponseErrorType> | MiscRespType
86
+ /**
87
+ * A private boolean variable indicating whether the return value of a synchronous operation
88
+ * should be synchronized with the calling thread.
89
+ */
90
+ private syncReturn: boolean
91
+ /**
92
+ * A boolean flag indicating whether retroactive errors are enabled or not.
93
+ * @private
94
+ */
95
+ private retrowErrors: boolean
96
+ /**
97
+ * A logger object used for logging messages, errors, and other information.
98
+ * @readonly
99
+ */
100
+ public readonly logger: Logger
101
+ /**
102
+ * The request object for making a request of type InputType.
103
+ * @readonly
104
+ */
105
+ public readonly request: Request<InputType, PathParamsType, QueryParamsType>
106
+ /**
107
+ * The publisher of the content.
108
+ */
109
+ public readonly publisher: Publisher
110
+ /**
111
+ * A function that acts as a response proxy for a given response object.
112
+ * @param {Response<ResponseInnerType>} response - The response object to proxy.
113
+ * @returns A promise that resolves to void.
114
+ */
115
+ public responseProxy: ((response: Response<ResponseInnerType>) => Promise<void>) | null
116
+
117
+ /**
118
+ * Constructs a new instance of the Transaction class.
119
+ * @param {APIGatewayEvent | SQSEvent | DynamoDBStreamEvent} event - The event object passed to the Lambda function.
120
+ * @param {Context} context - The context object passed to the Lambda function.
121
+ * @param {TransactionConfig} [config] - Optional configuration object for the transaction.
122
+ * @returns None
123
+ */
124
+ constructor(
125
+ event: APIGatewayEvent | SQSEvent | DynamoDBStreamEvent,
126
+ context: Context,
127
+ config?: TransactionConfig
128
+ ) {
129
+ const transactionId = context.awsRequestId
130
+ ? context.awsRequestId
131
+ : (<APIGatewayEvent>event).requestContext
132
+ ? (<APIGatewayEvent>event).requestContext.requestId
133
+ : 'unknown'
134
+ // transaction ctx
135
+ this.event = event
136
+ this.context = context
137
+ // when set, this will be called with the response context right before calling the context suceed/fail - useful for writing the resp for example.
138
+ this.responseProxy = null
139
+ // transaction flags
140
+ this.syncReturn = !!config?.syncReturn
141
+ this.retrowErrors = !!config?.throwOnErrors /* retrow internal errors */
142
+ // components
143
+ this.logger = new Logger(config?.logger, transactionId)
144
+ this.request = new Request<InputType, PathParamsType, QueryParamsType>(
145
+ this.event,
146
+ this.context,
147
+ this.logger
148
+ )
149
+ this.publisher = new Publisher(config?.publisher)
150
+ }
151
+
152
+ /**
153
+ * Executes a transaction using the provided execution function and returns a promise
154
+ * that resolves to the response or miscellaneous response.
155
+ * @param {TransactionExecution<Transaction<InputType, ResponseInnerType, MiscRespType>, ResponseInnerType, MiscRespType>} executionFunc - The execution function to be executed.
156
+ * @returns {Promise<Response<ResponseInnerType | ResponseErrorType> | MiscRespType>} - A promise that resolves to the response or miscellaneous response.
157
+ */
158
+ public async execute(
159
+ executionFunc: TransactionExecution<
160
+ Transaction<InputType, ResponseInnerType, MiscRespType, PathParamsType, QueryParamsType>,
161
+ ResponseInnerType,
162
+ MiscRespType
163
+ >
164
+ ): Promise<Response<ResponseInnerType | ResponseErrorType> | MiscRespType | null> {
165
+ await this.executeLoggerFlush(async () => {
166
+ await this.executeDBTransactions(async () => {
167
+ return await this.iexecute(executionFunc)
168
+ })
169
+ })
170
+ // return raw response if sync return is requested
171
+ if (this.syncReturn) return this.response
172
+ // allow request to async succeed through lambda context
173
+ return null
174
+ }
175
+
176
+ /**
177
+ * Executes a transaction using the provided execution function and handles the response.
178
+ * @param {TransactionExecution<Transaction<InputType, ResponseInnerType, MiscRespType>, ResponseInnerType, MiscRespType>} executionFunc - The function to execute the transaction.
179
+ * @returns {Promise<boolean>} - A promise that resolves to a boolean indicating whether the execution failed or not.
180
+ */
181
+ private async iexecute(
182
+ executionFunc: TransactionExecution<
183
+ Transaction<InputType, ResponseInnerType, MiscRespType, PathParamsType, QueryParamsType>,
184
+ ResponseInnerType,
185
+ MiscRespType
186
+ >
187
+ ): Promise<boolean> {
188
+ let executionFailed = true //failed til we say no!
189
+ //safe execution handler
190
+ try {
191
+ //Execute
192
+ this.logger.debug('Starting main request code')
193
+ this.response = await executionFunc(this)
194
+ //Answer client
195
+ if (this.response && this.response instanceof Response) {
196
+ await this.response.build(this.context, this, this.syncReturn)
197
+ executionFailed = !!(this.response.getBody() && this.response.getBody()['rollback'])
198
+ } else if (this.syncReturn && this.response) {
199
+ this.logger.log('Sync return with different response object')
200
+ this.logger.debug(this.response)
201
+ executionFailed = false
202
+ } else {
203
+ this.response = this.getErrorResponse(
204
+ Globals.ErrorResponseInvalidServerResponse,
205
+ Globals.ErrorCode_APIError
206
+ )
207
+ await this.response.build(this.context, this, this.syncReturn)
208
+ this.logger.error('Invalid response object from main request code.')
209
+ }
210
+ } catch (e) {
211
+ /*EXECUTION FAIL*/
212
+ this.logger.error('Exception when executing main request code.')
213
+ this.logger.exception(e)
214
+ //retrow?
215
+ if (this.retrowErrors) throw e
216
+ //envelope exception?
217
+ this.response = this.getErrorResponse(
218
+ Globals.ErrorResponseUnhandledError,
219
+ Globals.ErrorCode_APIError
220
+ )
221
+ await this.response.build(this.context, this, this.syncReturn)
222
+ }
223
+ return executionFailed
224
+ }
225
+
226
+ /**
227
+ * Retrieves a database transaction based on the provided database configuration.
228
+ * @param {DbConfig<S>} config - The configuration object for the database.
229
+ * @returns {Promise<DatabaseTransactionType<S, DBSchema>>} A promise that resolves to the database transaction.
230
+ */
231
+ public async getDbTransaction<S extends DatabaseType, DBSchema>(
232
+ config: DbConfig<S>
233
+ ): Promise<DatabaseTransactionType<S, DBSchema>> {
234
+ const db = this.getDatabase<S, DBSchema>(config)
235
+ const dbTrans = await db.transaction()
236
+ this.transactions.push(dbTrans)
237
+ return dbTrans as any
238
+ }
239
+
240
+ /**
241
+ * Retrieves a database instance based on the provided configuration.
242
+ * @param {DbConfig<S>} config - The configuration object specifying the type of database.
243
+ * @returns {DatabaseImplType<S, DBSchema>} A database instance based on the provided configuration.
244
+ */
245
+ public getDatabase<S extends DatabaseType, DBSchema>(
246
+ config: DbConfig<S>
247
+ ): DatabaseImplType<S, DBSchema> {
248
+ return this.databaseManager.create<S, DBSchema>(config)
249
+ }
250
+
251
+ /**
252
+ * Get the remaining time in milliseconds for the current execution context.
253
+ * @returns {number} The remaining time in milliseconds, or -1 if the time is not available.
254
+ */
255
+ public getRemainingTimeInMillis() {
256
+ return this.context?.getRemainingTimeInMillis?.() || -1
257
+ }
258
+
259
+ /*
260
+ * Executes a series of database transactions in a safe manner.
261
+ * @param {Function} safeExecution - The function that contains the database transactions to be executed.
262
+ * @returns None
263
+ * @throws {Error} - If an exception occurs during the execution of the transactions and `retrowErrors` is true.
264
+ */
265
+ private async executeDBTransactions(safeExecution: () => Promise<boolean>): Promise<void> {
266
+ try {
267
+ // Execute
268
+ const execFailed = await safeExecution()
269
+ for (const transaction of [...this.transactions].reverse()) {
270
+ try {
271
+ await transaction[execFailed ? 'closeFailure' : 'closeSuccess']()
272
+ } catch (e) {
273
+ this.logger.error('Exception when closing DB transactions after success.')
274
+ this.logger.exception(e)
275
+ }
276
+ }
277
+ } catch (e) {
278
+ /* this part of the code handle exceptions at transaction level,
279
+ so probably a bug but we still handle such */
280
+ for (const transaction of [...this.transactions].reverse()) {
281
+ try {
282
+ await transaction.closeFailure()
283
+ } catch (e) {
284
+ this.logger.error('Exception when closing DB transactions after failure.')
285
+ this.logger.exception(e)
286
+ }
287
+ }
288
+ this.logger.error('Exception when executing DB transactions.')
289
+ this.logger.log(e.stack)
290
+ //retrow?
291
+ if (this.retrowErrors) throw e
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Executes a logger flush operation with error handling and logging.
297
+ * @param {Function} safeExecution - The function to execute safely.
298
+ * @returns None
299
+ * @throws {Error} - If `retrowErrors` is true and an error occurs during execution.
300
+ */
301
+ private async executeLoggerFlush(safeExecution): Promise<void> {
302
+ try {
303
+ await safeExecution()
304
+ } catch (e) {
305
+ this.logger.error('Exception when flushing logs.')
306
+ this.logger.exception(e)
307
+ //retrow?
308
+ if (this.retrowErrors) throw e
309
+ } finally {
310
+ this.logger.debug('Transaction ended')
311
+ }
312
+ }
313
+
314
+ /**
315
+ * Generates an error response with the provided error message and code.
316
+ * @param {string} error - The error message to include in the response.
317
+ * @param {string} code - The error code associated with the response.
318
+ * @returns {Response<ResponseErrorType>} - The error response object.
319
+ */
320
+ protected getErrorResponse(error: string, code: string): Response<ResponseErrorType> {
321
+ return Response.BadRequestResponseWithRollback(error, code)
322
+ }
323
+ }
@@ -0,0 +1,89 @@
1
+ import { RedisClientType, RedisClusterType, createCluster, createClient } from 'redis'
2
+
3
+ import { CacheConfig } from './types.js'
4
+ import AsyncSingleton from '../Util/AsyncSingleton.js'
5
+ /**
6
+ * Represents a Redis cache connection class.
7
+ */
8
+ export default class Redis {
9
+ private static singleton = new AsyncSingleton<
10
+ RedisClientType | RedisClusterType,
11
+ CacheConfig<'redis'>
12
+ >(Redis.connectionFactory, async c => c.isOpen)
13
+
14
+ /**
15
+ * A private static property that holds a reference to the redis.createClient function.
16
+ * This property is used to create client.
17
+ */
18
+ private static ClientFactory = createClient
19
+
20
+ /**
21
+ * A private static property that references the createCluster function.
22
+ * This property can be used to create clusters within the class.
23
+ */
24
+ private static ClusterFactory = createCluster
25
+
26
+ public static connection(
27
+ config: CacheConfig<'redis'>
28
+ ): Promise<RedisClientType | RedisClusterType> {
29
+ return Redis.singleton.instance(config)
30
+ }
31
+
32
+ private static async connectionFactory(
33
+ config: CacheConfig<'redis'>
34
+ ): Promise<RedisClientType | RedisClusterType> {
35
+ if (config.clusterMode) return Redis.redisClusterConnection(config)
36
+ else return Redis.redisClientConnection(config)
37
+ }
38
+
39
+ /**
40
+ * Establishes a connection to a Redis client based on the provided configuration
41
+ * and holds it for reusability. If connection is detected closed, new connection is
42
+ * initialized and established.
43
+ * @param {CacheConfig<'redis'>} config - The configuration object for connecting to the Redis client.
44
+ * @returns {Promise<RedisClientType>} A promise that resolves to the Redis client connection.
45
+ */
46
+ private static async redisClientConnection(
47
+ config: CacheConfig<'redis'>
48
+ ): Promise<RedisClientType> {
49
+ console.debug('Starting remote client cache connection')
50
+ const connection = Redis.ClientFactory({
51
+ username: config.username,
52
+ ...(config.password ? { password: config.password } : {}),
53
+ disableOfflineQueue: true,
54
+ socket: {
55
+ host: config.hostname,
56
+ tls: config.enableTLS,
57
+ connectTimeout: 10000,
58
+ },
59
+ })
60
+ await connection.connect()
61
+
62
+ return connection as any
63
+ }
64
+
65
+ private static async redisClusterConnection(
66
+ config: CacheConfig<'redis'>
67
+ ): Promise<RedisClusterType> {
68
+ console.debug('Starting remote cluster cache connection')
69
+ const connection = Redis.ClusterFactory({
70
+ defaults: {
71
+ username: config.username,
72
+ ...(config.password ? { password: config.password } : {}),
73
+ socket: {
74
+ tls: config.enableTLS,
75
+ connectTimeout: 10000,
76
+ },
77
+ },
78
+ rootNodes: [
79
+ {
80
+ url: `redis://${config.username}:${config.username}@${config.hostname}:6379`,
81
+ disableOfflineQueue: true,
82
+ },
83
+ ],
84
+ })
85
+ await connection.connect()
86
+
87
+ return connection as any
88
+ }
89
+ }
@@ -0,0 +1,33 @@
1
+ import Redis from './Redis.js'
2
+
3
+ /**
4
+ * Defines a type alias for specifying the cache type as 'redis'.
5
+ */
6
+ export type CacheType = 'redis'
7
+
8
+ /**
9
+ * Defines a CacheClass type that has a 'redis' property which is a constructor function
10
+ * that takes in any number of arguments and returns an instance of Redis.
11
+ */
12
+ export type CacheClass = {
13
+ redis: new (...args: any[]) => Redis
14
+ }
15
+
16
+ /**
17
+ * Represents the base configuration for a cache, including host, username, password, and TLS settings.
18
+ */
19
+ export type CacheBaseConfig = {
20
+ hostname: string
21
+ username: string
22
+ password?: string
23
+ enableTLS: boolean
24
+ clusterMode?: boolean
25
+ }
26
+
27
+ /**
28
+ * Defines a CacheConfig type that extends CacheBaseConfig and includes a specific cache type.
29
+ * @template S - The specific cache type to be included in the CacheConfig.
30
+ * @extends CacheBaseConfig
31
+ * @property {S} type - The specific cache type included in the CacheConfig.
32
+ */
33
+ export type CacheConfig<S extends CacheType> = CacheBaseConfig & { type: S }