@rhizomatics/signalk-einklabel-plugin 0.7.0 → 0.7.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/CHANGELOG.md
CHANGED
package/dist/cli/liveContext.js
CHANGED
|
@@ -8,6 +8,7 @@ exports.assembleExampleContext = assembleExampleContext;
|
|
|
8
8
|
const promises_1 = require("fs/promises");
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const formatters_1 = require("../render/formatters");
|
|
11
|
+
const unwrapSignalkTree_1 = require("../render/unwrapSignalkTree");
|
|
11
12
|
const httpJson_1 = require("../httpJson");
|
|
12
13
|
const unitCategories_1 = require("../unitCategories");
|
|
13
14
|
const pathMeta_1 = require("../pathMeta");
|
|
@@ -18,29 +19,6 @@ const RESOURCES_API_PATH = "/signalk/v2/api/resources";
|
|
|
18
19
|
function contextPath(context) {
|
|
19
20
|
return context === "self" ? "vessels/self" : context.replace(/\./g, "/");
|
|
20
21
|
}
|
|
21
|
-
/**
|
|
22
|
-
* `GET .../vessels/self` (or any other subtree) returns SignalK's full delta-tree shape, where every
|
|
23
|
-
* leaf is wrapped as `{ value, $source, timestamp, ... }` rather than the bare value - unlike
|
|
24
|
-
* `app.getSelfPath`/`getPath` in the live plugin (repaintScheduler.ts), which already return bare
|
|
25
|
-
* values. Recursively unwraps every such leaf so `path=` bindings resolve the same way over HTTP as
|
|
26
|
-
* they do live. Only applied to `signalk` fetches - `resources` responses have no such wrapper.
|
|
27
|
-
*
|
|
28
|
-
* Keys off `value` alone, not also requiring `timestamp`/`$source` - not every server includes both on
|
|
29
|
-
* every leaf, and a `value` key is otherwise meaningless on a SignalK data-model node (it isn't a
|
|
30
|
-
* regular vessel property name), so there's no real risk of unwrapping something that isn't this
|
|
31
|
-
* wrapper.
|
|
32
|
-
*/
|
|
33
|
-
function unwrapSignalkTree(node) {
|
|
34
|
-
if (node === null || typeof node !== "object")
|
|
35
|
-
return node;
|
|
36
|
-
if (Array.isArray(node))
|
|
37
|
-
return node.map(unwrapSignalkTree);
|
|
38
|
-
const obj = node;
|
|
39
|
-
if ("value" in obj) {
|
|
40
|
-
return obj.value;
|
|
41
|
-
}
|
|
42
|
-
return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, unwrapSignalkTree(value)]));
|
|
43
|
-
}
|
|
44
22
|
/**
|
|
45
23
|
* CLI counterpart to `assembleRawContext` + `considerRepaint`'s `meta` injection in
|
|
46
24
|
* repaintScheduler.ts - same `{ signalk, resources, pathMeta, categories, meta }` shape, but fetched
|
|
@@ -56,7 +34,7 @@ async function assembleLiveContext(signalkUrl, bindings) {
|
|
|
56
34
|
for (const context of contexts) {
|
|
57
35
|
const url = `${signalkUrl}/signalk/v1/api/${contextPath(context)}`;
|
|
58
36
|
(0, log_1.logDebug)(`GET ${url}`);
|
|
59
|
-
signalk[context] = unwrapSignalkTree(await (0, httpJson_1.fetchJson)(url));
|
|
37
|
+
signalk[context] = (0, unwrapSignalkTree_1.unwrapSignalkTree)(await (0, httpJson_1.fetchJson)(url));
|
|
60
38
|
}
|
|
61
39
|
const pathMeta = {};
|
|
62
40
|
for (const context of contexts) {
|
|
@@ -130,7 +108,7 @@ async function assembleExampleContext(examplesDir, bindings) {
|
|
|
130
108
|
if (node === undefined) {
|
|
131
109
|
throw new Error(`example data file ${vesselsPath} has no "${segments.join(".")}" subtree for context "${context}"`);
|
|
132
110
|
}
|
|
133
|
-
signalk[context] = unwrapSignalkTree(node);
|
|
111
|
+
signalk[context] = (0, unwrapSignalkTree_1.unwrapSignalkTree)(node);
|
|
134
112
|
}
|
|
135
113
|
}
|
|
136
114
|
const resources = {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignalK's full data-model shape wraps every leaf as `{ value, $source, timestamp, ... }` rather
|
|
3
|
+
* than the bare value - true both over HTTP (`GET .../vessels/self`) and in-process
|
|
4
|
+
* (`app.getSelfPath`/`getPath` in the live plugin, see `repaintScheduler.ts` - despite that module's
|
|
5
|
+
* name, these do NOT already return bare values for a regular published path; only a handful of
|
|
6
|
+
* vessel-identity fields like `uuid` do). Recursively unwraps every such leaf so a `path=` binding
|
|
7
|
+
* resolves the same way regardless of which of the two ways the render context was assembled. Only
|
|
8
|
+
* applied to `signalk` fetches - `resources` responses have no such wrapper.
|
|
9
|
+
*
|
|
10
|
+
* Keys off `value` alone, not also requiring `timestamp`/`$source` - not every server includes both
|
|
11
|
+
* on every leaf, and a `value` key is otherwise meaningless on a SignalK data-model node (it isn't a
|
|
12
|
+
* regular vessel property name), so there's no real risk of unwrapping something that isn't this
|
|
13
|
+
* wrapper.
|
|
14
|
+
*/
|
|
15
|
+
export declare function unwrapSignalkTree(node: unknown): unknown;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.unwrapSignalkTree = unwrapSignalkTree;
|
|
4
|
+
/**
|
|
5
|
+
* SignalK's full data-model shape wraps every leaf as `{ value, $source, timestamp, ... }` rather
|
|
6
|
+
* than the bare value - true both over HTTP (`GET .../vessels/self`) and in-process
|
|
7
|
+
* (`app.getSelfPath`/`getPath` in the live plugin, see `repaintScheduler.ts` - despite that module's
|
|
8
|
+
* name, these do NOT already return bare values for a regular published path; only a handful of
|
|
9
|
+
* vessel-identity fields like `uuid` do). Recursively unwraps every such leaf so a `path=` binding
|
|
10
|
+
* resolves the same way regardless of which of the two ways the render context was assembled. Only
|
|
11
|
+
* applied to `signalk` fetches - `resources` responses have no such wrapper.
|
|
12
|
+
*
|
|
13
|
+
* Keys off `value` alone, not also requiring `timestamp`/`$source` - not every server includes both
|
|
14
|
+
* on every leaf, and a `value` key is otherwise meaningless on a SignalK data-model node (it isn't a
|
|
15
|
+
* regular vessel property name), so there's no real risk of unwrapping something that isn't this
|
|
16
|
+
* wrapper.
|
|
17
|
+
*/
|
|
18
|
+
function unwrapSignalkTree(node) {
|
|
19
|
+
if (node === null || typeof node !== "object")
|
|
20
|
+
return node;
|
|
21
|
+
if (Array.isArray(node))
|
|
22
|
+
return node.map(unwrapSignalkTree);
|
|
23
|
+
const obj = node;
|
|
24
|
+
if ("value" in obj) {
|
|
25
|
+
return obj.value;
|
|
26
|
+
}
|
|
27
|
+
return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, unwrapSignalkTree(value)]));
|
|
28
|
+
}
|
package/dist/repaintScheduler.js
CHANGED
|
@@ -10,6 +10,7 @@ const registry_1 = require("./devices/registry");
|
|
|
10
10
|
const svgRenderer_1 = require("./render/svgRenderer");
|
|
11
11
|
const binding_1 = require("./render/binding");
|
|
12
12
|
const formatters_1 = require("./render/formatters");
|
|
13
|
+
const unwrapSignalkTree_1 = require("./render/unwrapSignalkTree");
|
|
13
14
|
const unitCategories_1 = require("./unitCategories");
|
|
14
15
|
const pathMeta_1 = require("./pathMeta");
|
|
15
16
|
const resolveApiUrl_1 = require("./resolveApiUrl");
|
|
@@ -58,13 +59,20 @@ function setAtPath(target, path, value) {
|
|
|
58
59
|
/**
|
|
59
60
|
* Reads live data for exactly what a template's own bindings ask for - no separate config declaring it.
|
|
60
61
|
* `signalk`-sourced bindings are read directly (`self` via `getSelfPath`, anything else via `getPath`
|
|
61
|
-
* against that literal SignalK context) - in-process, no URL needed.
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
62
|
+
* against that literal SignalK context) - in-process, no URL needed. Despite their names, neither
|
|
63
|
+
* already returns a bare value for a regular published path - both return the full data-model node
|
|
64
|
+
* (`{ path, value, context, source, $source, timestamp }`); only a handful of vessel-identity fields
|
|
65
|
+
* like `uuid` come back bare. `unwrapSignalkTree` strips that wrapper the same way it does for the
|
|
66
|
+
* CLI's HTTP-fetched equivalent (`assembleLiveContext` in `cli/liveContext.ts`), so a `path=` binding
|
|
67
|
+
* resolves to the same value either way - without it, `resolveBinding` would hand back the whole
|
|
68
|
+
* wrapper object instead of e.g. a plain string, breaking any binding that expects one (a `<image>`'s
|
|
69
|
+
* `assets=`, a `format=` formatter, etc). `resources`-sourced bindings go through `app.resourcesApi`,
|
|
70
|
+
* in-process too, with no such wrapper. Per-path unit-conversion metadata (`pathMeta`, for automatic
|
|
71
|
+
* conversion - see `renderBinding`) and an explicit `category=` binding's resolved conversion both
|
|
72
|
+
* have no in-process equivalent (confirmed against the signalk-server source - that resolution only
|
|
73
|
+
* happens in its REST layer), so both need `apiUrl` - fetching `pathMeta` is best-effort (a
|
|
74
|
+
* missing/unreachable server just means no automatic conversion), but a `category=` binding is a
|
|
75
|
+
* declared dependency, so a missing `apiUrl` is a hard error there.
|
|
68
76
|
*/
|
|
69
77
|
async function assembleRawContext(app, apiUrl, bindings) {
|
|
70
78
|
var _a;
|
|
@@ -77,7 +85,8 @@ async function assembleRawContext(app, apiUrl, bindings) {
|
|
|
77
85
|
if (seenSignalk.has(key))
|
|
78
86
|
continue;
|
|
79
87
|
seenSignalk.add(key);
|
|
80
|
-
const
|
|
88
|
+
const rawValue = binding.context === "self" ? app.getSelfPath(binding.path) : app.getPath(`${binding.context}.${binding.path}`);
|
|
89
|
+
const value = (0, unwrapSignalkTree_1.unwrapSignalkTree)(rawValue);
|
|
81
90
|
const namespace = (signalk[_a = binding.context] ?? (signalk[_a] = {}));
|
|
82
91
|
setAtPath(namespace, binding.path, value);
|
|
83
92
|
}
|