{
  "version": 3,
  "sources": ["../../../../src/packages/deps.graph-sequencer/index.ts"],
  "sourcesContent": ["export type Graph<T> = Map<T, T[]>;\nexport type Groups<T> = T[][];\n\nexport type Options<T> = {\n  graph: Graph<T>;\n  groups: Groups<T>;\n};\n\nexport type Result<T> = {\n  safe: boolean;\n  chunks: Groups<T>;\n  cycles: Groups<T>;\n};\n\n/**\n * Performs topological sorting on a graph while supporting node restrictions.\n *\n * @param {Graph<T>}  graph - The graph represented as a Map where keys are nodes and values are their outgoing edges.\n * @param {T[]} includedNodes - An array of nodes that should be included in the sorting process. Other nodes will be ignored.\n * @returns {Result<T>} An object containing the result of the sorting, including safe, chunks, and cycles.\n */\nexport function graphSequencer<T>(\n  graph: Graph<T>,\n  includedNodes: T[] = [...graph.keys()]\n): Result<T> {\n  // Initialize reverseGraph with empty arrays for all nodes.\n  const reverseGraph = new Map<T, T[]>();\n\n  for (const key of graph.keys()) {\n    reverseGraph.set(key, []);\n  }\n\n  // Calculate outDegree and reverseGraph for the included nodes.\n  const nodes = new Set<T>(includedNodes);\n\n  const visited = new Set<T>();\n\n  const outDegree = new Map<T, number>();\n\n  for (const [from, edges] of graph.entries()) {\n    outDegree.set(from, 0);\n\n    for (const to of edges) {\n      if (nodes.has(from) && nodes.has(to)) {\n        changeOutDegree(from, 1);\n\n        reverseGraph.get(to)?.push(from);\n      }\n    }\n\n    if (!nodes.has(from)) {\n      visited.add(from);\n    }\n  }\n\n  const chunks: T[][] = [];\n\n  const cycles: T[][] = [];\n\n  let safe = true;\n\n  while (nodes.size) {\n    const chunk: T[] = [];\n\n    let minDegree = Number.MAX_SAFE_INTEGER;\n\n    for (const node of nodes) {\n      const degree = outDegree.get(node);\n\n      if (degree === 0) {\n        chunk.push(node);\n      }\n\n      if (typeof degree === 'number') {\n        minDegree = Math.min(minDegree, degree);\n      }\n    }\n\n    if (minDegree === 0) {\n      chunk.forEach(removeNode);\n\n      chunks.push(chunk);\n    } else {\n      const cycleNodes: T[] = [];\n\n      for (const node of nodes) {\n        const cycle = findCycle(node);\n\n        if (cycle.length) {\n          cycles.push(cycle);\n\n          cycle.forEach(removeNode);\n\n          cycleNodes.push(...cycle);\n\n          if (cycle.length > 1) {\n            safe = false;\n          }\n        }\n      }\n\n      chunks.push(cycleNodes);\n    }\n  }\n\n  return { safe, chunks, cycles };\n\n  // Function to update the outDegree of a node.\n  function changeOutDegree(node: T, value: number): void {\n    const degree = outDegree.get(node) ?? 0;\n\n    outDegree.set(node, degree + value);\n  }\n\n  // Function to remove a node from the graph.\n  function removeNode(node: T): void {\n    for (const from of reverseGraph.get(node) ?? []) {\n      changeOutDegree(from, -1);\n    }\n\n    visited.add(node);\n\n    nodes.delete(node);\n  }\n\n  function findCycle(startNode: T): T[] {\n    const queue: Array<[T, T[]]> = [[startNode, [startNode]]];\n\n    const cycleVisited = new Set<T>();\n\n    const cycles: T[][] = [];\n\n    while (queue.length) {\n      const q = queue.shift();\n\n      if (typeof q === 'undefined') {\n        return [];\n      }\n\n      const [id, cycle] = q;\n\n      for (const to of graph.get(id) ?? []) {\n        if (to === startNode) {\n          cycleVisited.add(to);\n\n          cycles.push([...cycle]);\n\n          continue;\n        }\n\n        if (visited.has(to) || cycleVisited.has(to)) {\n          continue;\n        }\n\n        cycleVisited.add(to);\n\n        queue.push([to, [...cycle, to]]);\n      }\n    }\n\n    if (!cycles.length) {\n      return [];\n    }\n\n    cycles.sort((a, b) => b.length - a.length);\n\n    return cycles[0] ?? [];\n  }\n}\n"],
  "mappings": "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",
  "names": ["cycles"]
}
