@tachybase/plugin-adapter-red-node 1.3.24 → 1.4.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.
Files changed (24) hide show
  1. package/dist/externalVersion.js +2 -2
  2. package/dist/node_modules/@node-red/editor-api/package.json +1 -1
  3. package/dist/node_modules/@node-red/runtime/466.index.js +10135 -0
  4. package/dist/node_modules/@node-red/runtime/lib/api/context.js +26 -6
  5. package/dist/node_modules/@node-red/runtime/lib/api/settings.js +14 -0
  6. package/dist/node_modules/@node-red/runtime/lib/flows/Flow.js +14 -0
  7. package/dist/node_modules/@node-red/runtime/lib/flows/Group.js +8 -0
  8. package/dist/node_modules/@node-red/runtime/lib/flows/util.js +23 -2
  9. package/dist/node_modules/@node-red/runtime/lib/index.js +55 -55
  10. package/dist/node_modules/@node-red/runtime/lib/nodes/index.js +3 -2
  11. package/dist/node_modules/@node-red/runtime/lib/storage/localfilesystem/library.js +1 -1
  12. package/dist/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/git/index.js +2 -0
  13. package/dist/node_modules/@node-red/runtime/lib/telemetry/index.js +213 -0
  14. package/dist/node_modules/@node-red/runtime/lib/telemetry/metrics/01-core.js +5 -0
  15. package/dist/node_modules/@node-red/runtime/lib/telemetry/metrics/02-os.js +9 -0
  16. package/dist/node_modules/@node-red/runtime/lib/telemetry/metrics/03-env.js +8 -0
  17. package/dist/node_modules/@node-red/runtime/metrics/01-core.js +5 -0
  18. package/dist/node_modules/@node-red/runtime/metrics/02-os.js +9 -0
  19. package/dist/node_modules/@node-red/runtime/metrics/03-env.js +8 -0
  20. package/dist/node_modules/@node-red/runtime/node_modules/.bin/semver +21 -0
  21. package/dist/node_modules/@node-red/runtime/package.json +1 -1
  22. package/dist/node_modules/@node-red/util/package.json +1 -1
  23. package/dist/node_modules/express/package.json +1 -1
  24. package/package.json +6 -6
@@ -172,9 +172,10 @@ function installModule(module,version,url) {
172
172
  if (info.pending_version) {
173
173
  events.emit("runtime-event",{id:"node/upgraded",retain:false,payload:{module:info.name,version:info.pending_version}});
174
174
  } else {
175
- if (!info.nodes.length && info.plugins.length) {
175
+ if (info.plugins.length) {
176
176
  events.emit("runtime-event",{id:"plugin/added",retain:false,payload:info.plugins});
177
- } else {
177
+ }
178
+ if (info.nodes.length) {
178
179
  events.emit("runtime-event",{id:"node/added",retain:false,payload:info.nodes});
179
180
  }
180
181
  }
@@ -135,7 +135,7 @@ function getLibraryEntry(type,path) {
135
135
  throw err;
136
136
  });
137
137
  } else {
138
- throw err;
138
+ throw new Error(`Library Entry not found ${path}`, { cause: err});
139
139
  }
140
140
  });
141
141
  }
