{"version":3,"file":"index.mjs","names":["DYNAMIC_SEGMENT: unique symbol","DYNAMIC_EXTENDED_SEGMENT: unique symbol","result: any","resolvedOptions: Required<KeyHierarchyOptions>"],"sources":["../src/runtime/utils.ts","../src/types.ts","../src/runtime/precompute.ts","../src/runtime/proxy.ts","../src/index.ts"],"sourcesContent":["export function deepFreeze(value: any): unknown {\n  if (value === undefined || value === null) {\n    return value\n  }\n  Object.freeze(value)\n  Object.getOwnPropertyNames(value).forEach((prop) => {\n    if (value[prop] !== null\n      && (typeof value[prop] === 'object' || typeof value[prop] === 'function')\n      && !Object.isFrozen(value[prop])) {\n      deepFreeze(value[prop])\n    }\n  })\n  return value\n}\n\nexport function createClone<T>(value: T): T {\n  if (typeof value === 'function' || typeof value === 'symbol') {\n    return value\n  }\n  return structuredClone(value)\n}\n","/**\n * Represents a key hierarchy for a given object type.\n * Dynamically derived based on a provided {@link KeyHierarchyConfig}.\n */\nexport type KeyHierarchy<\n  T,\n  Path extends readonly unknown[] = [],\n> = {\n    readonly [K in keyof T as K extends InternalKeys\n    ? never\n    : K extends number\n    ? `${K}`\n    : K]:\n    // 1) dynamic *extend*: property is a function that accepts Arg and returns a nested hierarchy\n    T[K] extends DynamicExtendedSegment<infer Arg, infer U>\n    ? (arg: Arg) => KeyHierarchy<\n      U,\n      readonly [...Path, readonly [K extends number ? `${K}` : K, DeepReadonly<Arg>]]\n    > & {\n      readonly __key: readonly [...Path, readonly [K extends number ? `${K}` : K, DeepReadonly<Arg>]]\n    }\n\n    // 2) dynamic *leaf*: property is a function that accepts Arg and returns the final tuple\n    : T[K] extends DynamicSegment<infer Arg>\n    ? (arg: Arg) => readonly [...Path, readonly [K extends number ? `${K}` : K, DeepReadonly<Arg>]]\n\n    // 3) nested (normal object) => recurse and expose __key\n    : T[K] extends object\n    ? KeyHierarchy<\n      T[K],\n      readonly [...Path, K extends number ? `${K}` : K]\n    > & {\n      readonly __key: readonly [...Path, K extends number ? `${K}` : K]\n    }\n\n    // 4) plain leaf (true) => final tuple\n    : readonly [...Path, K extends number ? `${K}` : K]\n  }\n\nexport const DYNAMIC_SEGMENT: unique symbol = Symbol('DynamicSegment')\n\nexport interface DynamicSegment<T> {\n  readonly [DYNAMIC_SEGMENT]: T\n}\n\nexport const DYNAMIC_EXTENDED_SEGMENT: unique symbol = Symbol('DynamicExtendedSegment')\n\nexport type DynamicExtendedSegment<T, U extends KeyHierarchyConfig<U>> = U & {\n  readonly [DYNAMIC_EXTENDED_SEGMENT]: T\n}\n\nexport type DynamicExtendableSegment<T> = DynamicSegment<T> & {\n  /**\n   * Extends the dynamic segment with a nested configuration.\n   * @param config - The nested configuration to extend the dynamic segment with.\n   * @returns The extended dynamic segment.\n   */\n  extend: <U extends KeyHierarchyConfig<U>>(config: U) => DynamicExtendedSegment<T, U>\n}\n\ntype InternalKeys = '__key' | typeof DYNAMIC_SEGMENT | typeof DYNAMIC_EXTENDED_SEGMENT\n\n/**\n * Declarative configuration of a key hierarchy.\n * @remarks **Note:** May not contain `__key` as a property at any place.\n */\nexport type KeyHierarchyConfig<T> =\n  '__key' extends keyof T ? never\n  : {\n    [K in keyof T as K extends InternalKeys ? never : K]:\n    T[K] extends DynamicSegment<infer Arg>\n    ? DynamicExtendableSegment<Arg>\n    : T[K] extends DynamicExtendedSegment<infer Arg, infer U>\n    ? DynamicExtendedSegment<Arg, U>\n    // eslint-disable-next-line ts/no-unsafe-function-type\n    : T[K] extends Function\n    ? never\n    : T[K] extends object\n    ? KeyHierarchyConfig<T[K]>\n    : true\n  }\n\n/**\n * Options for a key hierarchy.\n */\nexport interface KeyHierarchyOptions {\n  /**\n   * If enabled, all key arrays and their elements will be deeply frozen.\n   * While already present at the type level, due to {@link DeepReadonly}, this ensures true immutability during runtime.\n   * @remarks **Note:** Function arguments will be cloned with {@link structuredClone} to not affect the original values.\n   * @remarks **Warning:** Does not work with values that are not supported by {@link structuredClone}.\n   * @remarks **Warning:** Do not enable this for `queryKey` or `mutationKey` with `@tanstack/vue-query` as it will cause issues with reactivity.\n   * @defaultValue false\n   */\n  freeze?: boolean\n  /**\n   * The method to use for key hierarchy computation.\n   * `proxy` uses a {@link Proxy} to dynamically resolve keys on demand.\n   * `precompute` computes the key hierarchy upfront.\n   * @defaultValue 'proxy'\n   */\n  method?: 'proxy' | 'precompute'\n}\n\n/**\n * Represents a deeply readonly version of a type.\n */\nexport type DeepReadonly<T> =\n  T extends (infer R)[] ? DeepReadonlyArray<R> :\n  // eslint-disable-next-line ts/no-unsafe-function-type\n  T extends Function ? T :\n  T extends object ? DeepReadonlyObject<T> :\n  T\n\n/**\n * Represents a deeply readonly version of an array.\n */\nexport interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> { }\n\n/**\n * Represents a deeply readonly version of an object.\n */\nexport type DeepReadonlyObject<T> = {\n  readonly [P in keyof T]: DeepReadonly<T[P]>;\n}\n","import { createClone, deepFreeze } from './utils'\nimport { DYNAMIC_EXTENDED_SEGMENT, DYNAMIC_SEGMENT } from '../types'\nimport type { KeyHierarchyOptions } from '../types'\n\nexport function precomputeHierarchy(path: unknown[], currentConfig: any, options: Required<KeyHierarchyOptions>): any {\n  const result: any = {}\n\n  // Iterate over all own properties, including symbols\n  const keys = [...Object.keys(currentConfig), ...Object.getOwnPropertySymbols(currentConfig)]\n    .filter((key) => key !== DYNAMIC_SEGMENT && key !== DYNAMIC_EXTENDED_SEGMENT) as (string | symbol)[]\n\n  for (const key of keys) {\n    const value = currentConfig[key]\n    const currentPath = [...path, key]\n\n    if (typeof value === 'boolean') {\n      // Leaf node: return the path\n      result[key] = options.freeze ? deepFreeze(currentPath) : [...currentPath]\n    } else if (typeof value === 'object' && value !== null) {\n      // Check if this is a DynamicExtend object\n      if (DYNAMIC_EXTENDED_SEGMENT in value) {\n        // Extract the extended config (symbols are not enumerable, so spread gets everything else)\n        const extendedConfig = { ...value }\n\n        // Create a function that returns the precomputed hierarchy for the extended config\n        result[key] = (arg: unknown) => {\n          const argPath = options.freeze ? createClone(arg) : arg\n          const functionPath = [...path, [key, argPath]]\n\n          // Precompute the sub-hierarchy with the extended config\n          const nested = precomputeHierarchy(functionPath, extendedConfig, options)\n          nested.__key = options.freeze ? deepFreeze(functionPath) : functionPath\n          return nested\n        }\n      } else if (DYNAMIC_SEGMENT in value) { // Check if this is a DynamicLeaf object\n        // Create a function that returns the final path\n        result[key] = (arg: unknown) => {\n          const argPath = options.freeze ? createClone(arg) : arg\n          const functionPath = [...path, [key, argPath]]\n\n          // Leaf node\n          return options.freeze ? deepFreeze(functionPath) : functionPath\n        }\n      } else { // Regular nested object: recurse\n        const nested = precomputeHierarchy(currentPath, value, options)\n        nested.__key = options.freeze ? deepFreeze(currentPath) : [...currentPath]\n        result[key] = nested\n      }\n    }\n  }\n\n  return result\n}\n","import { createClone, deepFreeze } from './utils'\nimport { DYNAMIC_EXTENDED_SEGMENT, DYNAMIC_SEGMENT } from '../types'\nimport type { KeyHierarchyOptions } from '../types'\n\nexport function createProxy<T>(path: unknown[], currentConfig: unknown, options: Required<KeyHierarchyOptions>): unknown {\n  return new Proxy(\n    {},\n    {\n      get(_, prop: string | number | symbol) {\n        // Return the frozen path for __key\n        if (prop === '__key') {\n          if (options.freeze) {\n            return deepFreeze([...path])\n          }\n          return [...path]\n        }\n\n        const value = (currentConfig as T)[prop as keyof T]\n\n        // Handle DynamicExtend - create a function that returns a proxy to the extended config\n        if (typeof value === 'object' && value !== null && DYNAMIC_EXTENDED_SEGMENT in value) {\n          return (arg: unknown) => {\n            const argPath = options.freeze ? createClone(arg) : arg\n            const functionPath = [\n              ...path,\n              [prop, argPath],\n            ]\n\n            // Extract the extended config (symbols are not enumerable, so spread gets everything else)\n            const extendedConfig = { ...value }\n\n            // Continue with nested object using the extended config\n            return createProxy(functionPath, extendedConfig, options)\n          }\n        }\n\n        // Handle DynamicLeaf - create a function that returns the final path\n        if (typeof value === 'object' && value !== null && DYNAMIC_SEGMENT in value) {\n          return (arg: unknown) => {\n            const argPath = options.freeze ? createClone(arg) : arg\n            const functionPath = [\n              ...path,\n              [prop, argPath],\n            ]\n\n            // Leaf node reached\n            if (options.freeze) {\n              return deepFreeze(functionPath)\n            }\n            return functionPath\n          }\n        }\n\n        // Handle object properties (non-dynamic)\n        if (typeof value === 'object' && value !== null) {\n          return createProxy([...path, prop], value, options)\n        }\n\n        if (options.freeze) {\n          return deepFreeze([...path, prop])\n        }\n        // Leaf node - return the path array\n        return [...path, prop]\n      },\n    },\n  )\n}\n","import { precomputeHierarchy } from './runtime/precompute'\nimport { createProxy } from './runtime/proxy'\nimport { DYNAMIC_EXTENDED_SEGMENT, DYNAMIC_SEGMENT } from './types'\nimport type { KeyHierarchyConfig, KeyHierarchyOptions, KeyHierarchy, DynamicExtendedSegment, DynamicExtendableSegment } from './types'\n\nexport type * from './types'\n\n/**\n * Represents a configuration or a builder function for a key hierarchy.\n */\nexport type ConfigOrBuilder<T extends KeyHierarchyConfig<T>> = T | ((dynamic: typeof dynamicHelper) => T)\n\nfunction resolveConfigOrBuilder<T extends KeyHierarchyConfig<T>>(configOrBuilder: ConfigOrBuilder<T>): T {\n  return typeof configOrBuilder === 'function' ? configOrBuilder(dynamicHelper) : configOrBuilder\n}\n\n/**\n * Defines a key hierarchy based on the provided configuration and options.\n * @remarks **Note:** This function uses {@link Proxy} objects by default. See {@link KeyHierarchyOptions.method} for other options.\n * @param config - The declarative {@link KeyHierarchyConfig} of the key hierarchy.\n * @param options - The {@link KeyHierarchyOptions} for the key hierarchy.\n * @returns The {@link KeyHierarchy} derived from the given config and options.\n * @example\n * ```ts\n * const keys = defineKeyHierarchy((dynamic) => ({\n *   users: {\n *     getAll: true,\n *     create: true,\n *     byId: dynamic<number>().extend({\n *       get: true,\n *       update: true,\n *       delete: true,\n *     }),\n *   },\n *   posts: {\n *     byUserId: dynamic<number>(),\n *     byMonth: dynamic<number>().extend({\n *       byDay: dynamic<number>(),\n *     }),\n *     byAuthorAndYear: dynamic<{ authorId: string, year: number }>(),\n *     byTags: dynamic<{ tags: string[], filter?: PostFilter }>(),\n *   }\n * }))\n * console.log(keys.users.getAll) // readonly ['users', 'getAll']\n * console.log(keys.users.byId(42).update) // readonly ['users', ['byId', 42], 'update']\n * console.log(keys.users.byId(42).__key) // readonly ['users', ['byId', 42]]\n * console.log(keys.posts.byUserId(42)) // readonly ['posts', ['byUserId', 42]]\n * console.log(keys.posts.byMonth(3).byDay(15)) // readonly ['posts', ['byMonth', 3], ['byDay', 15]]\n * console.log(keys.posts.byAuthorAndYear({ authorId: 'id', year: 2023 })) // readonly ['posts', ['byAuthorAndYear', { authorId: 'id', year: 2023 }]]\n * ```\n */\nexport function defineKeyHierarchy<T extends KeyHierarchyConfig<T>>(configOrBuilder: ConfigOrBuilder<T>, options: KeyHierarchyOptions = {}): KeyHierarchy<T> {\n  const resolvedOptions: Required<KeyHierarchyOptions> = {\n    freeze: false,\n    method: 'proxy',\n    ...options,\n  }\n\n  const resolvedConfig = defineKeyHierarchyModule(configOrBuilder)\n\n  if (resolvedOptions.method === 'precompute') {\n    return precomputeHierarchy([], resolvedConfig, resolvedOptions) as KeyHierarchy<T>\n  }\n\n  return createProxy([], resolvedConfig, resolvedOptions) as KeyHierarchy<T>\n}\n\n/**\n * Defines a key hierarchy module.\n * @remarks This function is a no-op and is used for type inference only.\n * @param config - The declarative {@link KeyHierarchyConfig} of the key hierarchy module.\n * @returns The {@link KeyHierarchyConfig} of the key hierarchy module.\n * @example\n * ```ts\n * const userKeyModule = defineKeyHierarchyModule((dynamic) => ({\n *   getAll: true,\n *   create: true,\n *   byId: dynamic<number>().extend({\n *     get: true,\n *     update: true,\n *     delete: true,\n *   })\n * }))\n *\n * const postKeyModule = defineKeyHierarchyModule((dynamic) => ({\n *   byUserId: dynamic<number>(),\n *   byMonth: dynamic<number>().extend({\n *     byDay: dynamic<number>(),\n *   })\n * })\n *\n * const keys = defineKeyHierarchy({\n *   users: userKeyModule,\n *   posts: postKeyModule\n * })\n * ```\n */\nexport function defineKeyHierarchyModule<T extends KeyHierarchyConfig<T>>(configOrBuilder: ConfigOrBuilder<T>): T {\n  return resolveConfigOrBuilder(configOrBuilder)\n}\n\n/**\n * Helper function to define dynamic key segments with a single argument.\n * @returns A dynamic key segment that can optionally be extended with a nested configuration.\n * @example\n * ```ts\n * defineKeyHierarchy({\n *   getAll: true,\n *   byGroup: dynamic<{ groupId: string }>(),\n *   byId: dynamic<string>().extend({ get: true, update: true }),\n *   byMonth: dynamic<number>().extend({\n *     byDay: dynamic<number>(),\n *   }),\n *   byAuthorAndYear: dynamic<{ authorId: string, year: number }>(),\n *   byTags: dynamic<{ tags: string[], filter?: PostFilter }>(),\n * })\n * ```\n */\nfunction dynamicHelper<T>(): DynamicExtendableSegment<T> {\n  return {\n    [DYNAMIC_SEGMENT]: undefined as any as T,\n    extend<U extends KeyHierarchyConfig<U>>(config: U): DynamicExtendedSegment<T, U> {\n      return {\n        [DYNAMIC_EXTENDED_SEGMENT]: undefined as any as T,\n        ...config,\n      }\n    },\n  } as DynamicExtendableSegment<T>\n}\n"],"mappings":"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"}