@pond-ts/react 0.14.0 → 0.14.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.
Files changed (2) hide show
  1. package/CHANGELOG.md +108 -1
  2. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,10 +7,117 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
7
7
  file covers both packages. Pre-1.0: minor bumps may include new features and
8
8
  type-level changes; patch bumps are strictly additive.
9
9
 
10
- [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.14.0...HEAD
10
+ [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.14.1...HEAD
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [0.14.1] — 2026-05-03
15
+
16
+ The "samples reducer + lifted custom-fn guard" release. Surfaced by
17
+ the gRPC experiment's step-4 (anomaly density) walkback: the use
18
+ case "compute counts of values exceeding `k·σ` from a baseline" needs
19
+ the **raw values** from the rolling window, but pond's existing
20
+ built-ins all collapse to scalars or deduplicate. Custom-function
21
+ reducers — which would cover the use case cleanly — worked on batch
22
+ but were rejected at runtime on live with a `TypeError` pointing at
23
+ `AggregateOutputMap` aliases (which don't actually solve "all values"
24
+ either). Two related changes ship together to close both gaps.
25
+
26
+ ### Added
27
+
28
+ - **`'samples'` built-in reducer.** Returns the bucket's defined
29
+ values as an array, in arrival order, with duplicates preserved.
30
+ Sits beside `'unique'` (which deduplicates) and `'top${N}'` (which
31
+ bounds and frequency-orders) — same array-output kind, same
32
+ type-system narrowing through `AggregateOutputMap`. Library-
33
+ implemented; per-event cost is O(1) `add` / O(1) `remove`
34
+ (Map-keyed by event index); `snapshot` is O(N) array copy.
35
+ Memory O(window size).
36
+
37
+ ```ts
38
+ // Anomaly density: count samples > k·σ from a separate baseline.
39
+ const stats = live.rolling(
40
+ '1m',
41
+ {
42
+ mean: { from: 'cpu', using: 'avg' },
43
+ sd: { from: 'cpu', using: 'stdev' },
44
+ },
45
+ { trigger: Trigger.every('30s') },
46
+ );
47
+
48
+ const recent = live.rolling('200ms', {
49
+ vals: { from: 'cpu', using: 'samples' },
50
+ });
51
+
52
+ // At each tick, count threshold crossings against the baseline:
53
+ stats.on('event', (e) => {
54
+ const samples = recent.value().vals as ReadonlyArray<number>;
55
+ const counts = thresholds.map(
56
+ (k) => samples.filter((v) => v - e.get('mean') > k * e.get('sd')).length,
57
+ );
58
+ // ... emit anomaly density
59
+ });
60
+ ```
61
+
62
+ Like `unique`, `samples` flattens one level on array-kind source
63
+ columns. Returns `[]` for an empty bucket.
64
+
65
+ ### Changed
66
+
67
+ - **Custom-function reducers now work on live.** Removed the runtime
68
+ `TypeError` guards on `LiveAggregation`, `LiveRollingAggregation`,
69
+ and `LivePartitionedSyncRolling` that previously rejected
70
+ function-typed reducers. New `bucketStateFor` and `rollingStateFor`
71
+ helpers in `reducers/index.ts` route built-ins to their dedicated
72
+ O(1) machinery and wrap custom functions in a generic adapter:
73
+
74
+ - **Bucket adapter** (`LiveAggregation`): buffers values, calls
75
+ the function once at `snapshot()` time. O(N) per snapshot.
76
+ - **Rolling adapter** (`LiveRollingAggregation`,
77
+ `LivePartitionedSyncRolling`): Map-keyed by event index for O(1)
78
+ `add` / O(1) `remove`; `snapshot()` calls the function with
79
+ `Array.from(map.values())` in arrival order. **O(N) per
80
+ snapshot** — the function re-runs over the current window each
81
+ time the accumulator emits.
82
+
83
+ Documented as the explicit trade-off: convenience of writing
84
+ `(values) => ...` inline against the perf cliff at high event
85
+ rates. For high-throughput streams prefer built-ins or `'samples'`
86
+ (collapse the window once on the producer side, run custom logic
87
+ on the consumer). For low-rate dashboards / debug pipelines /
88
+ prototypes, the convenience usually wins.
89
+
90
+ Pre-v0.14.1, calling `live.rolling(...)` with a custom-function
91
+ reducer threw `TypeError: live rolling reducer for output 'X' must
92
+ be a built-in name; ...`. Post-v0.14.1, the same call constructs
93
+ successfully and runs.
94
+
95
+ ### Tests
96
+
97
+ - 15 new tests in `test/samples-reducer.test.ts` covering: batch
98
+ reduce / aggregate / rolling (including the array-source
99
+ flattening); live aggregate (per-bucket arrays); live rolling
100
+ (window eviction, snapshot correctness through multiple cycles);
101
+ synced partitioned rolling with samples per partition; an
102
+ end-to-end anomaly-density-against-baseline scenario.
103
+ - 2 obsolete tests in `LiveAggregateOutputMap.test.ts` rewritten —
104
+ previously asserted the rejection error, now assert that custom
105
+ functions construct successfully and produce the right value.
106
+ - Total core tests: 1087 (was 1072).
107
+
108
+ ### Docs
109
+
110
+ - `pond-ts/transforms/reducer-reference.mdx`: new `'samples'` entry
111
+ in the Array-producing reducers section; "Choosing a reducer"
112
+ matrix updated; empty-bucket and rolling-complexity tables
113
+ updated; Custom reducers section gained the live perf-cliff
114
+ callout.
115
+ - `pond-ts/transforms/rolling.mdx`: replaced the "Custom-function
116
+ reducers are batch-only" note with the new "O(N) per snapshot on
117
+ live" perf-cliff note pointing at the reducer reference.
118
+
119
+ [0.14.1]: https://github.com/pjm17971/pond-ts/compare/v0.14.0...v0.14.1
120
+
14
121
  ## [0.14.0] — 2026-05-01
15
122
 
16
123
  Two perf wins driven by the gRPC experiment's V3 profiling pass
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pond-ts/react",
3
- "version": "0.14.0",
3
+ "version": "0.14.1",
4
4
  "description": "React hooks for pond-ts live time series",
5
5
  "license": "MIT",
6
6
  "repository": {