@toa.io/extensions.configuration 1.1.0-dev.12 → 1.1.0-dev.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -6
- package/readme.md +32 -12
- package/source/.provider/env.js +19 -0
- package/source/.provider/index.js +7 -0
- package/source/provider.js +3 -1
- package/source/provider.test.js +43 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/extensions.configuration",
|
|
3
|
-
"version": "1.1.0-dev.
|
|
3
|
+
"version": "1.1.0-dev.15",
|
|
4
4
|
"description": "Toa Configuration",
|
|
5
5
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@toa.io/core": "1.1.0-dev.
|
|
20
|
-
"@toa.io/generic": "0.11.0-dev.
|
|
21
|
-
"@toa.io/schema": "0.7.6-dev.
|
|
22
|
-
"@toa.io/yaml": "0.7.6-dev.
|
|
19
|
+
"@toa.io/core": "1.1.0-dev.15",
|
|
20
|
+
"@toa.io/generic": "0.11.0-dev.15",
|
|
21
|
+
"@toa.io/schema": "0.7.6-dev.15",
|
|
22
|
+
"@toa.io/yaml": "0.7.6-dev.15",
|
|
23
23
|
"clone-deep": "4.0.1"
|
|
24
24
|
},
|
|
25
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "f479f6e79d5caaa207da4d0a3192425def1abf75"
|
|
26
26
|
}
|
package/readme.md
CHANGED
|
@@ -163,11 +163,6 @@ configuration:
|
|
|
163
163
|
bar@staging: 2
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
### Local environment
|
|
167
|
-
|
|
168
|
-
Configuration Objects for local environment may be created
|
|
169
|
-
by [`toa configure`](../../runtime/cli/readme.md#configure) command.
|
|
170
|
-
|
|
171
166
|
## Configuration Secrets
|
|
172
167
|
|
|
173
168
|
Context Configuration values which are uppercase strings prefixed with `$` considered as Secrets.
|
|
@@ -196,13 +191,13 @@ Deployed kubernetes secret's name is predefined as `configuration`.
|
|
|
196
191
|
$ toa conceal configuration STRIPE_API_KEY xxxxxxxx
|
|
197
192
|
```
|
|
198
193
|
|
|
199
|
-
##
|
|
200
|
-
|
|
201
|
-
Configuration Value is available as a well-known operation context extension `configuration`.
|
|
194
|
+
## Aspect
|
|
202
195
|
|
|
203
|
-
|
|
196
|
+
Configuration Value is available as a well-known operation Aspect `configuration`.
|
|
204
197
|
|
|
205
198
|
```javascript
|
|
199
|
+
// Node.js bridge
|
|
200
|
+
|
|
206
201
|
function transition (input, entity, context) {
|
|
207
202
|
const foo = context.configiuration.foo
|
|
208
203
|
|
|
@@ -216,21 +211,46 @@ function transition (input, entity, context) {
|
|
|
216
211
|
> from [hot updates](#).
|
|
217
212
|
>
|
|
218
213
|
> ```javascript
|
|
219
|
-
> //
|
|
214
|
+
> // NOT RECOMMENDED
|
|
220
215
|
> let foo
|
|
221
216
|
>
|
|
222
217
|
> function transition (input, entity, context) {
|
|
218
|
+
> // NOT RECOMMENDED
|
|
223
219
|
> if (foo === undefined) foo = context.configuration.foo
|
|
224
220
|
>
|
|
225
221
|
> // ...
|
|
226
222
|
> }
|
|
227
223
|
> ```
|
|
228
|
-
> See [Genuine operations](#).
|
|
224
|
+
> See [Genuine operations](/documentation/design.md#genuine-operations).
|
|
225
|
+
|
|
226
|
+
## Development Configuration
|
|
227
|
+
|
|
228
|
+
Configuration can be exported by [`toa env`](/runtime/cli/readme.md#env).
|
|
229
|
+
|
|
230
|
+
### Local Environment Placeholders
|
|
231
|
+
|
|
232
|
+
Context Configuration values may contain placeholders that reference environment variables.
|
|
233
|
+
Placeholders are replaced with values if the corresponding environment variables are set.
|
|
234
|
+
|
|
235
|
+
> Placeholders can only be used with local environment (exported by `toa env`), as these values are not
|
|
236
|
+
> deployed.
|
|
237
|
+
|
|
238
|
+
```yaml
|
|
239
|
+
# context.toa.yaml
|
|
240
|
+
configuration:
|
|
241
|
+
dummies.dummy:
|
|
242
|
+
url@local: https://stage${STAGE}.intranet/
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
```dotenv
|
|
246
|
+
# .env
|
|
247
|
+
STAGE=82
|
|
248
|
+
```
|
|
229
249
|
|
|
230
250
|
## Appendix
|
|
231
251
|
|
|
232
252
|
- [Discussion](./docs/discussion.md)
|
|
233
253
|
- [Configuration consistency](./docs/consistency.md)
|
|
234
254
|
|
|
235
|
-
[^1]: Cannot be changed without a deployment
|
|
255
|
+
[^1]: Cannot be changed without a deployment as new values are considered to be a subject of
|
|
236
256
|
testing. [#146](https://github.com/toa-io/toa/issues/146)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { map } = require('@toa.io/generic')
|
|
4
|
+
|
|
5
|
+
function env (object) {
|
|
6
|
+
return map(object,
|
|
7
|
+
/**
|
|
8
|
+
* @type {toa.generic.map.transform<string>}
|
|
9
|
+
*/
|
|
10
|
+
(value) => {
|
|
11
|
+
if (typeof value !== 'string') return
|
|
12
|
+
|
|
13
|
+
return value.replaceAll(RX, (match, variable) => process.env[variable] ?? match)
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const RX = /\${(?<variable>[A-Z0-9_]{1,32})}/g
|
|
18
|
+
|
|
19
|
+
exports.env = env
|
package/source/provider.js
CHANGED
|
@@ -6,7 +6,7 @@ const { decode, encode, empty, overwrite } = require('@toa.io/generic')
|
|
|
6
6
|
const { Connector } = require('@toa.io/core')
|
|
7
7
|
|
|
8
8
|
const { secrets } = require('./secrets')
|
|
9
|
-
const { form } = require('./.provider
|
|
9
|
+
const { env, form } = require('./.provider')
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @implements {toa.extensions.configuration.Provider}
|
|
@@ -88,6 +88,8 @@ class Provider extends Connector {
|
|
|
88
88
|
|
|
89
89
|
#set (object) {
|
|
90
90
|
object = this.#reveal(object)
|
|
91
|
+
object = env(object)
|
|
92
|
+
|
|
91
93
|
this.#merge(object)
|
|
92
94
|
|
|
93
95
|
this.object = empty(object) ? undefined : object
|
package/source/provider.test.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
/* eslint-disable no-template-curly-in-string */
|
|
4
|
+
|
|
3
5
|
const { generate } = require('randomstring')
|
|
4
6
|
const { encode } = require('@toa.io/generic')
|
|
5
7
|
|
|
@@ -52,6 +54,44 @@ it('should replace nested secrets', async () => {
|
|
|
52
54
|
expect(value).toStrictEqual({ foo: { bar: secrets.BAR } })
|
|
53
55
|
})
|
|
54
56
|
|
|
57
|
+
it('should replace placeholders', async () => {
|
|
58
|
+
const name = 'FOO_VALUE'
|
|
59
|
+
const configuration = { foo: { bar: 'foo_${' + name + '}' } }
|
|
60
|
+
const value = generate()
|
|
61
|
+
|
|
62
|
+
setEnv(configuration)
|
|
63
|
+
setVal(name, value)
|
|
64
|
+
|
|
65
|
+
await provider.open()
|
|
66
|
+
const source = provider.source()
|
|
67
|
+
|
|
68
|
+
expect(source).toStrictEqual({ foo: { bar: 'foo_' + value } })
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('should replace multiple placeholders', async () => {
|
|
72
|
+
const configuration = { foo: '${FOO} ${BAR}' }
|
|
73
|
+
|
|
74
|
+
setEnv(configuration)
|
|
75
|
+
setVal('FOO', 'hello')
|
|
76
|
+
setVal('BAR', 'world')
|
|
77
|
+
|
|
78
|
+
await provider.open()
|
|
79
|
+
const source = provider.source()
|
|
80
|
+
|
|
81
|
+
expect(source).toStrictEqual({ foo: 'hello world' })
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('should not replace if variable not set', async () => {
|
|
85
|
+
const configuration = { foo: '${FOO}' }
|
|
86
|
+
|
|
87
|
+
setEnv(configuration)
|
|
88
|
+
|
|
89
|
+
await provider.open()
|
|
90
|
+
const value = provider.source()
|
|
91
|
+
|
|
92
|
+
expect(value).toStrictEqual(configuration)
|
|
93
|
+
})
|
|
94
|
+
|
|
55
95
|
const usedVariables = []
|
|
56
96
|
|
|
57
97
|
/**
|
|
@@ -60,8 +100,9 @@ const usedVariables = []
|
|
|
60
100
|
*/
|
|
61
101
|
function setEnv (configuration, secrets) {
|
|
62
102
|
const variable = PREFIX + locator.uppercase
|
|
103
|
+
const encoded = encode(configuration)
|
|
63
104
|
|
|
64
|
-
setVal(variable,
|
|
105
|
+
setVal(variable, encoded)
|
|
65
106
|
|
|
66
107
|
if (secrets !== undefined) {
|
|
67
108
|
for (const [key, value] of Object.entries(secrets)) {
|
|
@@ -74,7 +115,7 @@ function setEnv (configuration, secrets) {
|
|
|
74
115
|
}
|
|
75
116
|
|
|
76
117
|
function setVal (variable, value) {
|
|
77
|
-
process.env[variable] =
|
|
118
|
+
process.env[variable] = value
|
|
78
119
|
usedVariables.push(variable)
|
|
79
120
|
}
|
|
80
121
|
|