{"version":3,"sources":["common/appContext/sharedState.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAuB,MAAM,EAAE,MAAM,cAAc,CAAC;AAI3D,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED,oBAAY,aAAa,GAAG,CAAC,UAAU,KAAA,KAAK,GAAG,CAAC;AAEhD,UAAU,KAAK;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,QAAQ,CAAC;CACf;AAID,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAe;IAE5B,OAAO,CAAC,WAAW,CAA0B;gBAEjC,KAAK,EAAE,KAAK;IAKjB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAY7B,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO;IAY1D,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO;IAI7D,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK7C;;;;;;;;OAQG;IACI,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,KAAA,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAsB/F,MAAM,KAAK,YAAY,WAEtB;CACF;AAYD,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAM3D","file":"../../../common/appContext/sharedState.d.ts","sourcesContent":["import { deepCopy } from '../mutexHelper.js';\nimport { Provider, singletonProvider } from '../provider.js';\nimport AppContext, { Dictionary, getTools } from './appContext.js';\nimport { BusEvent, EventBus } from './eventBus.js';\nimport { aliasName as logKey, Logger } from './logging.js';\n\n/* eslint-disable @typescript-eslint/ban-types */\n\nexport interface StateEvent extends BusEvent {\n  data: { old: object, new: object };\n}\n\nexport type StateListener = (StateEvent) => any;\n\ninterface Tools {\n  logger: Logger;\n  bus: EventBus;\n}\n\nconst empty = Object.freeze({});\n\nexport class SharedState {\n  private tools: Tools = null;\n\n  private frozenState: Dictionary<object> = {};\n\n  constructor(tools: Tools) {\n    this.tools = tools;\n  }\n\n  // strip leading or traling /\n  public cleanKey(key: string): string {\n    if (key) {\n      return key.replace(/(^\\/+)|(\\/+$)/g, '');\n    }\n    throw new Error(`Invalid key: ${key}`);\n  }\n\n  //\n  // Shortcut for EventBus.addListener\n  // Fires a state change as a shortcut, so the listener\n  // immediately gets the current value (old and new both set to current)\n  //\n  public addListener(key: string, listener: StateListener): boolean {\n    const busKey = `lw-sc:${this.cleanKey(key)}`;\n    if (this.tools.bus.addListener(busKey, listener)) {\n      this.getState(key).then(\n        (v) => listener({ evType: busKey, data: { old: v, new: v } }),\n      );\n      return true;\n    }\n    return false;\n  }\n\n  // Shortcut for EventBus.addListener\n  public removeListener(key: string, listener: StateListener): boolean {\n    return this.tools.bus.removeListener(`lw-sc:${this.cleanKey(key)}`, listener);\n  }\n\n  public getState(key: string): Promise<object> {\n    const cleanKey = this.cleanKey(key);\n    return Promise.resolve(this.frozenState[cleanKey] || empty);\n  }\n\n  /**\n   * Change the state associated with the given key,\n   * and trigger a lw-sc: event if handler()\n   * returns an object.  NOOP of handler returns null\n   * or undefined.\n   *\n   * @param key\n   * @param handler\n   */\n  public changeState(key: string, handler: (object) => object | Promise<object>): Promise<object> {\n    const cleanKey = this.cleanKey(key);\n    return this.getState(cleanKey).then(\n      (v1) => Promise.resolve(handler(deepCopy(v1))).then(\n        (v2) => ({ v1, v2 }),\n      ),\n    ).then(\n      ({ v1, v2 }) => {\n        if (!v2) {\n          return v1;\n        }\n        v2 = deepCopy(v2, true);\n        if (typeof v2 !== 'object' || Array.isArray(v2)) {\n          v2 = Object.freeze({ thing: v2 });\n        }\n        this.frozenState[cleanKey] = v2;\n        this.tools.bus.dispatch(`lw-sc:${cleanKey}`, { old: v1, new: v2 });\n        return v2;\n      },\n    );\n  }\n\n  static get providerName() {\n    return 'driver/littleware/little-elements/common/appContext/sharedState';\n  }\n}\n\nAppContext.get().then(\n  (cx) => {\n    cx.putProvider(SharedState.providerName, { logger: logKey, bus: EventBus.providerName },\n      async (toolBox) => {\n        const tools: Tools = await getTools(toolBox) as Tools;\n        return singletonProvider(() => new SharedState(tools));\n      });\n  },\n);\n\nexport async function getSharedState(): Promise<SharedState> {\n  return AppContext.get().then(\n    (cx) => cx.getProvider(SharedState.providerName),\n  ).then(\n    (provider: Provider<SharedState>) => provider.get(),\n  );\n}\n"]}