node-red-contrib-config-files 0.2.0 → 0.3.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.
- package/CHANGELOG.md +9 -0
- package/HELP.md +14 -6
- package/README.md +14 -6
- package/package.json +1 -1
- package/subflow.json +136 -78
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.0] - 2026-01-31
|
|
4
|
+
### Changed
|
|
5
|
+
- New configuration property `concatArrays`: true -> array elements of corresponding arrays are concatenated, otherwise merged, default: `true`. Input message `msg.concatArrays` overwrites the node property.
|
|
6
|
+
- Properties: The allowed data types for the input fields are now more restricted.
|
|
7
|
+
|
|
8
|
+
## [0.2.1] - 2026-01-31
|
|
9
|
+
### Changed
|
|
10
|
+
- If directory `configDir` doesn't exist or is not accessible: Instead of throwing a node error, a node warning is created. This warning may appear in the “Debug Messages” sidebar.
|
|
11
|
+
|
|
3
12
|
## [0.2.0] - 2026-01-30
|
|
4
13
|
### Added
|
|
5
14
|
- If directory `configDir` doesn't exist or is not accessible, a node error is throw. This error can be received with a `catch` node, for example.
|
package/HELP.md
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
Read and merge configuration files (JSON).
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
### Inputs
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
Directory and filename extension used to search for configuration
|
|
6
6
|
files can be configured using the node properties and/or with the
|
|
7
7
|
input message.
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
: configDir (string) : Directory with config files. Absolute or relative path, default: `/config`. Input message `msg.configDir` overwrites the node property.
|
|
10
10
|
: configFileExt (string) : Filename extension for config files, default: `.json`. Input message `msg.configFileExt` overwrites the node property.
|
|
11
|
-
|
|
11
|
+
: concatArrays (boolean) : true -> array elements of corresponding arrays are concatenated, otherwise merged, default: `true`. Input message `msg.concatArrays` overwrites the node property.
|
|
12
|
+
|
|
12
13
|
### Outputs
|
|
13
|
-
|
|
14
|
+
|
|
14
15
|
: payload (object) : Merged content from config files.
|
|
16
|
+
: configFiles [] : Paths to config files found, empty array if no files were found.
|
|
15
17
|
|
|
16
18
|
### Details
|
|
17
19
|
The node pproperty `defaultConfig` can be used to define configuration
|
|
18
|
-
values that are missing in the configuration files.
|
|
20
|
+
values that are used when they are missing in the configuration files.
|
|
19
21
|
|
|
20
22
|
The `configDir` is searched non-recursively for configuration files using
|
|
21
23
|
the filename extension `configFilePattern`.
|
|
@@ -24,6 +26,12 @@ The files are sorted by their file names and merged in this order.
|
|
|
24
26
|
The content of the `defaultConfig` property and the configuration files
|
|
25
27
|
must by valid JSON.
|
|
26
28
|
|
|
29
|
+
The property `concatArrays` defines how to merge corresponding arrays defined in more
|
|
30
|
+
than one config file and/or `defaultConfig`:
|
|
31
|
+
- `true` Concatenate the array elements of corresponding arrays.
|
|
32
|
+
- `false` Array elements in corresponding arrays with the same index overwrite each
|
|
33
|
+
other, with the overwrite order depending on the order of the sorted files (see above).
|
|
34
|
+
|
|
27
35
|
### References
|
|
28
36
|
|
|
29
37
|
- [GitHub](https://github.com/schaeren/node-red-contrib-config-files) - source code
|
package/README.md
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# node-red-contrib-config-files
|
|
2
|
-
[Node-Red](https://nodered.org/) node for reading and merging configuration files with JSON content. The output returns
|
|
2
|
+
[Node-Red](https://nodered.org/) node for reading and merging configuration files with JSON content. The output returns
|
|
3
|
+
the resulting configuration object.
|
|
3
4
|
|
|
4
|
-
Directory and filename extension used to search for configuration files can be configured using the node properties and/or
|
|
5
|
+
Directory and filename extension used to search for configuration files can be configured using the node properties and/or
|
|
6
|
+
with the input message.
|
|
5
7
|
|
|
6
|
-
The files are sorted by their file names and merged in this order. The `defaultConfig`
|
|
8
|
+
The files are sorted by their file names and merged in this order. The `defaultConfig` can be used to define configuration
|
|
9
|
+
values that are used when they are missing in the configuration files.
|
|
7
10
|
|
|
8
11
|
If no configuration files are found, the `defaultConfig` is returned.
|
|
9
12
|
|
|
@@ -11,10 +14,15 @@ The node status displays one of the following two messages:
|
|
|
11
14
|
- Found {count} config files in '{configDir}' with extension '{configFileExt}'
|
|
12
15
|
- No config files found in '{configDir}' with extension '{configFileExt}' -> using default config
|
|
13
16
|
|
|
14
|
-
If directory `configDir` doesn't exist or is not accessible
|
|
17
|
+
If directory `configDir` doesn't exist or is not accessible or if no file was found with `configFileExt`, node warnings
|
|
18
|
+
are created. These warnings may appear in the “Debug Messages” sidebar.
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
Special care is required when using config files containing arrays with objects: The `concatArray` property can be used
|
|
21
|
+
to define whether the array elements should be concatenated or merged. In the latter case, array elements with the same
|
|
22
|
+
array index are merged, i.e., element properties with identical names overwrite each other.
|
|
17
23
|
|
|
18
24
|
## Internals
|
|
19
|
-
- This custom node
|
|
25
|
+
- This custom node was created from a subflow.
|
|
20
26
|
- It uses `lodash.merge()` to merge the `defaultConfig` with the contents of the files found.
|
|
27
|
+
- Some debug information is written by the node using `node.debug()`. To view these messages, set the logging level
|
|
28
|
+
in `settings.js` to at least `debug`.
|
package/package.json
CHANGED
package/subflow.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "ec796389903c1d0f",
|
|
3
3
|
"type": "subflow",
|
|
4
4
|
"name": "config-files",
|
|
5
|
-
"info": "Read and merge configuration files (JSON)
|
|
5
|
+
"info": "Read and merge configuration files (JSON). \n\n### Inputs\n\nDirectory and filename extension used to search for configuration \nfiles can be configured using the node properties and/or with the \ninput message.\n\n: configDir (string) : Directory with config files. Absolute or relative path, default: `/config`. Input message `msg.configDir` overwrites the node property.\n: configFileExt (string) : Filename extension for config files, default: `.json`. Input message `msg.configFileExt` overwrites the node property.\n\n### Outputs\n\n: payload (object) : Merged content from config files.\n: configFiles [] : Paths to config files found, empty array if no files were found.\n\n### Details\nThe node pproperty `defaultConfig` can be used to define configuration \nvalues that are used when they are missing in the configuration files.\n\nThe `configDir` is searched non-recursively for configuration files using \nthe filename extension `configFilePattern`.\nThe files are sorted by their file names and merged in this order. \n\nThe content of the `defaultConfig` property and the configuration files \nmust by valid JSON.\n\n### References\n\n- [GitHub](https://github.com/schaeren/node-red-contrib-config-files) - source code",
|
|
6
6
|
"category": "",
|
|
7
7
|
"in": [
|
|
8
8
|
{
|
|
@@ -17,38 +17,83 @@
|
|
|
17
17
|
],
|
|
18
18
|
"out": [
|
|
19
19
|
{
|
|
20
|
-
"x":
|
|
21
|
-
"y":
|
|
20
|
+
"x": 740,
|
|
21
|
+
"y": 400,
|
|
22
22
|
"wires": [
|
|
23
|
+
{
|
|
24
|
+
"id": "efa7ea24e8224b84",
|
|
25
|
+
"port": 0
|
|
26
|
+
},
|
|
23
27
|
{
|
|
24
28
|
"id": "86c429715975c781",
|
|
25
29
|
"port": 0
|
|
26
30
|
}
|
|
27
31
|
]
|
|
28
|
-
}
|
|
32
|
+
}
|
|
29
33
|
],
|
|
30
34
|
"env": [
|
|
31
35
|
{
|
|
32
36
|
"name": "configDir",
|
|
33
37
|
"type": "str",
|
|
34
|
-
"value": "/config"
|
|
38
|
+
"value": "/config",
|
|
39
|
+
"ui": {
|
|
40
|
+
"type": "input",
|
|
41
|
+
"opts": {
|
|
42
|
+
"types": [
|
|
43
|
+
"str",
|
|
44
|
+
"env"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
35
48
|
},
|
|
36
49
|
{
|
|
37
50
|
"name": "configFileExt",
|
|
38
51
|
"type": "str",
|
|
39
|
-
"value": ".json"
|
|
52
|
+
"value": ".json",
|
|
53
|
+
"ui": {
|
|
54
|
+
"type": "input",
|
|
55
|
+
"opts": {
|
|
56
|
+
"types": [
|
|
57
|
+
"str",
|
|
58
|
+
"env"
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "concatArrays",
|
|
65
|
+
"type": "bool",
|
|
66
|
+
"value": "true",
|
|
67
|
+
"ui": {
|
|
68
|
+
"type": "input",
|
|
69
|
+
"opts": {
|
|
70
|
+
"types": [
|
|
71
|
+
"bool",
|
|
72
|
+
"env"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
40
76
|
},
|
|
41
77
|
{
|
|
42
78
|
"name": "defaultConfig",
|
|
43
79
|
"type": "json",
|
|
44
|
-
"value": "{}"
|
|
80
|
+
"value": "{}",
|
|
81
|
+
"ui": {
|
|
82
|
+
"type": "input",
|
|
83
|
+
"opts": {
|
|
84
|
+
"types": [
|
|
85
|
+
"json",
|
|
86
|
+
"env"
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
}
|
|
45
90
|
}
|
|
46
91
|
],
|
|
47
92
|
"meta": {
|
|
48
93
|
"module": "node-red-contrib-config-files",
|
|
49
94
|
"type": "config-files",
|
|
50
95
|
"desc": "Read and merge configuration files (JSON).",
|
|
51
|
-
"version": "0.
|
|
96
|
+
"version": "0.3.0",
|
|
52
97
|
"author": "Peter Schären <peter.schaeren@gmail.com>",
|
|
53
98
|
"keywords": "node-red,config-files,config,json",
|
|
54
99
|
"license": "MIT"
|
|
@@ -56,8 +101,8 @@
|
|
|
56
101
|
"color": "#b0c2ba",
|
|
57
102
|
"icon": "node-red/parser-json.svg",
|
|
58
103
|
"status": {
|
|
59
|
-
"x":
|
|
60
|
-
"y":
|
|
104
|
+
"x": 740,
|
|
105
|
+
"y": 160,
|
|
61
106
|
"wires": [
|
|
62
107
|
{
|
|
63
108
|
"id": "73c98834cb90c714",
|
|
@@ -79,7 +124,7 @@
|
|
|
79
124
|
"encoding": "utf8",
|
|
80
125
|
"allProps": false,
|
|
81
126
|
"x": 200,
|
|
82
|
-
"y":
|
|
127
|
+
"y": 280,
|
|
83
128
|
"wires": [
|
|
84
129
|
[
|
|
85
130
|
"f3c260d6c082e422"
|
|
@@ -98,12 +143,11 @@
|
|
|
98
143
|
"stream": false,
|
|
99
144
|
"addname": "",
|
|
100
145
|
"property": "payload",
|
|
101
|
-
"x":
|
|
102
|
-
"y":
|
|
146
|
+
"x": 510,
|
|
147
|
+
"y": 240,
|
|
103
148
|
"wires": [
|
|
104
149
|
[
|
|
105
|
-
"7f1816d008fa2b70"
|
|
106
|
-
"b46481b92cb28e07"
|
|
150
|
+
"7f1816d008fa2b70"
|
|
107
151
|
]
|
|
108
152
|
]
|
|
109
153
|
},
|
|
@@ -116,10 +160,9 @@
|
|
|
116
160
|
"action": "obj",
|
|
117
161
|
"pretty": false,
|
|
118
162
|
"x": 230,
|
|
119
|
-
"y":
|
|
163
|
+
"y": 320,
|
|
120
164
|
"wires": [
|
|
121
165
|
[
|
|
122
|
-
"86c429715975c781",
|
|
123
166
|
"8639805af947d0c3"
|
|
124
167
|
]
|
|
125
168
|
]
|
|
@@ -137,8 +180,8 @@
|
|
|
137
180
|
"msgKeyType": "elem",
|
|
138
181
|
"seqKey": "payload",
|
|
139
182
|
"seqKeyType": "msg",
|
|
140
|
-
"x":
|
|
141
|
-
"y":
|
|
183
|
+
"x": 370,
|
|
184
|
+
"y": 240,
|
|
142
185
|
"wires": [
|
|
143
186
|
[
|
|
144
187
|
"bebafe14f9cc467b"
|
|
@@ -150,7 +193,7 @@
|
|
|
150
193
|
"type": "function",
|
|
151
194
|
"z": "ec796389903c1d0f",
|
|
152
195
|
"name": "get config dir and filename extension",
|
|
153
|
-
"func": "const configDir = msg.configDir ?? null;\nif (typeof configDir === 'string' && configDir.trim().length > 0) {\n msg.configDir = configDir;\n}\nelse {\n msg.configDir = env.get('configDir');\n}\n\nconst configFileExt = msg.configFileExt ?? null;\nif (typeof configFileExt === 'string' && configFileExt.trim().length > 0) {\n msg.configFileExt = configFileExt;\n}\nelse {\n msg.configFileExt = env.get('configFileExt');\n}\n\nmsg.topic = 'configFiles';\nreturn msg;",
|
|
196
|
+
"func": "const configDir = msg.configDir ?? null;\nif (typeof configDir === 'string' && configDir.trim().length > 0) {\n msg.configDir = configDir;\n}\nelse {\n msg.configDir = env.get('configDir');\n}\n\nconst configFileExt = msg.configFileExt ?? null;\nif (typeof configFileExt === 'string' && configFileExt.trim().length > 0) {\n msg.configFileExt = configFileExt;\n}\nelse {\n msg.configFileExt = env.get('configFileExt');\n}\n\nconst concatArrays = msg.concatArrays ?? null;\nif (typeof concatArrays === 'boolean') {\n msg.concatArrays = concatArrays;\n}\nelse {\n msg.concatArrays = env.get('concatArrays');\n}\n\nmsg.topic = 'configFiles';\nreturn msg;",
|
|
154
197
|
"outputs": 1,
|
|
155
198
|
"timeout": 0,
|
|
156
199
|
"noerr": 0,
|
|
@@ -170,23 +213,20 @@
|
|
|
170
213
|
"type": "function",
|
|
171
214
|
"z": "ec796389903c1d0f",
|
|
172
215
|
"name": "node status",
|
|
173
|
-
"func": "const count = Array.isArray(msg.payload) ? msg.payload.length : 0;\
|
|
174
|
-
"outputs":
|
|
216
|
+
"func": "const count = Array.isArray(msg.payload) ? msg.payload.length : 0;\n\nlet statusText = '';\nif (count > 0) {\n statusText = `Found ${count} config files in '${msg.configDir}' with extension '${msg.configFileExt}'`;\n}\nelse {\n statusText = `No config files found in '${msg.configDir}' with extension '${msg.configFileExt}' -> using default config`;\n}\nconst statusMsg = { payload: { fill: \"blue\", shape: \"ring\", text: statusText } };\n\nmsg.configFiles = msg.payload;\n\nreturn [msg, statusMsg];\n",
|
|
217
|
+
"outputs": 2,
|
|
175
218
|
"timeout": 0,
|
|
176
219
|
"noerr": 0,
|
|
177
220
|
"initialize": "",
|
|
178
221
|
"finalize": "",
|
|
179
222
|
"libs": [],
|
|
180
223
|
"x": 210,
|
|
181
|
-
"y":
|
|
224
|
+
"y": 160,
|
|
182
225
|
"wires": [
|
|
183
226
|
[
|
|
184
|
-
"
|
|
227
|
+
"6a7545e5271cd1fa"
|
|
185
228
|
],
|
|
186
|
-
[]
|
|
187
|
-
[
|
|
188
|
-
"cdec17dcc5a199ab"
|
|
189
|
-
]
|
|
229
|
+
[]
|
|
190
230
|
]
|
|
191
231
|
},
|
|
192
232
|
{
|
|
@@ -194,8 +234,8 @@
|
|
|
194
234
|
"type": "function",
|
|
195
235
|
"z": "ec796389903c1d0f",
|
|
196
236
|
"name": "find files",
|
|
197
|
-
"func": "const dir = msg.configDir;\nconst ext = msg.configFileExt\n\
|
|
198
|
-
"outputs":
|
|
237
|
+
"func": "const dir = msg.configDir;\nconst ext = msg.configFileExt\n\n// ---------------------------------------------------------------------------------------\n\nasync function findFiles(dir, ext) {\n try {\n // Check if directory exists and is accessible\n await fs.promises.access(dir);\n\n // Find files\n let filenames = await fs.promises.readdir(dir);\n filenames = filenames.filter(f => path.extname(f) === ext);\n\n // Prepend configDir to filenames\n const filepaths = filenames.map(f => path.join(dir, f));\n return filepaths ?? [];\n\n } catch (err) {\n node.warn(`Directory not found or not accessible: ${dir}`);\n return [];\n }\n}\n\n// ---------------------------------------------------------------------------------------\n\nnode.debug(`Searching files in directory '${dir}' filename extension '${ext}' ...`);\n\nconst filepaths = await findFiles(dir, ext);\n\n// log\nif (filepaths.length > 0) {\n node.debug(`${filepaths.length} files found:`);\n for (let fp of filepaths) {\n node.debug(` ${fp}`);\n }\n}\nelse {\n node.warn(`No config files found in '${dir}' with extension '${ext}' -> using default config`);\n}\n\nmsg.payload = filepaths;\nreturn msg;\n",
|
|
238
|
+
"outputs": 1,
|
|
199
239
|
"timeout": 0,
|
|
200
240
|
"noerr": 0,
|
|
201
241
|
"initialize": "",
|
|
@@ -215,99 +255,117 @@
|
|
|
215
255
|
"wires": [
|
|
216
256
|
[
|
|
217
257
|
"73c98834cb90c714"
|
|
218
|
-
],
|
|
219
|
-
[
|
|
220
|
-
"aa017e7a5d0c867e"
|
|
221
258
|
]
|
|
222
259
|
]
|
|
223
260
|
},
|
|
224
261
|
{
|
|
225
|
-
"id": "
|
|
262
|
+
"id": "7f1816d008fa2b70",
|
|
226
263
|
"type": "function",
|
|
227
264
|
"z": "ec796389903c1d0f",
|
|
228
|
-
"name": "
|
|
229
|
-
"func": "node.
|
|
230
|
-
"outputs":
|
|
265
|
+
"name": "log",
|
|
266
|
+
"func": "node.debug(`Reading file '${msg.payload}' ...`)\nreturn msg;",
|
|
267
|
+
"outputs": 1,
|
|
231
268
|
"timeout": 0,
|
|
232
269
|
"noerr": 0,
|
|
233
270
|
"initialize": "",
|
|
234
271
|
"finalize": "",
|
|
235
272
|
"libs": [],
|
|
236
|
-
"x":
|
|
237
|
-
"y":
|
|
238
|
-
"wires": [
|
|
273
|
+
"x": 650,
|
|
274
|
+
"y": 240,
|
|
275
|
+
"wires": [
|
|
276
|
+
[
|
|
277
|
+
"b46481b92cb28e07"
|
|
278
|
+
]
|
|
279
|
+
]
|
|
239
280
|
},
|
|
240
281
|
{
|
|
241
|
-
"id": "
|
|
282
|
+
"id": "8639805af947d0c3",
|
|
242
283
|
"type": "function",
|
|
243
284
|
"z": "ec796389903c1d0f",
|
|
244
|
-
"name": "
|
|
245
|
-
"func": "
|
|
285
|
+
"name": "log",
|
|
286
|
+
"func": "node.debug(`Config read from '${msg.filename}':\\n${JSON.stringify(msg.payload, null, 2)}`)\nreturn msg;",
|
|
246
287
|
"outputs": 1,
|
|
247
288
|
"timeout": 0,
|
|
248
289
|
"noerr": 0,
|
|
249
|
-
"initialize": "
|
|
290
|
+
"initialize": "",
|
|
250
291
|
"finalize": "",
|
|
251
|
-
"libs": [
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
"module": "lodash"
|
|
255
|
-
}
|
|
256
|
-
],
|
|
257
|
-
"x": 220,
|
|
258
|
-
"y": 420,
|
|
292
|
+
"libs": [],
|
|
293
|
+
"x": 650,
|
|
294
|
+
"y": 320,
|
|
259
295
|
"wires": [
|
|
260
|
-
[
|
|
296
|
+
[
|
|
297
|
+
"86c429715975c781"
|
|
298
|
+
]
|
|
261
299
|
]
|
|
262
300
|
},
|
|
263
301
|
{
|
|
264
|
-
"id": "
|
|
265
|
-
"type": "
|
|
302
|
+
"id": "6a7545e5271cd1fa",
|
|
303
|
+
"type": "switch",
|
|
266
304
|
"z": "ec796389903c1d0f",
|
|
267
|
-
"name": "
|
|
268
|
-
"
|
|
269
|
-
"
|
|
270
|
-
"
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
305
|
+
"name": "files found",
|
|
306
|
+
"property": "payload.length",
|
|
307
|
+
"propertyType": "msg",
|
|
308
|
+
"rules": [
|
|
309
|
+
{
|
|
310
|
+
"t": "gt",
|
|
311
|
+
"v": "0",
|
|
312
|
+
"vt": "str"
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"t": "else"
|
|
316
|
+
}
|
|
317
|
+
],
|
|
318
|
+
"checkall": "true",
|
|
319
|
+
"repair": false,
|
|
320
|
+
"outputs": 2,
|
|
321
|
+
"x": 210,
|
|
322
|
+
"y": 240,
|
|
323
|
+
"wires": [
|
|
324
|
+
[
|
|
325
|
+
"e2a872db2d9086e6"
|
|
326
|
+
],
|
|
327
|
+
[
|
|
328
|
+
"efa7ea24e8224b84"
|
|
329
|
+
]
|
|
330
|
+
]
|
|
278
331
|
},
|
|
279
332
|
{
|
|
280
|
-
"id": "
|
|
333
|
+
"id": "efa7ea24e8224b84",
|
|
281
334
|
"type": "function",
|
|
282
335
|
"z": "ec796389903c1d0f",
|
|
283
|
-
"name": "
|
|
284
|
-
"func": "
|
|
336
|
+
"name": "use defaultConfig only",
|
|
337
|
+
"func": "let defaultConfig = env.get('defaultConfig');\n// defaultConfig may be null or '' (value can be '' if an undefined environment variable is used)\nif (!defaultConfig) {\n defaultConfig = {};\n}\n\n\nmsg.payload = defaultConfig;\nreturn msg;\n",
|
|
285
338
|
"outputs": 1,
|
|
286
339
|
"timeout": 0,
|
|
287
340
|
"noerr": 0,
|
|
288
341
|
"initialize": "",
|
|
289
342
|
"finalize": "",
|
|
290
343
|
"libs": [],
|
|
291
|
-
"x":
|
|
292
|
-
"y":
|
|
344
|
+
"x": 560,
|
|
345
|
+
"y": 380,
|
|
293
346
|
"wires": [
|
|
294
347
|
[]
|
|
295
348
|
]
|
|
296
349
|
},
|
|
297
350
|
{
|
|
298
|
-
"id": "
|
|
351
|
+
"id": "86c429715975c781",
|
|
299
352
|
"type": "function",
|
|
300
353
|
"z": "ec796389903c1d0f",
|
|
301
|
-
"name": "
|
|
302
|
-
"func": "
|
|
354
|
+
"name": "merge configs",
|
|
355
|
+
"func": "// -----------------------------------------------------------------------\nconst merge_customizer = (objValue, srcValue) => {\n if (Array.isArray(objValue) && Array.isArray(srcValue)) {\n return objValue.concat(srcValue);\n }\n return undefined;\n};\n// -----------------------------------------------------------------------\n\nlet config = flow.get('mergedConfig');\nconst concatArrays = env.get('concatArrays');\n\nif (concatArrays) {\n config = lodash.mergeWith(config, msg.payload, merge_customizer);\n}\nelse {\n config = lodash.merge(config, msg.payload);\n}\nnode.trace(`Merged config after merging file #${msg.parts.index + 1} '${msg.configFiles[msg.parts.index]}':\\n${JSON.stringify(config, null, 2)}`);\n\n\n// Last config file read?\nif (msg.parts.index == msg.parts.count - 1) {\n msg.topic = 'config';\n msg.payload = config;\n delete msg.parts;\n delete msg.filename;\n\n node.debug(`Merged ALL configs (concatArraays: ${concatArrays}):\\n ${JSON.stringify(msg.payload, null, 2)}`);\n return msg;\n}\n",
|
|
303
356
|
"outputs": 1,
|
|
304
357
|
"timeout": 0,
|
|
305
358
|
"noerr": 0,
|
|
306
|
-
"initialize": "",
|
|
359
|
+
"initialize": "let defaultConfig = env.get('defaultConfig');\n// defaultConfig may be null or '' (value can be '' if an undefined environment variable is used)\nif (!defaultConfig) {\n defaultConfig = {};\n}\n\nflow.set('mergedConfig', defaultConfig);\n",
|
|
307
360
|
"finalize": "",
|
|
308
|
-
"libs": [
|
|
309
|
-
|
|
310
|
-
|
|
361
|
+
"libs": [
|
|
362
|
+
{
|
|
363
|
+
"var": "lodash",
|
|
364
|
+
"module": "lodash"
|
|
365
|
+
}
|
|
366
|
+
],
|
|
367
|
+
"x": 220,
|
|
368
|
+
"y": 400,
|
|
311
369
|
"wires": [
|
|
312
370
|
[]
|
|
313
371
|
]
|