@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,205 @@
1
+ import { SSMClient, GetParameterCommand } from '@aws-sdk/client-ssm'
2
+ import { mockClient } from 'aws-sdk-client-mock'
3
+ import { expect as c_expect } from 'chai'
4
+
5
+ import Configuration from '../../src/Config/Configuration.js'
6
+ import { SampleConfig } from '../Test.utils.js'
7
+
8
+ const SSMMock = mockClient(SSMClient)
9
+ const config = new Configuration<typeof SampleConfig>(SampleConfig, 'my-prefix')
10
+ describe(`Optional remote environment`, () => {
11
+ // reset mock
12
+ beforeEach(() => {
13
+ SSMMock.reset()
14
+ config['resetCache']()
15
+ })
16
+
17
+ test('Does not accept sync get (+ compiler error)', async () => {
18
+ let err = null
19
+ try {
20
+ // @ts-expect-error
21
+ config.get('TOKEN_SECRET')
22
+ } catch (e) {
23
+ err = e
24
+ }
25
+ c_expect(err).is.not.null
26
+ c_expect(err?.['message']).is.not.null
27
+ })
28
+
29
+ test('Optional value with null value', async () => {
30
+ SSMMock.on(GetParameterCommand).resolves({
31
+ Parameter: {
32
+ Value: undefined,
33
+ },
34
+ })
35
+ const token = await config.asyncGet('TOKEN_SECRET_FALSY')
36
+ c_expect(token).is.undefined
37
+ })
38
+
39
+ test('Optional value with empty response', async () => {
40
+ SSMMock.on(GetParameterCommand).resolves({})
41
+ const token = await config.asyncGet('TOKEN_SECRET_FALSY')
42
+ c_expect(token).is.undefined
43
+ })
44
+
45
+ test('Optional value with valid response', async () => {
46
+ const value = 'abc'
47
+ SSMMock.on(GetParameterCommand).resolves({
48
+ Parameter: {
49
+ Value: value,
50
+ },
51
+ })
52
+ const token = await config.asyncGet('TOKEN_SECRET_FALSY')
53
+ c_expect(token).is.not.undefined
54
+ c_expect(token).to.be.equals(value)
55
+ })
56
+
57
+ test('Optional value rejection', async () => {
58
+ SSMMock.on(GetParameterCommand).rejects(new Error('failed!'))
59
+ const token = await config.asyncGet('TOKEN_SECRET_FALSY')
60
+ c_expect(token).is.undefined
61
+ })
62
+ })
63
+
64
+ describe(`Required remote environment`, () => {
65
+ // reset mock
66
+ beforeEach(() => {
67
+ SSMMock.reset()
68
+ config['resetCache']()
69
+ })
70
+
71
+ test('Does not accept sync get (+ compiler error)', async () => {
72
+ let err = null
73
+ try {
74
+ // @ts-expect-error
75
+ config.get('TOKEN_SECRET')
76
+ } catch (e) {
77
+ err = e
78
+ }
79
+ c_expect(err).is.not.null
80
+ c_expect(err?.['message']).is.not.null
81
+ })
82
+
83
+ test('Required value with null value', async () => {
84
+ SSMMock.on(GetParameterCommand).resolves({
85
+ Parameter: {
86
+ Value: undefined,
87
+ },
88
+ })
89
+ let err = null
90
+ try {
91
+ await config.asyncGet('TOKEN_SECRET')
92
+ } catch (e) {
93
+ err = e
94
+ }
95
+ c_expect(err).is.not.null
96
+ c_expect(err?.['message']).is.not.null
97
+ })
98
+
99
+ test('Required value with empty response', async () => {
100
+ SSMMock.on(GetParameterCommand).resolves({})
101
+ let err = null
102
+ try {
103
+ await config.asyncGet('TOKEN_SECRET')
104
+ } catch (e) {
105
+ err = e
106
+ }
107
+ c_expect(err).is.not.null
108
+ c_expect(err?.['message']).is.not.null
109
+ })
110
+
111
+ test('Required value with valid response', async () => {
112
+ const value = 'abc'
113
+ SSMMock.on(GetParameterCommand).resolves({
114
+ Parameter: {
115
+ Value: value,
116
+ },
117
+ })
118
+ const token = await config.asyncGet('TOKEN_SECRET')
119
+ c_expect(token).is.not.undefined
120
+ c_expect(token).to.be.equals(value)
121
+ })
122
+
123
+ test('Required value rejection', async () => {
124
+ SSMMock.on(GetParameterCommand).rejects(new Error('failed!'))
125
+ let err = null
126
+ try {
127
+ await config.asyncGet('TOKEN_SECRET')
128
+ } catch (e) {
129
+ err = e
130
+ }
131
+ c_expect(err).is.not.null
132
+ c_expect(err?.['message']).is.not.null
133
+ })
134
+ })
135
+
136
+ describe(`Optional local environment`, () => {
137
+ beforeEach(() => {
138
+ config['resetCache']()
139
+ })
140
+
141
+ test('Optional value with null value', async () => {
142
+ const token = config.get('PATH123')
143
+ c_expect(token).is.undefined
144
+ })
145
+ })
146
+
147
+ describe(`Required local environment`, () => {
148
+ beforeEach(() => {
149
+ config['resetCache']()
150
+ })
151
+
152
+ test('Test compiler error', async () => {
153
+ let err = null
154
+ try {
155
+ // @ts-expect-error
156
+ await config.asyncGet('PATH')
157
+ } catch (e) {
158
+ err = e
159
+ }
160
+ c_expect(err).is.not.null
161
+ c_expect(err?.['message']).is.not.null
162
+ })
163
+
164
+ test('Required value with null value', async () => {
165
+ let err = null
166
+ try {
167
+ config.get('PATH_FALSY')
168
+ } catch (e) {
169
+ err = e
170
+ }
171
+ c_expect(err).is.not.null
172
+ c_expect(err?.['message']).is.not.null
173
+ })
174
+
175
+ test('Required value with valid response', async () => {
176
+ const key = 'PATH'
177
+ const v = config.get(key)
178
+ c_expect(v).is.not.null
179
+ c_expect(v).to.be.equals(process.env[key])
180
+ })
181
+ })
182
+
183
+ describe(`Caching test`, () => {
184
+ test('Does cache previous fetched value', async () => {
185
+ const value = '123'
186
+ const key = 'TOKEN_SECRET'
187
+ // initial fetch
188
+ SSMMock.on(GetParameterCommand).resolves({
189
+ Parameter: {
190
+ Value: value,
191
+ },
192
+ })
193
+ const v = await config.asyncGet(key)
194
+ c_expect(v).is.not.null
195
+ c_expect(v).to.be.equals(value)
196
+ // subsequent fetch
197
+ SSMMock.reset()
198
+ SSMMock.on(GetParameterCommand).rejects(new Error('failed!'))
199
+ const v2 = await config.asyncGet(key)
200
+ c_expect(v2).is.not.null
201
+ c_expect(v2).to.be.equals(value)
202
+ })
203
+ })
204
+
205
+ export {}
@@ -0,0 +1,251 @@
1
+ import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager'
2
+ import { SSMClient, GetParameterCommand } from '@aws-sdk/client-ssm'
3
+ import { mockClient } from 'aws-sdk-client-mock'
4
+ import { expect } from 'chai'
5
+
6
+ import EnvironmentVar, { EnvironmentType } from '../../src/Config/EnvironmentVar.js'
7
+
8
+ const SSMMock = mockClient(SSMClient)
9
+ const SecretsManagerMock = mockClient(SecretsManagerClient)
10
+ const prefix = '/abc/test-01/'
11
+
12
+ function testRemoteEnv(mock, type, command) {
13
+ describe(`Optional ${type} environment`, () => {
14
+ // reset mock
15
+ beforeEach(() => {
16
+ mock.reset()
17
+ })
18
+
19
+ test('Does not accept sync resolve', async () => {
20
+ mock.on(command).resolves({
21
+ ...(type == EnvironmentType.PlainRemote
22
+ ? {
23
+ Parameter: {
24
+ Value: undefined,
25
+ },
26
+ }
27
+ : {
28
+ SecretString: undefined,
29
+ }),
30
+ })
31
+ let err = null
32
+ try {
33
+ const env = new EnvironmentVar('abc', type, true, prefix)
34
+ env.syncResolve()
35
+ } catch (e) {
36
+ err = e
37
+ }
38
+ expect(err).is.not.null
39
+ expect(err?.['message']).is.not.null
40
+ })
41
+
42
+ test('Optional value with null value', async () => {
43
+ mock.on(command).resolves({
44
+ ...(type == EnvironmentType.PlainRemote
45
+ ? {
46
+ Parameter: {
47
+ Value: undefined,
48
+ },
49
+ }
50
+ : {
51
+ SecretString: undefined,
52
+ }),
53
+ })
54
+ const env = new EnvironmentVar('abc', type, true, prefix)
55
+ const token = await env.resolve()
56
+ expect(token).is.undefined
57
+ })
58
+
59
+ test('Optional value with empty response', async () => {
60
+ mock.on(command).resolves({})
61
+ const env = new EnvironmentVar('abc', type, true, prefix)
62
+ const token = await env.resolve()
63
+ expect(token).is.undefined
64
+ })
65
+
66
+ test('Optional value with valid response', async () => {
67
+ const value = 'abc'
68
+ mock.on(command).resolves({
69
+ ...(type == EnvironmentType.PlainRemote
70
+ ? {
71
+ Parameter: {
72
+ Value: value,
73
+ },
74
+ }
75
+ : {
76
+ SecretString: value,
77
+ }),
78
+ })
79
+ const env = new EnvironmentVar(value, type, true, prefix)
80
+ const token = await env.resolve()
81
+ expect(token).is.not.undefined
82
+ expect(token).to.be.equals(value)
83
+ })
84
+
85
+ test('Optional value rejection', async () => {
86
+ const value = 'abc'
87
+ mock.on(command).rejects(new Error('failed!'))
88
+ const env = new EnvironmentVar(value, type, true, prefix)
89
+ const token = await env.resolve()
90
+ expect(token).is.undefined
91
+ })
92
+ })
93
+
94
+ describe(`Required ${type} environment`, () => {
95
+ // reset mock
96
+ beforeEach(() => {
97
+ mock.reset()
98
+ })
99
+
100
+ test('Does not accept sync resolve', async () => {
101
+ mock.on(command).resolves({
102
+ ...(type == EnvironmentType.PlainRemote
103
+ ? {
104
+ Parameter: {
105
+ Value: undefined,
106
+ },
107
+ }
108
+ : {
109
+ SecretString: undefined,
110
+ }),
111
+ })
112
+ let err = null
113
+ try {
114
+ const env = new EnvironmentVar('abc', type, undefined, prefix)
115
+ env.syncResolve()
116
+ } catch (e) {
117
+ err = e
118
+ }
119
+ expect(err).is.not.null
120
+ expect(err?.['message']).is.not.null
121
+ })
122
+
123
+ test('Required fails when null', async () => {
124
+ mock.on(command).resolves({
125
+ ...(type == EnvironmentType.PlainRemote
126
+ ? {
127
+ Parameter: {
128
+ Value: undefined,
129
+ },
130
+ }
131
+ : {
132
+ SecretString: undefined,
133
+ }),
134
+ })
135
+ let err = null
136
+ try {
137
+ const env = new EnvironmentVar('abc', type, false, prefix)
138
+ await env.resolve()
139
+ } catch (e) {
140
+ err = e
141
+ }
142
+ console.log(err)
143
+ expect(err).is.not.null
144
+ expect(err?.['message']).is.not.null
145
+ })
146
+
147
+ test('Required fails when empty response', async () => {
148
+ mock.on(command).resolves({})
149
+ let err = null
150
+ try {
151
+ const env = new EnvironmentVar('abc', type, false, prefix)
152
+ await env.resolve()
153
+ } catch (e) {
154
+ err = e
155
+ }
156
+ expect(err).is.not.null
157
+ expect(err?.['message']).is.not.null
158
+ })
159
+
160
+ test('Required value with valid response', async () => {
161
+ const value = 'abc'
162
+ mock.on(command).resolves({
163
+ ...(type == EnvironmentType.PlainRemote
164
+ ? {
165
+ Parameter: {
166
+ Value: value,
167
+ },
168
+ }
169
+ : {
170
+ SecretString: value,
171
+ }),
172
+ })
173
+ const env = new EnvironmentVar(value, type, false, prefix)
174
+ const token = await env.resolve()
175
+ expect(token).is.not.undefined
176
+ expect(token).to.be.equals(value)
177
+ })
178
+
179
+ test('Required value rejection', async () => {
180
+ mock.on(command).rejects(new Error('failed!'))
181
+ let err = null
182
+ try {
183
+ const env = new EnvironmentVar('abc', type, false, prefix)
184
+ await env.resolve()
185
+ } catch (e) {
186
+ err = e
187
+ }
188
+ expect(err).is.not.null
189
+ expect(err?.['message']).is.not.null
190
+ })
191
+ })
192
+ }
193
+
194
+ /* Remote envs test */
195
+ testRemoteEnv(SSMMock, EnvironmentType.PlainRemote, GetParameterCommand)
196
+ testRemoteEnv(SecretsManagerMock, EnvironmentType.SecureRemote, GetSecretValueCommand)
197
+
198
+ describe('Optional Local environment', () => {
199
+ test('Does accept async resolve', async () => {
200
+ const env = new EnvironmentVar('PATH123', EnvironmentType.Local, true, prefix)
201
+ const v = await env.resolve()
202
+ expect(v).is.undefined
203
+ })
204
+
205
+ test('Optional value with null value', async () => {
206
+ const env = new EnvironmentVar('PATH123', EnvironmentType.Local, true, prefix)
207
+ const token = env.syncResolve()
208
+ expect(token).is.undefined
209
+ })
210
+
211
+ test('Optional value with valid value', async () => {
212
+ const key = 'PATH'
213
+ const env = new EnvironmentVar(key, EnvironmentType.Local, true, prefix)
214
+ const token = env.syncResolve()
215
+ expect(token).is.not.undefined
216
+ expect(token).to.be.equals(process.env[key])
217
+ })
218
+ })
219
+
220
+ describe('Required local environment', () => {
221
+ test('Does accept async resolve', async () => {
222
+ const key = 'PATH'
223
+ const env = new EnvironmentVar(key, EnvironmentType.Local, false, prefix)
224
+ const v = await env.resolve()
225
+ expect(v).is.not.null
226
+ expect(v).to.be.equals(process.env[key])
227
+ })
228
+
229
+ test('Required fails when null', async () => {
230
+ let err = null
231
+ try {
232
+ const env = new EnvironmentVar('PATH123', EnvironmentType.Local, false, prefix)
233
+ env.syncResolve()
234
+ } catch (e) {
235
+ err = e
236
+ }
237
+ console.log(err)
238
+ expect(err).is.not.null
239
+ expect(err?.['message']).is.not.null
240
+ })
241
+
242
+ test('Required value with valid value', async () => {
243
+ const key = 'PATH'
244
+ const env = new EnvironmentVar(key, EnvironmentType.Local, false, prefix)
245
+ const v = env.syncResolve()
246
+ expect(v).is.not.null
247
+ expect(v).to.be.equals(process.env[key])
248
+ })
249
+ })
250
+
251
+ export {}
@@ -0,0 +1,88 @@
1
+ import { DecryptCommand, EncryptCommand, KMSClient } from '@aws-sdk/client-kms'
2
+ import { mockClient } from 'aws-sdk-client-mock'
3
+ import { expect } from 'chai'
4
+
5
+ import Crypto from '../../src/Crypto/Crypto.js'
6
+
7
+ const KMSMock = mockClient(KMSClient)
8
+
9
+ function fakeEncryption(v) {
10
+ const f = new TextEncoder().encode(v)
11
+ return Buffer.from(f as any, 'utf8').toString('hex')
12
+ }
13
+ function fakeDecryption(v) {
14
+ return new TextEncoder().encode(v)
15
+ }
16
+
17
+ describe('Encryption', () => {
18
+ // reset mock
19
+ beforeEach(() => {
20
+ KMSMock.reset()
21
+ })
22
+
23
+ const provider = new Crypto('ca-central-1', 'abc123')
24
+ test('Encrypts json object', async () => {
25
+ const encryptionObj = { userID: 123 }
26
+ KMSMock.on(EncryptCommand).resolves({
27
+ CiphertextBlob: new TextEncoder().encode(JSON.stringify(encryptionObj)),
28
+ })
29
+ const token = await provider.encryptData(encryptionObj)
30
+ expect(token).is.not.null
31
+ expect(token).to.be.equals(fakeEncryption(JSON.stringify(encryptionObj)))
32
+ })
33
+
34
+ test('Encrypts string', async () => {
35
+ const encryptionText = 'Hello encryption!'
36
+ KMSMock.on(EncryptCommand).resolves({
37
+ CiphertextBlob: new TextEncoder().encode(encryptionText),
38
+ })
39
+ const token = await provider.encryptData(encryptionText)
40
+ expect(token).is.not.null
41
+ expect(token).to.be.equals(fakeEncryption(encryptionText))
42
+ })
43
+
44
+ test('Fails to encrypt a number', async () => {
45
+ const encryptionText = 123
46
+ KMSMock.on(EncryptCommand).rejects(new Error('failed'))
47
+ const token = await provider.encryptData(encryptionText)
48
+ expect(token).is.null
49
+ })
50
+ })
51
+
52
+ describe('Decryption', () => {
53
+ // reset mock
54
+ beforeEach(() => {
55
+ KMSMock.reset()
56
+ })
57
+
58
+ const provider = new Crypto('ca-central-1', 'abc123')
59
+ test('Decrypts json object', async () => {
60
+ const encryptionObj = { userID: 123 }
61
+ KMSMock.on(DecryptCommand).resolves({
62
+ Plaintext: fakeDecryption(JSON.stringify(encryptionObj)),
63
+ })
64
+ const token = await provider.decryptData(fakeEncryption(JSON.stringify(encryptionObj)))
65
+ expect(token).is.not.null
66
+ expect(token).to.be.equals(JSON.stringify(encryptionObj))
67
+ })
68
+
69
+ test('Decrypts string', async () => {
70
+ const encryptionText = 'abc123'
71
+ KMSMock.on(DecryptCommand).resolves({
72
+ Plaintext: fakeDecryption(encryptionText),
73
+ })
74
+ const token = await provider.decryptData(fakeEncryption(encryptionText))
75
+ expect(token).is.not.null
76
+ expect(token).to.be.equals(encryptionText)
77
+ })
78
+
79
+ test('Fails to decrypt a number', async () => {
80
+ const encryptionText = 123
81
+ KMSMock.on(DecryptCommand).rejects(new Error('failed'))
82
+ // @ts-ignore
83
+ const token = await provider.decryptData(encryptionText)
84
+ expect(token).is.null
85
+ })
86
+ })
87
+
88
+ export {}
@@ -0,0 +1,79 @@
1
+ import { jest } from '@jest/globals'
2
+ import { expect } from 'chai'
3
+
4
+ import { DatabaseManager } from '../../src/Database/index.js'
5
+ import type { DatabaseType, DbConfig } from '../../src/Database/types.js'
6
+
7
+ type FakeDatabase = { host: string; tableName: string; type: 'pg' | 'kysely' | 'dynamo' }
8
+
9
+ const fakeConfig = (host: string, type: DatabaseType) => {
10
+ return {
11
+ type,
12
+ host,
13
+ } as DbConfig<typeof type>
14
+ }
15
+
16
+ const fakeNoSQLConfig = (tableName: string, type: DatabaseType) => {
17
+ return {
18
+ type,
19
+ tableName,
20
+ } as DbConfig<typeof type>
21
+ }
22
+
23
+ describe('Database Manager', () => {
24
+ test('should correctly create and cache database instances', () => {
25
+ const underTest = new DatabaseManager()
26
+
27
+ underTest['databases'] = {
28
+ pg: jest.fn((config: any) => {
29
+ return { host: config.host, type: 'pg' } as any
30
+ }) as any,
31
+ kysely: jest.fn((config: any) => {
32
+ return { host: config.host, type: 'kysely' } as any
33
+ }) as any,
34
+ dynamo: jest.fn((config: any) => {
35
+ return { tableName: config.tableName, type: 'dynamo' } as any
36
+ }) as any,
37
+ }
38
+
39
+ const create = config => underTest.create({ ...config }) as unknown as FakeDatabase
40
+
41
+ const pgConfig1 = fakeConfig('localhost', 'pg')
42
+ const pgConfig2 = fakeConfig('other', 'pg')
43
+ const kyselyConfig1 = fakeConfig('localhost', 'pg')
44
+ const kyselyConfig2 = fakeConfig('other', 'pg')
45
+ const dynamoConfig1 = fakeNoSQLConfig('localhost', 'dynamo')
46
+ const dynamoConfig2 = fakeNoSQLConfig('other', 'dynamo')
47
+
48
+ const pg1 = create(pgConfig1)
49
+ const pg2 = create(pgConfig1)
50
+ const pg3 = create(pgConfig2)
51
+
52
+ const kysely1 = create(kyselyConfig1)
53
+ const kysely2 = create(kyselyConfig1)
54
+ const kysely3 = create(kyselyConfig2)
55
+
56
+ const dynamo1 = create(dynamoConfig1)
57
+ const dynamo2 = create(dynamoConfig1)
58
+ const dynamo3 = create(dynamoConfig2)
59
+
60
+ expect(pg1).to.equal(pg2).to.not.equal(pg3)
61
+
62
+ expect(pgConfig1).to.be.deep.equal(pg1).to.be.deep.equal(pg2)
63
+
64
+ expect(pg3).to.be.deep.equal(pgConfig2)
65
+
66
+ expect(kysely1).to.equal(kysely2).to.not.equal(kysely3)
67
+
68
+ expect(kyselyConfig1).to.be.deep.equal(kysely1).to.be.deep.equal(kysely2)
69
+
70
+ expect(kysely3).to.be.deep.equal(kyselyConfig2)
71
+
72
+ expect(dynamo1).to.equal(dynamo2).to.not.equal(dynamo3).to.not.equal(pg1)
73
+ console.log(dynamoConfig1)
74
+ console.log(dynamo1)
75
+ expect(dynamoConfig1).to.be.deep.equal(dynamo1).to.be.deep.equal(dynamo2)
76
+
77
+ expect(dynamo3).to.be.deep.equal(dynamoConfig2)
78
+ })
79
+ })
@@ -0,0 +1,44 @@
1
+ import { Agent } from 'https'
2
+
3
+ import { DynamoDB } from '@aws-sdk/client-dynamodb'
4
+ import { jest } from '@jest/globals'
5
+ import { NodeHttpHandler } from '@smithy/node-http-handler'
6
+
7
+ import type { DbConfig } from '../../../../src/Database/index.js'
8
+ import { DynamoDatabase } from '../../../../src/Database/integrations/dynamo/DynamoDatabase.js'
9
+
10
+ const config: DbConfig<'dynamo'> = {
11
+ type: 'dynamo',
12
+ region: 'ca-central-1',
13
+ tableName: 'myTable',
14
+ }
15
+
16
+ const expectedImplConfig = {
17
+ region: config.region,
18
+ maxAttempts: 3,
19
+ requestHandler: new NodeHttpHandler({
20
+ connectionTimeout: 60000,
21
+ socketTimeout: 60000,
22
+ httpsAgent: new Agent({ keepAlive: false, maxSockets: 50, rejectUnauthorized: true }),
23
+ }),
24
+ }
25
+
26
+ describe('DynamoDatabase', () => {
27
+ test('DynamoDatabase', async () => {
28
+ const mockTrans = { a: 'b' } as any
29
+ const mockClient = jest.fn(
30
+ () =>
31
+ ({
32
+ test: async () => mockTrans,
33
+ }) as any as DynamoDB
34
+ )
35
+ DynamoDatabase['dynamoProvider'] = mockClient
36
+
37
+ const underTest = new DynamoDatabase(config)
38
+ expect(mockClient).toBeCalledWith(expectedImplConfig)
39
+
40
+ // no transaction
41
+ const trans = await underTest.transaction()
42
+ expect(trans).toBe(null)
43
+ })
44
+ })