import { Observer, Property, Event, isValue, valueEvent, endEvent, PropertySeed, Function0, Function1, Function2, Function3, Function4, Function5, Function6, isProperty, Desc, } from "./abstractions" import { StatelessProperty, PropertySeedImpl, StatefulProperty, } from "./property" import { globalScope, intersectionScope } from "./scope" import { argumentsToObservablesAndFunction } from "./argumentstoobservables" import { cached } from "./cached" import { nop, rename, toString } from "./util" import { cachedFn } from "./cachedFn" /** Combines given *n* Properties and EventStreams using the given n-ary function `f(v1, v2 ...)`. To calculate the current sum of three numeric Properties, you can do ```js function sum3(x,y,z) { return x + y + z } combine(sum3, p1, p2, p3) ``` */ export type PropertyLike = Property | PropertySeed export function combineAsArray(observables: Property[]): Property export function combineAsArray( observables: PropertySeed[] ): PropertySeed export function combineAsArray( observables: Property[] | PropertySeed[] ): PropertyLike { return rename( ["combineAsArray", observables], combine(observables as any, (...xs: V[]) => xs) ) } export function combine(fn: Function0): Property export function combine(a: Property, fn: Function1): Property export function combine( a: Property, b: Property, fn: Function2 ): Property export function combine( a: Property, b: Property, c: Property, fn: Function3 ): Property export function combine( a: Property, b: Property, c: Property, d: Property, fn: Function4 ): Property export function combine( a: Property, b: Property, c: Property, d: Property, e: Property, fn: Function5 ): Property export function combine( a: Property, b: Property, c: Property, d: Property, e: Property, f: Property, fn: Function6 ): Property export function combine( properties: Property[], fn: (...values: V[]) => R ): Property export function combine(fn: Function1, a: Property): Property export function combine( fn: Function2, a: Property, b: Property ): Property export function combine( fn: Function3, a: Property, b: Property, c: Property ): Property export function combine( fn: Function4, a: Property, b: Property, c: Property, d: Property ): Property export function combine( fn: Function5, a: Property, b: Property, c: Property, d: Property, e: Property ): Property export function combine( fn: Function6, a: Property, b: Property, c: Property, d: Property, e: Property, f: Property ): Property export function combine( fn: (...values: V[]) => R, Propertys: Property[] ): Property export function combine( a: PropertySeed, fn: Function1 ): PropertySeed export function combine( a: PropertySeed, b: PropertySeed, fn: Function2 ): PropertySeed export function combine( a: PropertySeed, b: PropertySeed, c: PropertySeed, fn: Function3 ): PropertySeed export function combine( a: PropertySeed, b: PropertySeed, c: PropertySeed, d: PropertySeed, fn: Function4 ): PropertySeed export function combine( a: PropertySeed, b: PropertySeed, c: PropertySeed, d: PropertySeed, e: PropertySeed, fn: Function5 ): PropertySeed export function combine( a: PropertySeed, b: PropertySeed, c: PropertySeed, d: PropertySeed, e: PropertySeed, f: PropertySeed, fn: Function6 ): PropertySeed export function combine( properties: PropertySeed[], fn: (...values: V[]) => R ): PropertySeed export function combine( fn: Function1, a: PropertySeed ): PropertySeed export function combine( fn: Function2, a: PropertySeed, b: PropertySeed ): PropertySeed export function combine( fn: Function3, a: PropertySeed, b: PropertySeed, c: PropertySeed ): PropertySeed export function combine( fn: Function4, a: PropertySeed, b: PropertySeed, c: PropertySeed, d: PropertySeed ): PropertySeed export function combine( fn: Function5, a: PropertySeed, b: PropertySeed, c: PropertySeed, d: PropertySeed, e: PropertySeed ): PropertySeed export function combine( fn: Function6, a: PropertySeed, b: PropertySeed, c: PropertySeed, d: PropertySeed, e: PropertySeed, f: PropertySeed ): PropertySeed export function combine( fn: (...values: V[]) => R, Propertys: PropertySeed[] ): PropertySeed export function combine(...args: any[]): PropertyLike { let [properties, combinator] = argumentsToObservablesAndFunction< Out, Property >(args) const seeds = !(properties.length === 0 || isProperty(properties[0])) combinator = cachedFn(combinator) function getCurrentArray(): any[] { return properties.map((s) => s.get()) } const get = () => combinator(...getCurrentArray()) const subscribe = (seeds ? subscribeSeeds : subscribeProps)( properties, getCurrentArray, combinator ) const desc = ["combine", [properties, combinator]] as Desc if (!seeds) { const scope = intersectionScope(properties.map((p) => p.getScope())) return new StatelessProperty>( desc, get, subscribe, scope ) } else { return new PropertySeedImpl(desc, get, subscribe) } } const subscribeProps = ( properties: Property[], getCurrentArray: () => any[], combinator: (...args: any[]) => Out ) => (onValue: Observer, onEnd: Observer = nop) => { let endCount = 0 const unsubs = properties.map((src, i) => { return src.onChange( () => { onValue(combinator(...getCurrentArray())) }, () => { endCount++ if (endCount == properties.length) { onEnd() } } ) }) return () => { unsubs.forEach((f) => f()) } } const subscribeSeeds = ( properties: Property[], getCurrentArray: () => any[], combinator: (...args: any[]) => Out ) => (onValue: Observer, onEnd: Observer = nop) => { let endCount = 0 const unsubs = properties.map((src, i) => { return src.onChange( (value) => { currentArray[i] = value onValue(combinator(...currentArray)) }, () => { endCount++ if (endCount == properties.length) { onEnd() } } ) }) let currentArray = getCurrentArray() return () => { unsubs.forEach((f) => f()) } }