@winkjs/composer 0.0.2 → 0.4.0
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/LICENSE +1 -1
- package/README.md +42 -103
- package/package.json +53 -29
- package/src/composer.js +75 -0
- package/src/core/batch/aoo-encoder.js +148 -0
- package/src/core/batch/index.js +12 -0
- package/src/core/batch/sliding-window.js +91 -0
- package/src/core/codec/index.js +137 -0
- package/src/core/emitter-manager/mqtt/constants.js +102 -0
- package/src/core/emitter-manager/mqtt/emitter.js +780 -0
- package/src/core/emitter-manager/mqtt/index.js +190 -0
- package/src/core/emitter-manager/mqtt/mqtt-store.js +538 -0
- package/src/core/emitter-manager/terminal/assert-columns.js +98 -0
- package/src/core/emitter-manager/terminal/formatters.js +160 -0
- package/src/core/emitter-manager/terminal/index.js +341 -0
- package/src/core/env-vars.js +245 -0
- package/src/core/mqtt-protocol.js +47 -0
- package/src/core/partition-manager/index.js +7 -0
- package/src/core/partition-manager/init.js +44 -0
- package/src/core/partition-manager/introspect.js +15 -0
- package/src/core/partition-manager/publish-to.js +6 -0
- package/src/core/partition-manager/recompute.js +5 -0
- package/src/core/partition-manager/reset.js +5 -0
- package/src/core/partition-manager/update.js +264 -0
- package/src/core/partition-manager/validate-flow.js +157 -0
- package/src/core/semantics/digest.js +128 -0
- package/src/core/semantics/index.js +83 -0
- package/src/core/semantics/loader.js +571 -0
- package/src/core/semantics/schemas/asset-class-schema.js +218 -0
- package/src/core/semantics/schemas/column-schema.js +651 -0
- package/src/core/semantics/schemas/enum-schema.js +153 -0
- package/src/core/semantics/schemas/index.js +51 -0
- package/src/core/semantics/warnings.js +141 -0
- package/src/core/shutdown-manager/index.js +289 -0
- package/src/core/source-manager/csv/index.js +171 -0
- package/src/core/source-manager/csv/start.js +456 -0
- package/src/core/source-manager/mqtt/client.js +406 -0
- package/src/core/source-manager/mqtt/constants.js +147 -0
- package/src/core/source-manager/mqtt/dedup.js +244 -0
- package/src/core/source-manager/mqtt/index.js +260 -0
- package/src/core/source-manager/mqtt/status.js +546 -0
- package/src/core/source-manager/test-harness/comparator.js +226 -0
- package/src/core/source-manager/test-harness/field-generator.js +85 -0
- package/src/core/source-manager/test-harness/fuzz.js +87 -0
- package/src/core/source-manager/test-harness/index.js +115 -0
- package/src/core/source-manager/test-harness/prng.js +57 -0
- package/src/core/source-manager/test-harness/start.js +232 -0
- package/src/core/source-manager/test-harness/validate.js +213 -0
- package/src/core/storage-manager/questdb/assert-columns.js +120 -0
- package/src/core/storage-manager/questdb/ensure-tables.js +187 -0
- package/src/core/storage-manager/questdb/index.js +1251 -0
- package/src/core/storage-manager/questdb/persist-plan.js +488 -0
- package/src/core/storage-manager/questdb/writers.js +142 -0
- package/src/core/test-utils/sealed-record.js +80 -0
- package/src/core/test-utils/soak-signature.js +149 -0
- package/src/core/test-utils/tcp-proxy.js +106 -0
- package/src/core/tunable/helpers.js +254 -0
- package/src/core/tunable/index.js +87 -0
- package/src/core/utils/console-formatter/index.js +207 -0
- package/src/core/utils/create-smart-store-as/index.js +98 -0
- package/src/core/utils/create-smart-store-as/sanitize-field.js +46 -0
- package/src/core/utils/create-smart-store-as/smart-truncate.js +93 -0
- package/src/core/utils/flow/index.js +5 -0
- package/src/core/utils/flow/make-collision-checker.js +23 -0
- package/src/core/utils/flow/to-kebab.js +20 -0
- package/src/core/utils/half-life/index.js +111 -0
- package/src/core/utils/node/disable.js +11 -0
- package/src/core/utils/node/enable.js +11 -0
- package/src/core/utils/node/execute-triggers.js +40 -0
- package/src/core/utils/node/index.js +10 -0
- package/src/core/utils/node/pause.js +11 -0
- package/src/core/utils/node/populate-predicate-inputs.js +14 -0
- package/src/core/utils/node/publish-nan.js +19 -0
- package/src/core/utils/node/reset-predicate-inputs.js +11 -0
- package/src/core/utils/node/unpause.js +11 -0
- package/src/core/utils/node/validate-spec.js +22 -0
- package/src/core/utils/options/resolve-field-keyed.js +115 -0
- package/src/core/utils/quantize/index.js +75 -0
- package/src/core/utils/stats/formulas.js +67 -0
- package/src/core/utils/stats/index.js +3 -0
- package/src/core/utils/validate/composer-validators.js +141 -0
- package/src/core/utils/validate/helpers.js +206 -0
- package/src/core/utils/validate/index.js +12 -0
- package/src/core/utils/validate/type-validators.js +538 -0
- package/src/core/utils/validate/validate.js +107 -0
- package/src/core/utils/validate/validators.js +177 -0
- package/src/core/wiring/assert-handle.js +57 -0
- package/src/core/wiring/assert-module.js +63 -0
- package/src/core/wiring/index.js +5 -0
- package/src/core/wiring/node-type-to-module.js +17 -0
- package/src/core/wiring/wire-emitters.js +256 -0
- package/src/core/wiring/wire-linear-graph.js +25 -0
- package/src/core/wiring/wire-node.js +157 -0
- package/src/core/wiring/wire-semantics.js +173 -0
- package/src/core/wiring/wire-storages.js +344 -0
- package/src/flow/check-output-collisions.js +93 -0
- package/src/flow/consts.js +9 -0
- package/src/flow/deep-clone-spec.js +64 -0
- package/src/flow/driver.js +171 -0
- package/src/flow/expand-single-input-array.js +76 -0
- package/src/flow/expand-template-spec.js +93 -0
- package/src/flow/flow-api-schemas.js +300 -0
- package/src/flow/flow.js +658 -0
- package/src/flow/for-each.js +225 -0
- package/src/flow/get-signature-pattern.js +31 -0
- package/src/flow/get-target-array.js +46 -0
- package/src/flow/inspect.js +67 -0
- package/src/flow/load-node-module.js +81 -0
- package/src/flow/make-node-method.js +112 -0
- package/src/flow/resolve-pick-by-field.js +77 -0
- package/src/flow/resolve-tunables.js +76 -0
- package/src/flow/run.js +392 -0
- package/src/flow/serialize.js +161 -0
- package/src/flow/signatures-schema.js +222 -0
- package/src/flow/spec-builder.js +65 -0
- package/src/flow/validate-triggers.js +250 -0
- package/src/flow/validate.js +261 -0
- package/src/nodes/accumulate/index.js +21 -0
- package/src/nodes/accumulate/init.js +48 -0
- package/src/nodes/accumulate/introspect.js +123 -0
- package/src/nodes/accumulate/publish-to.js +34 -0
- package/src/nodes/accumulate/recompute.js +27 -0
- package/src/nodes/accumulate/reset.js +25 -0
- package/src/nodes/accumulate/update.js +42 -0
- package/src/nodes/appraise/calibrate.js +64 -0
- package/src/nodes/appraise/decision.js +66 -0
- package/src/nodes/appraise/deviation.js +140 -0
- package/src/nodes/appraise/index.js +23 -0
- package/src/nodes/appraise/init.js +165 -0
- package/src/nodes/appraise/integrate.js +45 -0
- package/src/nodes/appraise/introspect.js +352 -0
- package/src/nodes/appraise/publish-to.js +93 -0
- package/src/nodes/appraise/receptor.js +69 -0
- package/src/nodes/appraise/recompute.js +79 -0
- package/src/nodes/appraise/reset.js +53 -0
- package/src/nodes/appraise/update.js +130 -0
- package/src/nodes/archive/csv/index.js +6 -0
- package/src/nodes/archive/csv/init.js +36 -0
- package/src/nodes/archive/csv/load.js +70 -0
- package/src/nodes/archive/csv/reset.js +14 -0
- package/src/nodes/archive/csv/simple-parser.js +216 -0
- package/src/nodes/archive/csv/test.js +173 -0
- package/src/nodes/archive/csv/update.js +63 -0
- package/src/nodes/butterworth-filter/index.js +18 -0
- package/src/nodes/butterworth-filter/init.js +184 -0
- package/src/nodes/butterworth-filter/introspect.js +228 -0
- package/src/nodes/butterworth-filter/publish-to.js +21 -0
- package/src/nodes/butterworth-filter/recompute.js +13 -0
- package/src/nodes/butterworth-filter/reset.js +30 -0
- package/src/nodes/butterworth-filter/update.js +38 -0
- package/src/nodes/categorize/index.js +19 -0
- package/src/nodes/categorize/init.js +58 -0
- package/src/nodes/categorize/introspect.js +177 -0
- package/src/nodes/categorize/publish-to.js +29 -0
- package/src/nodes/categorize/recompute.js +14 -0
- package/src/nodes/categorize/reset.js +16 -0
- package/src/nodes/categorize/update.js +53 -0
- package/src/nodes/controller/index.js +9 -0
- package/src/nodes/controller/init.js +55 -0
- package/src/nodes/controller/introspect.js +91 -0
- package/src/nodes/controller/publish-to.js +8 -0
- package/src/nodes/controller/recompute.js +9 -0
- package/src/nodes/controller/reset.js +17 -0
- package/src/nodes/controller/update.js +63 -0
- package/src/nodes/diff/index.js +19 -0
- package/src/nodes/diff/init.js +37 -0
- package/src/nodes/diff/introspect.js +132 -0
- package/src/nodes/diff/publish-to.js +21 -0
- package/src/nodes/diff/recompute.js +12 -0
- package/src/nodes/diff/reset.js +12 -0
- package/src/nodes/diff/update.js +37 -0
- package/src/nodes/digest-moments/formulas.js +12 -0
- package/src/nodes/digest-moments/index.js +14 -0
- package/src/nodes/digest-moments/init.js +67 -0
- package/src/nodes/digest-moments/introspect.js +154 -0
- package/src/nodes/digest-moments/publish-to.js +34 -0
- package/src/nodes/digest-moments/recompute.js +14 -0
- package/src/nodes/digest-moments/reset.js +14 -0
- package/src/nodes/digest-moments/update.js +120 -0
- package/src/nodes/dwell-time-tracker/index.js +14 -0
- package/src/nodes/dwell-time-tracker/init.js +59 -0
- package/src/nodes/dwell-time-tracker/introspect.js +137 -0
- package/src/nodes/dwell-time-tracker/publish-to.js +22 -0
- package/src/nodes/dwell-time-tracker/recompute.js +8 -0
- package/src/nodes/dwell-time-tracker/reset.js +23 -0
- package/src/nodes/dwell-time-tracker/update.js +103 -0
- package/src/nodes/emit-if/helpers.js +94 -0
- package/src/nodes/emit-if/index.js +16 -0
- package/src/nodes/emit-if/init.js +67 -0
- package/src/nodes/emit-if/introspect.js +102 -0
- package/src/nodes/emit-if/publish-to.js +13 -0
- package/src/nodes/emit-if/recompute.js +12 -0
- package/src/nodes/emit-if/reset.js +27 -0
- package/src/nodes/emit-if/update.js +93 -0
- package/src/nodes/es-correlation/index.js +19 -0
- package/src/nodes/es-correlation/init.js +73 -0
- package/src/nodes/es-correlation/introspect.js +176 -0
- package/src/nodes/es-correlation/publish-to.js +32 -0
- package/src/nodes/es-correlation/recompute.js +56 -0
- package/src/nodes/es-correlation/reset.js +27 -0
- package/src/nodes/es-correlation/update.js +110 -0
- package/src/nodes/es-mean/index.js +20 -0
- package/src/nodes/es-mean/init.js +58 -0
- package/src/nodes/es-mean/introspect.js +129 -0
- package/src/nodes/es-mean/publish-to.js +19 -0
- package/src/nodes/es-mean/recompute.js +16 -0
- package/src/nodes/es-mean/reset.js +24 -0
- package/src/nodes/es-mean/update.js +69 -0
- package/src/nodes/es-pairwise-correlation/index.js +19 -0
- package/src/nodes/es-pairwise-correlation/init.js +98 -0
- package/src/nodes/es-pairwise-correlation/introspect.js +187 -0
- package/src/nodes/es-pairwise-correlation/publish-to.js +31 -0
- package/src/nodes/es-pairwise-correlation/recompute.js +69 -0
- package/src/nodes/es-pairwise-correlation/reset.js +29 -0
- package/src/nodes/es-pairwise-correlation/update.js +89 -0
- package/src/nodes/es-stats/index.js +21 -0
- package/src/nodes/es-stats/init.js +105 -0
- package/src/nodes/es-stats/introspect.js +157 -0
- package/src/nodes/es-stats/publish-to.js +42 -0
- package/src/nodes/es-stats/recompute.js +74 -0
- package/src/nodes/es-stats/reset.js +49 -0
- package/src/nodes/es-stats/update-envelope.js +44 -0
- package/src/nodes/es-stats/update-welford.js +64 -0
- package/src/nodes/es-stats/update.js +59 -0
- package/src/nodes/index.js +83 -0
- package/src/nodes/invert-flag/index.js +20 -0
- package/src/nodes/invert-flag/init.js +36 -0
- package/src/nodes/invert-flag/introspect.js +115 -0
- package/src/nodes/invert-flag/publish-to.js +23 -0
- package/src/nodes/invert-flag/recompute.js +12 -0
- package/src/nodes/invert-flag/reset.js +12 -0
- package/src/nodes/invert-flag/update.js +32 -0
- package/src/nodes/kalman1d/index.js +20 -0
- package/src/nodes/kalman1d/init.js +103 -0
- package/src/nodes/kalman1d/introspect.js +250 -0
- package/src/nodes/kalman1d/publish-to.js +34 -0
- package/src/nodes/kalman1d/recompute.js +23 -0
- package/src/nodes/kalman1d/reset.js +29 -0
- package/src/nodes/kalman1d/update.js +144 -0
- package/src/nodes/kernel/index.js +18 -0
- package/src/nodes/kernel/init.js +66 -0
- package/src/nodes/kernel/introspect.js +163 -0
- package/src/nodes/kernel/presets.js +74 -0
- package/src/nodes/kernel/publish-to.js +25 -0
- package/src/nodes/kernel/recompute.js +14 -0
- package/src/nodes/kernel/reset.js +20 -0
- package/src/nodes/kernel/update.js +69 -0
- package/src/nodes/lag/index.js +21 -0
- package/src/nodes/lag/init.js +87 -0
- package/src/nodes/lag/introspect.js +202 -0
- package/src/nodes/lag/publish-to.js +64 -0
- package/src/nodes/lag/recompute.js +33 -0
- package/src/nodes/lag/reset.js +49 -0
- package/src/nodes/lag/update.js +133 -0
- package/src/nodes/median3/index.js +19 -0
- package/src/nodes/median3/init.js +40 -0
- package/src/nodes/median3/introspect.js +116 -0
- package/src/nodes/median3/publish-to.js +21 -0
- package/src/nodes/median3/recompute.js +12 -0
- package/src/nodes/median3/reset.js +15 -0
- package/src/nodes/median3/update.js +58 -0
- package/src/nodes/moments-digest/copy-from.js +12 -0
- package/src/nodes/moments-digest/flush.js +17 -0
- package/src/nodes/moments-digest/index.js +132 -0
- package/src/nodes/moments-digest/init.js +84 -0
- package/src/nodes/moments-digest/introspect.js +122 -0
- package/src/nodes/moments-digest/prelude.js +28 -0
- package/src/nodes/moments-digest/publish-to.js +31 -0
- package/src/nodes/moments-digest/recompute.js +9 -0
- package/src/nodes/moments-digest/reset.js +20 -0
- package/src/nodes/moments-digest/update.js +182 -0
- package/src/nodes/node-names.js +67 -0
- package/src/nodes/page-hinkley/index.js +20 -0
- package/src/nodes/page-hinkley/init.js +66 -0
- package/src/nodes/page-hinkley/introspect.js +193 -0
- package/src/nodes/page-hinkley/publish-to.js +28 -0
- package/src/nodes/page-hinkley/recompute.js +14 -0
- package/src/nodes/page-hinkley/reset.js +23 -0
- package/src/nodes/page-hinkley/update.js +105 -0
- package/src/nodes/pass-if/index.js +21 -0
- package/src/nodes/pass-if/init.js +37 -0
- package/src/nodes/pass-if/introspect.js +93 -0
- package/src/nodes/pass-if/publish-to.js +15 -0
- package/src/nodes/pass-if/recompute.js +15 -0
- package/src/nodes/pass-if/reset.js +18 -0
- package/src/nodes/pass-if/update.js +37 -0
- package/src/nodes/persist-if/helpers.js +111 -0
- package/src/nodes/persist-if/index.js +9 -0
- package/src/nodes/persist-if/init.js +98 -0
- package/src/nodes/persist-if/introspect.js +106 -0
- package/src/nodes/persist-if/publish-to.js +21 -0
- package/src/nodes/persist-if/recompute.js +20 -0
- package/src/nodes/persist-if/reset.js +35 -0
- package/src/nodes/persist-if/update.js +112 -0
- package/src/nodes/persistence-check/index.js +14 -0
- package/src/nodes/persistence-check/init.js +38 -0
- package/src/nodes/persistence-check/introspect.js +144 -0
- package/src/nodes/persistence-check/publish-to.js +11 -0
- package/src/nodes/persistence-check/recompute.js +7 -0
- package/src/nodes/persistence-check/reset.js +12 -0
- package/src/nodes/persistence-check/update.js +57 -0
- package/src/nodes/process-index/index.js +15 -0
- package/src/nodes/process-index/init.js +48 -0
- package/src/nodes/process-index/introspect.js +182 -0
- package/src/nodes/process-index/publish-to.js +29 -0
- package/src/nodes/process-index/recompute.js +8 -0
- package/src/nodes/process-index/reset.js +8 -0
- package/src/nodes/process-index/update.js +75 -0
- package/src/nodes/ratio/index.js +14 -0
- package/src/nodes/ratio/init.js +37 -0
- package/src/nodes/ratio/introspect.js +155 -0
- package/src/nodes/ratio/publish-to.js +15 -0
- package/src/nodes/ratio/recompute.js +7 -0
- package/src/nodes/ratio/reset.js +7 -0
- package/src/nodes/ratio/update.js +47 -0
- package/src/nodes/sanitize/index.js +82 -0
- package/src/nodes/sanitize/init.js +82 -0
- package/src/nodes/sanitize/introspect.js +194 -0
- package/src/nodes/sanitize/publish-to.js +15 -0
- package/src/nodes/sanitize/recompute.js +8 -0
- package/src/nodes/sanitize/reset.js +14 -0
- package/src/nodes/sanitize/update.js +102 -0
- package/src/nodes/spike-guard/index.js +14 -0
- package/src/nodes/spike-guard/init.js +47 -0
- package/src/nodes/spike-guard/introspect.js +130 -0
- package/src/nodes/spike-guard/publish-to.js +35 -0
- package/src/nodes/spike-guard/recompute.js +14 -0
- package/src/nodes/spike-guard/reset.js +19 -0
- package/src/nodes/spike-guard/update.js +89 -0
- package/src/nodes/sse-emitter/index.js +7 -0
- package/src/nodes/sse-emitter/init.js +105 -0
- package/src/nodes/sse-emitter/introspect.js +134 -0
- package/src/nodes/sse-emitter/publish-to.js +6 -0
- package/src/nodes/sse-emitter/recompute.js +16 -0
- package/src/nodes/sse-emitter/reset.js +19 -0
- package/src/nodes/sse-emitter/update.js +69 -0
- package/src/nodes/sse-emitter/utils/broadcast-heartbeat.js +36 -0
- package/src/nodes/sse-emitter/utils/build-message.js +31 -0
- package/src/nodes/sse-emitter/utils/connection-manager.js +45 -0
- package/src/nodes/sse-emitter/utils/endpoint-initializer.js +20 -0
- package/src/nodes/sse-emitter/utils/health-monitor.js +38 -0
- package/src/nodes/sse-emitter/utils/qos-handler.js +41 -0
- package/src/nodes/state-change-detector/helpers.js +35 -0
- package/src/nodes/state-change-detector/index.js +12 -0
- package/src/nodes/state-change-detector/init.js +56 -0
- package/src/nodes/state-change-detector/introspect.js +146 -0
- package/src/nodes/state-change-detector/publish-to.js +20 -0
- package/src/nodes/state-change-detector/recompute.js +6 -0
- package/src/nodes/state-change-detector/reset.js +20 -0
- package/src/nodes/state-change-detector/update.js +97 -0
- package/src/nodes/sw-stats/index.js +14 -0
- package/src/nodes/sw-stats/init.js +51 -0
- package/src/nodes/sw-stats/introspect.js +131 -0
- package/src/nodes/sw-stats/publish-to.js +45 -0
- package/src/nodes/sw-stats/recompute.js +33 -0
- package/src/nodes/sw-stats/reset.js +15 -0
- package/src/nodes/sw-stats/update.js +39 -0
- package/src/nodes/swing-watch/index.js +17 -0
- package/src/nodes/swing-watch/init.js +144 -0
- package/src/nodes/swing-watch/introspect.js +188 -0
- package/src/nodes/swing-watch/publish-to.js +53 -0
- package/src/nodes/swing-watch/recompute.js +22 -0
- package/src/nodes/swing-watch/reset.js +55 -0
- package/src/nodes/swing-watch/update.js +767 -0
- package/src/nodes/tally/index.js +15 -0
- package/src/nodes/tally/init.js +32 -0
- package/src/nodes/tally/introspect.js +116 -0
- package/src/nodes/tally/publish-to.js +28 -0
- package/src/nodes/tally/recompute.js +10 -0
- package/src/nodes/tally/reset.js +10 -0
- package/src/nodes/tally/update.js +44 -0
- package/src/nodes/threshold/index.js +14 -0
- package/src/nodes/threshold/init.js +121 -0
- package/src/nodes/threshold/introspect.js +192 -0
- package/src/nodes/threshold/publish-to.js +11 -0
- package/src/nodes/threshold/recompute.js +8 -0
- package/src/nodes/threshold/reset.js +14 -0
- package/src/nodes/threshold/update.js +54 -0
- package/src/nodes/transform/helpers.js +39 -0
- package/src/nodes/transform/index.js +15 -0
- package/src/nodes/transform/init.js +35 -0
- package/src/nodes/transform/introspect.js +118 -0
- package/src/nodes/transform/publish-to.js +23 -0
- package/src/nodes/transform/recompute.js +12 -0
- package/src/nodes/transform/reset.js +11 -0
- package/src/nodes/transform/update.js +32 -0
- package/src/nodes/trend/compute-confidence.js +112 -0
- package/src/nodes/trend/index.js +14 -0
- package/src/nodes/trend/init.js +81 -0
- package/src/nodes/trend/introspect.js +151 -0
- package/src/nodes/trend/publish-to.js +22 -0
- package/src/nodes/trend/recompute.js +15 -0
- package/src/nodes/trend/reset.js +26 -0
- package/src/nodes/trend/update.js +93 -0
- package/src/nodes/tw-stats/copy-from.js +16 -0
- package/src/nodes/tw-stats/flush.js +12 -0
- package/src/nodes/tw-stats/index.js +41 -0
- package/src/nodes/tw-stats/init.js +92 -0
- package/src/nodes/tw-stats/introspect.js +171 -0
- package/src/nodes/tw-stats/publish-to.js +108 -0
- package/src/nodes/tw-stats/recompute.js +9 -0
- package/src/nodes/tw-stats/reset.js +16 -0
- package/src/nodes/tw-stats/update.js +113 -0
- package/src/nodes/unbalance/index.js +15 -0
- package/src/nodes/unbalance/init.js +59 -0
- package/src/nodes/unbalance/introspect.js +167 -0
- package/src/nodes/unbalance/publish-to.js +52 -0
- package/src/nodes/unbalance/recompute.js +11 -0
- package/src/nodes/unbalance/reset.js +10 -0
- package/src/nodes/unbalance/update.js +83 -0
- package/src/nodes/vector-distance/index.js +14 -0
- package/src/nodes/vector-distance/init.js +54 -0
- package/src/nodes/vector-distance/introspect.js +149 -0
- package/src/nodes/vector-distance/publish-to.js +35 -0
- package/src/nodes/vector-distance/recompute.js +11 -0
- package/src/nodes/vector-distance/reset.js +20 -0
- package/src/nodes/vector-distance/update.js +139 -0
- package/src/nodes/winnow/index.js +12 -0
- package/src/nodes/winnow/init.js +82 -0
- package/src/nodes/winnow/introspect.js +253 -0
- package/src/nodes/winnow/publish-to.js +51 -0
- package/src/nodes/winnow/recompute.js +14 -0
- package/src/nodes/winnow/reset.js +34 -0
- package/src/nodes/winnow/update.js +203 -0
- package/src/tools/training/features.js +227 -0
- package/src/tools/training/index.js +21 -0
- package/src/tools/training/logistic.js +238 -0
- package/src/tools/training/metrics.js +126 -0
- package/src/tools/training/scale.js +239 -0
- package/src/tools/training/validate.js +103 -0
- package/src/windowing/count-sliding/create.js +16 -0
- package/src/windowing/count-sliding/get-reverse-chronological-index.js +19 -0
- package/src/windowing/count-sliding/index.js +6 -0
- package/src/windowing/count-sliding/is-not-full.js +5 -0
- package/src/windowing/count-sliding/push.js +15 -0
- package/src/windowing/count-sliding/reset.js +11 -0
- package/src/windowing/count-sliding/size.js +5 -0
- package/src/windowing/time-sliding/create.js +25 -0
- package/src/windowing/time-sliding/push.js +42 -0
- package/CODE_OF_CONDUCT.md +0 -46
- package/CONTRIBUTING.md +0 -132
- package/docs/.nojekyll +0 -0
- package/docs/CONTRIBUTING.md +0 -134
- package/docs/README.md +0 -132
- package/docs/_coverpage.md +0 -26
- package/docs/_media/bg.png +0 -0
- package/docs/_media/wink-logo.png +0 -0
- package/docs/_navbar.md +0 -14
- package/docs/_sidebar.md +0 -2
- package/docs/index.html +0 -44
- package/eslint.config.js +0 -283
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Console Formatter for WinkComposer
|
|
3
|
+
*
|
|
4
|
+
* Provides rich, colored console output with structured formatting
|
|
5
|
+
* for development, debugging, and edge device monitoring.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ANSI color codes for terminal output
|
|
9
|
+
const colors = {
|
|
10
|
+
reset: '\x1b[0m',
|
|
11
|
+
bright: '\x1b[1m',
|
|
12
|
+
dim: '\x1b[2m',
|
|
13
|
+
|
|
14
|
+
// Foreground colors
|
|
15
|
+
black: '\x1b[30m',
|
|
16
|
+
red: '\x1b[31m',
|
|
17
|
+
green: '\x1b[32m',
|
|
18
|
+
yellow: '\x1b[33m',
|
|
19
|
+
blue: '\x1b[34m',
|
|
20
|
+
magenta: '\x1b[35m',
|
|
21
|
+
cyan: '\x1b[36m',
|
|
22
|
+
white: '\x1b[37m',
|
|
23
|
+
gray: '\x1b[90m',
|
|
24
|
+
|
|
25
|
+
// Background colors
|
|
26
|
+
bgRed: '\x1b[41m',
|
|
27
|
+
bgYellow: '\x1b[43m',
|
|
28
|
+
bgGreen: '\x1b[42m'
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Method-specific configurations
|
|
32
|
+
const methodConfig = {
|
|
33
|
+
log: {
|
|
34
|
+
color: colors.reset,
|
|
35
|
+
symbol: ' ',
|
|
36
|
+
label: 'INFO'
|
|
37
|
+
},
|
|
38
|
+
warn: {
|
|
39
|
+
color: colors.yellow,
|
|
40
|
+
symbol: '⚠️ ',
|
|
41
|
+
label: 'WARN'
|
|
42
|
+
},
|
|
43
|
+
error: {
|
|
44
|
+
color: colors.red,
|
|
45
|
+
symbol: '✗ ',
|
|
46
|
+
label: 'ERROR'
|
|
47
|
+
},
|
|
48
|
+
table: {
|
|
49
|
+
color: colors.cyan,
|
|
50
|
+
symbol: '📊',
|
|
51
|
+
label: 'DATA'
|
|
52
|
+
},
|
|
53
|
+
debug: {
|
|
54
|
+
color: colors.gray,
|
|
55
|
+
symbol: '🔍',
|
|
56
|
+
label: 'DEBUG'
|
|
57
|
+
},
|
|
58
|
+
success: {
|
|
59
|
+
color: colors.green,
|
|
60
|
+
symbol: '✓ ',
|
|
61
|
+
label: 'OK'
|
|
62
|
+
},
|
|
63
|
+
critical: {
|
|
64
|
+
color: `${colors.bright}${colors.bgRed}${colors.white}`,
|
|
65
|
+
symbol: '🔴',
|
|
66
|
+
label: 'CRITICAL'
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Format timestamp for console output
|
|
72
|
+
*/
|
|
73
|
+
const formatTimestamp = function () {
|
|
74
|
+
const now = new Date();
|
|
75
|
+
const time = now.toTimeString().split( ' ' )[ 0 ]; // HH:MM:SS
|
|
76
|
+
const ms = now.getMilliseconds().toString().padStart( 3, '0' );
|
|
77
|
+
return `${colors.gray}[${time}.${ms}]${colors.reset}`;
|
|
78
|
+
}; // formatTimestamp()
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Format node identifier
|
|
82
|
+
*/
|
|
83
|
+
const formatNodeId = function ( partitionKey ) {
|
|
84
|
+
const partition = partitionKey ? `/${partitionKey}` : '';
|
|
85
|
+
return `${colors.cyan}[${partition}]${colors.reset}`;
|
|
86
|
+
}; // formatNodeId()
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Format structured data for console
|
|
90
|
+
*/
|
|
91
|
+
const formatData = function ( data, indent = 2 ) {
|
|
92
|
+
if ( data === null || data === undefined ) {
|
|
93
|
+
return `${colors.gray}(empty)${colors.reset}`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if ( typeof data === 'string' || typeof data === 'number' || typeof data === 'boolean' ) {
|
|
97
|
+
return String( data );
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// For objects, create indented key-value display
|
|
101
|
+
const spaces = ' '.repeat( indent );
|
|
102
|
+
const lines = [];
|
|
103
|
+
|
|
104
|
+
for ( const [ key, value ] of Object.entries( data ) ) {
|
|
105
|
+
const formattedKey = `${colors.bright}${key}:${colors.reset}`;
|
|
106
|
+
|
|
107
|
+
// Handle different value types
|
|
108
|
+
let formattedValue;
|
|
109
|
+
if ( typeof value === 'object' && value !== null ) {
|
|
110
|
+
// Nested object - use JSON stringify with indent
|
|
111
|
+
formattedValue = JSON.stringify( value, null, 2 )
|
|
112
|
+
.split( '\n' )
|
|
113
|
+
.map( ( line, i ) => ( i === 0 ? line : spaces + line ) )
|
|
114
|
+
.join( '\n' );
|
|
115
|
+
} else if ( typeof value === 'string' ) {
|
|
116
|
+
formattedValue = `"${value}"`;
|
|
117
|
+
} else {
|
|
118
|
+
formattedValue = String( value );
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
lines.push( `${spaces}${formattedKey} ${formattedValue}` );
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return lines.join( '\n' );
|
|
125
|
+
}; // formatData()
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Create formatted console output
|
|
129
|
+
*/
|
|
130
|
+
const createConsoleFormatter = function () {
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Format and emit to console
|
|
134
|
+
*
|
|
135
|
+
* @param {string} method - Console method (log, warn, error, table)
|
|
136
|
+
* @param {Object} data - Data to output
|
|
137
|
+
* @param {string} [partitionKey] - Optional partition identifier
|
|
138
|
+
* @param {Object} [metadata] - Optional metadata (UNS, etc.)
|
|
139
|
+
*/
|
|
140
|
+
const format = function ( method, data, partitionKey, metadata ) {
|
|
141
|
+
const config = methodConfig[ method ] || methodConfig.log;
|
|
142
|
+
|
|
143
|
+
// Build header line
|
|
144
|
+
const timestamp = formatTimestamp();
|
|
145
|
+
const nodeId = formatNodeId( partitionKey );
|
|
146
|
+
const header = `${config.symbol} ${timestamp} ${nodeId}`;
|
|
147
|
+
|
|
148
|
+
// Handle table method specially
|
|
149
|
+
if ( method === 'table' && ( Array.isArray( data ) || typeof data === 'object' ) ) {
|
|
150
|
+
console.log( `${header} ${config.color}[TABLE]${colors.reset}` );
|
|
151
|
+
console.table( data );
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Handle critical alerts with emphasis
|
|
156
|
+
if ( method === 'critical' ) {
|
|
157
|
+
console.log( `\n${config.color} ${config.label} ${colors.reset}` );
|
|
158
|
+
console.log( header );
|
|
159
|
+
console.log( formatData( data, 4 ) );
|
|
160
|
+
console.log( `${config.color} ${'═'.repeat( 40 )} ${colors.reset}\n` );
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Standard formatted output
|
|
165
|
+
const output = [];
|
|
166
|
+
output.push( header );
|
|
167
|
+
|
|
168
|
+
// Add metadata if present (UNS path, etc.)
|
|
169
|
+
if ( metadata?.uns ) {
|
|
170
|
+
output.push( ` ${colors.gray}UNS: ${metadata.uns}${colors.reset}` );
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Format main data
|
|
174
|
+
if ( typeof data === 'string' ) {
|
|
175
|
+
output.push( ` ${config.color}${data}${colors.reset}` );
|
|
176
|
+
} else {
|
|
177
|
+
output.push( formatData( data, 2 ) );
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Output using appropriate console method
|
|
181
|
+
const consoleMethod = [ 'log', 'warn', 'error', 'table' ].includes( method ) ? method : 'log';
|
|
182
|
+
|
|
183
|
+
console[ consoleMethod ]( output.join( '\n' ) );
|
|
184
|
+
}; // format()
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Create separator line for visual grouping
|
|
188
|
+
*/
|
|
189
|
+
const separator = function ( label, char = '═' ) {
|
|
190
|
+
const line = char.repeat( 40 );
|
|
191
|
+
if ( label ) {
|
|
192
|
+
console.log( `${colors.cyan}${line}${colors.reset}` );
|
|
193
|
+
console.log( `${colors.bright}${colors.cyan} ${label}${colors.reset}` );
|
|
194
|
+
console.log( `${colors.cyan}${line}${colors.reset}` );
|
|
195
|
+
} else {
|
|
196
|
+
console.log( `${colors.gray}${line}${colors.reset}` );
|
|
197
|
+
}
|
|
198
|
+
}; // separator()
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
format: format,
|
|
202
|
+
separator: separator,
|
|
203
|
+
colors: colors // Export for custom formatting
|
|
204
|
+
};
|
|
205
|
+
}; // createConsoleFormatter()
|
|
206
|
+
|
|
207
|
+
export default createConsoleFormatter;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import sanitizeField from './sanitize-field.js';
|
|
2
|
+
import { smartTruncate } from './smart-truncate.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates a smart, sanitized identifier for storing computed values.
|
|
6
|
+
* Ensures valid JavaScript identifiers while preserving readability.
|
|
7
|
+
*
|
|
8
|
+
* Examples:
|
|
9
|
+
* ('ewma', 'temperature') → 'ewma_temperature'
|
|
10
|
+
* ('diff', 'temperature', 'setpoint') → 'diff_temperature_setpoint'
|
|
11
|
+
* ('mean', 'sensor.pressure') → 'mean_sensor_pressure'
|
|
12
|
+
* ('ratio', 'inlet-flow', 'outlet-flow') → 'ratio_inlet_flow_outlet_flow'
|
|
13
|
+
*
|
|
14
|
+
* @param {string} statType - Type of computation (e.g., 'diff', 'ewma', 'mean')
|
|
15
|
+
* @param {string} x - First field name (required)
|
|
16
|
+
* @param {string} y - Second field name (optional for single-field nodes)
|
|
17
|
+
* @returns {string} A valid, meaningful identifier under 50 characters
|
|
18
|
+
*/
|
|
19
|
+
const createSmartStoreAs = function ( statType, x, y ) {
|
|
20
|
+
// Maximum length for the final identifier
|
|
21
|
+
const MAX_LENGTH = 50;
|
|
22
|
+
|
|
23
|
+
// Ensure statType is valid and reasonable length
|
|
24
|
+
const cleanStatType = ( statType && typeof statType === 'string' && statType.length > 0 ) ?
|
|
25
|
+
( statType.length > 10 ? statType.substring( 0, 10 ) : statType ) :
|
|
26
|
+
'value';
|
|
27
|
+
|
|
28
|
+
// Sanitize the primary field
|
|
29
|
+
const cleanX = sanitizeField( x );
|
|
30
|
+
|
|
31
|
+
// Build name based on whether we have one or two fields
|
|
32
|
+
let fullName;
|
|
33
|
+
if ( y === null || y === undefined || y === '' ) {
|
|
34
|
+
// Single field pattern: statType_field
|
|
35
|
+
fullName = `${cleanStatType}_${cleanX}`;
|
|
36
|
+
} else {
|
|
37
|
+
// Two field pattern: statType_field1_field2
|
|
38
|
+
const cleanY = sanitizeField( y );
|
|
39
|
+
fullName = `${cleanStatType}_${cleanX}_${cleanY}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// If it fits within limit, use it as-is
|
|
43
|
+
if ( fullName.length <= MAX_LENGTH ) {
|
|
44
|
+
return fullName;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// For single field, just truncate it
|
|
48
|
+
if ( y === null || y === undefined || y === '' ) {
|
|
49
|
+
const prefixLen = cleanStatType.length + 1; // statType + 1 underscore
|
|
50
|
+
const availableLen = MAX_LENGTH - prefixLen - 5; // Reserve 5 for hash
|
|
51
|
+
|
|
52
|
+
if ( availableLen < 5 ) {
|
|
53
|
+
return smartTruncate( fullName, MAX_LENGTH );
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const truncatedField = cleanX.length > availableLen ?
|
|
57
|
+
smartTruncate( cleanX, availableLen ) :
|
|
58
|
+
cleanX;
|
|
59
|
+
|
|
60
|
+
return `${cleanStatType}_${truncatedField}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// For two fields, sanitize y once and reuse
|
|
64
|
+
const cleanY = sanitizeField( y );
|
|
65
|
+
|
|
66
|
+
// Distribute space between both fields
|
|
67
|
+
const prefixLen = cleanStatType.length + 2; // statType + 2 underscores
|
|
68
|
+
const availableLen = MAX_LENGTH - prefixLen;
|
|
69
|
+
|
|
70
|
+
// If even the prefix is too long, truncate everything
|
|
71
|
+
if ( availableLen < 10 ) {
|
|
72
|
+
return smartTruncate( fullName, MAX_LENGTH );
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Distribute available space between both fields
|
|
76
|
+
const fieldMaxLen = Math.floor( ( availableLen - 10 ) / 2 );
|
|
77
|
+
|
|
78
|
+
// Truncate fields if needed
|
|
79
|
+
const shortX = cleanX.length > fieldMaxLen ?
|
|
80
|
+
smartTruncate( cleanX, fieldMaxLen ) :
|
|
81
|
+
cleanX;
|
|
82
|
+
|
|
83
|
+
const shortY = cleanY.length > fieldMaxLen ?
|
|
84
|
+
smartTruncate( cleanY, fieldMaxLen ) :
|
|
85
|
+
cleanY;
|
|
86
|
+
|
|
87
|
+
// Build shortened name
|
|
88
|
+
const shortName = `${cleanStatType}_${shortX}_${shortY}`;
|
|
89
|
+
|
|
90
|
+
// Final check - if still too long, truncate the whole thing
|
|
91
|
+
if ( shortName.length > MAX_LENGTH ) {
|
|
92
|
+
return smartTruncate( shortName, MAX_LENGTH );
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return shortName;
|
|
96
|
+
}; // createSmartStoreAs()
|
|
97
|
+
|
|
98
|
+
export default createSmartStoreAs;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitizes a field name to create a valid JavaScript identifier part.
|
|
3
|
+
* Converts common separators to underscores and removes invalid characters.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} field - The field name to sanitize
|
|
6
|
+
* @returns {string} A valid identifier part, 'field' if input is invalid
|
|
7
|
+
*/
|
|
8
|
+
const sanitizeField = function ( field ) {
|
|
9
|
+
// Handle invalid input
|
|
10
|
+
if ( !field || typeof field !== 'string' ) {
|
|
11
|
+
return 'field';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Replace common separators with underscores
|
|
15
|
+
// This handles dots, hyphens, spaces, and slashes
|
|
16
|
+
let clean = field.replace( /[\s\-\.\/\\]+/g, '_' );
|
|
17
|
+
|
|
18
|
+
// Remove all non-alphanumeric characters except underscores
|
|
19
|
+
clean = clean.replace( /[^a-zA-Z0-9_]/g, '' );
|
|
20
|
+
|
|
21
|
+
// If nothing remains, return default
|
|
22
|
+
if ( !clean ) {
|
|
23
|
+
return 'field';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Collapse multiple consecutive underscores into one
|
|
27
|
+
clean = clean.replace( /_+/g, '_' );
|
|
28
|
+
|
|
29
|
+
// Remove leading and trailing underscores
|
|
30
|
+
clean = clean.replace( /^_+|_+$/g, '' );
|
|
31
|
+
|
|
32
|
+
// If nothing remains after trimming underscores, return default
|
|
33
|
+
if ( !clean ) {
|
|
34
|
+
return 'field';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Ensure it doesn't start with a number (invalid in JavaScript)
|
|
38
|
+
// Check AFTER removing leading underscores
|
|
39
|
+
if ( ( /^\d/ ).test( clean ) ) {
|
|
40
|
+
clean = '_' + clean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return clean;
|
|
44
|
+
}; // sanitizeField()
|
|
45
|
+
|
|
46
|
+
export default sanitizeField;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a simple hash from a string for uniqueness.
|
|
3
|
+
* Uses a variant of djb2 algorithm, returns 4-character base36 string.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} str - String to hash
|
|
6
|
+
* @returns {string} 4-character hash
|
|
7
|
+
*/
|
|
8
|
+
const generateHash = function ( str ) {
|
|
9
|
+
let hash = 5381;
|
|
10
|
+
|
|
11
|
+
for ( let i = 0; i < str.length; i += 1 ) {
|
|
12
|
+
// hash * 33 + char
|
|
13
|
+
hash = ( ( hash << 5 ) + hash ) + str.charCodeAt( i ); // eslint-disable-line no-bitwise
|
|
14
|
+
// Convert to 32-bit integer
|
|
15
|
+
hash &= hash; // eslint-disable-line no-bitwise
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Convert to base36 and take last 4 characters
|
|
19
|
+
return Math.abs( hash ).toString( 36 ).slice( -4 ).padStart( 4, '0' );
|
|
20
|
+
}; // generateHash()
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Finds the best truncation point in a string, preferring word boundaries.
|
|
24
|
+
* Looks for underscores or camelCase transitions.
|
|
25
|
+
*
|
|
26
|
+
* @param {string} str - String to analyze
|
|
27
|
+
* @param {number} maxLen - Maximum length before truncation
|
|
28
|
+
* @returns {number} Best truncation index
|
|
29
|
+
*/
|
|
30
|
+
const findBestBreakPoint = function ( str, maxLen ) {
|
|
31
|
+
// For very short strings, just return maxLen
|
|
32
|
+
if ( maxLen < 10 || str.length <= maxLen ) {
|
|
33
|
+
return maxLen;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const truncated = str.substring( 0, maxLen );
|
|
37
|
+
|
|
38
|
+
// Look for the last underscore
|
|
39
|
+
const lastUnderscore = truncated.lastIndexOf( '_' );
|
|
40
|
+
|
|
41
|
+
// Look for the last camelCase boundary (lowercase followed by uppercase)
|
|
42
|
+
let lastCamelBoundary = -1;
|
|
43
|
+
for ( let i = truncated.length - 2; i >= 0; i -= 1 ) {
|
|
44
|
+
if ( ( /[a-z]/ ).test( truncated[i] ) && ( /[A-Z]/ ).test( truncated[i + 1] ) ) {
|
|
45
|
+
lastCamelBoundary = i + 1;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Choose the better break point
|
|
51
|
+
const breakPoint = Math.max( lastUnderscore, lastCamelBoundary );
|
|
52
|
+
|
|
53
|
+
// Only use the break point if it's not too short (at least 60% of maxLen)
|
|
54
|
+
if ( breakPoint > maxLen * 0.6 ) {
|
|
55
|
+
return breakPoint;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return maxLen;
|
|
59
|
+
}; // findBestBreakPoint()
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Intelligently truncates a string to fit within maxLength.
|
|
63
|
+
* Tries to break at word boundaries and adds a hash for uniqueness.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} str - String to truncate
|
|
66
|
+
* @param {number} maxLen - Maximum allowed length
|
|
67
|
+
* @returns {string} Truncated string with hash suffix
|
|
68
|
+
*/
|
|
69
|
+
const smartTruncate = function ( str, maxLen ) {
|
|
70
|
+
// No truncation needed
|
|
71
|
+
if ( str.length <= maxLen ) {
|
|
72
|
+
return str;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Very short maxLen - just truncate directly
|
|
76
|
+
if ( maxLen < 10 ) {
|
|
77
|
+
return str.substring( 0, maxLen );
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Reserve space for underscore and 4-char hash
|
|
81
|
+
const availableLen = maxLen - 5;
|
|
82
|
+
|
|
83
|
+
// Find best break point
|
|
84
|
+
const breakPoint = findBestBreakPoint( str, availableLen );
|
|
85
|
+
const truncated = str.substring( 0, breakPoint );
|
|
86
|
+
|
|
87
|
+
// Generate hash from original string for uniqueness
|
|
88
|
+
const hash = generateHash( str );
|
|
89
|
+
|
|
90
|
+
return `${truncated}_${hash}`;
|
|
91
|
+
}; // smartTruncate()
|
|
92
|
+
|
|
93
|
+
export { smartTruncate, generateHash };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Flow build-time utilities. The naming-policy helpers (renderName / template
|
|
2
|
+
// rendering) were retired when fan naming converged on the fixed
|
|
3
|
+
// ${field}_${label} rule shared by the forEach and pick fan constructs.
|
|
4
|
+
export { makeCollisionChecker } from './make-collision-checker.js';
|
|
5
|
+
export { toKebab } from './to-kebab.js';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collision checker for generated identifiers.
|
|
3
|
+
* Throws on duplicates; keeps errors explicit and early.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const makeCollisionChecker = function () {
|
|
7
|
+
const seen = Object.create( null );
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Assert identifier has not been seen before.
|
|
11
|
+
* @param {string} id
|
|
12
|
+
* @param {string=} hint Optional: human context for error messages
|
|
13
|
+
*/
|
|
14
|
+
const isDuplicate = function ( id ) {
|
|
15
|
+
if ( seen[ id ] === 1 ) return true;
|
|
16
|
+
seen[ id ] = 1;
|
|
17
|
+
return false;
|
|
18
|
+
}; // assertUnique()
|
|
19
|
+
|
|
20
|
+
return isDuplicate;
|
|
21
|
+
}; // makeCollisionChecker()
|
|
22
|
+
|
|
23
|
+
export { makeCollisionChecker };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// core/utils/flow/to-kebab.js
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Converts camelCase string to kebab-case.
|
|
5
|
+
* Used for mapping node module names to directory paths.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* toKebab('esMean') → 'es-mean'
|
|
9
|
+
* toKebab('pageHinkley') → 'page-hinkley'
|
|
10
|
+
* toKebab('threshold') → 'threshold'
|
|
11
|
+
*
|
|
12
|
+
* @param {string} str - camelCase string
|
|
13
|
+
* @returns {string} kebab-case string
|
|
14
|
+
*/
|
|
15
|
+
export const toKebab = function ( str ) {
|
|
16
|
+
return str
|
|
17
|
+
.replace( /([A-Z])/g, '-$1' )
|
|
18
|
+
.toLowerCase()
|
|
19
|
+
.replace( /^-/, '' );
|
|
20
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Half-Life Parameter Utilities
|
|
3
|
+
*
|
|
4
|
+
* Converts between half-life (intuitive) and alpha (computational)
|
|
5
|
+
* parameterizations for exponential decay processes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Convert half-life to EWMA alpha parameter.
|
|
10
|
+
* Uses expm1 for numerical stability with large half-life values.
|
|
11
|
+
*
|
|
12
|
+
* @param {number} halfLife Half-life in consistent units (samples or seconds)
|
|
13
|
+
* @returns {number} alpha in (0,1)
|
|
14
|
+
*/
|
|
15
|
+
export const halfLifeToAlpha = function ( halfLife ) {
|
|
16
|
+
if ( typeof halfLife !== 'number' || !Number.isFinite( halfLife ) || ( halfLife <= 0 ) ) {
|
|
17
|
+
throw new Error( 'Half-life must be a finite number > 0' );
|
|
18
|
+
}
|
|
19
|
+
// alpha = 1 - exp( -ln(2) / halfLife ); use expm1 to avoid cancellation
|
|
20
|
+
let alpha = -Math.expm1( -( Math.LN2 / halfLife ) );
|
|
21
|
+
|
|
22
|
+
// Defensive clamps (never publish 0 or ≥1):
|
|
23
|
+
const MIN_ALPHA = ( 32 * Number.EPSILON ); // ~3.55e-15 on double
|
|
24
|
+
const MAX_ALPHA = ( 1 - ( 8 * Number.EPSILON ) );
|
|
25
|
+
if ( alpha < MIN_ALPHA ) alpha = MIN_ALPHA;
|
|
26
|
+
if ( alpha > MAX_ALPHA ) alpha = MAX_ALPHA;
|
|
27
|
+
|
|
28
|
+
return alpha;
|
|
29
|
+
}; // halfLifeToAlpha()
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Convert EWMA alpha to half-life.
|
|
33
|
+
* Uses log1p for numerical stability with small alpha values.
|
|
34
|
+
*
|
|
35
|
+
* @param {number} alpha Smoothing factor in (0,1)
|
|
36
|
+
* @returns {number} Half-life in same units used to derive alpha (samples or seconds)
|
|
37
|
+
*/
|
|
38
|
+
export const alphaToHalfLife = function ( alpha ) {
|
|
39
|
+
if ( typeof alpha !== 'number' || !Number.isFinite( alpha ) || ( alpha <= 0 ) || ( alpha >= 1 ) ) {
|
|
40
|
+
throw new Error( 'Alpha must be a finite number in (0,1)' );
|
|
41
|
+
}
|
|
42
|
+
// halfLife = ln(2) / -ln(1 - alpha) ; use log1p(-alpha) for stability
|
|
43
|
+
return Math.LN2 / ( -Math.log1p( -alpha ) );
|
|
44
|
+
}; // alphaToHalfLife()
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Samples to warm up a slow EWMA so that the initial-condition influence
|
|
48
|
+
* has decayed to (1 - settledFraction). Half-life is in SAMPLES.
|
|
49
|
+
*
|
|
50
|
+
* @param {number} halfLifeSamples Half-life in samples (> 0)
|
|
51
|
+
* @param {number} settledFraction Target fraction absorbed in (0,1), e.g., 0.95
|
|
52
|
+
* @returns {number} Ceil’d samples to wait
|
|
53
|
+
*/
|
|
54
|
+
export const halfLifeToWarmupSamples = function ( halfLifeSamples, settledFraction = 0.95 ) {
|
|
55
|
+
if ( typeof halfLifeSamples !== 'number' || !Number.isFinite( halfLifeSamples ) || ( halfLifeSamples <= 0 ) ) {
|
|
56
|
+
throw new Error( 'halfLifeSamples must be a finite number > 0' );
|
|
57
|
+
}
|
|
58
|
+
if ( typeof settledFraction !== 'number' || !Number.isFinite( settledFraction ) || ( settledFraction <= 0 ) || ( settledFraction >= 1 ) ) {
|
|
59
|
+
throw new Error( 'settledFraction must be a finite number in (0,1)' );
|
|
60
|
+
}
|
|
61
|
+
// nHL = -log2(1 - settledFraction) = -ln(1 - s)/ln2
|
|
62
|
+
const nHalfLives = ( -Math.log1p( -settledFraction ) ) / Math.LN2;
|
|
63
|
+
return Math.ceil( halfLifeSamples * nHalfLives );
|
|
64
|
+
}; // halfLifeToWarmupSamples()
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Effective window (samples) for a chosen settled fraction.
|
|
68
|
+
* By default uses TWO HALF-LIVES → 75% response (settledFraction = 0.75).
|
|
69
|
+
*
|
|
70
|
+
* @param {number} halfLifeSamples Half-life in samples (> 0)
|
|
71
|
+
* @param {number} settledFraction=0.75 Desired settled fraction (0,1)
|
|
72
|
+
* @returns {number} Samples corresponding to the chosen settled fraction
|
|
73
|
+
*/
|
|
74
|
+
export const halfLifeToEffectiveWindow = function ( halfLifeSamples, settledFraction = 0.75 ) {
|
|
75
|
+
return halfLifeToWarmupSamples( halfLifeSamples, settledFraction );
|
|
76
|
+
}; // halfLifeToEffectiveWindow()
|
|
77
|
+
|
|
78
|
+
/* Notes (samples + half-life only)
|
|
79
|
+
* Settled fraction s ∈ (0,1):
|
|
80
|
+
* nHalfLives = -log1p( -s ) / Math.LN2
|
|
81
|
+
*
|
|
82
|
+
* Quick refs (multiply your HLs by these and ceil):
|
|
83
|
+
* s=0.75 → 2.000 half-lives
|
|
84
|
+
* s=0.865 → 2.885 half-lives // ≈ 86.5% settled
|
|
85
|
+
* s=0.90 → 3.322 half-lives
|
|
86
|
+
* s=0.95 → 4.322 half-lives
|
|
87
|
+
* s=0.98 → 6.644 half-lives
|
|
88
|
+
*
|
|
89
|
+
* Example: HLs = 20, s = 0.95 → ceil( 20 × 4.322 ) = 87 samples.
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Clamp a numeric value between lower and upper bounds.
|
|
94
|
+
*
|
|
95
|
+
* Uses a simple ternary chain, which is the fastest pattern in V8
|
|
96
|
+
* (monomorphic, inlined, no extra function calls). Preferred over
|
|
97
|
+
* Math.min/Math.max for hot-path use.
|
|
98
|
+
*
|
|
99
|
+
* @param {number} x Value to clamp
|
|
100
|
+
* @param {number} lo Lower bound (inclusive)
|
|
101
|
+
* @param {number} hi Upper bound (inclusive)
|
|
102
|
+
* @returns {number} x constrained to [lo, hi]
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* clamp( 5, 0, 10 ); // → 5
|
|
106
|
+
* clamp( -3, 0, 10 ); // → 0
|
|
107
|
+
* clamp( 15, 0, 10 ); // → 10
|
|
108
|
+
*/
|
|
109
|
+
export const clamp = function ( x, lo, hi ) {
|
|
110
|
+
return ( x < lo ) ? lo : ( x > hi ? hi : x );
|
|
111
|
+
}; // clamp()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disables a node by setting its disable flag to true
|
|
3
|
+
* @param {Object} state - The node's state object
|
|
4
|
+
* @returns {boolean} - Always returns true for consistency with control methods
|
|
5
|
+
*/
|
|
6
|
+
const disable = function ( state ) {
|
|
7
|
+
state.disable = true;
|
|
8
|
+
return true;
|
|
9
|
+
}; // disable()
|
|
10
|
+
|
|
11
|
+
export default disable;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enables a node by setting its disable flag to false
|
|
3
|
+
* @param {Object} state - The node's state object
|
|
4
|
+
* @returns {boolean} - Always returns true for consistency with control methods
|
|
5
|
+
*/
|
|
6
|
+
const enable = function ( state ) {
|
|
7
|
+
state.disable = false;
|
|
8
|
+
return true;
|
|
9
|
+
}; // enable()
|
|
10
|
+
|
|
11
|
+
export default enable;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execute control triggers with re-entrancy protection.
|
|
3
|
+
* Called by nodes during their update cycle when trigger conditions are met.
|
|
4
|
+
*
|
|
5
|
+
* @param {Object} state - Node state containing resolvedTriggers
|
|
6
|
+
* @returns {number} Number of triggers executed (0 if skipped or no triggers)
|
|
7
|
+
*/
|
|
8
|
+
const executeTriggers = function ( state ) {
|
|
9
|
+
// No triggers to execute
|
|
10
|
+
if ( !state.resolvedTriggers || state.resolvedTriggers.length === 0 ) {
|
|
11
|
+
return 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Prevent re-entrant execution
|
|
15
|
+
if ( state.inControlPhase ) {
|
|
16
|
+
// `skippedTriggers` property is being created on demand.
|
|
17
|
+
state.skippedTriggers = ( state.skippedTriggers || 0 ) + 1;
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
state.inControlPhase = true;
|
|
22
|
+
let executed = 0;
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const triggers = state.resolvedTriggers;
|
|
26
|
+
for ( let i = 0; i < triggers.length; i += 1 ) {
|
|
27
|
+
const { control, targets } = triggers[ i ];
|
|
28
|
+
for ( let j = 0; j < targets.length; j += 1 ) {
|
|
29
|
+
control( targets[ j ] );
|
|
30
|
+
executed += 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
} finally {
|
|
34
|
+
state.inControlPhase = false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return executed;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default executeTriggers;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { default as executeTriggers } from './execute-triggers.js';
|
|
2
|
+
export { default as validateSpec } from './validate-spec.js';
|
|
3
|
+
export { default as publishNaN } from './publish-nan.js';
|
|
4
|
+
export { default as enable } from './enable.js';
|
|
5
|
+
export { default as disable } from './disable.js';
|
|
6
|
+
export { default as pause } from './pause.js';
|
|
7
|
+
export { default as unpause } from './unpause.js';
|
|
8
|
+
export { default as populatePredicateInput } from './populate-predicate-inputs.js';
|
|
9
|
+
export { default as resetPredicateInput } from './reset-predicate-inputs.js';
|
|
10
|
+
|