@pond-ts/react 0.15.2 → 0.16.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.
Files changed (2) hide show
  1. package/CHANGELOG.md +131 -1
  2. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -7,10 +7,139 @@ 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.15.2...HEAD
10
+ [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.16.0...HEAD
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [0.16.0] — 2026-05-06
15
+
16
+ Live-API ergonomic wave. Four PRs:
17
+ [#122](https://github.com/pjm17971/pond-ts/pull/122) (buffer-as-window
18
+ Tier 1), [#123](https://github.com/pjm17971/pond-ts/pull/123)
19
+ (`stats()` accessor), [#124](https://github.com/pjm17971/pond-ts/pull/124)
20
+ (`history` option + compile-time fused uniqueness),
21
+ [#125](https://github.com/pjm17971/pond-ts/pull/125) (Tier 2 query
22
+ primitives). Strictly additive surface — no public-API removals or
23
+ narrowings.
24
+
25
+ ### Added
26
+
27
+ - **`live.reduce(mapping, opts?)`** on `LiveSeries` and `LiveView`
28
+ — streaming reduce over the source's current buffer. Mirrors
29
+ `series.reduce(mapping)` from batch but reactive: per-event
30
+ `add`, per-eviction `remove`, microtask-deferred trigger
31
+ emission so retention has run before the snapshot. Closes the
32
+ buffer-as-window persona's biggest ergonomic gap.
33
+ - **`live.timeRange()`** on `LiveSeries` and `LiveView` — O(1)
34
+ temporal extent of the current buffer (`undefined` when empty).
35
+ - **`live.eventRate()`** on `LiveSeries` and `LiveView` — O(1)
36
+ events-per-second over the buffer's time span (zero when fewer
37
+ than two events). Convenience over the existing
38
+ `view.eventRate()` shape; no window argument required.
39
+ - **`live.count()`** on `LiveSeries` (alias for `length`) for
40
+ parity with `LiveView.count()` and chainable composition with
41
+ `eventRate()`.
42
+ - **`stats()` accessor on every live accumulator/series.** Per-class
43
+ shapes, all returning a plain record (cumulative integer counters
44
+ + current-state fields):
45
+
46
+ | Class | Shape |
47
+ |---|---|
48
+ | LiveSeries | `{ ingested, evicted, rejected, length, earliestTs?, latestTs? }` |
49
+ | LiveRollingAggregation | `{ eventsObserved, evictions, emissions, windowSize }` |
50
+ | LiveFusedRolling | `{ eventsObserved, evictions, emissions, windowSize, windowsCount }` |
51
+ | LiveAggregation | `{ eventsObserved, bucketsClosed, openBuckets, openBucketStart? }` |
52
+ | LiveReduce | `{ eventsObserved, evictions, emissions, bufferSize }` |
53
+ | LivePartitionedSeries | `{ partitions, eventsRouted }` |
54
+ | LivePartitionedSyncRolling | `{ partitions, eventsObserved, emissions, windowSize }` |
55
+ | LivePartitionedFusedRolling | `{ partitions, eventsObserved, emissions, windowSize, windowsCount }` |
56
+
57
+ Per-event cost: ~1-3 integer increments in already-existing
58
+ handlers. `stats()` itself is O(1) — or O(partitions) for the
59
+ max-across-partitions `windowSize` on partitioned variants.
60
+ Polling-based by design — wall-clock timers inside pond would
61
+ break the data-is-the-clock invariant.
62
+
63
+ - **`history: false | RetentionPolicy` option on
64
+ `LiveRollingAggregation` and `LiveFusedRolling`** (and
65
+ partitioned variants — threaded through
66
+ `LivePartitionedSeries.rolling` end-to-end). Controls how much
67
+ of the rolling's emitted history the accumulator keeps in its
68
+ own output buffer (the one read by `length` / `at(i)`). Default
69
+ `true` preserves current behavior; `false` skips the push
70
+ entirely (`'event'` listeners and `value()` still work, but
71
+ `length` stays at 0); `RetentionPolicy` (`{ maxEvents?, maxAge? }`)
72
+ caps the buffer using the same shape as `LiveSeries.retention`.
73
+ Stricter validation: rejects 0, negative, or non-integer
74
+ `maxEvents`; `Infinity` is the documented "no cap" sentinel.
75
+
76
+ - **Compile-time uniqueness check on fused output columns**
77
+ (`FusedMappingValid<FM>`). Two windows declaring the same
78
+ output name now fail at the call site with a branded error
79
+ type naming the conflict. Wired into all four fused-rolling
80
+ overloads (LiveSeries, LiveView, root + view
81
+ LivePartitionedSeries). Runtime check still in place.
82
+
83
+ - **Tier 2 query primitives on `LiveSeries` and `LiveView`** —
84
+ pure parity additions mirroring `TimeSeries`:
85
+ - `find(pred)`, `some(pred)`, `every(pred)` — O(N) predicate query
86
+ - `includesKey(key)`, `bisect(key)`, `atOrBefore(key)`,
87
+ `atOrAfter(key)` — O(log N) binary search on the sorted buffer
88
+
89
+ Use cases: "is there already an event with key K?" / "what was
90
+ the most recent event before time T?" Both come up in dashboard
91
+ patterns where the live buffer IS the working set.
92
+
93
+ - **`KeyLike` type** exported from the package root (re-exported
94
+ from `TimeSeries`). Accepts `EventKey | TimestampInput |
95
+ TimeRangeInput | IntervalInput`; normalised by the new query
96
+ primitives.
97
+
98
+ - **`DurationLiteral` and `DurationUnit` types** extracted from
99
+ `utils/duration.ts` and exported. Same shape as before, just
100
+ named.
101
+
102
+ - **Concrete return types from partitioned rolling overloads.**
103
+ `LivePartitionedSeries.rolling` and `LivePartitionedView.rolling`
104
+ clock-trigger and fused-mapping overloads now return the concrete
105
+ `LivePartitionedSyncRolling` / `LivePartitionedFusedRolling`
106
+ classes (instead of bare `LiveSource<...>`), exposing `stats()`
107
+ to callers without a cast. Strictly additive — concrete classes
108
+ implement `LiveSource` plus `stats()`.
109
+
110
+ ### Changed
111
+
112
+ - **`LiveSeries.clear()`** now increments the `evicted` counter
113
+ on `stats()` to match the existing `'evict'` listener fan-out.
114
+ Previously cleared the buffer and fired listeners but didn't
115
+ update the counter.
116
+ - **`LiveSeries` insertion comparator** delegates to
117
+ `EventKey.compare` (was previously `begin/end` only). Affects
118
+ interval-keyed series with same-span / different-value
119
+ intervals: previously stored in arrival order — and broke
120
+ `bisect`/`includesKey` queries — now stored in value-ascending
121
+ order. Time-keyed and timeRange-keyed series unaffected.
122
+ - **`LiveView.map(fn)` runtime check** rejects re-keying maps
123
+ that produce non-monotonic outputs. Throws `ValidationError`
124
+ at append time rather than silently breaking the view's
125
+ sorted-buffer invariant (which Tier 2 query primitives rely
126
+ on). Sane transforms (data-only maps, monotonic time-shifts)
127
+ unaffected.
128
+ - **`LiveAggregationOptions.grace`** type tightened from
129
+ `DurationInput | \`${number}${unit}\`` (redundant union) to
130
+ just `DurationInput`. No behavioral change.
131
+
132
+ ### Notes
133
+
134
+ - React package (`@pond-ts/react`) version-bumped lock-step; no
135
+ hook surface changes in this release. New core hooks
136
+ (`useLiveReduce`, `useStats`, optional-window `useEventRate`)
137
+ are queued for a follow-up — see PLAN.md for the design.
138
+ - Codex caught real bugs on every Layer-2-reviewed PR in this
139
+ wave (1 HIGH + 1 MEDIUM on PR #123, 1 HIGH + 1 MEDIUM on
140
+ PR #124, 2 MEDIUM on PR #125). The Layer 2 + Codex two-pass
141
+ protocol earned its keep again.
142
+
14
143
  ## [0.15.2] — 2026-05-06
15
144
 
16
145
  Performance fix for live rolling at firehose rates. The gRPC
@@ -108,6 +237,7 @@ compaction); any downstream code reading `#entries` directly would
108
237
  break, but those fields are private. Public APIs and types are
109
238
  unchanged.
110
239
 
240
+ [0.16.0]: https://github.com/pjm17971/pond-ts/compare/v0.15.2...v0.16.0
111
241
  [0.15.2]: https://github.com/pjm17971/pond-ts/compare/v0.15.1...v0.15.2
112
242
 
113
243
  ## [0.15.1] — 2026-05-05
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pond-ts/react",
3
- "version": "0.15.2",
3
+ "version": "0.16.0",
4
4
  "description": "React hooks for pond-ts live time series",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -31,7 +31,7 @@
31
31
  "test:runtime": "vitest run"
32
32
  },
33
33
  "peerDependencies": {
34
- "pond-ts": "^0.15.0",
34
+ "pond-ts": "^0.16.0",
35
35
  "react": "^18.0.0 || ^19.0.0"
36
36
  },
37
37
  "devDependencies": {