{"version":3,"file":"pipe.cjs","names":["SKIP_ITEM"],"sources":["../src/pipe.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable jsdoc/check-param-names -- we don't document the op params, it'd be redundant */\n\nimport type { LazyDefinition } from \"./internal/types/LazyDefinition\";\nimport type { LazyEvaluator } from \"./internal/types/LazyEvaluator\";\nimport type { LazyResult } from \"./internal/types/LazyResult\";\nimport { SKIP_ITEM } from \"./internal/utilityEvaluators\";\n\ntype PreparedLazyFunction = LazyEvaluator & {\n  readonly isSingle: boolean;\n\n  // These are intentionally mutable, they maintain the lazy piped state.\n  index: number;\n  items: unknown[];\n};\n\ntype LazyFunction = LazyDefinition & ((input: unknown) => unknown);\n\n/**\n * Performs left-to-right function composition, passing data through functions\n * in sequence. Each function receives the output of the previous function,\n * creating a readable top-to-bottom data flow that matches how the\n * transformation is executed. This enables converting deeply nested function\n * calls into clear, sequential steps without temporary variables.\n *\n * When consecutive functions with a `lazy` tag (e.g., `map`, `filter`, `take`,\n * `drop`, `forEach`, etc...) are used together, they process data item-by-item\n * rather than creating intermediate arrays. This enables early termination\n * when only partial results are needed, improving performance for large\n * datasets and expensive operations.\n *\n * Functions are only evaluated lazily when their data-last form is used\n * directly in the pipe. To disable lazy evaluation, use data-first calls via\n * arrow functions: `($) => map($, callback)` instead of `map(callback)`.\n *\n * Any function can be used in pipes, not just Remeda utilities. For creating\n * custom functions with currying and lazy evaluation support, see the `purry`\n * utility.\n *\n * A \"headless\" variant `piped` is available for creating reusable pipe\n * functions without initial data.\n *\n * IMPORTANT: During lazy evaluation, callbacks using the third parameter (the\n * input array) receive only items processed up to that point, not the complete\n * array.\n *\n * @param data - The input data.\n * @param functions - A sequence of functions that take one argument and\n * return a value.\n * @signature\n *   pipe(data, ...functions);\n * @example\n *    pipe([1, 2, 3], map(multiply(3))); //=> [3, 6, 9]\n *\n *    // = Early termination with lazy evaluation =\n *    pipe(\n *      hugeArray,\n *      map(expensiveComputation),\n *      filter(complexPredicate),\n *      // Only processes items until 2 results are found, then stops.\n *      // Most of hugeArray never gets processed.\n *      take(2),\n *    );\n *\n *    // = Custom logic within a pipe =\n *    pipe(\n *      input,\n *      toLowerCase(),\n *      normalize,\n *      ($) => validate($, CONFIG),\n *      split(\",\"),\n *      unique(),\n *    );\n *\n *    // = Migrating nested transformations to pipes =\n *    // Nested\n *    const result = prop(\n *      mapValues(groupByProp(users, \"department\"), length()),\n *      \"engineering\",\n *    );\n *\n *    // Piped\n *    const result = pipe(\n *      users,\n *      groupByProp(\"department\"),\n *      mapValues(length()),\n *      prop(\"engineering\"),\n *    );\n *\n *    // = Using the 3rd param of a callback =\n *    // The following would print out `data` in its entirety for each value\n *    // of `data`.\n *    forEach([1, 2, 3, 4], (_item, _index, data) => {\n *      console.log(data);\n *    }); //=> \"[1, 2, 3, 4]\" logged 4 times\n *\n *    // But with `pipe` data would only contain the items up to the current\n *    // index\n *    pipe([1, 2, 3, 4], forEach((_item, _index, data) => {\n *      console.log(data);\n *    })); //=> \"[1]\", \"[1, 2]\", \"[1, 2, 3]\", \"[1, 2, 3, 4]\"\n * @dataFirst\n * @category Function\n */\nexport function pipe<A>(data: A): A;\n\nexport function pipe<A, B>(data: A, funcA: (input: A) => B): B;\n\nexport function pipe<A, B, C>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n): C;\n\nexport function pipe<A, B, C, D>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n): D;\n\nexport function pipe<A, B, C, D, E>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n): E;\n\nexport function pipe<A, B, C, D, E, F>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n  funcE: (input: E) => F,\n): F;\n\nexport function pipe<A, B, C, D, E, F, G>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n  funcE: (input: E) => F,\n  funcF: (input: F) => G,\n): G;\n\nexport function pipe<A, B, C, D, E, F, G, H>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n  funcE: (input: E) => F,\n  funcF: (input: F) => G,\n  funcG: (input: G) => H,\n): H;\n\nexport function pipe<A, B, C, D, E, F, G, H, I>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n  funcE: (input: E) => F,\n  funcF: (input: F) => G,\n  funcG: (input: G) => H,\n  funcH: (input: H) => I,\n): I;\n\nexport function pipe<A, B, C, D, E, F, G, H, I, J>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n  funcE: (input: E) => F,\n  funcF: (input: F) => G,\n  funcG: (input: G) => H,\n  funcH: (input: H) => I,\n  funcI: (input: I) => J,\n): J;\n\nexport function pipe<A, B, C, D, E, F, G, H, I, J, K>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n  funcE: (input: E) => F,\n  funcF: (input: F) => G,\n  funcG: (input: G) => H,\n  funcH: (input: H) => I,\n  funcI: (input: I) => J,\n  funcJ: (input: J) => K,\n): K;\n\nexport function pipe<A, B, C, D, E, F, G, H, I, J, K, L>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n  funcE: (input: E) => F,\n  funcF: (input: F) => G,\n  funcG: (input: G) => H,\n  funcH: (input: H) => I,\n  funcI: (input: I) => J,\n  funcJ: (input: J) => K,\n  funcK: (input: K) => L,\n): L;\n\nexport function pipe<A, B, C, D, E, F, G, H, I, J, K, L, M>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n  funcE: (input: E) => F,\n  funcF: (input: F) => G,\n  funcG: (input: G) => H,\n  funcH: (input: H) => I,\n  funcI: (input: I) => J,\n  funcJ: (input: J) => K,\n  funcK: (input: K) => L,\n  funcL: (input: L) => M,\n): M;\n\nexport function pipe<A, B, C, D, E, F, G, H, I, J, K, L, M, N>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n  funcE: (input: E) => F,\n  funcF: (input: F) => G,\n  funcG: (input: G) => H,\n  funcH: (input: H) => I,\n  funcI: (input: I) => J,\n  funcJ: (input: J) => K,\n  funcK: (input: K) => L,\n  funcL: (input: L) => M,\n  funcM: (input: M) => N,\n): N;\n\nexport function pipe<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n  funcE: (input: E) => F,\n  funcF: (input: F) => G,\n  funcG: (input: G) => H,\n  funcH: (input: H) => I,\n  funcI: (input: I) => J,\n  funcJ: (input: J) => K,\n  funcK: (input: K) => L,\n  funcL: (input: L) => M,\n  funcM: (input: M) => N,\n  funcN: (input: N) => O,\n): O;\n\nexport function pipe<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>(\n  data: A,\n  funcA: (input: A) => B,\n  funcB: (input: B) => C,\n  funcC: (input: C) => D,\n  funcD: (input: D) => E,\n  funcE: (input: E) => F,\n  funcF: (input: F) => G,\n  funcG: (input: G) => H,\n  funcH: (input: H) => I,\n  funcI: (input: I) => J,\n  funcJ: (input: J) => K,\n  funcK: (input: K) => L,\n  funcL: (input: L) => M,\n  funcM: (input: M) => N,\n  funcN: (input: N) => O,\n  funcO: (input: O) => P,\n): P;\n\nexport function pipe(\n  input: unknown,\n  ...functions: readonly (LazyFunction | ((value: any) => unknown))[]\n): any {\n  let output = input;\n\n  const lazyFunctions = functions.map((op) =>\n    \"lazy\" in op ? prepareLazyFunction(op) : undefined,\n  );\n\n  let functionIndex = 0;\n  while (functionIndex < functions.length) {\n    const lazyFunction = lazyFunctions[functionIndex];\n    if (lazyFunction === undefined || !isIterable(output)) {\n      const func = functions[functionIndex]!;\n      output = func(output);\n      functionIndex += 1;\n      continue;\n    }\n\n    const lazySequence: PreparedLazyFunction[] = [];\n    for (let index = functionIndex; index < functions.length; index++) {\n      const lazyOp = lazyFunctions[index];\n      if (lazyOp === undefined) {\n        break;\n      }\n\n      lazySequence.push(lazyOp);\n      if (lazyOp.isSingle) {\n        break;\n      }\n    }\n\n    const accumulator: unknown[] = [];\n\n    for (const value of output) {\n      const shouldExitEarly = processItem(value, accumulator, lazySequence);\n      if (shouldExitEarly) {\n        break;\n      }\n    }\n\n    const { isSingle } = lazySequence.at(-1)!;\n    output = isSingle ? accumulator[0] : accumulator;\n    functionIndex += lazySequence.length;\n  }\n  return output;\n}\n\nfunction processItem(\n  item: unknown,\n  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types -- Intentionally mutable, we use the accumulator directly to accumulate the results.\n  accumulator: unknown[],\n  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types -- Intentionally mutable, the lazy sequence is stateful and contains the state needed to compute the next value lazily.\n  lazySequence: readonly PreparedLazyFunction[],\n): boolean {\n  if (lazySequence.length === 0) {\n    accumulator.push(item);\n    return false;\n  }\n\n  let currentItem = item;\n\n  let lazyResult: LazyResult<any> = SKIP_ITEM;\n  let isDone = false;\n  for (const [functionsIndex, lazyFn] of lazySequence.entries()) {\n    const { index, items } = lazyFn;\n    items.push(currentItem);\n    lazyResult = lazyFn(currentItem, index, items);\n    lazyFn.index += 1;\n    if (lazyResult.hasNext) {\n      if (lazyResult.hasMany ?? false) {\n        for (const subItem of lazyResult.next as readonly unknown[]) {\n          const subResult = processItem(\n            subItem,\n            accumulator,\n            lazySequence.slice(functionsIndex + 1),\n          );\n          if (subResult) {\n            return true;\n          }\n        }\n        return isDone;\n      }\n      currentItem = lazyResult.next;\n    }\n    if (!lazyResult.hasNext) {\n      break;\n    }\n    // process remaining functions in the pipe\n    // but don't process remaining elements in the input array\n    if (lazyResult.done) {\n      isDone = true;\n    }\n  }\n  if (lazyResult.hasNext) {\n    accumulator.push(currentItem);\n  }\n  return isDone;\n}\n\nfunction prepareLazyFunction(func: LazyFunction): PreparedLazyFunction {\n  const { lazy, lazyArgs } = func;\n  const fn = lazy(...lazyArgs);\n  return Object.assign(fn, {\n    isSingle: lazy.single ?? false,\n    index: 0,\n    items: [] as unknown[],\n  });\n}\n\nfunction isIterable(something: unknown): something is Iterable<unknown> {\n  // Check for null and undefined to avoid errors when accessing Symbol.iterator\n  return (\n    typeof something === \"string\" ||\n    (typeof something === \"object\" &&\n      something !== null &&\n      Symbol.iterator in something)\n  );\n}\n"],"mappings":"uHA2RA,SAAgB,EACd,EACA,GAAG,EACE,CACL,IAAI,EAAS,EAEP,EAAgB,EAAU,IAAK,GACnC,SAAU,EAAK,EAAoB,EAAG,CAAG,IAAA,GAC1C,CAEG,EAAgB,EACpB,KAAO,EAAgB,EAAU,QAAQ,CAEvC,GADqB,EAAc,KACd,IAAA,IAAa,CAAC,EAAW,EAAO,CAAE,CACrD,IAAM,EAAO,EAAU,GACvB,EAAS,EAAK,EAAO,CACrB,GAAiB,EACjB,SAGF,IAAM,EAAuC,EAAE,CAC/C,IAAK,IAAI,EAAQ,EAAe,EAAQ,EAAU,OAAQ,IAAS,CACjE,IAAM,EAAS,EAAc,GAM7B,GALI,IAAW,IAAA,KAIf,EAAa,KAAK,EAAO,CACrB,EAAO,UACT,MAIJ,IAAM,EAAyB,EAAE,CAEjC,IAAK,IAAM,KAAS,EAElB,GADwB,EAAY,EAAO,EAAa,EAAa,CAEnE,MAIJ,GAAM,CAAE,YAAa,EAAa,GAAG,GAAG,CACxC,EAAS,EAAW,EAAY,GAAK,EACrC,GAAiB,EAAa,OAEhC,OAAO,EAGT,SAAS,EACP,EAEA,EAEA,EACS,CACT,GAAI,EAAa,SAAW,EAE1B,OADA,EAAY,KAAK,EAAK,CACf,GAGT,IAAI,EAAc,EAEd,EAA8BA,EAAAA,EAC9B,EAAS,GACb,IAAK,GAAM,CAAC,EAAgB,KAAW,EAAa,SAAS,CAAE,CAC7D,GAAM,CAAE,QAAO,SAAU,EAIzB,GAHA,EAAM,KAAK,EAAY,CACvB,EAAa,EAAO,EAAa,EAAO,EAAM,CAC9C,EAAO,OAAS,EACZ,EAAW,QAAS,CACtB,GAAI,EAAW,SAAW,GAAO,CAC/B,IAAK,IAAM,KAAW,EAAW,KAM/B,GALkB,EAChB,EACA,EACA,EAAa,MAAM,EAAiB,EAAE,CACvC,CAEC,MAAO,GAGX,OAAO,EAET,EAAc,EAAW,KAE3B,GAAI,CAAC,EAAW,QACd,MAIE,EAAW,OACb,EAAS,IAMb,OAHI,EAAW,SACb,EAAY,KAAK,EAAY,CAExB,EAGT,SAAS,EAAoB,EAA0C,CACrE,GAAM,CAAE,OAAM,YAAa,EACrB,EAAK,EAAK,GAAG,EAAS,CAC5B,OAAO,OAAO,OAAO,EAAI,CACvB,SAAU,EAAK,QAAU,GACzB,MAAO,EACP,MAAO,EAAE,CACV,CAAC,CAGJ,SAAS,EAAW,EAAoD,CAEtE,OACE,OAAO,GAAc,UACpB,OAAO,GAAc,YACpB,GACA,OAAO,YAAY"}