pond-ts 0.22.0 → 0.24.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/CHANGELOG.md +125 -1
- package/README.md +18 -14
- package/dist/batch/aggregate-columns.d.ts +0 -24
- package/dist/batch/aggregate-columns.js +47 -32
- package/dist/batch/partitioned-time-series.d.ts +4 -20
- package/dist/batch/partitioned-time-series.js +25 -67
- package/dist/batch/time-series.d.ts +11 -20
- package/dist/batch/time-series.js +154 -15
- package/dist/batch/validate.js +2 -2
- package/dist/cjs-fallback.cjs +15 -0
- package/dist/index.d.ts +1 -1
- package/dist/live/live-aggregation.d.ts +2 -2
- package/dist/live/live-partitioned-series.d.ts +8 -31
- package/dist/live/live-rolling-aggregation.d.ts +2 -2
- package/dist/live/live-series.d.ts +5 -10
- package/dist/live/live-series.js +2 -1
- package/dist/live/live-view.d.ts +5 -10
- package/dist/live/live-view.js +1 -0
- package/dist/reducers/first.js +1 -0
- package/dist/reducers/last.js +1 -0
- package/dist/reducers/types.d.ts +16 -0
- package/dist/schema/aggregate.d.ts +162 -64
- package/dist/schema/events.d.ts +10 -0
- package/dist/schema/index.d.ts +1 -2
- package/dist/schema/index.js +8 -0
- package/dist/schema/reduce.d.ts +34 -4
- package/dist/schema/rolling.d.ts +1 -1
- package/package.json +4 -3
- package/dist/batch/aggregate-columns.d.ts.map +0 -1
- package/dist/batch/aggregate-columns.js.map +0 -1
- package/dist/batch/index.d.ts.map +0 -1
- package/dist/batch/index.js.map +0 -1
- package/dist/batch/json.d.ts.map +0 -1
- package/dist/batch/json.js.map +0 -1
- package/dist/batch/operators/collapse.d.ts.map +0 -1
- package/dist/batch/operators/collapse.js.map +0 -1
- package/dist/batch/operators/cumulative.d.ts.map +0 -1
- package/dist/batch/operators/cumulative.js.map +0 -1
- package/dist/batch/operators/diff-rate.d.ts.map +0 -1
- package/dist/batch/operators/diff-rate.js.map +0 -1
- package/dist/batch/operators/fill.d.ts.map +0 -1
- package/dist/batch/operators/fill.js.map +0 -1
- package/dist/batch/operators/map.d.ts.map +0 -1
- package/dist/batch/operators/map.js.map +0 -1
- package/dist/batch/operators/shift.d.ts.map +0 -1
- package/dist/batch/operators/shift.js.map +0 -1
- package/dist/batch/partitioned-time-series.d.ts.map +0 -1
- package/dist/batch/partitioned-time-series.js.map +0 -1
- package/dist/batch/time-series.d.ts.map +0 -1
- package/dist/batch/time-series.js.map +0 -1
- package/dist/batch/validate.d.ts.map +0 -1
- package/dist/batch/validate.js.map +0 -1
- package/dist/column.d.ts.map +0 -1
- package/dist/column.js.map +0 -1
- package/dist/columnar/array-column.d.ts.map +0 -1
- package/dist/columnar/array-column.js.map +0 -1
- package/dist/columnar/builder.d.ts.map +0 -1
- package/dist/columnar/builder.js.map +0 -1
- package/dist/columnar/chunked-column.d.ts.map +0 -1
- package/dist/columnar/chunked-column.js.map +0 -1
- package/dist/columnar/column.d.ts.map +0 -1
- package/dist/columnar/column.js.map +0 -1
- package/dist/columnar/concat.d.ts.map +0 -1
- package/dist/columnar/concat.js.map +0 -1
- package/dist/columnar/index.d.ts.map +0 -1
- package/dist/columnar/index.js.map +0 -1
- package/dist/columnar/key-column.d.ts.map +0 -1
- package/dist/columnar/key-column.js.map +0 -1
- package/dist/columnar/ring-buffer.d.ts.map +0 -1
- package/dist/columnar/ring-buffer.js.map +0 -1
- package/dist/columnar/scatter.d.ts.map +0 -1
- package/dist/columnar/scatter.js.map +0 -1
- package/dist/columnar/store.d.ts.map +0 -1
- package/dist/columnar/store.js.map +0 -1
- package/dist/columnar/string-column.d.ts.map +0 -1
- package/dist/columnar/string-column.js.map +0 -1
- package/dist/columnar/types.d.ts.map +0 -1
- package/dist/columnar/types.js.map +0 -1
- package/dist/columnar/validity.d.ts.map +0 -1
- package/dist/columnar/validity.js.map +0 -1
- package/dist/columnar/view.d.ts.map +0 -1
- package/dist/columnar/view.js.map +0 -1
- package/dist/core/calendar.d.ts.map +0 -1
- package/dist/core/calendar.js.map +0 -1
- package/dist/core/duration.d.ts.map +0 -1
- package/dist/core/duration.js.map +0 -1
- package/dist/core/errors.d.ts.map +0 -1
- package/dist/core/errors.js.map +0 -1
- package/dist/core/event.d.ts.map +0 -1
- package/dist/core/event.js.map +0 -1
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js.map +0 -1
- package/dist/core/interval.d.ts.map +0 -1
- package/dist/core/interval.js.map +0 -1
- package/dist/core/temporal.d.ts.map +0 -1
- package/dist/core/temporal.js.map +0 -1
- package/dist/core/time-range.d.ts.map +0 -1
- package/dist/core/time-range.js.map +0 -1
- package/dist/core/time.d.ts.map +0 -1
- package/dist/core/time.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/live/index.d.ts.map +0 -1
- package/dist/live/index.js.map +0 -1
- package/dist/live/live-aggregation.d.ts.map +0 -1
- package/dist/live/live-aggregation.js.map +0 -1
- package/dist/live/live-chunked-storage.d.ts.map +0 -1
- package/dist/live/live-chunked-storage.js.map +0 -1
- package/dist/live/live-fused-rolling.d.ts.map +0 -1
- package/dist/live/live-fused-rolling.js.map +0 -1
- package/dist/live/live-history.d.ts.map +0 -1
- package/dist/live/live-history.js.map +0 -1
- package/dist/live/live-partitioned-fused-rolling.d.ts.map +0 -1
- package/dist/live/live-partitioned-fused-rolling.js.map +0 -1
- package/dist/live/live-partitioned-series.d.ts.map +0 -1
- package/dist/live/live-partitioned-series.js.map +0 -1
- package/dist/live/live-partitioned-sync-rolling.d.ts.map +0 -1
- package/dist/live/live-partitioned-sync-rolling.js.map +0 -1
- package/dist/live/live-reduce.d.ts.map +0 -1
- package/dist/live/live-reduce.js.map +0 -1
- package/dist/live/live-rolling-aggregation.d.ts.map +0 -1
- package/dist/live/live-rolling-aggregation.js.map +0 -1
- package/dist/live/live-series.d.ts.map +0 -1
- package/dist/live/live-series.js.map +0 -1
- package/dist/live/live-storage.d.ts.map +0 -1
- package/dist/live/live-storage.js.map +0 -1
- package/dist/live/live-view.d.ts.map +0 -1
- package/dist/live/live-view.js.map +0 -1
- package/dist/live/series-store.d.ts.map +0 -1
- package/dist/live/series-store.js.map +0 -1
- package/dist/live/triggers.d.ts.map +0 -1
- package/dist/live/triggers.js.map +0 -1
- package/dist/reducers/avg.d.ts.map +0 -1
- package/dist/reducers/avg.js.map +0 -1
- package/dist/reducers/count.d.ts.map +0 -1
- package/dist/reducers/count.js.map +0 -1
- package/dist/reducers/difference.d.ts.map +0 -1
- package/dist/reducers/difference.js.map +0 -1
- package/dist/reducers/first.d.ts.map +0 -1
- package/dist/reducers/first.js.map +0 -1
- package/dist/reducers/index.d.ts.map +0 -1
- package/dist/reducers/index.js.map +0 -1
- package/dist/reducers/keep.d.ts.map +0 -1
- package/dist/reducers/keep.js.map +0 -1
- package/dist/reducers/last.d.ts.map +0 -1
- package/dist/reducers/last.js.map +0 -1
- package/dist/reducers/max.d.ts.map +0 -1
- package/dist/reducers/max.js.map +0 -1
- package/dist/reducers/median.d.ts.map +0 -1
- package/dist/reducers/median.js.map +0 -1
- package/dist/reducers/min.d.ts.map +0 -1
- package/dist/reducers/min.js.map +0 -1
- package/dist/reducers/percentile.d.ts.map +0 -1
- package/dist/reducers/percentile.js.map +0 -1
- package/dist/reducers/rolling.d.ts.map +0 -1
- package/dist/reducers/rolling.js.map +0 -1
- package/dist/reducers/samples.d.ts.map +0 -1
- package/dist/reducers/samples.js.map +0 -1
- package/dist/reducers/stdev.d.ts.map +0 -1
- package/dist/reducers/stdev.js.map +0 -1
- package/dist/reducers/sum.d.ts.map +0 -1
- package/dist/reducers/sum.js.map +0 -1
- package/dist/reducers/top.d.ts.map +0 -1
- package/dist/reducers/top.js.map +0 -1
- package/dist/reducers/types.d.ts.map +0 -1
- package/dist/reducers/types.js.map +0 -1
- package/dist/reducers/unique.d.ts.map +0 -1
- package/dist/reducers/unique.js.map +0 -1
- package/dist/schema/aggregate.d.ts.map +0 -1
- package/dist/schema/aggregate.js.map +0 -1
- package/dist/schema/diff.d.ts.map +0 -1
- package/dist/schema/diff.js.map +0 -1
- package/dist/schema/events.d.ts.map +0 -1
- package/dist/schema/events.js.map +0 -1
- package/dist/schema/index.d.ts.map +0 -1
- package/dist/schema/index.js.map +0 -1
- package/dist/schema/join.d.ts.map +0 -1
- package/dist/schema/join.js.map +0 -1
- package/dist/schema/json.d.ts.map +0 -1
- package/dist/schema/json.js.map +0 -1
- package/dist/schema/public.d.ts.map +0 -1
- package/dist/schema/public.js.map +0 -1
- package/dist/schema/reduce.d.ts.map +0 -1
- package/dist/schema/reduce.js.map +0 -1
- package/dist/schema/reshape.d.ts.map +0 -1
- package/dist/schema/reshape.js.map +0 -1
- package/dist/schema/rolling.d.ts.map +0 -1
- package/dist/schema/rolling.js.map +0 -1
- package/dist/schema/series.d.ts.map +0 -1
- package/dist/schema/series.js.map +0 -1
- package/dist/sequence/bounded-sequence.d.ts.map +0 -1
- package/dist/sequence/bounded-sequence.js.map +0 -1
- package/dist/sequence/index.d.ts.map +0 -1
- package/dist/sequence/index.js.map +0 -1
- package/dist/sequence/sample.d.ts.map +0 -1
- package/dist/sequence/sample.js.map +0 -1
- package/dist/sequence/sequence.d.ts.map +0 -1
- package/dist/sequence/sequence.js.map +0 -1
|
@@ -12,7 +12,7 @@ import { TimeRange } from '../core/time-range.js';
|
|
|
12
12
|
import { compareEventKeys } from '../core/temporal.js';
|
|
13
13
|
import { PartitionedTimeSeries } from './partitioned-time-series.js';
|
|
14
14
|
import { Sequence } from '../sequence/sequence.js';
|
|
15
|
-
import { IntervalKeyColumn, TimeKeyColumn, TimeRangeKeyColumn, float64ColumnFromArray, stringColumnFromArray, withColumnsRenamed, withColumnsSelected, withKeyColumn, withRowRange, } from '../columnar/index.js';
|
|
15
|
+
import { IntervalKeyColumn, TimeKeyColumn, TimeRangeKeyColumn, float64ColumnFromArray, stringColumnFromArray, withColumnsRenamed, withColumnsSelected, withKeyColumn, withRowRange, withRowSelection, } from '../columnar/index.js';
|
|
16
16
|
import { SeriesStore } from '../live/series-store.js';
|
|
17
17
|
import { parseDuration } from '../core/duration.js';
|
|
18
18
|
import { resolveReducer, } from '../reducers/index.js';
|
|
@@ -468,6 +468,7 @@ export class TimeSeries {
|
|
|
468
468
|
name: input.name,
|
|
469
469
|
schema: input.schema,
|
|
470
470
|
rows: parseJsonRows(input.schema, input.rows, input.parse),
|
|
471
|
+
sort: input.sort ?? false,
|
|
471
472
|
});
|
|
472
473
|
}
|
|
473
474
|
/**
|
|
@@ -587,13 +588,21 @@ export class TimeSeries {
|
|
|
587
588
|
}
|
|
588
589
|
else {
|
|
589
590
|
this.schema = Object.freeze(input.schema.slice());
|
|
591
|
+
// `{ sort: true }` sorts unsorted input by key before intake (otherwise
|
|
592
|
+
// the intake's non-decreasing-order check throws). Stable, so rows with
|
|
593
|
+
// equal keys keep their input order; same key comparator as
|
|
594
|
+
// `fromEvents` / `concat`. Copies the array — the caller's `rows` is not
|
|
595
|
+
// mutated.
|
|
596
|
+
const rows = input.sort
|
|
597
|
+
? [...input.rows].sort((a, b) => compareEventKeys(toKey(a[0]), toKey(b[0])))
|
|
598
|
+
: input.rows;
|
|
590
599
|
// `SeriesStore.fromValidatedRows` runs the column-native
|
|
591
600
|
// intake (`validateAndNormalizeColumnar`) — same validation
|
|
592
601
|
// rules as the pre-2a row-shape `validateAndNormalize` but
|
|
593
602
|
// writes directly into columnar buffers without allocating
|
|
594
603
|
// Event objects + frozen data dicts. Events lazy-materialize
|
|
595
604
|
// on first `eventAt(i)` access via the store's per-row cache.
|
|
596
|
-
this.#store = SeriesStore.fromValidatedRows(this.schema,
|
|
605
|
+
this.#store = SeriesStore.fromValidatedRows(this.schema, rows);
|
|
597
606
|
}
|
|
598
607
|
Object.freeze(this);
|
|
599
608
|
}
|
|
@@ -701,6 +710,98 @@ export class TimeSeries {
|
|
|
701
710
|
};
|
|
702
711
|
return new TimeSeries(trustedInput);
|
|
703
712
|
}
|
|
713
|
+
/**
|
|
714
|
+
* @internal Per-row partition-key encoder, mirroring the (removed)
|
|
715
|
+
* event-based `partitionKeyOf` exactly: single column → `String(value)`,
|
|
716
|
+
* or `' undefined'` (leading space, so it can't collide with the literal
|
|
717
|
+
* string `'undefined'`) for a missing cell; composite → `JSON.stringify`
|
|
718
|
+
* of the cells with a `?? null` fallback. Reads cells by index off the
|
|
719
|
+
* store — no event materialization; array cells stringify as the event
|
|
720
|
+
* path did. Shared by `_partitionByColumns` and `_distinctPartitionKeys`
|
|
721
|
+
* so the encoding can't drift between the split and the declared-`groups`
|
|
722
|
+
* membership check.
|
|
723
|
+
*/
|
|
724
|
+
#partitionKeyEncoder(by) {
|
|
725
|
+
const store = this.#store.store;
|
|
726
|
+
if (by.length === 1) {
|
|
727
|
+
// Single-column fast path — no per-row array allocation.
|
|
728
|
+
const col = store.columns.get(by[0]);
|
|
729
|
+
return (i) => {
|
|
730
|
+
const value = col.read(i);
|
|
731
|
+
return value === undefined ? ' undefined' : `${String(value)}`;
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
const cols = by.map((name) => store.columns.get(name));
|
|
735
|
+
const parts = new Array(cols.length);
|
|
736
|
+
return (i) => {
|
|
737
|
+
for (let c = 0; c < cols.length; c += 1) {
|
|
738
|
+
parts[c] = cols[c].read(i) ?? null;
|
|
739
|
+
}
|
|
740
|
+
return JSON.stringify(parts);
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* @internal Columnar partition split — groups row indices by the partition
|
|
745
|
+
* key (see {@link TimeSeries.#partitionKeyEncoder}), gathers each group via
|
|
746
|
+
* `withRowSelection`, and wraps it as a trusted-store `TimeSeries`, with
|
|
747
|
+
* **no event materialization**. The columnar dual of the old
|
|
748
|
+
* `fromEvents`-per-bucket split that `PartitionedTimeSeries` paid through
|
|
749
|
+
* `this.events`. First-encountered partition order is preserved (Map
|
|
750
|
+
* insertion order), matching the previous `bucketByPartition`.
|
|
751
|
+
*
|
|
752
|
+
* **Identity note:** each sub-series lazily materializes its own `Event`
|
|
753
|
+
* objects from the gathered store — it does NOT reuse the source's `Event`
|
|
754
|
+
* instances (the old `fromEvents` path did). Cell values are identical;
|
|
755
|
+
* only object identity differs, and only for the no-transform paths
|
|
756
|
+
* (`toMap()` / `apply(g => g)`). `collect()` returns the source unchanged,
|
|
757
|
+
* so it is unaffected. This is the deliberate cost of skipping
|
|
758
|
+
* materialization.
|
|
759
|
+
*
|
|
760
|
+
* Used by `PartitionedTimeSeries` (`collect` / sugar via `applyToSource`,
|
|
761
|
+
* and `toMap`).
|
|
762
|
+
*/
|
|
763
|
+
_partitionByColumns(by) {
|
|
764
|
+
const columnarStore = this.#store.store;
|
|
765
|
+
const length = columnarStore.length;
|
|
766
|
+
const encode = this.#partitionKeyEncoder(by);
|
|
767
|
+
const groups = new Map();
|
|
768
|
+
for (let i = 0; i < length; i += 1) {
|
|
769
|
+
const key = encode(i);
|
|
770
|
+
let indices = groups.get(key);
|
|
771
|
+
if (indices === undefined) {
|
|
772
|
+
indices = [];
|
|
773
|
+
groups.set(key, indices);
|
|
774
|
+
}
|
|
775
|
+
indices.push(i);
|
|
776
|
+
}
|
|
777
|
+
const result = new Map();
|
|
778
|
+
for (const [key, rowIndices] of groups) {
|
|
779
|
+
const sub = withRowSelection(columnarStore, new Int32Array(rowIndices));
|
|
780
|
+
result.set(key, TimeSeries.#fromTrustedStore(this.name, this.schema, sub));
|
|
781
|
+
}
|
|
782
|
+
return result;
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* @internal Distinct partition keys in first-encountered order, encoded by
|
|
786
|
+
* {@link TimeSeries.#partitionKeyEncoder} (identical to
|
|
787
|
+
* `_partitionByColumns`). Scans the partition columns off the store — no
|
|
788
|
+
* event materialization. Used by `PartitionedTimeSeries`'s declared-`groups`
|
|
789
|
+
* membership check so that path is materialization-free too.
|
|
790
|
+
*/
|
|
791
|
+
_distinctPartitionKeys(by) {
|
|
792
|
+
const length = this.#store.store.length;
|
|
793
|
+
const encode = this.#partitionKeyEncoder(by);
|
|
794
|
+
const seen = new Set();
|
|
795
|
+
const keys = [];
|
|
796
|
+
for (let i = 0; i < length; i += 1) {
|
|
797
|
+
const key = encode(i);
|
|
798
|
+
if (!seen.has(key)) {
|
|
799
|
+
seen.add(key);
|
|
800
|
+
keys.push(key);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return keys;
|
|
804
|
+
}
|
|
704
805
|
/**
|
|
705
806
|
* Example: `series.events`. Returns the full event array.
|
|
706
807
|
*
|
|
@@ -782,14 +883,18 @@ export class TimeSeries {
|
|
|
782
883
|
* series.events[i]` holds whenever both are accessed.
|
|
783
884
|
*/
|
|
784
885
|
at(index) {
|
|
785
|
-
//
|
|
786
|
-
//
|
|
787
|
-
// `#store.eventAt
|
|
788
|
-
//
|
|
789
|
-
//
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
886
|
+
// Non-integer / NaN inputs return undefined rather than throwing
|
|
887
|
+
// downstream from `#store.eventAt` (`this.events[NaN]` returned undefined
|
|
888
|
+
// per JS array semantics; the direct route to `#store.eventAt(NaN)` would
|
|
889
|
+
// proceed past the bounds check and materialize a key at an invalid row).
|
|
890
|
+
// Closed Codex round 4's medium finding on PR #150.
|
|
891
|
+
if (!Number.isInteger(index))
|
|
892
|
+
return undefined;
|
|
893
|
+
// Negative indices count from the end — parity with `LiveSeries.at` and
|
|
894
|
+
// `Array.prototype.at` (`at(-1)` is the last event).
|
|
895
|
+
if (index < 0)
|
|
896
|
+
index += this.#store.length;
|
|
897
|
+
if (index < 0 || index >= this.#store.length) {
|
|
793
898
|
return undefined;
|
|
794
899
|
}
|
|
795
900
|
return this.#store.eventAt(index);
|
|
@@ -1292,7 +1397,8 @@ export class TimeSeries {
|
|
|
1292
1397
|
}
|
|
1293
1398
|
pivotByGroup(groupCol, valueCol, options = {}) {
|
|
1294
1399
|
if (this.schema[0].kind !== 'time') {
|
|
1295
|
-
throw new TypeError(`pivotByGroup requires a time-keyed series; got ${this.schema[0].kind}`
|
|
1400
|
+
throw new TypeError(`pivotByGroup requires a time-keyed series; got ${this.schema[0].kind}` +
|
|
1401
|
+
` — piping from aggregate/materialize? call .asTime({ at: 'begin' }) first`);
|
|
1296
1402
|
}
|
|
1297
1403
|
const valueColumnDef = this.schema.find((c) => c.name === valueCol);
|
|
1298
1404
|
if (!valueColumnDef) {
|
|
@@ -2387,12 +2493,37 @@ export class TimeSeries {
|
|
|
2387
2493
|
}
|
|
2388
2494
|
/** Example: `series.timeRange()`. Returns the overall temporal extent of the series, if the series is not empty. */
|
|
2389
2495
|
timeRange() {
|
|
2390
|
-
|
|
2391
|
-
|
|
2496
|
+
// Columnar key-axis read. The old implementation reduced over
|
|
2497
|
+
// `this.events`, materializing every Event (the ~495 ns/row + heap
|
|
2498
|
+
// tax) on every call — including the cold `aggregate()` default
|
|
2499
|
+
// range, which erased the 3B fast-path win for one-shot pipelines.
|
|
2500
|
+
const key = this.keyColumn();
|
|
2501
|
+
const n = key.length;
|
|
2502
|
+
if (n === 0) {
|
|
2392
2503
|
return undefined;
|
|
2393
2504
|
}
|
|
2394
|
-
|
|
2395
|
-
|
|
2505
|
+
// `begin` is sorted non-decreasing (the intake invariant) for every
|
|
2506
|
+
// key kind, so the minimum start is always `begin[0]`.
|
|
2507
|
+
const start = key.begin[0];
|
|
2508
|
+
let end;
|
|
2509
|
+
if (key.kind === 'time') {
|
|
2510
|
+
// Point-in-time keys: `end === begin`, and begin is sorted, so the
|
|
2511
|
+
// maximum end is the final begin. O(1).
|
|
2512
|
+
end = key.begin[n - 1];
|
|
2513
|
+
}
|
|
2514
|
+
else {
|
|
2515
|
+
// Range / interval keys: `begin[i] <= end[i]` per row, but `end` is
|
|
2516
|
+
// NOT monotonic (a long early event can outlast the final row), so
|
|
2517
|
+
// the max end needs a scan — a typed-array scan, not Event
|
|
2518
|
+
// materialization. Seeds with `end[0]` and maxes the rest, matching
|
|
2519
|
+
// the old `reduce` seeded at `first.end()`.
|
|
2520
|
+
const ends = key.end;
|
|
2521
|
+
end = ends[0];
|
|
2522
|
+
for (let i = 1; i < n; i += 1) {
|
|
2523
|
+
if (ends[i] > end)
|
|
2524
|
+
end = ends[i];
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2396
2527
|
return new TimeRange({ start, end });
|
|
2397
2528
|
}
|
|
2398
2529
|
/** Example: `series.overlaps(range)`. Returns `true` when the overall series extent overlaps the supplied temporal value. */
|
|
@@ -2826,6 +2957,12 @@ export class TimeSeries {
|
|
|
2826
2957
|
rollingOptions.alignment = alignment;
|
|
2827
2958
|
if (minSamples !== undefined)
|
|
2828
2959
|
rollingOptions.minSamples = minSamples;
|
|
2960
|
+
// Trust boundary: a generic mapping can't prove it satisfies the
|
|
2961
|
+
// public overload's ValidatedAggregateMap constraint (S is
|
|
2962
|
+
// unresolved here), so route through the broad-schema escape hatch
|
|
2963
|
+
// — for concrete SeriesSchema the constraint degrades to the
|
|
2964
|
+
// permissive AggregateMap by design. The computed spec keys are
|
|
2965
|
+
// collision-checked above.
|
|
2829
2966
|
const rolling = this.rolling(window, {
|
|
2830
2967
|
[avgName]: { from: col, using: 'avg' },
|
|
2831
2968
|
[sdName]: { from: col, using: 'stdev' },
|
|
@@ -2920,6 +3057,8 @@ export class TimeSeries {
|
|
|
2920
3057
|
rollingOptions.alignment = alignment;
|
|
2921
3058
|
if (minSamples !== undefined)
|
|
2922
3059
|
rollingOptions.minSamples = minSamples;
|
|
3060
|
+
// Trust boundary: see baseline() above — generic mapping routed
|
|
3061
|
+
// through the broad-schema escape hatch of ValidatedAggregateMap.
|
|
2923
3062
|
const rolling = this.rolling(window, rollingMapping, rollingOptions);
|
|
2924
3063
|
const kept = [];
|
|
2925
3064
|
for (let i = 0; i < this.events.length; i += 1) {
|
package/dist/batch/validate.js
CHANGED
|
@@ -376,11 +376,11 @@ export function validateAndNormalizeColumnar(input) {
|
|
|
376
376
|
const prevBegin = beginBuf[i - 1];
|
|
377
377
|
const curBegin = beginBuf[i];
|
|
378
378
|
if (prevBegin > curBegin) {
|
|
379
|
-
throw new ValidationError(`row ${i} is out of order`);
|
|
379
|
+
throw new ValidationError(`row ${i} is out of order — keys must be non-decreasing; pass { sort: true } to sort rows on construction, or pre-sort them`);
|
|
380
380
|
}
|
|
381
381
|
if (prevBegin === curBegin && endBuf !== beginBuf) {
|
|
382
382
|
if (endBuf[i - 1] > endBuf[i]) {
|
|
383
|
-
throw new ValidationError(`row ${i} is out of order`);
|
|
383
|
+
throw new ValidationError(`row ${i} is out of order — keys must be non-decreasing; pass { sort: true } to sort rows on construction, or pre-sort them`);
|
|
384
384
|
}
|
|
385
385
|
}
|
|
386
386
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// pond-ts ships as ES modules only. This stub is the `require` target in the
|
|
4
|
+
// package's `exports` map so that CommonJS consumers get a clear, actionable
|
|
5
|
+
// error instead of Node's cryptic `ERR_PACKAGE_PATH_NOT_EXPORTED`.
|
|
6
|
+
//
|
|
7
|
+
// It is copied verbatim into `dist/` during `prepack` (see package.json) so it
|
|
8
|
+
// rides along in the published tarball; the source of truth lives at the
|
|
9
|
+
// package root and is never touched by `tsc`.
|
|
10
|
+
|
|
11
|
+
throw new Error(
|
|
12
|
+
'pond-ts is an ES module package and cannot be loaded with require(). ' +
|
|
13
|
+
"Use `import { TimeSeries } from 'pond-ts'` instead, or a dynamic " +
|
|
14
|
+
"`await import('pond-ts')` from CommonJS. See https://nodejs.org/api/esm.html.",
|
|
15
|
+
);
|
package/dist/index.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export { ArrayColumn } from './columnar/array-column.js';
|
|
|
29
29
|
export { ChunkedArrayColumn, ChunkedBooleanColumn, ChunkedFloat64Column, ChunkedStringColumn, } from './columnar/chunked-column.js';
|
|
30
30
|
export { type IntervalLabelKind, type KeyColumn, IntervalKeyColumn, TimeKeyColumn, TimeRangeKeyColumn, } from './columnar/key-column.js';
|
|
31
31
|
export { type ValidityBitmap } from './columnar/validity.js';
|
|
32
|
-
export type { AlignSchema, ArrayColumnNameForSchema, BaselineSchema, AggregateFunction, AggregateReducer, AggregateOutputMap, AggregateOutputSpec, AggregateMap, AggregateSchema, ColumnDef, CollapseData, ArrayAggregateAppendSchema, ArrayAggregateKind, ArrayAggregateReplaceSchema, ArrayExplodeAppendSchema, ArrayExplodeReplaceSchema, CollapseSchema, DedupeKeep, EventDataForSchema, EventForSchema, EventKeyForKind, FillMapping, FillStrategy, MaterializeSchema, EventKeyForSchema, FirstColKind, FirstColumn, IntervalKeyedSchema, JsonIntervalInput, JsonObjectRowForSchema, JsonRowFormat, JsonRowForSchema, JsonTimeRangeInput, JsonTimestampInput, JsonValueForKind, RollingAlignment, RollingSchema, JoinConflictMode, JoinManySchema, PrefixedJoinManySchema, PrefixedJoinSchema, LiveSource, JoinType, JoinSchema, NormalizedRowForSchema, NormalizedObjectRowForSchema, NormalizedObjectRow, NormalizedValueForKind, ReduceResult, RenameData, RenameMap, RenameSchema, RekeySchema, RowForSchema, ArrayValue, ColumnValue, ScalarKind, ScalarValue, CustomAggregateReducer, DiffSchema, NumericColumnNameForSchema, SmoothMethod, SmoothAppendSchema, SmoothSchema, SelectData, SelectSchema, SeriesSchema, TimeKeyedSchema, TimeSeriesInput, TimeSeriesJsonInput, TimeRangeKeyedSchema, ValueColumnsForSchema, ValueColumn, ValueForKind, } from './schema/index.js';
|
|
32
|
+
export type { AlignSchema, ArrayColumnNameForSchema, BaselineSchema, AggregateFunction, AggregateReducer, AggregateOutputMap, AggregateOutputSpec, AggregateMap, AggregateSchema, ValidatedAggregateMap, ColumnDef, CollapseData, ArrayAggregateAppendSchema, ArrayAggregateKind, ArrayAggregateReplaceSchema, ArrayExplodeAppendSchema, ArrayExplodeReplaceSchema, CollapseSchema, DedupeKeep, EventDataForSchema, EventForSchema, EventKeyForKind, FillMapping, FillStrategy, MaterializeSchema, EventKeyForSchema, FirstColKind, FirstColumn, IntervalKeyedSchema, JsonIntervalInput, JsonObjectRowForSchema, JsonRowFormat, JsonRowForSchema, JsonTimeRangeInput, JsonTimestampInput, JsonValueForKind, RollingAlignment, RollingSchema, JoinConflictMode, JoinManySchema, PrefixedJoinManySchema, PrefixedJoinSchema, LiveSource, JoinType, JoinSchema, NormalizedRowForSchema, NormalizedObjectRowForSchema, NormalizedObjectRow, NormalizedValueForKind, ReduceResult, RenameData, RenameMap, RenameSchema, RekeySchema, RowForSchema, ArrayValue, ColumnValue, ScalarKind, ScalarValue, CustomAggregateReducer, DiffSchema, NumericColumnNameForSchema, SmoothMethod, SmoothAppendSchema, SmoothSchema, SelectData, SelectSchema, SeriesSchema, TimeKeyedSchema, TimeSeriesInput, TimeSeriesJsonInput, TimeRangeKeyedSchema, ValueColumnsForSchema, ValueColumn, ValueForKind, } from './schema/index.js';
|
|
33
33
|
export type { CalendarOptions, CalendarUnit, TimeZoneOptions, } from './core/calendar.js';
|
|
34
34
|
export type { EventKey, IntervalInput, IntervalValue, TemporalLike, TimeRangeInput, TimestampInput, } from './core/temporal.js';
|
|
35
35
|
export type { DurationInput } from './core/duration.js';
|
|
@@ -4,7 +4,7 @@ import { LiveView, type LiveFillMapping, type LiveFillStrategy } from './live-vi
|
|
|
4
4
|
import { LiveRollingAggregation, type LiveRollingOptions, type RollingWindow } from './live-rolling-aggregation.js';
|
|
5
5
|
import { TimeSeries } from '../batch/time-series.js';
|
|
6
6
|
import type { Sequence } from '../sequence/sequence.js';
|
|
7
|
-
import type { AggregateMap, AggregateOutputMap, DiffSchema, EventDataForSchema, EventForSchema, LiveSource, NumericColumnNameForSchema, ColumnValue, RollingSchema, SelectSchema, SeriesSchema } from '../schema/index.js';
|
|
7
|
+
import type { AggregateMap, AggregateOutputMap, DiffSchema, EventDataForSchema, EventForSchema, LiveSource, NumericColumnNameForSchema, ColumnValue, RollingSchema, SelectSchema, SeriesSchema, ValidatedAggregateMap } from '../schema/index.js';
|
|
8
8
|
import type { RollingOutputMapSchema } from '../schema/index.js';
|
|
9
9
|
import type { DurationInput } from '../core/duration.js';
|
|
10
10
|
type ClosedEvent = Event<Interval, Record<string, ColumnValue | undefined>>;
|
|
@@ -48,7 +48,7 @@ export declare class LiveAggregation<S extends SeriesSchema, Out extends SeriesS
|
|
|
48
48
|
cumulative<const Targets extends NumericColumnNameForSchema<Out>>(spec: {
|
|
49
49
|
[K in Targets]: 'sum' | 'max' | 'min' | 'count' | ((acc: number, value: number) => number);
|
|
50
50
|
}): LiveView<DiffSchema<Out, Targets>>;
|
|
51
|
-
rolling<const M extends
|
|
51
|
+
rolling<const M extends ValidatedAggregateMap<Out, M>>(windowSize: RollingWindow, mapping: M, options?: LiveRollingOptions): LiveRollingAggregation<Out, RollingSchema<Out, M>>;
|
|
52
52
|
rolling<const M extends AggregateOutputMap<Out>>(windowSize: RollingWindow, mapping: M, options?: LiveRollingOptions): LiveRollingAggregation<Out, RollingOutputMapSchema<Out, M>>;
|
|
53
53
|
/**
|
|
54
54
|
* Pipeline stats snapshot — cumulative counters since
|
|
@@ -4,9 +4,8 @@ import { LivePartitionedFusedRolling } from './live-partitioned-fused-rolling.js
|
|
|
4
4
|
import type { SampleStrategy } from '../sequence/sample.js';
|
|
5
5
|
import { type LiveFillMapping, type LiveFillStrategy } from './live-view.js';
|
|
6
6
|
import type { Trigger } from './triggers.js';
|
|
7
|
-
import { type
|
|
8
|
-
import type {
|
|
9
|
-
import type { FusedMapping, FusedMappingValid, FusedPartitionedRollingSchema } from '../schema/index.js';
|
|
7
|
+
import { type DiffSchema, type EventDataForSchema, type LiveSource, type NumericColumnNameForSchema, type RollingSchema, type SeriesSchema } from '../schema/index.js';
|
|
8
|
+
import type { FusedMapping, FusedMappingValid, FusedPartitionedRollingSchema, ValidatedAggregateMap } from '../schema/index.js';
|
|
10
9
|
import type { DurationInput } from '../core/duration.js';
|
|
11
10
|
import type { LiveRollingOptions, RollingWindow } from './live-rolling-aggregation.js';
|
|
12
11
|
/**
|
|
@@ -252,28 +251,17 @@ export declare class LivePartitionedSeries<S extends SeriesSchema, K extends str
|
|
|
252
251
|
* );
|
|
253
252
|
* ```
|
|
254
253
|
*/
|
|
255
|
-
rolling<const M extends
|
|
254
|
+
rolling<const M extends ValidatedAggregateMap<S, M>>(window: RollingWindow, mapping: M, options?: LiveRollingOptions & {
|
|
256
255
|
trigger?: {
|
|
257
256
|
kind: 'event' | 'count';
|
|
258
257
|
};
|
|
259
258
|
}): LivePartitionedView<S, RollingSchema<S, M>, K, ByCol>;
|
|
260
|
-
rolling<const M extends
|
|
261
|
-
trigger?: {
|
|
262
|
-
kind: 'event' | 'count';
|
|
263
|
-
};
|
|
264
|
-
}): LivePartitionedView<S, RollingOutputMapSchema<S, M>, K, ByCol>;
|
|
265
|
-
rolling<const M extends AggregateMap<S>>(window: RollingWindow, mapping: M, options: LiveRollingOptions & {
|
|
266
|
-
trigger: {
|
|
267
|
-
kind: 'clock';
|
|
268
|
-
} & Trigger;
|
|
269
|
-
}): LivePartitionedSyncRolling<S, K, SeriesSchema>;
|
|
270
|
-
rolling<const M extends AggregateOutputMap<S>>(window: RollingWindow, mapping: M, options: LiveRollingOptions & {
|
|
259
|
+
rolling<const M extends ValidatedAggregateMap<S, M>>(window: RollingWindow, mapping: M, options: LiveRollingOptions & {
|
|
271
260
|
trigger: {
|
|
272
261
|
kind: 'clock';
|
|
273
262
|
} & Trigger;
|
|
274
263
|
}): LivePartitionedSyncRolling<S, K, SeriesSchema>;
|
|
275
|
-
rolling<const M extends
|
|
276
|
-
rolling<const M extends AggregateOutputMap<S>>(window: RollingWindow, mapping: M, options: LiveRollingOptions): LivePartitionedView<S, RollingOutputMapSchema<S, M>, K, ByCol> | LivePartitionedSyncRolling<S, K, SeriesSchema>;
|
|
264
|
+
rolling<const M extends ValidatedAggregateMap<S, M>>(window: RollingWindow, mapping: M, options: LiveRollingOptions): LivePartitionedView<S, RollingSchema<S, M>, K, ByCol> | LivePartitionedSyncRolling<S, K, SeriesSchema>;
|
|
277
265
|
/**
|
|
278
266
|
* Keyed-form fused multi-window partitioned rolling. Maintains N
|
|
279
267
|
* windows per partition in a single ingest pass over a single
|
|
@@ -437,28 +425,17 @@ export declare class LivePartitionedView<SBase extends SeriesSchema, R extends S
|
|
|
437
425
|
* partition column with a passthrough reducer (e.g.
|
|
438
426
|
* `host: 'last'`) to keep it visible in the unified output.
|
|
439
427
|
*/
|
|
440
|
-
rolling<const M extends
|
|
428
|
+
rolling<const M extends ValidatedAggregateMap<R, M>>(window: RollingWindow, mapping: M, options?: LiveRollingOptions & {
|
|
441
429
|
trigger?: {
|
|
442
430
|
kind: 'event' | 'count';
|
|
443
431
|
};
|
|
444
432
|
}): LivePartitionedView<SBase, RollingSchema<R, M>, K, ByCol>;
|
|
445
|
-
rolling<const M extends
|
|
446
|
-
trigger?: {
|
|
447
|
-
kind: 'event' | 'count';
|
|
448
|
-
};
|
|
449
|
-
}): LivePartitionedView<SBase, RollingOutputMapSchema<R, M>, K, ByCol>;
|
|
450
|
-
rolling<const M extends AggregateMap<R>>(window: RollingWindow, mapping: M, options: LiveRollingOptions & {
|
|
451
|
-
trigger: {
|
|
452
|
-
kind: 'clock';
|
|
453
|
-
} & Trigger;
|
|
454
|
-
}): LivePartitionedSyncRolling<R, K, SeriesSchema>;
|
|
455
|
-
rolling<const M extends AggregateOutputMap<R>>(window: RollingWindow, mapping: M, options: LiveRollingOptions & {
|
|
433
|
+
rolling<const M extends ValidatedAggregateMap<R, M>>(window: RollingWindow, mapping: M, options: LiveRollingOptions & {
|
|
456
434
|
trigger: {
|
|
457
435
|
kind: 'clock';
|
|
458
436
|
} & Trigger;
|
|
459
437
|
}): LivePartitionedSyncRolling<R, K, SeriesSchema>;
|
|
460
|
-
rolling<const M extends
|
|
461
|
-
rolling<const M extends AggregateOutputMap<R>>(window: RollingWindow, mapping: M, options: LiveRollingOptions): LivePartitionedView<SBase, RollingOutputMapSchema<R, M>, K, ByCol> | LivePartitionedSyncRolling<R, K, SeriesSchema>;
|
|
438
|
+
rolling<const M extends ValidatedAggregateMap<R, M>>(window: RollingWindow, mapping: M, options: LiveRollingOptions): LivePartitionedView<SBase, RollingSchema<R, M>, K, ByCol> | LivePartitionedSyncRolling<R, K, SeriesSchema>;
|
|
462
439
|
/**
|
|
463
440
|
* Keyed-form fused multi-window rolling on a chained
|
|
464
441
|
* `LivePartitionedView`. Same shape as the root variant — each
|
|
@@ -2,7 +2,7 @@ import { LiveAggregation } from './live-aggregation.js';
|
|
|
2
2
|
import { LiveView, type LiveFillMapping, type LiveFillStrategy } from './live-view.js';
|
|
3
3
|
import type { Sequence } from '../sequence/sequence.js';
|
|
4
4
|
import { type Trigger } from './triggers.js';
|
|
5
|
-
import type { AggregateMap, AggregateOutputMap, AggregateSchema, DiffSchema, EventDataForSchema, EventForSchema, LiveSource, NumericColumnNameForSchema, SelectSchema, SeriesSchema, ColumnValue } from '../schema/index.js';
|
|
5
|
+
import type { AggregateMap, AggregateOutputMap, AggregateSchema, DiffSchema, EventDataForSchema, EventForSchema, LiveSource, NumericColumnNameForSchema, SelectSchema, SeriesSchema, ColumnValue, ValidatedAggregateMap } from '../schema/index.js';
|
|
6
6
|
import type { AggregateOutputMapResultSchema } from '../schema/index.js';
|
|
7
7
|
import type { DurationInput } from '../core/duration.js';
|
|
8
8
|
import type { RetentionPolicy } from './live-series.js';
|
|
@@ -107,7 +107,7 @@ export declare class LiveRollingAggregation<S extends SeriesSchema, Out extends
|
|
|
107
107
|
cumulative<const Targets extends NumericColumnNameForSchema<Out>>(spec: {
|
|
108
108
|
[K in Targets]: 'sum' | 'max' | 'min' | 'count' | ((acc: number, value: number) => number);
|
|
109
109
|
}): LiveView<DiffSchema<Out, Targets>>;
|
|
110
|
-
aggregate<const M extends
|
|
110
|
+
aggregate<const M extends ValidatedAggregateMap<Out, M>>(sequence: Sequence, mapping: M): LiveAggregation<Out, AggregateSchema<Out, M>>;
|
|
111
111
|
aggregate<const M extends AggregateOutputMap<Out>>(sequence: Sequence, mapping: M): LiveAggregation<Out, AggregateOutputMapResultSchema<Out, M>>;
|
|
112
112
|
/**
|
|
113
113
|
* Pipeline stats snapshot — cumulative counters since
|
|
@@ -5,12 +5,11 @@ import { LiveRollingAggregation, type LiveRollingOptions, type RollingWindow } f
|
|
|
5
5
|
import { TimeSeries, type KeyLike } from '../batch/time-series.js';
|
|
6
6
|
import type { TimeZoneOptions } from '../core/calendar.js';
|
|
7
7
|
import type { Sequence } from '../sequence/sequence.js';
|
|
8
|
-
import {
|
|
9
|
-
import type { AggregateOutputMapResultSchema, RollingOutputMapSchema } from '../schema/index.js';
|
|
8
|
+
import { type AggregateSchema, type DiffSchema, type EventDataForSchema, type EventForSchema, type JsonObjectRowForSchema, type JsonRowForSchema, type NormalizedObjectRow, type NormalizedRowForSchema, type NumericColumnNameForSchema, type RollingSchema, type RowForSchema, type SelectSchema, type SeriesSchema, type TimeSeriesJsonInput, type TimeSeriesJsonOutputArray, type TimeSeriesJsonOutputObject } from '../schema/index.js';
|
|
10
9
|
import { LiveFusedRolling } from './live-fused-rolling.js';
|
|
11
10
|
import { LiveReduce } from './live-reduce.js';
|
|
12
11
|
import type { SampleStrategy } from '../sequence/sample.js';
|
|
13
|
-
import type { FusedMapping, FusedMappingValid, FusedRollingSchema } from '../schema/index.js';
|
|
12
|
+
import type { FusedMapping, FusedMappingValid, FusedRollingSchema, ValidatedAggregateMap } from '../schema/index.js';
|
|
14
13
|
import type { DurationInput } from '../core/duration.js';
|
|
15
14
|
export type OrderingMode = 'strict' | 'drop' | 'reorder';
|
|
16
15
|
export type RetentionPolicy = {
|
|
@@ -44,7 +43,6 @@ type BatchListener<S extends SeriesSchema> = (events: ReadonlyArray<EventForSche
|
|
|
44
43
|
type EvictListener<S extends SeriesSchema> = (events: ReadonlyArray<EventForSchema<S>>) => void;
|
|
45
44
|
export declare class LiveSeries<S extends SeriesSchema> {
|
|
46
45
|
#private;
|
|
47
|
-
readonly [EMITS_EVICT]: true;
|
|
48
46
|
readonly name: string;
|
|
49
47
|
readonly schema: S;
|
|
50
48
|
constructor(options: LiveSeriesOptions<S>);
|
|
@@ -239,10 +237,8 @@ export declare class LiveSeries<S extends SeriesSchema> {
|
|
|
239
237
|
sample(strategy: SampleStrategy): LiveView<S>;
|
|
240
238
|
select<const Keys extends readonly (keyof EventDataForSchema<S>)[]>(...keys: Keys): LiveView<SelectSchema<S, Keys[number] & string>>;
|
|
241
239
|
window(size: RollingWindow): LiveView<S>;
|
|
242
|
-
aggregate<const M extends
|
|
243
|
-
|
|
244
|
-
rolling<const M extends AggregateMap<S>>(window: RollingWindow, mapping: M, options?: LiveRollingOptions): LiveRollingAggregation<S, RollingSchema<S, M>>;
|
|
245
|
-
rolling<const M extends AggregateOutputMap<S>>(window: RollingWindow, mapping: M, options?: LiveRollingOptions): LiveRollingAggregation<S, RollingOutputMapSchema<S, M>>;
|
|
240
|
+
aggregate<const M extends ValidatedAggregateMap<S, M>>(sequence: Sequence, mapping: M): LiveAggregation<S, AggregateSchema<S, M>>;
|
|
241
|
+
rolling<const M extends ValidatedAggregateMap<S, M>>(window: RollingWindow, mapping: M, options?: LiveRollingOptions): LiveRollingAggregation<S, RollingSchema<S, M>>;
|
|
246
242
|
/**
|
|
247
243
|
* Keyed-form fused multi-window rolling. Maintains N windows in
|
|
248
244
|
* one ingest pass over a single shared deque; emits one merged
|
|
@@ -278,8 +274,7 @@ export declare class LiveSeries<S extends SeriesSchema> {
|
|
|
278
274
|
* `[time, ...mappingColumns]`. Composes with the rest of the
|
|
279
275
|
* live operator surface.
|
|
280
276
|
*/
|
|
281
|
-
reduce<const M extends
|
|
282
|
-
reduce<const M extends AggregateOutputMap<S>>(mapping: M, options?: LiveRollingOptions): LiveReduce<S, RollingOutputMapSchema<S, M>>;
|
|
277
|
+
reduce<const M extends ValidatedAggregateMap<S, M>>(mapping: M, options?: LiveRollingOptions): LiveReduce<S, RollingSchema<S, M>>;
|
|
283
278
|
/**
|
|
284
279
|
* Time span of the current buffer — `last.begin() - first.begin()`
|
|
285
280
|
* in milliseconds. Returns `0` if the buffer is empty or holds a
|
package/dist/live/live-series.js
CHANGED
|
@@ -87,6 +87,7 @@ function assertCellKind(kind, value, name) {
|
|
|
87
87
|
}
|
|
88
88
|
// ── LiveSeries ──────────────────────────────────────────────────
|
|
89
89
|
export class LiveSeries {
|
|
90
|
+
/** @internal */
|
|
90
91
|
[EMITS_EVICT] = true;
|
|
91
92
|
name;
|
|
92
93
|
schema;
|
|
@@ -373,7 +374,7 @@ export class LiveSeries {
|
|
|
373
374
|
rows,
|
|
374
375
|
});
|
|
375
376
|
// INTRA-batch order is enforced by `validateAndNormalizeColumnar`
|
|
376
|
-
// above (it throws `ValidationError
|
|
377
|
+
// above (it throws a `ValidationError` naming the out-of-order row). The
|
|
377
378
|
// cross-batch boundary check + commit/fan-out live in `#commitChunk`.
|
|
378
379
|
const store = ColumnarStore.fromTrustedStore(this.schema, keys, columns);
|
|
379
380
|
this.#commitChunk(store);
|
package/dist/live/live-view.d.ts
CHANGED
|
@@ -7,9 +7,8 @@ import { TimeSeries, type KeyLike } from '../batch/time-series.js';
|
|
|
7
7
|
import type { Sequence } from '../sequence/sequence.js';
|
|
8
8
|
import { TimeKeyColumn } from '../columnar/key-column.js';
|
|
9
9
|
import type { PublicColumnForKind, KeyColumnForSchema } from '../column.js';
|
|
10
|
-
import {
|
|
11
|
-
import type {
|
|
12
|
-
import type { FusedMapping, FusedMappingValid, FusedRollingSchema } from '../schema/index.js';
|
|
10
|
+
import { type AggregateSchema, type DiffSchema, type EventDataForSchema, type EventForSchema, type LiveSource, type NumericColumnNameForSchema, type ValueColumnNameForSchema, type RollingSchema, type ScalarValue, type SelectSchema, type SeriesSchema, type ValueColumnsForSchema } from '../schema/index.js';
|
|
11
|
+
import type { FusedMapping, FusedMappingValid, FusedRollingSchema, ValidatedAggregateMap } from '../schema/index.js';
|
|
13
12
|
export type LiveFillStrategy = 'hold' | 'zero';
|
|
14
13
|
export type LiveFillMapping<S extends SeriesSchema> = {
|
|
15
14
|
[K in ValueColumnsForSchema<S>[number]['name']]?: LiveFillStrategy | ScalarValue;
|
|
@@ -40,7 +39,6 @@ type ViewOptions<S extends SeriesSchema> = {
|
|
|
40
39
|
type TimeKeyOnly<S extends SeriesSchema> = KeyColumnForSchema<S> extends TimeKeyColumn ? KeyColumnForSchema<S> : 'LiveView.keyColumn() supports time-keyed views only — use toTimeSeries() for other key kinds';
|
|
41
40
|
export declare class LiveView<S extends SeriesSchema> implements LiveSource<S> {
|
|
42
41
|
#private;
|
|
43
|
-
readonly [EMITS_EVICT]: true;
|
|
44
42
|
readonly name: string;
|
|
45
43
|
readonly schema: S;
|
|
46
44
|
constructor(source: LiveSource<any>, process: (event: any) => EventForSchema<S> | undefined, options?: ViewOptions<S>);
|
|
@@ -122,10 +120,8 @@ export declare class LiveView<S extends SeriesSchema> implements LiveSource<S> {
|
|
|
122
120
|
* is per-event derivative of the named columns.
|
|
123
121
|
*/
|
|
124
122
|
eventRate(): number;
|
|
125
|
-
aggregate<const M extends
|
|
126
|
-
|
|
127
|
-
rolling<const M extends AggregateMap<S>>(window: RollingWindow, mapping: M, options?: LiveRollingOptions): LiveRollingAggregation<S, RollingSchema<S, M>>;
|
|
128
|
-
rolling<const M extends AggregateOutputMap<S>>(window: RollingWindow, mapping: M, options?: LiveRollingOptions): LiveRollingAggregation<S, RollingOutputMapSchema<S, M>>;
|
|
123
|
+
aggregate<const M extends ValidatedAggregateMap<S, M>>(sequence: Sequence, mapping: M): LiveAggregation<S, AggregateSchema<S, M>>;
|
|
124
|
+
rolling<const M extends ValidatedAggregateMap<S, M>>(window: RollingWindow, mapping: M, options?: LiveRollingOptions): LiveRollingAggregation<S, RollingSchema<S, M>>;
|
|
129
125
|
/**
|
|
130
126
|
* Keyed-form fused multi-window rolling on a `LiveView`. See
|
|
131
127
|
* {@link LiveSeries.rolling} for the full surface — chained-from-
|
|
@@ -137,8 +133,7 @@ export declare class LiveView<S extends SeriesSchema> implements LiveSource<S> {
|
|
|
137
133
|
* Streaming reduce over the view's current buffer. See
|
|
138
134
|
* {@link LiveSeries.reduce} for the full surface.
|
|
139
135
|
*/
|
|
140
|
-
reduce<const M extends
|
|
141
|
-
reduce<const M extends AggregateOutputMap<S>>(mapping: M, options?: LiveRollingOptions): LiveReduce<S, RollingOutputMapSchema<S, M>>;
|
|
136
|
+
reduce<const M extends ValidatedAggregateMap<S, M>>(mapping: M, options?: LiveRollingOptions): LiveReduce<S, RollingSchema<S, M>>;
|
|
142
137
|
diff<const Target extends NumericColumnNameForSchema<S>>(columns: Target | readonly Target[], options?: {
|
|
143
138
|
drop?: boolean;
|
|
144
139
|
}): LiveView<DiffSchema<S, Target>>;
|
package/dist/live/live-view.js
CHANGED
package/dist/reducers/first.js
CHANGED
package/dist/reducers/last.js
CHANGED
package/dist/reducers/types.d.ts
CHANGED
|
@@ -85,6 +85,22 @@ export type ReducerDef = {
|
|
|
85
85
|
* `reduceColumn` may assume the column is a packed `Float64Column`.
|
|
86
86
|
*/
|
|
87
87
|
reduceColumn?(col: Float64Column): ColumnValue | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* **Columnar fast-path for boundary selectors.** Present only on
|
|
90
|
+
* `first` / `last`. Marks the reducer as "pick the {first|last}
|
|
91
|
+
* *defined* value in the bucket" — which a columnar caller can compute
|
|
92
|
+
* as a boundary scan over the source column (via `col.read(i)`, any
|
|
93
|
+
* kind / any storage) instead of bailing the whole call to the row
|
|
94
|
+
* path just because these reducers lack a numeric `reduceColumn`.
|
|
95
|
+
*
|
|
96
|
+
* Semantics match `reduce` / `bucketState` exactly: scan past *missing*
|
|
97
|
+
* cells to the first/last cell whose `read(i)` is not `undefined`; an
|
|
98
|
+
* all-missing or empty bucket yields `undefined`. This is what lets the
|
|
99
|
+
* partitioned-`aggregate` fast path run — the auto-injected
|
|
100
|
+
* partition-column reducer is `'first'` (see `PartitionedTimeSeries`),
|
|
101
|
+
* which previously tripped the all-or-nothing gate for every call.
|
|
102
|
+
*/
|
|
103
|
+
definedBoundary?: 'first' | 'last';
|
|
88
104
|
/** Return a fresh incremental state for one aggregation bucket. */
|
|
89
105
|
bucketState(): AggregateBucketState;
|
|
90
106
|
/** Return a fresh incremental state for one rolling window column. */
|