signalk-edge-link 2.9.0 → 2.9.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.
package/lib/bonding.js CHANGED
@@ -575,14 +575,15 @@ class BondingManager {
575
575
  return;
576
576
  }
577
577
  try {
578
+ // Emit a `$source` string rather than a structured `source` object:
579
+ // signalk-server derives `${label}.XX` from a label-only source object,
580
+ // which would split this notification across a spurious
581
+ // `signalk-edge-link.XX` bucket. See src/source-dispatch.ts.
578
582
  this.app.handleMessage(this.sourceLabel, {
579
583
  context: "vessels.self",
580
584
  updates: [
581
585
  {
582
- source: {
583
- label: this.sourceLabel,
584
- type: "plugin"
585
- },
586
+ $source: "signalk-edge-link",
586
587
  timestamp: new Date().toISOString(),
587
588
  values: [
588
589
  {
@@ -129,14 +129,17 @@ class MetricsPublisher {
129
129
  }
130
130
  // Only publish if values changed
131
131
  if (this._hasChanged(values)) {
132
+ // Use a `$source` string rather than a structured `source` object.
133
+ // signalk-server's getSourceId() turns a label-only source object into
134
+ // `${label}.XX` (and rewrites our `signalk-edge-link:<instanceId>` label
135
+ // to the plugin id first), which would create a spurious
136
+ // `signalk-edge-link.XX` source bucket alongside the canonical one. A
137
+ // plain `$source` string is stored verbatim. See src/source-dispatch.ts.
132
138
  this.app.handleMessage(this.sourceLabel, {
133
139
  context: "vessels.self",
134
140
  updates: [
135
141
  {
136
- source: {
137
- label: this.sourceLabel,
138
- type: "plugin"
139
- },
142
+ $source: "signalk-edge-link",
140
143
  timestamp: new Date().toISOString(),
141
144
  values: values
142
145
  }
@@ -188,11 +191,13 @@ class MetricsPublisher {
188
191
  })
189
192
  }
190
193
  ];
194
+ // See publish() above: emit a `$source` string so the leaf lands on the
195
+ // canonical `signalk-edge-link` bucket instead of `signalk-edge-link.XX`.
191
196
  this.app.handleMessage(this.sourceLabel, {
192
197
  context: "vessels.self",
193
198
  updates: [
194
199
  {
195
- source: { label: this.sourceLabel, type: "plugin" },
200
+ $source: "signalk-edge-link",
196
201
  timestamp: new Date().toISOString(),
197
202
  values: values
198
203
  }
package/lib/monitoring.js CHANGED
@@ -529,11 +529,15 @@ class AlertManager {
529
529
  return;
530
530
  }
531
531
  try {
532
+ // Emit a `$source` string rather than a structured `source` object:
533
+ // signalk-server derives `${label}.XX` from a label-only source object,
534
+ // which would split this notification across a spurious
535
+ // `signalk-edge-link.XX` bucket. See src/source-dispatch.ts.
532
536
  this.app.handleMessage(this.sourceLabel, {
533
537
  context: "vessels.self",
534
538
  updates: [
535
539
  {
536
- source: { label: this.sourceLabel, type: "plugin" },
540
+ $source: "signalk-edge-link",
537
541
  timestamp: new Date().toISOString(),
538
542
  values: [{ path, value: { state, message, method } }]
539
543
  }
@@ -67,6 +67,17 @@ function resolveSourceRef(update) {
67
67
  }
68
68
  return derived;
69
69
  }
70
+ /**
71
+ * Return true when at least one value in the update targets a
72
+ * `networking.edgeLink.*` path (own-data namespace owned by this plugin).
73
+ */
74
+ function hasEdgeLinkOwnDataValues(update) {
75
+ if (!Array.isArray(update.values)) {
76
+ return false;
77
+ }
78
+ return update.values.some((v) => typeof v.path === "string" &&
79
+ v.path.startsWith("networking.edgeLink."));
80
+ }
70
81
  /**
71
82
  * Build the update object actually handed to `app.handleMessage`.
72
83
  *
@@ -87,7 +98,18 @@ function resolveSourceRef(update) {
87
98
  * available under `/signalk/v1/api/sources`.
88
99
  */
89
100
  function prepareUpdateForDispatch(update) {
90
- const sourceRef = resolveSourceRef(update);
101
+ let sourceRef = resolveSourceRef(update);
102
+ // Normalise stale qualified signalk-edge-link refs (e.g. ".XX",
103
+ // ":instanceId") to the canonical base label for networking.edgeLink.*
104
+ // values. Old plugin versions used a label-only `source` object which
105
+ // signalk-server converts to "${label}.XX" via getSourceId; normalising
106
+ // here collapses that spurious bucket into the same key the receiver's
107
+ // own MetricsPublisher uses, preventing the dual-source appearance.
108
+ if (sourceRef !== "signalk-edge-link" &&
109
+ isStaleEdgeLinkRef(sourceRef) &&
110
+ hasEdgeLinkOwnDataValues(update)) {
111
+ sourceRef = "signalk-edge-link";
112
+ }
91
113
  const prepared = {
92
114
  values: Array.isArray(update.values)
93
115
  ? update.values.map((value) => ({ ...value }))
package/package.json CHANGED
@@ -1,167 +1,167 @@
1
- {
2
- "name": "signalk-edge-link",
3
- "version": "2.9.0",
4
- "description": "SignalK Edge Link. Secure UDP link for data exchange.",
5
- "main": "lib/index.js",
6
- "files": [
7
- "lib/",
8
- "public/"
9
- ],
10
- "keywords": [
11
- "signalk-node-server-plugin",
12
- "signalk-category-network",
13
- "signalk-webapp",
14
- "signalk-category-utility",
15
- "signalk-plugin-configurator"
16
- ],
17
- "signalk": {
18
- "appIcon": "./icons/icon-72x72.png",
19
- "displayName": "Edge Link Configuration"
20
- },
21
- "signalk-plugin-enabled-by-default": false,
22
- "scripts": {
23
- "clean:lib": "node -e \"const fs=require('fs');if(fs.existsSync('lib'))fs.rmSync('lib',{recursive:true,force:true});\"",
24
- "clean:public": "node -e \"const fs=require('fs');if(fs.existsSync('public'))fs.rmSync('public',{recursive:true,force:true});\"",
25
- "build": "npm run build:ts && npm run build:web",
26
- "build:web": "npm run clean:public && webpack --mode production",
27
- "build:ts": "npm run clean:lib && tsc",
28
- "check:ts": "tsc --noEmit",
29
- "check:release-docs": "node scripts/check-release-truth.js",
30
- "dev": "webpack --mode development --watch",
31
- "test": "jest --runInBand",
32
- "test:v2": "jest __tests__/v2/",
33
- "test:integration": "jest __tests__/integration/",
34
- "test:watch": "jest --watch",
35
- "test:coverage": "jest --coverage",
36
- "lint": "eslint .",
37
- "lint:fix": "eslint . --fix",
38
- "format": "prettier --write \"**/*.{js,ts,json,md}\"",
39
- "migrate:config": "node lib/scripts/migrate-config.js",
40
- "cli": "node lib/bin/edge-link-cli.js",
41
- "prepare": "husky"
42
- },
43
- "dependencies": {
44
- "@msgpack/msgpack": "^3.0.0",
45
- "@rjsf/core": "^5.18.4",
46
- "@rjsf/utils": "^5.18.4",
47
- "@rjsf/validator-ajv8": "^5.18.4",
48
- "ping-monitor": "^0.8.2"
49
- },
50
- "devDependencies": {
51
- "@babel/core": "^7.22.0",
52
- "@babel/preset-env": "^7.22.0",
53
- "@babel/preset-react": "^7.22.0",
54
- "@testing-library/jest-dom": "^5.17.0",
55
- "@testing-library/react": "^12.1.5",
56
- "@types/node": "^25.3.5",
57
- "@types/react": "^16.14.0",
58
- "@types/react-dom": "^16.9.0",
59
- "babel-loader": "^9.1.2",
60
- "copy-webpack-plugin": "^14.0.0",
61
- "css-loader": "^6.8.1",
62
- "eslint": "^8.57.1",
63
- "eslint-plugin-react": "^7.37.5",
64
- "html-webpack-plugin": "^5.5.3",
65
- "husky": "^9.1.7",
66
- "jest": "^29.7.0",
67
- "jest-environment-jsdom": "^30.3.0",
68
- "lint-staged": "^15.4.3",
69
- "mini-css-extract-plugin": "^2.7.6",
70
- "prettier": "^3.6.2",
71
- "react": "^16.13.1",
72
- "react-dom": "^16.13.1",
73
- "react-test-renderer": "^16.14.0",
74
- "style-loader": "^3.3.3",
75
- "ts-jest": "^29.4.6",
76
- "ts-loader": "^9.5.4",
77
- "typescript": "^5.9.3",
78
- "webpack": "^5.102.1",
79
- "webpack-cli": "^5.1.4"
80
- },
81
- "engines": {
82
- "node": ">=16"
83
- },
84
- "author": "Karl-Erik Gustafsson",
85
- "repository": "https://github.com/KEGustafsson/signalk-edge-link",
86
- "homepage": "https://github.com/KEGustafsson/signalk-edge-link#readme",
87
- "bugs": {
88
- "url": "https://github.com/KEGustafsson/signalk-edge-link/issues"
89
- },
90
- "license": "MIT",
91
- "jest": {
92
- "testEnvironment": "node",
93
- "coverageDirectory": "coverage",
94
- "collectCoverageFrom": [
95
- "lib/**/*.js",
96
- "!lib/webapp/**",
97
- "!lib/components/**",
98
- "!lib/utils/**"
99
- ],
100
- "testMatch": [
101
- "**/__tests__/**/*.js",
102
- "**/*.test.js",
103
- "**/*.spec.js"
104
- ],
105
- "transform": {
106
- "^.+\\.js$": [
107
- "babel-jest",
108
- {
109
- "presets": [
110
- [
111
- "@babel/preset-env",
112
- {
113
- "targets": {
114
- "node": "current"
115
- }
116
- }
117
- ]
118
- ]
119
- }
120
- ],
121
- ".+\\.tsx$": [
122
- "ts-jest",
123
- {
124
- "tsconfig": "tsconfig.webapp.json",
125
- "diagnostics": false
126
- }
127
- ],
128
- "^.+\\.ts$": "ts-jest"
129
- },
130
- "moduleFileExtensions": [
131
- "ts",
132
- "tsx",
133
- "js",
134
- "json",
135
- "node"
136
- ],
137
- "testPathIgnorePatterns": [
138
- "/node_modules/",
139
- "/public/",
140
- "/__tests__/benchmarks/",
141
- "/__tests__/network-simulator\\.js$"
142
- ],
143
- "coverageThreshold": {
144
- "global": {
145
- "branches": 60,
146
- "functions": 65,
147
- "lines": 65,
148
- "statements": 65
149
- }
150
- }
151
- },
152
- "bin": {
153
- "edge-link-cli": "lib/bin/edge-link-cli.js"
154
- },
155
- "lint-staged": {
156
- "*.js": [
157
- "prettier --write",
158
- "eslint --fix"
159
- ],
160
- "*.ts": [
161
- "prettier --write"
162
- ],
163
- "*.{json,md}": [
164
- "prettier --write"
165
- ]
166
- }
167
- }
1
+ {
2
+ "name": "signalk-edge-link",
3
+ "version": "2.9.1",
4
+ "description": "SignalK Edge Link. Secure UDP link for data exchange.",
5
+ "main": "lib/index.js",
6
+ "files": [
7
+ "lib/",
8
+ "public/"
9
+ ],
10
+ "keywords": [
11
+ "signalk-node-server-plugin",
12
+ "signalk-category-network",
13
+ "signalk-webapp",
14
+ "signalk-category-utility",
15
+ "signalk-plugin-configurator"
16
+ ],
17
+ "signalk": {
18
+ "appIcon": "./icons/icon-72x72.png",
19
+ "displayName": "Edge Link Configuration"
20
+ },
21
+ "signalk-plugin-enabled-by-default": false,
22
+ "scripts": {
23
+ "clean:lib": "node -e \"const fs=require('fs');if(fs.existsSync('lib'))fs.rmSync('lib',{recursive:true,force:true});\"",
24
+ "clean:public": "node -e \"const fs=require('fs');if(fs.existsSync('public'))fs.rmSync('public',{recursive:true,force:true});\"",
25
+ "build": "npm run build:ts && npm run build:web",
26
+ "build:web": "npm run clean:public && webpack --mode production",
27
+ "build:ts": "npm run clean:lib && tsc",
28
+ "check:ts": "tsc --noEmit",
29
+ "check:release-docs": "node scripts/check-release-truth.js",
30
+ "dev": "webpack --mode development --watch",
31
+ "test": "jest --runInBand",
32
+ "test:v2": "jest __tests__/v2/",
33
+ "test:integration": "jest __tests__/integration/",
34
+ "test:watch": "jest --watch",
35
+ "test:coverage": "jest --coverage",
36
+ "lint": "eslint .",
37
+ "lint:fix": "eslint . --fix",
38
+ "format": "prettier --write \"**/*.{js,ts,json,md}\"",
39
+ "migrate:config": "node lib/scripts/migrate-config.js",
40
+ "cli": "node lib/bin/edge-link-cli.js",
41
+ "prepare": "husky"
42
+ },
43
+ "dependencies": {
44
+ "@msgpack/msgpack": "^3.0.0",
45
+ "@rjsf/core": "^5.18.4",
46
+ "@rjsf/utils": "^5.18.4",
47
+ "@rjsf/validator-ajv8": "^5.18.4",
48
+ "ping-monitor": "^0.8.2"
49
+ },
50
+ "devDependencies": {
51
+ "@babel/core": "^7.22.0",
52
+ "@babel/preset-env": "^7.22.0",
53
+ "@babel/preset-react": "^7.22.0",
54
+ "@testing-library/jest-dom": "^5.17.0",
55
+ "@testing-library/react": "^12.1.5",
56
+ "@types/node": "^25.3.5",
57
+ "@types/react": "^16.14.0",
58
+ "@types/react-dom": "^16.9.0",
59
+ "babel-loader": "^9.1.2",
60
+ "copy-webpack-plugin": "^14.0.0",
61
+ "css-loader": "^6.8.1",
62
+ "eslint": "^8.57.1",
63
+ "eslint-plugin-react": "^7.37.5",
64
+ "html-webpack-plugin": "^5.5.3",
65
+ "husky": "^9.1.7",
66
+ "jest": "^29.7.0",
67
+ "jest-environment-jsdom": "^30.3.0",
68
+ "lint-staged": "^15.4.3",
69
+ "mini-css-extract-plugin": "^2.7.6",
70
+ "prettier": "^3.6.2",
71
+ "react": "^16.13.1",
72
+ "react-dom": "^16.13.1",
73
+ "react-test-renderer": "^16.14.0",
74
+ "style-loader": "^3.3.3",
75
+ "ts-jest": "^29.4.6",
76
+ "ts-loader": "^9.5.4",
77
+ "typescript": "^5.9.3",
78
+ "webpack": "^5.102.1",
79
+ "webpack-cli": "^5.1.4"
80
+ },
81
+ "engines": {
82
+ "node": ">=24"
83
+ },
84
+ "author": "Karl-Erik Gustafsson",
85
+ "repository": "https://github.com/KEGustafsson/signalk-edge-link",
86
+ "homepage": "https://github.com/KEGustafsson/signalk-edge-link#readme",
87
+ "bugs": {
88
+ "url": "https://github.com/KEGustafsson/signalk-edge-link/issues"
89
+ },
90
+ "license": "MIT",
91
+ "jest": {
92
+ "testEnvironment": "node",
93
+ "coverageDirectory": "coverage",
94
+ "collectCoverageFrom": [
95
+ "lib/**/*.js",
96
+ "!lib/webapp/**",
97
+ "!lib/components/**",
98
+ "!lib/utils/**"
99
+ ],
100
+ "testMatch": [
101
+ "**/__tests__/**/*.js",
102
+ "**/*.test.js",
103
+ "**/*.spec.js"
104
+ ],
105
+ "transform": {
106
+ "^.+\\.js$": [
107
+ "babel-jest",
108
+ {
109
+ "presets": [
110
+ [
111
+ "@babel/preset-env",
112
+ {
113
+ "targets": {
114
+ "node": "current"
115
+ }
116
+ }
117
+ ]
118
+ ]
119
+ }
120
+ ],
121
+ ".+\\.tsx$": [
122
+ "ts-jest",
123
+ {
124
+ "tsconfig": "tsconfig.webapp.json",
125
+ "diagnostics": false
126
+ }
127
+ ],
128
+ "^.+\\.ts$": "ts-jest"
129
+ },
130
+ "moduleFileExtensions": [
131
+ "ts",
132
+ "tsx",
133
+ "js",
134
+ "json",
135
+ "node"
136
+ ],
137
+ "testPathIgnorePatterns": [
138
+ "/node_modules/",
139
+ "/public/",
140
+ "/__tests__/benchmarks/",
141
+ "/__tests__/network-simulator\\.js$"
142
+ ],
143
+ "coverageThreshold": {
144
+ "global": {
145
+ "branches": 60,
146
+ "functions": 65,
147
+ "lines": 65,
148
+ "statements": 65
149
+ }
150
+ }
151
+ },
152
+ "bin": {
153
+ "edge-link-cli": "lib/bin/edge-link-cli.js"
154
+ },
155
+ "lint-staged": {
156
+ "*.js": [
157
+ "prettier --write",
158
+ "eslint --fix"
159
+ ],
160
+ "*.ts": [
161
+ "prettier --write"
162
+ ],
163
+ "*.{json,md}": [
164
+ "prettier --write"
165
+ ]
166
+ }
167
+ }