@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,103 @@
1
+ import { APIGatewayProxyEvent, Context } from 'aws-lambda'
2
+ import { expect } from 'chai'
3
+ import { Request } from 'express'
4
+
5
+ import { HttpMethod } from '../../../../src/API/Request.js'
6
+ import GenericHandlerEvent from '../../../../src/Server/lib/container/GenericHandlerEvent.js'
7
+
8
+ describe('GenericHandlerEvent invocation paths', () => {
9
+ test('Simple success', async () => {
10
+ const event = new GenericHandlerEvent(
11
+ <Request>(<unknown>{
12
+ socket: { remoteAddress: '127.0.0.1' },
13
+ }),
14
+ async (event: APIGatewayProxyEvent, context: Context) => {
15
+ expect(context.getRemainingTimeInMillis()).to.not.be.null
16
+ context.succeed('Success')
17
+ }
18
+ )
19
+ const resp = await event.invoke()
20
+ expect(resp).to.not.be.null
21
+ expect(resp.err).to.be.undefined
22
+ expect(resp.data).to.be.equals('Success')
23
+ })
24
+
25
+ test('Simple failure', async () => {
26
+ const event = new GenericHandlerEvent(
27
+ <Request>(<unknown>{}),
28
+ async (event: APIGatewayProxyEvent, context: Context) => {
29
+ context.fail('Error!')
30
+ }
31
+ )
32
+ const resp = await event.invoke()
33
+ expect(resp).to.not.be.null
34
+ expect(resp.data).to.be.undefined
35
+ expect(resp.err).to.be.equals('Error!')
36
+ })
37
+
38
+ test('Simple done (errored)', async () => {
39
+ const event = new GenericHandlerEvent(
40
+ <Request>(<unknown>{}),
41
+ async (event: APIGatewayProxyEvent, context: Context) => {
42
+ context.done(new Error('Error!'))
43
+ }
44
+ )
45
+ const resp = await event.invoke()
46
+ expect(resp).to.not.be.null
47
+ expect(resp.data).to.be.undefined
48
+ expect(resp.err).to.be.an('Error')
49
+ if (resp.err instanceof Error) expect(resp.err?.message).to.be.equals('Error!')
50
+ })
51
+
52
+ test('Simple done (success)', async () => {
53
+ const event = new GenericHandlerEvent(
54
+ <Request>(<unknown>{}),
55
+ async (event: APIGatewayProxyEvent, context: Context) => {
56
+ context.done(undefined, 'Success!')
57
+ }
58
+ )
59
+ const resp = await event.invoke()
60
+ expect(resp).to.not.be.null
61
+ expect(resp.err).to.be.undefined
62
+ expect(resp.data).to.be.equals('Success!')
63
+ })
64
+
65
+ test('Exception on execution', async () => {
66
+ const event = new GenericHandlerEvent(<Request>(<unknown>{}), async () => {
67
+ throw new Error('Failed!')
68
+ })
69
+ let err: any = null,
70
+ resp: any = null
71
+ try {
72
+ resp = await event.invoke()
73
+ } catch (e) {
74
+ err = e
75
+ }
76
+ expect(resp).to.be.null
77
+ expect(err).to.not.be.null
78
+ expect(err).to.be.an('Error')
79
+ expect(err.message).to.be.equals('Failed!')
80
+ })
81
+ })
82
+
83
+ describe('GenericHandlerEvent event test', () => {
84
+ test('Simple event test', async () => {
85
+ const event = new GenericHandlerEvent(
86
+ <Request>(<unknown>{
87
+ headers: { Authorization: '123', 'x-forwarded-for': '127.0.0.1' },
88
+ method: HttpMethod.GET,
89
+ query: '/status?name=ryan',
90
+ }),
91
+ async (event: APIGatewayProxyEvent, context: Context) => {
92
+ expect(context.getRemainingTimeInMillis()).to.not.be.null
93
+ context.succeed('Success')
94
+ }
95
+ )
96
+ const resp = await event.invoke()
97
+ expect(resp).to.not.be.null
98
+ expect(resp.err).to.be.undefined
99
+ expect(resp.data).to.be.equals('Success')
100
+ })
101
+ })
102
+
103
+ export {}
@@ -0,0 +1,30 @@
1
+ import { jest } from '@jest/globals'
2
+ import { expect as c_expect } from 'chai'
3
+ import { Request, Response } from 'express'
4
+
5
+ import HealthHandler from '../../../../src/Server/lib/container/HealthHandler.js'
6
+
7
+ function observableResponse(): Response {
8
+ const resp = <Response>(<unknown>{
9
+ send: jest.fn(() => resp),
10
+ json: jest.fn(() => resp),
11
+ status: jest.fn(() => resp),
12
+ header: jest.fn(() => resp),
13
+ })
14
+ return resp
15
+ }
16
+
17
+ describe('HealthHandler invocation path', () => {
18
+ test('Simple', async () => {
19
+ const resp = observableResponse()
20
+ const handlerResp = await HealthHandler(<Request>(<unknown>{}), resp)
21
+ //
22
+ c_expect(handlerResp).to.be.undefined
23
+ expect(resp.send).toBeCalledWith('Healthy!')
24
+ expect(resp.json).not.toBeCalled()
25
+ expect(resp.status).not.toBeCalled()
26
+ expect(resp.header).not.toBeCalled()
27
+ })
28
+ })
29
+
30
+ export {}
@@ -0,0 +1,268 @@
1
+ import { jest } from '@jest/globals'
2
+ import { APIGatewayProxyEvent, Context } from 'aws-lambda'
3
+ import { expect as c_expect } from 'chai'
4
+ import request from 'supertest'
5
+
6
+ import Globals from '../../../../src/Globals.js'
7
+ import Proxy from '../../../../src/Server/lib/container/Proxy.js'
8
+ import { defaultUrl } from '../../../Test.utils.js'
9
+
10
+ describe('Proxy configs', () => {
11
+ // @ts-ignore
12
+ let mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {})
13
+ beforeAll(() => {
14
+ // @ts-ignore
15
+ mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {})
16
+ })
17
+ afterAll(() => {
18
+ mockExit.mockRestore()
19
+ })
20
+ beforeEach(() => {
21
+ mockExit.mockReset()
22
+ })
23
+
24
+ test('Empty config url & unload with error', async () => {
25
+ const proxy = new Proxy({ routes: [] }, async () => {})
26
+ await proxy.load()
27
+ await proxy.unload('Error')
28
+ expect(mockExit).toBeCalledWith(1)
29
+ })
30
+
31
+ test('Simple port config', async () => {
32
+ const proxy = new Proxy({ routes: [], port: 56562 }, async () => {})
33
+ await proxy.load()
34
+ await proxy.unload()
35
+ expect(mockExit).toBeCalledWith(0)
36
+ })
37
+
38
+ test('Simple timeout config', async () => {
39
+ const proxy = new Proxy({ routes: [], timeout: 1000 }, async () => {})
40
+ await proxy.load()
41
+ await proxy.unload()
42
+ expect(mockExit).toBeCalledWith(0)
43
+ })
44
+
45
+ test('Simple cors config', async () => {
46
+ const proxy = new Proxy(
47
+ {
48
+ routes: [],
49
+ cors: {
50
+ origin: '*',
51
+ headers: ['Authorization'],
52
+ allowCredentials: true,
53
+ },
54
+ },
55
+ async () => {}
56
+ )
57
+ await proxy.load()
58
+ await proxy.unload()
59
+ expect(mockExit).toBeCalledWith(0)
60
+ })
61
+
62
+ test('Empty cors config', async () => {
63
+ const proxy = new Proxy(
64
+ {
65
+ routes: [],
66
+ cors: {},
67
+ },
68
+ async () => {}
69
+ )
70
+ await proxy.load()
71
+ await proxy.unload()
72
+ expect(mockExit).toBeCalledWith(0)
73
+ })
74
+ })
75
+
76
+ describe('Proxy behaviour', () => {
77
+ // @ts-ignore
78
+ let mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {})
79
+ beforeAll(() => {
80
+ // @ts-ignore
81
+ mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {})
82
+ })
83
+ afterAll(() => {
84
+ mockExit.mockRestore()
85
+ })
86
+ beforeEach(() => {
87
+ mockExit.mockReset()
88
+ })
89
+
90
+ test('Stop twice', async () => {
91
+ const proxy = new Proxy({ routes: [] }, async () => {})
92
+ await proxy.load()
93
+ await Promise.all([proxy.unload('Error'), proxy.unload('Error')])
94
+ expect(mockExit).toHaveBeenCalledTimes(1)
95
+ expect(mockExit).toBeCalledWith(1)
96
+ })
97
+ })
98
+
99
+ describe('Proxy routing', () => {
100
+ // @ts-ignore
101
+ let mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {})
102
+ beforeAll(() => {
103
+ // @ts-ignore
104
+ mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {})
105
+ })
106
+ afterAll(() => {
107
+ mockExit.mockRestore()
108
+ })
109
+ beforeEach(() => {
110
+ mockExit.mockReset()
111
+ })
112
+
113
+ test('Health & Default handler', async () => {
114
+ let count = 0
115
+ const proxy = new Proxy(
116
+ { routes: [] },
117
+ async (event: APIGatewayProxyEvent, context: Context) => {
118
+ count++
119
+ context.succeed({
120
+ body: JSON.stringify({ name: '123' }),
121
+ statusCode: 200,
122
+ })
123
+ }
124
+ )
125
+ await proxy.load()
126
+ // Health check
127
+ const res = await request(defaultUrl)
128
+ .get(Globals.Listener_HTTP_DefaultHealthCheckRoute)
129
+ .expect('Content-Type', 'text/html; charset=utf-8')
130
+ .expect(200)
131
+ c_expect(res.text).to.be.equals('Healthy!')
132
+ // Generic handler
133
+ const resG = await request(defaultUrl)
134
+ .get(`/abc`)
135
+ .expect('Content-Type', 'application/json; charset=utf-8')
136
+ .expect(200)
137
+ c_expect(resG.body).to.be.deep.equals({ name: '123' })
138
+ // Expected count
139
+ c_expect(count).to.be.equals(1)
140
+ // Unload
141
+ await proxy.unload('Error')
142
+ expect(mockExit).toHaveBeenCalledTimes(1)
143
+ expect(mockExit).toBeCalledWith(1)
144
+ })
145
+
146
+ test('Proxy on custom port', async () => {
147
+ let count = 0
148
+ const port = 56542
149
+ const url = defaultUrl.replace(String(Globals.Listener_HTTP_DefaultPort), String(port))
150
+ const proxy = new Proxy(
151
+ { routes: [], port },
152
+ async (event: APIGatewayProxyEvent, context: Context) => {
153
+ count++
154
+ context.succeed({
155
+ body: JSON.stringify({ name: '123' }),
156
+ statusCode: 200,
157
+ })
158
+ }
159
+ )
160
+ await proxy.load()
161
+ // Health check
162
+ const res = await request(url)
163
+ .get(Globals.Listener_HTTP_DefaultHealthCheckRoute)
164
+ .expect('Content-Type', 'text/html; charset=utf-8')
165
+ .expect(200)
166
+ c_expect(res.text).to.be.equals('Healthy!')
167
+ // Generic handler
168
+ const resG = await request(url)
169
+ .get(`/abc`)
170
+ .expect('Content-Type', 'application/json; charset=utf-8')
171
+ .expect(200)
172
+ c_expect(resG.body).to.be.deep.equals({ name: '123' })
173
+ // Expected count
174
+ c_expect(count).to.be.equals(1)
175
+ // Unload
176
+ await proxy.unload()
177
+ expect(mockExit).toHaveBeenCalledTimes(1)
178
+ expect(mockExit).toBeCalledWith(0)
179
+ })
180
+
181
+ test('Proxy does timeout', async () => {
182
+ let count = 0
183
+ const timeout = 1000
184
+ const proxy = new Proxy(
185
+ { routes: [], timeout },
186
+ async (event: APIGatewayProxyEvent, context: Context) => {
187
+ count++
188
+ setTimeout(() => {
189
+ context.succeed({
190
+ body: JSON.stringify({ name: '123' }),
191
+ statusCode: 200,
192
+ })
193
+ }, timeout * 2)
194
+ }
195
+ )
196
+ await proxy.load()
197
+ // Health check
198
+ const res = await request(defaultUrl)
199
+ .get(Globals.Listener_HTTP_DefaultHealthCheckRoute)
200
+ .expect('Content-Type', 'text/html; charset=utf-8')
201
+ .expect(200)
202
+ c_expect(res.text).to.be.equals('Healthy!')
203
+ // Generic handler
204
+ let err: any = null
205
+ try {
206
+ await request(defaultUrl)
207
+ .get(`/abc`)
208
+ .expect('Content-Type', 'application/json; charset=utf-8')
209
+ .expect(200)
210
+ } catch (e) {
211
+ err = e
212
+ }
213
+ c_expect(err?.message).to.be.equals('socket hang up')
214
+ // Expected count
215
+ c_expect(count).to.be.equals(1)
216
+ // Unload
217
+ await proxy.unload('Error')
218
+ expect(mockExit).toHaveBeenCalledTimes(1)
219
+ expect(mockExit).toBeCalledWith(1)
220
+ //
221
+ return new Promise(resolve => {
222
+ setTimeout(resolve, timeout * 2)
223
+ })
224
+ })
225
+
226
+ test('Proxy respects cors', async () => {
227
+ let count = 0
228
+ const proxy = new Proxy(
229
+ {
230
+ routes: [],
231
+ cors: {
232
+ origin: '*',
233
+ headers: ['Authorization'],
234
+ allowCredentials: true,
235
+ },
236
+ },
237
+ async (event: APIGatewayProxyEvent, context: Context) => {
238
+ count++
239
+ context.succeed({
240
+ body: JSON.stringify({ name: '123' }),
241
+ statusCode: 200,
242
+ })
243
+ }
244
+ )
245
+ await proxy.load()
246
+ // White-listed header is allowed
247
+ const resWH = await request(defaultUrl).options(`/abc`).set('Authorization', '123').expect(204)
248
+ c_expect(resWH.header['access-control-allow-origin']).to.equal('*')
249
+ c_expect(resWH.header['access-control-allow-credentials']).to.equal('true')
250
+ c_expect(resWH.header['access-control-allow-headers']).to.equal('Authorization')
251
+ // Non white-listed header is allowed
252
+ const resNWH = await request(defaultUrl)
253
+ .options(`/abc`)
254
+ .set('2Authorization2', '123')
255
+ .expect(204)
256
+ c_expect(resNWH.header['access-control-allow-origin']).to.equal('*')
257
+ c_expect(resNWH.header['access-control-allow-credentials']).to.equal('true')
258
+ c_expect(resNWH.header['access-control-allow-headers']).to.equal('Authorization')
259
+ // Expected count
260
+ c_expect(count).to.be.equals(0)
261
+ // Unload
262
+ await proxy.unload()
263
+ expect(mockExit).toHaveBeenCalledTimes(1)
264
+ expect(mockExit).toBeCalledWith(0)
265
+ })
266
+ })
267
+
268
+ export {}
@@ -0,0 +1,47 @@
1
+ import { expect } from 'chai'
2
+
3
+ import * as Utils from '../../../../src/Server/lib/container/Utils.js'
4
+
5
+ describe('parseQueryStringParameters', () => {
6
+ test('Null url', () => {
7
+ // @ts-ignore
8
+ const validationResult = Utils.parseQueryStringParameters(null)
9
+ expect(validationResult).to.be.deep.equals({})
10
+ })
11
+
12
+ test('Empty url', () => {
13
+ const validationResult = Utils.parseQueryStringParameters('')
14
+ expect(validationResult).to.be.deep.equals({})
15
+ })
16
+
17
+ test('Simple param', () => {
18
+ const validationResult = Utils.parseQueryStringParameters('/status?name=ryan')
19
+ expect(validationResult).to.be.deep.equals({
20
+ name: 'ryan',
21
+ })
22
+ })
23
+ })
24
+
25
+ describe('parseMultiValueQueryStringParameters', () => {
26
+ test('Null url', () => {
27
+ // @ts-ignore
28
+ const validationResult = Utils.parseMultiValueQueryStringParameters()
29
+ expect(validationResult).to.be.deep.equals({})
30
+ })
31
+
32
+ test('Empty url', () => {
33
+ const validationResult = Utils.parseMultiValueQueryStringParameters('')
34
+ expect(validationResult).to.be.deep.equals({})
35
+ })
36
+
37
+ test('Simple multivalue param', () => {
38
+ const validationResult = Utils.parseMultiValueQueryStringParameters(
39
+ '/status?name=ryan&name=ryan2'
40
+ )
41
+ expect(validationResult).to.be.deep.equals({
42
+ name: ['ryan', 'ryan2'],
43
+ })
44
+ })
45
+ })
46
+
47
+ export {}
@@ -0,0 +1,78 @@
1
+ import { jest } from '@jest/globals'
2
+ import { APIGatewayEvent, Context, DynamoDBStreamEvent, SQSEvent } from 'aws-lambda'
3
+ import { z } from 'zod'
4
+
5
+ import Transaction from '../src/BaseEvent/Transaction.js'
6
+ import Globals from '../src/Globals.js'
7
+
8
+ export const defaultHeaders = {
9
+ 'Access-Control-Allow-Credentials': true,
10
+ 'Access-Control-Allow-Origin': '*',
11
+ 'Content-Type': 'application/json',
12
+ }
13
+
14
+ export const defaultUrl = `localhost:${Globals.Listener_HTTP_DefaultPort}`
15
+
16
+ export const SampleConfig = {
17
+ PATH: {
18
+ isLocal: true,
19
+ required: true,
20
+ },
21
+ PATH_FALSY: {
22
+ isLocal: true,
23
+ required: true,
24
+ },
25
+ PATH123: {
26
+ isLocal: true,
27
+ required: false,
28
+ },
29
+ TOKEN_SECRET: {
30
+ isRemote: true,
31
+ required: true,
32
+ },
33
+ TOKEN_SECRET_FALSY: {
34
+ isRemote: true,
35
+ required: false,
36
+ },
37
+ } as const
38
+
39
+ export function observableContext(data?: any) {
40
+ return <Context>(<unknown>{
41
+ done: jest.fn(),
42
+ fail: jest.fn(),
43
+ succeed: jest.fn(),
44
+ ...(data || {}),
45
+ })
46
+ }
47
+
48
+ export const privateKey = 'tMHOuszBQmF6XtwgrUpvqpk07rh3RATX'
49
+
50
+ export const foreignToken =
51
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
52
+
53
+ export const ViewSchema = z.object({
54
+ id: z.string(),
55
+ content: z.string(),
56
+ createdAt: z.date(),
57
+ updatedAt: z.date(),
58
+ })
59
+
60
+ export type View = z.infer<typeof ViewSchema>
61
+
62
+ export function emptyEvent(data?: any) {
63
+ return <APIGatewayEvent>(<unknown>data || {})
64
+ }
65
+
66
+ export function emptyQueueEvent(data?: any) {
67
+ return <SQSEvent>(<unknown>data || {})
68
+ }
69
+
70
+ export function emptyDynamoDBEvent(data?: any) {
71
+ return <DynamoDBStreamEvent>(<unknown>data || {})
72
+ }
73
+
74
+ export function observableTransaction() {
75
+ const t = new Transaction(emptyEvent(), observableContext())
76
+ t.responseProxy = jest.fn() as any
77
+ return t
78
+ }