UNPKG

ixfx

Version:

Bundle of ixfx libraries

1,414 lines (1,413 loc) 89 kB
import { a as ChangeRecord, t as PathDataChange } from "./pathed-7exI3RzP.js"; import { r as RecursivePartial } from "./ts-utility-01VlmgFR.js"; import { n as IsEqualContext, t as IsEqual } from "./is-equal-BE9SbPVX.js"; import { i as Interval, l as RankFunction, o as Primitive, u as RankOptions } from "./types-1oz6G7XR.js"; import { A as IQueueMutableWithEvents } from "./index-CvH8hp8B.js"; import { $ as InterpolateOptions } from "./index-D7rg4bcN2.js"; import { v as Processors } from "./index-C0VvOavs.js"; //#region ../packages/rx/src/ops/types.d.ts type SyncOptions = { /** * How to handle when a source completes. * * 'allow' means we continue synchronising with remaining alive sources. Use 'finalValue' option to control what data is returned for completed sources * * 'break' means we stop the stream, because synchronisation across all sources is no longer possible. * * Default: 'break'. */ onSourceDone: `allow` | `break`; /** * Maximum time to wait for synchronisation to happen. * If interval is exceeded, stream closes. * Default: 2s */ maximumWait: Interval; /** * If we continue synchronisation when a source is done (via `onSourceDone:'allow'`), * what source should be returned for a completed source? * * 'undefined': _undefined_ * * 'last': the last received value, or _undefined_ * * Default: 'undefined' */ finalValue: `undefined` | `last`; }; /** * Switcher options. * * match (default: 'first') * * 'first': Outputs to first case where predicate is _true_ * * 'all': Outputs to all cases where predicate is _true_ */ type SwitcherOptions = { match: `first` | `all`; }; /** * Transform options */ type TransformOpts = InitStreamOptions & { traceInput: boolean; traceOutput: boolean; }; type ChunkOptions = InitStreamOptions & { /** * If _true_ (default) remaining results are yielded * if source closes. If _false_, only chunks that meet * `elapsed` or `quantity` are emitted. */ returnRemainder: boolean; /** * Amount of time to gather results for a chunk. * 'elapsed' and 'quantity' is ORed. Meaning a chunk will the minimum of * 'elapsed' and 'quantity' */ elapsed: Interval; /** * Number of items to gather for a chunk. * 'elapsed' and 'quantity' is ORed. Meaning a chunk will the minimum of * 'elapsed' and 'quantity' */ quantity: number; }; type DebounceOptions = InitStreamOptions & { /** * Minimum time between events. Default 50ms */ elapsed: Interval; }; type FilterPredicate<In> = (value: In) => boolean; type ThrottleOptions = InitStreamOptions & { elapsed: Interval; }; type SplitOptions = { quantity: number; }; type FieldOptions<TSource, TValue> = InitStreamOptions & { /** * If `field` is missing on a value, it is query from this object instead. * If this also is missing, `fallbackFieldValue` is attempted. */ fallbackObject: TSource; /** * If `field` is missing on a value and `fallbackObject` (if specified), * this value is used in its place. * If not set, no value is emitted when the field is missing. */ fallbackFieldValue: TValue; }; type SingleFromArrayOptions<V> = { /** * Function to select a single value from array * @param value * @returns */ predicate: (value: V) => boolean; /** * `default`: leave array in same order (default option) * `random`: shuffles array before further processing * function: function that sorts values */ order: `default` | `random` | ((a: V, b: V) => number); /** * Selects an index from array. 0 being first, 1 being second. * Reverse indexing also works: -1 being last, -2 being second last... * * If index exceeds length of array, _undefined_ is returned */ at: number; }; type OpAsAnnotation = { annotate: true; }; type OpMathOptions = Partial<InitStreamOptions> & { annotate?: boolean; /** * If _true_ (default) operations that return _undefined_ do not emit a value. * If _false_, _undefined_ is potentially emitted */ skipUndefined?: boolean; /** * If _true_ (default) operations only emit a value if it has changed. * In the case of `max()`, for example, a stream of '1, 2, 3, 2, 1' would emit '1, 2, 3'. * If _false_ was used, same input would emit '1, 2, 3, 3, 3' */ skipIdentical?: boolean; }; //#endregion //#region ../packages/rx/src/sinks/dom.d.ts type SetHtmlOptionsQuery = { query: string; }; type SetHtmlOptionsElement = { el: HTMLElement; }; type SetHtmlOptions = (SetHtmlOptionsQuery | SetHtmlOptionsElement) & { /** * If _true_ .innerHTML is used * If _false_ (default) .textContent is used */ asHtml?: boolean; }; /** * Values from `input` are set to the textContent/innerHTML of an element. * ```js * const rxSource = Rx.From.string('hello'); * const rxSet = Rx.Sinks.setHtmlText(rxSource, { query: }) * ``` * @param rxOrSource * @param optionsOrElementOrQuery */ declare const setHtmlText: (rxOrSource: ReactiveOrSource<any>, optionsOrElementOrQuery: SetHtmlOptions | string | HTMLElement) => Unsubscriber; //#endregion //#region ../packages/rx/src/ops/math.d.ts declare function max(input: ReactiveOrSource<any>, options: OpMathOptions): Reactive<number>; declare function max(input: ReactiveOrSource<any>, options: OpAsAnnotation & OpMathOptions): Reactive<{ value: number; max: number; }>; declare function min(input: ReactiveOrSource<any>, options: OpMathOptions): Reactive<number>; declare function min(input: ReactiveOrSource<any>, options: OpAsAnnotation & OpMathOptions): Reactive<{ value: number; min: number; }>; declare function average(input: ReactiveOrSource<any>, options: OpMathOptions): Reactive<number>; declare function average(input: ReactiveOrSource<any>, options: OpAsAnnotation & OpMathOptions): Reactive<{ value: number; average: number; }>; declare function sum(input: ReactiveOrSource<any>, options: OpMathOptions): Reactive<number>; declare function sum(input: ReactiveOrSource<any>, options: OpAsAnnotation & OpMathOptions): Reactive<{ value: number; sum: number; }>; type TallyOptions = OpMathOptions & { countArrayItems: boolean; }; declare function tally(input: ReactiveOrSource<any>, options: Partial<TallyOptions>): Reactive<number>; declare function tally<TIn>(input: ReactiveOrSource<TIn>, options: OpAsAnnotation & Partial<TallyOptions>): Reactive<{ value: TIn; tally: number; }>; declare function rank<TIn>(input: ReactiveOrSource<any>, rank: RankFunction<TIn>, options: Partial<RankOptions & OpMathOptions>): Reactive<TIn>; declare function rank<TIn>(input: ReactiveOrSource<any>, rank: RankFunction<TIn>, options: OpAsAnnotation & Partial<RankOptions & OpMathOptions>): Reactive<{ value: TIn; rank: TIn; }>; //#endregion //#region ../packages/rx/src/types.d.ts type CombineLatestOptions = { /** * If _true_, disposes all the merged sources when the merged reactive closes. * Default: _true_. */ disposeSources: boolean; /** * How to handle when a source ends. * * 'allow': continue combined stream, last value for done stream will kept * * 'break': stop combined stream * * Default: 'break' */ onSourceDone: `allow` | `break`; /** * If _true_ (default), emits a value when initialised. */ emitInitial: boolean; }; type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>; declare const symbol: unique symbol; type SignalKinds = `done` | `warn`; type Passed<V> = { value: V | undefined; signal?: SignalKinds; context?: string; }; type PassedSignal = Passed<any> & { value: undefined; signal: SignalKinds; context: string; }; type PassedValue<V> = Passed<V> & { value: V; }; type UpstreamOptions<In> = { lazy: Lazy; /** * If _true_ (default), we dispose the underlying stream if the upstream closes. This happens after onStop() is called. */ disposeIfSourceDone: boolean; onValue: (v: In) => void; /** * Called just before we subscribe to source * @returns */ onStart: () => void; /** * Called after we unsubscribe from source * @returns */ onStop: () => void; debugLabel: string; onDispose: (reason: string) => void; }; type UpstreamInitialOptions<In> = UpstreamOptions<In> & { initialValue: In; }; /** * Wrapped Reactive for object-oriented access */ type Wrapped<TIn> = { enacts: { setHtmlText: (options: SetHtmlOptions) => () => void; }; source: Reactive<TIn>; /** * Annotate values with output from the `annotation` function. * Returned values will be in the form `{ value:TIn, annotation:TAnnotation }` * @param transformer * @returns */ annotate: <TAnnotation>(transformer: (value: TIn) => TAnnotation) => Wrapped<{ value: TIn; annotation: TAnnotation; }>; annotateWithOp: <TOut>(op: ReactiveOp<TIn, TOut>) => Wrapped<{ value: TIn; annotation: TOut; }>; /** * Accumulate a chunk of values, emitted as an array * @param options * @returns */ chunk: (options: Partial<ChunkOptions>) => Wrapped<TIn[]>; debounce: (options: Partial<DebounceOptions>) => Wrapped<TIn>; /** * Pluck and emit a single field from values * @param fieldName * @param options * @returns */ field: <TSource, TFieldType>(fieldName: keyof TIn, options: Partial<FieldOptions<TSource, TFieldType>>) => Wrapped<TFieldType>; /** * Throws away values that don't match `predicate` * @param predicate * @param options * @returns */ filter: (predicate: FilterPredicate<TIn>, options: Partial<InitStreamOptions>) => Wrapped<TIn>; combineLatestToArray: <const T extends readonly ReactiveOrSource<any>[]>(sources: T, options: Partial<CombineLatestOptions>) => Wrapped<RxValueTypes<T>>; combineLatestToObject: <const T extends Record<string, ReactiveOrSource<any>>>(sources: T, options: { name: string; } & Partial<CombineLatestOptions>) => Wrapped<RxValueTypeObject<T>>; min: (options?: Partial<OpMathOptions>) => Wrapped<number>; max: (options?: Partial<OpMathOptions>) => Wrapped<number>; average: (options?: Partial<OpMathOptions>) => Wrapped<number>; sum: (options?: Partial<OpMathOptions>) => Wrapped<number>; tally: (options?: Partial<TallyOptions>) => Wrapped<number>; /** * Converts one source stream into two, with values being emitted by both * @param options * @returns */ split: (options?: Partial<SplitOptions>) => Wrapped<TIn>[]; /** * Emits values when this stream and any additional streams produce a value. The resulting stream is * thus an array of values, each source at a given index. * Waits to output a value until each stream has produced a value. Thus, the pace is determined by * the slowest stream. * @returns */ syncToArray: <const T extends readonly ReactiveOrSource<any>[]>(reactiveSources: T, options?: Partial<SyncOptions>) => Wrapped<[TIn, ...RxValueTypes<T>]>; syncToObject: <const T extends Record<string, ReactiveOrSource<any>>>(reactiveSources: T, options?: { name?: string; } & Partial<SyncOptions>) => Wrapped<RxValueTypeObject<T>>; /** * Creates new streams for each case, sending values to the stream if they match the filter predicate * @param cases * @param options * @returns */ switcher: <TRec extends Record<string, FilterPredicate<TIn>>, TLabel extends keyof TRec>(cases: TRec, options: Partial<SwitcherOptions>) => Record<TLabel, Wrapped<TIn>>; /** * Creates new streams for each case * @param labels * @returns */ splitLabelled: <K extends keyof TIn>(...labels: K[]) => Record<K, Wrapped<TIn>>; /** * Taps the stream, passing values to one or more 'processor' functions. * This processing essentially happens in parallel, not affecting the main stream. * * ```js * // Stream of pointermove events with {x:0,y:0} as default * const move = Rx.From.event(document.body, `pointermove`, {x:0,y:0}); * // Wrap it for fluent access * const ptr = Rx.wrap(move) * .tapProcess( * // Create a string representation * v => `${v.x},${v.y}` * // Set to DOM * v => { * document.getElementById(`coords`).innerText = v; * } * ) * .onValue(value => { * // 'value' will be original PointerEvent, since .tapProcess happened in parallel, * // not affecting stream * }); * ``` * @param processors One-five processing functions * @returns */ tapProcess: <T2, T3, T4, T5, T6>(...processors: Processors<TIn, T2, T3, T4, T5, T6>) => Wrapped<TIn>; tapStream: (divergedStream: ReactiveWritable<TIn>) => Wrapped<TIn>; tapOps: <TOut>(source: ReactiveOrSource<TIn>, ...ops: ReactiveOp<TIn, TOut>[]) => Wrapped<TIn>; /** * Transforms all values * @param transformer * @param options * @returns */ transform: <TOut>(transformer: (value: TIn) => TOut, options?: Partial<TransformOpts>) => Wrapped<TOut>; /** * Only allow values through if a minimum of time has elapsed. Throws away values. * Ie. converts a fast stream into a slower one. * @param options * @returns */ throttle: (options: Partial<ThrottleOptions>) => Wrapped<TIn>; /** * Emits a value if `source` does not emit a value after `interval` * has elapsed. This can be useful to reset a reactive to some * 'zero' state if nothing is going on. * * If `source` emits faster than the `interval`, it won't get triggered. * * Default for 'timeout': 1000s. * * ```js * // Emit 'hello' if 'source' doesn't emit a value after 1 minute * const r = Rx.timeoutValue(source, { value: 'hello', interval: { mins: 1 } }); * ``` * * Can also emit results from a function or generator * ```js * // Emits a random number if 'source' doesn't emit a value after 500ms * const r = Rx.timeoutValue(source, { fn: Math.random, interval: 500 }); * ``` * * If `immediate` option is _true_ (default), the timer starts from stream initialisation. * Otherwise it won't start until it observes the first value from `source`. * @param options */ timeoutValue: <TTriggerValue>(options: TimeoutValueOptions<TTriggerValue>) => Wrapped<TIn | TTriggerValue>; /** * 'Pings' reactive (if it supports it) if a value is not received within a given interval. * Behaviour can be stopped using an abort signal. * @param options * @returns */ timeoutPing: (options: TimeoutPingOptions) => Wrapped<TIn>; /** * Copies values from source into an array, throwing * an error if expected number of items is not reached * @param options * @returns */ toArrayOrThrow: (options: Partial<ToArrayOptions<TIn>>) => Promise<TIn[]>; /** * Copies values from source into an array. * @param options * @returns */ toArray: (options: Partial<ToArrayOptions<TIn>>) => Promise<(TIn | undefined)[]>; /** * Listen for values * @param callback * @returns */ onValue: (callback: (value: TIn) => void) => void; }; type ToArrayOptions<V> = { /** * Maximim time to wait for `limit` to be reached. 10s by default. */ maximumWait: Interval; /** * Number of items to read */ limit: number; /** * Behaviour if threshold is not reached. * partial: return partial results * throw: throw an error * fill: fill remaining array slots with `fillValue` */ underThreshold: `partial` | `throw` | `fill`; /** * Value to fill empty slots with if `underThreshold = 'fill'`. */ fillValue: V; }; /** * Laziness * * start: only begins on first subscriber. Keeps running even when there are no subscribers * * very: only begins on first subscriber. Stops looping if there are no subscribers * * never: begins calling function when initalised and doesn't stop until Reactive is disposed */ type Lazy = `initial` | `never` | `very`; type InitLazyStreamOptions = Partial<InitStreamOptions> & { lazy?: Lazy; debugLabel?: string; onStart: () => void; onStop: () => void; }; type InitLazyStreamInitedOptions<T> = InitLazyStreamOptions & { initialValue: T; }; type ReactiveOrSource<V> = Wrapped<V> | Reactive<V> | IterableIterator<V> | AsyncIterableIterator<V> | Generator<V> | AsyncGenerator<V> | V[] | (() => V); /** * A Reactive */ type Reactive<V> = { /** * Subscribes to a reactive. Receives * data as well as signals. Use `onValue` if you * just care about values. * * Return result unsubscribes. * * ```js * const unsub = someReactive.on(msg => { * // Do something with msg.value * }); * * unsub(); // Unsubscribe * ``` * @param handler */ on(handler: (value: Passed<V>) => void): Unsubscriber; /** * Subscribes to a reactive's values. * Returns a function that unsubscribes. * @param handler */ onValue(handler: (value: V) => void): Unsubscriber; /** * Disposes the reactive, providing a reason for debug tracing * @param reason */ dispose(reason: string): void; /** * Returns _true_ if Reactive is disposed */ isDisposed(): boolean; /** * Optional 'set' to write a value. Use {@link ReactiveWritable} if you want this non-optional * @param value */ set?(value: V): void; }; /** * A reactive that can be 'pinged' to produce a value. * * Use {@link isPingable} to check if a reactive is pingable. * * Pingable reactives are returned from * * interpolate * * computeWithPrevious * * valueToPing */ type ReactivePingable<V> = Reactive<V> & { ping(): void; }; type Unsubscriber = () => void; type ReactiveNonInitial<V> = Reactive<V> & { last(): V | undefined; }; /** * A stream that can be written to */ type ReactiveWritable<TIn, TOut = TIn> = Reactive<TOut> & { /** * Sets a value * @param value Value to write */ set(value: TIn): void; }; type ReactiveInitial<V> = Reactive<V> & { last(): V; }; type ReactiveFinite = { isDone(): boolean; }; type ReactiveArray<V> = ReactiveWritable<V[]> & { push(value: V): void; deleteAt(index: number): void; deleteWhere(filter: (value: V) => boolean): number; setAt(index: number, value: V): void; insertAt(index: number, value: V): void; onArray(handler: (changes: Passed<ChangeRecord<number>[]>) => void): () => void; }; type ObjectFieldHandler = { value: any; fieldName: string; pattern: string; }; type ReactiveDiff<V> = Reactive<V> & ReactiveWritable<V> & { /** * Notifies when the value of `fieldName` is changed. * * Use the returned function to unsubscribe. * @param fieldName * @param handler */ onField(fieldName: string, handler: (result: ObjectFieldHandler) => void): () => void; /** * Notifies of which field(s) were changed. * If you just care about the whole, changed data use the `value` event. * * Use the returned function to unsubscribe. * @param changes */ onDiff(changes: (changes: PathDataChange<any>[]) => void): () => void; /** * Updates the reactive with some partial key-value pairs. * Keys omitted are left the same as the current value. * @param changedPart * @returns Returns new value */ update(changedPart: RecursivePartial<V>): V; /** * Updates a particular field by its path * @param field * @param value */ updateField(field: string, value: any): void; }; /** * A reactive stream which can be read and written to */ type ReactiveStream<V> = Reactive<V> & ReactiveWritable<V> & { /** * Removes all the subscribers from this stream. */ removeAllSubscribers(): void; /** * Dispatches a signal * @param signal * @param context */ signal(signal: SignalKinds, context?: string): void; }; type ReactiveInitialStream<V> = ReactiveStream<V> & ReactiveInitial<V>; type PipeSet<In, Out> = [Reactive<In>, ...(Reactive<any> & ReactiveWritable<any>)[]]; type InitStreamOptions = { /** * Optional label to associate with this stream. Useful for debugging. */ debugLabel: string; /** * Called when there is a subscriber after there were no subscribers. * Useful for 'startup' types of things that we want to run only when someone is actually listening. * * During the lifeycle of a stream, this could be called multiple times. Eg if all subscribers are removed * next time someone subscribes it will get called again. * @returns */ onFirstSubscribe: () => void; /** * Called when there are no longer any subscribers. Useful for shutting down * activities now that no-one is listening. * * During the lifecycle of a stream, this could be called multiple times. * @returns */ onNoSubscribers: () => void; /** * Called whenever the stream disposes. Useful for cleaning up. * @param reason * @returns */ onDispose: (reason: string) => void; }; /** * WithValue stream options */ type WithValueOptions<V> = Partial<InitStreamOptions> & { /** * Initial value */ initial: V; /** * Laziness */ lazy?: Lazy; }; type ResolveOptions = { /** * How many times to return value or call function. * If _infinite_ is set to true, this value is ignored */ loops: number; /** * If _true_ loops forever */ infinite: boolean; /** * Delay before value */ interval: Interval; lazy: Lazy; }; type ReactiveOpInit<TIn, TOut, TOpts> = (options: Partial<TOpts>) => ReactiveOp<TIn, TOut>; type ReactiveOp<TIn, TOut> = (source: ReactiveOrSource<TIn>) => Reactive<TOut>; type ReactiveOpLinks<In, Out> = [ReactiveOrSource<In>, ...ReactiveOp<any, any>[], ReactiveOp<any, Out>]; type RxValueTypes<T extends readonly ReactiveOrSource<any>[]> = { [K in keyof T]: T[K] extends Reactive<infer V> ? V | undefined : T[K] extends Wrapped<infer V> ? V | undefined : T[K] extends Generator<infer V> ? V | undefined : T[K] extends AsyncGenerator<infer V> ? V | undefined : T[K] extends IterableIterator<infer V> ? V | undefined : T[K] extends AsyncIterableIterator<infer V> ? V | undefined : T[K] extends (infer V)[] ? V | undefined : never }; type RxValueTypeObject<T extends Record<string, ReactiveOrSource<any>>> = { [K in keyof T]: T[K] extends Reactive<infer V> ? V : T[K] extends Wrapped<infer V> ? V : T[K] extends Generator<infer V> ? V : T[K] extends AsyncGenerator<infer V> ? V : T[K] extends IterableIterator<infer V> ? V : T[K] extends AsyncIterableIterator<infer V> ? V : T[K] extends (infer V)[] ? V : never }; type RxValueTypeObjectOrUndefined<T extends Record<string, ReactiveOrSource<any>>> = { [K in keyof T]: T[K] extends Reactive<infer V> ? V | undefined : T[K] extends Wrapped<infer V> ? V | undefined : T[K] extends Generator<infer V> ? V | undefined : T[K] extends AsyncGenerator<infer V> ? V | undefined : T[K] extends IterableIterator<infer V> ? V | undefined : T[K] extends AsyncIterableIterator<infer V> ? V | undefined : T[K] extends (infer V)[] ? V | undefined : never }; type RxValueTypeRx<T extends Record<string, ReactiveOrSource<any>>> = { [K in keyof T]: T[K] extends Reactive<infer V> ? Reactive<V> : T[K] extends Wrapped<infer V> ? Reactive<V> : T[K] extends Generator<infer V> ? Reactive<V> : T[K] extends AsyncGenerator<infer V> ? Reactive<V> : T[K] extends IterableIterator<infer V> ? Reactive<V> : T[K] extends AsyncIterableIterator<infer V> ? Reactive<V> : T[K] extends (infer V)[] ? Reactive<V> : never }; type PrimitiveValueTypeObject<T extends Record<string, Primitive>> = { [K in keyof T]: T[K] extends number ? number | undefined : T[K] extends string ? string | undefined : T[K] extends boolean ? boolean | undefined : T[K] extends bigint ? bigint | undefined : never }; //#endregion //#region ../packages/rx/src/from/types.d.ts type TriggerValue<TTriggerValue> = { value: TTriggerValue; }; /** * Options for the 'count' source. */ type CountOptions = { /** * Determines when counting starts * @defaultValue 'initial' */ lazy: Lazy; /** * Amount to increment by * @defaultValue 1 */ amount: number; /** * Where to begin counting * @defaultValue 0 */ offset: number; /** * How long to wait before incrementing. * @defaultValue 1 second */ interval: Interval; /** * Abort signal to trigger the source to close. */ signal: AbortSignal; }; /** * Function which returns a result. Or promised result. * * `abort` value is a callback to exit out of looped execution. */ type FunctionFunction<T> = ((abort: (reason: string) => void) => T) | ((abort: (reason: string) => void) => Promise<T>); type ArrayOptions = { /** * Interval between each item being read. Default: 5ms. */ interval: Interval; lazy: Lazy; /** * Behaviour when reactive stops, for example due to having no subscribers * * continue: iteration continues through array where it left off * * reset: iteration begins from start of array */ whenStopped: `continue` | `reset`; debugLifecycle: boolean; signal: AbortSignal; }; /** * Function which returns a result. Or promised result. * Takes a `value` as first parameter, and callback to signal an abort as the second. */ type PingedFunctionFunction<T, TSource> = ((value: TSource, abort: (reason: string) => void) => T) | ((value: TSource, abort: (reason: string) => void) => Promise<T>); /** * Trigger that calls a `fn`. * If `fn` returns _undefined_, it means the trigger is complete */ type TriggerFunction<TTriggerValue> = { fn: () => TTriggerValue; }; type TriggerGenerator<TTriggerValue> = { gen: IterableIterator<TTriggerValue>; }; /** * A trigger can be a value, a function or generator. Value triggers never complete. * * A trigger function is considered complete if it returns undefined. * A trigger generator is considered complete if it returns done. * */ type Trigger<TTriggerValue> = TriggerValue<TTriggerValue> | TriggerFunction<TTriggerValue> | TriggerGenerator<TTriggerValue>; type TimeoutPingOptions = Interval & { /** * If abort signals, it will disable */ abort?: AbortSignal; }; type TimeoutValueOptions<TTriggerValue> = Trigger<TTriggerValue> & { /** * Whether to repeatedly trigger even if upstream source doesn't emit values. * When _false_ (default) it will emit a max of one value after a source value if `interval` is reached. * When _true_, it will continue emitting values at `interval`. * Default: false */ repeat?: boolean; /** * Interval before emitting trigger value * Default: 1s */ interval: Interval; /** * If _true_ (default) start the timeout * immediately, even before the first value. * If _false_, it won't timeout until the first * upstream value happens. */ immediate?: boolean; }; /** * Options when creating a reactive object. */ type ObjectOptions<V extends Record<string, unknown>> = { /** * _false_ by default. * If _true_, inherited fields are included. This is necessary for event args, for example. */ deepEntries: boolean; /** * Uses JSON.stringify() by default. * Fn that returns _true_ if two values are equal, given a certain path. */ eq: IsEqualContext<V>; }; type ValueToPingOptions<TUpstream> = { /** * If set, this function acts as a threshold gate. * If the function returns _true_ the upstream value will trigger a ping * Otherwise the value won't trigger a ping. * * By default all values trigger a ping. * @param value * @returns */ gate: (value: TUpstream) => boolean; /** * Laziness * * start: only begins on first subscriber. Keeps running even when there are no subscribers * * very: only begins on first subscriber. Stops looping if there are no subscribers * * never: begins calling function when initalised and doesn't stop until Reactive is disposed */ lazy: Lazy; /** * If specified, signal is checked to prevent function execution. * Also used for aborting a looped fromFunction. */ signal: AbortSignal; }; type PingedFunctionOptions = { /** * If _true_, stream closes if function throws an error. * If _false_, errors are emitted as signals, but stream is not closed. * Default: _true_ */ closeOnError: boolean; /** * Laziness * * start: only begins on first subscriber. Keeps running even when there are no subscribers * * very: only begins on first subscriber. Stops looping if there are no subscribers * * never: begins calling function when initalised and doesn't stop until Reactive is disposed */ lazy: Lazy; /** * If specified, a time before invoking function. * If `repeat` is used, this is in addition to `interval` time. */ predelay: Interval; /*** * If specified, signal is checked to prevent function execution. * Also used for aborting a looped fromFunction. */ signal: AbortSignal; }; /** * Options when creating a reactive object. */ type ArrayObjectOptions<V> = { /** * Uses JSON.stringify() by default. * Fn that returns _true_ if two values are equal, given a certain path. */ eq: IsEqual<V>; }; type FunctionOptions = Partial<InitLazyStreamOptions> & { /** * If _true_, stream closes if function throws an error. * If _false_, errors are emitted as signals, but stream is not closed. * Default: _true_ */ closeOnError: boolean; /** * Laziness * * start: only begins on first subscriber. Keeps running even when there are no subscribers * * very: only begins on first subscriber. Stops looping if there are no subscribers * * never: begins calling function when initalised and doesn't stop until Reactive is disposed */ lazy: Lazy; /** * If _true_, no automatic calling of function will happen, it will only * be executed if the reactive gets a ping * When this is set, 'interval' is ignored. 'maximumRepeats' and 'predelay' still apply. * Default: _false_ */ manual: boolean; /** * If specified, sets an upper limit of how many times we loop * (if this is also enabled) */ maximumRepeats: number; /** * If specified, function is called repeatedly with this delay */ interval: Interval; /** * If specified, a time before invoking function. * If `repeat` is used, this is in addition to `interval` time. */ predelay: Interval; /*** * If specified, signal is checked to prevent function execution. * Also used for aborting a looped fromFunction. */ signal: AbortSignal; }; type GeneratorOptions = { traceLifecycle: boolean; /** * Wait between reading from generator * Default: 5ms */ readInterval: Interval; /** * Timeout when waiting for a value * Default: `{ mins: 5 }` */ readTimeout: Interval; /** * If _true_, only accesses the generator if there is a subscriber. * Default: true */ lazy: Lazy; signal: AbortSignal; /** * Behaviour when reactive stops, for example due to having no subscribers * * continue: iteration continues through array where it left off * * reset: iteration begins from start of array */ whenStopped: `continue` | `reset`; }; type EventSourceOptions = { /** * If true, behaves like Source.object where event * properties are compared and source only * emits where there is a change. * * Default: _false_ */ diff?: boolean; lazy?: Lazy; /** * If true, log messages are emitted * when event handlers are added/removed */ debugLifecycle?: boolean; /** * If true, log messages are emitted * when the source event fires */ debugFiring?: boolean; }; type EventSourceTriggerOptions = EventSourceOptions & { /** * If _true_ sends an initial trigger when starting * Default: false */ fireInitial: boolean; }; type EventPluckedFieldOptions<T> = { lazy?: Lazy; initialValue: T; }; type EventPluckedFieldOptions2<TDomSource, TValueDestination> = { lazy?: Lazy; initialValue: TValueDestination; domToValue: (value: TDomSource | undefined) => TValueDestination | undefined; valueToDom: (value: TValueDestination) => TDomSource; }; type DerivedFunction<TOutput> = (...args: unknown[]) => TOutput; type DerivedOptions<TResult, T> = { ignoreIdentical: boolean; eq: (a: TResult, b: TResult) => boolean; } & CombineLatestOptions & UpstreamOptions<T>; //#endregion //#region ../packages/rx/src/ops/annotate.d.ts /** * Annotates values from `source`. Output values will be * in the form `{ value: TIn, annotation: TAnnotation }`. * Where `TIn` is the type of the input, and `TAnnotation` is * the return type of the annotator function. * * Example calculating area from width & height: * ```js * const data = Rx.From.array( * { w: 1, h: 3 }, { w: 1, h: 1 }, { w: 2, h: 2 } * ); * const annotated = Rx.Ops.annotate(data, v => { * return { area: v.w * v.h } * }); * const data = await Rx.toArray(annotated); * // Data = [ { value: { w:1, h:3 }, annotation: { area:3 } } ...] * ``` * * If you would rather annotate and have values merge with the input, * use `transform`: * ```js * const data = Rx.From.array( * { w: 1, h: 3 }, { w: 1, h: 1 }, { w: 2, h: 2 } * ); * const withArea = Rx.Ops.transform(data, v => { * return { ...v, area: v.w * v.h } * }); * const data = await Rx.toArray(withArea); * // Data = [ { w:1, h:3, area:3 }, ...] * ``` */ declare function annotate<In, TAnnotation>(input: ReactiveOrSource<In>, annotator: (value: In) => TAnnotation, options?: Partial<TransformOpts>): Reactive<{ value: In; annotation: TAnnotation; }>; /** * Annotates the input stream using {@link ReactiveOp} as the source of annotations. * The output values will have the shape of `{ value: TIn, annotation: TAnnotation }`. * Meaning that the original value is stored under `.value`, and the annotation under `.annotation`. * * ```js * const data = Rx.From.array([ 1, 2, 3 ]); * const annotated = Rx.Ops.annotateWithOp(data, Rx.Ops.sum()); * const data = await annotated.toArray(annotated); * // Data = [ { value: 1, annotation: 1 }, { value: 2, annotation: 3 }, { value: 3, annotation: 6 } ] * ``` * @param annotatorOp Operator to generate annotations * @param input Input stream * @returns */ declare function annotateWithOp<In, TAnnotation>(input: ReactiveOrSource<In>, annotatorOp: ReactiveOp<In, TAnnotation>): Reactive<{ value: In; annotation: TAnnotation; }>; //#endregion //#region ../packages/rx/src/ops/chunk.d.ts /** * Queue from `source`, emitting when thresholds are reached. * The resulting Reactive produces arrays. * * Can use a combination of elapsed time or number of data items. * * By default options are OR'ed together. * * ```js * // Emit data in chunks of 5 items * chunk(source, { quantity: 5 }); * // Emit a chunk of data every second * chunk(source, { elapsed: 1000 }); * ``` * @param source * @param options * @returns */ declare function chunk<V>(source: ReactiveOrSource<V>, options?: Partial<ChunkOptions>): Reactive<V[]>; //#endregion //#region ../packages/rx/src/ops/clone-from-fields.d.ts /** * Create a new object from input, based on cloning fields rather than a destructured copy. * This is useful for event args. * @param source * @returns */ declare const cloneFromFields: <In>(source: ReactiveOrSource<In>) => Reactive<In>; //#endregion //#region ../packages/rx/src/ops/combine-latest-to-array.d.ts /** * Monitors input reactive values, storing values as they happen to an array. * Whenever a new value is emitted, the whole array is sent out, containing current * values from each source, or _undefined_ if not yet emitted. * * See {@link combineLatestToObject} to combine streams by name into an object, rather than array. * * ``` * const sources = [ * Rx.fromFunction(Math.random, { loop: true, interval: 100 }), * Rx.fromFunction(Math.random, { loop: true, interval: 200 }) * ]; * const r = Rx.combineLatestToArray(sources); * r.onValue(value => { * // Value will be an array of last value from each source: * // [number,number] * }); * ``` * * The tempo of this stream will be set by the fastest source stream. * See {@link syncToArray} to have pace determined by slowest source, and only * send when each source has produce a new value compared to last time. * * Set `onSourceDone` to choose behaviour if a source stops. By default it * is 'break', meaning the whole merged stream stops. * * Note: unlike RxJS's `combineLatest`, does not wait for each source to emit once * before emitting first value. * @param reactiveSources Sources to merge * @param options Options for merging * @returns */ declare function combineLatestToArray<const T extends readonly ReactiveOrSource<any>[]>(reactiveSources: T, options?: Partial<CombineLatestOptions>): Reactive<RxValueTypes<T>>; //#endregion //#region ../packages/rx/src/ops/combine-latest-to-object.d.ts type CombineLatestToObject<T extends Record<string, ReactiveOrSource<any>>> = { hasSource: (field: string) => boolean; replaceSource: (field: Extract<keyof T, string>, source: ReactiveOrSource<any>) => void; /** * Reactive sources being combined */ sources: RxValueTypeRx<T>; /** * Updates writable sources with values. * @param data * @returns Keys and values set to writable source(s) */ setWith: (data: Partial<RxValueTypeObject<T>>) => Partial<RxValueTypeObject<T>>; } & ReactiveDiff<RxValueTypeObject<T>> & ReactiveInitial<RxValueTypeObject<T>>; /** * Monitors input reactive values, storing values as they happen to an object. * Whenever a new value is emitted, the whole object is sent out, containing current * values from each source (or _undefined_ if not yet emitted) * * See {@link combineLatestToArray} to combine streams by name into an array instead. * * ``` * const sources = { * fast: Rx.fromFunction(Math.random, { loop: true, interval: 100 }), * slow: Rx.fromFunction(Math.random, { loop: true, interval: 200 }) * ]; * const r = Rx.combineLatestToObject(sources); * r.onValue(value => { * // 'value' will be an object containing the labelled latest * // values from each source. * // { fast: number, slow: number } * }); * ``` * * The tempo of this stream will be set by the fastest source stream. * See {@link syncToObject} to have pace determined by slowest source, and only * send when each source has produce a new value compared to last time. * * This source ends if all source streams end. * @param reactiveSources Sources to merge * @param options Options for merging * @returns */ declare function combineLatestToObject<const T extends Record<string, ReactiveOrSource<any>>>(reactiveSources: T, options?: Partial<CombineLatestOptions>): CombineLatestToObject<T>; //#endregion //#region ../packages/rx/src/ops/compute-with-previous.d.ts /** * When there is a value from `input`, or the reactive is pinged, * this reactive emits the result of `fn`. * * `fn` is provided the previous value as well as the most recent value. * * If no previous value is available, the current value is emitted and `fn` is not called. * @param input * @param fn * @returns */ declare function computeWithPrevious<TIn>(input: ReactiveOrSource<TIn>, fn: (previous: TIn, current: TIn) => TIn): ReactivePingable<TIn>; //#endregion //#region ../packages/rx/src/ops/debounce.d.ts declare function debounce<V>(options: Partial<DebounceOptions>): ReactiveOp<V, V>; //#endregion //#region ../packages/rx/src/ops/elapsed.d.ts /** * Emits time in milliseconds since last message. * If it is the first value, 0 is used. * @param input * @returns */ declare const elapsed: <In>(input: ReactiveOrSource<In>) => Reactive<number>; //#endregion //#region ../packages/rx/src/ops/field.d.ts /** * From a source value, yields a field from it. Only works * if stream values are objects. * * If a source value doesn't have that field, it is skipped. * * @returns */ declare function field<TIn extends object, TFieldType>(fieldSource: ReactiveOrSource<TIn>, fieldName: keyof TIn, options?: Partial<FieldOptions<TIn, TFieldType>>): Reactive<TFieldType>; //#endregion //#region ../packages/rx/src/ops/filter.d.ts /** * Passes all values where `predicate` function returns _true_. */ declare function filter<In>(input: ReactiveOrSource<In>, predicate: FilterPredicate<In>, options: Partial<InitStreamOptions>): Reactive<In>; /** * Drops all values where `predicate` function returns _true_. */ declare function drop<In>(input: ReactiveOrSource<In>, predicate: FilterPredicate<In>, options: Partial<InitStreamOptions>): Reactive<In>; //#endregion //#region ../packages/rx/src/ops/interpolate.d.ts type OpInterpolateOptions = InterpolateOptions & { amount: number; /** * Percentage of value that we consider 'done'. * Since interpolation can never converge to target exactly, this allows us to snap to completion. * Default: 0.99, meaning if value gets to within 99%, return the target. */ snapAt: number; }; /** * Interpolates to the source value. * * Outputs one value for every input value. Thus, to interpolation * over time, it's necessary to get the source to emit values at the desired rate. * * Options can specify an easing name or custom transform of easing progress. * @param input * @param options * @returns */ declare function interpolate(input: ReactiveOrSource<number>, options?: Partial<OpInterpolateOptions>): ReactivePingable<number>; //#endregion //#region ../packages/rx/src/ops/pipe.d.ts /** * Pipes the output of one stream into another, in order. * The stream returned is a new stream which captures the final output. * * If any stream in the pipe closes the whole pipe is closed. * @param streams * @returns */ declare const pipe: <TInput, TOutput>(...streams: PipeSet<TInput, TOutput>) => Reactive<TOutput>; //#endregion //#region ../packages/rx/src/ops/single-from-array.d.ts /** * For a stream that emits arrays of values, this op will select a single value. * * Can select based on: * * predicate: a function that returns _true_ for a value * * at: selection based on array index (can be combined with random ordering to select a random value) * * ```js * // If source is Reactive<Array<number>>, picks the first even number * singleFromArray(source, { * predicate: v => v % 2 === 0 * }); * * // Selects a random value from source * singleFromArray(source, { * order: `random`, * at: 0 * }); * ``` * * If neither `predicate` or `at` options are given, exception is thrown. * @param source Source to read from * @param options Options for selection * @returns */ declare function singleFromArray<V>(source: ReactiveOrSource<V[]>, options?: Partial<SingleFromArrayOptions<V>>): Reactive<V>; //#endregion //#region ../packages/rx/src/ops/split.d.ts /** * Creates a set of streams each of which receives data from `source`. * By default these are lazy and dispose if the upstream source closes. * * See also {@link splitLabelled} to split into named streams. * @param rxOrSource * @param options * @returns */ declare const split: <T>(rxOrSource: ReactiveOrSource<T>, options?: Partial<SplitOptions>) => ReactiveStream<T>[]; /** * Splits `source` into several duplicated streams. * Returns an object with keys according to `labels`. * Each value is a stream which echos the values from `source`. * ```js * const { a, b, c} = splitLabelled(source, `a`, `b`, `c`); * // a, b, c are Reactive types * ``` * * See also {@link split} to get an unlabelled split * @param rxOrSource * @param labels * @returns */ declare const splitLabelled: <T, K extends PropertyKey>(rxOrSource: ReactiveOrSource<T>, labels: K[]) => Record<K, Reactive<T>>; //#endregion //#region ../packages/rx/src/ops/switcher.d.ts /** * Switcher generates several output streams, labelled according to the values of `cases`. * Values from `source` are fed to the output streams if their associated predicate function returns _true_. * * In this way, we can split one input stream into several output streams, each potentially getting a different * subset of the input. * * With `options`, you can specify whether to send to multiple outputs if several match, or just the first (default behaviour). * * The below example shows setting up a switcher and consuming the output streams. * @example * ```js * // Initialise a reactive number, starting at 0 * const switcherSource = Reactive.number(0); * // Set up the switcher * const x = Reactive.switcher(switcherSource, { * even: v => v % 2 === 0, * odd: v => v % 2 !== 0 * }); * // Listen for outputs from each of the resulting streams * x.even.on(msg => { * log(`even: ${msg.value}`); * }); * x.odd.on(msg => { * log(`odd: ${msg.value}`); * }) * // Set new values to the number source, counting upwards * // ...this will in turn trigger the outputs above * setInterval(() => { * switcherSource.set(switcherSource.last() + 1); * }, 1000); * ``` * * If `source` closes, all the output streams will be closed as well. * @param reactiveOrSource * @param cases * @param options * @returns */ declare const switcher: <TValue, TRec extends Record<string, FilterPredicate<TValue>>, TLabel extends keyof TRec>(reactiveOrSource: ReactiveOrSource<TValue>, cases: TRec, options?: Partial<SwitcherOptions>) => Record<TLabel, Reactive<TValue>>; //#endregion //#region ../packages/rx/src/ops/sync-to-array.d.ts /** * Waits for all sources to produce a value, sending the combined results as an array. * After sending, it waits again for each source to send at least one value. * * Use {@link syncToObject} to output objects based on labelled sources rather than an array of values. * * Pace will be set by the slowest source. Alternatively, use {@link combineLatestToArray} where the rate is determined by fastest source. * * Only complete results are sent. For example if source A & B finish and source C is still producing values, * synchronisation is not possible because A & B stopped producing values. Thus the stream will self-terminate * after `maximumWait` (2 seconds). The newer values from C are lost. */ declare function syncToArray<const T extends readonly ReactiveOrSource<any>[]>(reactiveSources: T, options?: Partial<SyncOptions>): Reactive<RxValueTypes<T>>; //#endregion //#region ../packages/rx/src/ops/sync-to-object.d.ts declare function syncToObject<const T extends Record<string, ReactiveOrSource<any>>>(reactiveSources: T, options?: Partial<SyncOptions>): Reactive<RxValueTypeObject<T>>; //#endregion //#region ../packages/rx/src/ops/tap.d.ts /** * 'Taps' the values from 'input', passing them to the 'process' function. * Return stream is the input stream, unaffected by what 'process' does. * @param input Input stream * @param processors List of processors * @returns */ declare function tapProcess<In, T2, T3, T4, T5, T6>(input: ReactiveOrSource<In>, ...processors: Processors<In, T2, T3, T4, T5, T6>): Reactive<In>; /** * 'Taps' the values from 'input', passing them to 'diverged' * Returns the original input stream, unaffected by what 'diverged' does. * @param input Input stream * @param diverged Stream to write to * @returns */ declare function tapStream<In>(input: ReactiveOrSource<In>, diverged: ReactiveWritable<In>): Reactive<In>; /** * Create a parallel 'tap' of processing * @param input Input stream * @param ops Series of ops to process data * @returns */ declare const tapOps: <TIn, TOut>(input: ReactiveOrSource<TIn>, ...ops: ReactiveOp<TIn, TOut>[]) => Reactive<TOut>; //#endregion //#region ../packages/rx/src/ops/throttle.d.ts /** * Only allow a value through if a minimum amount of time has elapsed. * since the last value. This effectively slows down a source to a given number * of values/ms. Values emitted by the source which are too fast are discarded. * * Throttle will fire on the first value received. * * In more detail: * Every time throttle passes a value, it records the time it allowed something through. For every * value received, it checks the elapsed time against this timestamp, throwing away values if * the period hasn't elapsed. * * With this logic, a fury of values of the source might be discarded if they fall within the elapsed time * window. But then if there is not a new value for a while, the actual duration between values can be longer * than expected. This is in contrast to {@link debounce}, which will emit the last value received after a duration, * even if the source stops sending. * @param options * @returns */ declare function throttle<V>(throttleSource: ReactiveOrSource<V>, options?: Partial<ThrottleOptions>): Reactive<V>; //#endregion //#region ../packages/rx/src/ops/timeout-value.d.ts /** * Emits a value if `source` does not emit a value after `interval` * has elapsed. This can be useful to reset a reactive to some * 'zero' state if nothing is going on. * * If `source` emits faster than the `interval`, it won't get triggered. * * Default for 'timeout': 1000s. * * ```js * // Emit 'hello' if 'source' doesn't emit a value after 1 minute * const r = Rx.timeoutValue(source, { value: 'hello', interval: { mins: 1 } }); * ``` * * Can also emit results from a function or generator * ```js * // Emits a random number if 'source' doesn't emit a value after 500ms * const r = Rx.timeoutValue(source, { fn: Math.random, interval: 500 }); * ``` * * If `immediate` option is _true_ (default), the timer starts from stream initialisation. * Otherwise it won't start until it observes the first value from `source`. * @param source * @param options */ declare function timeoutValue<TSource, TTriggerValue>(source: ReactiveOrSource<TSource>, options: TimeoutValueOptions<TTriggerValue>): Reactive<TSource | TTriggerValue>; //#endregion //#region ../packages/rx/src/ops/timeout-ping.d.ts /** * Pings a reactive if no value is emitted at after `interval`. * Returns `source`. * * ```js * // Ping `source` if no value is emitted after one minute * const r = Rx.timeoutPing(source, { mins: 1 }); * ``` * * Behavior can be stopped using an abort signal. * @see {@link ReactivePingable} * @param source * @param options */ declare function timeoutPing<TSource>(source: ReactiveOrSource<TSource>, options: TimeoutPi