@creator.co/wapi 1.7.1-alpha3 → 1.7.1

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 (114) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc.cjs +60 -0
  3. package/.github/workflows/npmpublish.yml +11 -0
  4. package/.github/workflows/prs.yml +13 -0
  5. package/dist/package-lock.json +2 -2
  6. package/dist/package.json +1 -1
  7. package/jest.config.ts +33 -0
  8. package/jest.smoke.config.ts +35 -0
  9. package/package.json +1 -1
  10. package/tests/API/Request.test.ts +273 -0
  11. package/tests/API/Response.test.ts +367 -0
  12. package/tests/API/Utils.test.ts +167 -0
  13. package/tests/BaseEvent/EventProcessor.test.ts +261 -0
  14. package/tests/BaseEvent/Process.test.ts +49 -0
  15. package/tests/BaseEvent/Transaction.test.ts +408 -0
  16. package/tests/Cache/Redis-client.test.ts +90 -0
  17. package/tests/Cache/Redis-cluster.test.ts +100 -0
  18. package/tests/Config/Config.test.ts +205 -0
  19. package/tests/Config/EnvironmentVar.test.ts +250 -0
  20. package/tests/Crypto/Crypto.test.ts +88 -0
  21. package/tests/Crypto/JWT.test.ts +92 -0
  22. package/tests/Database/DatabaseManager.test.ts +71 -0
  23. package/tests/Database/integrations/knex/KnexDatabase.test.ts +76 -0
  24. package/tests/Database/integrations/knex/KnexTransaction.test.ts +149 -0
  25. package/tests/Database/integrations/kysely/KyselyDatabase.test.ts +113 -0
  26. package/tests/Database/integrations/kysely/KyselyTransaction.test.ts +119 -0
  27. package/tests/Database/integrations/pg/PostgresDatabase.test.ts +76 -0
  28. package/tests/Database/integrations/pg/PostgresTransaction.test.ts +118 -0
  29. package/tests/Logger/Logger.test.ts +219 -0
  30. package/tests/Mailer/Mailer.test.ts +59 -0
  31. package/tests/Publisher/Publisher.test.ts +94 -0
  32. package/tests/Server/RouteResolver.test.ts +102 -0
  33. package/tests/Server/Router.test.ts +39 -0
  34. package/tests/Server/lib/ContainerServer.test.ts +531 -0
  35. package/tests/Server/lib/Server.test.ts +12 -0
  36. package/tests/Server/lib/container/GenericHandler.test.ts +131 -0
  37. package/tests/Server/lib/container/GenericHandlerEvent.test.ts +103 -0
  38. package/tests/Server/lib/container/HealthHandler.test.ts +30 -0
  39. package/tests/Server/lib/container/Proxy.test.ts +268 -0
  40. package/tests/Server/lib/container/Utils.test.ts +47 -0
  41. package/tests/Test.utils.ts +74 -0
  42. package/tests/Validation/Validator.test.ts +76 -0
  43. package/tsconfig.json +26 -0
  44. package/tsconfig.smoke.json +26 -0
  45. package/coverage/clover.xml +0 -1088
  46. package/coverage/coverage/coverage.txt +0 -40
  47. package/coverage/coverage-final.json +0 -37
  48. package/coverage/coverage-summary.json +0 -38
  49. package/coverage/coverage.txt +0 -59
  50. package/coverage/lcov-report/base.css +0 -224
  51. package/coverage/lcov-report/block-navigation.js +0 -87
  52. package/coverage/lcov-report/favicon.png +0 -0
  53. package/coverage/lcov-report/index.html +0 -371
  54. package/coverage/lcov-report/prettify.css +0 -1
  55. package/coverage/lcov-report/prettify.js +0 -2
  56. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  57. package/coverage/lcov-report/sorter.js +0 -196
  58. package/coverage/lcov-report/src/API/Request.ts.html +0 -727
  59. package/coverage/lcov-report/src/API/Response.ts.html +0 -1189
  60. package/coverage/lcov-report/src/API/Utils.ts.html +0 -313
  61. package/coverage/lcov-report/src/API/index.html +0 -131
  62. package/coverage/lcov-report/src/BaseEvent/EventProcessor.ts.html +0 -496
  63. package/coverage/lcov-report/src/BaseEvent/Process.ts.html +0 -346
  64. package/coverage/lcov-report/src/BaseEvent/Transaction.ts.html +0 -1015
  65. package/coverage/lcov-report/src/BaseEvent/index.html +0 -146
  66. package/coverage/lcov-report/src/Cache/Redis.ts.html +0 -367
  67. package/coverage/lcov-report/src/Cache/index.html +0 -116
  68. package/coverage/lcov-report/src/Config/Configuration.ts.html +0 -700
  69. package/coverage/lcov-report/src/Config/EnvironmentVar.ts.html +0 -526
  70. package/coverage/lcov-report/src/Config/index.html +0 -131
  71. package/coverage/lcov-report/src/Crypto/Crypto.ts.html +0 -352
  72. package/coverage/lcov-report/src/Crypto/JWT.ts.html +0 -337
  73. package/coverage/lcov-report/src/Crypto/index.html +0 -131
  74. package/coverage/lcov-report/src/Database/Database.ts.html +0 -151
  75. package/coverage/lcov-report/src/Database/DatabaseManager.ts.html +0 -289
  76. package/coverage/lcov-report/src/Database/DatabaseTransaction.ts.html +0 -595
  77. package/coverage/lcov-report/src/Database/index.html +0 -161
  78. package/coverage/lcov-report/src/Database/index.ts.html +0 -169
  79. package/coverage/lcov-report/src/Database/integrations/knex/KnexDatabase.ts.html +0 -283
  80. package/coverage/lcov-report/src/Database/integrations/knex/KnexTransaction.ts.html +0 -337
  81. package/coverage/lcov-report/src/Database/integrations/knex/index.html +0 -131
  82. package/coverage/lcov-report/src/Database/integrations/kysely/KyselyDatabase.ts.html +0 -376
  83. package/coverage/lcov-report/src/Database/integrations/kysely/KyselyTransaction.ts.html +0 -601
  84. package/coverage/lcov-report/src/Database/integrations/kysely/index.html +0 -131
  85. package/coverage/lcov-report/src/Database/integrations/pgsql/PostgresDatabase.ts.html +0 -250
  86. package/coverage/lcov-report/src/Database/integrations/pgsql/PostgresTransaction.ts.html +0 -346
  87. package/coverage/lcov-report/src/Database/integrations/pgsql/index.html +0 -131
  88. package/coverage/lcov-report/src/Database/types.d.ts.html +0 -232
  89. package/coverage/lcov-report/src/Globals.ts.html +0 -394
  90. package/coverage/lcov-report/src/Logger/Logger.ts.html +0 -1138
  91. package/coverage/lcov-report/src/Logger/index.html +0 -116
  92. package/coverage/lcov-report/src/Mailer/Mailer.ts.html +0 -754
  93. package/coverage/lcov-report/src/Mailer/index.html +0 -116
  94. package/coverage/lcov-report/src/Publisher/Publisher.ts.html +0 -460
  95. package/coverage/lcov-report/src/Publisher/index.html +0 -116
  96. package/coverage/lcov-report/src/Server/RouteResolver.ts.html +0 -442
  97. package/coverage/lcov-report/src/Server/Router.ts.html +0 -616
  98. package/coverage/lcov-report/src/Server/index.html +0 -131
  99. package/coverage/lcov-report/src/Server/lib/ContainerServer.ts.html +0 -280
  100. package/coverage/lcov-report/src/Server/lib/Server.ts.html +0 -403
  101. package/coverage/lcov-report/src/Server/lib/container/GenericHandler.ts.html +0 -331
  102. package/coverage/lcov-report/src/Server/lib/container/GenericHandlerEvent.ts.html +0 -547
  103. package/coverage/lcov-report/src/Server/lib/container/HealthHandler.ts.html +0 -118
  104. package/coverage/lcov-report/src/Server/lib/container/Proxy.ts.html +0 -619
  105. package/coverage/lcov-report/src/Server/lib/container/Utils.ts.html +0 -184
  106. package/coverage/lcov-report/src/Server/lib/container/index.html +0 -176
  107. package/coverage/lcov-report/src/Server/lib/index.html +0 -131
  108. package/coverage/lcov-report/src/Util/AsyncSingleton.ts.html +0 -343
  109. package/coverage/lcov-report/src/Util/Utils.ts.html +0 -313
  110. package/coverage/lcov-report/src/Util/index.html +0 -131
  111. package/coverage/lcov-report/src/Validation/Validator.ts.html +0 -217
  112. package/coverage/lcov-report/src/Validation/index.html +0 -116
  113. package/coverage/lcov-report/src/index.html +0 -116
  114. package/coverage/lcov.info +0 -2326
