@creator.co/wapi 1.2.1-beta6 → 1.2.3

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 (129) hide show
  1. package/.eslintrc.cjs +29 -22
  2. package/.github/workflows/npmpublish.yml +11 -19
  3. package/.github/workflows/prs.yml +13 -0
  4. package/index.ts +12 -10
  5. package/jest.config.ts +39 -0
  6. package/package.json +15 -4
  7. package/src/API/Request.ts +136 -44
  8. package/src/API/Response.ts +256 -46
  9. package/src/API/Utils.ts +60 -7
  10. package/src/BaseEvent/EventProcessor.ts +93 -28
  11. package/src/BaseEvent/Process.ts +69 -13
  12. package/src/BaseEvent/Transaction.ts +29 -50
  13. package/src/Config/Configuration.ts +119 -19
  14. package/src/Config/EnvironmentVar.ts +100 -21
  15. package/src/Crypto/Crypto.ts +78 -19
  16. package/src/Crypto/JWT.ts +53 -13
  17. package/src/Globals.ts +159 -27
  18. package/src/Logger/Logger.ts +204 -65
  19. package/src/Mailer/Mailer.ts +114 -31
  20. package/src/Publisher/Publisher.ts +57 -16
  21. package/src/Server/RouteResolver.ts +141 -0
  22. package/src/Server/Router.ts +84 -12
  23. package/src/Server/lib/ContainerServer.ts +53 -6
  24. package/src/Server/lib/Server.ts +82 -54
  25. package/src/Server/lib/container/GenericHandler.ts +15 -18
  26. package/src/Server/lib/container/GenericHandlerEvent.ts +78 -50
  27. package/src/Server/lib/container/HealthHandler.ts +2 -2
  28. package/src/Server/lib/container/Proxy.ts +114 -45
  29. package/src/Server/lib/container/Utils.ts +18 -27
  30. package/src/Validation/Validator.ts +23 -7
  31. package/tests/API/Request.test.ts +259 -0
  32. package/tests/API/Response.test.ts +367 -0
  33. package/tests/API/Utils.test.ts +157 -0
  34. package/tests/BaseEvent/EventProcessor.test.ts +262 -0
  35. package/tests/BaseEvent/Process.test.ts +49 -0
  36. package/tests/BaseEvent/Transaction.test.ts +222 -0
  37. package/tests/Config/Config.test.ts +193 -0
  38. package/tests/Config/EnvironmentVar.test.ts +214 -0
  39. package/tests/Crypto/Crypto.test.ts +88 -0
  40. package/tests/Crypto/JWT.test.ts +92 -0
  41. package/tests/Logger/Logger.test.ts +96 -0
  42. package/tests/Mailer/Mailer.test.ts +59 -0
  43. package/tests/Publisher/Publisher.test.ts +60 -0
  44. package/tests/Server/RouteResolver.test.ts +103 -0
  45. package/tests/Server/Router.test.ts +38 -0
  46. package/tests/Server/lib/ContainerServer.test.ts +327 -0
  47. package/tests/Server/lib/Server.test.ts +12 -0
  48. package/tests/Server/lib/container/GenericHandler.test.ts +131 -0
  49. package/tests/Server/lib/container/GenericHandlerEvent.test.ts +102 -0
  50. package/tests/Server/lib/container/HealthHandler.test.ts +30 -0
  51. package/tests/Server/lib/container/Proxy.test.ts +265 -0
  52. package/tests/Server/lib/container/Utils.test.ts +47 -0
  53. package/tests/Test.utils.ts +95 -0
  54. package/tests/Validation/Validator.test.ts +76 -0
  55. package/tests/main.test.ts +15 -0
  56. package/tsconfig.json +1 -0
  57. package/dist/index.d.ts +0 -11
  58. package/dist/index.js +0 -24
  59. package/dist/index.js.map +0 -1
  60. package/dist/package.json +0 -53
  61. package/dist/src/API/Request.d.ts +0 -21
  62. package/dist/src/API/Request.js +0 -86
  63. package/dist/src/API/Request.js.map +0 -1
  64. package/dist/src/API/Response.d.ts +0 -39
  65. package/dist/src/API/Response.js +0 -232
  66. package/dist/src/API/Response.js.map +0 -1
  67. package/dist/src/API/Utils.d.ts +0 -8
  68. package/dist/src/API/Utils.js +0 -49
  69. package/dist/src/API/Utils.js.map +0 -1
  70. package/dist/src/BaseEvent/EventProcessor.d.ts +0 -13
  71. package/dist/src/BaseEvent/EventProcessor.js +0 -151
  72. package/dist/src/BaseEvent/EventProcessor.js.map +0 -1
  73. package/dist/src/BaseEvent/Process.d.ts +0 -12
  74. package/dist/src/BaseEvent/Process.js +0 -114
  75. package/dist/src/BaseEvent/Process.js.map +0 -1
  76. package/dist/src/BaseEvent/Transaction.d.ts +0 -29
  77. package/dist/src/BaseEvent/Transaction.js +0 -248
  78. package/dist/src/BaseEvent/Transaction.js.map +0 -1
  79. package/dist/src/Config/Configuration.d.ts +0 -34
  80. package/dist/src/Config/Configuration.js +0 -93
  81. package/dist/src/Config/Configuration.js.map +0 -1
  82. package/dist/src/Config/EnvironmentVar.d.ts +0 -17
  83. package/dist/src/Config/EnvironmentVar.js +0 -152
  84. package/dist/src/Config/EnvironmentVar.js.map +0 -1
  85. package/dist/src/Crypto/Crypto.d.ts +0 -8
  86. package/dist/src/Crypto/Crypto.js +0 -84
  87. package/dist/src/Crypto/Crypto.js.map +0 -1
  88. package/dist/src/Crypto/JWT.d.ts +0 -16
  89. package/dist/src/Crypto/JWT.js +0 -49
  90. package/dist/src/Crypto/JWT.js.map +0 -1
  91. package/dist/src/Globals.d.ts +0 -21
  92. package/dist/src/Globals.js +0 -35
  93. package/dist/src/Globals.js.map +0 -1
  94. package/dist/src/Logger/Logger.d.ts +0 -34
  95. package/dist/src/Logger/Logger.js +0 -345
  96. package/dist/src/Logger/Logger.js.map +0 -1
  97. package/dist/src/Mailer/Mailer.d.ts +0 -12
  98. package/dist/src/Mailer/Mailer.js +0 -234
  99. package/dist/src/Mailer/Mailer.js.map +0 -1
  100. package/dist/src/Publisher/Publisher.d.ts +0 -10
  101. package/dist/src/Publisher/Publisher.js +0 -109
  102. package/dist/src/Publisher/Publisher.js.map +0 -1
  103. package/dist/src/Server/Router.d.ts +0 -27
  104. package/dist/src/Server/Router.js +0 -22
  105. package/dist/src/Server/Router.js.map +0 -1
  106. package/dist/src/Server/lib/ContainerServer.d.ts +0 -11
  107. package/dist/src/Server/lib/ContainerServer.js +0 -103
  108. package/dist/src/Server/lib/ContainerServer.js.map +0 -1
  109. package/dist/src/Server/lib/Server.d.ts +0 -9
  110. package/dist/src/Server/lib/Server.js +0 -141
  111. package/dist/src/Server/lib/Server.js.map +0 -1
  112. package/dist/src/Server/lib/container/GenericHandler.d.ts +0 -4
  113. package/dist/src/Server/lib/container/GenericHandler.js +0 -136
  114. package/dist/src/Server/lib/container/GenericHandler.js.map +0 -1
  115. package/dist/src/Server/lib/container/GenericHandlerEvent.d.ts +0 -14
  116. package/dist/src/Server/lib/container/GenericHandlerEvent.js +0 -164
  117. package/dist/src/Server/lib/container/GenericHandlerEvent.js.map +0 -1
  118. package/dist/src/Server/lib/container/HealthHandler.d.ts +0 -3
  119. package/dist/src/Server/lib/container/HealthHandler.js +0 -44
  120. package/dist/src/Server/lib/container/HealthHandler.js.map +0 -1
  121. package/dist/src/Server/lib/container/Proxy.d.ts +0 -15
  122. package/dist/src/Server/lib/container/Proxy.js +0 -157
  123. package/dist/src/Server/lib/container/Proxy.js.map +0 -1
  124. package/dist/src/Server/lib/container/Utils.d.ts +0 -6
  125. package/dist/src/Server/lib/container/Utils.js +0 -109
  126. package/dist/src/Server/lib/container/Utils.js.map +0 -1
  127. package/dist/src/Validation/Validator.d.ts +0 -5
  128. package/dist/src/Validation/Validator.js +0 -31
  129. package/dist/src/Validation/Validator.js.map +0 -1
