{"version":3,"file":"ngx-observable-lifecycle.mjs","sources":["../../../projects/ngx-observable-lifecycle/src/lib/ngx-observable-lifecycle.ts","../../../projects/ngx-observable-lifecycle/src/public-api.ts","../../../projects/ngx-observable-lifecycle/src/ngx-observable-lifecycle.ts"],"sourcesContent":["import {\n  AfterContentChecked,\n  AfterContentInit,\n  AfterViewChecked,\n  AfterViewInit,\n  DoCheck,\n  OnChanges,\n  OnDestroy,\n  OnInit,\n} from '@angular/core';\nimport { Observable, Subject } from 'rxjs';\n\nexport const hookSubject: unique symbol = Symbol('ngx-observable-lifecycle-hooks');\nexport const hooksPatched: unique symbol = Symbol('ngx-observable-lifecycle-hooks-decorator');\n\nexport type AllHooks = OnChanges &\n  OnInit &\n  DoCheck &\n  AfterContentInit &\n  AfterContentChecked &\n  AfterViewInit &\n  AfterViewChecked &\n  OnDestroy;\nexport type LifecycleHookKey = keyof AllHooks;\n\ntype AllHookOptions = Record<LifecycleHookKey, true>;\ntype DecorateHookOptions = Partial<AllHookOptions>;\n\nexport interface TypedSimpleChange<Data> {\n  previousValue: Data;\n  currentValue: Data;\n  firstChange: boolean;\n}\n\n/**\n * FIRST POINT:\n * the key is made optional because an ngOnChanges will only give keys of inputs that have changed\n * SECOND POINT:\n * the value is associated with `| null` as if an input value is defined but actually retrieved with\n * an `async` pipe, we'll initially get a `null` value\n *\n * For both point, feel free to check the following stackblitz that demo this\n * https://stackblitz.com/edit/stackblitz-starters-s5uphw?file=src%2Fmain.ts\n */\nexport type TypedSimpleChanges<Component, Keys extends keyof Component> = {\n  [Key in Keys]?: TypedSimpleChange<Component[Key]> | null;\n};\n\n// none of the hooks have arguments, EXCEPT ngOnChanges which we need to handle differently\nexport type DecoratedHooks<Component = any, Keys extends keyof Component = any> = Record<\n  Exclude<LifecycleHookKey, 'ngOnChanges'>,\n  Observable<void>\n> & {\n  ngOnChanges: Observable<TypedSimpleChanges<Component, Keys>>;\n};\nexport type DecoratedHooksSub = {\n  [k in keyof DecoratedHooks]: DecoratedHooks[k] extends Observable<infer U> ? Subject<U> : never;\n};\n\ntype PatchedComponentInstance<Hooks extends LifecycleHookKey = any> = Pick<AllHooks, Hooks> & {\n  [hookSubject]: Pick<DecoratedHooksSub, Hooks>;\n  constructor: {\n    prototype: {\n      [hooksPatched]: Pick<DecorateHookOptions, Hooks>;\n    };\n  };\n};\n\nfunction getSubjectForHook(componentInstance: PatchedComponentInstance, hook: LifecycleHookKey): Subject<void> {\n  if (hook === 'ngOnChanges' && !componentInstance.constructor.prototype[hook]) {\n    throw new Error(\n      `When using the ngOnChanges hook, you have to define the hook in your class even if it's empty. See https://stackoverflow.com/a/77930589/2398593`,\n    );\n  }\n\n  if (!componentInstance[hookSubject]) {\n    componentInstance[hookSubject] = {};\n  }\n\n  if (!componentInstance[hookSubject][hook]) {\n    componentInstance[hookSubject][hook] = new Subject<void>();\n  }\n\n  const proto = componentInstance.constructor.prototype;\n  if (!proto[hooksPatched]) {\n    proto[hooksPatched] = {};\n  }\n\n  if (!proto[hooksPatched][hook]) {\n    const originalHook = proto[hook];\n\n    proto[hook] = function (...args: any[]) {\n      originalHook?.call(this, ...args);\n\n      if (hook === 'ngOnChanges') {\n        this[hookSubject]?.[hook]?.next(args[0]);\n      } else {\n        this[hookSubject]?.[hook]?.next();\n      }\n    };\n\n    const originalOnDestroy = proto.ngOnDestroy;\n    proto.ngOnDestroy = function (this: PatchedComponentInstance<typeof hook>) {\n      originalOnDestroy?.call(this);\n      this[hookSubject]?.[hook]?.complete();\n      delete this[hookSubject]?.[hook];\n    };\n\n    proto[hooksPatched][hook] = true;\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n  return componentInstance[hookSubject][hook]!;\n}\n\n/**\n * Library authors should use this to create their own lifecycle-aware functionality\n */\nexport function getObservableLifecycle<Component, Inputs extends keyof Component = never>(\n  classInstance: Component,\n): DecoratedHooks<Component, Inputs> {\n  return new Proxy({} as DecoratedHooks<Component, Inputs>, {\n    get(target: DecoratedHooks<Component, Inputs>, p: LifecycleHookKey): Observable<void> {\n      return getSubjectForHook(classInstance as unknown as PatchedComponentInstance, p).asObservable();\n    },\n  });\n}\n","/*\n * Public API Surface of ngx-observable-lifecycle\n */\n\nexport * from './lib/ngx-observable-lifecycle';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;MAYa,WAAW,GAAkB,MAAM,CAAC,gCAAgC,EAAE;MACtE,YAAY,GAAkB,MAAM,CAAC,0CAA0C,EAAE;AAuD9F,SAAS,iBAAiB,CAAC,iBAA2C,EAAE,IAAsB;IAC5F,IAAI,IAAI,KAAK,aAAa,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;QAC5E,MAAM,IAAI,KAAK,CACb,iJAAiJ,CAClJ,CAAC;KACH;IAED,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,EAAE;QACnC,iBAAiB,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC;KACrC;IAED,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE;QACzC,iBAAiB,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,EAAQ,CAAC;KAC5D;IAED,MAAM,KAAK,GAAG,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC;IACtD,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;QACxB,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;KAC1B;IAED,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE;QAC9B,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QAEjC,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,GAAG,IAAW;YACpC,YAAY,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;YAElC,IAAI,IAAI,KAAK,aAAa,EAAE;gBAC1B,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;aAC1C;iBAAM;gBACL,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;aACnC;SACF,CAAC;QAEF,MAAM,iBAAiB,GAAG,KAAK,CAAC,WAAW,CAAC;QAC5C,KAAK,CAAC,WAAW,GAAG;YAClB,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC;SAClC,CAAC;QAEF,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAClC;;IAGD,OAAO,iBAAiB,CAAC,WAAW,CAAC,CAAC,IAAI,CAAE,CAAC;AAC/C,CAAC;AAED;;;SAGgB,sBAAsB,CACpC,aAAwB;IAExB,OAAO,IAAI,KAAK,CAAC,EAAuC,EAAE;QACxD,GAAG,CAAC,MAAyC,EAAE,CAAmB;YAChE,OAAO,iBAAiB,CAAC,aAAoD,EAAE,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;SAClG;KACF,CAAC,CAAC;AACL;;AC9HA;;;;ACAA;;;;;;"}