import { Observable } from "rxjs"; import { UserId } from "../../types/guid"; import { StateUpdateOptions } from "./state-update-options"; export type CombinedState = readonly [userId: UserId, state: T]; /** A helper object for interacting with state that is scoped to a specific user. */ export interface UserState { /** Emits a stream of data. Emits null if the user does not have specified state. */ readonly state$: Observable; /** Emits a stream of tuples, with the first element being a user id and the second element being the data for that user. */ readonly combinedState$: Observable>; } export const activeMarker: unique symbol = Symbol("active"); export interface ActiveUserState extends UserState { readonly [activeMarker]: true; /** * Emits a stream of data. Emits null if the user does not have specified state. * Note: Will not emit if there is no active user. */ readonly state$: Observable; /** * Updates backing stores for the active user. * @param configureState function that takes the current state and returns the new state * @param options Defaults to @see {module:state-update-options#DEFAULT_OPTIONS} * @param options.shouldUpdate A callback for determining if you want to update state. Defaults to () => true * @param options.combineLatestWith An observable that you want to combine with the current state for callbacks. Defaults to null * @param options.msTimeout A timeout for how long you are willing to wait for a `combineLatestWith` option to complete. Defaults to 1000ms. Only applies if `combineLatestWith` is set. * * @returns A promise that must be awaited before your next action to ensure the update has been written to state. * Resolves to the new state. If `shouldUpdate` returns false, the promise will resolve to the current state. */ readonly update: ( configureState: (state: T | null, dependencies: TCombine) => T | null, options?: StateUpdateOptions, ) => Promise<[UserId, T | null]>; } export interface SingleUserState extends UserState { readonly userId: UserId; /** * Updates backing stores for the active user. * @param configureState function that takes the current state and returns the new state * @param options Defaults to @see {module:state-update-options#DEFAULT_OPTIONS} * @param options.shouldUpdate A callback for determining if you want to update state. Defaults to () => true * @param options.combineLatestWith An observable that you want to combine with the current state for callbacks. Defaults to null * @param options.msTimeout A timeout for how long you are willing to wait for a `combineLatestWith` option to complete. Defaults to 1000ms. Only applies if `combineLatestWith` is set. * * @returns A promise that must be awaited before your next action to ensure the update has been written to state. * Resolves to the new state. If `shouldUpdate` returns false, the promise will resolve to the current state. */ readonly update: ( configureState: (state: T | null, dependencies: TCombine) => T | null, options?: StateUpdateOptions, ) => Promise; }