{"version":3,"file":"cyclone.modern.mjs","sources":["../../src/main/ts/error.ts","../../src/main/ts/generator.ts","../../src/main/ts/log.ts","../../src/main/ts/machine.ts","../../src/main/ts/registry.ts","../../src/main/ts/factory.ts"],"sourcesContent":["export const TRANSITION_VIOLATION = 'Transition violation'\nexport const INVALID_UNLOCK_KEY = 'Invalid unlock key'\nexport const LOCK_VIOLATION = 'Lock violation'\nexport const UNREACHABLE_STATE = 'Unreachable state'\n\nexport class MachineError extends Error {}\n","export const generateDate = (): Date => new Date()\nexport const generateId = (): string => Math.random().toString()\n","export const LOG_PREFIX = '[cyclone]'\n\nexport const debug = console.debug.bind(console, LOG_PREFIX)\nexport const info = console.info.bind(console, LOG_PREFIX)\nexport const error = console.error.bind(console, LOG_PREFIX)\nexport const warn = console.warn.bind(console, LOG_PREFIX)\n\nexport const log = {\n  debug,\n  info,\n  error,\n  warn\n}\n","import {\n  INVALID_UNLOCK_KEY,\n  LOCK_VIOLATION,\n  MachineError,\n  TRANSITION_VIOLATION,\n  UNREACHABLE_STATE\n} from './error'\nimport {\n  generateDate,\n  generateId\n} from './generator'\nimport { log } from './log'\n\ntype IState = string\n\ntype IAny = any\n\ntype IHandler = (data: IAny, ...payload: Array<IAny>) => IAny\n\ntype ITransitions = {\n  [key: string]: IHandler | null | boolean\n}\n\ntype IMachineOpts = {\n  transitions: ITransitions,\n  initialState?: IState,\n  initialData?: IAny,\n  immutable?: boolean,\n  historySize?: number\n}\n\nexport const DELIMITER = '>'\nexport const DEFAULT_HANDLER: IHandler = (...last) => last.pop()\nexport const DEFAULT_HISTORY_SIZE = 10\nexport const DEFAULT_OPTS: IMachineOpts = {\n  transitions: {},\n  historySize: DEFAULT_HISTORY_SIZE,\n  immutable: false\n}\n\ntype IKey = string | null\n\ntype IDigest = {\n  state?: IState,\n  data?: IAny\n}\n\ntype IHistoryItem = {\n  state: IState,\n  data: IAny,\n  id: string,\n  date: Date\n}\ntype IHistory = IHistoryItem[]\n\ninterface IMachine {\n  next(state: IState, ...payload: Array<IAny>): IMachine,\n  prev(state?: IState): IMachine,\n  current(): IDigest,\n  lock(key?: IKey): IMachine,\n  unlock(key: IKey): IMachine,\n\n  transitions: ITransitions,\n  history: IHistory,\n  opts: IMachineOpts,\n  key: IKey,\n  id: string,\n}\n\ntype IPredicate = (item: IHistoryItem) => boolean\n\nexport class Machine implements IMachine {\n\n  /**\n   * Machine options.\n   * @property\n   */\n  public opts: IMachineOpts\n\n  /**\n   * State history.\n   * @property\n   */\n  public history: IHistory\n\n  /**\n   * Lock key.\n   * @property\n   */\n  public key: IKey\n\n  /**\n   * Unique machine id\n   * @property\n   */\n  public id: string\n\n  /**\n   * Transition handler map\n   * @property\n   */\n  public transitions: ITransitions\n\n  constructor(opts: IMachineOpts) {\n    this.opts = { ...DEFAULT_OPTS, ...opts }\n    this.history = []\n    this.key = null\n    this.id = generateId()\n    this.transitions = opts.transitions\n\n    if (typeof opts.initialState === 'string') {\n      this.history.push({\n        state: opts.initialState,\n        data: opts.initialData,\n        id: generateId(),\n        date: generateDate()\n      })\n    }\n\n    return this\n  }\n\n  /**\n   * Provides next state transition.\n   * @param state Next state name.\n   * @param payload Any data for handler.\n   */\n  public next(state: IState, ...payload: Array<IAny>): IMachine {\n    if (this.key) {\n      throw new MachineError(LOCK_VIOLATION)\n    }\n\n    const handler = Machine.getHandler(state, this.history, this.transitions)\n    const current = this.current()\n    const data = handler(current.data, ...payload)\n    const id = generateId()\n    const date = generateDate()\n\n    this.history.push({\n      state,\n      data,\n      id,\n      date\n    })\n\n    if (this.history.length > Machine.getHistoryLimit(this.opts.historySize)) {\n      log.debug('history limit reached')\n      this.history.shift()\n    }\n\n    return this\n  }\n\n  /**\n   * Returns the machine's digest: state name and stored data.\n   */\n  public current(): IHistoryItem {\n    return { ...this.history[this.history.length - 1] }\n  }\n\n  /**\n   * Returns the last state, that satisfies the condition\n   */\n  public last(condition?: string | IPredicate): IHistoryItem | void {\n    if (condition === undefined) {\n      return this.current()\n    }\n\n    const filter = typeof condition === 'string'\n      ? ({ state }: IHistoryItem) => state === condition\n      : condition\n\n    return [...this.history].reverse().find(filter)\n  }\n\n  /**\n   * Reverts current state to the previous.\n   * @param state\n   */\n  public prev(state?: string | IPredicate): IMachine {\n    if (this.key) {\n      throw new MachineError(LOCK_VIOLATION)\n    }\n\n    if (this.history.length < 2) {\n      throw new MachineError(UNREACHABLE_STATE)\n    }\n\n    if (state === undefined) {\n      this.history.pop()\n      return this\n    }\n\n    const last = this.last(state)\n    if (!last) {\n      throw new MachineError(UNREACHABLE_STATE)\n    }\n\n    this.history.length = this.history.indexOf(last) + 1\n\n    return this\n  }\n\n  /**\n   * Locks the machine. Any transitions are prohibited before unlocking.\n   * @param key\n   */\n  public lock(key?: IKey): IMachine {\n    this.key = key || `lock${generateId()}`\n\n    return this\n  }\n\n  /**\n   * Unlocks the machine.\n   * @param key\n   */\n  public unlock(key: IKey): IMachine {\n    if (this.key !== key) {\n      throw new MachineError(INVALID_UNLOCK_KEY)\n    }\n\n    this.key = null\n\n    return this\n  }\n\n  public static getHistoryLimit(historySize?: number): number {\n    if (historySize === undefined) {\n      return DEFAULT_HISTORY_SIZE\n    }\n\n    if (historySize === -1) {\n      return Number.POSITIVE_INFINITY\n    }\n\n    return historySize\n  }\n\n  public static getHandler(next: IState, history: IHistory, transitions: ITransitions): IHandler {\n    const targetTransition = this.getTargetTransition(next, history)\n    const nextTransition = this.getTransition(targetTransition, transitions)\n\n    if (!nextTransition) {\n      throw new MachineError(TRANSITION_VIOLATION)\n    }\n\n    const handler = transitions[nextTransition]\n\n    return typeof handler === 'function'\n      ? handler\n      : DEFAULT_HANDLER\n  }\n\n  public static getTransition(targetTransition: string, transitions: ITransitions): string | void {\n    // TODO Support wildcards\n    // TODO Support OR operator\n    // TODO Generate patterns in constructor\n    return Object.keys(transitions)\n      .filter(transition => targetTransition.length > transition.length\n        ? new RegExp(`.*${transition}$`).test(targetTransition)\n        : targetTransition === transition\n      )\n      .sort((a, b) => b.length - a.length)[0]\n  }\n\n  public static getTargetTransition(next: IState, history: IHistory): string {\n    return [...history.map(({ state }: IHistoryItem) => state), next]\n      .join(DELIMITER)\n  }\n\n  /**\n   * Returns the last passes argument as a result\n   * @param {any} state\n   * @param {any} [payload]\n   * @return {any}\n   */\n  public DEFAULT_HANDLER = DEFAULT_HANDLER\n\n}\n\nexport {\n  IMachine, IHistory, ITransitions, IHistoryItem, IHandler, IMachineOpts\n}\n","export class Registry {\n\n  store: { [key: string]: any }\n\n  constructor () {\n    this.store = {}\n  }\n\n  get (key: string): void {\n    return this.store[key]\n  }\n\n  add (key: string, value: any): void {\n    this.store[key] = value\n  }\n\n  remove (key: string): void {\n    delete this.store[key]\n  }\n\n}\n","import {\n  DEFAULT_OPTS as DEFAULT_MACHINE_OPTS,\n  IMachine,\n  IMachineOpts,\n  Machine} from './machine'\nimport {\n  Registry\n} from './registry'\n\nexport const DEFAULT_TEMPLATE = {}\nexport const DEFAULT_TEMPLATE_REGISTRY = new Registry()\nexport const DEFAULT_MACHINE_REGISTRY = new Registry()\n\ntype IFactoryOpts = {\n  machine?: IMachineOpts\n  template?: string | Object\n  templateRegistry?: Registry\n  machineRegistry?: Registry\n}\n\nexport const factory = (opts: IFactoryOpts): IMachine => {\n  // NOTE flowgen throws error on typed args destruction\n  const {\n    machine,\n    template,\n    templateRegistry = DEFAULT_TEMPLATE_REGISTRY,\n    machineRegistry = DEFAULT_MACHINE_REGISTRY\n  } = opts\n  const _template = getTemplate(template, templateRegistry)\n  const machineOpts: IMachineOpts = { ...DEFAULT_MACHINE_OPTS, ..._template, ...machine }\n  const instance = new Machine(machineOpts)\n\n  machineRegistry.add(instance.id, instance)\n\n  return instance\n}\n\nexport const getTemplate = (template: string | Object | void, templateRegistry: Registry): any => {\n  return typeof template === 'string'\n    ? templateRegistry.get(template)\n    : template\n}\n\nexport {\n  IFactoryOpts\n}\n"],"names":["TRANSITION_VIOLATION","INVALID_UNLOCK_KEY","LOCK_VIOLATION","UNREACHABLE_STATE","MachineError","Error","generateDate","Date","generateId","Math","random","toString","log","debug","console","bind","info","error","warn","DELIMITER","last","pop","DEFAULT_HISTORY_SIZE","DEFAULT_OPTS","transitions","historySize","immutable","Machine","constructor","opts","this","history","key","id","DEFAULT_HANDLER","_extends","initialState","push","state","data","initialData","date","next","payload","getHandler","handler","current","length","getHistoryLimit","shift","condition","undefined","filter","reverse","find","prev","indexOf","lock","unlock","static","POSITIVE_INFINITY","targetTransition","getTargetTransition","getTransition","nextTransition","Object","keys","transition","RegExp","test","sort","a","b","map","join","Registry","store","get","add","value","remove","DEFAULT_TEMPLATE","DEFAULT_TEMPLATE_REGISTRY","DEFAULT_MACHINE_REGISTRY","factory","machine","template","templateRegistry","machineRegistry","_template","getTemplate","machineOpts","DEFAULT_MACHINE_OPTS","instance"],"mappings":"AAAaA,MAAoBA,EAAG,uBACLC,EAAG,qBACPC,EAAG,iBACAC,EAAG,oBAE3B,MAAoBC,UAAaC,iPCLdC,EAAG,IAAY,IAAIC,KACrBC,EAAG,IAAcC,KAAKC,SAASC,WCMzCC,EAAM,CACjBC,MANmBC,QAAQD,MAAME,KAAKD,QAFd,aASxBE,KANkBF,QAAQE,KAAKD,KAAKD,QAHZ,aAUxBG,MANmBH,QAAQG,MAAMF,KAAKD,QAJd,aAWxBI,KANkBJ,QAAQI,KAAKH,KAAKD,QALZ,cC+BbK,EAAY,MACgB,IAAIC,IAASA,EAAKC,MAC9CC,EAAuB,GACvBC,EAA6B,CACxCC,YAAa,CAAA,EACbC,YAHkC,GAIlCC,WAAW,GAkCAC,MAAAA,EAgCXC,YAAYC,GAgBV,YA1CKA,UAAI,EAAAC,KAMJC,aAMAC,EAAAA,KAAAA,gBAMAC,QAAE,EAAAH,KAMFN,iBAAW,EAAAM,KAgLXI,gBAAkBA,EA7KvBJ,KAAKD,KAAIM,EAAA,CAAA,EAAQZ,EAAiBM,GAClCC,KAAKC,QAAU,GACfD,KAAKE,IAAM,KACXF,KAAKG,GAAKzB,IACVsB,KAAKN,YAAcK,EAAKL,YAES,iBAAtBK,EAAKO,cACdN,KAAKC,QAAQM,KAAK,CAChBC,MAAOT,EAAKO,aACZG,KAAMV,EAAKW,YACXP,GAAIzB,IACJiC,KAAMnC,MAIHwB,IACT,CAOOY,KAAKJ,KAAkBK,GAC5B,GAAIb,KAAKE,IACP,MAAU5B,IAAAA,EH/Hc,kBGkI1B,MAEUmC,EAFMZ,EAAQiB,WAAWN,EAAOR,KAAKC,QAASD,KAAKN,YAEhDqB,CADGf,KAAKgB,UACQP,QAASI,KAC3BnC,IACDiC,EAAGnC,IAcb,OAZAwB,KAAKC,QAAQM,KAAK,CAChBC,QACAC,OACAN,KACAQ,SAGEX,KAAKC,QAAQgB,OAASpB,EAAQqB,gBAAgBlB,KAAKD,KAAKJ,eAC1Db,EAAIC,MAAM,yBACViB,KAAKC,QAAQkB,SAGRnB,IACT,CAKOgB,UACL,OAAYX,EAAA,GAAAL,KAAKC,QAAQD,KAAKC,QAAQgB,OAAS,GACjD,CAKO3B,KAAK8B,GACV,QAAkBC,IAAdD,EACF,OAAWpB,KAACgB,UAGd,MAAYM,EAAwB,iBAALF,EAC3B,EAAGZ,WAA0BA,IAAUY,EACvCA,EAEJ,MAAO,IAAIpB,KAAKC,SAASsB,UAAUC,KAAKF,EAC1C,CAMOG,KAAKjB,GACV,GAAIR,KAAKE,IACP,MAAU5B,IAAAA,EHnLc,kBGsL1B,GAAI0B,KAAKC,QAAQgB,OAAS,EACxB,MAAM,MHtLqB,qBGyL7B,QAAcI,IAAVb,EAEF,OADAR,KAAKC,QAAQV,WAIf,QAAaS,KAAKV,KAAKkB,GACvB,IAAKlB,EACH,MAAUhB,IAAAA,EHhMiB,qBGqM7B,OAFA0B,KAAKC,QAAQgB,OAASjB,KAAKC,QAAQyB,QAAQpC,GAAQ,EAGrDU,IAAA,CAMO2B,KAAKzB,GAGV,OAFAF,KAAKE,IAAMA,GAAc,OAAAxB,UAG3B,CAMOkD,OAAO1B,GACZ,GAAIF,KAAKE,MAAQA,EACf,UAAsB5B,EH1NM,sBG+N9B,OAFA0B,KAAKE,IAAM,KAEJF,IACT,CAEO6B,uBAAuBlC,GAC5B,YAAoB0B,IAAhB1B,EAnM4B,IAuMX,IAAjBA,SACYmC,mBAIlB,CAEOD,kBAAkBjB,EAAcX,EAAmBP,GACxD,MAAMqC,EAAmB/B,KAAKgC,oBAAoBpB,EAAMX,KACjCD,KAAKiC,cAAcF,EAAkBrC,GAE5D,IAAKwC,EACH,MAAU5D,IAAAA,EHpPoB,wBGuPhC,MAAMyC,EAAUrB,EAAYwC,GAE5B,MAA0B,qBACtBnB,EACAX,CACN,CAEOyB,qBAAqBE,EAA0BrC,GAIpD,OAAayC,OAACC,KAAK1C,GAChB4B,OAAOe,GAAcN,EAAiBd,OAASoB,EAAWpB,OACvD,IAAUqB,OAAM,KAAAD,MAAeE,KAAKR,GACpCA,IAAqBM,GAExBG,KAAK,CAACC,EAAGC,IAAMA,EAAEzB,OAASwB,EAAExB,QAAQ,EACzC,CAEOY,2BAA2BjB,EAAcX,GAC9C,MAAO,IAAIA,EAAQ0C,IAAI,EAAGnC,WAA0BA,GAAQI,GACzDgC,KA7OkB,IA8OvB,QC7QmBC,EAInB/C,cAFAgD,KAAAA,WAGE,EAAA9C,KAAK8C,MAAQ,CAAA,CACf,CAEAC,IAAK7C,GACH,OAAOF,KAAK8C,MAAM5C,EACpB,CAEA8C,IAAK9C,EAAa+C,GAChBjD,KAAK8C,MAAM5C,GAAO+C,CACpB,CAEAC,OAAQhD,UACKF,KAAC8C,MAAM5C,EACpB,ECTWiD,MAAAA,EAAmB,CACnBC,EAAyBA,EAAG,IAAIP,EAChCQ,EAA2B,IAAcR,EASlCS,EAAIvD,IAEtB,MAAMwD,QACJA,EAAOC,SACPA,EAAQC,iBACRA,EAAmBL,EAAyBM,gBAC5CA,EAAkBL,GAChBtD,EACE4D,EAAYC,EAAYJ,EAAUC,GACvBI,EAAAxD,EAAA,CAAA,EAAsByD,EAAyBH,EAAcJ,GAChEQ,EAAG,IAAIlE,EAAQgE,GAI7B,OAFAH,EAAgBV,IAAIe,EAAS5D,GAAI4D,GAGnCA,GAEaH,EAAc,CAACJ,EAAkCC,IACjC,iBAAbD,EACVC,EAAiBV,IAAIS,GACrBA"}