{"version":3,"file":"evolve.cjs","names":["purry"],"sources":["../src/evolve.ts"],"sourcesContent":["import type { IterableContainer } from \"./internal/types/IterableContainer\";\nimport { purry } from \"./purry\";\n\n/**\n * Basic structure of `evolver` parameter of the function `evolve`.\n */\ntype GenericEvolver = {\n  readonly [P in string]: GenericEvolver | ((data: unknown) => unknown);\n};\n\n/**\n * Creates an assumed `evolver` type from the type of `data` argument.\n *\n * @example\n * interface Data {\n *   id: number;\n *   quartile: number[];\n *   time?: { elapsed: number; remaining?: number };\n * }\n * type Nested = Evolver<Data>; //  => type Nested = {\n * //   id?: ((data: number) => unknown) | undefined;\n * //   quartile?: ((data: number[]) => unknown) | undefined;\n * //   time?:\n * //     | ((data: { elapsed: number; remaining?: number | undefined }) => unknown)\n * //     | {\n * //         elapsed?: ((data: number) => unknown) | undefined;\n * //         remaining?: ((data: number) => unknown) | undefined;\n * //       }\n * //     | undefined;\n * // };\n */\ntype Evolver<T> = T extends object\n  ? T extends IterableContainer\n    ? never\n    : {\n        readonly [K in keyof T]?: K extends symbol\n          ? never\n          : Evolver<T[K]> | ((data: Required<T>[K]) => unknown);\n      }\n  : never;\n\n/**\n * Creates return type from the type of arguments of `evolve`.\n */\ntype Evolved<T, E> = T extends object\n  ? {\n      -readonly [K in keyof T]: K extends keyof E\n        ? E[K] extends (\n            // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Functions aren't inferred correctly when using `unknown` for the params.\n            ...arg: any\n          ) => infer R\n          ? R\n          : Evolved<T[K], E[K]>\n        : Required<T>[K];\n    }\n  : T;\n\n/**\n * Creates a new object by applying functions that is included in `evolver` object parameter\n * to the `data` object parameter according to their corresponding path.\n *\n * Functions included in `evolver` object will not be invoked\n * if its corresponding key does not exist in the `data` object.\n * Also, values included in `data` object will be kept as is\n * if its corresponding key does not exist in the `evolver` object.\n *\n * @param object - Object whose value is applied to the corresponding function\n * that is defined in `evolver` at the same path.\n * @param evolver - Object that include functions that is applied to\n * the corresponding value of `data` object at the same path.\n * @signature\n *    evolve(data, evolver)\n * @example\n *    const evolver = {\n *      count: add(1),\n *      time: { elapsed: add(1), remaining: add(-1) },\n *    };\n *    const data = {\n *      id: 10,\n *      count: 10,\n *      time: { elapsed: 100, remaining: 1400 },\n *    };\n *    evolve(data, evolver)\n *    // => {\n *    //   id: 10,\n *    //   count: 11,\n *    //   time: { elapsed: 101, remaining: 1399 },\n *    // }\n * @dataFirst\n * @category Object\n */\nexport function evolve<T extends object, E extends Evolver<T>>(\n  object: T,\n  evolver: E,\n): Evolved<T, E>;\n\n/**\n * Creates a new object by applying functions that is included in `evolver` object parameter\n * to the `data` object parameter according to their corresponding path.\n *\n * Functions included in `evolver` object will not be invoked\n * if its corresponding key does not exist in the `data` object.\n * Also, values included in `data` object will not be used\n * if its corresponding key does not exist in the `evolver` object.\n *\n * @param evolver - Object that include functions that is applied to\n * the corresponding value of `data` object at the same path.\n * @signature\n *    evolve(evolver)(data)\n * @example\n *    const evolver = {\n *      count: add(1),\n *      time: { elapsed: add(1), remaining: add(-1) },\n *    };\n *    const data = {\n *      id: 10,\n *      count: 10,\n *      time: { elapsed: 100, remaining: 1400 },\n *    };\n *    pipe(data, evolve(evolver))\n *    // => {\n *    //   id: 10,\n *    //   count: 11,\n *    //   time: { elapsed: 101, remaining: 1399 },\n *    // }\n * @dataLast\n * @category Object\n */\nexport function evolve<T extends object, E extends Evolver<T>>(\n  evolver: E,\n): (object: T) => Evolved<T, E>;\n\nexport function evolve(...args: readonly unknown[]): unknown {\n  return purry(evolveImplementation, args);\n}\n\nfunction evolveImplementation(data: unknown, evolver: GenericEvolver): unknown {\n  if (typeof data !== \"object\" || data === null) {\n    return data;\n  }\n\n  const out: Record<string, unknown> = { ...data };\n\n  for (const [key, value] of Object.entries(evolver)) {\n    if (key in out) {\n      out[key] =\n        typeof value === \"function\"\n          ? value(out[key])\n          : evolveImplementation(out[key], value);\n    }\n  }\n\n  return out;\n}\n"],"mappings":"kGAoIA,SAAgB,EAAO,GAAG,EAAmC,CAC3D,OAAOA,EAAAA,MAAM,EAAsB,EAAK,CAG1C,SAAS,EAAqB,EAAe,EAAkC,CAC7E,GAAI,OAAO,GAAS,WAAY,EAC9B,OAAO,EAGT,IAAM,EAA+B,CAAE,GAAG,EAAM,CAEhD,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAQ,CAC5C,KAAO,IACT,EAAI,GACF,OAAO,GAAU,WACb,EAAM,EAAI,GAAK,CACf,EAAqB,EAAI,GAAM,EAAM,EAI/C,OAAO"}