{"version":3,"file":"index.cjs","names":["AdapterConfigurationStatus","AdapterSubscriptionStatus","adapterIdentifiers","this","AdapterInitializationStatus","exposeGlobally"],"sources":["../src/adapter.ts","../src/index.ts"],"sourcesContent":["import { exposeGlobally } from '@flopflip/adapter-utilities';\nimport {\n  AdapterConfigurationStatus,\n  AdapterInitializationStatus,\n  AdapterSubscriptionStatus,\n  adapterIdentifiers,\n  type TAdapter,\n  type TAdapterEventHandlers,\n  type TAdapterIdentifiers,\n  type TAdapterStatus,\n  type TAdapterStatusChange,\n  type TCombinedAdapterArgs,\n  type TCombinedAdapterInterface,\n  type TFlags,\n  type TUpdateFlagsOptions,\n} from '@flopflip/types';\nimport mitt, { type Emitter } from 'mitt';\nimport warning from 'tiny-warning';\n\ntype TInternalStatusChange = '__internalConfiguredStatusChange__';\ntype TEmitterEvents = {\n  __internalConfiguredStatusChange__: undefined;\n  flagsStateChange: TFlags;\n  statusStateChange: Partial<TAdapterStatus>;\n};\ntype TEventHandlers = {\n  statusStateChange: (status: Partial<TAdapterStatus>) => void;\n};\ntype TCombinedAdaptersState = {\n  emitter: Emitter<TEmitterEvents>;\n};\n\n// A factory, so no two adapters or resets share the same flags, locked\n// flags or emitter.\nconst createInitialAdapterState = (\n  emitter: Emitter<TEmitterEvents> = mitt<TEmitterEvents>(),\n): TAdapterStatus & TCombinedAdaptersState => ({\n  configurationStatus: AdapterConfigurationStatus.Unconfigured,\n  subscriptionStatus: AdapterSubscriptionStatus.Subscribed,\n  emitter,\n});\n\nclass CombineAdapters implements TCombinedAdapterInterface {\n  id: typeof adapterIdentifiers.combined;\n  effectIds?: TAdapterIdentifiers[];\n\n  #__internalConfiguredStatusChange__: TInternalStatusChange =\n    '__internalConfiguredStatusChange__';\n\n  #adapters: TAdapter[] = [];\n  #adapterState: TAdapterStatus & TCombinedAdaptersState;\n\n  #eventHandlers?: TEventHandlers;\n\n  readonly #removeEventHandlers = () => {\n    if (!this.#eventHandlers) {\n      return;\n    }\n\n    this.#adapterState.emitter.off(\n      'statusStateChange',\n      this.#eventHandlers.statusStateChange,\n    );\n    this.#eventHandlers = undefined;\n  };\n\n  // Each `configure` replaces the event handlers of a previous one, so only\n  // the latest handlers are invoked.\n  readonly #replaceEventHandlers = (eventHandlers: TEventHandlers) => {\n    this.#removeEventHandlers();\n    this.#eventHandlers = eventHandlers;\n    this.#adapterState.emitter.on(\n      'statusStateChange',\n      eventHandlers.statusStateChange,\n    );\n  };\n\n  constructor() {\n    this.#adapterState = createInitialAdapterState();\n    this.id = adapterIdentifiers.combined;\n  }\n\n  readonly #getHasCombinedAdapters = () => this.#adapters.length > 0;\n  readonly #getHasArgsForAllAdapters = (adapterArgs: TCombinedAdapterArgs) =>\n    this.#adapters.every((adapter) => adapterArgs[adapter.id]);\n\n  readonly #getIsAdapterUnsubscribed = () =>\n    this.#adapterState.subscriptionStatus ===\n    AdapterSubscriptionStatus.Unsubscribed;\n\n  updateFlags = (flags: TFlags, options?: TUpdateFlagsOptions) => {\n    const isAdapterConfigured = this.getIsConfigurationStatus(\n      AdapterConfigurationStatus.Configured,\n    );\n    const hasCombinedAdapters = this.#getHasCombinedAdapters();\n\n    warning(\n      isAdapterConfigured,\n      '@flopflip/combine-adapters: adapter is not configured. Flags can not be updated before.',\n    );\n    warning(\n      hasCombinedAdapters,\n      '@flopflip/combine-adapters: adapter has no combined adapters. Please combine before updating flags.',\n    );\n\n    if (!isAdapterConfigured || !hasCombinedAdapters) {\n      return;\n    }\n\n    for (const adapter of this.#adapters) {\n      adapter.updateFlags(flags, options);\n    }\n  };\n\n  combine(adapters: TAdapter[]) {\n    this.#adapters = adapters;\n    this.effectIds = adapters.map((adapter) => adapter.id).concat(this.id);\n  }\n\n  async configure(\n    adapterArgs: TCombinedAdapterArgs,\n    adapterEventHandlers: TAdapterEventHandlers,\n  ) {\n    const hasCombinedAdapters = this.#getHasCombinedAdapters();\n    const hasArgsForAllAdapters = this.#getHasArgsForAllAdapters(adapterArgs);\n\n    warning(\n      hasCombinedAdapters,\n      '@flopflip/combine-adapters: adapter has no combined adapters. Please combine before reconfiguring flags.',\n    );\n    warning(\n      hasArgsForAllAdapters,\n      '@flopflip/combine-adapters: not all adapters have args. Please provide args for all adapters.',\n    );\n\n    if (!hasCombinedAdapters || !hasArgsForAllAdapters) {\n      return Promise.resolve({\n        initializationStatus: AdapterInitializationStatus.Failed,\n      });\n    }\n\n    const handleStatusChange = (nextStatus: TAdapterStatusChange['status']) => {\n      if (this.#getIsAdapterUnsubscribed()) {\n        return;\n      }\n\n      adapterEventHandlers.onStatusStateChange({\n        status: nextStatus,\n        id: this.id,\n      });\n    };\n\n    this.#replaceEventHandlers({ statusStateChange: handleStatusChange });\n\n    this.setConfigurationStatus(AdapterConfigurationStatus.Configuring);\n\n    return Promise.all(\n      this.#adapters.map(async (adapter) => {\n        const adapterArgsForAdapter = adapterArgs[adapter.id];\n\n        return adapter.configure(adapterArgsForAdapter, {\n          onFlagsStateChange: adapterEventHandlers.onFlagsStateChange,\n          onStatusStateChange: adapterEventHandlers.onStatusStateChange,\n        });\n      }),\n    ).then((allInitializationStatus) => {\n      const haveAllAdaptersInitializedSuccessfully =\n        allInitializationStatus.every(\n          ({ initializationStatus }) =>\n            initializationStatus === AdapterInitializationStatus.Succeeded,\n        );\n\n      // NOTE: We consider this adapter configured if all adapters have been asked to do so\n      // and have reported to be initialized successfully.\n      this.setConfigurationStatus(AdapterConfigurationStatus.Configured);\n\n      this.#adapterState.emitter.emit(this.#__internalConfiguredStatusChange__);\n\n      if (haveAllAdaptersInitializedSuccessfully) {\n        return {\n          initializationStatus: AdapterInitializationStatus.Succeeded,\n        };\n      }\n\n      // NOTE: If not all adapters have initialized successfully we can not consider\n      // this adapter being configured fully.\n      this.setConfigurationStatus(AdapterConfigurationStatus.Unconfigured);\n\n      this.#adapterState.emitter.emit(this.#__internalConfiguredStatusChange__);\n\n      return {\n        initializationStatus: AdapterInitializationStatus.Failed,\n      };\n    });\n  }\n\n  async reconfigure(\n    adapterArgs: TCombinedAdapterArgs,\n    adapterEventHandlers: TAdapterEventHandlers,\n  ) {\n    this.setConfigurationStatus(AdapterConfigurationStatus.Configuring);\n\n    const hasCombinedAdapters = this.#getHasCombinedAdapters();\n    const hasArgsForAllAdapters = this.#getHasArgsForAllAdapters(adapterArgs);\n\n    warning(\n      hasCombinedAdapters,\n      '@flopflip/combine-adapters: adapter has no combined adapters. Please combine before reconfiguring flags.',\n    );\n    warning(\n      hasArgsForAllAdapters,\n      '@flopflip/combine-adapters: not all adapters have args. Please provide args for all adapters.',\n    );\n\n    if (!hasCombinedAdapters || !hasArgsForAllAdapters) {\n      return Promise.resolve({\n        initializationStatus: AdapterInitializationStatus.Failed,\n      });\n    }\n\n    return Promise.all(\n      this.#adapters.map(async (adapter) => {\n        const adapterArgsForAdapter = adapterArgs[adapter.id];\n\n        return adapter.reconfigure(adapterArgsForAdapter, {\n          onFlagsStateChange: adapterEventHandlers.onFlagsStateChange,\n          onStatusStateChange: adapterEventHandlers.onStatusStateChange,\n        });\n      }),\n    ).then((allInitializationStatus) => {\n      const haveAllAdaptersInitializedSuccessfully =\n        allInitializationStatus.every(\n          ({ initializationStatus }) =>\n            initializationStatus === AdapterInitializationStatus.Succeeded,\n        );\n\n      // NOTE: We consider this adapter reconfigured if all adapters have been asked to do so\n      // and have reported to be initialized successfully.\n      this.setConfigurationStatus(AdapterConfigurationStatus.Configured);\n\n      this.#adapterState.emitter.emit(this.#__internalConfiguredStatusChange__);\n\n      if (haveAllAdaptersInitializedSuccessfully) {\n        return { initializationStatus: AdapterInitializationStatus.Succeeded };\n      }\n\n      // NOTE: If not all adapters have initialized successfully we can not consider\n      // this adapter being configured fully.\n      this.setConfigurationStatus(AdapterConfigurationStatus.Unconfigured);\n\n      this.#adapterState.emitter.emit(this.#__internalConfiguredStatusChange__);\n\n      return { initializationStatus: AdapterInitializationStatus.Failed };\n    });\n  }\n\n  getIsConfigurationStatus(configurationStatus: AdapterConfigurationStatus) {\n    return this.#adapterState.configurationStatus === configurationStatus;\n  }\n\n  setConfigurationStatus(nextConfigurationStatus: AdapterConfigurationStatus) {\n    this.#adapterState.configurationStatus = nextConfigurationStatus;\n\n    this.#adapterState.emitter.emit('statusStateChange', {\n      configurationStatus: this.#adapterState.configurationStatus,\n    });\n  }\n\n  reset = () => {\n    this.#removeEventHandlers();\n    // Keeps the emitter, so pending `waitUntilConfigured` calls still resolve\n    // once the adapter is configured again.\n    this.#adapterState = createInitialAdapterState(this.#adapterState.emitter);\n  };\n\n  async waitUntilConfigured() {\n    return Promise.all(\n      this.#adapters.map(async (adapter) => adapter?.waitUntilConfigured?.()),\n    );\n  }\n\n  unsubscribe = () => {\n    this.#adapterState.subscriptionStatus =\n      AdapterSubscriptionStatus.Unsubscribed;\n  };\n\n  subscribe = () => {\n    this.#adapterState.subscriptionStatus =\n      AdapterSubscriptionStatus.Subscribed;\n  };\n}\n\nconst adapter = new CombineAdapters();\n\nexposeGlobally(adapter);\n\n// The class is exported for tests only. The package exports the instance.\nexport { adapter, CombineAdapters };\n","const version = '__@FLOPFLIP/VERSION_OF_RELEASE__';\n\nexport { adapter } from './adapter';\nexport { version };\n"],"mappings":"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"}