pond-ts 0.8.2 → 0.9.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.
@@ -0,0 +1,192 @@
1
+ import { TimeSeries } from './TimeSeries.js';
2
+ import type { BoundedSequence } from './BoundedSequence.js';
3
+ import type { Sequence } from './Sequence.js';
4
+ import type { DurationInput } from './utils/duration.js';
5
+ import type { TemporalLike } from './temporal.js';
6
+ import type { AggregateMap, AggregateOutputMap, AggregateSchema, AlignSchema, BaselineSchema, DedupeKeep, DiffSchema, EventDataForSchema, FillMapping, FillStrategy, NumericColumnNameForSchema, RollingAlignment, RollingSchema, SeriesSchema, SmoothAppendSchema, SmoothMethod, SmoothSchema } from './types.js';
7
+ import type { AggregateOutputMapResultSchema, RollingOutputMapSchema } from './types-aggregate.js';
8
+ type SequenceLike = Sequence | BoundedSequence;
9
+ type AlignMethod = 'hold' | 'linear';
10
+ type AlignSample = 'begin' | 'center' | 'end';
11
+ /**
12
+ * View over a `TimeSeries` that scopes stateful transforms to within
13
+ * each partition. Created by `TimeSeries.partitionBy(by)`.
14
+ *
15
+ * Most pond-ts stateful operators read from neighboring events when
16
+ * computing each output. On a multi-entity series (events for many
17
+ * hosts interleaved by time), those neighbors silently cross entity
18
+ * boundaries: a `fill('linear')` for `host-A` would interpolate using
19
+ * `host-B`'s value as a "neighbor"; a `rolling('5m', { cpu: 'avg' })`
20
+ * would average across all hosts in the window.
21
+ *
22
+ * `partitionBy` runs the transform independently on each partition's
23
+ * events. The view is **persistent across chains** — each sugar method
24
+ * returns another `PartitionedTimeSeries` carrying the same partition
25
+ * columns, so multi-step per-partition workflows compose cleanly:
26
+ *
27
+ * ```ts
28
+ * const cleaned = ts
29
+ * .partitionBy('host')
30
+ * .dedupe({ keep: 'last' }) // per-host
31
+ * .fill({ cpu: 'linear' }) // per-host
32
+ * .rolling('5m', { cpu: 'avg' }) // per-host
33
+ * .collect(); // back to TimeSeries<S>
34
+ * ```
35
+ *
36
+ * Call `.collect()` (or `.apply(fn)` for arbitrary transforms) to
37
+ * materialize back to a regular `TimeSeries`. Without `.collect()`,
38
+ * the chain stays in partition view.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * // Per-host fill
43
+ * const filled = series.partitionBy('host').fill({ cpu: 'linear' }).collect();
44
+ *
45
+ * // Composite partitioning by host + region
46
+ * const filled = series.partitionBy(['host', 'region']).fill({ cpu: 'linear' }).collect();
47
+ *
48
+ * // Arbitrary transform via apply (terminal — returns TimeSeries directly)
49
+ * const custom = series.partitionBy('host').apply(g =>
50
+ * g.fill({ cpu: 'linear' }).rolling('5m', { cpu: 'avg' }),
51
+ * );
52
+ * ```
53
+ */
54
+ export declare class PartitionedTimeSeries<S extends SeriesSchema> {
55
+ readonly source: TimeSeries<S>;
56
+ readonly by: ReadonlyArray<keyof EventDataForSchema<S> & string>;
57
+ constructor(source: TimeSeries<S>, by: (keyof EventDataForSchema<S> & string) | ReadonlyArray<keyof EventDataForSchema<S> & string>);
58
+ /**
59
+ * Materialize the partitioned view back into a regular `TimeSeries`.
60
+ * Terminal operation — call this at the end of a chain to "collect"
61
+ * the per-partition results. Equivalent to `.apply(g => g)` but
62
+ * cheaper (no fn dispatch, just returns the source as-is).
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * const cleaned = ts
67
+ * .partitionBy('host')
68
+ * .fill({ cpu: 'linear' })
69
+ * .rolling('5m', { cpu: 'avg' })
70
+ * .collect(); // <- TimeSeries<S>
71
+ * ```
72
+ */
73
+ collect(): TimeSeries<S>;
74
+ /**
75
+ * Run a transform `fn` independently on each partition and return a
76
+ * `TimeSeries<R>` directly (terminal — does not stay in the
77
+ * partitioned view). The escape hatch for compositions or operators
78
+ * not exposed as sugar.
79
+ *
80
+ * To keep the partition after a custom transform, use the sugar
81
+ * methods (which preserve partition state) or call `.partitionBy(...)`
82
+ * again on the result.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * // chain two stateful ops within each partition (one shot)
87
+ * const out = series.partitionBy('host').apply(g =>
88
+ * g.fill({ cpu: 'linear' }).rolling('5m', { cpu: 'avg' }),
89
+ * );
90
+ * ```
91
+ */
92
+ apply<R extends SeriesSchema>(fn: (group: TimeSeries<S>) => TimeSeries<R>): TimeSeries<R>;
93
+ private static applyToSource;
94
+ private rewrap;
95
+ /** Per-partition `fill`. See {@link TimeSeries.fill}. */
96
+ fill(strategy: FillStrategy | FillMapping<S>, options?: {
97
+ limit?: number;
98
+ maxGap?: DurationInput;
99
+ }): PartitionedTimeSeries<S>;
100
+ /**
101
+ * Per-partition `dedupe`. The duplicate key becomes "same partition
102
+ * columns AND same timestamp" — `partitionBy` provides the partition
103
+ * segregation, `dedupe` handles the within-partition timestamp
104
+ * collapse. The most common dedupe shape for multi-entity ingest.
105
+ *
106
+ * See {@link TimeSeries.dedupe}.
107
+ */
108
+ dedupe(options?: {
109
+ keep?: DedupeKeep<S>;
110
+ }): PartitionedTimeSeries<S>;
111
+ /** Per-partition `align`. See {@link TimeSeries.align}. */
112
+ align(sequence: SequenceLike, options?: {
113
+ method?: AlignMethod;
114
+ sample?: AlignSample;
115
+ range?: TemporalLike;
116
+ }): PartitionedTimeSeries<AlignSchema<S>>;
117
+ /** Per-partition `rolling`. See {@link TimeSeries.rolling}. */
118
+ rolling<const Mapping extends AggregateMap<S>>(window: DurationInput, mapping: Mapping, options?: {
119
+ alignment?: RollingAlignment;
120
+ }): PartitionedTimeSeries<RollingSchema<S, Mapping>>;
121
+ rolling<const Mapping extends AggregateOutputMap<S>>(window: DurationInput, mapping: Mapping, options?: {
122
+ alignment?: RollingAlignment;
123
+ }): PartitionedTimeSeries<RollingOutputMapSchema<S, Mapping>>;
124
+ rolling<const Mapping extends AggregateMap<S>>(sequence: SequenceLike, window: DurationInput, mapping: Mapping, options?: {
125
+ alignment?: RollingAlignment;
126
+ sample?: AlignSample;
127
+ range?: TemporalLike;
128
+ }): PartitionedTimeSeries<AggregateSchema<S, Mapping>>;
129
+ rolling<const Mapping extends AggregateOutputMap<S>>(sequence: SequenceLike, window: DurationInput, mapping: Mapping, options?: {
130
+ alignment?: RollingAlignment;
131
+ sample?: AlignSample;
132
+ range?: TemporalLike;
133
+ }): PartitionedTimeSeries<AggregateOutputMapResultSchema<S, Mapping>>;
134
+ /** Per-partition `smooth`. See {@link TimeSeries.smooth}. */
135
+ smooth<const Target extends NumericColumnNameForSchema<S>, const Output extends string | undefined = undefined>(column: Target, method: SmoothMethod, options: {
136
+ alpha: number;
137
+ warmup?: number;
138
+ output?: Output;
139
+ } | {
140
+ window: DurationInput;
141
+ alignment?: RollingAlignment;
142
+ output?: Output;
143
+ } | {
144
+ span: number;
145
+ output?: Output;
146
+ }): PartitionedTimeSeries<Output extends string ? SmoothAppendSchema<S, Output> : SmoothSchema<S, Target>>;
147
+ /** Per-partition `baseline`. See {@link TimeSeries.baseline}. */
148
+ baseline<const Col extends NumericColumnNameForSchema<S>, const AvgName extends string = 'avg', const SdName extends string = 'sd', const UpperName extends string = 'upper', const LowerName extends string = 'lower'>(col: Col, options: {
149
+ window: DurationInput;
150
+ sigma: number;
151
+ alignment?: RollingAlignment;
152
+ names?: {
153
+ avg?: AvgName;
154
+ sd?: SdName;
155
+ upper?: UpperName;
156
+ lower?: LowerName;
157
+ };
158
+ }): PartitionedTimeSeries<BaselineSchema<S, AvgName, SdName, UpperName, LowerName>>;
159
+ /** Per-partition `outliers`. See {@link TimeSeries.outliers}. */
160
+ outliers<const Col extends NumericColumnNameForSchema<S>>(col: Col, options: {
161
+ window: DurationInput;
162
+ sigma: number;
163
+ alignment?: RollingAlignment;
164
+ }): PartitionedTimeSeries<S>;
165
+ /** Per-partition `diff`. See {@link TimeSeries.diff}. */
166
+ diff<const Target extends NumericColumnNameForSchema<S>>(columns: Target | readonly Target[], options?: {
167
+ drop?: boolean;
168
+ }): PartitionedTimeSeries<DiffSchema<S, Target>>;
169
+ /** Per-partition `rate`. See {@link TimeSeries.rate}. */
170
+ rate<const Target extends NumericColumnNameForSchema<S>>(columns: Target | readonly Target[], options?: {
171
+ drop?: boolean;
172
+ }): PartitionedTimeSeries<DiffSchema<S, Target>>;
173
+ /** Per-partition `pctChange`. See {@link TimeSeries.pctChange}. */
174
+ pctChange<const Target extends NumericColumnNameForSchema<S>>(columns: Target | readonly Target[], options?: {
175
+ drop?: boolean;
176
+ }): PartitionedTimeSeries<DiffSchema<S, Target>>;
177
+ /** Per-partition `cumulative`. See {@link TimeSeries.cumulative}. */
178
+ cumulative<const Targets extends NumericColumnNameForSchema<S>>(spec: {
179
+ [K in Targets]: 'sum' | 'max' | 'min' | 'count' | ((acc: number, value: number) => number);
180
+ }): PartitionedTimeSeries<DiffSchema<S, Targets>>;
181
+ /** Per-partition `shift`. See {@link TimeSeries.shift}. */
182
+ shift<const Target extends NumericColumnNameForSchema<S>>(columns: Target | readonly Target[], n: number): PartitionedTimeSeries<DiffSchema<S, Target>>;
183
+ /** Per-partition `aggregate`. See {@link TimeSeries.aggregate}. */
184
+ aggregate<const Mapping extends AggregateMap<S>>(sequence: SequenceLike, mapping: Mapping, options?: {
185
+ range?: TemporalLike;
186
+ }): PartitionedTimeSeries<AggregateSchema<S, Mapping>>;
187
+ aggregate<const Mapping extends AggregateOutputMap<S>>(sequence: SequenceLike, mapping: Mapping, options?: {
188
+ range?: TemporalLike;
189
+ }): PartitionedTimeSeries<AggregateOutputMapResultSchema<S, Mapping>>;
190
+ }
191
+ export {};
192
+ //# sourceMappingURL=PartitionedTimeSeries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PartitionedTimeSeries.d.ts","sourceRoot":"","sources":["../src/PartitionedTimeSeries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,228 @@
1
+ import { TimeSeries } from './TimeSeries.js';
2
+ /**
3
+ * View over a `TimeSeries` that scopes stateful transforms to within
4
+ * each partition. Created by `TimeSeries.partitionBy(by)`.
5
+ *
6
+ * Most pond-ts stateful operators read from neighboring events when
7
+ * computing each output. On a multi-entity series (events for many
8
+ * hosts interleaved by time), those neighbors silently cross entity
9
+ * boundaries: a `fill('linear')` for `host-A` would interpolate using
10
+ * `host-B`'s value as a "neighbor"; a `rolling('5m', { cpu: 'avg' })`
11
+ * would average across all hosts in the window.
12
+ *
13
+ * `partitionBy` runs the transform independently on each partition's
14
+ * events. The view is **persistent across chains** — each sugar method
15
+ * returns another `PartitionedTimeSeries` carrying the same partition
16
+ * columns, so multi-step per-partition workflows compose cleanly:
17
+ *
18
+ * ```ts
19
+ * const cleaned = ts
20
+ * .partitionBy('host')
21
+ * .dedupe({ keep: 'last' }) // per-host
22
+ * .fill({ cpu: 'linear' }) // per-host
23
+ * .rolling('5m', { cpu: 'avg' }) // per-host
24
+ * .collect(); // back to TimeSeries<S>
25
+ * ```
26
+ *
27
+ * Call `.collect()` (or `.apply(fn)` for arbitrary transforms) to
28
+ * materialize back to a regular `TimeSeries`. Without `.collect()`,
29
+ * the chain stays in partition view.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * // Per-host fill
34
+ * const filled = series.partitionBy('host').fill({ cpu: 'linear' }).collect();
35
+ *
36
+ * // Composite partitioning by host + region
37
+ * const filled = series.partitionBy(['host', 'region']).fill({ cpu: 'linear' }).collect();
38
+ *
39
+ * // Arbitrary transform via apply (terminal — returns TimeSeries directly)
40
+ * const custom = series.partitionBy('host').apply(g =>
41
+ * g.fill({ cpu: 'linear' }).rolling('5m', { cpu: 'avg' }),
42
+ * );
43
+ * ```
44
+ */
45
+ export class PartitionedTimeSeries {
46
+ source;
47
+ by;
48
+ constructor(source, by) {
49
+ this.source = source;
50
+ this.by = (Array.isArray(by) ? by : [by]);
51
+ if (this.by.length === 0) {
52
+ throw new TypeError('PartitionedTimeSeries requires at least one partition column.');
53
+ }
54
+ for (const col of this.by) {
55
+ if (!source.schema.some((c) => c.name === col)) {
56
+ throw new TypeError(`PartitionedTimeSeries: column "${String(col)}" not in schema`);
57
+ }
58
+ }
59
+ }
60
+ /**
61
+ * Materialize the partitioned view back into a regular `TimeSeries`.
62
+ * Terminal operation — call this at the end of a chain to "collect"
63
+ * the per-partition results. Equivalent to `.apply(g => g)` but
64
+ * cheaper (no fn dispatch, just returns the source as-is).
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * const cleaned = ts
69
+ * .partitionBy('host')
70
+ * .fill({ cpu: 'linear' })
71
+ * .rolling('5m', { cpu: 'avg' })
72
+ * .collect(); // <- TimeSeries<S>
73
+ * ```
74
+ */
75
+ collect() {
76
+ return this.source;
77
+ }
78
+ /**
79
+ * Run a transform `fn` independently on each partition and return a
80
+ * `TimeSeries<R>` directly (terminal — does not stay in the
81
+ * partitioned view). The escape hatch for compositions or operators
82
+ * not exposed as sugar.
83
+ *
84
+ * To keep the partition after a custom transform, use the sugar
85
+ * methods (which preserve partition state) or call `.partitionBy(...)`
86
+ * again on the result.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * // chain two stateful ops within each partition (one shot)
91
+ * const out = series.partitionBy('host').apply(g =>
92
+ * g.fill({ cpu: 'linear' }).rolling('5m', { cpu: 'avg' }),
93
+ * );
94
+ * ```
95
+ */
96
+ apply(fn) {
97
+ return PartitionedTimeSeries.applyToSource(this.source, this.by, fn);
98
+ }
99
+ // Internal helper used by both `apply` (terminal) and the sugar
100
+ // methods (which re-wrap the result back into a partitioned view).
101
+ static applyToSource(source, by, fn) {
102
+ // Empty source: apply fn to an empty group so the output schema
103
+ // and name come from fn, not from inferring R structurally.
104
+ if (source.events.length === 0) {
105
+ const empty = TimeSeries.fromEvents([], {
106
+ schema: source.schema,
107
+ name: source.name,
108
+ });
109
+ return fn(empty);
110
+ }
111
+ const compositeKey = (event) => {
112
+ const data = event.data();
113
+ // Single-column case: avoid the encoding overhead.
114
+ if (by.length === 1) {
115
+ const v = data[by[0]];
116
+ return v === undefined ? ' undefined' : `${String(v)}`;
117
+ }
118
+ // Multi-column case: JSON.stringify guarantees no collision
119
+ // because it encodes strings with quotes and escapes. A naive
120
+ // separator approach (e.g. join('|')) would collide on values
121
+ // containing the separator.
122
+ const parts = new Array(by.length);
123
+ for (let i = 0; i < by.length; i += 1) {
124
+ parts[i] = data[by[i]] ?? null;
125
+ }
126
+ return JSON.stringify(parts);
127
+ };
128
+ const buckets = new Map();
129
+ for (const event of source.events) {
130
+ const key = compositeKey(event);
131
+ let bucket = buckets.get(key);
132
+ if (!bucket) {
133
+ bucket = [];
134
+ buckets.set(key, bucket);
135
+ }
136
+ bucket.push(event);
137
+ }
138
+ const transformed = [];
139
+ for (const events of buckets.values()) {
140
+ const sub = TimeSeries.fromEvents(events, {
141
+ schema: source.schema,
142
+ name: source.name,
143
+ });
144
+ transformed.push(fn(sub));
145
+ }
146
+ return TimeSeries.concat(transformed);
147
+ }
148
+ // Wrap a transform result back into a PartitionedTimeSeries with the
149
+ // same partition columns. Used by the sugar methods to keep the chain
150
+ // in partition view. Cast at the boundary because R may not preserve
151
+ // the partition columns type-narrowly (e.g. RollingSchema<S, M> may
152
+ // drop columns); runtime constructor validates that the partition
153
+ // columns are still present in the result schema.
154
+ rewrap(out) {
155
+ return new PartitionedTimeSeries(out, this.by);
156
+ }
157
+ // ─── Sugar: stateful ops, applied per partition ─────────────────────
158
+ //
159
+ // Each method's overload signatures mirror the corresponding
160
+ // `TimeSeries` method but return `PartitionedTimeSeries<NewSchema>`
161
+ // instead of `TimeSeries<NewSchema>`, so the chain stays in partition
162
+ // view. Call `.collect()` to materialize back. Each impl runs the
163
+ // underlying op per-partition via `applyToSource` and re-wraps.
164
+ /** Per-partition `fill`. See {@link TimeSeries.fill}. */
165
+ fill(strategy, options) {
166
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) => g.fill(strategy, options)));
167
+ }
168
+ /**
169
+ * Per-partition `dedupe`. The duplicate key becomes "same partition
170
+ * columns AND same timestamp" — `partitionBy` provides the partition
171
+ * segregation, `dedupe` handles the within-partition timestamp
172
+ * collapse. The most common dedupe shape for multi-entity ingest.
173
+ *
174
+ * See {@link TimeSeries.dedupe}.
175
+ */
176
+ dedupe(options) {
177
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) => g.dedupe(options)));
178
+ }
179
+ /** Per-partition `align`. See {@link TimeSeries.align}. */
180
+ align(sequence, options) {
181
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) => g.align(sequence, options)));
182
+ }
183
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
184
+ rolling(...args) {
185
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) =>
186
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
187
+ g.rolling(...args)));
188
+ }
189
+ /** Per-partition `smooth`. See {@link TimeSeries.smooth}. */
190
+ smooth(column, method, options) {
191
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) => g.smooth(column, method, options)));
192
+ }
193
+ /** Per-partition `baseline`. See {@link TimeSeries.baseline}. */
194
+ baseline(col, options) {
195
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) => g.baseline(col, options)));
196
+ }
197
+ /** Per-partition `outliers`. See {@link TimeSeries.outliers}. */
198
+ outliers(col, options) {
199
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) => g.outliers(col, options)));
200
+ }
201
+ /** Per-partition `diff`. See {@link TimeSeries.diff}. */
202
+ diff(columns, options) {
203
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) => g.diff(columns, options)));
204
+ }
205
+ /** Per-partition `rate`. See {@link TimeSeries.rate}. */
206
+ rate(columns, options) {
207
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) => g.rate(columns, options)));
208
+ }
209
+ /** Per-partition `pctChange`. See {@link TimeSeries.pctChange}. */
210
+ pctChange(columns, options) {
211
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) => g.pctChange(columns, options)));
212
+ }
213
+ /** Per-partition `cumulative`. See {@link TimeSeries.cumulative}. */
214
+ cumulative(spec) {
215
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) => g.cumulative(spec)));
216
+ }
217
+ /** Per-partition `shift`. See {@link TimeSeries.shift}. */
218
+ shift(columns, n) {
219
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) => g.shift(columns, n)));
220
+ }
221
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
222
+ aggregate(...args) {
223
+ return this.rewrap(PartitionedTimeSeries.applyToSource(this.source, this.by, (g) =>
224
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
225
+ g.aggregate(...args)));
226
+ }
227
+ }
228
+ //# sourceMappingURL=PartitionedTimeSeries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PartitionedTimeSeries.js","sourceRoot":"","sources":["../src/PartitionedTimeSeries.ts"],"names":[],"mappings":"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"}