node-red-contrib-config-files 0.1.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/LICENSE +1 -0
- package/README.md +17 -0
- package/install.js +9 -0
- package/package.json +35 -0
- package/subflow.json +258 -0
package/LICENSE
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Apache-2.0
|
package/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
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 the resulting configuration.
|
|
3
|
+
|
|
4
|
+
Directory and search patterns for configuration files can be configured using the node properties and/or with the input message.
|
|
5
|
+
|
|
6
|
+
The files are sorted by their file names and merged in this order. The `defaultConfig` property can be used to define configuration values that are missing in the files.
|
|
7
|
+
|
|
8
|
+
If no configuration files are found, the `defaultConfig` is returned.
|
|
9
|
+
|
|
10
|
+
The node status displays one of the following two messages:
|
|
11
|
+
- Found {count} config files in '{configDir}' with pattern '{configFilePattern}'
|
|
12
|
+
- No config files found in '{configDir}' with pattern '{configFilePattern}' -> using default config
|
|
13
|
+
|
|
14
|
+
## Internals
|
|
15
|
+
- This custom node is created from a subflow.
|
|
16
|
+
- It uses `node-red-contrib-filesystem : fs-list` to find the config files.
|
|
17
|
+
- It uses `lodash.merge()` to merge the `defaultConfig` with the contents of the files found.
|
package/install.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
module.exports = function(RED) {
|
|
5
|
+
const subflowFile = path.join(__dirname,"subflow.json");
|
|
6
|
+
const subflowContents = fs.readFileSync(subflowFile);
|
|
7
|
+
const subflowJSON = JSON.parse(subflowContents);
|
|
8
|
+
RED.nodes.registerSubflow(subflowJSON);
|
|
9
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "node-red-contrib-config-files",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Read and merge configuration files (JSON). The files are sorted by their file names and merged in this order. The “defaultConfig” property can be used to define configuration values that are missing in the files.",
|
|
5
|
+
"main": "install.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"node-red",
|
|
11
|
+
"config-files",
|
|
12
|
+
"config",
|
|
13
|
+
"json"
|
|
14
|
+
],
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "Peter Schären",
|
|
17
|
+
"url": "https://github.com/schaeren"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/schaeren/node-red-contrib-config-files"
|
|
22
|
+
},
|
|
23
|
+
"license": "Apache-2.0",
|
|
24
|
+
"node-red": {
|
|
25
|
+
"nodes": {
|
|
26
|
+
"config-files": "install.js"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": [
|
|
29
|
+
"node-red-contrib-filesystem"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"node-red-contrib-filesystem": "*"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/subflow.json
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "0d7c13f79e4a7aee",
|
|
3
|
+
"type": "subflow",
|
|
4
|
+
"name": "config-files",
|
|
5
|
+
"info": "Read and merge configuration files (JSON). \r\n\r\n### Inputs\r\nIf the node receives any message, it will read the \r\nconfig files and merge their contents.\r\n\r\nOptionally a directory and file search pattern can \r\nbe specified in the input message. These will \r\noverwrite the corresponding node properties.\r\n\r\n: configDir (string) : Directory with config files. Absolute or relative path.\r\n: configFilePattern (string) : Search pattern for config files, e.g. `\"*.json\"`\r\n\r\n### Outputs\r\n\r\n: payload (object) : Merged content from config files.\r\n\r\n### Details\r\nThe `defaultConfig` property can be used to define \r\nconfiguration values that are missing in the \r\nconfiguration files.\r\n\r\nThe `configDir` is searched non-recursively for \r\nconfiguration files using the filename pattern \r\n`configFilePattern`.\r\nThe files are sorted by their file names and merged in \r\nthis order. \r\n\r\nThe content of the `defaultConfig` property and the \r\nconfiguration files must by valid JSON.\r\n\r\n### References\r\n\r\n - [GitHub](https://github.com/schaeren/node-red-contrib-config-files) - source code\r\n ",
|
|
6
|
+
"category": "",
|
|
7
|
+
"in": [
|
|
8
|
+
{
|
|
9
|
+
"x": 60,
|
|
10
|
+
"y": 40,
|
|
11
|
+
"wires": [
|
|
12
|
+
{
|
|
13
|
+
"id": "3c563aca59369641"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"out": [
|
|
19
|
+
{
|
|
20
|
+
"x": 720,
|
|
21
|
+
"y": 240,
|
|
22
|
+
"wires": [
|
|
23
|
+
{
|
|
24
|
+
"id": "81b18d7aad495891",
|
|
25
|
+
"port": 0
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"env": [
|
|
31
|
+
{
|
|
32
|
+
"name": "configDir",
|
|
33
|
+
"type": "str",
|
|
34
|
+
"value": "/config"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "configFilePattern",
|
|
38
|
+
"type": "str",
|
|
39
|
+
"value": "*.json"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "defaultConfig",
|
|
43
|
+
"type": "json",
|
|
44
|
+
"value": "{}"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"meta": {
|
|
48
|
+
"module": "node-red-contrib-config-files",
|
|
49
|
+
"type": "config-files",
|
|
50
|
+
"version": "0.1.0",
|
|
51
|
+
"author": "Peter Schären <peter.schaeren@gmail.com>",
|
|
52
|
+
"desc": "Read and merge configuration files (JSON).",
|
|
53
|
+
"keywords": "node-red,config-files,config,json",
|
|
54
|
+
"license": "Apache-2.0"
|
|
55
|
+
},
|
|
56
|
+
"color": "#b0c2ba",
|
|
57
|
+
"icon": "node-red/parser-json.svg",
|
|
58
|
+
"status": {
|
|
59
|
+
"x": 720,
|
|
60
|
+
"y": 120,
|
|
61
|
+
"wires": [
|
|
62
|
+
{
|
|
63
|
+
"id": "73c98834cb90c714",
|
|
64
|
+
"port": 1
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"flow": [
|
|
69
|
+
{
|
|
70
|
+
"id": "2b5d6f663d02b82f",
|
|
71
|
+
"type": "fs-list",
|
|
72
|
+
"z": "0d7c13f79e4a7aee",
|
|
73
|
+
"name": "Find config files",
|
|
74
|
+
"path": "configDir",
|
|
75
|
+
"pathType": "msg",
|
|
76
|
+
"pattern": "configFilePattern",
|
|
77
|
+
"patternType": "msg",
|
|
78
|
+
"filter": "files",
|
|
79
|
+
"recursive": false,
|
|
80
|
+
"follow": false,
|
|
81
|
+
"property": "payload",
|
|
82
|
+
"propertyType": "msg",
|
|
83
|
+
"x": 220,
|
|
84
|
+
"y": 80,
|
|
85
|
+
"wires": [
|
|
86
|
+
[
|
|
87
|
+
"73c98834cb90c714"
|
|
88
|
+
]
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"id": "b46481b92cb28e07",
|
|
93
|
+
"type": "file in",
|
|
94
|
+
"z": "0d7c13f79e4a7aee",
|
|
95
|
+
"name": "read file",
|
|
96
|
+
"filename": "payload",
|
|
97
|
+
"filenameType": "msg",
|
|
98
|
+
"format": "utf8",
|
|
99
|
+
"chunk": false,
|
|
100
|
+
"sendError": false,
|
|
101
|
+
"encoding": "utf8",
|
|
102
|
+
"allProps": false,
|
|
103
|
+
"x": 200,
|
|
104
|
+
"y": 200,
|
|
105
|
+
"wires": [
|
|
106
|
+
[
|
|
107
|
+
"f3c260d6c082e422"
|
|
108
|
+
]
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "bebafe14f9cc467b",
|
|
113
|
+
"type": "split",
|
|
114
|
+
"z": "0d7c13f79e4a7aee",
|
|
115
|
+
"name": "",
|
|
116
|
+
"splt": "\\n",
|
|
117
|
+
"spltType": "str",
|
|
118
|
+
"arraySplt": 1,
|
|
119
|
+
"arraySpltType": "len",
|
|
120
|
+
"stream": false,
|
|
121
|
+
"addname": "",
|
|
122
|
+
"property": "payload",
|
|
123
|
+
"x": 330,
|
|
124
|
+
"y": 160,
|
|
125
|
+
"wires": [
|
|
126
|
+
[
|
|
127
|
+
"ef0d2e4ce8988133"
|
|
128
|
+
]
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"id": "ef0d2e4ce8988133",
|
|
133
|
+
"type": "function",
|
|
134
|
+
"z": "0d7c13f79e4a7aee",
|
|
135
|
+
"name": "make paths absolute",
|
|
136
|
+
"func": "const configDir = env.get('configDir');\nmsg.payload = path.join(configDir, msg.payload);\n\nreturn msg;\n",
|
|
137
|
+
"outputs": 1,
|
|
138
|
+
"timeout": 0,
|
|
139
|
+
"noerr": 0,
|
|
140
|
+
"initialize": "",
|
|
141
|
+
"finalize": "",
|
|
142
|
+
"libs": [
|
|
143
|
+
{
|
|
144
|
+
"var": "path",
|
|
145
|
+
"module": "path"
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
"x": 520,
|
|
149
|
+
"y": 160,
|
|
150
|
+
"wires": [
|
|
151
|
+
[
|
|
152
|
+
"b46481b92cb28e07"
|
|
153
|
+
]
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"id": "f3c260d6c082e422",
|
|
158
|
+
"type": "json",
|
|
159
|
+
"z": "0d7c13f79e4a7aee",
|
|
160
|
+
"name": "to JS",
|
|
161
|
+
"property": "payload",
|
|
162
|
+
"action": "obj",
|
|
163
|
+
"pretty": false,
|
|
164
|
+
"x": 350,
|
|
165
|
+
"y": 200,
|
|
166
|
+
"wires": [
|
|
167
|
+
[
|
|
168
|
+
"81b18d7aad495891"
|
|
169
|
+
]
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"id": "e2a872db2d9086e6",
|
|
174
|
+
"type": "sort",
|
|
175
|
+
"z": "0d7c13f79e4a7aee",
|
|
176
|
+
"name": "",
|
|
177
|
+
"order": "ascending",
|
|
178
|
+
"as_num": false,
|
|
179
|
+
"target": "payload",
|
|
180
|
+
"targetType": "msg",
|
|
181
|
+
"msgKey": "payload",
|
|
182
|
+
"msgKeyType": "elem",
|
|
183
|
+
"seqKey": "payload",
|
|
184
|
+
"seqKeyType": "msg",
|
|
185
|
+
"x": 190,
|
|
186
|
+
"y": 160,
|
|
187
|
+
"wires": [
|
|
188
|
+
[
|
|
189
|
+
"bebafe14f9cc467b"
|
|
190
|
+
]
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"id": "81b18d7aad495891",
|
|
195
|
+
"type": "function",
|
|
196
|
+
"z": "0d7c13f79e4a7aee",
|
|
197
|
+
"name": "merge configs",
|
|
198
|
+
"func": "// const _t = global.get('libTracer');\n// _t.init(node, msg, flow.get('enableTracer')); \n\nlet config = flow.get('mergedConfig');\nconfig = lodash.merge(config, msg.payload);\n// _t.trace(node, msg, 'config', lodash.cloneDeep(config));\n\nmsg.payload = config;\nreturn msg;\n",
|
|
199
|
+
"outputs": 1,
|
|
200
|
+
"timeout": 0,
|
|
201
|
+
"noerr": 0,
|
|
202
|
+
"initialize": "// Code added here will be run once\n// whenever the node is started.\n\nconst defaultConfig = env.get('defaultConfig') ?? {};\n\nflow.set('mergedConfig', defaultConfig);\n",
|
|
203
|
+
"finalize": "",
|
|
204
|
+
"libs": [
|
|
205
|
+
{
|
|
206
|
+
"var": "lodash",
|
|
207
|
+
"module": "lodash"
|
|
208
|
+
}
|
|
209
|
+
],
|
|
210
|
+
"x": 220,
|
|
211
|
+
"y": 240,
|
|
212
|
+
"wires": [
|
|
213
|
+
[]
|
|
214
|
+
]
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"id": "3c563aca59369641",
|
|
218
|
+
"type": "function",
|
|
219
|
+
"z": "0d7c13f79e4a7aee",
|
|
220
|
+
"name": "get config dir and filename pattern",
|
|
221
|
+
"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 configFilePattern = msg.configFilePattern ?? null;\nif (typeof configFilePattern === 'string' && configFilePattern.trim().length > 0) {\n msg.configFilePattern = configFilePattern;\n}\nelse {\n msg.configFilePattern = env.get('configFilePattern');\n}\n\nmsg.topic = 'configFiles';\nreturn msg;",
|
|
222
|
+
"outputs": 1,
|
|
223
|
+
"timeout": 0,
|
|
224
|
+
"noerr": 0,
|
|
225
|
+
"initialize": "",
|
|
226
|
+
"finalize": "",
|
|
227
|
+
"libs": [],
|
|
228
|
+
"x": 280,
|
|
229
|
+
"y": 40,
|
|
230
|
+
"wires": [
|
|
231
|
+
[
|
|
232
|
+
"2b5d6f663d02b82f"
|
|
233
|
+
]
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"id": "73c98834cb90c714",
|
|
238
|
+
"type": "function",
|
|
239
|
+
"z": "0d7c13f79e4a7aee",
|
|
240
|
+
"name": "status",
|
|
241
|
+
"func": "const count = Array.isArray(msg.payload) ? msg.payload.length : 0;\n\nlet statusText = `No config files found in '${msg.configDir}' with pattern '${msg.configFilePattern}' -> using default config`;\nif (count > 0) {\n statusText = `Found ${count} config files in '${msg.configDir}' with pattern '${msg.configFilePattern}'`;\n}\nconst status = { fill: \"blue\", shape: \"ring\", text: statusText };\n\nreturn [ msg, { payload: status} ];",
|
|
242
|
+
"outputs": 2,
|
|
243
|
+
"timeout": 0,
|
|
244
|
+
"noerr": 0,
|
|
245
|
+
"initialize": "",
|
|
246
|
+
"finalize": "",
|
|
247
|
+
"libs": [],
|
|
248
|
+
"x": 190,
|
|
249
|
+
"y": 120,
|
|
250
|
+
"wires": [
|
|
251
|
+
[
|
|
252
|
+
"e2a872db2d9086e6"
|
|
253
|
+
],
|
|
254
|
+
[]
|
|
255
|
+
]
|
|
256
|
+
}
|
|
257
|
+
]
|
|
258
|
+
}
|