# Reference — Limitations ![code-ref](https://img.shields.io/badge/code--ref-48fa543-blue) > [!NOTE] > What `generalFunctions` does not do, current rough edges, stability/versioning rules, and open questions. For an intuitive overview, return to [Home](Home). --- ## When NOT to depend on this library - **Passive HTTP gateway nodes** (e.g. `dashboardAPI`) may skip `BaseDomain` and `BaseNodeAdapter` entirely if they hold no domain state. A plain Node-RED node with HTTP endpoints needs only `logger`, `outputUtils`, and `configManager`. See the `dashboardAPI` wiki for the rationale. - **External scripts or standalone tools** that need only unit conversion can import just `const { convert } = require('generalFunctions')` without pulling in the full domain stack. - **Nodes at a different S88 level** that inherit from a third-party base class must not import from `src/domain/` or `src/nodered/` internal paths — they may only use root-level exports. --- ## Known limitations ### 1. `loadCurve` is deprecated `loadCurve(modelId)` is kept as a thin shim over `assetResolver.resolve('curves', modelId)` so legacy consumers don't have to change in one go. New code should use `assetResolver` directly. Replacement `loadModel` exists but not every node has migrated. - **Tracked in**: `OPEN_QUESTIONS.md` — Phase 8.5 cleanup. ### 2. `outlierDetection` (`DynamicClusterDeviation`) prints to `console.log` The dynamic-cluster outlier detector emits diagnostic lines via `console.log` directly, bypassing the structured `logger`. This means its output cannot be silenced per-node and doesn't honour `logLevel`. Fix is routing through `logger` like the rest of the library. - **Tracked in**: Code review backlog. ### 3. `configUtils.initConfig` silently strips unknown keys When the user config carries a key that isn't in the schema, `configUtils.initConfig` (via `validationUtils.validateSchema`) silently drops it. This means a typo in an editor field name or a missed schema entry results in the default value being used — with no error, no warning, no log line. Workaround: the schema must include every key the domain reads, with a sensible default. The 2026-05-11 monster schema fix was a direct consequence of this gotcha. - **Tracked in**: `OPEN_QUESTIONS.md` — e.g. monster schema fix. ### 4. `state` (FSM) and `predict` are not yet integrated with `BaseDomain` lifecycle The state machine and the prediction class are exported but not lifecycle-managed by `BaseDomain`. Consumer nodes wire them manually in `configure()` — constructor, event subscriptions, teardown. A second wave of refactor work will move them under the `BaseDomain` umbrella so subclasses get them for free. - **Tracked in**: Architecture backlog. ### 5. `menuUtils` / `MenuManager` bypass the Node.js import path These are served as browser JavaScript via the admin `endpointUtils` and run in the Node-RED editor's iframe. Deep changes require testing in both environments (Node-side schema validation, browser-side editor form rendering). There is no automated test harness for the browser side. - **Tracked in**: `endpointUtils.js` comments. ### 6. `CascadePIDController` has no dedicated test suite `PIDController` is unit-tested; the cascade variant is not. Adding tests is on the backlog. - **Tracked in**: Test backlog. ### 7. Wiki autogen is hand-maintained The API surface section is hand-maintained between the `` markers in `CONTRACT.md`. There is no `npm run wiki:all` script (yet); when an export is added or changed, the table must be edited by hand. Mitigation: the source-of-truth is the barrel (`index.js`); when in doubt, trust the barrel. - **Tracked in**: Phase 9 follow-up. ### 8. Single-side pressure handling lives in consumers Consumer-node concerns like single-side pressure degradation, residue handling, and sequence-abort semantics are NOT centralised in this library — each consumer (`rotatingMachine`, `valveGroupControl`, …) implements its own variant. Cross-node consistency is by convention, not by enforcement. A future `BaseDomain` extension could pull common pressure-routing patterns up. - **Tracked in**: Internal architecture notes. ### 9. Asset registry backends are not fully symmetric `FileBackend` is the production default (sync, in-process JSON). `HttpBackend` is provided for remote-resolver scenarios but has fewer call sites and less test coverage. If you switch to `HttpBackend` in production, expect to find edge-case differences. - **Tracked in**: Internal — not yet ticketed. ### 10. No editor form `generalFunctions` is never placed in a flow. It has no Node-RED type registration, no `.html`, no admin endpoint of its own. Consumer nodes expose their own editor forms; each form field writes into a config key that `configManager.buildConfig` validates against the node's schema in `src/configs/.json`. This is a deliberate design choice, not a limitation — documented here for visitors searching for "where's the editor form". --- ## Stability + versioning Source of truth: [`.claude/rules/general-functions.md`](https://gitea.wbd-rd.nl/RnD/EVOLV/src/branch/development/.claude/rules/general-functions.md) in the superproject. | Category | Rule | |:---|:---| | **Safe to add** | New named exports. New optional methods on existing classes. New config keys with defaults in the schema. | | **Requires decision-gate interview** | Removing or renaming any export. Changing a method signature. Changing the output key format of `MeasurementContainer.getFlattenedOutput()`. Changing the `formatMsg` delta-compression behaviour. | | **Forbidden without migration** | Breaking the 4-segment key shape (`type.variant.position.childId`). Changing Port 0/1/2 payload envelope. Changing the [CONTRACTS.md](https://gitea.wbd-rd.nl/RnD/EVOLV/src/branch/development/.claude/refactor/CONTRACTS.md) §1–§9 shapes. | ### Cross-node impact `generalFunctions` is a git submodule shared by all 12 node repos. **Any change here can break any node.** Before modifying any module: ```bash # Identify all consumers of the symbol you're touching. grep -r "require('generalFunctions')" nodes/*/ # Or for a specific export: grep -rn "BaseDomain\|UnitPolicy\|MeasurementContainer" nodes/*/src/ ``` After changes, run the test suites of every affected consumer node, not just `generalFunctions/test/`. ### Canonical units `MeasurementContainer` and all internal processing assume canonical units: | Quantity | Canonical | |:---|:---| | Pressure | `Pa` | | Flow | `m3/s` | | Power | `W` | | Temperature | `K` | Unit conversion happens at system boundaries (input via `CommandRegistry.units` normalisation, output via `UnitPolicy.output` rendering) — never in core logic. Code that assumes anything else is a bug. --- ## Deprecations | Symbol | Status | Replacement | Plan | |:---|:---|:---|:---| | `loadCurve(modelId)` | deprecated | `assetResolver.resolve('curves', modelId)` | Remove after every consumer migrates. Tracked in Phase 8.5. | When a symbol is marked deprecated: 1. The row in `CONTRACT.md` flips to `deprecated` and gains a "removed-in" line. 2. Consumers in `nodes/*` are updated to the replacement. 3. Each touched node's submodule pin is bumped in the superproject. 4. After one release on `development` with no consumers, the export and its row are removed. --- ## Open questions (tracked) | Question | Where it lives | |:---|:---| | Phase 8.5: complete `loadCurve` → `assetResolver` migration | Internal | | Route `DynamicClusterDeviation` log lines through `logger` | Code review backlog | | Surface a warning when `configUtils.initConfig` strips a key not in schema | `OPEN_QUESTIONS.md` | | Move `state` (FSM) and `predict` under `BaseDomain` lifecycle | Architecture backlog | | Browser-side test harness for `menuUtils` | `endpointUtils.js` | | Test suite for `CascadePIDController` | Test backlog | | Wiki autogen script (`npm run wiki:all`) for the API surface section | Phase 9 follow-up | | `HttpBackend` test coverage parity with `FileBackend` | Internal | | Centralised single-side-pressure handling pattern in `BaseDomain` | Internal architecture notes | --- ## Migration notes ### Pre-refactor: per-node `registerChild` switch The `ChildRouter` replaces hand-written `registerChild(child)` methods. The mechanical migration: ```js // Before: registerChild(child) { switch (child.softwareType) { case 'measurement': if (child.config.asset.type === 'pressure' && child.positionVsParent === 'upstream') { this._onUpstream(child); } else if (child.config.asset.type === 'flow') { this._onFlow(child); } break; case 'machinegroup': this._onMgcChild(child); break; } } // After (in configure()): this.router .onMeasurement('measurement', { type: 'pressure', position: 'upstream' }, (data, child) => this._onUpstream(child)) .onMeasurement('measurement', { type: 'flow' }, (data, child) => this._onFlow(child)) .onRegister('machinegroup', (child) => this._onMgcChild(child)); ``` Behaviour is identical (the underlying `childRegistrationUtils` calls are unchanged); the wiring is just declarative. ### Pre-refactor: per-node `getStatusBadge` duplication The `statusBadge` pure-function helpers replaced 12 copies of slightly different status-text formatters. New domains should use `statusBadge.compose(parts, opts)`, `statusBadge.error(msg)`, `statusBadge.idle(label)` instead of building `{fill, shape, text}` by hand. Text is clipped to 60 chars to fit the Node-RED editor. ### Pre-AssetResolver: `loadCurve` shim Old code: ```js const { loadCurve } = require('generalFunctions'); const curve = loadCurve('SomeModel'); ``` New code (preferred): ```js const { assetResolver } = require('generalFunctions'); const curve = assetResolver.resolve('curves', 'SomeModel'); ``` The shim still works, but the next API-surface review may remove it. Migrate when next touching the file. --- ## Related pages | Page | Why | |:---|:---| | [Home](Home) | Intuitive overview | | [Reference — Contracts](Reference-Contracts) | Full public API surface, per-export stability tags | | [Reference — Architecture](Reference-Architecture) | Three-tier rule, `src/` layout, consumer responsibilities | | [Reference — Examples](Reference-Examples) | Usage patterns: extending base classes, registering commands, declaring child routes | | [Platform CONTRACTS.md](https://gitea.wbd-rd.nl/RnD/EVOLV/src/branch/development/.claude/refactor/CONTRACTS.md) | The authoritative platform base-class + protocol spec | | [`.claude/rules/general-functions.md`](https://gitea.wbd-rd.nl/RnD/EVOLV/src/branch/development/.claude/rules/general-functions.md) | Stability + change-impact rules |