{"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?.(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?.(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\n// TODO: there must be a way to parse the args more efficiently\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\tif (args.length > 3) {\n\t\treturn [\n\t\t\targs[0] as Observable<unknown>,\n\t\t\targs[1] as Reducer<unknown, unknown>,\n\t\t\targs[2] as Injector | DestroyRef,\n\t\t\targs[3] as boolean,\n\t\t\tnull,\n\t\t];\n\t}\n\n\tif (args.length === 3) {\n\t\tif (typeof args[2] === 'boolean') {\n\t\t\tif (isObservable(args[0])) {\n\t\t\t\treturn [\n\t\t\t\t\targs[0] as Observable<unknown>,\n\t\t\t\t\tnull,\n\t\t\t\t\targs[1] as Injector | DestroyRef,\n\t\t\t\t\targs[2],\n\t\t\t\t\tnull,\n\t\t\t\t];\n\t\t\t} else {\n\t\t\t\treturn [\n\t\t\t\t\tnull,\n\t\t\t\t\tnull,\n\t\t\t\t\targs[1] as Injector | DestroyRef,\n\t\t\t\t\targs[2],\n\t\t\t\t\targs[0] as () => unknown,\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\treturn [\n\t\t\targs[0] as Observable<unknown>,\n\t\t\targs[1] as Reducer<unknown, unknown>,\n\t\t\targs[2] as Injector | DestroyRef,\n\t\t\tfalse,\n\t\t\tnull,\n\t\t];\n\t}\n\n\tif (args.length === 2) {\n\t\tif (typeof args[1] === 'boolean') {\n\t\t\treturn [null, null, args[0] as Injector | DestroyRef, args[1], null];\n\t\t}\n\n\t\tif (typeof args[1] === 'function') {\n\t\t\treturn [\n\t\t\t\targs[0] as Observable<unknown>,\n\t\t\t\targs[1] as Reducer<unknown, unknown>,\n\t\t\t\tnull,\n\t\t\t\tfalse,\n\t\t\t\tnull,\n\t\t\t];\n\t\t}\n\n\t\treturn [\n\t\t\targs[0] as Observable<unknown>,\n\t\t\tnull,\n\t\t\targs[1] as Injector | DestroyRef,\n\t\t\tfalse,\n\t\t\tnull,\n\t\t];\n\t}\n\n\tif (isObservable(args[0])) {\n\t\treturn [args[0] as Observable<unknown>, null, null, false, null];\n\t}\n\n\t// to connect signals to other signals, we need to use a callback that includes a signal call\n\tif (typeof args[0] === 'function') {\n\t\treturn [null, null, null, false, args[0] as () => unknown];\n\t}\n\n\treturn [null, null, args[0] as Injector | DestroyRef, false, null];\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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"}