@winkjs/composer 0.0.2 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +106 -80
- package/package.json +56 -28
- 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,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Introspection metadata for categorize node.
|
|
3
|
+
*
|
|
4
|
+
* Defines supported stats (category, index), control methods, capabilities,
|
|
5
|
+
* DSL schema with cross-field validators, and tunable params (thresholds).
|
|
6
|
+
* All getters return defensive copies.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { validators } from '../../core/utils/validate/index.js';
|
|
10
|
+
import { resolveArray } from '../../core/utils/options/resolve-field-keyed.js';
|
|
11
|
+
|
|
12
|
+
/** Single source of truth for what this plugin can do */
|
|
13
|
+
const SUPPORTED_STATS = [
|
|
14
|
+
'category', // Assigned category name (string)
|
|
15
|
+
'index' // Category index (number: 0, 1, 2, ...)
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
/** Human-readable descriptions (for introspection) */
|
|
19
|
+
const STAT_DESCRIPTIONS = {
|
|
20
|
+
category: 'Assigned category name based on threshold comparison',
|
|
21
|
+
index: 'Zero-based index of the assigned category for efficient comparisons'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** Control methods available for triggers */
|
|
25
|
+
const SUPPORTED_CONTROL_METHODS = {
|
|
26
|
+
reset: 'Clears accumulated state and restarts computation',
|
|
27
|
+
enable: 'Enables node processing',
|
|
28
|
+
disable: 'Disables node processing',
|
|
29
|
+
pause: 'Pauses node processing while keeping state visible',
|
|
30
|
+
unpause: 'Resumes node processing after pause'
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** The type of this node */
|
|
34
|
+
const NODE_TYPE = 'Categorize';
|
|
35
|
+
|
|
36
|
+
/** Node capabilities for documentation */
|
|
37
|
+
const CAPABILITIES = {
|
|
38
|
+
description: 'Assigns numeric values to discrete categories using threshold boundaries',
|
|
39
|
+
features: [
|
|
40
|
+
'Deterministic threshold-based categorization',
|
|
41
|
+
'Outputs both category name and numeric index',
|
|
42
|
+
'O(n) linear search for typical threshold counts',
|
|
43
|
+
'Validates threshold ordering at initialization',
|
|
44
|
+
'Handles out-of-range values gracefully'
|
|
45
|
+
]
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/** Spec default values */
|
|
49
|
+
export const DEFAULT_OPTIONS = {
|
|
50
|
+
// No defaults needed for this node
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** Parameters that support tunable (dynamic) values */
|
|
54
|
+
export const TUNABLE_PARAMS = [ 'thresholds' ];
|
|
55
|
+
|
|
56
|
+
// Export functions for accessing metadata
|
|
57
|
+
export const getSupportedStats = () => SUPPORTED_STATS.slice();
|
|
58
|
+
export const getStatDescriptions = () => ( { ...STAT_DESCRIPTIONS } );
|
|
59
|
+
export const getSupportedControlMethods = () => ( { ...SUPPORTED_CONTROL_METHODS } );
|
|
60
|
+
export const getNodeType = () => NODE_TYPE;
|
|
61
|
+
export const getCapabilities = () => ( { ...CAPABILITIES, features: CAPABILITIES.features.slice() } );
|
|
62
|
+
|
|
63
|
+
// DSL Metadata for transpilation
|
|
64
|
+
const DSL_METADATA = {
|
|
65
|
+
// Spec schema for validation
|
|
66
|
+
specSchema: {
|
|
67
|
+
nodeType: {
|
|
68
|
+
type: 'string',
|
|
69
|
+
required: true,
|
|
70
|
+
value: NODE_TYPE
|
|
71
|
+
},
|
|
72
|
+
name: {
|
|
73
|
+
type: 'string',
|
|
74
|
+
required: true,
|
|
75
|
+
validator: validators.identifier,
|
|
76
|
+
error: 'Name must be a valid identifier'
|
|
77
|
+
},
|
|
78
|
+
from: {
|
|
79
|
+
type: 'object',
|
|
80
|
+
required: true,
|
|
81
|
+
properties: {
|
|
82
|
+
x: {
|
|
83
|
+
type: 'string',
|
|
84
|
+
required: true,
|
|
85
|
+
validator: validators.noSpaces,
|
|
86
|
+
error: 'Field name cannot contain spaces'
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
thresholds: {
|
|
91
|
+
type: 'arrayOrFunctionOrFieldKeyed',
|
|
92
|
+
required: true,
|
|
93
|
+
minItems: 1,
|
|
94
|
+
// Supports tunable for shift/mode-based category boundaries
|
|
95
|
+
itemSchema: {
|
|
96
|
+
type: 'number',
|
|
97
|
+
validator: validators.isFinite,
|
|
98
|
+
error: 'Threshold values must be finite numbers'
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
categories: {
|
|
102
|
+
type: 'arrayOrFieldKeyed',
|
|
103
|
+
required: true,
|
|
104
|
+
minItems: 2,
|
|
105
|
+
itemSchema: {
|
|
106
|
+
type: 'string',
|
|
107
|
+
minLength: 1,
|
|
108
|
+
error: 'Category names must be non-empty strings'
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
stats: {
|
|
112
|
+
type: 'object',
|
|
113
|
+
required: true,
|
|
114
|
+
minProperties: 1,
|
|
115
|
+
propertyNames: SUPPORTED_STATS,
|
|
116
|
+
propertySchema: {
|
|
117
|
+
type: 'object',
|
|
118
|
+
required: true,
|
|
119
|
+
properties: {
|
|
120
|
+
storeAs: {
|
|
121
|
+
type: 'string',
|
|
122
|
+
required: true,
|
|
123
|
+
validator: validators.identifier,
|
|
124
|
+
error: 'storeAs must be a valid identifier'
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
// Cross-field validators
|
|
132
|
+
crossFieldValidators: [
|
|
133
|
+
{
|
|
134
|
+
fields: [ 'thresholds', 'categories' ],
|
|
135
|
+
// Must have exactly n+1 categories for n thresholds (skip if thresholds is function).
|
|
136
|
+
// Resolve both for the node's field the way the runtime does, so a direct
|
|
137
|
+
// array and a field-keyed map are checked the same way.
|
|
138
|
+
validator: ( spec ) => {
|
|
139
|
+
if ( typeof spec.thresholds === 'function' ) return true;
|
|
140
|
+
const t = resolveArray( spec.thresholds, spec.from?.x );
|
|
141
|
+
const c = resolveArray( spec.categories, spec.from?.x );
|
|
142
|
+
if ( !Array.isArray( t ) || !Array.isArray( c ) ) return false;
|
|
143
|
+
return c.length === ( t.length + 1 );
|
|
144
|
+
},
|
|
145
|
+
error: 'Categories array must have exactly one more element than thresholds array'
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
fields: [ 'thresholds' ],
|
|
149
|
+
validator: ( spec ) => {
|
|
150
|
+
// If thresholds is a function, validation deferred to runtime
|
|
151
|
+
if ( typeof spec.thresholds === 'function' ) return true;
|
|
152
|
+
// Resolve for the node's field; the count validator owns the
|
|
153
|
+
// "did not resolve to an array" error, so defer here.
|
|
154
|
+
const t = resolveArray( spec.thresholds, spec.from?.x );
|
|
155
|
+
if ( !Array.isArray( t ) ) return true;
|
|
156
|
+
// Thresholds must be in strictly ascending order
|
|
157
|
+
for ( let i = 1; i < t.length; i += 1 ) {
|
|
158
|
+
if ( t[ i ] <= t[ i - 1 ] ) return false;
|
|
159
|
+
}
|
|
160
|
+
return true;
|
|
161
|
+
},
|
|
162
|
+
error: 'Thresholds must be in strictly ascending order with no duplicates'
|
|
163
|
+
}
|
|
164
|
+
],
|
|
165
|
+
|
|
166
|
+
// How to build the spec from DSL params
|
|
167
|
+
buildSpec: ( name, x, stats, options ) => ( {
|
|
168
|
+
nodeType: NODE_TYPE,
|
|
169
|
+
name,
|
|
170
|
+
from: { x },
|
|
171
|
+
stats,
|
|
172
|
+
...options
|
|
173
|
+
} ),
|
|
174
|
+
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export const getDSLMetadata = () => ( { ...DSL_METADATA } );
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Publish function for categorize node.
|
|
3
|
+
*
|
|
4
|
+
* Copies the assigned category name and/or index to the output message.
|
|
5
|
+
* Propagates NaN via publishNaN when the last input was invalid.
|
|
6
|
+
* Skipped entirely when the node is disabled.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { publishNaN } from '../../core/utils/node/index.js';
|
|
10
|
+
|
|
11
|
+
const publishTo = function ( state, msg ) {
|
|
12
|
+
if ( state.disable ) return;
|
|
13
|
+
// Propagate NaN if unhealthy
|
|
14
|
+
if ( state.inputValidationFailed ) {
|
|
15
|
+
publishNaN( state, msg );
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Publish requested stats
|
|
20
|
+
if ( state.stats.category ) {
|
|
21
|
+
msg[ state.stats.category.storeAs ] = state.category;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if ( state.stats.index ) {
|
|
25
|
+
msg[ state.stats.index.storeAs ] = state.categoryIndex;
|
|
26
|
+
}
|
|
27
|
+
}; // publishTo()
|
|
28
|
+
|
|
29
|
+
export default publishTo;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Recompute for categorize node.
|
|
3
|
+
*
|
|
4
|
+
* No-op: categorization is computed fresh from the input value on every
|
|
5
|
+
* update — there is no accumulated state that can drift over time.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const recompute = function () {
|
|
9
|
+
// Nothing to recompute - categorization is stateless
|
|
10
|
+
// No accumulations or numerical drift possible
|
|
11
|
+
return true;
|
|
12
|
+
}; // recompute()
|
|
13
|
+
|
|
14
|
+
export default recompute;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Reset categorize node state.
|
|
3
|
+
*
|
|
4
|
+
* Restores categorization to init-time defaults: first category, cleared
|
|
5
|
+
* error flags, and reset tunable error suppression.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const reset = function ( state ) {
|
|
9
|
+
state.inputValidationFailed = false;
|
|
10
|
+
state.categoryIndex = 0;
|
|
11
|
+
state.category = state.categories[ 0 ];
|
|
12
|
+
state.tunableErrorLogged = false;
|
|
13
|
+
return true;
|
|
14
|
+
}; // reset()
|
|
15
|
+
|
|
16
|
+
export default reset;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Update function for categorize node.
|
|
3
|
+
*
|
|
4
|
+
* Extracts the input value, resolves tunable thresholds for the current
|
|
5
|
+
* message, and finds the matching category via linear search. For typical
|
|
6
|
+
* threshold counts (3–5), linear search outperforms binary search.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const update = function ( state, msg ) {
|
|
10
|
+
if ( state.disable || state.pause ) return state;
|
|
11
|
+
const xVal = msg[ state.x ];
|
|
12
|
+
// Reset on each update
|
|
13
|
+
state.inputValidationFailed = false;
|
|
14
|
+
// Handle faults gracefully: ensure their isolation
|
|
15
|
+
if ( !Number.isFinite( xVal ) ) {
|
|
16
|
+
// Signals publishing NaN for all demanded `stats` in publishTo.
|
|
17
|
+
state.inputValidationFailed = true;
|
|
18
|
+
return state;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Resolve thresholds tunable for this message
|
|
22
|
+
try {
|
|
23
|
+
state.resolvedThresholds = state.thresholdsFn( msg );
|
|
24
|
+
if ( state.tunableErrorLogged ) state.tunableErrorLogged = false;
|
|
25
|
+
} catch ( error ) {
|
|
26
|
+
if ( !state.tunableErrorLogged ) {
|
|
27
|
+
state.tunableErrorLogged = true;
|
|
28
|
+
console.error( `WinkComposer/${state.nodeType}: tunable threw: ${error.message}` );
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if ( !state.resolvedThresholds ) {
|
|
33
|
+
state.inputValidationFailed = true;
|
|
34
|
+
return state;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Find category using linear search
|
|
38
|
+
// For typical threshold counts (3-5), this is faster than binary search
|
|
39
|
+
// Convention: value >= threshold belongs to upper category
|
|
40
|
+
let categoryIndex = 0;
|
|
41
|
+
|
|
42
|
+
for ( categoryIndex = 0; categoryIndex < state.resolvedThresholds.length; categoryIndex += 1 ) {
|
|
43
|
+
if ( xVal < state.resolvedThresholds[ categoryIndex ] ) break;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Update state
|
|
47
|
+
state.categoryIndex = categoryIndex;
|
|
48
|
+
state.category = state.categories[ categoryIndex ];
|
|
49
|
+
|
|
50
|
+
return state;
|
|
51
|
+
}; // update()
|
|
52
|
+
|
|
53
|
+
export default update;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// nodes/controller/index.js
|
|
2
|
+
|
|
3
|
+
export { default as init } from './init.js';
|
|
4
|
+
export { default as update } from './update.js';
|
|
5
|
+
export { default as reset } from './reset.js';
|
|
6
|
+
export { default as recompute } from './recompute.js';
|
|
7
|
+
export { default as publishTo } from './publish-to.js';
|
|
8
|
+
// Re-export everything from introspection.js
|
|
9
|
+
export * from './introspect.js';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// nodes/controller/init.js
|
|
2
|
+
|
|
3
|
+
import { validateWithSchema } from '../../core/utils/validate/index.js';
|
|
4
|
+
import { getDSLMetadata, getNodeType } from './introspect.js';
|
|
5
|
+
|
|
6
|
+
const init = function ( spec ) {
|
|
7
|
+
// Get validation schema from introspect
|
|
8
|
+
const metadata = getDSLMetadata();
|
|
9
|
+
const schema = {
|
|
10
|
+
...metadata.specSchema,
|
|
11
|
+
_crossFieldValidators: metadata.crossFieldValidators
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// Validate spec
|
|
15
|
+
const validation = validateWithSchema( schema, spec, 'spec' );
|
|
16
|
+
validation.throwIfInvalid( getNodeType() );
|
|
17
|
+
|
|
18
|
+
// Create state after validation passes
|
|
19
|
+
const state = Object.create( null );
|
|
20
|
+
|
|
21
|
+
// Copy logic array with structure as the placeholder resolved triggers,
|
|
22
|
+
// computed during the partition time.
|
|
23
|
+
state.logic = [];
|
|
24
|
+
for ( let i = 0; i < spec.logic.length; i += 1 ) {
|
|
25
|
+
const condition = Object.create( null );
|
|
26
|
+
condition.when = spec.logic[ i ].when;
|
|
27
|
+
// Keep spec for partition manager
|
|
28
|
+
condition.triggers = spec.logic[ i ].triggers;
|
|
29
|
+
// PLACEHOLDER: will be resolved by partition manager
|
|
30
|
+
condition.resolvedTriggers = null;
|
|
31
|
+
state.logic.push( condition );
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Controller metadata
|
|
35
|
+
state.name = spec.name;
|
|
36
|
+
state.nodeType = getNodeType();
|
|
37
|
+
|
|
38
|
+
// Observability fields
|
|
39
|
+
state.lastMatchedCondition = -1;
|
|
40
|
+
state.matchCount = 0;
|
|
41
|
+
state.errorCount = 0;
|
|
42
|
+
state.lastError = null;
|
|
43
|
+
|
|
44
|
+
// Log suppression: one log per error episode; reset on recovery.
|
|
45
|
+
state.predicateErrorLogged = false;
|
|
46
|
+
|
|
47
|
+
// Control phase tracking (executeTriggers re-entrancy guard)
|
|
48
|
+
state.inControlPhase = false;
|
|
49
|
+
// Points to the matched condition's triggers during execution
|
|
50
|
+
state.resolvedTriggers = null;
|
|
51
|
+
|
|
52
|
+
return state;
|
|
53
|
+
}; // init()
|
|
54
|
+
|
|
55
|
+
export default init;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// nodes/controller/introspect.js
|
|
2
|
+
|
|
3
|
+
import { validators, composerValidators } from '../../core/utils/validate/index.js';
|
|
4
|
+
|
|
5
|
+
/** Single source of truth for what this node can do */
|
|
6
|
+
const SUPPORTED_STATS = []; // Controller doesn't publish stats
|
|
7
|
+
|
|
8
|
+
/** Human-readable descriptions (for introspection) */
|
|
9
|
+
const STAT_DESCRIPTIONS = {}; // No stats, no descriptions
|
|
10
|
+
|
|
11
|
+
/** Control methods available for triggers (none - pure orchestrator) */
|
|
12
|
+
const SUPPORTED_CONTROL_METHODS = {};
|
|
13
|
+
|
|
14
|
+
/** Default options (none for this node) */
|
|
15
|
+
const DEFAULT_OPTIONS = {};
|
|
16
|
+
|
|
17
|
+
/** The type of this node */
|
|
18
|
+
const NODE_TYPE = 'Controller';
|
|
19
|
+
|
|
20
|
+
/** Node capabilities for documentation */
|
|
21
|
+
const CAPABILITIES = {
|
|
22
|
+
description: 'Pure orchestration node that monitors messages and coordinates other nodes without modifying data',
|
|
23
|
+
features: [
|
|
24
|
+
'Multi-condition state machine support',
|
|
25
|
+
'First-match-wins execution model',
|
|
26
|
+
'Re-entrancy protected trigger execution',
|
|
27
|
+
'No data transformation - pure control flow'
|
|
28
|
+
]
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Export functions for accessing metadata
|
|
32
|
+
export const getSupportedStats = () => SUPPORTED_STATS.slice();
|
|
33
|
+
export const getStatDescriptions = () => ( { ...STAT_DESCRIPTIONS } );
|
|
34
|
+
export const getSupportedControlMethods = () => ( { ...SUPPORTED_CONTROL_METHODS } );
|
|
35
|
+
export const getNodeType = () => NODE_TYPE;
|
|
36
|
+
export const getCapabilities = () => ( { ...CAPABILITIES, features: CAPABILITIES.features.slice() } );
|
|
37
|
+
|
|
38
|
+
// DSL Metadata for transpilation and validation
|
|
39
|
+
const DSL_METADATA = {
|
|
40
|
+
specSchema: {
|
|
41
|
+
nodeType: {
|
|
42
|
+
type: 'string',
|
|
43
|
+
required: true,
|
|
44
|
+
value: NODE_TYPE
|
|
45
|
+
},
|
|
46
|
+
name: {
|
|
47
|
+
type: 'string',
|
|
48
|
+
required: true,
|
|
49
|
+
validator: validators.identifier,
|
|
50
|
+
error: 'Name must be a valid JavaScript identifier'
|
|
51
|
+
},
|
|
52
|
+
logic: {
|
|
53
|
+
type: 'array',
|
|
54
|
+
required: true,
|
|
55
|
+
minItems: 1,
|
|
56
|
+
itemSchema: {
|
|
57
|
+
type: 'object',
|
|
58
|
+
properties: {
|
|
59
|
+
when: {
|
|
60
|
+
type: 'function',
|
|
61
|
+
required: true,
|
|
62
|
+
arity: 1,
|
|
63
|
+
error: 'when must be a predicate function with one parameter'
|
|
64
|
+
},
|
|
65
|
+
triggers: {
|
|
66
|
+
type: 'array',
|
|
67
|
+
required: true,
|
|
68
|
+
minItems: 1,
|
|
69
|
+
itemSchema: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
validator: composerValidators.trigger,
|
|
72
|
+
error: 'Invalid trigger specification'
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
crossFieldValidators: [], // No cross-field validation needed
|
|
81
|
+
|
|
82
|
+
buildSpec: ( name, logic ) => ( {
|
|
83
|
+
nodeType: NODE_TYPE,
|
|
84
|
+
name,
|
|
85
|
+
logic
|
|
86
|
+
} ),
|
|
87
|
+
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const getDSLMetadata = () => ( { ...DSL_METADATA } );
|
|
91
|
+
export { DEFAULT_OPTIONS };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// nodes/controller/reset.js
|
|
2
|
+
|
|
3
|
+
const reset = function ( state ) {
|
|
4
|
+
// Reset observability counters
|
|
5
|
+
state.lastMatchedCondition = -1;
|
|
6
|
+
state.matchCount = 0;
|
|
7
|
+
state.errorCount = 0;
|
|
8
|
+
state.lastError = null;
|
|
9
|
+
// Clear error suppression so next error episode is logged
|
|
10
|
+
state.predicateErrorLogged = false;
|
|
11
|
+
|
|
12
|
+
// Note: We don't reset logic or resolvedTriggers
|
|
13
|
+
// as they are structural, not runtime state
|
|
14
|
+
return true;
|
|
15
|
+
}; // reset()
|
|
16
|
+
|
|
17
|
+
export default reset;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// nodes/controller/update.js
|
|
2
|
+
|
|
3
|
+
import { executeTriggers } from '../../core/utils/node/index.js';
|
|
4
|
+
|
|
5
|
+
const update = function ( state, msg ) {
|
|
6
|
+
// Track whether any predicate threw during this pass
|
|
7
|
+
let anyError = false;
|
|
8
|
+
|
|
9
|
+
// Iterate through conditions in order
|
|
10
|
+
for ( let i = 0; i < state.logic.length; i += 1 ) {
|
|
11
|
+
const condition = state.logic[ i ];
|
|
12
|
+
|
|
13
|
+
// Evaluate predicate with error handling
|
|
14
|
+
let predicateResult = false;
|
|
15
|
+
try {
|
|
16
|
+
predicateResult = condition.when( msg );
|
|
17
|
+
} catch ( error ) {
|
|
18
|
+
anyError = true;
|
|
19
|
+
// Track predicate errors
|
|
20
|
+
state.errorCount += 1;
|
|
21
|
+
state.lastError = error.message;
|
|
22
|
+
// Log first error per episode; suppress subsequent until recovery
|
|
23
|
+
if ( !state.predicateErrorLogged ) {
|
|
24
|
+
state.predicateErrorLogged = true;
|
|
25
|
+
console.error( `WinkComposer/controller: predicate threw exception: ${error.message}` );
|
|
26
|
+
}
|
|
27
|
+
// Skip to next condition
|
|
28
|
+
continue; // eslint-disable-line no-continue
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Check if condition matches
|
|
32
|
+
if ( predicateResult === true ) {
|
|
33
|
+
// Recovery: clear flag only when entire pass is exception-free
|
|
34
|
+
if ( !anyError && state.predicateErrorLogged ) state.predicateErrorLogged = false;
|
|
35
|
+
|
|
36
|
+
// Update observability
|
|
37
|
+
state.lastMatchedCondition = i;
|
|
38
|
+
state.matchCount += 1;
|
|
39
|
+
|
|
40
|
+
// Check for resolved triggers
|
|
41
|
+
if ( !condition.resolvedTriggers || condition.resolvedTriggers.length === 0 ) {
|
|
42
|
+
return state; // No triggers to execute
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Point to this condition's triggers; it is an executeTriggers' requirement.
|
|
46
|
+
state.resolvedTriggers = condition.resolvedTriggers;
|
|
47
|
+
|
|
48
|
+
// Execute triggers with re-entrancy protection
|
|
49
|
+
executeTriggers( state );
|
|
50
|
+
|
|
51
|
+
// First match wins - stop processing
|
|
52
|
+
return state;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Recovery: clear flag only when entire pass is exception-free
|
|
57
|
+
if ( !anyError && state.predicateErrorLogged ) state.predicateErrorLogged = false;
|
|
58
|
+
|
|
59
|
+
// No conditions matched
|
|
60
|
+
return state;
|
|
61
|
+
}; // update()
|
|
62
|
+
|
|
63
|
+
export default update;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Entry point for diff node.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all lifecycle functions (init, update, publishTo, reset, recompute),
|
|
5
|
+
* shared control signals (disable, enable, pause, unpause), and introspection metadata.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { default as init } from './init.js';
|
|
9
|
+
export { default as update } from './update.js';
|
|
10
|
+
export { default as reset } from './reset.js';
|
|
11
|
+
export { default as recompute } from './recompute.js';
|
|
12
|
+
export { default as publishTo } from './publish-to.js';
|
|
13
|
+
// Direct imports for common control functions
|
|
14
|
+
export { default as disable } from '../../core/utils/node/disable.js';
|
|
15
|
+
export { default as enable } from '../../core/utils/node/enable.js';
|
|
16
|
+
export { default as pause } from '../../core/utils/node/pause.js';
|
|
17
|
+
export { default as unpause } from '../../core/utils/node/unpause.js';
|
|
18
|
+
// Re-export everything from introspection.js
|
|
19
|
+
export * from './introspect.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Initialization for diff node.
|
|
3
|
+
*
|
|
4
|
+
* Validates the spec, extracts field names and the absolute option,
|
|
5
|
+
* and returns the fully initialized state object.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { validateSpec } from '../../core/utils/node/index.js';
|
|
9
|
+
import * as introspect from './introspect.js';
|
|
10
|
+
|
|
11
|
+
const init = function ( spec ) {
|
|
12
|
+
validateSpec( spec, introspect );
|
|
13
|
+
|
|
14
|
+
const state = Object.create( null );
|
|
15
|
+
// Standard input parameter health flag during update: false means healthy
|
|
16
|
+
state.inputValidationFailed = false;
|
|
17
|
+
// Ensure node is enabled by default
|
|
18
|
+
state.disable = false;
|
|
19
|
+
state.pause = false;
|
|
20
|
+
|
|
21
|
+
// Extract field name & option.
|
|
22
|
+
state.x = spec.from.x;
|
|
23
|
+
state.y = spec.from.y;
|
|
24
|
+
state.absolute = spec.absolute ?? introspect.DEFAULT_OPTIONS.absolute;
|
|
25
|
+
|
|
26
|
+
// Config copy.
|
|
27
|
+
state.stats = spec.stats;
|
|
28
|
+
|
|
29
|
+
// State variables.
|
|
30
|
+
state.diff = 0;
|
|
31
|
+
|
|
32
|
+
state.nodeType = introspect.getNodeType();
|
|
33
|
+
|
|
34
|
+
return state;
|
|
35
|
+
}; // init()
|
|
36
|
+
|
|
37
|
+
export default init;
|