@@ -51,6 +51,8 @@ function runGitCommand(args,cwd,env,emit) {
51
51
  err.code = "git_auth_failed";
52
52
  } else if(/Authentication failed/i.test(stderr)) {
53
53
  err.code = "git_auth_failed";
54
+ } else if (/The requested URL returned error: 403/i.test(stderr)) {
55
+ err.code = "git_auth_failed";
54
56
  } else if (/commit your changes or stash/i.test(stderr)) {
55
57
  err.code = "git_local_overwrite";
56
58
  } else if (/CONFLICT/.test(err.stdout)) {
@@ -0,0 +1,213 @@
1
+ const path = require('path')
2
+ const fs = require('fs/promises')
3
+ const semver = require('semver')
4
+ const cronosjs = require('cronosjs')
5
+
6
+ const METRICS_DIR = path.join(__dirname, 'metrics')
7
+ const INITIAL_PING_DELAY = 1000 * 60 * 30 // 30 minutes from startup
8
+
9
+ /** @type {import("got").Got | undefined} */
10
+ let got
11
+
12
+ let runtime
13
+
14
+ let scheduleTask
15
+
16
+ async function gather () {
17
+ let metricFiles = await fs.readdir(METRICS_DIR)
18
+ metricFiles = metricFiles.filter(name => /^\d+-.*\.js$/.test(name))
19
+ metricFiles.sort()
20
+
21
+ const metrics = {}
22
+
23
+ for (let i = 0, l = metricFiles.length; i < l; i++) {
24
+ const metricModule = require(path.join(METRICS_DIR, metricFiles[i]))
25
+ let result = metricModule(runtime)
26
+ if (!!result && (typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') {
27
+ result = await result
28
+ }
29
+ const keys = Object.keys(result)
30
+ keys.forEach(key => {
31
+ const keyParts = key.split('.')
32
+ let p = metrics
33
+ keyParts.forEach((part, index) => {
34
+ if (index < keyParts.length - 1) {
35
+ if (!p[part]) {
36
+ p[part] = {}
37
+ }
38
+ p = p[part]
39
+ } else {
40
+ p[part] = result[key]
41
+ }
42
+ })
43
+ })
44
+ }
45
+ return metrics
46
+ }
47
+
48
+ async function report () {
49
+ if (!isTelemetryEnabled()) {
50
+ return
51
+ }
52
+ // If enabled, gather metrics
53
+ const metrics = await gather()
54
+
55
+ // Post metrics to endpoint - handle any error silently
56
+
57
+ if (!got) {
58
+ got = (await import('got')).got
59
+ }
60
+
61
+ runtime.log.debug('Sending telemetry')
62
+ const response = await got.post('https://telemetry.nodered.org/ping', {
63
+ json: metrics,
64
+ responseType: 'json',
65
+ headers: {
66
+ 'User-Agent': `Node-RED/${runtime.settings.version}`
67
+ }
68
+ }).json().catch(err => {
69
+ // swallow errors
70
+ runtime.log.debug('Failed to send telemetry: ' + err.toString())
71
+ })
72
+ // Example response:
73
+ // { 'node-red': { latest: '4.0.9', next: '4.1.0-beta.1.9' } }
74
+ runtime.log.debug(`Telemetry response: ${JSON.stringify(response)}`)
75
+ // Get response from endpoint
76
+ if (response?.['node-red']) {
77
+ const currentVersion = metrics.env['node-red']
78
+ if (semver.valid(currentVersion)) {
79
+ const latest = response['node-red'].latest
80
+ const next = response['node-red'].next
81
+ let updatePayload
82
+ if (semver.lt(currentVersion, latest)) {
83
+ // Case one: current < latest
84
+ runtime.log.info(`A new version of Node-RED is available: ${latest}`)
85
+ updatePayload = { version: latest }
86
+ } else if (semver.gt(currentVersion, latest) && semver.lt(currentVersion, next)) {
87
+ // Case two: current > latest && current < next
88
+ runtime.log.info(`A new beta version of Node-RED is available: ${next}`)
89
+ updatePayload = { version: next }
90
+ }
91
+
92
+ if (updatePayload && isUpdateNotificationEnabled()) {
93
+ runtime.events.emit("runtime-event",{id:"update-available", payload: updatePayload, retain: true});
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ function isTelemetryEnabled () {
100
+ // If NODE_RED_DISABLE_TELEMETRY was set, or --no-telemetry was specified,
101
+ // the settings object will have been updated to disable telemetry explicitly
102
+
103
+ // If there are no telemetry settings then the user has not had a chance
104
+ // to opt out yet - so keep it disabled until they do
105
+
106
+ let telemetrySettings
107
+ try {
108
+ telemetrySettings = runtime.settings.get('telemetry')
109
+ } catch (err) {
110
+ // Settings not available
111
+ }
112
+ let runtimeTelemetryEnabled
113
+ try {
114
+ runtimeTelemetryEnabled = runtime.settings.get('telemetryEnabled')
115
+ } catch (err) {
116
+ // Settings not available
117
+ }
118
+
119
+ if (telemetrySettings === undefined && runtimeTelemetryEnabled === undefined) {
120
+ // No telemetry settings - so keep it disabled
121
+ return undefined
122
+ }
123
+
124
+ // User has made a choice; defer to that
125
+ if (runtimeTelemetryEnabled !== undefined) {
126
+ return runtimeTelemetryEnabled
127
+ }
128
+
129
+ // If there are telemetry settings, use what it says
130
+ if (telemetrySettings && telemetrySettings.enabled !== undefined) {
131
+ return telemetrySettings.enabled
132
+ }
133
+
134
+ // At this point, we have no sign the user has consented to telemetry, so
135
+ // keep disabled - but return undefined as a false-like value to distinguish
136
+ // it from the explicit disable above
137
+ return undefined
138
+ }
139
+
140
+ function isUpdateNotificationEnabled () {
141
+ const telemetrySettings = runtime.settings.get('telemetry') || {}
142
+ return telemetrySettings.updateNotification !== false
143
+ }
144
+ /**
145
+ * Start the telemetry schedule
146
+ */
147
+ function startTelemetry () {
148
+ if (scheduleTask) {
149
+ // Already scheduled - nothing left to do
150
+ return
151
+ }
152
+
153
+ const pingTime = new Date(Date.now() + INITIAL_PING_DELAY)
154
+ const pingMinutes = pingTime.getMinutes()
155
+ const pingHours = pingTime.getHours()
156
+ const pingSchedule = `${pingMinutes} ${pingHours} * * *`
157
+
158
+ runtime.log.debug(`Telemetry enabled. Schedule: ${pingSchedule}`)
159
+
160
+ scheduleTask = cronosjs.scheduleTask(pingSchedule, () => {
161
+ report()
162
+ })
163
+ }
164
+
165
+ function stopTelemetry () {
166
+ if (scheduleTask) {
167
+ runtime.log.debug(`Telemetry disabled`)
168
+ scheduleTask.stop()
169
+ scheduleTask = null
170
+ }
171
+ }
172
+
173
+ module.exports = {
174
+ init: (_runtime) => {
175
+ runtime = _runtime
176
+
177
+ if (isTelemetryEnabled()) {
178
+ startTelemetry()
179
+ }
180
+ },
181
+ /**
182
+ * Enable telemetry via user opt-in in the editor
183
+ */
184
+ enable: () => {
185
+ if (runtime.settings.available()) {
186
+ runtime.settings.set('telemetryEnabled', true)
187
+ }
188
+ startTelemetry()
189
+ },
190
+
191
+ /**
192
+ * Disable telemetry via user opt-in in the editor
193
+ */
194
+ disable: () => {
195
+ if (runtime.settings.available()) {
196
+ runtime.settings.set('telemetryEnabled', false)
197
+ }
198
+ stopTelemetry()
199
+ },
200
+
201
+ /**
202
+ * Get telemetry enabled status
203
+ * @returns {boolean} true if telemetry is enabled, false if disabled, undefined if not set
204
+ */
205
+ isEnabled: isTelemetryEnabled,
206
+
207
+ stop: () => {
208
+ if (scheduleTask) {
209
+ scheduleTask.stop()
210
+ scheduleTask = null
211
+ }
212
+ }
213
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = (runtime) => {
2
+ return {
3
+ instanceId: runtime.settings.get('instanceId')
4
+ }
5
+ }
@@ -0,0 +1,9 @@
1
+ const os = require('os')
2
+
3
+ module.exports = (_) => {
4
+ return {
5
+ 'os.type': os.type(),
6
+ 'os.release': os.release(),
7
+ 'os.arch': os.arch()
8
+ }
9
+ }
@@ -0,0 +1,8 @@
1
+ const process = require('process')
2
+
3
+ module.exports = (runtime) => {
4
+ return {
5
+ 'env.nodejs': process.version.replace(/^v/, ''),
6
+ 'env.node-red': runtime.settings.version
7
+ }
8
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = (runtime) => {
2
+ return {
3
+ instanceId: runtime.settings.get('instanceId')
4
+ }
5
+ }
@@ -0,0 +1,9 @@
1
+ const os = require('os')
2
+
3
+ module.exports = (_) => {
4
+ return {
5
+ 'os.type': os.type(),
6
+ 'os.release': os.release(),
7
+ 'os.arch': os.arch()
8
+ }
9
+ }
@@ -0,0 +1,8 @@
1
+ const process = require('process')
2
+
3
+ module.exports = (runtime) => {
4
+ return {
5
+ 'env.nodejs': process.version.replace(/^v/, ''),
6
+ 'env.node-red': runtime.settings.version
7
+ }
8
+ }
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/tego-standard/tego-standard/node_modules/.pnpm/semver@7.7.1/node_modules/semver/bin/node_modules:/home/runner/work/tego-standard/tego-standard/node_modules/.pnpm/semver@7.7.1/node_modules/semver/node_modules:/home/runner/work/tego-standard/tego-standard/node_modules/.pnpm/semver@7.7.1/node_modules:/home/runner/work/tego-standard/tego-standard/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/tego-standard/tego-standard/node_modules/.pnpm/semver@7.7.1/node_modules/semver/bin/node_modules:/home/runner/work/tego-standard/tego-standard/node_modules/.pnpm/semver@7.7.1/node_modules/semver/node_modules:/home/runner/work/tego-standard/tego-standard/node_modules/.pnpm/semver@7.7.1/node_modules:/home/runner/work/tego-standard/tego-standard/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../../../semver@7.7.1/node_modules/semver/bin/semver.js" "$@"
19
+ else
20
+ exec node "$basedir/../../../../../../semver@7.7.1/node_modules/semver/bin/semver.js" "$@"
21
+ fi
@@ -1 +1 @@
1
- {"name":"@node-red/runtime","version":"4.0.8","license":"Apache-2.0","main":"./lib/index.js","repository":{"type":"git","url":"https://github.com/node-red/node-red.git"},"contributors":[{"name":"Nick O'Leary"},{"name":"Dave Conway-Jones"}],"dependencies":{"@node-red/registry":"4.0.8","@node-red/util":"4.0.8","async-mutex":"0.5.0","clone":"2.1.2","express":"4.21.2","fs-extra":"11.2.0","json-stringify-safe":"5.0.1","rfdc":"^1.3.1"},"_lastModified":"2025-08-03T23:05:57.670Z"}
1
+ {"name":"@node-red/runtime","version":"4.1.1","license":"Apache-2.0","main":"./lib/index.js","repository":{"type":"git","url":"https://github.com/node-red/node-red.git"},"contributors":[{"name":"Nick O'Leary"},{"name":"Dave Conway-Jones"}],"dependencies":{"@node-red/registry":"4.1.1","@node-red/util":"4.1.1","async-mutex":"0.5.0","clone":"2.1.2","cronosjs":"1.7.1","express":"4.21.2","fs-extra":"11.3.0","got":"12.6.1","json-stringify-safe":"5.0.1","rfdc":"^1.3.1","semver":"7.7.1"},"_lastModified":"2025-11-10T07:33:31.724Z"}
@@ -1 +1 @@
1
- {"name":"@node-red/util","version":"4.0.8","license":"Apache-2.0","repository":{"type":"git","url":"https://github.com/node-red/node-red.git"},"contributors":[{"name":"Nick O'Leary"},{"name":"Dave Conway-Jones"}],"dependencies":{"fs-extra":"11.2.0","i18next":"21.10.0","json-stringify-safe":"5.0.1","jsonata":"2.0.5","lodash.clonedeep":"^4.5.0","moment":"2.30.1","moment-timezone":"0.5.46"},"_lastModified":"2025-08-03T23:05:58.723Z"}
1
+ {"name":"@node-red/util","version":"4.0.8","license":"Apache-2.0","repository":{"type":"git","url":"https://github.com/node-red/node-red.git"},"contributors":[{"name":"Nick O'Leary"},{"name":"Dave Conway-Jones"}],"dependencies":{"fs-extra":"11.2.0","i18next":"21.10.0","json-stringify-safe":"5.0.1","jsonata":"2.0.5","lodash.clonedeep":"^4.5.0","moment":"2.30.1","moment-timezone":"0.5.46"},"_lastModified":"2025-11-10T07:33:32.657Z"}
@@ -1 +1 @@
1
- {"name":"express","description":"Fast, unopinionated, minimalist web framework","version":"4.21.2","author":"TJ Holowaychuk <tj@vision-media.ca>","contributors":["Aaron Heckmann <aaron.heckmann+github@gmail.com>","Ciaran Jessup <ciaranj@gmail.com>","Douglas Christopher Wilson <doug@somethingdoug.com>","Guillermo Rauch <rauchg@gmail.com>","Jonathan Ong <me@jongleberry.com>","Roman Shtylman <shtylman+expressjs@gmail.com>","Young Jae Sim <hanul@hanul.me>"],"license":"MIT","repository":"expressjs/express","homepage":"http://expressjs.com/","funding":{"type":"opencollective","url":"https://opencollective.com/express"},"keywords":["express","framework","sinatra","web","http","rest","restful","router","app","api"],"dependencies":{"accepts":"~1.3.8","array-flatten":"1.1.1","body-parser":"1.20.3","content-disposition":"0.5.4","content-type":"~1.0.4","cookie":"0.7.1","cookie-signature":"1.0.6","debug":"2.6.9","depd":"2.0.0","encodeurl":"~2.0.0","escape-html":"~1.0.3","etag":"~1.8.1","finalhandler":"1.3.1","fresh":"0.5.2","http-errors":"2.0.0","merge-descriptors":"1.0.3","methods":"~1.1.2","on-finished":"2.4.1","parseurl":"~1.3.3","path-to-regexp":"0.1.12","proxy-addr":"~2.0.7","qs":"6.13.0","range-parser":"~1.2.1","safe-buffer":"5.2.1","send":"0.19.0","serve-static":"1.16.2","setprototypeof":"1.2.0","statuses":"2.0.1","type-is":"~1.6.18","utils-merge":"1.0.1","vary":"~1.1.2"},"devDependencies":{"after":"0.8.2","connect-redis":"3.4.2","cookie-parser":"1.4.6","cookie-session":"2.0.0","ejs":"3.1.9","eslint":"8.47.0","express-session":"1.17.2","hbs":"4.2.0","marked":"0.7.0","method-override":"3.0.0","mocha":"10.2.0","morgan":"1.10.0","nyc":"15.1.0","pbkdf2-password":"1.2.1","supertest":"6.3.0","vhost":"~3.0.2"},"engines":{"node":">= 0.10.0"},"files":["LICENSE","History.md","Readme.md","index.js","lib/"],"scripts":{"lint":"eslint .","test":"mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/","test-ci":"nyc --exclude examples --exclude test --exclude benchmarks --reporter=lcovonly --reporter=text npm test","test-cov":"nyc --exclude examples --exclude test --exclude benchmarks --reporter=html --reporter=text npm test","test-tap":"mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/"},"_lastModified":"2025-08-03T23:05:48.542Z"}
1
+ {"name":"express","description":"Fast, unopinionated, minimalist web framework","version":"4.21.2","author":"TJ Holowaychuk <tj@vision-media.ca>","contributors":["Aaron Heckmann <aaron.heckmann+github@gmail.com>","Ciaran Jessup <ciaranj@gmail.com>","Douglas Christopher Wilson <doug@somethingdoug.com>","Guillermo Rauch <rauchg@gmail.com>","Jonathan Ong <me@jongleberry.com>","Roman Shtylman <shtylman+expressjs@gmail.com>","Young Jae Sim <hanul@hanul.me>"],"license":"MIT","repository":"expressjs/express","homepage":"http://expressjs.com/","funding":{"type":"opencollective","url":"https://opencollective.com/express"},"keywords":["express","framework","sinatra","web","http","rest","restful","router","app","api"],"dependencies":{"accepts":"~1.3.8","array-flatten":"1.1.1","body-parser":"1.20.3","content-disposition":"0.5.4","content-type":"~1.0.4","cookie":"0.7.1","cookie-signature":"1.0.6","debug":"2.6.9","depd":"2.0.0","encodeurl":"~2.0.0","escape-html":"~1.0.3","etag":"~1.8.1","finalhandler":"1.3.1","fresh":"0.5.2","http-errors":"2.0.0","merge-descriptors":"1.0.3","methods":"~1.1.2","on-finished":"2.4.1","parseurl":"~1.3.3","path-to-regexp":"0.1.12","proxy-addr":"~2.0.7","qs":"6.13.0","range-parser":"~1.2.1","safe-buffer":"5.2.1","send":"0.19.0","serve-static":"1.16.2","setprototypeof":"1.2.0","statuses":"2.0.1","type-is":"~1.6.18","utils-merge":"1.0.1","vary":"~1.1.2"},"devDependencies":{"after":"0.8.2","connect-redis":"3.4.2","cookie-parser":"1.4.6","cookie-session":"2.0.0","ejs":"3.1.9","eslint":"8.47.0","express-session":"1.17.2","hbs":"4.2.0","marked":"0.7.0","method-override":"3.0.0","mocha":"10.2.0","morgan":"1.10.0","nyc":"15.1.0","pbkdf2-password":"1.2.1","supertest":"6.3.0","vhost":"~3.0.2"},"engines":{"node":">= 0.10.0"},"files":["LICENSE","History.md","Readme.md","index.js","lib/"],"scripts":{"lint":"eslint .","test":"mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/","test-ci":"nyc --exclude examples --exclude test --exclude benchmarks --reporter=lcovonly --reporter=text npm test","test-cov":"nyc --exclude examples --exclude test --exclude benchmarks --reporter=html --reporter=text npm test","test-tap":"mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/"},"_lastModified":"2025-11-10T07:33:22.776Z"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tachybase/plugin-adapter-red-node",
3
3
  "displayName": "Adapter red node",
4
- "version": "1.3.24",
4
+ "version": "1.4.0",
5
5
  "description": "Integrate and manage RedNode workflow automation engine.",
6
6
  "keywords": [
7
7
  "System management"
@@ -10,16 +10,16 @@
10
10
  "devDependencies": {
11
11
  "@node-red/editor-api": "4.0.8",
12
12
  "@node-red/nodes": "4.0.8",
13
- "@node-red/runtime": "4.0.8",
13
+ "@node-red/runtime": "4.1.1",
14
14
  "@node-red/util": "4.0.8",
15
- "@tachybase/test": "^1.3.49",
16
- "@tego/client": "^1.3.49",
17
- "@tego/server": "^1.3.49",
15
+ "@tachybase/test": "*",
16
+ "@tego/client": "*",
17
+ "@tego/server": "*",
18
18
  "@types/express": "5.0.2",
19
19
  "@types/node-red": "1.3.5",
20
20
  "express": "4.21.2",
21
21
  "node-red": "4.0.8",
22
- "@tachybase/client": "1.3.24"
22
+ "@tachybase/client": "1.4.0"
23
23
  },
24
24
  "description.zh-CN": "集成和管理 Node-RED 流程自动化引擎",
25
25
  "displayName.zh-CN": "Node-RED 管理",