Files
generalFunctions/wiki/Reference-Limitations.md
znetsixe 8b28f8969e docs(wiki): full 5-page wiki matching the rotatingMachine reference format
Replaces the prior stub/partial wiki with a Home + Reference-{Architecture,
Contracts,Examples,Limitations} + _Sidebar structure. Topic-contract and
data-model sections wrapped in AUTOGEN markers for the future wiki-gen tool.
Source-vs-spec contradictions surfaced and flagged inline (not silently
fixed). Pending-review notes mark sections that need a full node review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 09:42:15 +02:00

11 KiB
Raw Blame History

Reference — Limitations

code-ref

Note

What generalFunctions does not do, current rough edges, stability/versioning rules, and open questions. For an intuitive overview, return to 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 <!-- BEGIN/END AUTOGEN: api-surface --> 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/<nodeName>.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 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 §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:

# 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 loadCurveassetResolver 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:

// 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:

const { loadCurve } = require('generalFunctions');
const curve = loadCurve('SomeModel');

New code (preferred):

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.


Page Why
Home Intuitive overview
Reference — Contracts Full public API surface, per-export stability tags
Reference — Architecture Three-tier rule, src/ layout, consumer responsibilities
Reference — Examples Usage patterns: extending base classes, registering commands, declaring child routes
Platform CONTRACTS.md The authoritative platform base-class + protocol spec
.claude/rules/general-functions.md Stability + change-impact rules