deanius/polyrhythm

View on GitHub
src/types.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { Observable, Subscriber } from 'rxjs';
export { Subscriber, Subscription } from 'rxjs';

export interface Event {
  type: string;
  payload?: any;
  error?: boolean;
  meta?: Object;
}
export interface EventWithAnyFields extends Event {
  [others: string]: any;
}
export interface EventWithResult extends Event {
  result?: Promise<any>;
}
/* A function that can be used as an EventMatcher. */
export interface Predicate {
  (item: Event): boolean;
}

export interface AwaitableObservable<T> extends PromiseLike<T>, Observable<T> {}

export type EventMatcher = string | string[] | RegExp | Predicate | boolean;

interface PromiseFactory<T> {
  (): Promise<T>;
}
interface ObservableConstructorFn<T> {
  (notify: Subscriber<T>): void | Function;
}

export type EffectDescriptor<T> =
  | Promise<T>
  | PromiseFactory<T>
  | AwaitableObservable<T>
  | Generator<T>
  | Observable<T>
  | ObservableConstructorFn<T>;

/**
 * A Filter runs a synchronous function prior to any listeners
 * being invoked, and can cancel future filters, and all listeners
 * by throwing an exception, which must be caught by the caller of
 * `trigger`. It may cancel or replace the event by returning `null` or non-null.
 *
 * It does *not*, as its name might suggest, split off a slice of the
 * stream. To do that see `query`.
 * @see query
 */
export interface Filter<T> {
  (item: T): void | null | EventWithAnyFields;
}

/**
 * The function you assign to `.on(eventType, fn)`
 * events is known as a Listener. It receives the event.
 */
export interface Listener<T, U> {
  (item: T): void | any | EffectDescriptor<U>;
}

/**
 * When a listener is async, returning an Observable, it's possible
 * that a previous Observable of that listener is running already.
 * Concurrency modes control how the new and old listener are affected
 * when when they overlap.
 *
 * ![concurrency modes](https://s3.amazonaws.com/www.deanius.com/ConcurModes2.png)
 */
export enum ConcurrencyMode {
  /**
   * Newly returned Observables are subscribed immediately, without regard to resource constraints, or the ordering of their completion. (ala mergeMap) */
  parallel = 'parallel',
  /**
   * Observables are enqueued and always complete in the order they were triggered. (ala concatMap)*/
  serial = 'serial',
  /**
   * Any existing Observable is canceled, and a new is begun (ala switchMap) */
  replace = 'replace',
  /**
   * Any new Observable is not subscribed if another is running. (ala exhaustMap) */
  ignore = 'ignore',
  /**
   * Any new Observable is not subscribed if another is running, and
   * the previous one is canceled. (ala switchMap with empty() aka toggleMap) */
  toggle = 'toggle',
}

export interface TriggerConfig {
  next?: string;
  complete?: string;
  error?: string;
  start?: string;
}

export interface ListenerConfig {
  /** The concurrency mode to use. Governs what happens when another handling from this handler is already in progress. */
  mode?:
    | ConcurrencyMode
    | 'serial'
    | 'parallel'
    | 'replace'
    | 'ignore'
    | 'toggle';
  /** A declarative way to map the Observable returned from the listener onto new triggered events */
  trigger?: TriggerConfig | true;
  takeUntil?: EventMatcher;
}

export interface Thunk<T> {
  (): T;
}