{"version":3,"file":"ngxtension-inject-route-data.mjs","sources":["../../../../libs/ngxtension/inject-route-data/src/inject-route-data.ts","../../../../libs/ngxtension/inject-route-data/src/ngxtension-inject-route-data.ts"],"sourcesContent":["import { inject, type Signal } from '@angular/core';\nimport { toObservable, toSignal } from '@angular/core/rxjs-interop';\nimport { ActivatedRoute, type Data } from '@angular/router';\nimport { assertInjector } from 'ngxtension/assert-injector';\nimport { injectLeafActivatedRoute } from 'ngxtension/inject-leaf-activated-route';\nimport { DefaultValueOptions, InjectorOptions } from 'ngxtension/shared';\nimport { map, switchMap } from 'rxjs';\n\ntype RouteDataTransformFn<T> = (data: Data) => T;\n\n/**\n * Merges all data from the route hierarchy by walking from root to the given route.\n * Child route data override parent route data if there are naming conflicts.\n */\nfunction mergeRouteData(route: ActivatedRoute): Data {\n\t// Build path from root to current route\n\tconst routePath: ActivatedRoute[] = [];\n\tlet currentRoute: ActivatedRoute | null = route;\n\n\twhile (currentRoute) {\n\t\troutePath.unshift(currentRoute);\n\t\tcurrentRoute = currentRoute.parent;\n\t}\n\n\t// Merge data from root to leaf (child data overrides parent data)\n\tconst mergedData: Data = {};\n\tfor (const r of routePath) {\n\t\tconst data = r.snapshot?.data || {};\n\t\tObject.assign(mergedData, data);\n\t}\n\n\treturn mergedData;\n}\n\n/**\n * The `RouteDataOptions` type defines options for configuring the behavior of the `injectRouteData` function.\n *\n * @template ReadT - The expected type of the read value.\n * @template WriteT - The type of the value to be written.\n * @template DefaultValueT - The type of the default value.\n */\nexport type RouteDataOptions<DefaultValueT> =\n\tDefaultValueOptions<DefaultValueT> & InjectorOptions;\n\n/**\n * Core implementation shared between `injectRouteData` and `injectRouteData.global`.\n * Handles the logic for accessing route data based on key, transform function, or returning all data.\n */\nfunction injectRouteDataCore<T>(\n\tdataObservable: import('rxjs').Observable<Data>,\n\tinitialData: Data,\n\tkeyOrTransform?: keyof Data | RouteDataTransformFn<T>,\n\toptions: RouteDataOptions<T> = {},\n): Signal<T | Data | null> {\n\tconst { defaultValue } = options;\n\n\tif (!keyOrTransform) {\n\t\treturn toSignal(dataObservable, { initialValue: initialData });\n\t}\n\n\tif (typeof keyOrTransform === 'function') {\n\t\treturn toSignal(dataObservable.pipe(map(keyOrTransform)), {\n\t\t\tinitialValue: keyOrTransform(initialData),\n\t\t});\n\t}\n\n\tconst getDataParam = (data: Data) => {\n\t\tconst param = data?.[keyOrTransform as keyof Data] as unknown | undefined;\n\t\treturn param ?? defaultValue ?? null;\n\t};\n\n\treturn toSignal(dataObservable.pipe(map(getDataParam)), {\n\t\tinitialValue: getDataParam(initialData),\n\t});\n}\n\n/**\n * The `injectRouteData` function allows you to access and manipulate route data from the current route.\n *\n * @returns A `Signal` that emits the entire data object.\n */\nexport function injectRouteData(): Signal<Data>;\n\n/**\n * The `injectRouteData` function allows you to access and manipulate route data from the current route.\n *\n * @template T - The expected type of the read value.\n * @param {string} key - The name of the route data to retrieve.\n * @param {RouteDataOptions} options - Optional configuration options for the route data.\n * @returns {Signal} A `Signal` that emits the value of the specified route data, or `null` if it's not present.\n */\nexport function injectRouteData<T>(\n\tkey: keyof Data,\n\toptions?: RouteDataOptions<T>,\n): Signal<T | null>;\n\n/**\n * The `injectRouteData` function allows you to access and manipulate route data from the current route.\n * It retrieves the value of the route data based on a custom transform function applied to the route data object.\n *\n * @template T - The expected type of the read value.\n * @param {RouteDataTransformFn<T>} fn - A transform function that takes the route data object and returns the desired value.\n * @param {RouteDataOptions} options - Optional configuration options for the route data.\n * @returns {Signal<T>} A `Signal` that emits the transformed value based on the provided custom transform function.\n *\n * @example\n * const searchValue = injectRouteData((data) => data['search'] as string);\n */\nexport function injectRouteData<ReadT>(\n\tfn: RouteDataTransformFn<ReadT>,\n\toptions?: RouteDataOptions<ReadT>,\n): Signal<ReadT>;\n\nexport function injectRouteData<T>(\n\tkeyOrTransform?: keyof Data | RouteDataTransformFn<T>,\n\toptions: RouteDataOptions<T> = {},\n) {\n\treturn assertInjector(injectRouteData, options?.injector, () => {\n\t\tconst route = inject(ActivatedRoute);\n\t\treturn injectRouteDataCore(\n\t\t\troute.data,\n\t\t\troute.snapshot.data || {},\n\t\t\tkeyOrTransform,\n\t\t\toptions,\n\t\t);\n\t});\n}\n\n/**\n * Global variant of `injectRouteData` that retrieves route data from the leaf (deepest) `ActivatedRoute` in the router state tree.\n * This allows you to access route data from the entire route hierarchy, including child routes,\n * regardless of where your component is positioned in the component tree.\n *\n * @template T - The expected type of the read value.\n * @param keyOrTransform OPTIONAL The key of the route data to return, or a transform function to apply to the route data object\n * @param {RouteDataOptions} options - Optional configuration options for the route data.\n * @returns {Signal} A `Signal` that emits the transformed value of the specified route data, or the entire data object if no key is provided.\n *\n * @example\n * // Get all route data from route hierarchy\n * const data = injectRouteData.global();\n *\n * @example\n * // Get specific data from route hierarchy\n * const title = injectRouteData.global('title');\n *\n * @example\n * // Transform route data from route hierarchy\n * const breadcrumbs = injectRouteData.global((data) => data['breadcrumbs'] as string[]);\n *\n * @example\n * // With default value option\n * const title = injectRouteData.global('title', { defaultValue: 'Default Title' });\n */\ninjectRouteData.global = function <T>(\n\tkeyOrTransform?: keyof Data | RouteDataTransformFn<T>,\n\toptions: RouteDataOptions<T> = {},\n): Signal<T | Data | null> {\n\treturn assertInjector(injectRouteData.global, options?.injector, () => {\n\t\tconst leafRoute = injectLeafActivatedRoute();\n\t\tconst leafRoute$ = toObservable(leafRoute);\n\n\t\tconst mergedData$ = leafRoute$.pipe(\n\t\t\tswitchMap((route) => route.data),\n\t\t\tmap(() => mergeRouteData(leafRoute())),\n\t\t);\n\n\t\treturn injectRouteDataCore(\n\t\t\tmergedData$,\n\t\t\tmergeRouteData(leafRoute()),\n\t\t\tkeyOrTransform,\n\t\t\toptions,\n\t\t);\n\t});\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}