@node-red/runtime 2.2.2 → 3.0.0-beta.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.
@@ -0,0 +1,202 @@
1
+
2
+ const os = require('os');
3
+ const fs = require('fs');
4
+
5
+ let runtime;
6
+ let isContainerCached;
7
+ let isWSLCached;
8
+
9
+ const isInWsl = () => {
10
+ if (isWSLCached === undefined) {
11
+ isWSLCached = getIsInWSL();
12
+ }
13
+ return isWSLCached;
14
+ function getIsInWSL() {
15
+ if (process.platform !== 'linux') {
16
+ return false;
17
+ }
18
+ try {
19
+ if (os.release().toLowerCase().includes('microsoft')) {
20
+ if (isInContainer()) {
21
+ return false;
22
+ }
23
+ return true;
24
+ }
25
+ return fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft') ? !isInContainer() : false;
26
+ } catch (_) {
27
+ return false;
28
+ }
29
+ }
30
+ };
31
+
32
+ const isInContainer = () => {
33
+ if (isContainerCached === undefined) {
34
+ isContainerCached = hasDockerEnv() || hasDockerCGroup();
35
+ }
36
+ return isContainerCached;
37
+ function hasDockerEnv() {
38
+ try {
39
+ fs.statSync('/.dockerenv');
40
+ return true;
41
+ } catch {
42
+ return false;
43
+ }
44
+ }
45
+ function hasDockerCGroup() {
46
+ try {
47
+ const s = fs.readFileSync('/proc/self/cgroup', 'utf8');
48
+ if (s.includes('docker')) {
49
+ return "docker"
50
+ } else if (s.includes('kubepod')) {
51
+ return "kubepod"
52
+ } else if (s.includes('lxc')) {
53
+ return "lxc"
54
+ }
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+ }
60
+
61
+ function buildDiagnosticReport(scope, callback) {
62
+ const modules = {};
63
+ const nl = runtime.nodes.getNodeList();
64
+ for (let i = 0; i < nl.length; i++) {
65
+ if (modules[nl[i].module]) {
66
+ continue;
67
+ }
68
+ modules[nl[i].module] = nl[i].version
69
+ }
70
+
71
+ const now = new Date();
72
+ const {locale, timeZone} = Intl.DateTimeFormat().resolvedOptions();
73
+ const report = {
74
+ report: "diagnostics",
75
+ scope: scope,
76
+ time: {
77
+ utc: now.toUTCString(),
78
+ local: now.toLocaleString(),
79
+ },
80
+ intl: {
81
+ locale, timeZone
82
+ },
83
+ nodejs: {
84
+ version: process.version,
85
+ arch: process.arch,
86
+ platform: process.platform,
87
+ memoryUsage: process.memoryUsage(),
88
+ },
89
+ os: {
90
+ containerised: isInContainer(),
91
+ wsl: isInWsl(),
92
+ totalmem: os.totalmem(),
93
+ freemem: os.freemem(),
94
+ arch: os.arch(),
95
+ loadavg: os.loadavg(),
96
+ platform: os.platform(),
97
+ release: os.release(),
98
+ type: os.type(),
99
+ uptime: os.uptime(),
100
+ version: os.version(),
101
+ },
102
+ runtime: {
103
+ isStarted: runtime.isStarted(),
104
+ modules: modules,
105
+ version: runtime.settings.version,
106
+ settings: {
107
+ available: runtime.settings.available(),
108
+ apiMaxLength: runtime.settings.apiMaxLength || "UNSET",
109
+ //coreNodesDir: runtime.settings.coreNodesDir,
110
+ disableEditor: runtime.settings.disableEditor,
111
+ contextStorage: listContextModules(),
112
+ debugMaxLength: runtime.settings.debugMaxLength || "UNSET",
113
+ editorTheme: runtime.settings.editorTheme || "UNSET",
114
+ flowFile: runtime.settings.flowFile || "UNSET",
115
+ mqttReconnectTime: runtime.settings.mqttReconnectTime || "UNSET",
116
+ serialReconnectTime: runtime.settings.serialReconnectTime || "UNSET",
117
+
118
+ adminAuth: runtime.settings.adminAuth ? "SET" : "UNSET",
119
+
120
+ httpAdminRoot: runtime.settings.httpAdminRoot || "UNSET",
121
+ httpAdminCors: runtime.settings.httpAdminCors ? "SET" : "UNSET",
122
+ httpNodeAuth: runtime.settings.httpNodeAuth ? "SET" : "UNSET",
123
+
124
+ httpNodeRoot: runtime.settings.httpNodeRoot || "UNSET",
125
+ httpNodeCors: runtime.settings.httpNodeCors ? "SET" : "UNSET",
126
+
127
+ httpStatic: runtime.settings.httpStatic ? "SET" : "UNSET",
128
+ httpStaticRoot: runtime.settings.httpStaticRoot || "UNSET",
129
+ httpStaticCors: runtime.settings.httpStaticCors ? "SET" : "UNSET",
130
+
131
+ uiHost: runtime.settings.uiHost ? "SET" : "UNSET",
132
+ uiPort: runtime.settings.uiPort ? "SET" : "UNSET",
133
+ userDir: runtime.settings.userDir ? "SET" : "UNSET",
134
+ }
135
+ }
136
+ }
137
+
138
+ // if (scope == "admin") {
139
+ // const moreSettings = {
140
+ // adminAuth_type: (runtime.settings.adminAuth && runtime.settings.adminAuth.type) ? runtime.settings.adminAuth.type : "UNSET",
141
+ // httpAdminCors: runtime.settings.httpAdminCors ? runtime.settings.httpAdminCors : "UNSET",
142
+ // httpNodeCors: runtime.settings.httpNodeCors ? runtime.settings.httpNodeCors : "UNSET",
143
+ // httpStaticCors: runtime.settings.httpStaticCors ? "SET" : "UNSET",
144
+ // settingsFile: runtime.settings.settingsFile ? runtime.settings.settingsFile : "UNSET",
145
+ // uiHost: runtime.settings.uiHost ? runtime.settings.uiHost : "UNSET",
146
+ // uiPort: runtime.settings.uiPort ? runtime.settings.uiPort : "UNSET",
147
+ // userDir: runtime.settings.userDir ? runtime.settings.userDir : "UNSET",
148
+ // }
149
+ // const moreNodejs = {
150
+ // execPath: process.execPath,
151
+ // pid: process.pid,
152
+ // }
153
+ // const moreOs = {
154
+ // cpus: os.cpus(),
155
+ // homedir: os.homedir(),
156
+ // hostname: os.hostname(),
157
+ // networkInterfaces: os.networkInterfaces(),
158
+ // }
159
+ // report.runtime.settings = Object.assign({}, report.runtime.settings, moreSettings);
160
+ // report.nodejs = Object.assign({}, report.nodejs, moreNodejs);
161
+ // report.os = Object.assign({}, report.os, moreOs);
162
+ // }
163
+
164
+ callback(report);
165
+
166
+ /** gets a sanitised list containing only the module name */
167
+ function listContextModules() {
168
+ const keys = Object.keys(runtime.settings.contextStorage);
169
+ const result = {};
170
+ keys.forEach(e => {
171
+ result[e] = {
172
+ module: String(runtime.settings.contextStorage[e].module)
173
+ }
174
+ })
175
+ return result;
176
+ }
177
+ }
178
+
179
+
180
+ module.exports = {
181
+ init: function (_runtime) {
182
+ runtime = _runtime;
183
+ },
184
+ /**
185
+ * Gets the node-red diagnostics report
186
+ * @param {{scope: string}} opts - settings
187
+ * @return {Promise} the diagnostics information
188
+ * @memberof @node-red/diagnostics
189
+ */
190
+ get: async function (opts) {
191
+ return new Promise(function (resolve, reject) {
192
+ opts = opts || {}
193
+ try {
194
+ runtime.log.audit({ event: "diagnostics.get", scope: opts.scope }, opts.req);
195
+ buildDiagnosticReport(opts.scope, (report) => resolve(report));
196
+ } catch (error) {
197
+ error.status = 500;
198
+ reject(error);
199
+ }
200
+ })
201
+ },
202
+ }
package/lib/api/index.js CHANGED
@@ -29,6 +29,7 @@ var api = module.exports = {
29
29
  api.projects.init(runtime);
30
30
  api.context.init(runtime);
31
31
  api.plugins.init(runtime);
32
+ api.diagnostics.init(runtime);
32
33
  },
33
34
 
34
35
  comms: require("./comms"),
@@ -39,6 +40,7 @@ var api = module.exports = {
39
40
  projects: require("./projects"),
40
41
  context: require("./context"),
41
42
  plugins: require("./plugins"),
43
+ diagnostics: require("./diagnostics"),
42
44
 
43
45
  isStarted: async function(opts) {
44
46
  return runtime.isStarted();
@@ -142,6 +142,13 @@ var api = module.exports = {
142
142
  }
143
143
 
144
144
  safeSettings.flowEncryptionType = runtime.nodes.getCredentialKeyType();
145
+
146
+ safeSettings.diagnostics = {
147
+ //unless diagnostics.ui and diagnostics.enabled are explicitly false, they will default to true.
148
+ enabled: (runtime.settings.diagnostics && runtime.settings.diagnostics.enabled === false) ? false : true,
149
+ ui: (runtime.settings.diagnostics && runtime.settings.diagnostics.ui === false) ? false : true
150
+ }
151
+
145
152
  runtime.settings.exportNodeSettings(safeSettings);
146
153
  runtime.plugins.exportPluginSettings(safeSettings);
147
154
  }
package/lib/flows/Flow.js CHANGED
@@ -582,7 +582,7 @@ class Flow {
582
582
  reportingNode = node;
583
583
  }
584
584
  if (!muteStatusEvent) {
585
- if (statusMessage.hasOwnProperty("text") && typeof(statusMessage.text !== "string")) {
585
+ if (statusMessage.hasOwnProperty("text") && typeof statusMessage.text !== "string") {
586
586
  try {
587
587
  statusMessage.text = statusMessage.text.toString();
588
588
  }
package/lib/index.js CHANGED
@@ -207,8 +207,12 @@ function start() {
207
207
  if (settings.readOnly){
208
208
  log.info(log._("settings.readonly-mode"))
209
209
  }
210
- if (settings.httpStatic) {
211
- log.info(log._("runtime.paths.httpStatic",{path:path.resolve(settings.httpStatic)}));
210
+ if (settings.httpStatic && settings.httpStatic.length) {
211
+ for (let si = 0; si < settings.httpStatic.length; si++) {
212
+ let p = path.resolve(settings.httpStatic[si].path);
213
+ let r = settings.httpStatic[si].root || "/";
214
+ log.info(log._("runtime.paths.httpStatic",{path:`${p} > ${r}`}));
215
+ }
212
216
  }
213
217
  return redNodes.loadContextsPlugin().then(function () {
214
218
  redNodes.loadFlows().then(redNodes.startFlows).catch(function(err) {});
@@ -395,7 +399,12 @@ module.exports = {
395
399
  * @memberof @node-red/runtime
396
400
  */
397
401
  version: externalAPI.version,
398
-
402
+
403
+ /**
404
+ * @memberof @node-red/diagnostics
405
+ */
406
+ diagnostics:externalAPI.diagnostics,
407
+
399
408
  storage: storage,
400
409
  events: events,
401
410
  hooks: hooks,
@@ -239,7 +239,15 @@ var api = module.exports = {
239
239
  throw error;
240
240
  }
241
241
  } else {
242
- credentialCache = credentials;
242
+ if (encryptionEnabled) {
243
+ // Our config expects the credentials to be encrypted but the encrypted object is not found
244
+ log.warn(log._("nodes.credentials.encryptedNotFound"))
245
+ credentialCache = credentials;
246
+ } else {
247
+ // credentialSecret is set to False
248
+ log.warn(log._("nodes.credentials.unencrypted"))
249
+ credentialCache = credentials;
250
+ }
243
251
  }
244
252
  if (clearInvalidFlag) {
245
253
  // TODO: this delves too deep into Project structure
@@ -104,7 +104,9 @@
104
104
  "error":"Error loading credentials: __message__",
105
105
  "error-saving":"Error saving credentials: __message__",
106
106
  "not-registered": "Credential type '__type__' is not registered",
107
- "system-key-warning": "\n\n---------------------------------------------------------------------\nYour flow credentials file is encrypted using a system-generated key.\n\nIf the system-generated key is lost for any reason, your credentials\nfile will not be recoverable, you will have to delete it and re-enter\nyour credentials.\n\nYou should set your own key using the 'credentialSecret' option in\nyour settings file. Node-RED will then re-encrypt your credentials\nfile using your chosen key the next time you deploy a change.\n---------------------------------------------------------------------\n"
107
+ "system-key-warning": "\n\n---------------------------------------------------------------------\nYour flow credentials file is encrypted using a system-generated key.\n\nIf the system-generated key is lost for any reason, your credentials\nfile will not be recoverable, you will have to delete it and re-enter\nyour credentials.\n\nYou should set your own key using the 'credentialSecret' option in\nyour settings file. Node-RED will then re-encrypt your credentials\nfile using your chosen key the next time you deploy a change.\n---------------------------------------------------------------------\n",
108
+ "unencrypted" : "Using unencrypted credentials",
109
+ "encryptedNotFound" : "Encrypted credentials not found"
108
110
  },
109
111
  "flows": {
110
112
  "safe-mode": "Flows stopped in safe mode. Deploy to start.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-red/runtime",
3
- "version": "2.2.2",
3
+ "version": "3.0.0-beta.1",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./lib/index.js",
6
6
  "repository": {
@@ -16,12 +16,12 @@
16
16
  }
17
17
  ],
18
18
  "dependencies": {
19
- "@node-red/registry": "2.2.2",
20
- "@node-red/util": "2.2.2",
19
+ "@node-red/registry": "3.0.0-beta.1",
20
+ "@node-red/util": "3.0.0-beta.1",
21
21
  "async-mutex": "0.3.2",
22
22
  "clone": "2.1.2",
23
- "express": "4.17.2",
24
- "fs-extra": "10.0.0",
23
+ "express": "4.18.1",
24
+ "fs-extra": "10.1.0",
25
25
  "json-stringify-safe": "5.0.1"
26
26
  }
27
27
  }