@2112-lab/central-plant 0.3.58 โ 0.3.59
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/dist/bundle/index.js +1635 -32
- package/dist/cjs/src/core/centralPlant.js +80 -11
- package/dist/cjs/src/core/centralPlantInternals.js +4 -0
- package/dist/cjs/src/core/centralPlantValidator.js +10 -6
- package/dist/cjs/src/core/stateEngine.js +733 -0
- package/dist/cjs/src/core/stateEngineScene.js +97 -0
- package/dist/cjs/src/index.js +10 -0
- package/dist/cjs/src/managers/pathfinding/PathFlowManager.js +94 -13
- package/dist/cjs/src/managers/pathfinding/PathRenderingManager.js +15 -0
- package/dist/cjs/src/managers/scene/componentTooltipManager.js +7 -1
- package/dist/cjs/src/managers/scene/controlPanelManager.js +377 -0
- package/dist/cjs/src/managers/scene/sceneExportManager.js +10 -1
- package/dist/cjs/src/managers/state/EffectiveVisualManager.js +270 -0
- package/dist/esm/src/core/centralPlant.js +80 -11
- package/dist/esm/src/core/centralPlantInternals.js +4 -0
- package/dist/esm/src/core/centralPlantValidator.js +10 -6
- package/dist/esm/src/core/stateEngine.js +725 -0
- package/dist/esm/src/core/stateEngineScene.js +90 -0
- package/dist/esm/src/index.js +2 -0
- package/dist/esm/src/managers/pathfinding/PathFlowManager.js +94 -13
- package/dist/esm/src/managers/pathfinding/PathRenderingManager.js +15 -0
- package/dist/esm/src/managers/scene/componentTooltipManager.js +7 -1
- package/dist/esm/src/managers/scene/controlPanelManager.js +352 -0
- package/dist/esm/src/managers/scene/sceneExportManager.js +10 -1
- package/dist/esm/src/managers/state/EffectiveVisualManager.js +266 -0
- package/dist/index.d.ts +85 -0
- package/package.json +5 -2
|
@@ -2,6 +2,7 @@ import { createClass as _createClass, classCallCheck as _classCallCheck, toConsu
|
|
|
2
2
|
import 'three';
|
|
3
3
|
import { GLTFExporter } from '../../../node_modules/three/examples/jsm/exporters/GLTFExporter.js';
|
|
4
4
|
import { getHardcodedUuid } from '../../utils/nameUtils.js';
|
|
5
|
+
import { applyDeclarationToExport } from '../../core/stateEngineScene.js';
|
|
5
6
|
|
|
6
7
|
var SceneExportManager = /*#__PURE__*/function () {
|
|
7
8
|
function SceneExportManager(sceneViewer) {
|
|
@@ -56,7 +57,8 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
56
57
|
key: "exportSceneData",
|
|
57
58
|
value: function exportSceneData() {
|
|
58
59
|
var _this = this,
|
|
59
|
-
_this$sceneViewer$cur2
|
|
60
|
+
_this$sceneViewer$cur2,
|
|
61
|
+
_this$sceneViewer$cen;
|
|
60
62
|
console.log('๐ค Starting scene export...');
|
|
61
63
|
if (!this.sceneViewer.scene) {
|
|
62
64
|
console.warn('โ ๏ธ No scene available for export');
|
|
@@ -289,6 +291,13 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
289
291
|
if (sceneBehaviors && sceneBehaviors.length > 0) {
|
|
290
292
|
exportData.behaviors = sceneBehaviors;
|
|
291
293
|
}
|
|
294
|
+
|
|
295
|
+
// Persist plant / groups / chains / stateRegistry from the State Engine and
|
|
296
|
+
// bump the format to 3.0 (Framework ยง12; no-op if no engine present).
|
|
297
|
+
var stateEngine = (_this$sceneViewer$cen = this.sceneViewer.centralPlant) === null || _this$sceneViewer$cen === void 0 ? void 0 : _this$sceneViewer$cen.stateEngine;
|
|
298
|
+
if (stateEngine) {
|
|
299
|
+
applyDeclarationToExport(exportData, stateEngine);
|
|
300
|
+
}
|
|
292
301
|
console.log('โ
Scene export completed:', exportData);
|
|
293
302
|
console.log("\uD83D\uDCCA Exported ".concat(sceneChildren.length, " components and ").concat(exportData.connections.length, " connections"));
|
|
294
303
|
return exportData;
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { inherits as _inherits, createClass as _createClass, slicedToArray as _slicedToArray, createForOfIteratorHelper as _createForOfIteratorHelper, classCallCheck as _classCallCheck, callSuper as _callSuper } from '../../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
+
import { BaseDisposable } from '../../core/baseDisposable.js';
|
|
3
|
+
import { findObjectByHardcodedUuid } from '../../utils/nameUtils.js';
|
|
4
|
+
|
|
5
|
+
/** How far the albedo is pulled toward black for a gated-off mesh. */
|
|
6
|
+
var OFF_COLOR_SCALE = 0.2;
|
|
7
|
+
var EffectiveVisualManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
8
|
+
/**
|
|
9
|
+
* @param {Object} sceneViewer - The central sceneViewer hub
|
|
10
|
+
*/
|
|
11
|
+
function EffectiveVisualManager(sceneViewer) {
|
|
12
|
+
var _this;
|
|
13
|
+
_classCallCheck(this, EffectiveVisualManager);
|
|
14
|
+
_this = _callSuper(this, EffectiveVisualManager);
|
|
15
|
+
_this.sceneViewer = sceneViewer;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Materials this manager has gated (cloned + cached), for restore on dispose.
|
|
19
|
+
* @type {Set<THREE.Material>}
|
|
20
|
+
*/
|
|
21
|
+
_this._gatedMaterials = new Set();
|
|
22
|
+
|
|
23
|
+
// Bound handlers so we can unsubscribe in _doDispose().
|
|
24
|
+
_this._onChange = _this._onChange.bind(_this);
|
|
25
|
+
_this._regateAll = _this._regateAll.bind(_this);
|
|
26
|
+
if (sceneViewer !== null && sceneViewer !== void 0 && sceneViewer.on) {
|
|
27
|
+
sceneViewer.on('engine-state-changed', _this._onChange);
|
|
28
|
+
sceneViewer.on('scene-loaded', _this._regateAll);
|
|
29
|
+
}
|
|
30
|
+
return _this;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// โโ Engine change handling โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* React to one committed registry change. Only 2-part object / pipe addresses
|
|
37
|
+
* are gated; everything else is ignored.
|
|
38
|
+
* @param {{ address: string, desired: *, effective: * }} change
|
|
39
|
+
* @private
|
|
40
|
+
*/
|
|
41
|
+
_inherits(EffectiveVisualManager, _BaseDisposable);
|
|
42
|
+
return _createClass(EffectiveVisualManager, [{
|
|
43
|
+
key: "_onChange",
|
|
44
|
+
value: function _onChange(change) {
|
|
45
|
+
if (!change || typeof change.address !== 'string') return;
|
|
46
|
+
var parts = change.address.split('::');
|
|
47
|
+
if (parts.length !== 2) return; // 3-part I/O is desired-driven; skip
|
|
48
|
+
|
|
49
|
+
var _parts = _slicedToArray(parts, 2),
|
|
50
|
+
scope = _parts[0],
|
|
51
|
+
attr = _parts[1];
|
|
52
|
+
if (scope === 'plant' || scope.startsWith('group:')) return; // members self-report
|
|
53
|
+
|
|
54
|
+
if (attr === 'power') {
|
|
55
|
+
this._gateEquipment(scope, change.effective);
|
|
56
|
+
} else if (attr === 'flow') {
|
|
57
|
+
this._gatePipe(scope, change.effective);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Re-gate the whole scene from current effective state. Used after scene load,
|
|
63
|
+
* where StateEngine.load() populates the registry without emitting per-address
|
|
64
|
+
* events (and the meshes have just been (re)built).
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
}, {
|
|
68
|
+
key: "_regateAll",
|
|
69
|
+
value: function _regateAll() {
|
|
70
|
+
var _this$sceneViewer;
|
|
71
|
+
var engine = (_this$sceneViewer = this.sceneViewer) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.centralPlant) === null || _this$sceneViewer === void 0 ? void 0 : _this$sceneViewer.stateEngine;
|
|
72
|
+
if (!engine) return;
|
|
73
|
+
var registry = engine.toRegistry();
|
|
74
|
+
for (var _i = 0, _Object$keys = Object.keys(registry); _i < _Object$keys.length; _i++) {
|
|
75
|
+
var address = _Object$keys[_i];
|
|
76
|
+
var parts = address.split('::');
|
|
77
|
+
if (parts.length !== 2) continue;
|
|
78
|
+
var _parts2 = _slicedToArray(parts, 2),
|
|
79
|
+
scope = _parts2[0],
|
|
80
|
+
attr = _parts2[1];
|
|
81
|
+
if (scope === 'plant' || scope.startsWith('group:')) continue;
|
|
82
|
+
if (attr === 'power') {
|
|
83
|
+
this._gateEquipment(scope, engine.getEffective(address));
|
|
84
|
+
} else if (attr === 'flow') {
|
|
85
|
+
this._gatePipe(scope, engine.getEffective(address));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// โโ Equipment gating โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Darken (off) or restore (on) every mesh of an equipment object.
|
|
94
|
+
* @param {string} objectId - Hardcoded object id (address scope)
|
|
95
|
+
* @param {boolean} on - Effective power
|
|
96
|
+
* @private
|
|
97
|
+
*/
|
|
98
|
+
}, {
|
|
99
|
+
key: "_gateEquipment",
|
|
100
|
+
value: function _gateEquipment(objectId, on) {
|
|
101
|
+
var _this$sceneViewer2,
|
|
102
|
+
_this2 = this;
|
|
103
|
+
var scene = (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.scene;
|
|
104
|
+
if (!scene) return;
|
|
105
|
+
var obj = findObjectByHardcodedUuid(scene, objectId);
|
|
106
|
+
if (!obj || typeof obj.traverse !== 'function') return;
|
|
107
|
+
obj.traverse(function (mesh) {
|
|
108
|
+
if (!mesh.isMesh && !mesh.material) return;
|
|
109
|
+
// Leave attached I/O control panels (switches) lit and operable even when
|
|
110
|
+
// their host is powered off โ you must be able to see and click the switch
|
|
111
|
+
// that turns it back on. (traverse can't prune, so guard per mesh.)
|
|
112
|
+
if (_this2._isUnderIoDevice(mesh, obj)) return;
|
|
113
|
+
var materials = _this2._prepareMeshMaterials(mesh);
|
|
114
|
+
var _iterator = _createForOfIteratorHelper(materials),
|
|
115
|
+
_step;
|
|
116
|
+
try {
|
|
117
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
118
|
+
var material = _step.value;
|
|
119
|
+
_this2._applyGate(material, on);
|
|
120
|
+
}
|
|
121
|
+
} catch (err) {
|
|
122
|
+
_iterator.e(err);
|
|
123
|
+
} finally {
|
|
124
|
+
_iterator.f();
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* True if `mesh` is an io-device or nested under one, walking up to (but not
|
|
131
|
+
* past) the equipment root `stopAt`.
|
|
132
|
+
* @param {THREE.Object3D} mesh
|
|
133
|
+
* @param {THREE.Object3D} stopAt - equipment root to stop the upward walk at
|
|
134
|
+
* @returns {boolean}
|
|
135
|
+
* @private
|
|
136
|
+
*/
|
|
137
|
+
}, {
|
|
138
|
+
key: "_isUnderIoDevice",
|
|
139
|
+
value: function _isUnderIoDevice(mesh, stopAt) {
|
|
140
|
+
var node = mesh;
|
|
141
|
+
while (node) {
|
|
142
|
+
var _node$userData;
|
|
143
|
+
if (((_node$userData = node.userData) === null || _node$userData === void 0 ? void 0 : _node$userData.objectType) === 'io-device') return true;
|
|
144
|
+
if (node === stopAt) break;
|
|
145
|
+
node = node.parent;
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Ensure a mesh's material(s) are cloned-on-write and have their baseline
|
|
152
|
+
* cached, then return the material list to gate.
|
|
153
|
+
* @param {THREE.Mesh} mesh
|
|
154
|
+
* @returns {THREE.Material[]}
|
|
155
|
+
* @private
|
|
156
|
+
*/
|
|
157
|
+
}, {
|
|
158
|
+
key: "_prepareMeshMaterials",
|
|
159
|
+
value: function _prepareMeshMaterials(mesh) {
|
|
160
|
+
if (!mesh.material) return [];
|
|
161
|
+
|
|
162
|
+
// Clone-on-write once per mesh so shared library materials aren't shared.
|
|
163
|
+
if (!mesh.userData._effectiveGateCloned) {
|
|
164
|
+
if (Array.isArray(mesh.material)) {
|
|
165
|
+
mesh.material = mesh.material.map(function (m) {
|
|
166
|
+
return m !== null && m !== void 0 && m.clone ? m.clone() : m;
|
|
167
|
+
});
|
|
168
|
+
} else if (mesh.material.clone) {
|
|
169
|
+
mesh.material = mesh.material.clone();
|
|
170
|
+
}
|
|
171
|
+
mesh.userData._effectiveGateCloned = true;
|
|
172
|
+
}
|
|
173
|
+
var materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
174
|
+
var _iterator2 = _createForOfIteratorHelper(materials),
|
|
175
|
+
_step2;
|
|
176
|
+
try {
|
|
177
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
178
|
+
var _material$userData, _material$color$clone, _material$color, _material$color$clone2, _material$emissive$cl, _material$emissive, _material$emissive$cl2;
|
|
179
|
+
var material = _step2.value;
|
|
180
|
+
if (!material || (_material$userData = material.userData) !== null && _material$userData !== void 0 && _material$userData._effectiveGate) continue;
|
|
181
|
+
material.userData = material.userData || {};
|
|
182
|
+
material.userData._effectiveGate = {
|
|
183
|
+
color: (_material$color$clone = (_material$color = material.color) === null || _material$color === void 0 || (_material$color$clone2 = _material$color.clone) === null || _material$color$clone2 === void 0 ? void 0 : _material$color$clone2.call(_material$color)) !== null && _material$color$clone !== void 0 ? _material$color$clone : null,
|
|
184
|
+
emissive: (_material$emissive$cl = (_material$emissive = material.emissive) === null || _material$emissive === void 0 || (_material$emissive$cl2 = _material$emissive.clone) === null || _material$emissive$cl2 === void 0 ? void 0 : _material$emissive$cl2.call(_material$emissive)) !== null && _material$emissive$cl !== void 0 ? _material$emissive$cl : null,
|
|
185
|
+
emissiveIntensity: typeof material.emissiveIntensity === 'number' ? material.emissiveIntensity : null
|
|
186
|
+
};
|
|
187
|
+
this._gatedMaterials.add(material);
|
|
188
|
+
}
|
|
189
|
+
} catch (err) {
|
|
190
|
+
_iterator2.e(err);
|
|
191
|
+
} finally {
|
|
192
|
+
_iterator2.f();
|
|
193
|
+
}
|
|
194
|
+
return materials.filter(Boolean);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Darken or restore a single material from its cached baseline.
|
|
199
|
+
* @param {THREE.Material} material
|
|
200
|
+
* @param {boolean} on
|
|
201
|
+
* @private
|
|
202
|
+
*/
|
|
203
|
+
}, {
|
|
204
|
+
key: "_applyGate",
|
|
205
|
+
value: function _applyGate(material, on) {
|
|
206
|
+
var _material$userData2;
|
|
207
|
+
var base = (_material$userData2 = material.userData) === null || _material$userData2 === void 0 ? void 0 : _material$userData2._effectiveGate;
|
|
208
|
+
if (!base) return;
|
|
209
|
+
if (on) {
|
|
210
|
+
if (base.color && material.color) material.color.copy(base.color);
|
|
211
|
+
if (base.emissive && material.emissive) material.emissive.copy(base.emissive);
|
|
212
|
+
if (base.emissiveIntensity !== null) material.emissiveIntensity = base.emissiveIntensity;
|
|
213
|
+
} else {
|
|
214
|
+
if (base.color && material.color) material.color.copy(base.color).multiplyScalar(OFF_COLOR_SCALE);
|
|
215
|
+
if (material.emissive) material.emissive.setScalar(0);
|
|
216
|
+
if (typeof material.emissiveIntensity === 'number') material.emissiveIntensity = 0;
|
|
217
|
+
}
|
|
218
|
+
material.needsUpdate = true;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// โโ Pipe flow gating โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Delegate pipe-flow gating to PathFlowManager (grays the shared per-path
|
|
225
|
+
* material when off, restores the temperature colour when on).
|
|
226
|
+
* @param {string} pathId - `${from}-->${to}`
|
|
227
|
+
* @param {boolean} on - Effective flow
|
|
228
|
+
* @private
|
|
229
|
+
*/
|
|
230
|
+
}, {
|
|
231
|
+
key: "_gatePipe",
|
|
232
|
+
value: function _gatePipe(pathId, on) {
|
|
233
|
+
var _this$sceneViewer3, _pathFlowManager$setF;
|
|
234
|
+
var pathFlowManager = (_this$sceneViewer3 = this.sceneViewer) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.managers) === null || _this$sceneViewer3 === void 0 ? void 0 : _this$sceneViewer3.pathFlowManager;
|
|
235
|
+
pathFlowManager === null || pathFlowManager === void 0 || (_pathFlowManager$setF = pathFlowManager.setFlowEnabled) === null || _pathFlowManager$setF === void 0 || _pathFlowManager$setF.call(pathFlowManager, pathId, on);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// โโ Lifecycle โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
239
|
+
}, {
|
|
240
|
+
key: "_doDispose",
|
|
241
|
+
value: function _doDispose() {
|
|
242
|
+
var _this$sceneViewer4;
|
|
243
|
+
if ((_this$sceneViewer4 = this.sceneViewer) !== null && _this$sceneViewer4 !== void 0 && _this$sceneViewer4.off) {
|
|
244
|
+
this.sceneViewer.off('engine-state-changed', this._onChange);
|
|
245
|
+
this.sceneViewer.off('scene-loaded', this._regateAll);
|
|
246
|
+
}
|
|
247
|
+
// Restore any still-gated materials to their cached baseline.
|
|
248
|
+
var _iterator3 = _createForOfIteratorHelper(this._gatedMaterials),
|
|
249
|
+
_step3;
|
|
250
|
+
try {
|
|
251
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
252
|
+
var material = _step3.value;
|
|
253
|
+
this._applyGate(material, true);
|
|
254
|
+
}
|
|
255
|
+
} catch (err) {
|
|
256
|
+
_iterator3.e(err);
|
|
257
|
+
} finally {
|
|
258
|
+
_iterator3.f();
|
|
259
|
+
}
|
|
260
|
+
this._gatedMaterials.clear();
|
|
261
|
+
this.sceneViewer = null;
|
|
262
|
+
}
|
|
263
|
+
}]);
|
|
264
|
+
}(BaseDisposable);
|
|
265
|
+
|
|
266
|
+
export { EffectiveVisualManager };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,91 @@
|
|
|
5
5
|
* organized by their functional categories.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
// โโโ State Engine โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
9
|
+
|
|
10
|
+
export function makeAddress(scope: string, attribute: string): string
|
|
11
|
+
export function valuesEqual(a: unknown, b: unknown): boolean
|
|
12
|
+
export function offValue(desired: unknown): unknown
|
|
13
|
+
|
|
14
|
+
export interface StateChange {
|
|
15
|
+
address: string
|
|
16
|
+
desired: unknown
|
|
17
|
+
effective: unknown
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** One endpoint of a declared chain (scope + attribute). */
|
|
21
|
+
export interface ChainEndpoint {
|
|
22
|
+
/** Object/scope id, e.g. "pump-001" or "pump-001::start-switch". */
|
|
23
|
+
address: string
|
|
24
|
+
/** Attribute name, e.g. "power", "mode", "flow". */
|
|
25
|
+
attribute: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The chain trigger; `source` selects which layer of the trigger to read. */
|
|
29
|
+
export interface ChainWhen extends ChainEndpoint {
|
|
30
|
+
/** Read the trigger's desired (default) or effective value. */
|
|
31
|
+
source?: 'desired' | 'effective'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** A declared chain: when the trigger changes, copy its value to the target. */
|
|
35
|
+
export interface Chain {
|
|
36
|
+
/** Unique id within the scene. */
|
|
37
|
+
id?: string
|
|
38
|
+
/** Only 'copy' is supported today. */
|
|
39
|
+
action?: 'copy'
|
|
40
|
+
when: ChainWhen
|
|
41
|
+
set: ChainEndpoint
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface StateEngineOptions {
|
|
45
|
+
/** Ripple hop limit per initiating change (Framework ยง11.2). Default 8. */
|
|
46
|
+
maxChainDepth?: number
|
|
47
|
+
/** Operational attributes gated to a safe-off value when power is off (ยง6/ยง10). */
|
|
48
|
+
gatedOperationalAttributes?: string[]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export declare class StateEngine {
|
|
52
|
+
constructor(options?: StateEngineOptions)
|
|
53
|
+
maxChainDepth: number
|
|
54
|
+
load(declaration?: Record<string, unknown>): void
|
|
55
|
+
reset(): void
|
|
56
|
+
getDesired(address: string): unknown
|
|
57
|
+
getEffective(address: string): unknown
|
|
58
|
+
getGroupsForObject(objectId: string): string[]
|
|
59
|
+
setDesired(address: string, value: unknown): boolean
|
|
60
|
+
/** Register a pipe/path so its `<pipeId>::flow` state exists (tied to lifecycle). */
|
|
61
|
+
registerPipe(pipeId: string, options?: { defaultFlow?: boolean }): string
|
|
62
|
+
/** Remove a pipe and all of its registry keys; returns the number removed. */
|
|
63
|
+
unregisterPipe(pipeId: string): number
|
|
64
|
+
subscribe(listener: (change: StateChange) => void): () => void
|
|
65
|
+
toRegistry(): Record<string, unknown>
|
|
66
|
+
/** Reconstruct the ยง17 scene declaration (round-trips with load). */
|
|
67
|
+
toDeclaration(): {
|
|
68
|
+
version: string
|
|
69
|
+
plant: Record<string, unknown>
|
|
70
|
+
groups: Record<string, unknown>
|
|
71
|
+
chains: Chain[]
|
|
72
|
+
stateRegistry: Record<string, unknown>
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// โโโ State Engine โ scene glue (stateEngineScene.js) โโโโโโโโโโโโโโโโโโโโโโโโ
|
|
77
|
+
|
|
78
|
+
export function ioAddress(attachmentId: string, stateId: string, parentUuid?: string): string
|
|
79
|
+
export function parseIoAddress(
|
|
80
|
+
address: string
|
|
81
|
+
): { parentUuid: string; attachmentId: string; stateId: string; scopedKey: string } | null
|
|
82
|
+
export function extractDeclaration(sceneData?: Record<string, unknown>): {
|
|
83
|
+
plant: Record<string, unknown>
|
|
84
|
+
groups: Record<string, unknown>
|
|
85
|
+
chains: Chain[]
|
|
86
|
+
stateRegistry: Record<string, unknown>
|
|
87
|
+
}
|
|
88
|
+
export function applyDeclarationToExport<T extends Record<string, unknown>>(
|
|
89
|
+
exportData: T,
|
|
90
|
+
engine: { toDeclaration: () => Record<string, unknown> }
|
|
91
|
+
): T
|
|
92
|
+
|
|
8
93
|
// โโโ Connector flow types โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
9
94
|
|
|
10
95
|
/** The flow direction of a connector port. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@2112-lab/central-plant",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.59",
|
|
4
4
|
"description": "Utility modules for the Central Plant Application",
|
|
5
5
|
"main": "dist/bundle/index.js",
|
|
6
6
|
"module": "dist/esm/src/index.js",
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
"build": "rollup -c && npm run build:types",
|
|
19
19
|
"build:types": "node -e \"require('fs').copyFileSync('src/index.d.ts', 'dist/index.d.ts')\"",
|
|
20
20
|
"dev": "rollup -c -w",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
21
23
|
"prepublishOnly": "npm run build",
|
|
22
24
|
"docs": "jsdoc -c jsdoc.json",
|
|
23
25
|
"release": "npm install @2112-lab/pathfinder@latest && npm version patch && npm publish"
|
|
@@ -46,6 +48,7 @@
|
|
|
46
48
|
"regenerator-runtime": "^0.14.1",
|
|
47
49
|
"rollup": "^2.79.1",
|
|
48
50
|
"rollup-plugin-copy": "^3.5.0",
|
|
49
|
-
"rollup-plugin-terser": "^7.0.2"
|
|
51
|
+
"rollup-plugin-terser": "^7.0.2",
|
|
52
|
+
"vitest": "^2.1.9"
|
|
50
53
|
}
|
|
51
54
|
}
|