{"version":3,"file":"treeKill.cjs","names":["buildChildrenByParentMap","collectDescendantPidsFromMap","execFileSync","isErrnoException"],"sources":["../src/treeKill.ts"],"sourcesContent":["import { execFileSync } from 'node:child_process';\n\nimport { isErrnoException } from './errno.js';\nimport { buildChildrenByParentMap, collectDescendantPids as collectDescendantPidsFromMap } from './processTree.js';\n\nexport function treeKill(pid: number, signal: NodeJS.Signals = 'SIGTERM'): void {\n  if (!Number.isInteger(pid) || pid <= 0) {\n    throw new Error(`Invalid pid: ${pid}`);\n  }\n\n  if (process.platform === 'win32') {\n    killTreeOnWindows(pid);\n    return;\n  }\n\n  const descendants = collectDescendantPids(pid);\n  const targetPids = toChildrenFirstPids(pid, descendants);\n  for (const targetPid of targetPids) {\n    killIfNeeded(targetPid, signal);\n  }\n}\n\nfunction killIfNeeded(pid: number, signal: NodeJS.Signals): void {\n  try {\n    process.kill(pid, signal);\n  } catch (error) {\n    if (isNoSuchProcessError(error)) {\n      return;\n    }\n    throw error;\n  }\n}\n\nfunction killTreeOnWindows(pid: number): void {\n  try {\n    runCommand('taskkill', ['/PID', String(pid), '/T', '/F'], {\n      maxBuffer: 1024 * 1024,\n      timeout: 2000,\n    });\n  } catch (error) {\n    if (isNoSuchProcessError(error)) {\n      return;\n    }\n    throw error;\n  }\n}\n\nfunction collectDescendantPids(rootPid: number): number[] {\n  const { stdout } = runCommand(\n    'ps',\n    ['-Ao', 'pid=,ppid='],\n    // Keep command bounded so watch-mode kill loops cannot hang this path.\n    { maxBuffer: 1024 * 1024, timeout: 2000 }\n  );\n  const childrenByParent = buildChildrenByParentMap(stdout);\n  return collectDescendantPidsFromMap(rootPid, childrenByParent);\n}\n\nfunction toChildrenFirstPids(pid: number, descendants: readonly number[]): number[] {\n  const targetPids = descendants.toReversed();\n  targetPids.push(pid);\n  return targetPids;\n}\n\nfunction runCommand(\n  command: string,\n  args: readonly string[],\n  options?: { timeout: number; maxBuffer: number }\n): { stdout: string; stderr: string } {\n  try {\n    const stdout = execFileSync(command, [...args], {\n      encoding: 'utf8',\n      maxBuffer: options?.maxBuffer,\n      timeout: options?.timeout,\n      stdio: ['ignore', 'pipe', 'pipe'],\n    });\n    return { stdout, stderr: '' };\n  } catch (error) {\n    const stderr = extractStderr(error);\n    throw new CommandExecutionError(command, args, stderr, toExitCode(error));\n  }\n}\n\nfunction isNoSuchProcessError(error: unknown): boolean {\n  if (isErrnoException(error) && error.code === 'ESRCH') {\n    return true;\n  }\n\n  if (error instanceof CommandExecutionError) {\n    return /no such process|not found|not recognized|there is no running instance/i.test(error.stderr);\n  }\n  return false;\n}\n\nfunction toExitCode(error: unknown): number | string | undefined {\n  if (isErrnoException(error)) {\n    return error.code;\n  }\n  if (typeof error === 'object' && error !== null && 'status' in error) {\n    const status = (error as { status: unknown }).status;\n    if (typeof status === 'number') {\n      return status;\n    }\n  }\n  return undefined;\n}\n\nfunction extractStderr(error: unknown): string {\n  if (typeof error !== 'object' || error === null || !('stderr' in error)) {\n    return '';\n  }\n\n  const stderr = (error as Record<'stderr', unknown>).stderr;\n  if (typeof stderr === 'string') {\n    return stderr;\n  }\n  if (Buffer.isBuffer(stderr)) {\n    return stderr.toString('utf8');\n  }\n  return '';\n}\n\nclass CommandExecutionError extends Error {\n  readonly stderr: string;\n  readonly code: number | string | undefined;\n\n  constructor(command: string, args: readonly string[], stderr: string, code: number | string | undefined) {\n    super(`Command failed: ${command} ${args.join(' ')}`);\n    this.name = 'CommandExecutionError';\n    this.stderr = stderr;\n    this.code = code;\n  }\n}\n"],"mappings":"+GAKA,SAAgB,EAAS,EAAa,EAAyB,UAAiB,CAC9E,GAAI,CAAC,OAAO,UAAU,CAAG,GAAK,GAAO,EACnC,MAAU,MAAM,gBAAgB,GAAK,EAGvC,GAAI,QAAQ,WAAa,QAAS,CAChC,EAAkB,CAAG,EACrB,MACF,CAGA,IAAM,EAAa,EAAoB,EADnB,EAAsB,CACY,CAAC,EACvD,IAAK,IAAM,KAAa,EACtB,EAAa,EAAW,CAAM,CAElC,CAEA,SAAS,EAAa,EAAa,EAA8B,CAC/D,GAAI,CACF,QAAQ,KAAK,EAAK,CAAM,CAC1B,OAAS,EAAO,CACd,GAAI,EAAqB,CAAK,EAC5B,OAEF,MAAM,CACR,CACF,CAEA,SAAS,EAAkB,EAAmB,CAC5C,GAAI,CACF,EAAW,WAAY,CAAC,OAAQ,OAAO,CAAG,EAAG,KAAM,IAAI,EAAG,CACxD,UAAW,QACX,QAAS,GACX,CAAC,CACH,OAAS,EAAO,CACd,GAAI,EAAqB,CAAK,EAC5B,OAEF,MAAM,CACR,CACF,CAEA,SAAS,EAAsB,EAA2B,CACxD,GAAM,CAAE,UAAW,EACjB,KACA,CAAC,MAAO,YAAY,EAEpB,CAAE,UAAW,QAAa,QAAS,GAAK,CAC1C,EACM,EAAmBA,EAAAA,yBAAyB,CAAM,EACxD,OAAOC,EAAAA,sBAA6B,EAAS,CAAgB,CAC/D,CAEA,SAAS,EAAoB,EAAa,EAA0C,CAClF,IAAM,EAAa,EAAY,WAAW,EAE1C,OADA,EAAW,KAAK,CAAG,EACZ,CACT,CAEA,SAAS,EACP,EACA,EACA,EACoC,CACpC,GAAI,CAOF,MAAO,CAAE,QAAA,EANMC,EAAAA,aAAAA,CAAa,EAAS,CAAC,GAAG,CAAI,EAAG,CAC9C,SAAU,OACV,UAAW,GAAS,UACpB,QAAS,GAAS,QAClB,MAAO,CAAC,SAAU,OAAQ,MAAM,CAClC,CACc,EAAG,OAAQ,EAAG,CAC9B,OAAS,EAAO,CAEd,MAAM,IAAI,EAAsB,EAAS,EAD1B,EAAc,CACkB,EAAQ,EAAW,CAAK,CAAC,CAC1E,CACF,CAEA,SAAS,EAAqB,EAAyB,CAQrD,OAPIC,EAAAA,iBAAiB,CAAK,GAAK,EAAM,OAAS,QACrC,GAGL,aAAiB,GACZ,yEAAyE,KAAK,EAAM,MAAM,CAGrG,CAEA,SAAS,EAAW,EAA6C,CAC/D,GAAIA,EAAAA,iBAAiB,CAAK,EACxB,OAAO,EAAM,KAEf,GAAI,OAAO,GAAU,UAAY,GAAkB,WAAY,EAAO,CACpE,IAAM,EAAU,EAA8B,OAC9C,GAAI,OAAO,GAAW,SACpB,OAAO,CAEX,CAEF,CAEA,SAAS,EAAc,EAAwB,CAC7C,GAAI,OAAO,GAAU,WAAY,GAAkB,EAAE,WAAY,GAC/D,MAAO,GAGT,IAAM,EAAU,EAAoC,OAOpD,OANI,OAAO,GAAW,SACb,EAEL,OAAO,SAAS,CAAM,EACjB,EAAO,SAAS,MAAM,EAExB,EACT,CAEA,IAAM,EAAN,cAAoC,KAAM,CACxC,OACA,KAEA,YAAY,EAAiB,EAAyB,EAAgB,EAAmC,CACvG,MAAM,mBAAmB,EAAQ,GAAG,EAAK,KAAK,GAAG,GAAG,EACpD,KAAK,KAAO,wBACZ,KAAK,OAAS,EACd,KAAK,KAAO,CACd,CACF"}