@@ -0,0 +1,90 @@
1
+ import { jest } from '@jest/globals'
2
+
3
+ import Redis from '../../src/Cache/Redis'
4
+
5
+ let _connectionId = 1
6
+
7
+ async function simpleRedisTest(config: any, concurrent?: boolean) {
8
+ const RedisMock = jest.fn(() => {
9
+ let opened = false
10
+ const connectionId = _connectionId++
11
+ return {
12
+ connectionId,
13
+ isOpen: () => opened,
14
+ close: () => (opened = false),
15
+ connect: jest.fn(() => {
16
+ opened = true
17
+ return {
18
+ mget: jest.fn(() => {
19
+ return true
20
+ }),
21
+ }
22
+ }),
23
+ } as any
24
+ })
25
+ Redis['ClientFactory'] = RedisMock
26
+ // Double call is intentional
27
+ const [provider, provider2] = concurrent
28
+ ? await Promise.all([Redis.connection(config), Redis.connection(config)])
29
+ : [await Redis.connection(config), await Redis.connection(config)]
30
+
31
+ // client checks
32
+ expect(RedisMock).toHaveBeenNthCalledWith(1, {
33
+ username: config.username,
34
+ ...(config.password ? { password: config.password } : {}),
35
+ disableOfflineQueue: true,
36
+ socket: {
37
+ host: config.hostname,
38
+ tls: config.enableTLS,
39
+ connectTimeout: 10000,
40
+ },
41
+ })
42
+ // Does not have double connection
43
+ expect(provider['connectionId']).toEqual(provider2['connectionId'])
44
+ expect(provider.connect).toHaveBeenCalledTimes(1)
45
+ expect(provider2.connect).toHaveBeenCalledTimes(1)
46
+ }
47
+
48
+ describe('Redis (client)', () => {
49
+ beforeEach(async () => {
50
+ // hack to close singleton connection
51
+ if (Redis['singleton'].getValue()) Redis['singleton'].clear()
52
+ })
53
+ test('Simple redis - do not connect twice', async () => {
54
+ await simpleRedisTest({
55
+ hostname: 'redis://localhost',
56
+ username: 'gabe',
57
+ password: 'mypassword',
58
+ enableTLS: true,
59
+ type: 'redis',
60
+ })
61
+ })
62
+ test('Simple redis (no SSL) - do not connect twice', async () => {
63
+ await simpleRedisTest({
64
+ hostname: 'redis://localhost',
65
+ username: 'gabe',
66
+ password: 'mypassword',
67
+ enableTLS: false,
68
+ type: 'redis',
69
+ })
70
+ })
71
+ test('Simple redis (passwordless) - do not connect twice', async () => {
72
+ await simpleRedisTest({
73
+ hostname: 'redis://localhost',
74
+ username: 'gabe',
75
+ enableTLS: false,
76
+ type: 'redis',
77
+ })
78
+ })
79
+ test('Concurrent redis - do not connect twice', async () => {
80
+ await simpleRedisTest(
81
+ {
82
+ hostname: 'redis://localhost',
83
+ username: 'gabe',
84
+ enableTLS: false,
85
+ type: 'redis',
86
+ },
87
+ true
88
+ )
89
+ })
90
+ })
@@ -0,0 +1,100 @@
1
+ import { jest } from '@jest/globals'
2
+
3
+ import Redis from '../../src/Cache/Redis'
4
+
5
+ let _connectionId = 1
6
+
7
+ async function simpleRedisTest(config: any, concurrent?: boolean) {
8
+ const RedisMock = jest.fn(() => {
9
+ let opened = false
10
+ const connectionId = _connectionId++
11
+ return {
12
+ connectionId,
13
+ isOpen: () => opened,
14
+ close: () => (opened = false),
15
+ connect: jest.fn(() => {
16
+ opened = true
17
+ return {
18
+ mget: jest.fn(() => {
19
+ return true
20
+ }),
21
+ }
22
+ }),
23
+ } as any
24
+ })
25
+ Redis['ClusterFactory'] = RedisMock
26
+ // Double call is intentional
27
+ const [provider, provider2] = concurrent
28
+ ? await Promise.all([Redis.connection(config), Redis.connection(config)])
29
+ : [await Redis.connection(config), await Redis.connection(config)]
30
+
31
+ // client checks
32
+ expect(RedisMock).toHaveBeenNthCalledWith(1, {
33
+ defaults: {
34
+ username: config.username,
35
+ ...(config.password ? { password: config.password } : {}),
36
+ socket: {
37
+ tls: config.enableTLS,
38
+ connectTimeout: 10000,
39
+ },
40
+ },
41
+ rootNodes: [
42
+ {
43
+ url: `redis://${config.username}:${config.username}@${config.hostname}:6379`,
44
+ disableOfflineQueue: true,
45
+ },
46
+ ],
47
+ })
48
+ // Does not have double connection
49
+ expect(provider['connectionId']).toEqual(provider2['connectionId'])
50
+ expect(provider.connect).toHaveBeenCalledTimes(1)
51
+ expect(provider2.connect).toHaveBeenCalledTimes(1)
52
+ }
53
+
54
+ describe('Redis (cluster)', () => {
55
+ beforeEach(async () => {
56
+ // hack to close singleton connection
57
+ if (Redis['singleton'].getValue()) Redis['singleton'].clear()
58
+ })
59
+ test('Simple redis - do not connect twice', async () => {
60
+ await simpleRedisTest({
61
+ hostname: 'redis://localhost',
62
+ username: 'gabe',
63
+ password: 'mypassword',
64
+ enableTLS: true,
65
+ clusterMode: true,
66
+ type: 'redis',
67
+ })
68
+ })
69
+ test('Simple redis (no SSL) - do not connect twice', async () => {
70
+ await simpleRedisTest({
71
+ hostname: 'redis://localhost',
72
+ username: 'gabe',
73
+ password: 'mypassword',
74
+ enableTLS: false,
75
+ clusterMode: true,
76
+ type: 'redis',
77
+ })
78
+ })
79
+ test('Simple redis (passwordless) - do not connect twice', async () => {
80
+ await simpleRedisTest({
81
+ hostname: 'redis://localhost',
82
+ username: 'gabe',
83
+ enableTLS: false,
84
+ clusterMode: true,
85
+ type: 'redis',
86
+ })
87
+ })
88
+ test('Concurrent redis - do not connect twice', async () => {
89
+ await simpleRedisTest(
90
+ {
91
+ hostname: 'redis://localhost',
92
+ username: 'gabe',
93
+ enableTLS: false,
94
+ clusterMode: true,
95
+ type: 'redis',
96
+ },
97
+ true
98
+ )
99
+ })
100
+ })
@@ -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'
6
+ import { SampleConfig } from '../Test.utils'
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,250 @@
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
+ ...(type == EnvironmentType.PlainRemote
21
+ ? {
22
+ Parameter: {
23
+ Value: undefined,
24
+ },
25
+ }
26
+ : {
27
+ SecretString: undefined,
28
+ }),
29
+ })
30
+ let err = null
31
+ try {
32
+ const env = new EnvironmentVar('abc', type, true)
33
+ env.syncResolve()
34
+ } catch (e) {
35
+ err = e
36
+ }
37
+ expect(err).is.not.null
38
+ expect(err?.['message']).is.not.null
39
+ })
40
+
41
+ test('Optional value with null value', async () => {
42
+ mock.on(command).resolves({
43
+ ...(type == EnvironmentType.PlainRemote
44
+ ? {
45
+ Parameter: {
46
+ Value: undefined,
47
+ },
48
+ }
49
+ : {
50
+ SecretString: undefined,
51
+ }),
52
+ })
53
+ const env = new EnvironmentVar('abc', type, true)
54
+ const token = await env.resolve()
55
+ expect(token).is.undefined
56
+ })
57
+
58
+ test('Optional value with empty response', async () => {
59
+ mock.on(command).resolves({})
60
+ const env = new EnvironmentVar('abc', type, true)
61
+ const token = await env.resolve()
62
+ expect(token).is.undefined
63
+ })
64
+
65
+ test('Optional value with valid response', async () => {
66
+ const value = 'abc'
67
+ mock.on(command).resolves({
68
+ ...(type == EnvironmentType.PlainRemote
69
+ ? {
70
+ Parameter: {
71
+ Value: value,
72
+ },
73
+ }
74
+ : {
75
+ SecretString: value,
76
+ }),
77
+ })
78
+ const env = new EnvironmentVar(value, type, true)
79
+ const token = await env.resolve()
80
+ expect(token).is.not.undefined
81
+ expect(token).to.be.equals(value)
82
+ })
83
+
84
+ test('Optional value rejection', async () => {
85
+ const value = 'abc'
86
+ mock.on(command).rejects(new Error('failed!'))
87
+ const env = new EnvironmentVar(value, type, true)
88
+ const token = await env.resolve()
89
+ expect(token).is.undefined
90
+ })
91
+ })
92
+
93
+ describe(`Required ${type} environment`, () => {
94
+ // reset mock
95
+ beforeEach(() => {
96
+ mock.reset()
97
+ })
98
+
99
+ test('Does not accept sync resolve', async () => {
100
+ mock.on(command).resolves({
101
+ ...(type == EnvironmentType.PlainRemote
102
+ ? {
103
+ Parameter: {
104
+ Value: undefined,
105
+ },
106
+ }
107
+ : {
108
+ SecretString: undefined,
109
+ }),
110
+ })
111
+ let err = null
112
+ try {
113
+ const env = new EnvironmentVar('abc', type)
114
+ env.syncResolve()
115
+ } catch (e) {
116
+ err = e
117
+ }
118
+ expect(err).is.not.null
119
+ expect(err?.['message']).is.not.null
120
+ })
121
+
122
+ test('Required fails when null', async () => {
123
+ mock.on(command).resolves({
124
+ ...(type == EnvironmentType.PlainRemote
125
+ ? {
126
+ Parameter: {
127
+ Value: undefined,
128
+ },
129
+ }
130
+ : {
131
+ SecretString: undefined,
132
+ }),
133
+ })
134
+ let err = null
135
+ try {
136
+ const env = new EnvironmentVar('abc', type)
137
+ await env.resolve()
138
+ } catch (e) {
139
+ err = e
140
+ }
141
+ console.log(err)
142
+ expect(err).is.not.null
143
+ expect(err?.['message']).is.not.null
144
+ })
145
+
146
+ test('Required fails when empty response', async () => {
147
+ mock.on(command).resolves({})
148
+ let err = null
149
+ try {
150
+ const env = new EnvironmentVar('abc', type)
151
+ await env.resolve()
152
+ } catch (e) {
153
+ err = e
154
+ }
155
+ expect(err).is.not.null
156
+ expect(err?.['message']).is.not.null
157
+ })
158
+
159
+ test('Required value with valid response', async () => {
160
+ const value = 'abc'
161
+ mock.on(command).resolves({
162
+ ...(type == EnvironmentType.PlainRemote
163
+ ? {
164
+ Parameter: {
165
+ Value: value,
166
+ },
167
+ }
168
+ : {
169
+ SecretString: value,
170
+ }),
171
+ })
172
+ const env = new EnvironmentVar(value, type)
173
+ const token = await env.resolve()
174
+ expect(token).is.not.undefined
175
+ expect(token).to.be.equals(value)
176
+ })
177
+
178
+ test('Required value rejection', async () => {
179
+ mock.on(command).rejects(new Error('failed!'))
180
+ let err = null
181
+ try {
182
+ const env = new EnvironmentVar('abc', type)
183
+ await env.resolve()
184
+ } catch (e) {
185
+ err = e
186
+ }
187
+ expect(err).is.not.null
188
+ expect(err?.['message']).is.not.null
189
+ })
190
+ })
191
+ }
192
+
193
+ /* Remote envs test */
194
+ testRemoteEnv(SSMMock, EnvironmentType.PlainRemote, GetParameterCommand)
195
+ testRemoteEnv(SecretsManagerMock, EnvironmentType.SecureRemote, GetSecretValueCommand)
196
+
197
+ describe('Optional Local environment', () => {
198
+ test('Does accept async resolve', async () => {
199
+ const env = new EnvironmentVar('PATH123', EnvironmentType.Local, true)
200
+ const v = await env.resolve()
201
+ expect(v).is.undefined
202
+ })
203
+
204
+ test('Optional value with null value', async () => {
205
+ const env = new EnvironmentVar('PATH123', EnvironmentType.Local, true)
206
+ const token = env.syncResolve()
207
+ expect(token).is.undefined
208
+ })
209
+
210
+ test('Optional value with valid value', async () => {
211
+ const key = 'PATH'
212
+ const env = new EnvironmentVar(key, EnvironmentType.Local, true)
213
+ const token = env.syncResolve()
214
+ expect(token).is.not.undefined
215
+ expect(token).to.be.equals(process.env[key])
216
+ })
217
+ })
218
+
219
+ describe('Required local environment', () => {
220
+ test('Does accept async resolve', async () => {
221
+ const key = 'PATH'
222
+ const env = new EnvironmentVar(key, EnvironmentType.Local)
223
+ const v = await env.resolve()
224
+ expect(v).is.not.null
225
+ expect(v).to.be.equals(process.env[key])
226
+ })
227
+
228
+ test('Required fails when null', async () => {
229
+ let err = null
230
+ try {
231
+ const env = new EnvironmentVar('PATH123', EnvironmentType.Local)
232
+ env.syncResolve()
233
+ } catch (e) {
234
+ err = e
235
+ }
236
+ console.log(err)
237
+ expect(err).is.not.null
238
+ expect(err?.['message']).is.not.null
239
+ })
240
+
241
+ test('Required value with valid value', async () => {
242
+ const key = 'PATH'
243
+ const env = new EnvironmentVar(key, EnvironmentType.Local)
244
+ const v = env.syncResolve()
245
+ expect(v).is.not.null
246
+ expect(v).to.be.equals(process.env[key])
247
+ })
248
+ })
249
+
250
+ export {}