@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.
- package/.eslintignore +3 -0
- package/.eslintrc.cjs +81 -0
- package/.github/workflows/npmpublish.yml +8 -19
- package/.github/workflows/prs.yml +12 -0
- package/README.md +89 -99
- package/dist/index.d.ts +16 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/package-lock.json +11881 -0
- package/dist/package.json +81 -0
- package/dist/src/API/Request.d.ts +125 -0
- package/dist/src/API/Request.js +185 -0
- package/dist/src/API/Request.js.map +1 -0
- package/dist/src/API/Response.d.ts +188 -0
- package/dist/src/API/Response.js +270 -0
- package/dist/src/API/Response.js.map +1 -0
- package/dist/src/BaseEvent/DynamoTransaction.d.ts +70 -0
- package/dist/src/BaseEvent/DynamoTransaction.js +104 -0
- package/dist/src/BaseEvent/DynamoTransaction.js.map +1 -0
- package/dist/src/BaseEvent/EventProcessor.d.ts +58 -0
- package/dist/src/BaseEvent/EventProcessor.js +101 -0
- package/dist/src/BaseEvent/EventProcessor.js.map +1 -0
- package/dist/src/BaseEvent/Process.d.ts +50 -0
- package/dist/src/BaseEvent/Process.js +64 -0
- package/dist/src/BaseEvent/Process.js.map +1 -0
- package/dist/src/BaseEvent/StepTransaction.d.ts +23 -0
- package/dist/src/BaseEvent/StepTransaction.js +27 -0
- package/dist/src/BaseEvent/StepTransaction.js.map +1 -0
- package/dist/src/BaseEvent/Transaction.d.ts +149 -0
- package/dist/src/BaseEvent/Transaction.js +224 -0
- package/dist/src/BaseEvent/Transaction.js.map +1 -0
- package/dist/src/Cache/Redis.d.ts +29 -0
- package/dist/src/Cache/Redis.js +80 -0
- package/dist/src/Cache/Redis.js.map +1 -0
- package/dist/src/Cache/types.d.ts +31 -0
- package/dist/src/Cache/types.js +2 -0
- package/dist/src/Cache/types.js.map +1 -0
- package/dist/src/Config/Configuration.d.ts +123 -0
- package/dist/src/Config/Configuration.js +109 -0
- package/dist/src/Config/Configuration.js.map +1 -0
- package/dist/src/Config/EnvironmentVar.d.ts +74 -0
- package/dist/src/Config/EnvironmentVar.js +138 -0
- package/dist/src/Config/EnvironmentVar.js.map +1 -0
- package/dist/src/Crypto/Crypto.d.ts +45 -0
- package/dist/src/Crypto/Crypto.js +72 -0
- package/dist/src/Crypto/Crypto.js.map +1 -0
- package/dist/src/Database/Database.d.ts +21 -0
- package/dist/src/Database/Database.js +15 -0
- package/dist/src/Database/Database.js.map +1 -0
- package/dist/src/Database/DatabaseManager.d.ts +47 -0
- package/dist/src/Database/DatabaseManager.js +60 -0
- package/dist/src/Database/DatabaseManager.js.map +1 -0
- package/dist/src/Database/DatabaseTransaction.d.ts +101 -0
- package/dist/src/Database/DatabaseTransaction.js +126 -0
- package/dist/src/Database/DatabaseTransaction.js.map +1 -0
- package/dist/src/Database/index.d.ts +10 -0
- package/dist/src/Database/index.js +15 -0
- package/dist/src/Database/index.js.map +1 -0
- package/dist/src/Database/integrations/dynamo/DynamoDatabase.d.ts +35 -0
- package/dist/src/Database/integrations/dynamo/DynamoDatabase.js +59 -0
- package/dist/src/Database/integrations/dynamo/DynamoDatabase.js.map +1 -0
- package/dist/src/Database/integrations/kysely/KyselyDatabase.d.ts +66 -0
- package/dist/src/Database/integrations/kysely/KyselyDatabase.js +86 -0
- package/dist/src/Database/integrations/kysely/KyselyDatabase.js.map +1 -0
- package/dist/src/Database/integrations/kysely/KyselyTransaction.d.ts +70 -0
- package/dist/src/Database/integrations/kysely/KyselyTransaction.js +118 -0
- package/dist/src/Database/integrations/kysely/KyselyTransaction.js.map +1 -0
- package/dist/src/Database/integrations/pgsql/PostgresDatabase.d.ts +36 -0
- package/dist/src/Database/integrations/pgsql/PostgresDatabase.js +54 -0
- package/dist/src/Database/integrations/pgsql/PostgresDatabase.js.map +1 -0
- package/dist/src/Database/integrations/pgsql/PostgresTransaction.d.ts +63 -0
- package/dist/src/Database/integrations/pgsql/PostgresTransaction.js +61 -0
- package/dist/src/Database/integrations/pgsql/PostgresTransaction.js.map +1 -0
- package/dist/src/Database/types.d.ts +76 -0
- package/dist/src/Database/types.js +2 -0
- package/dist/src/Database/types.js.map +1 -0
- package/dist/src/Globals.d.ts +93 -0
- package/dist/src/Globals.js +99 -0
- package/dist/src/Globals.js.map +1 -0
- package/dist/src/Logger/Logger.d.ts +161 -0
- package/dist/src/Logger/Logger.js +299 -0
- package/dist/src/Logger/Logger.js.map +1 -0
- package/dist/src/Mailer/Mailer.d.ts +78 -0
- package/dist/src/Mailer/Mailer.js +182 -0
- package/dist/src/Mailer/Mailer.js.map +1 -0
- package/dist/src/Publisher/Publisher.d.ts +39 -0
- package/dist/src/Publisher/Publisher.js +77 -0
- package/dist/src/Publisher/Publisher.js.map +1 -0
- package/dist/src/Server/RouteResolver.d.ts +33 -0
- package/dist/src/Server/RouteResolver.js +100 -0
- package/dist/src/Server/RouteResolver.js.map +1 -0
- package/dist/src/Server/Router.d.ts +157 -0
- package/dist/src/Server/Router.js +32 -0
- package/dist/src/Server/Router.js.map +1 -0
- package/dist/src/Server/lib/ContainerServer.d.ts +42 -0
- package/dist/src/Server/lib/ContainerServer.js +66 -0
- package/dist/src/Server/lib/ContainerServer.js.map +1 -0
- package/dist/src/Server/lib/Server.d.ts +45 -0
- package/dist/src/Server/lib/Server.js +93 -0
- package/dist/src/Server/lib/Server.js.map +1 -0
- package/dist/src/Server/lib/container/GenericHandler.d.ts +9 -0
- package/dist/src/Server/lib/container/GenericHandler.js +82 -0
- package/dist/src/Server/lib/container/GenericHandler.js.map +1 -0
- package/dist/src/Server/lib/container/GenericHandlerEvent.d.ts +52 -0
- package/dist/src/Server/lib/container/GenericHandlerEvent.js +132 -0
- package/dist/src/Server/lib/container/GenericHandlerEvent.js.map +1 -0
- package/dist/src/Server/lib/container/HealthHandler.d.ts +9 -0
- package/dist/src/Server/lib/container/HealthHandler.js +19 -0
- package/dist/src/Server/lib/container/HealthHandler.js.map +1 -0
- package/dist/src/Server/lib/container/Proxy.d.ts +67 -0
- package/dist/src/Server/lib/container/Proxy.js +143 -0
- package/dist/src/Server/lib/container/Proxy.js.map +1 -0
- package/dist/src/Server/lib/container/Utils.d.ts +14 -0
- package/dist/src/Server/lib/container/Utils.js +37 -0
- package/dist/src/Server/lib/container/Utils.js.map +1 -0
- package/dist/src/Util/AsyncSingleton.d.ts +31 -0
- package/dist/src/Util/AsyncSingleton.js +83 -0
- package/dist/src/Util/AsyncSingleton.js.map +1 -0
- package/dist/src/Util/Utils.d.ts +61 -0
- package/dist/src/Util/Utils.js +147 -0
- package/dist/src/Util/Utils.js.map +1 -0
- package/dist/src/Validation/Validator.d.ts +17 -0
- package/dist/src/Validation/Validator.js +39 -0
- package/dist/src/Validation/Validator.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/index.ts +41 -0
- package/jest.config.ts +37 -0
- package/jest.smoke.config.ts +34 -0
- package/package.json +66 -22
- package/src/API/Request.ts +214 -0
- package/src/API/Response.ts +370 -0
- package/src/BaseEvent/DynamoTransaction.ts +175 -0
- package/src/BaseEvent/EventProcessor.ts +140 -0
- package/src/BaseEvent/Process.ts +78 -0
- package/src/BaseEvent/StepTransaction.ts +35 -0
- package/src/BaseEvent/Transaction.ts +323 -0
- package/src/Cache/Redis.ts +89 -0
- package/src/Cache/types.ts +33 -0
- package/src/Config/Configuration.ts +199 -0
- package/src/Config/EnvironmentVar.ts +142 -0
- package/src/Crypto/Crypto.ts +89 -0
- package/src/Database/Database.ts +22 -0
- package/src/Database/DatabaseManager.ts +67 -0
- package/src/Database/DatabaseTransaction.ts +170 -0
- package/src/Database/index.ts +27 -0
- package/src/Database/integrations/dynamo/DynamoDatabase.ts +58 -0
- package/src/Database/integrations/kysely/KyselyDatabase.ts +99 -0
- package/src/Database/integrations/kysely/KyselyTransaction.ts +172 -0
- package/src/Database/integrations/pgsql/PostgresDatabase.ts +56 -0
- package/src/Database/integrations/pgsql/PostgresTransaction.ts +87 -0
- package/src/Database/types.ts +85 -0
- package/src/Globals.ts +103 -0
- package/src/Logger/Logger.ts +363 -0
- package/src/Mailer/Mailer.ts +217 -0
- package/src/Publisher/Publisher.ts +96 -0
- package/src/Server/RouteResolver.ts +124 -0
- package/src/Server/Router.ts +200 -0
- package/src/Server/lib/ContainerServer.ts +65 -0
- package/src/Server/lib/Server.ts +109 -0
- package/src/Server/lib/container/GenericHandler.ts +76 -0
- package/src/Server/lib/container/GenericHandlerEvent.ts +154 -0
- package/src/Server/lib/container/HealthHandler.ts +11 -0
- package/src/Server/lib/container/Proxy.ts +172 -0
- package/src/Server/lib/container/Utils.ts +33 -0
- package/src/Util/AsyncSingleton.ts +86 -0
- package/src/Util/Utils.ts +131 -0
- package/src/Validation/Validator.ts +45 -0
- package/tests/API/Request.test.ts +273 -0
- package/tests/API/Response.test.ts +367 -0
- package/tests/BaseEvent/DynamoTransaction.test.ts +272 -0
- package/tests/BaseEvent/EventProcessor.test.ts +263 -0
- package/tests/BaseEvent/Process.test.ts +47 -0
- package/tests/BaseEvent/StepTransaction.test.ts +44 -0
- package/tests/BaseEvent/Transaction.test.ts +402 -0
- package/tests/Cache/Redis-client.test.ts +90 -0
- package/tests/Cache/Redis-cluster.test.ts +100 -0
- package/tests/Config/Config.test.ts +205 -0
- package/tests/Config/EnvironmentVar.test.ts +251 -0
- package/tests/Crypto/Crypto.test.ts +88 -0
- package/tests/Database/DatabaseManager.test.ts +79 -0
- package/tests/Database/integrations/dynamo/DynamoDatabase.test.ts +44 -0
- package/tests/Database/integrations/kysely/KyselyDatabase.test.ts +113 -0
- package/tests/Database/integrations/kysely/KyselyTransaction.test.ts +119 -0
- package/tests/Database/integrations/pg/PostgresDatabase.test.ts +76 -0
- package/tests/Database/integrations/pg/PostgresTransaction.test.ts +118 -0
- package/tests/Logger/Logger.test.ts +215 -0
- package/tests/Mailer/Mailer.test.ts +59 -0
- package/tests/Publisher/Publisher.test.ts +60 -0
- package/tests/Server/RouteResolver.test.ts +116 -0
- package/tests/Server/Router.test.ts +39 -0
- package/tests/Server/lib/ContainerServer.test.ts +531 -0
- package/tests/Server/lib/Server.test.ts +12 -0
- package/tests/Server/lib/container/GenericHandler.test.ts +131 -0
- package/tests/Server/lib/container/GenericHandlerEvent.test.ts +103 -0
- package/tests/Server/lib/container/HealthHandler.test.ts +30 -0
- package/tests/Server/lib/container/Proxy.test.ts +268 -0
- package/tests/Server/lib/container/Utils.test.ts +47 -0
- package/tests/Test.utils.ts +78 -0
- package/tests/Utils/Utils.test.ts +229 -0
- package/tests/Validation/Validator.test.ts +82 -0
- package/tsconfig.json +26 -0
- package/tsconfig.smoke.json +26 -0
- package/index.js +0 -88
- package/src/API/IKRequest.js +0 -52
- package/src/API/IKResponse.js +0 -119
- package/src/API/IKUtils.js +0 -51
- package/src/BaseEvent/IKProcess.js +0 -77
- package/src/BaseEvent/IKTransaction.js +0 -139
- package/src/Cache/Prototype/IKCache.js +0 -17
- package/src/Cache/Redis/IKRedis.js +0 -148
- package/src/Database/DDB/IKDB.js +0 -56
- package/src/Database/DDB/IKDBBaseExpression.js +0 -130
- package/src/Database/DDB/IKDBBaseQuery.js +0 -151
- package/src/Database/DDB/IKDBQueryBatchGet.js +0 -37
- package/src/Database/DDB/IKDBQueryBatchWrite.js +0 -64
- package/src/Database/DDB/IKDBQueryDelete.js +0 -34
- package/src/Database/DDB/IKDBQueryGet.js +0 -48
- package/src/Database/DDB/IKDBQueryPut.js +0 -87
- package/src/Database/DDB/IKDBQueryScan.js +0 -45
- package/src/Database/DDB/IKDBQueryTransactionalWrite.js +0 -69
- package/src/Database/DDB/IKDBQueryUpdate.js +0 -221
- package/src/Database/DDB/_IKDBQueryTransactionalRead.js +0 -46
- package/src/Database/PSQL/IKDB.js +0 -41
- package/src/Database/PSQL/IKDBBaseQuery.js +0 -26
- package/src/Database/Prototype/IKDB.js +0 -21
- package/src/Database/Prototype/IKDBBaseQuery.js +0 -14
- package/src/IKDynamoStream.js +0 -42
- package/src/IKEventProcessor.js +0 -42
- package/src/IKGlobals.js +0 -24
- package/src/IKRouter.js +0 -47
- package/src/IKStepTransaction.js +0 -14
- package/src/Logger/IKLogger.js +0 -136
- package/src/Mailer/IKMailer.js +0 -69
- package/src/Publisher/IKPublisher.js +0 -44
- package/src/Tracker/IKExecutionTracker.js +0 -79
- 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
|
+
})
|