@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,272 @@
1
+ import { expect as c_expect } from 'chai'
2
+
3
+ import Response from '../../src/API/Response.js'
4
+ import DynamoTransaction from '../../src/BaseEvent/DynamoTransaction.js'
5
+ import Globals from '../../src/Globals.js'
6
+ import Utils from '../../src/Util/Utils.js'
7
+ import { emptyDynamoDBEvent, observableContext } from '../Test.utils.js'
8
+
9
+ const skipCleanTmp = {
10
+ skipCleanTmp: true,
11
+ }
12
+
13
+ describe('DynamoTransaction success invocation path', () => {
14
+ test('Simple success', async () => {
15
+ const record = { id: '123' }
16
+ const context = observableContext()
17
+ const transaction = new DynamoTransaction(
18
+ emptyDynamoDBEvent({
19
+ Records: [
20
+ { dynamodb: { NewImage: Utils.ddbMarshall(record) } },
21
+ { dynamodb: { NewImage: Utils.ddbMarshall(record) } },
22
+ ],
23
+ }),
24
+ context
25
+ )
26
+ let count = 0
27
+ const handlerResp = await transaction.processEvent(async (transaction, eventRecord) => {
28
+ c_expect(eventRecord.marshalled.NewImage).to.be.deep.equal(record)
29
+ count++
30
+ return Response.SuccessResponse(null)
31
+ })
32
+ // check resp
33
+ c_expect(count).to.be.equals(2)
34
+ c_expect(handlerResp).to.be.an.instanceof(Response)
35
+ if (handlerResp instanceof Response) {
36
+ c_expect(handlerResp?.getBody()).to.be.deep.equal({
37
+ transactionID: 'unknown',
38
+ })
39
+ c_expect(handlerResp.getCode()).to.be.equal(200)
40
+ }
41
+ // ctx
42
+ expect(context.fail).not.toBeCalled()
43
+ expect(context.done).not.toBeCalled()
44
+ expect(context.succeed).not.toBeCalled()
45
+ })
46
+
47
+ test('Simple success - do not decode', async () => {
48
+ const record = { id: '123' }
49
+ const context = observableContext()
50
+ const transaction = new DynamoTransaction(
51
+ emptyDynamoDBEvent({
52
+ Records: [
53
+ { dynamodb: { NewImage: Utils.ddbMarshall(record) } },
54
+ { dynamodb: { NewImage: Utils.ddbMarshall(record) } },
55
+ ],
56
+ }),
57
+ context,
58
+ { ...skipCleanTmp }
59
+ )
60
+ let count = 0
61
+ const handlerResp = await transaction.processEvent(async (transaction, eventRecord) => {
62
+ c_expect(eventRecord.dynamodb?.NewImage).to.be.deep.equal(Utils.ddbMarshall(record))
63
+ count++
64
+ return Response.SuccessResponse(null)
65
+ })
66
+ // check resp
67
+ c_expect(count).to.be.equals(2)
68
+ c_expect(handlerResp).to.be.an.instanceof(Response)
69
+ if (handlerResp instanceof Response) {
70
+ c_expect(handlerResp?.getBody()).to.be.deep.equal({
71
+ transactionID: 'unknown',
72
+ })
73
+ c_expect(handlerResp.getCode()).to.be.equal(200)
74
+ }
75
+ // ctx
76
+ expect(context.fail).not.toBeCalled()
77
+ expect(context.done).not.toBeCalled()
78
+ expect(context.succeed).not.toBeCalled()
79
+ })
80
+ })
81
+
82
+ describe('DynamoTransaction failure invocation path', () => {
83
+ test('Simple failure', async () => {
84
+ const record = { id: '123' }
85
+ const context = observableContext()
86
+ const transaction = new DynamoTransaction(
87
+ emptyDynamoDBEvent({
88
+ Records: [
89
+ { dynamodb: { NewImage: Utils.ddbMarshall(record) } },
90
+ { eventID: '123', dynamodb: { NewImage: Utils.ddbMarshall(record) } },
91
+ { dynamodb: { NewImage: Utils.ddbMarshall(record) } },
92
+ ],
93
+ }),
94
+ context,
95
+ { ...skipCleanTmp }
96
+ )
97
+ let count = 0
98
+ let handlerResp: any = null,
99
+ err: any = null
100
+ try {
101
+ handlerResp = await transaction.processEvent(async (transaction, eventRecord) => {
102
+ c_expect(eventRecord.marshalled.NewImage).to.be.deep.equal(record)
103
+ count++
104
+ return count == 1 ? Response.SuccessResponse(null) : Response.BadRequestResponse('Failed!')
105
+ })
106
+ } catch (e) {
107
+ err = e
108
+ }
109
+ // check resp
110
+ c_expect(count).to.be.equals(2)
111
+ c_expect(handlerResp).to.be.null
112
+ c_expect(err).to.be.deep.equal(
113
+ new Error(
114
+ JSON.stringify({
115
+ err: 'Failed!',
116
+ transactionID: 'unknown',
117
+ })
118
+ )
119
+ )
120
+ // ctx
121
+ expect(context.fail).not.toBeCalled()
122
+ expect(context.done).not.toBeCalled()
123
+ expect(context.succeed).not.toBeCalled()
124
+ })
125
+
126
+ test('Simple failure w/ null', async () => {
127
+ const record = { id: '123' }
128
+ const context = observableContext()
129
+ const transaction = new DynamoTransaction(
130
+ emptyDynamoDBEvent({
131
+ Records: [
132
+ { dynamodb: { NewImage: Utils.ddbMarshall(record) } },
133
+ { eventID: '123', dynamodb: { NewImage: Utils.ddbMarshall(record) } },
134
+ { dynamodb: { NewImage: Utils.ddbMarshall(record) } },
135
+ ],
136
+ }),
137
+ context,
138
+ { ...skipCleanTmp }
139
+ )
140
+ let count = 0
141
+ let handlerResp: any = null,
142
+ err: any = null
143
+ try {
144
+ handlerResp = await transaction.processEvent(
145
+ // @ts-ignore
146
+ async (transaction, eventRecord) => {
147
+ c_expect(eventRecord.marshalled.NewImage).to.be.deep.equal(record)
148
+ count++
149
+ return null
150
+ }
151
+ )
152
+ } catch (e) {
153
+ err = e
154
+ }
155
+ // check resp
156
+ c_expect(count).to.be.equals(1)
157
+ c_expect(handlerResp).to.be.null
158
+ c_expect(err).to.be.deep.equal(
159
+ new Error(
160
+ JSON.stringify({
161
+ err: Globals.ErrorResponseInvalidServerResponse,
162
+ rollback: true,
163
+ errCode: Globals.ErrorCode_APIError,
164
+ transactionID: 'unknown',
165
+ })
166
+ )
167
+ )
168
+ // ctx
169
+ expect(context.fail).not.toBeCalled()
170
+ expect(context.done).not.toBeCalled()
171
+ expect(context.succeed).not.toBeCalled()
172
+ })
173
+
174
+ test('Simple failure - allow failures', async () => {
175
+ const record = { id: '123' }
176
+ const context = observableContext()
177
+ const transaction = new DynamoTransaction(
178
+ emptyDynamoDBEvent({
179
+ Records: [
180
+ { dynamodb: { NewImage: Utils.ddbMarshall(record) } },
181
+ { eventID: '123', dynamodb: { NewImage: Utils.ddbMarshall(record) } },
182
+ ],
183
+ }),
184
+ context,
185
+ { ...skipCleanTmp },
186
+ true
187
+ )
188
+ let count = 0
189
+ const handlerResp = await transaction.processEvent(async (transaction, eventRecord) => {
190
+ c_expect(eventRecord.marshalled.NewImage).to.be.deep.equal(record)
191
+ count++
192
+ return count == 1 ? Response.SuccessResponse(null) : Response.BadRequestResponse('Failed!')
193
+ })
194
+ // check resp
195
+ c_expect(count).to.be.equals(2)
196
+ c_expect(handlerResp).to.be.deep.equal({
197
+ batchItemFailures: [{ itemIdentifier: '123' }],
198
+ })
199
+ // ctx
200
+ expect(context.fail).not.toBeCalled()
201
+ expect(context.done).not.toBeCalled()
202
+ expect(context.succeed).not.toBeCalled()
203
+ })
204
+
205
+ test('Simple failure w/ null response - allow failures', async () => {
206
+ const record = { id: '123' }
207
+ const context = observableContext()
208
+ const transaction = new DynamoTransaction(
209
+ emptyDynamoDBEvent({
210
+ Records: [
211
+ { eventID: '456', dynamodb: { NewImage: Utils.ddbMarshall(record) } },
212
+ { eventID: '123', dynamodb: { NewImage: Utils.ddbMarshall(record) } },
213
+ ],
214
+ }),
215
+ context,
216
+ { ...skipCleanTmp },
217
+ true
218
+ )
219
+ let count = 0
220
+ const handlerResp = await transaction.processEvent(
221
+ // @ts-ignore
222
+ async (transaction, eventRecord) => {
223
+ c_expect(eventRecord.marshalled.NewImage).to.be.deep.equal(record)
224
+ count++
225
+ return null
226
+ }
227
+ )
228
+ // check resp
229
+ c_expect(count).to.be.equals(2)
230
+ c_expect(handlerResp).to.be.deep.equal({
231
+ batchItemFailures: [{ itemIdentifier: '456' }, { itemIdentifier: '123' }],
232
+ })
233
+ // ctx
234
+ expect(context.fail).not.toBeCalled()
235
+ expect(context.done).not.toBeCalled()
236
+ expect(context.succeed).not.toBeCalled()
237
+ })
238
+
239
+ test('Simple failure no records', async () => {
240
+ const context = observableContext()
241
+ const transaction = new DynamoTransaction(emptyDynamoDBEvent(), context, {})
242
+ let count = 0
243
+ let handlerResp: any = null,
244
+ err: any = null
245
+ try {
246
+ handlerResp = await transaction.processEvent(
247
+ // @ts-ignore
248
+ async () => {
249
+ count++
250
+ return null
251
+ }
252
+ )
253
+ } catch (e) {
254
+ err = e
255
+ }
256
+ // check resp
257
+ c_expect(count).to.be.equals(0)
258
+ c_expect(handlerResp).to.be.null
259
+ c_expect(err).to.be.deep.equal(
260
+ new Error(
261
+ JSON.stringify({
262
+ err: Globals.ErrorResponseNoRecords,
263
+ errCode: Globals.ErrorCode_NoRecords,
264
+ })
265
+ )
266
+ )
267
+ // ctx
268
+ expect(context.fail).not.toBeCalled()
269
+ expect(context.done).not.toBeCalled()
270
+ expect(context.succeed).not.toBeCalled()
271
+ })
272
+ })
@@ -0,0 +1,263 @@
1
+ import { expect as c_expect } from 'chai'
2
+
3
+ import Response from '../../src/API/Response.js'
4
+ import EventProcessor from '../../src/BaseEvent/EventProcessor.js'
5
+ import Globals from '../../src/Globals.js'
6
+ import { emptyQueueEvent, observableContext } from '../Test.utils.js'
7
+
8
+ const skipCleanTmp = {
9
+ skipCleanTmp: true,
10
+ }
11
+
12
+ describe('EventProcessor success invocation path', () => {
13
+ test('Simple success', async () => {
14
+ const b = { name: '123' }
15
+ const context = observableContext()
16
+ const transaction = new EventProcessor(
17
+ emptyQueueEvent({
18
+ Records: [{ body: JSON.stringify(b) }, { body: JSON.stringify(b) }],
19
+ }),
20
+ context,
21
+ { ...skipCleanTmp }
22
+ )
23
+ let count = 0
24
+ const handlerResp = await transaction.processEvent(async (transaction, eventRecord) => {
25
+ c_expect(eventRecord).to.be.deep.equal(b)
26
+ count++
27
+ return Response.SuccessResponse(null)
28
+ })
29
+ // check resp
30
+ c_expect(count).to.be.equals(2)
31
+ c_expect(handlerResp).to.be.an.instanceof(Response)
32
+ if (handlerResp instanceof Response) {
33
+ c_expect(handlerResp?.getBody()).to.be.deep.equal({
34
+ transactionID: 'unknown',
35
+ })
36
+ c_expect(handlerResp.getCode()).to.be.equal(200)
37
+ }
38
+ // ctx
39
+ expect(context.fail).not.toBeCalled()
40
+ expect(context.done).not.toBeCalled()
41
+ expect(context.succeed).not.toBeCalled()
42
+ })
43
+
44
+ test('Simple success - do not decode', async () => {
45
+ const b = { name: '123' }
46
+ const context = observableContext()
47
+ const transaction = new EventProcessor(
48
+ emptyQueueEvent({
49
+ Records: [{ body: JSON.stringify(b) }, { body: JSON.stringify(b) }],
50
+ }),
51
+ context,
52
+ { ...skipCleanTmp }
53
+ )
54
+ let count = 0
55
+ const handlerResp = await transaction.processEvent(async (transaction, eventRecord) => {
56
+ c_expect(eventRecord).to.be.deep.equal(JSON.stringify(b))
57
+ count++
58
+ return Response.SuccessResponse(null)
59
+ }, true)
60
+ // check resp
61
+ c_expect(count).to.be.equals(2)
62
+ c_expect(handlerResp).to.be.an.instanceof(Response)
63
+ if (handlerResp instanceof Response) {
64
+ c_expect(handlerResp?.getBody()).to.be.deep.equal({
65
+ transactionID: 'unknown',
66
+ })
67
+ c_expect(handlerResp.getCode()).to.be.equal(200)
68
+ }
69
+ // ctx
70
+ expect(context.fail).not.toBeCalled()
71
+ expect(context.done).not.toBeCalled()
72
+ expect(context.succeed).not.toBeCalled()
73
+ })
74
+ })
75
+
76
+ describe('EventProcessor failure invocation path', () => {
77
+ test('Simple failure', async () => {
78
+ const b = { name: '123' }
79
+ const context = observableContext()
80
+ const transaction = new EventProcessor(
81
+ emptyQueueEvent({
82
+ Records: [
83
+ { body: JSON.stringify(b) },
84
+ { messageId: '123', body: JSON.stringify(b) },
85
+ { body: JSON.stringify(b) },
86
+ ],
87
+ }),
88
+ context,
89
+ { ...skipCleanTmp }
90
+ )
91
+ let count = 0
92
+ let handlerResp: any = null,
93
+ err: any = null
94
+ try {
95
+ handlerResp = await transaction.processEvent(async (transaction, eventRecord) => {
96
+ c_expect(eventRecord).to.be.deep.equal(b)
97
+ count++
98
+ return count == 1 ? Response.SuccessResponse(null) : Response.BadRequestResponse('Failed!')
99
+ })
100
+ } catch (e) {
101
+ err = e
102
+ }
103
+ // check resp
104
+ c_expect(count).to.be.equals(2)
105
+ c_expect(handlerResp).to.be.null
106
+ c_expect(err).to.be.deep.equal(
107
+ new Error(
108
+ JSON.stringify({
109
+ err: 'Failed!',
110
+ transactionID: 'unknown',
111
+ })
112
+ )
113
+ )
114
+ // ctx
115
+ expect(context.fail).not.toBeCalled()
116
+ expect(context.done).not.toBeCalled()
117
+ expect(context.succeed).not.toBeCalled()
118
+ })
119
+
120
+ test('Simple failure w/ null', async () => {
121
+ const b = { name: '123' }
122
+ const context = observableContext()
123
+ const transaction = new EventProcessor(
124
+ emptyQueueEvent({
125
+ Records: [
126
+ { body: JSON.stringify(b) },
127
+ { messageId: '123', body: JSON.stringify(b) },
128
+ { body: JSON.stringify(b) },
129
+ ],
130
+ }),
131
+ context,
132
+ { ...skipCleanTmp }
133
+ )
134
+ let count = 0
135
+ let handlerResp: any = null,
136
+ err: any = null
137
+ try {
138
+ handlerResp = await transaction.processEvent(
139
+ // @ts-ignore
140
+ async (transaction, eventRecord) => {
141
+ c_expect(eventRecord).to.be.deep.equal(b)
142
+ count++
143
+ return null
144
+ }
145
+ )
146
+ } catch (e) {
147
+ err = e
148
+ }
149
+ // check resp
150
+ c_expect(count).to.be.equals(1)
151
+ c_expect(handlerResp).to.be.null
152
+ c_expect(err).to.be.deep.equal(
153
+ new Error(
154
+ JSON.stringify({
155
+ err: Globals.ErrorResponseInvalidServerResponse,
156
+ rollback: true,
157
+ errCode: Globals.ErrorCode_APIError,
158
+ transactionID: 'unknown',
159
+ })
160
+ )
161
+ )
162
+ // ctx
163
+ expect(context.fail).not.toBeCalled()
164
+ expect(context.done).not.toBeCalled()
165
+ expect(context.succeed).not.toBeCalled()
166
+ })
167
+
168
+ test('Simple failure - allow failures', async () => {
169
+ const b = { name: '123' }
170
+ const context = observableContext()
171
+ const transaction = new EventProcessor(
172
+ emptyQueueEvent({
173
+ Records: [{ body: JSON.stringify(b) }, { messageId: '123', body: JSON.stringify(b) }],
174
+ }),
175
+ context,
176
+ { ...skipCleanTmp },
177
+ true
178
+ )
179
+ let count = 0
180
+ const handlerResp = await transaction.processEvent(async (transaction, eventRecord) => {
181
+ c_expect(eventRecord).to.be.deep.equal(b)
182
+ count++
183
+ return count == 1 ? Response.SuccessResponse(null) : Response.BadRequestResponse('Failed!')
184
+ })
185
+ // check resp
186
+ c_expect(count).to.be.equals(2)
187
+ c_expect(handlerResp).to.be.deep.equal({
188
+ batchItemFailures: [{ itemIdentifier: '123' }],
189
+ })
190
+ // ctx
191
+ expect(context.fail).not.toBeCalled()
192
+ expect(context.done).not.toBeCalled()
193
+ expect(context.succeed).not.toBeCalled()
194
+ })
195
+
196
+ test('Simple failure w/ null response - allow failures', async () => {
197
+ const b = { name: '123' }
198
+ const context = observableContext()
199
+ const transaction = new EventProcessor(
200
+ emptyQueueEvent({
201
+ Records: [
202
+ { messageId: '456', body: JSON.stringify(b) },
203
+ { messageId: '123', body: JSON.stringify(b) },
204
+ ],
205
+ }),
206
+ context,
207
+ { ...skipCleanTmp },
208
+ true
209
+ )
210
+ let count = 0
211
+ const handlerResp = await transaction.processEvent(
212
+ // @ts-ignore
213
+ async (transaction, eventRecord) => {
214
+ c_expect(eventRecord).to.be.deep.equal(b)
215
+ count++
216
+ return null
217
+ }
218
+ )
219
+ // check resp
220
+ c_expect(count).to.be.equals(2)
221
+ c_expect(handlerResp).to.be.deep.equal({
222
+ batchItemFailures: [{ itemIdentifier: '456' }, { itemIdentifier: '123' }],
223
+ })
224
+ // ctx
225
+ expect(context.fail).not.toBeCalled()
226
+ expect(context.done).not.toBeCalled()
227
+ expect(context.succeed).not.toBeCalled()
228
+ })
229
+
230
+ test('Simple failure no records', async () => {
231
+ const context = observableContext()
232
+ const transaction = new EventProcessor(emptyQueueEvent(), context, {})
233
+ let count = 0
234
+ let handlerResp: any = null,
235
+ err: any = null
236
+ try {
237
+ handlerResp = await transaction.processEvent(
238
+ // @ts-ignore
239
+ async () => {
240
+ count++
241
+ return null
242
+ }
243
+ )
244
+ } catch (e) {
245
+ err = e
246
+ }
247
+ // check resp
248
+ c_expect(count).to.be.equals(0)
249
+ c_expect(handlerResp).to.be.null
250
+ c_expect(err).to.be.deep.equal(
251
+ new Error(
252
+ JSON.stringify({
253
+ err: Globals.ErrorResponseNoRecords,
254
+ errCode: Globals.ErrorCode_NoRecords,
255
+ })
256
+ )
257
+ )
258
+ // ctx
259
+ expect(context.fail).not.toBeCalled()
260
+ expect(context.done).not.toBeCalled()
261
+ expect(context.succeed).not.toBeCalled()
262
+ })
263
+ })
@@ -0,0 +1,47 @@
1
+ import { expect } from 'chai'
2
+
3
+ import Response from '../../src/API/Response.js'
4
+ import Process from '../../src/BaseEvent/Process.js'
5
+
6
+ describe('Process success invocation path', () => {
7
+ test('Simple success', async () => {
8
+ const b = { name: '123' }
9
+ const proc = new Process({}, 100)
10
+ let count = 0
11
+ const handlerResp = await proc.execute(async () => {
12
+ count++
13
+ return Response.SuccessResponse(b)
14
+ })
15
+ // check resp
16
+ expect(handlerResp).to.be.undefined
17
+ // check iterations
18
+ return new Promise(resolve => {
19
+ setTimeout(() => {
20
+ expect(count).to.be.equals(2)
21
+ clearInterval(proc.timeout)
22
+ resolve(null)
23
+ }, 250)
24
+ })
25
+ })
26
+ })
27
+
28
+ describe('Process failure invocation path', () => {
29
+ test('Simple failure', async () => {
30
+ const proc = new Process({}, 100)
31
+ let count = 0
32
+ const handlerResp = await proc.execute(async () => {
33
+ count++
34
+ throw new Error('Failed!')
35
+ })
36
+ // check resp
37
+ expect(handlerResp).to.be.undefined
38
+ // check iterations
39
+ return new Promise(resolve => {
40
+ setTimeout(() => {
41
+ expect(count).to.be.equals(2)
42
+ clearInterval(proc.timeout)
43
+ resolve(null)
44
+ }, 250)
45
+ })
46
+ })
47
+ })
@@ -0,0 +1,44 @@
1
+ import { Context } from 'aws-lambda' // Import Context from aws-lambda
2
+
3
+ import Response from '../../src/API/Response.js'
4
+ import StepTransaction from '../../src/BaseEvent/StepTransaction.js'
5
+ import Transaction from '../../src/BaseEvent/Transaction.js'
6
+
7
+ describe('StepTransaction', () => {
8
+ let mockEvent
9
+ let mockContext
10
+
11
+ beforeEach(() => {
12
+ mockEvent = { key: 'value' }
13
+ mockContext = {} as Context // Mock AWS Lambda context object
14
+ })
15
+
16
+ describe('constructor', () => {
17
+ test('should create an instance of StepTransaction with default config', () => {
18
+ const stepTransaction = new StepTransaction(mockEvent, mockContext)
19
+
20
+ expect(stepTransaction).toBeInstanceOf(StepTransaction)
21
+ expect(stepTransaction).toBeInstanceOf(Transaction)
22
+ expect((stepTransaction as any).syncReturn).toBe(true)
23
+ expect((stepTransaction as any).retrowErrors).toBe(true)
24
+ })
25
+ })
26
+
27
+ describe('getErrorResponse', () => {
28
+ test('should return an error response with provided error and code', () => {
29
+ const stepTransaction = new StepTransaction(mockEvent, mockContext)
30
+ const error = 'Test error message'
31
+ const code = 'TestErrorCode'
32
+
33
+ const response = (stepTransaction as any).getErrorResponse(error, code)
34
+
35
+ expect(response).toBeInstanceOf(Response)
36
+ expect(response).toEqual(
37
+ expect.objectContaining({
38
+ statusCode: 400,
39
+ body: { err: error, errCode: code },
40
+ })
41
+ )
42
+ })
43
+ })
44
+ })