@@ -0,0 +1,193 @@
1
+ import { SSMClient, GetParameterCommand } from '@aws-sdk/client-ssm'
2
+ import { mockClient } from 'aws-sdk-client-mock'
3
+ import { expect } from 'chai'
4
+
5
+ import Configuration from '../../src/Config/Configuration'
6
+ import { SampleConfig, SampleConfigSchema } from '../Test.utils'
7
+
8
+ const SSMMock = mockClient(SSMClient)
9
+ const config = new Configuration<SampleConfigSchema>(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', async () => {
18
+ let err = null
19
+ try {
20
+ // @ts-ignore
21
+ config.get('TOKEN_SECRET')
22
+ } catch (e) {
23
+ err = e
24
+ }
25
+ expect(err).is.not.null
26
+ 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
+ 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
+ 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
+ expect(token).is.not.undefined
54
+ 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
+ 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', async () => {
72
+ let err = null
73
+ try {
74
+ // @ts-ignore
75
+ config.get('TOKEN_SECRET')
76
+ } catch (e) {
77
+ err = e
78
+ }
79
+ expect(err).is.not.null
80
+ 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
+ expect(err).is.not.null
96
+ 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
+ expect(err).is.not.null
108
+ 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
+ expect(token).is.not.undefined
120
+ 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
+ expect(err).is.not.null
132
+ 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
+ expect(token).is.undefined
144
+ })
145
+ })
146
+
147
+ describe(`Required local environment`, () => {
148
+ beforeEach(() => {
149
+ config['resetCache']()
150
+ })
151
+
152
+ test('Required value with null value', async () => {
153
+ let err = null
154
+ try {
155
+ config.get('PATH_FALSY')
156
+ } catch (e) {
157
+ err = e
158
+ }
159
+ expect(err).is.not.null
160
+ expect(err?.['message']).is.not.null
161
+ })
162
+
163
+ test('Required value with valid response', async () => {
164
+ const key = 'PATH'
165
+ const v = config.get(key)
166
+ expect(v).is.not.null
167
+ expect(v).to.be.equals(process.env[key])
168
+ })
169
+ })
170
+
171
+ describe(`Caching test`, () => {
172
+ test('Does cache previous fetched value', async () => {
173
+ const value = '123'
174
+ const key = 'TOKEN_SECRET'
175
+ // initial fetch
176
+ SSMMock.on(GetParameterCommand).resolves({
177
+ Parameter: {
178
+ Value: value,
179
+ },
180
+ })
181
+ const v = await config.asyncGet(key)
182
+ expect(v).is.not.null
183
+ expect(v).to.be.equals(value)
184
+ // subsequent fetch
185
+ SSMMock.reset()
186
+ SSMMock.on(GetParameterCommand).rejects(new Error('failed!'))
187
+ const v2 = await config.asyncGet(key)
188
+ expect(v2).is.not.null
189
+ expect(v2).to.be.equals(value)
190
+ })
191
+ })
192
+
193
+ export {}
@@ -0,0 +1,214 @@
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'
7
+
8
+ const SSMMock = mockClient(SSMClient)
9
+ const SecretsManagerMock = mockClient(SecretsManagerClient)
10
+
11
+ function testRemoteEnv(mock, type, command) {
12
+ describe(`Optional ${type} environment`, () => {
13
+ // reset mock
14
+ beforeEach(() => {
15
+ mock.reset()
16
+ })
17
+
18
+ test('Does not accept sync resolve', async () => {
19
+ mock.on(command).resolves({
20
+ Parameter: {
21
+ Value: undefined,
22
+ },
23
+ })
24
+ let err = null
25
+ try {
26
+ const env = new EnvironmentVar('abc', type, true)
27
+ env.syncResolve()
28
+ } catch (e) {
29
+ err = e
30
+ }
31
+ expect(err).is.not.null
32
+ expect(err?.['message']).is.not.null
33
+ })
34
+
35
+ test('Optional value with null value', async () => {
36
+ mock.on(command).resolves({
37
+ Parameter: {
38
+ Value: undefined,
39
+ },
40
+ })
41
+ const env = new EnvironmentVar('abc', type, true)
42
+ const token = await env.resolve()
43
+ expect(token).is.undefined
44
+ })
45
+
46
+ test('Optional value with empty response', async () => {
47
+ mock.on(command).resolves({})
48
+ const env = new EnvironmentVar('abc', type, true)
49
+ const token = await env.resolve()
50
+ expect(token).is.undefined
51
+ })
52
+
53
+ test('Optional value with valid response', async () => {
54
+ const value = 'abc'
55
+ mock.on(command).resolves({
56
+ Parameter: {
57
+ Value: value,
58
+ },
59
+ })
60
+ const env = new EnvironmentVar(value, type, true)
61
+ const token = await env.resolve()
62
+ expect(token).is.not.undefined
63
+ expect(token).to.be.equals(value)
64
+ })
65
+
66
+ test('Optional value rejection', async () => {
67
+ const value = 'abc'
68
+ mock.on(command).rejects(new Error('failed!'))
69
+ const env = new EnvironmentVar(value, type, true)
70
+ const token = await env.resolve()
71
+ expect(token).is.undefined
72
+ })
73
+ })
74
+
75
+ describe(`Required ${type} environment`, () => {
76
+ // reset mock
77
+ beforeEach(() => {
78
+ mock.reset()
79
+ })
80
+
81
+ test('Does not accept sync resolve', async () => {
82
+ mock.on(command).resolves({
83
+ Parameter: {
84
+ Value: undefined,
85
+ },
86
+ })
87
+ let err = null
88
+ try {
89
+ const env = new EnvironmentVar('abc', type)
90
+ env.syncResolve()
91
+ } catch (e) {
92
+ err = e
93
+ }
94
+ expect(err).is.not.null
95
+ expect(err?.['message']).is.not.null
96
+ })
97
+
98
+ test('Required fails when null', async () => {
99
+ mock.on(command).resolves({
100
+ Parameter: {
101
+ Value: undefined,
102
+ },
103
+ })
104
+ let err = null
105
+ try {
106
+ const env = new EnvironmentVar('abc', type)
107
+ await env.resolve()
108
+ } catch (e) {
109
+ err = e
110
+ }
111
+ console.log(err)
112
+ expect(err).is.not.null
113
+ expect(err?.['message']).is.not.null
114
+ })
115
+
116
+ test('Required fails when empty response', async () => {
117
+ mock.on(command).resolves({})
118
+ let err = null
119
+ try {
120
+ const env = new EnvironmentVar('abc', type)
121
+ await env.resolve()
122
+ } catch (e) {
123
+ err = e
124
+ }
125
+ expect(err).is.not.null
126
+ expect(err?.['message']).is.not.null
127
+ })
128
+
129
+ test('Required value with valid response', async () => {
130
+ const value = 'abc'
131
+ mock.on(command).resolves({
132
+ Parameter: {
133
+ Value: value,
134
+ },
135
+ })
136
+ const env = new EnvironmentVar(value, type)
137
+ const token = await env.resolve()
138
+ expect(token).is.not.undefined
139
+ expect(token).to.be.equals(value)
140
+ })
141
+
142
+ test('Required value rejection', async () => {
143
+ mock.on(command).rejects(new Error('failed!'))
144
+ let err = null
145
+ try {
146
+ const env = new EnvironmentVar('abc', type)
147
+ await env.resolve()
148
+ } catch (e) {
149
+ err = e
150
+ }
151
+ expect(err).is.not.null
152
+ expect(err?.['message']).is.not.null
153
+ })
154
+ })
155
+ }
156
+
157
+ /* Remote envs test */
158
+ testRemoteEnv(SSMMock, EnvironmentType.PlainRemote, GetParameterCommand)
159
+ testRemoteEnv(SecretsManagerMock, EnvironmentType.SecureRemote, GetSecretValueCommand)
160
+
161
+ describe('Optional Local environment', () => {
162
+ test('Does accept async resolve', async () => {
163
+ const env = new EnvironmentVar('PATH123', EnvironmentType.Local, true)
164
+ const v = await env.resolve()
165
+ expect(v).is.undefined
166
+ })
167
+
168
+ test('Optional value with null value', async () => {
169
+ const env = new EnvironmentVar('PATH123', EnvironmentType.Local, true)
170
+ const token = env.syncResolve()
171
+ expect(token).is.undefined
172
+ })
173
+
174
+ test('Optional value with valid value', async () => {
175
+ const key = 'PATH'
176
+ const env = new EnvironmentVar(key, EnvironmentType.Local, true)
177
+ const token = env.syncResolve()
178
+ expect(token).is.not.undefined
179
+ expect(token).to.be.equals(process.env[key])
180
+ })
181
+ })
182
+
183
+ describe('Required local environment', () => {
184
+ test('Does accept async resolve', async () => {
185
+ const key = 'PATH'
186
+ const env = new EnvironmentVar(key, EnvironmentType.Local)
187
+ const v = await env.resolve()
188
+ expect(v).is.not.null
189
+ expect(v).to.be.equals(process.env[key])
190
+ })
191
+
192
+ test('Required fails when null', async () => {
193
+ let err = null
194
+ try {
195
+ const env = new EnvironmentVar('PATH123', EnvironmentType.Local)
196
+ env.syncResolve()
197
+ } catch (e) {
198
+ err = e
199
+ }
200
+ console.log(err)
201
+ expect(err).is.not.null
202
+ expect(err?.['message']).is.not.null
203
+ })
204
+
205
+ test('Required value with valid value', async () => {
206
+ const key = 'PATH'
207
+ const env = new EnvironmentVar(key, EnvironmentType.Local)
208
+ const v = env.syncResolve()
209
+ expect(v).is.not.null
210
+ expect(v).to.be.equals(process.env[key])
211
+ })
212
+ })
213
+
214
+ 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'
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,92 @@
1
+ import { expect } from 'chai'
2
+
3
+ import JWT from '../../src/Crypto/JWT'
4
+ import { foreignToken, privateKey } from '../Test.utils'
5
+
6
+ describe('Creates token', () => {
7
+ const provider = new JWT(privateKey, '7d')
8
+ test('Creates token without explicity expiration', () => {
9
+ const token = provider.createToken({ userID: 123 })
10
+ expect(token).to.be.a('string')
11
+ expect(token).is.not.null
12
+ })
13
+
14
+ test('Creates token with explicity expiration', () => {
15
+ const token = provider.createToken({ userID: 123 }, '7d')
16
+ expect(token).to.be.a('string')
17
+ expect(token).is.not.null
18
+ })
19
+
20
+ test('Creates token with explicity token override', () => {
21
+ const token = provider.createToken({ userID: 123 }, '7d', privateKey)
22
+ expect(token).to.be.a('string')
23
+ expect(token).is.not.null
24
+ })
25
+
26
+ test('Creates token with explicity token options', () => {
27
+ const token = provider.createToken({ userID: 123 }, undefined, undefined, {
28
+ expiresIn: '7d',
29
+ })
30
+ expect(token).to.be.a('string')
31
+ expect(token).is.not.null
32
+ })
33
+
34
+ test('Creates token with no expiration', () => {
35
+ const localProvider = new JWT(privateKey)
36
+ const token = localProvider.createToken({ userID: 123 })
37
+ expect(token).to.be.a('string')
38
+ expect(token).is.not.null
39
+ })
40
+ })
41
+
42
+ describe('Validates token', () => {
43
+ const provider = new JWT(privateKey, '7d')
44
+ test('Succeed to validate just created token', () => {
45
+ // Creates token
46
+ const token = provider.createToken({ userID: 123 }, '7d', privateKey)
47
+ expect(token).to.be.a('string')
48
+ expect(token).is.not.null
49
+ // Validates token
50
+ const validationResp = provider.validateToken(token)
51
+ expect(validationResp).is.not.null
52
+ expect(validationResp.isValid).is.true
53
+ expect(validationResp['isExpired']).is.undefined
54
+ expect(validationResp['decodedToken']).is.not.null
55
+ expect(validationResp['decodedToken'].userID).to.be.equals(123)
56
+ expect(validationResp['decodedToken'].exp).to.be.a('number')
57
+ expect(validationResp['decodedToken'].exp).to.be.above(Date.now() / 1000)
58
+ })
59
+
60
+ test('Fails to validate invalid token', () => {
61
+ // Creates token
62
+ const token = provider.createToken({ userID: 123 }, '7d', privateKey)
63
+ // Validates token
64
+ const validationResp = provider.validateToken(token + '123')
65
+ expect(validationResp).is.not.null
66
+ expect(validationResp.isValid).is.false
67
+ expect(validationResp['isExpired']).is.undefined
68
+ expect(validationResp['decodedToken']).to.undefined
69
+ })
70
+
71
+ test('Fails to validate expired token', () => {
72
+ // Creates token
73
+ const token = provider.createToken({ userID: 123 }, '-7d', privateKey)
74
+ // Validates token
75
+ const validationResp = provider.validateToken(token)
76
+ expect(validationResp).is.not.null
77
+ expect(validationResp.isValid).is.false
78
+ expect(validationResp['isExpired']).is.true
79
+ expect(validationResp['decodedToken']).to.undefined
80
+ })
81
+
82
+ test('Fails to validate foreign token', () => {
83
+ // Validates token
84
+ const validationResp = provider.validateToken(foreignToken)
85
+ expect(validationResp).is.not.null
86
+ expect(validationResp.isValid).is.false
87
+ expect(validationResp['isExpired']).is.undefined
88
+ expect(validationResp['decodedToken']).to.undefined
89
+ })
90
+ })
91
+
92
+ export {}
@@ -0,0 +1,96 @@
1
+ // get console ref and mock before logger import
2
+ const consoleProxy = console
3
+ const mock = jest.spyOn(consoleProxy, 'log')
4
+ // import logger after first ref
5
+ import Logger from '../../src/Logger/Logger'
6
+ // get console reference after logger import
7
+ const transactionID = '123-456'
8
+
9
+ function setContainerFlag(isContainer: boolean) {
10
+ if (isContainer) {
11
+ process.env['HYBRIDLESS_RUNTIME'] = 'true'
12
+ } else {
13
+ process.env['HYBRIDLESS_RUNTIME'] = undefined
14
+ }
15
+ }
16
+
17
+ function fixLogTypePrefix(logType: string) {
18
+ if (logType == 'exception') return 'error'
19
+ if (logType == 'warning') return 'warn'
20
+ if (logType == 'log') return 'info'
21
+ return logType
22
+ }
23
+
24
+ function testLogs(isContainer: boolean, provider?: Logger) {
25
+ const type = isContainer ? 'container' : 'serverless'
26
+ const loggerType = !provider ? 'Console' : 'Logger'
27
+ const localProvider = provider || console
28
+
29
+ test(`${type} - ${loggerType} Log - Suppress sensitive info`, async () => {
30
+ setContainerFlag(isContainer)
31
+ localProvider.log('TEST', { password: '123' })
32
+ expect(consoleProxy.log).toHaveBeenNthCalledWith(
33
+ 1,
34
+ expect.stringContaining((isContainer ? `${transactionID} ` : '') + '[INFO] [Logger.test.ts:')
35
+ )
36
+ expect(consoleProxy.log).toHaveBeenNthCalledWith(
37
+ 1,
38
+ expect.stringContaining('] TEST **SUPPRESSED_SENSITIVE_DATA**')
39
+ )
40
+ })
41
+
42
+ test(`${type} - ${loggerType} Log - Suppress sensitive info (array)`, async () => {
43
+ setContainerFlag(isContainer)
44
+ localProvider.log('TEST2', [{ password: '123' }])
45
+ expect(consoleProxy.log).toHaveBeenNthCalledWith(
46
+ 1,
47
+ expect.stringContaining((isContainer ? `${transactionID} ` : '') + '[INFO] [Logger.test.ts:')
48
+ )
49
+ expect(consoleProxy.log).toHaveBeenNthCalledWith(
50
+ 1,
51
+ expect.stringContaining('] TEST2 **SUPPRESSED_SENSITIVE_DATA**')
52
+ )
53
+ })
54
+
55
+ for (const logType of ['log', 'debug', 'info', 'warn', 'warning', 'error', 'exception']) {
56
+ test(`${type} - ${loggerType} ${logType}`, async () => {
57
+ setContainerFlag(isContainer)
58
+ localProvider[logType](logType.toUpperCase())
59
+ // alias
60
+ const logTypePrefix = fixLogTypePrefix(logType)
61
+ expect(consoleProxy.log).toHaveBeenNthCalledWith(
62
+ 1,
63
+ expect.stringContaining(
64
+ (isContainer ? `${transactionID} ` : '') +
65
+ `[${logTypePrefix.toUpperCase()}] [Logger.test.ts:`
66
+ )
67
+ )
68
+ expect(consoleProxy.log).toHaveBeenNthCalledWith(
69
+ 1,
70
+ expect.stringContaining(`] ${logType.toUpperCase()}`)
71
+ )
72
+ })
73
+ }
74
+ }
75
+
76
+ describe('Logger', () => {
77
+ beforeEach(() => {
78
+ mock.mockClear()
79
+ })
80
+ const provider = new Logger(
81
+ {
82
+ logLevel: 'DEBUG',
83
+ sensitiveFilteringKeywords: true,
84
+ },
85
+ transactionID
86
+ )
87
+ provider.notGlobalLogger()
88
+ // Test serverless logs
89
+ testLogs(false, provider)
90
+ testLogs(false)
91
+ // Test container logs
92
+ testLogs(true, provider)
93
+ testLogs(true)
94
+ })
95
+
96
+ export {}