{"version":3,"file":"state-effects.mjs","sources":["../../../../libs/state/effects/src/lib/utils.ts","../../../../libs/state/effects/src/lib/effects.service.ts","../../../../libs/state/effects/src/lib/rx-effects.ts","../../../../libs/state/effects/src/state-effects.ts"],"sourcesContent":["import { Observable } from 'rxjs';\nimport { filter, map, shareReplay, take } from 'rxjs/operators';\nimport { HookProps, SingleShotProps } from './model';\n\nexport function isSingleShotHookNameGuard<T>(\n  name: unknown,\n): name is keyof SingleShotProps {\n  return !!name && typeof name === 'string' && name !== '';\n}\n\n/**\n * @internal\n * Operator to filter values for single shot observables\n */\nconst singleShotOperators = (o$: Observable<true>): Observable<true> =>\n  o$.pipe(\n    filter((v) => v === true),\n    take(1),\n    shareReplay(),\n  );\n\n/**\n * This is an operator that is used to listen to Angular lifecycle hooks.\n * It plucks a defined lefe cycle name `HookProps` and forwards values for the particular value and in the behavior of the hook e.g. single shot\n *\n * @param name\n */\nexport function toHook<H extends keyof HookProps>(name: H) {\n  const operators = isSingleShotHookNameGuard(name)\n    ? singleShotOperators\n    : (o: Observable<HookProps[H]>): Observable<true> => o;\n  return (o$: Observable<HookProps>): Observable<HookProps[H]> =>\n    o$.pipe(\n      map((p) => p[name]),\n      operators,\n    );\n}\n","import { DestroyRef, ErrorHandler, inject, Injectable } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport {\n  EMPTY,\n  from,\n  Observable,\n  ObservableInput,\n  PartialObserver,\n  pipe,\n  Subject,\n  Subscription,\n} from 'rxjs';\nimport {\n  catchError,\n  filter,\n  map,\n  mergeAll,\n  share,\n  takeUntil,\n  tap,\n} from 'rxjs/operators';\nimport { DestroyProp, OnDestroy$ } from './model';\nimport { toHook } from './utils';\n\n/**\n * @deprecated - use rxEffects instead\n *\n * Reduces subscription boilerplate for performing observable-based side-effects in components.\n *\n * Before:\n * ```ts\n * @Component({\n *   // ...\n * })\n * export class FooComponent implements OnDestroy {\n *   private readonly destroy$ = new Subject<void>();\n *\n *   constructor() {\n *     obs$.pipe(takeUntil(this.destroy$)).subscribe(doSideEffect);\n *   }\n *\n *   ngOnDestroy(): void {\n *     this.destroy$.next();\n *     this.destroy$.complete();\n *   }\n * }\n * ```\n *\n * After:\n * ```ts\n * @Component({\n *   // ...\n *   providers: [RxEffects],\n * })\n * export class FooComponent {\n *   constructor(effects: RxEffects) {\n *     effects.register(obs$, doSideEffect);\n *     // OR\n *     effects.register(obs$.pipe(tap(doSideEffect)));\n *     // OR\n *     effects.register(obs$.subscribe(doSideEffect));\n *   }\n * }\n * ```\n *\n * NOTE: Avoid calling register/unregister/subscribe inside the side-effect function.\n */\n@Injectable()\nexport class RxEffects implements OnDestroy$ {\n  private static nextId = 0;\n  private readonly destroyRef = inject(DestroyRef);\n  private readonly errorHandler = inject(ErrorHandler, { optional: true });\n  readonly _hooks$ = new Subject<DestroyProp>();\n  private readonly observables$ = new Subject<Observable<unknown>>();\n  // we have to use publish here to make it hot (composition happens without subscriber)\n  private readonly effects$ = this.observables$.pipe(mergeAll(), share());\n  private readonly subscription = this.effects$.subscribe();\n  onDestroy$: Observable<boolean> = this._hooks$.pipe(toHook('destroy'));\n  private readonly destroyers: Record<number, Subject<void>> = {};\n\n  constructor() {\n    this.destroyRef.onDestroy(() => {\n      this._hooks$.next({ destroy: true });\n      this.subscription.unsubscribe();\n    });\n  }\n\n  /**\n   * Performs a side-effect whenever a source observable emits, and handles its subscription.\n   *\n   * @example\n   * effects.register(\n   *   colorMode$,\n   *   mode => localStorage.setItem('colorMode', mode)\n   * );\n   *\n   * @param sourceObs Source observable input\n   * @param sideEffectFn Function with side-effect\n   * @returns Effect ID (can be used to unregister imperatively)\n   */\n  register<T>(\n    sourceObs: ObservableInput<T>,\n    sideEffectFn: (value: T) => void,\n  ): number;\n\n  /**\n   * Subscribe to source observable using an observer object.\n   *\n   * @example\n   * effects.register(\n   *   colorMode$,\n   *   {\n   *     next: mode => localStorage.setItem('colorMode', mode),\n   *     error: err => {\n   *       console.error('Color mode error: ', err);\n   *       localStorage.removeItem('colorMode');\n   *     }\n   *   }\n   * );\n   *\n   * @param sourceObs Source observable input\n   * @param observer Observer object\n   */\n  register<T>(\n    sourceObs: ObservableInput<T>,\n    // tslint:disable-next-line: unified-signatures\n    observer: PartialObserver<T>,\n  ): number;\n\n  /**\n   * Handles subscription for an observable with a side-effect.\n   *\n   * @example\n   * effects.register(\n   *   colorMode$.pipe(\n   *     tap(mode => localStorage.setItem('colorMode', mode))\n   *   )\n   * );\n   *\n   * @param sideEffectObs Observable input with side-effect\n   * @returns Effect ID (can be used to unregister imperatively)\n   */\n  register(sideEffectObs: ObservableInput<unknown>): number;\n\n  /**\n   * Handles subscription to an observable with a side-effect.\n   *\n   * @example\n   * effects.register(\n   *   colorMode$.subscribe(mode => localStorage.setItem('colorMode', mode))\n   * );\n   *\n   * @param subscription Subscription to observable with side-effect\n   */\n  // tslint:disable-next-line: unified-signatures\n  register(subscription: Subscription): void;\n\n  register<T>(\n    obsOrSub: ObservableInput<T> | Subscription,\n    fnOrObj?: ((value: T) => void) | PartialObserver<T>,\n  ): number | void {\n    if (obsOrSub instanceof Subscription) {\n      this.subscription.add(obsOrSub);\n      return;\n    }\n    const effectId = RxEffects.nextId++;\n    const destroy$ = (this.destroyers[effectId] = new Subject<void>());\n    const applyBehavior = pipe(\n      map(() => effectId),\n      takeUntil(destroy$),\n    );\n    if (fnOrObj != null) {\n      this.observables$.next(\n        from(obsOrSub).pipe(\n          // ternary expression is to help Typescript infer overloads\n          typeof fnOrObj === 'function' ? tap(fnOrObj) : tap(fnOrObj),\n          catchError((err) => {\n            this.errorHandler?.handleError(err);\n            return EMPTY;\n          }),\n          applyBehavior,\n        ),\n      );\n    } else {\n      this.observables$.next(from(obsOrSub).pipe(applyBehavior));\n    }\n    return effectId;\n  }\n\n  /**\n   * Imperatively cancel a side-effect while the component is still running.\n   *\n   * Note that all effects are automatically cancelled when a component is destroyed,\n   * so you most often won't need to call this method.\n   * @param effectId Effect ID (returned by register method)\n   */\n  unregister(effectId: number): void {\n    this.destroyers[effectId]?.next();\n  }\n\n  /**\n   * Fires a sideEffect when the instances `OnDestroy` hook is fired.\n   *\n   * @example\n   * effects.registerOnDestroy(mode => localStorage.setItem('colorMode', mode));\n   *\n   * @param sideEffect\n   */\n  registerOnDestroy(sideEffect: (value: boolean) => void): number | void {\n    return this.register(this.onDestroy$, sideEffect);\n  }\n\n  /**\n   * Operator that unsubscribes based on emission of an registered effect.\n   *\n   * @NOTICE\n   * This operator has to be placed always at the end of the operator chain (before the subscription).\n   * Otherwise we may leak as a subsequent operator could instantiate new ongoing Observables which will not get unsubscribed.\n   *\n   * @example\n   * const effectId1 = effects.register(\n   *   colorMode$.subscribe(mode => localStorage.setItem('colorMode', mode))\n   * );\n   *\n   * someValue$.pipe(\n   *    effect.untilEffect(effectId1)\n   * )\n   *\n   */\n  untilEffect(effectId: number) {\n    return <V>(source: Observable<V>) =>\n      source.pipe(\n        takeUntilDestroyed(this.destroyRef),\n        takeUntil(this.effects$.pipe(filter((eId) => eId === effectId))),\n      );\n  }\n}\n","import {\n  assertInInjectionContext,\n  DestroyRef,\n  ErrorHandler,\n  inject,\n} from '@angular/core';\nimport { from, Subscription } from 'rxjs';\nimport { SideEffectFnOrObserver, SideEffectObservable } from './types';\n\ninterface RxEffects {\n  register<T>(\n    observable: SideEffectObservable<T>,\n    sideEffectOrObserver?: SideEffectFnOrObserver<T>\n  ): Fn;\n  onDestroy: (fn: Fn) => Fn;\n}\n\ntype Fn = () => void;\n\nexport type RxEffectsSetupFn = (\n  cfg: Pick<RxEffects, 'register' | 'onDestroy'>\n) => void;\n\n/**\n * @description\n * Functional way to setup observable based side effects with RxEffects.\n * It's a creation function for RxEffects that destroys itself when the provided\n * `DestroyRef` is destroyed.\n *\n * @example\n * ```ts\n * import { rxEffects } from '@rx-angular/state/effects';\n *\n * \\@Component({})\n * export class FooComponent {\n *  const readonly util = inject(Util);\n *  readonly effects = rxEffects(({ register }) => {\n *    register(this.util.windowResize$, () => {\n *      console.log('window was resized');\n *    })\n *  });\n *\n *  ngOnInit() {\n *    this.effects.register(this.util.rotationChanged$, () => {\n *      console.log('viewport rotation changed');\n *    });\n *  }\n * }\n * ```\n *\n * @param {RxEffectsSetupFn} setupFn\n * @returns RxEffects\n *\n * @docsCategory RxEffects\n * @docsPage RxEffects\n *\n */\nexport function rxEffects(setupFn?: RxEffectsSetupFn): RxEffects {\n  assertInInjectionContext(rxEffects);\n  const errorHandler = inject(ErrorHandler, { optional: true });\n  const destroyRef = inject(DestroyRef);\n  const runningEffects: Subscription[] = [];\n  destroyRef.onDestroy(() => runningEffects.forEach((ef) => ef.unsubscribe()));\n\n  /**\n   * Subscribe to observables and trigger side effect.\n   *\n   * @example\n   *\n   * /@Component({\n   *   template: `<button name=\"save\" (click)=\"save()\">Save</button>`\n   * })\n   * class ListComponent {\n   *   private ef = rxEffects(({register}) => {\n   *      register(timer(0, this.backupInterval), console.log));\n   *   }\n   * }\n   *\n   * @param {SideEffectObservable} obs$ Source observable input\n   * @param {SideEffectFnOrObserver} sideEffect Observer object\n   *\n   * @return {Function} - unregisterFn\n   */\n  function register<T>(\n    obs$: SideEffectObservable<T>,\n    sideEffect?: SideEffectFnOrObserver<T>\n  ): () => void {\n    const observer =\n      typeof sideEffect === 'object'\n        ? {\n            ...sideEffect,\n            // preserve original logic\n            error: (e: unknown) => {\n              sideEffect.error?.(e);\n              errorHandler?.handleError(e);\n            },\n          }\n        : {\n            next: sideEffect,\n            error: (e: unknown) => errorHandler?.handleError(e),\n          };\n    const sub = from(obs$).subscribe(observer);\n    runningEffects.push(sub);\n    return () => sub.unsubscribe();\n  }\n\n  /**\n   * Register custom cleanup logic.\n   *\n   * @example\n   *\n   * /@Component({\n   *   template: `<button name=\"save\" (click)=\"save()\">Save</button>`\n   * })\n   * class ListComponent {\n   *   private ef = rxEffects(({onDestroy}) => {\n   *      onDestroy(() => console.log('done'));\n   *   }\n   * }\n   *\n   * @param {Fn} callback onDestroy callback\n   *\n   * @return {Fn} unregisterFn\n   */\n  function onDestroy(callback: Fn): Fn {\n    return destroyRef.onDestroy(callback);\n  }\n\n  const effects = {\n    register,\n    onDestroy,\n  };\n\n  setupFn?.(effects);\n\n  return effects;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}