{"version":3,"file":"ngxtension-connect.mjs","sources":["../../../../libs/ngxtension/connect/src/connect.ts","../../../../libs/ngxtension/connect/src/ngxtension-connect.ts"],"sourcesContent":["import {\n\tDestroyRef,\n\tInjector,\n\teffect,\n\tuntracked,\n\ttype EffectRef,\n\ttype WritableSignal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { assertInjector } from 'ngxtension/assert-injector';\nimport { Subscription, isObservable, type Observable } from 'rxjs';\n\nexport type PartialOrValue<TValue> = TValue extends object\n\t? Partial<TValue>\n\t: TValue;\nexport type Reducer<TValue, TNext> = (\n\tprevious: TValue,\n\tnext: TNext,\n) => PartialOrValue<TValue>;\n\ntype ConnectedSignal<TSignalValue> = {\n\twith<TObservableValue extends PartialOrValue<TSignalValue>>(\n\t\tobservable: Observable<TObservableValue>,\n\t): ConnectedSignal<TSignalValue>;\n\twith<TObservableValue>(\n\t\tobservable: Observable<TObservableValue>,\n\t\treducer: Reducer<TSignalValue, TObservableValue>,\n\t): ConnectedSignal<TSignalValue>;\n\twith<TOriginSignalValue extends PartialOrValue<TSignalValue>>(\n\t\toriginSignal: () => TOriginSignalValue,\n\t): ConnectedSignal<TSignalValue>;\n\tsubscription: Subscription;\n};\n\n/**\n * Connects a signal to an observable and returns a subscription. The subscription is automatically\n * unsubscribed when the component is destroyed. If it's not called in an injection context, it must\n * be called with an injector or DestroyRef.\n *\n *\n * Usage\n * ```ts\n * @Component({})\n * export class MyComponent {\n *  private dataService = inject(DataService);\n *\n *  data = signal([] as string[]);\n *\n *  constructor() {\n *    connect(this.data, this.dataService.data$);\n *  }\n * }\n * ```\n */\nexport function connect<TSignalValue>(\n\tsignal: WritableSignal<TSignalValue>,\n\tinjectorOrDestroyRef?: Injector | DestroyRef,\n\tuseUntracked?: boolean,\n): ConnectedSignal<TSignalValue>;\n\n/**\n * Connects a signal to another signal value.\n * @param signal The signal to connect to.\n * @param originSignal A callback fn that includes a signal call. The signal call will be tracked.\n *\n * Usage\n * ```ts\n * export class MyComponent {\n * \tprivate dataService = inject(DataService);\n *\n * \tname = signal('');\n *\n *  constructor() {\n *    connect(this.name, () => this.dataService.user().name);\n *  }\n * }\n * ```\n */\nexport function connect<TSignalValue>(\n\tsignal: WritableSignal<TSignalValue>,\n\toriginSignal: () => TSignalValue,\n): EffectRef;\n\nexport function connect<\n\tTSignalValue,\n\tTObservableValue extends PartialOrValue<TSignalValue>,\n>(\n\tsignal: WritableSignal<TSignalValue>,\n\tobservable: Observable<TObservableValue>,\n\tinjectorOrDestroyRef?: Injector | DestroyRef,\n\tuseUntracked?: boolean,\n): Subscription;\nexport function connect<TSignalValue, TObservableValue>(\n\tsignal: WritableSignal<TSignalValue>,\n\tobservable: Observable<TObservableValue>,\n\treducer: Reducer<TSignalValue, TObservableValue>,\n\tinjectorOrDestroyRef?: Injector | DestroyRef,\n\tuseUntracked?: boolean,\n): Subscription;\nexport function connect(signal: WritableSignal<unknown>, ...args: any[]) {\n\tconst [\n\t\tobservable,\n\t\treducer,\n\t\tinjectorOrDestroyRef,\n\t\tuseUntracked,\n\t\toriginSignal,\n\t] = parseArgs(args);\n\n\tif (observable) {\n\t\tlet destroyRef = null;\n\n\t\tif (injectorOrDestroyRef instanceof DestroyRef) {\n\t\t\tdestroyRef = injectorOrDestroyRef; // if it's a DestroyRef, use it\n\t\t} else {\n\t\t\tconst injector = assertInjector(connect, injectorOrDestroyRef);\n\t\t\tdestroyRef = injector.get(DestroyRef);\n\t\t}\n\n\t\treturn observable.pipe(takeUntilDestroyed(destroyRef)).subscribe((x) => {\n\t\t\tconst update = () => {\n\t\t\t\tsignal.update((prev) => {\n\t\t\t\t\tif (!isObject(prev)) {\n\t\t\t\t\t\treturn reducer ? reducer(prev, x) : x;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!isObject(x)) {\n\t\t\t\t\t\tconst reducedValue = reducer ? reducer(prev, x) : x;\n\n\t\t\t\t\t\treturn isObject(reducedValue)\n\t\t\t\t\t\t\t? { ...prev, ...(reducedValue as object) }\n\t\t\t\t\t\t\t: reducedValue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst curr = reducer ? reducer(prev, x) : x;\n\n\t\t\t\t\tif (isDate(curr)) {\n\t\t\t\t\t\treturn new Date(curr);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn { ...prev, ...(curr as object) };\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tif (useUntracked) {\n\t\t\t\tuntracked(update);\n\t\t\t} else {\n\t\t\t\tupdate();\n\t\t\t}\n\t\t});\n\t}\n\n\tif (originSignal) {\n\t\tconst injector =\n\t\t\tinjectorOrDestroyRef instanceof Injector\n\t\t\t\t? assertInjector(connect, injectorOrDestroyRef)\n\t\t\t\t: undefined;\n\n\t\treturn effect(\n\t\t\t() => {\n\t\t\t\tsignal.update((prev) => {\n\t\t\t\t\tconst curr = originSignal();\n\n\t\t\t\t\tif (!isObject(prev)) {\n\t\t\t\t\t\treturn curr;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isDate(curr)) {\n\t\t\t\t\t\treturn new Date(curr);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn { ...prev, ...(curr as object) };\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ injector },\n\t\t);\n\t}\n\n\treturn {\n\t\twith(this: ConnectedSignal<unknown>, ...args: unknown[]) {\n\t\t\tif (!this.subscription) {\n\t\t\t\tthis.subscription = new Subscription();\n\t\t\t} else if (this.subscription.closed) {\n\t\t\t\tconsole.info(`[ngxtension connect] ConnectedSignal has been closed.`);\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tthis.subscription.add(\n\t\t\t\tconnect(\n\t\t\t\t\tsignal,\n\t\t\t\t\t...(args as any),\n\t\t\t\t\tinjectorOrDestroyRef as any,\n\t\t\t\t\tuseUntracked,\n\t\t\t\t) as unknown as Subscription,\n\t\t\t);\n\t\t\treturn this;\n\t\t},\n\t\tsubscription: null!,\n\t} as ConnectedSignal<unknown>;\n}\n\nfunction parseArgs(\n\targs: any[],\n): [\n\tObservable<unknown> | null,\n\tReducer<unknown, unknown> | null,\n\tInjector | DestroyRef | null,\n\tboolean,\n\t(() => unknown) | null,\n] {\n\tconst array = [...args];\n\n\tconst takeIf = (predicate: (val: any) => boolean) =>\n\t\tpredicate(array[0]) ? array.shift() : null;\n\n\tconst observable = takeIf(isObservable);\n\n\tconst originSignal = !observable\n\t\t? takeIf((v) => typeof v === 'function')\n\t\t: null;\n\n\tconst reducer = observable ? takeIf((v) => typeof v === 'function') : null;\n\n\tconst injectorOrDestroyRef = takeIf(\n\t\t(v) => typeof v === 'object' && v !== null,\n\t);\n\n\tconst useUntracked = takeIf((v) => typeof v === 'boolean') ?? false;\n\n\treturn [\n\t\tobservable,\n\t\treducer,\n\t\tinjectorOrDestroyRef,\n\t\tuseUntracked,\n\t\toriginSignal,\n\t];\n}\n\nfunction isDate(val: any): val is Date {\n\treturn val instanceof Date;\n}\n\nfunction isObject(val: any): val is object {\n\treturn (\n\t\ttypeof val === 'object' &&\n\t\tval !== undefined &&\n\t\tval !== null &&\n\t\t!Array.isArray(val)\n\t);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}