|
1 | | -import { |
2 | | - SignalsRuntimeAPI, |
3 | | - SignalOfType, |
4 | | - Signal, |
5 | | - SignalTypes, |
6 | | -} from './types/web/signals' |
| 1 | +interface BaseSignal { |
| 2 | + index?: number |
| 3 | + type: string |
| 4 | + time: number |
| 5 | +} |
| 6 | + |
| 7 | +export type SignalOfType< |
| 8 | + AllSignals extends BaseSignal, |
| 9 | + SignalType extends AllSignals['type'] |
| 10 | +> = AllSignals & { type: SignalType } |
| 11 | + |
| 12 | +/** |
| 13 | + * SignalsRuntime class to manage signals |
| 14 | + * @param AnySignal - Type of signals |
| 15 | + * @param signals - List of signals, with the most recent signals first (LIFO). |
| 16 | + * @returns SignalsRuntime object |
| 17 | + * @example |
| 18 | + * type MobileSignal = NavigationSignal | InteractionSignal | SomeOtherMobileSpecificSignal |
| 19 | + * const signalsRuntime = new SignalsRuntime<MobileSignal>([]) |
| 20 | + * signalsRuntime.add({ |
| 21 | + * index: 0, |
| 22 | + * type: 'foo' |
| 23 | + * }) |
| 24 | + */ |
| 25 | +export class SignalsRuntime<Signal extends BaseSignal = BaseSignal> { |
| 26 | + private signalBuffer: Signal[] |
| 27 | + // mobile only - see brandon for this code |
| 28 | + private signalCounter: number |
| 29 | + // mobile only - see brandon for this code |
| 30 | + private maxBufferSize: number |
| 31 | + |
| 32 | + constructor(signals: Signal[]) { |
| 33 | + // initial signals |
| 34 | + this.signalBuffer = signals |
| 35 | + // mobile only -- see brandon for this code |
| 36 | + this.signalCounter = 0 |
| 37 | + this.maxBufferSize = 1000 |
| 38 | + } |
7 | 39 |
|
8 | | -export function createSignalsRuntimeHelpers( |
9 | | - signals: Signal[] |
10 | | -): SignalsRuntimeAPI { |
11 | | - /** |
12 | | - * @param fromSignal - signal to start searching from |
13 | | - * @param signalType - type of signal to find (e.g. 'interaction') |
14 | | - * @param predicate - optional predicate function to filter the signals (search domain only includes signals after the signal defined in `fromSignal`) |
15 | | - * @returns signals after the current one. |
16 | | - */ |
17 | | - function find<T extends SignalTypes>( |
| 40 | + find = <SignalType extends Signal['type']>( |
18 | 41 | fromSignal: Signal, |
19 | | - signalType: T, |
20 | | - predicate?: (signal: SignalOfType<T>) => boolean |
21 | | - ): SignalOfType<T> | undefined { |
22 | | - const _isSignalOfType = (signal: Signal): signal is SignalOfType<T> => |
23 | | - signal.type === signalType |
24 | | - return signals |
25 | | - .slice(signals.indexOf(fromSignal) + 1) |
| 42 | + signalType: SignalType, |
| 43 | + predicate?: (signal: SignalOfType<Signal, SignalType>) => boolean |
| 44 | + ): SignalOfType<Signal, SignalType> | undefined => { |
| 45 | + const _isSignalOfType = ( |
| 46 | + signal: Signal |
| 47 | + ): signal is SignalOfType<Signal, SignalType> => signal.type === signalType |
| 48 | + return this.signalBuffer |
| 49 | + .slice(this.signalBuffer.indexOf(fromSignal) + 1) |
26 | 50 | .filter(_isSignalOfType) |
27 | 51 | .find((signal) => (predicate ? predicate(signal) : () => true)) |
28 | 52 | } |
29 | 53 |
|
30 | | - return { |
31 | | - find, |
| 54 | + // mobile only - see brandon for this code |
| 55 | + add = (signal: Signal) => { |
| 56 | + if (this.signalCounter < 0) { |
| 57 | + this.signalCounter = 0 |
| 58 | + } |
| 59 | + |
| 60 | + if ('index' in signal && signal.index == -1) { |
| 61 | + // this was previously broken for ages, not sure when this code path would ever be used. |
| 62 | + // My understanding is that currently, getNextIndex() is called _outside_ of this function and used to construct the added signal. - seth |
| 63 | + signal.index = this.getNextIndex() |
| 64 | + } |
| 65 | + this.signalBuffer.unshift(signal) |
| 66 | + if (this.signalBuffer.length > this.maxBufferSize) { |
| 67 | + this.signalBuffer.pop() |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | + // mobile only - see brandon for this code |
| 72 | + getNextIndex = () => { |
| 73 | + const index = this.signalCounter |
| 74 | + this.signalCounter += 1 |
| 75 | + return index |
32 | 76 | } |
33 | 77 | } |
0 commit comments