@saptools/cf-debugger 0.1.14 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/cloud-foundry/commands.ts","../src/regions.ts","../src/types.ts","../src/cloud-foundry/execute.ts","../src/cloud-foundry/ssh.ts","../src/debug-session/start.ts","../src/paths.ts","../src/network/ports.ts","../src/session-state/store.ts","../src/lock.ts","../src/debug-session/constants.ts","../src/debug-session/orphans.ts","../src/debug-session/processes.ts","../src/debug-session/sessions.ts"],"sourcesContent":["import process from \"node:process\";\n\nimport { Command } from \"commander\";\n\nimport { readCurrentCfTarget, requireCurrentCfRegion } from \"./cf.js\";\nimport {\n getSession,\n listSessions,\n startDebugger,\n stopAllDebuggers,\n stopDebugger,\n} from \"./debugger.js\";\nimport type { SessionKey, SessionStatus } from \"./types.js\";\nimport { CfDebuggerError } from \"./types.js\";\n\nfunction readRequiredOption(value: string | undefined, flag: string): string {\n if (value === undefined || value === \"\") {\n process.stderr.write(`Missing required option ${flag}\\n`);\n process.exit(1);\n }\n return value;\n}\n\nfunction parseOptionalPort(raw: string | undefined): number | undefined {\n if (raw === undefined) {\n return undefined;\n }\n const port = Number.parseInt(raw, 10);\n if (Number.isNaN(port) || port <= 0 || port > 65_535) {\n process.stderr.write(`Invalid port: ${raw}\\n`);\n process.exit(1);\n }\n return port;\n}\n\nfunction parseOptionalTimeout(raw: string | undefined): number | undefined {\n if (raw === undefined) {\n return undefined;\n }\n const seconds = Number.parseInt(raw, 10);\n if (Number.isNaN(seconds) || seconds <= 0) {\n process.stderr.write(`Invalid timeout: ${raw}\\n`);\n process.exit(1);\n }\n return seconds * 1000;\n}\n\ninterface StartCommandOptions {\n readonly region?: string;\n readonly org?: string;\n readonly space?: string;\n readonly app?: string;\n readonly port?: string;\n readonly timeout?: string;\n readonly verbose?: boolean;\n}\n\ninterface StopCommandOptions {\n readonly region?: string;\n readonly org?: string;\n readonly space?: string;\n readonly app?: string;\n readonly sessionId?: string;\n readonly all?: boolean;\n}\n\ninterface StatusCommandOptions {\n readonly region?: string;\n readonly org?: string;\n readonly space?: string;\n readonly app?: string;\n}\n\nfunction logStatus(verbose: boolean, status: SessionStatus, message?: string): void {\n if (verbose) {\n const suffix = message === undefined ? \"\" : `: ${message}`;\n process.stdout.write(`[cf-debugger] ${status}${suffix}\\n`);\n }\n}\n\nfunction mergeSelector<T extends { region?: string; org?: string; space?: string; app?: string }>(selector: string | undefined, opts: T): T {\n if (selector === undefined) {\n return opts;\n }\n const parts = selector.split(\"/\");\n if (parts.length === 4) {\n return { ...opts, region: opts.region ?? parts[0], org: opts.org ?? parts[1], space: opts.space ?? parts[2], app: opts.app ?? parts[3] };\n }\n if (parts.length === 1) {\n return { ...opts, app: opts.app ?? parts[0] };\n }\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Invalid app selector format. Expected <app> or <region>/<org>/<space>/<app>.\");\n}\n\nasync function handleStart(selector: string | undefined, rawOpts: StartCommandOptions): Promise<void> {\n const opts = mergeSelector(selector, rawOpts);\n const app = readRequiredOption(opts.app, \"--app or selector\");\n const key = await resolveSessionKey({ ...opts, app });\n const verbose = opts.verbose ?? false;\n\n const preferredPort = parseOptionalPort(opts.port);\n const tunnelReadyTimeoutMs = parseOptionalTimeout(opts.timeout);\n\n const abortController = new AbortController();\n const onStartupSignal = (exitCode: number) => (): void => {\n abortController.abort();\n process.stderr.write(`\\nAborting startup for ${app}...\\n`);\n setTimeout(() => {\n process.exit(exitCode);\n }, 5_000).unref();\n };\n const startupSigint = onStartupSignal(130);\n const startupSigterm = onStartupSignal(143);\n process.on(\"SIGINT\", startupSigint);\n process.on(\"SIGTERM\", startupSigterm);\n\n let handle;\n try {\n handle = await startDebugger({\n region: key.region,\n org: key.org,\n space: key.space,\n app,\n verbose,\n signal: abortController.signal,\n ...(preferredPort === undefined ? {} : { preferredPort }),\n ...(tunnelReadyTimeoutMs === undefined ? {} : { tunnelReadyTimeoutMs }),\n onStatus: (status, message) => {\n logStatus(verbose, status, message);\n },\n });\n } finally {\n process.off(\"SIGINT\", startupSigint);\n process.off(\"SIGTERM\", startupSigterm);\n }\n\n process.stdout.write(\n `Debugger ready for ${app} (${key.region}/${key.org}/${key.space}).\\n` +\n ` Local port: ${handle.session.localPort.toString()}\\n` +\n ` Remote port: ${handle.session.remotePort.toString()}\\n` +\n ` Session id: ${handle.session.sessionId}\\n` +\n ` PID: ${handle.session.pid.toString()}\\n` +\n `Press Ctrl+C to stop.\\n`,\n );\n\n let disposePromise: Promise<void> | undefined;\n const dispose = async (): Promise<void> => {\n disposePromise ??= (async (): Promise<void> => {\n process.stdout.write(`\\nStopping debugger for ${app}...\\n`);\n try {\n await handle.dispose();\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`Error during stop: ${msg}\\n`);\n }\n })();\n await disposePromise;\n };\n\n process.on(\"SIGINT\", () => {\n void dispose().then(() => {\n process.exit(130);\n });\n });\n process.on(\"SIGTERM\", () => {\n void dispose().then(() => {\n process.exit(143);\n });\n });\n\n const code = await handle.waitForExit();\n await dispose();\n process.exit(code ?? 0);\n}\n\nfunction hasText(value: string | undefined): boolean {\n return optionalText(value) !== undefined;\n}\n\nfunction optionalText(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed === undefined || trimmed.length === 0 ? undefined : trimmed;\n}\n\nfunction currentCfOptions(): { readonly command?: string } | undefined {\n const command = process.env[\"CF_DEBUGGER_CF_BIN\"];\n return command === undefined ? undefined : { command };\n}\n\nasync function resolveSessionKey(opts: StopCommandOptions): Promise<SessionKey> {\n const app = readRequiredOption(opts.app, \"--app or selector\");\n const region = optionalText(opts.region);\n const org = optionalText(opts.org);\n const space = optionalText(opts.space);\n if (region !== undefined && org !== undefined && space !== undefined) {\n return {\n region,\n org,\n space,\n app,\n };\n }\n\n const current = await readCurrentCfTarget(currentCfOptions()).catch((error: unknown) => {\n throw new CfDebuggerError(\n \"CF_TARGET_FAILED\",\n \"No current CF target found. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.\",\n error instanceof Error ? error.message : String(error),\n );\n });\n if (current === undefined) {\n throw new CfDebuggerError(\n \"CF_TARGET_FAILED\",\n \"No current CF target found. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.\",\n );\n }\n\n return {\n region: region ?? requireCurrentCfRegion(current),\n org: org ?? current.org,\n space: space ?? current.space,\n app,\n };\n}\n\nasync function resolveOptionalSessionKey(opts: StopCommandOptions): Promise<SessionKey | undefined> {\n if (!hasText(opts.app)) {\n if (hasText(opts.region) || hasText(opts.org) || hasText(opts.space)) {\n readRequiredOption(opts.app, \"--app\");\n }\n return undefined;\n }\n return await resolveSessionKey(opts);\n}\n\nasync function handleStop(selector: string | undefined, rawOpts: StopCommandOptions): Promise<void> {\n const opts = mergeSelector(selector, rawOpts);\n if (opts.all === true) {\n const count = await stopAllDebuggers();\n process.stdout.write(`Stopped ${count.toString()} session(s).\\n`);\n return;\n }\n const key = await resolveOptionalSessionKey(opts);\n const result = await stopDebugger({\n ...(opts.sessionId === undefined ? {} : { sessionId: opts.sessionId }),\n ...(key === undefined ? {} : { key }),\n });\n if (result === undefined) {\n process.stderr.write(\n \"No matching session found. Use `cf-debugger list` and pass --session-id or \" +\n \"region/org/space/app if the current CF target differs.\\n\",\n );\n process.exit(1);\n }\n if (result.stale) {\n process.stdout.write(\n `Removed stale session ${result.sessionId} (${result.app}, port ${result.localPort.toString()}).\\n`,\n );\n return;\n }\n process.stdout.write(\n `Stopped session ${result.sessionId} (${result.app}, port ${result.localPort.toString()}).\\n`,\n );\n}\n\nasync function handleList(): Promise<void> {\n const sessions = await listSessions();\n process.stdout.write(`${JSON.stringify(sessions, null, 2)}\\n`);\n}\n\nasync function handleStatus(selector: string | undefined, rawOpts: StatusCommandOptions): Promise<void> {\n const opts = mergeSelector(selector, rawOpts);\n const session = await getSession(await resolveSessionKey(opts));\n process.stdout.write(`${JSON.stringify(session ?? null, null, 2)}\\n`);\n}\n\nexport async function main(argv: readonly string[]): Promise<void> {\n const program = new Command();\n\n program\n .name(\"cf-debugger\")\n .description(\"Open an SSH debug tunnel to a SAP BTP Cloud Foundry app's Node.js inspector\");\n\n program\n .command(\"start\")\n .description(\"Open a debug tunnel for one app\")\n .argument(\"[selector]\", \"Optional app selector: `<app>` or `region/org/space/app`\")\n .option(\"--region <key>\", \"CF region key (default: current cf target)\")\n .option(\"--org <name>\", \"CF org name (default: current cf target)\")\n .option(\"--space <name>\", \"CF space name (default: current cf target)\")\n .option(\"--app <name>\", \"CF app name\")\n .option(\"--port <number>\", \"Preferred local port (auto-assigned if omitted)\")\n .option(\"--timeout <seconds>\", \"Tunnel-ready timeout in seconds (default: 180)\")\n .option(\"--verbose\", \"Print status transitions\", false)\n .action(async (selector: string | undefined, opts: StartCommandOptions): Promise<void> => {\n await handleStart(selector, opts);\n });\n\n program\n .command(\"stop\")\n .description(\"Stop one session (by key or id) or all sessions with --all\")\n .argument(\"[selector]\", \"Optional app selector: `<app>` or `region/org/space/app`\")\n .option(\"--region <key>\")\n .option(\"--org <name>\")\n .option(\"--space <name>\")\n .option(\"--app <name>\")\n .option(\"--session-id <id>\")\n .option(\"--all\", \"Stop every active session\", false)\n .action(async (selector: string | undefined, opts: StopCommandOptions): Promise<void> => {\n await handleStop(selector, opts);\n });\n\n program\n .command(\"list\")\n .description(\"Print every active debugger session as JSON\")\n .action(async (): Promise<void> => {\n await handleList();\n });\n\n program\n .command(\"status\")\n .description(\"Print one session by key as JSON (null if not active)\")\n .argument(\"[selector]\", \"Optional app selector: `<app>` or `region/org/space/app`\")\n .option(\"--region <key>\")\n .option(\"--org <name>\")\n .option(\"--space <name>\")\n .option(\"--app <name>\")\n .action(async (selector: string | undefined, opts: StatusCommandOptions): Promise<void> => {\n await handleStatus(selector, opts);\n });\n\n await program.parseAsync([...argv]);\n}\n\ntry {\n await main(process.argv);\n} catch (err: unknown) {\n if (err instanceof CfDebuggerError) {\n if (err.code === \"ABORTED\") {\n process.stderr.write(`Aborted: ${err.message}\\n`);\n process.exit(130);\n }\n process.stderr.write(`Error [${err.code}]: ${err.message}\\n`);\n } else {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`Error: ${msg}\\n`);\n }\n process.exit(1);\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nimport { listKnownRegionKeys, resolveApiEndpoint } from \"../regions.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nimport { type CfExecContext, runCf } from \"./execute.js\";\nimport { parseAppNames, parseNameTable } from \"./parsers.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst CF_AUTH_MAX_ATTEMPTS = 3;\nconst CURRENT_TARGET_TIMEOUT_MS = 30_000;\n\nexport interface CurrentCfTargetReadOptions {\n readonly command?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly timeoutMs?: number;\n}\n\nexport interface CurrentCfTarget {\n readonly apiEndpoint: string;\n readonly region?: string;\n readonly org: string;\n readonly space: string;\n}\n\nexport async function cfApi(apiEndpoint: string, context: CfExecContext): Promise<void> {\n await runCf([\"api\", apiEndpoint], context);\n}\n\nexport async function cfAuth(\n email: string,\n password: string,\n context: CfExecContext,\n): Promise<void> {\n let lastError: unknown;\n for (let attempt = 0; attempt < CF_AUTH_MAX_ATTEMPTS; attempt++) {\n try {\n await runCf([\"auth\", email, password], context);\n return;\n } catch (err: unknown) {\n lastError = err;\n if (attempt < CF_AUTH_MAX_ATTEMPTS - 1) {\n await new Promise<void>((resolve) => {\n setTimeout(resolve, 1000 * (attempt + 1));\n });\n }\n }\n }\n if (lastError instanceof Error) {\n throw lastError;\n }\n throw new CfDebuggerError(\"CF_AUTH_FAILED\", `cf auth failed: ${String(lastError)}`);\n}\n\nexport async function cfLogin(\n apiEndpoint: string,\n email: string,\n password: string,\n context: CfExecContext,\n): Promise<void> {\n try {\n await cfApi(apiEndpoint, context);\n await cfAuth(email, password, context);\n } catch (err: unknown) {\n if (err instanceof CfDebuggerError) {\n throw new CfDebuggerError(\"CF_LOGIN_FAILED\", err.message, err.stderr);\n }\n throw err;\n }\n}\n\nexport async function cfTarget(\n org: string,\n space: string,\n context: CfExecContext,\n): Promise<void> {\n try {\n await runCf([\"target\", \"-o\", org, \"-s\", space], context);\n } catch (err: unknown) {\n if (err instanceof CfDebuggerError) {\n throw new CfDebuggerError(\"CF_TARGET_FAILED\", err.message, err.stderr);\n }\n throw err;\n }\n}\n\nexport async function cfAppExists(appName: string, context: CfExecContext): Promise<boolean> {\n try {\n await runCf([\"app\", appName], context);\n return true;\n } catch (err: unknown) {\n const stderr = (err as CfDebuggerError).stderr ?? \"\";\n if (stderr.toLowerCase().includes(\"not found\")) {\n return false;\n }\n throw err;\n }\n}\n\nexport async function cfSshEnabled(appName: string, context: CfExecContext): Promise<boolean> {\n try {\n const stdout = await runCf([\"ssh-enabled\", appName], context);\n return stdout.toLowerCase().includes(\"ssh support is enabled\");\n } catch {\n return false;\n }\n}\n\nexport async function cfEnableSsh(appName: string, context: CfExecContext): Promise<void> {\n try {\n await runCf([\"enable-ssh\", appName], context);\n } catch (err: unknown) {\n if (err instanceof CfDebuggerError) {\n throw new CfDebuggerError(\"SSH_NOT_ENABLED\", err.message, err.stderr);\n }\n throw err;\n }\n}\n\nexport async function cfRestartApp(appName: string, context: CfExecContext): Promise<void> {\n await runCf([\"restart\", appName], context);\n}\n\nexport async function cfApps(context: CfExecContext): Promise<readonly string[]> {\n const stdout = await runCf([\"apps\"], context);\n return parseAppNames(stdout);\n}\n\nexport async function cfOrgs(context: CfExecContext): Promise<readonly string[]> {\n const stdout = await runCf([\"orgs\"], context);\n return parseNameTable(stdout);\n}\n\nexport async function cfSpaces(context: CfExecContext): Promise<readonly string[]> {\n const stdout = await runCf([\"spaces\"], context);\n return parseNameTable(stdout);\n}\n\nexport async function readCurrentCfTarget(\n options: CurrentCfTargetReadOptions = {},\n): Promise<CurrentCfTarget | undefined> {\n try {\n const { stdout } = await execFileAsync(options.command ?? process.env[\"CF_DEBUGGER_CF_BIN\"] ?? \"cf\", [\"target\"], {\n env: options.env ?? process.env,\n maxBuffer: 16 * 1024 * 1024,\n timeout: options.timeoutMs ?? CURRENT_TARGET_TIMEOUT_MS,\n });\n return parseCurrentCfTarget(stdout);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n throw new CfDebuggerError(\"CF_TARGET_FAILED\", `cf target failed: ${message}`);\n }\n}\n\nexport function parseCurrentCfTarget(stdout: string): CurrentCfTarget | undefined {\n const fields = parseTargetFields(stdout);\n const apiEndpoint = fields.get(\"api endpoint\");\n const org = fields.get(\"org\");\n const space = fields.get(\"space\");\n if (!isPresent(apiEndpoint) || !isPresent(org) || !isPresent(space)) {\n return undefined;\n }\n\n const region = regionKeyForApiEndpoint(apiEndpoint);\n return {\n apiEndpoint,\n ...(region === undefined ? {} : { region }),\n org,\n space,\n };\n}\n\nexport function requireCurrentCfRegion(\n target: Pick<CurrentCfTarget, \"apiEndpoint\" | \"region\">,\n instruction = \"Pass --region explicitly.\",\n): string {\n if (target.region !== undefined) {\n return target.region;\n }\n throw new CfDebuggerError(\n \"CF_TARGET_FAILED\",\n `Current CF API endpoint \"${target.apiEndpoint}\" does not match a known SAP region. ${instruction}`,\n );\n}\n\nfunction parseTargetFields(stdout: string): Map<string, string> {\n return new Map(\n stdout\n .split(\"\\n\")\n .map((line): readonly [string, string] | undefined => {\n const separator = line.indexOf(\":\");\n if (separator < 0) {\n return undefined;\n }\n return [\n line.slice(0, separator).trim().toLowerCase(),\n line.slice(separator + 1).trim(),\n ];\n })\n .filter((field): field is readonly [string, string] => field !== undefined),\n );\n}\n\nfunction regionKeyForApiEndpoint(apiEndpoint: string): string | undefined {\n const normalized = normalizeApiEndpoint(apiEndpoint);\n const known = listKnownRegionKeys().find((key) => normalizeApiEndpoint(resolveApiEndpoint(key)) === normalized);\n if (known !== undefined) {\n return known;\n }\n return regionKeyFromSapApiEndpoint(normalized);\n}\n\nfunction normalizeApiEndpoint(apiEndpoint: string): string {\n return apiEndpoint.trim().replace(/\\/+$/, \"\").toLowerCase();\n}\n\nfunction regionKeyFromSapApiEndpoint(apiEndpoint: string): string | undefined {\n const match = /^https:\\/\\/api\\.cf\\.([a-z]{2}\\d{2}(?:-\\d{3})?)\\.(?:hana\\.ondemand\\.com|platform\\.sapcloud\\.cn)$/.exec(apiEndpoint);\n return match?.[1];\n}\n\nfunction isPresent(value: string | undefined): value is string {\n return value !== undefined && value.length > 0;\n}\n","export interface RegionInfo {\n readonly key: string;\n readonly apiEndpoint: string;\n}\n\nconst REGION_API_ENDPOINTS: Readonly<Record<string, string>> = {\n ae01: \"https://api.cf.ae01.hana.ondemand.com\",\n ap01: \"https://api.cf.ap01.hana.ondemand.com\",\n ap10: \"https://api.cf.ap10.hana.ondemand.com\",\n ap11: \"https://api.cf.ap11.hana.ondemand.com\",\n ap12: \"https://api.cf.ap12.hana.ondemand.com\",\n ap20: \"https://api.cf.ap20.hana.ondemand.com\",\n ap21: \"https://api.cf.ap21.hana.ondemand.com\",\n ap30: \"https://api.cf.ap30.hana.ondemand.com\",\n br10: \"https://api.cf.br10.hana.ondemand.com\",\n br20: \"https://api.cf.br20.hana.ondemand.com\",\n br30: \"https://api.cf.br30.hana.ondemand.com\",\n ca10: \"https://api.cf.ca10.hana.ondemand.com\",\n ca20: \"https://api.cf.ca20.hana.ondemand.com\",\n ch20: \"https://api.cf.ch20.hana.ondemand.com\",\n cn20: \"https://api.cf.cn20.platform.sapcloud.cn\",\n cn40: \"https://api.cf.cn40.platform.sapcloud.cn\",\n eu01: \"https://api.cf.eu01.hana.ondemand.com\",\n eu02: \"https://api.cf.eu02.hana.ondemand.com\",\n eu10: \"https://api.cf.eu10.hana.ondemand.com\",\n \"eu10-002\": \"https://api.cf.eu10-002.hana.ondemand.com\",\n \"eu10-003\": \"https://api.cf.eu10-003.hana.ondemand.com\",\n \"eu10-004\": \"https://api.cf.eu10-004.hana.ondemand.com\",\n \"eu10-005\": \"https://api.cf.eu10-005.hana.ondemand.com\",\n eu11: \"https://api.cf.eu11.hana.ondemand.com\",\n eu13: \"https://api.cf.eu13.hana.ondemand.com\",\n eu20: \"https://api.cf.eu20.hana.ondemand.com\",\n \"eu20-001\": \"https://api.cf.eu20-001.hana.ondemand.com\",\n \"eu20-002\": \"https://api.cf.eu20-002.hana.ondemand.com\",\n eu22: \"https://api.cf.eu22.hana.ondemand.com\",\n eu30: \"https://api.cf.eu30.hana.ondemand.com\",\n il30: \"https://api.cf.il30.hana.ondemand.com\",\n in30: \"https://api.cf.in30.hana.ondemand.com\",\n jp01: \"https://api.cf.jp01.hana.ondemand.com\",\n jp10: \"https://api.cf.jp10.hana.ondemand.com\",\n jp20: \"https://api.cf.jp20.hana.ondemand.com\",\n jp30: \"https://api.cf.jp30.hana.ondemand.com\",\n jp31: \"https://api.cf.jp31.hana.ondemand.com\",\n sa30: \"https://api.cf.sa30.hana.ondemand.com\",\n sa31: \"https://api.cf.sa31.hana.ondemand.com\",\n uk20: \"https://api.cf.uk20.hana.ondemand.com\",\n us01: \"https://api.cf.us01.hana.ondemand.com\",\n us02: \"https://api.cf.us02.hana.ondemand.com\",\n us10: \"https://api.cf.us10.hana.ondemand.com\",\n \"us10-001\": \"https://api.cf.us10-001.hana.ondemand.com\",\n \"us10-002\": \"https://api.cf.us10-002.hana.ondemand.com\",\n us11: \"https://api.cf.us11.hana.ondemand.com\",\n us20: \"https://api.cf.us20.hana.ondemand.com\",\n us21: \"https://api.cf.us21.hana.ondemand.com\",\n us30: \"https://api.cf.us30.hana.ondemand.com\",\n};\n\nexport function resolveApiEndpoint(regionKey: string, override?: string): string {\n if (override !== undefined && override !== \"\") {\n return override;\n }\n const endpoint = REGION_API_ENDPOINTS[regionKey];\n if (endpoint === undefined) {\n throw new Error(\n `Unknown region key: ${regionKey}. Pass \\`apiEndpoint\\` explicitly to override.`,\n );\n }\n return endpoint;\n}\n\nexport function listKnownRegionKeys(): readonly string[] {\n return Object.keys(REGION_API_ENDPOINTS);\n}\n","export interface SessionKey {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n}\n\nexport type SessionStatus =\n | \"starting\"\n | \"logging-in\"\n | \"targeting\"\n | \"ssh-enabling\"\n | \"ssh-restarting\"\n | \"signaling\"\n | \"tunneling\"\n | \"ready\"\n | \"stopping\"\n | \"stopped\"\n | \"error\";\n\nexport interface ActiveSession extends SessionKey {\n readonly sessionId: string;\n readonly pid: number;\n readonly hostname: string;\n readonly localPort: number;\n readonly remotePort: number;\n readonly apiEndpoint: string;\n readonly cfHomeDir: string;\n readonly startedAt: string;\n readonly status: SessionStatus;\n readonly message?: string;\n}\n\nexport interface StartDebuggerOptions extends SessionKey {\n readonly email?: string;\n readonly password?: string;\n readonly apiEndpoint?: string;\n readonly preferredPort?: number;\n readonly tunnelReadyTimeoutMs?: number;\n readonly verbose?: boolean;\n readonly onStatus?: (status: SessionStatus, message?: string) => void;\n readonly signal?: AbortSignal;\n}\n\nexport interface DebuggerHandle {\n readonly session: ActiveSession;\n dispose(): Promise<void>;\n waitForExit(): Promise<number | null>;\n}\n\nexport interface StateFile {\n readonly version: \"1\";\n readonly sessions: readonly ActiveSession[];\n}\n\nexport class CfDebuggerError extends Error {\n public readonly code: string;\n public readonly stderr?: string;\n\n public constructor(code: string, message: string, stderr?: string) {\n super(message);\n this.name = \"CfDebuggerError\";\n this.code = code;\n if (stderr !== undefined) {\n this.stderr = stderr;\n }\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nimport { CfDebuggerError } from \"../types.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst MAX_BUFFER = 16 * 1024 * 1024;\nexport const DEFAULT_CF_COMMAND_TIMEOUT_MS = 180_000;\nconst REDACTED_ARG = \"<redacted>\";\n\nexport interface CfExecContext {\n readonly cfHome: string;\n readonly command?: string;\n}\n\nexport function buildEnv(cfHome: string): NodeJS.ProcessEnv {\n return { ...process.env, CF_HOME: cfHome };\n}\n\nexport function resolveBin(context: CfExecContext): string {\n return context.command ?? process.env[\"CF_DEBUGGER_CF_BIN\"] ?? \"cf\";\n}\n\nfunction sensitiveArgs(args: readonly string[]): readonly string[] {\n if (args[0] !== \"auth\") {\n return [];\n }\n return args.slice(1).filter((arg) => arg.length > 0);\n}\n\nfunction redactText(text: string, values: readonly string[]): string {\n return values.reduce((current, value) => current.split(value).join(REDACTED_ARG), text);\n}\n\nfunction formatArgsForError(args: readonly string[]): string {\n if (args[0] !== \"auth\") {\n return args.join(\" \");\n }\n return args.map((arg, index) => (index === 0 ? arg : REDACTED_ARG)).join(\" \");\n}\n\nexport async function runCf(\n args: readonly string[],\n context: CfExecContext,\n timeoutMs: number = DEFAULT_CF_COMMAND_TIMEOUT_MS,\n): Promise<string> {\n try {\n const { stdout } = await execFileAsync(resolveBin(context), [...args], {\n env: buildEnv(context.cfHome),\n maxBuffer: MAX_BUFFER,\n timeout: timeoutMs,\n });\n return stdout;\n } catch (err: unknown) {\n const e = err as NodeJS.ErrnoException & { stderr?: string; stdout?: string };\n const redactionValues = sensitiveArgs(args);\n const stderr = redactText(e.stderr?.trim() ?? \"\", redactionValues);\n const fallbackMessage = redactText(e.message, redactionValues);\n throw new CfDebuggerError(\n \"CF_CLI_FAILED\",\n `cf ${formatArgsForError(args)} failed: ${stderr.length > 0 ? stderr : fallbackMessage}`,\n stderr,\n );\n }\n}\n","import { spawn } from \"node:child_process\";\n\nimport {\n buildEnv,\n DEFAULT_CF_COMMAND_TIMEOUT_MS,\n resolveBin,\n type CfExecContext,\n} from \"./execute.js\";\n\nexport interface CfSshSignalResult {\n readonly exitCode: number | null;\n readonly stderr: string;\n readonly signal?: NodeJS.Signals;\n readonly timedOutAfterMs?: number;\n}\n\nexport async function cfSshOneShot(\n appName: string,\n command: string,\n context: CfExecContext,\n timeoutMs: number = DEFAULT_CF_COMMAND_TIMEOUT_MS,\n): Promise<CfSshSignalResult> {\n return await new Promise<CfSshSignalResult>((resolve) => {\n const child = spawn(resolveBin(context), [\"ssh\", appName, \"-c\", command], {\n env: buildEnv(context.cfHome),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n let stderrBuf = \"\";\n let settled = false;\n\n const timeout = setTimeout(() => {\n if (settled) {\n return;\n }\n settled = true;\n try {\n child.kill();\n } catch {\n // already gone\n }\n resolve({ exitCode: null, stderr: stderrBuf, timedOutAfterMs: timeoutMs });\n }, timeoutMs);\n\n child.stderr.on(\"data\", (data: Buffer | string) => {\n stderrBuf += data.toString();\n });\n\n child.on(\"close\", (code, signal) => {\n if (settled) {\n return;\n }\n settled = true;\n clearTimeout(timeout);\n resolve(\n signal === null\n ? { exitCode: code, stderr: stderrBuf }\n : { exitCode: code, stderr: stderrBuf, signal },\n );\n });\n\n child.on(\"error\", (err: Error) => {\n if (settled) {\n return;\n }\n settled = true;\n clearTimeout(timeout);\n resolve({ exitCode: null, stderr: err.message });\n });\n });\n}\n\nexport function isSshDisabledError(stderr: string): boolean {\n const lower = stderr.toLowerCase();\n return lower.includes(\"not authorized\") || lower.includes(\"ssh support is disabled\");\n}\n\nexport function spawnSshTunnel(\n appName: string,\n localPort: number,\n remotePort: number,\n context: CfExecContext,\n): ReturnType<typeof spawn> {\n const tunnelArg = `${localPort.toString()}:localhost:${remotePort.toString()}`;\n const isWindows = process.platform === \"win32\";\n return spawn(resolveBin(context), [\"ssh\", appName, \"-N\", \"-L\", tunnelArg], {\n env: buildEnv(context.cfHome),\n shell: isWindows,\n detached: !isWindows,\n });\n}\n","import type { ChildProcess } from \"node:child_process\";\nimport { mkdir, rm } from \"node:fs/promises\";\nimport process from \"node:process\";\n\nimport type { CfExecContext } from \"../cf.js\";\nimport {\n cfEnableSsh,\n cfLogin,\n cfRestartApp,\n cfSshEnabled,\n cfSshOneShot,\n cfTarget,\n isSshDisabledError,\n spawnSshTunnel,\n} from \"../cf.js\";\nimport { sessionCfHomeDir } from \"../paths.js\";\nimport { findListeningProcessId, isPortFree, killProcessOnPort, probeTunnelReady } from \"../port.js\";\nimport { resolveApiEndpoint } from \"../regions.js\";\nimport {\n registerNewSession,\n removeSession,\n sessionKeyString,\n updateSessionPid,\n updateSessionStatus,\n} from \"../state.js\";\nimport type { ActiveSession, DebuggerHandle, SessionStatus, StartDebuggerOptions } from \"../types.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nimport {\n DEFAULT_TUNNEL_READY_TIMEOUT_MS,\n PORT_CLEANUP_DELAY_MS,\n PORT_RECLAIM_DELAY_MS,\n POST_USR1_DELAY_MS,\n} from \"./constants.js\";\nimport { pruneAndCleanupOrphans } from \"./orphans.js\";\nimport { killProcessGroupOrProc } from \"./processes.js\";\n\ntype StatusEmitter = (status: SessionStatus, message?: string) => void;\n\ninterface TunnelResult {\n readonly child: ChildProcess;\n readonly activePid: number;\n}\n\ntype SignalResult = Awaited<ReturnType<typeof cfSshOneShot>>;\n\nfunction signalFailureDetail(result: SignalResult): string {\n if (result.timedOutAfterMs !== undefined) {\n return `timed out after ${(result.timedOutAfterMs / 1000).toString()}s`;\n }\n const stderr = result.stderr.trim();\n if (stderr.length > 0) {\n return stderr;\n }\n if (result.signal !== undefined) {\n return `terminated by signal ${result.signal}`;\n }\n return `exit code ${String(result.exitCode)}`;\n}\n\nfunction checkAbort(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\");\n }\n}\n\nfunction requireCredentials(options: StartDebuggerOptions): {\n readonly email: string;\n readonly password: string;\n} {\n const email = options.email ?? process.env[\"SAP_EMAIL\"];\n const password = options.password ?? process.env[\"SAP_PASSWORD\"];\n if (email === undefined || email === \"\") {\n throw new CfDebuggerError(\n \"MISSING_CREDENTIALS\",\n \"SAP email is required. Pass `email` or set SAP_EMAIL env var.\",\n );\n }\n if (password === undefined || password === \"\") {\n throw new CfDebuggerError(\n \"MISSING_CREDENTIALS\",\n \"SAP password is required. Pass `password` or set SAP_PASSWORD env var.\",\n );\n }\n return { email, password };\n}\n\nasync function registerSession(\n options: StartDebuggerOptions,\n apiEndpoint: string,\n): Promise<ActiveSession> {\n const registration = await registerNewSession({\n region: options.region,\n org: options.org,\n space: options.space,\n app: options.app,\n apiEndpoint,\n ...(options.preferredPort === undefined ? {} : { preferredPort: options.preferredPort }),\n portProbe: isPortFree,\n cfHomeForSession: sessionCfHomeDir,\n });\n\n if (registration.existing) {\n throw new CfDebuggerError(\n \"SESSION_ALREADY_RUNNING\",\n `A debugger session is already running for ${sessionKeyString(options)} ` +\n `on port ${registration.existing.localPort.toString()} ` +\n `(pid ${registration.existing.pid.toString()}, sessionId ${registration.existing.sessionId}). ` +\n `Stop it first with \\`cf-debugger stop\\`.`,\n );\n }\n return registration.session;\n}\n\nasync function loginAndTarget(\n options: StartDebuggerOptions,\n apiEndpoint: string,\n email: string,\n password: string,\n context: CfExecContext,\n sessionId: string,\n emit: StatusEmitter,\n): Promise<void> {\n emit(\"logging-in\");\n await updateSessionStatus(sessionId, \"logging-in\");\n await cfLogin(apiEndpoint, email, password, context);\n checkAbort(options.signal);\n\n emit(\"targeting\");\n await updateSessionStatus(sessionId, \"targeting\");\n await cfTarget(options.org, options.space, context);\n checkAbort(options.signal);\n}\n\nasync function signalRemoteNode(\n options: StartDebuggerOptions,\n context: CfExecContext,\n sessionId: string,\n emit: StatusEmitter,\n): Promise<void> {\n emit(\"signaling\");\n await updateSessionStatus(sessionId, \"signaling\");\n const signalResult = await cfSshOneShot(options.app, `kill -s USR1 $(pidof node)`, context);\n\n if (!isSshDisabledError(signalResult.stderr)) {\n if (signalResult.exitCode === 0) {\n return;\n }\n throw new CfDebuggerError(\n \"USR1_SIGNAL_FAILED\",\n `Failed to send SIGUSR1 to the Node.js process on ${options.app}: ${signalFailureDetail(signalResult)}`,\n signalResult.stderr,\n );\n }\n\n const alreadyEnabled = await cfSshEnabled(options.app, context);\n if (!alreadyEnabled) {\n emit(\"ssh-enabling\", \"Enabling SSH on the app\");\n await updateSessionStatus(sessionId, \"ssh-enabling\");\n await cfEnableSsh(options.app, context);\n }\n emit(\"ssh-restarting\", \"Restarting app so SSH becomes active\");\n await updateSessionStatus(sessionId, \"ssh-restarting\");\n await cfRestartApp(options.app, context);\n checkAbort(options.signal);\n\n await retryRemoteSignal(options, context, sessionId, emit);\n}\n\nasync function retryRemoteSignal(\n options: StartDebuggerOptions,\n context: CfExecContext,\n sessionId: string,\n emit: StatusEmitter,\n): Promise<void> {\n emit(\"signaling\");\n await updateSessionStatus(sessionId, \"signaling\");\n const retrySignalResult = await cfSshOneShot(\n options.app,\n `kill -s USR1 $(pidof node)`,\n context,\n );\n if (retrySignalResult.exitCode === 0) {\n return;\n }\n throw new CfDebuggerError(\n \"USR1_SIGNAL_FAILED\",\n `Failed to send SIGUSR1 to the Node.js process on ${options.app} after enabling SSH: ${\n signalFailureDetail(retrySignalResult)\n }`,\n retrySignalResult.stderr,\n );\n}\n\nasync function waitAfterSignal(signal: AbortSignal | undefined): Promise<void> {\n await new Promise<void>((resolve) => {\n setTimeout(resolve, POST_USR1_DELAY_MS);\n });\n checkAbort(signal);\n}\n\nasync function ensurePortAvailable(localPort: number): Promise<void> {\n if (await isPortFree(localPort)) {\n return;\n }\n await killProcessOnPort(localPort);\n await new Promise<void>((resolve) => {\n setTimeout(resolve, PORT_RECLAIM_DELAY_MS);\n });\n if (!(await isPortFree(localPort))) {\n throw new CfDebuggerError(\n \"PORT_UNAVAILABLE\",\n `Local port ${localPort.toString()} is in use and could not be reclaimed for the tunnel.`,\n );\n }\n}\n\nasync function openReadyTunnel(\n options: StartDebuggerOptions,\n session: ActiveSession,\n context: CfExecContext,\n tunnelReadyTimeoutMs: number,\n onChild: (child: ChildProcess) => void,\n): Promise<TunnelResult> {\n await ensurePortAvailable(session.localPort);\n const child = spawnSshTunnel(options.app, session.localPort, session.remotePort, context);\n onChild(child);\n if (child.pid !== undefined) {\n await updateSessionPid(session.sessionId, child.pid);\n }\n\n const ready = await probeTunnelReady(session.localPort, tunnelReadyTimeoutMs);\n checkAbort(options.signal);\n if (!ready) {\n throw new CfDebuggerError(\n \"TUNNEL_NOT_READY\",\n `SSH tunnel on port ${session.localPort.toString()} did not become ready within ` +\n `${Math.round(tunnelReadyTimeoutMs / 1000).toString()}s.`,\n );\n }\n\n const listeningPid = await findListeningProcessId(session.localPort);\n const activePid = listeningPid ?? child.pid ?? session.pid;\n if (activePid !== session.pid) {\n await updateSessionPid(session.sessionId, activePid);\n }\n return { child, activePid };\n}\n\nfunction attachTunnelEvents(\n child: ChildProcess,\n markClosed: () => void,\n resolveExit: (code: number | null) => void,\n emit: StatusEmitter,\n): void {\n child.on(\"close\", (code) => {\n markClosed();\n resolveExit(code);\n });\n\n child.on(\"error\", (err: Error) => {\n emit(\"error\", err.message);\n });\n}\n\nfunction createHandle(\n session: ActiveSession,\n emit: StatusEmitter,\n finalize: () => Promise<void>,\n exitPromise: Promise<number | null>,\n): DebuggerHandle {\n let disposePromise: Promise<void> | undefined;\n return {\n session,\n dispose: async (): Promise<void> => {\n disposePromise ??= (async (): Promise<void> => {\n emit(\"stopping\");\n await updateSessionStatus(session.sessionId, \"stopping\");\n await finalize();\n })();\n await disposePromise;\n },\n waitForExit: async (): Promise<number | null> => {\n return await exitPromise;\n },\n };\n}\n\nexport async function startDebugger(options: StartDebuggerOptions): Promise<DebuggerHandle> {\n const { email, password } = requireCredentials(options);\n const apiEndpoint = resolveApiEndpoint(options.region, options.apiEndpoint);\n const tunnelReadyTimeoutMs = options.tunnelReadyTimeoutMs ?? DEFAULT_TUNNEL_READY_TIMEOUT_MS;\n const emit = (status: SessionStatus, message?: string): void => {\n options.onStatus?.(status, message);\n };\n\n checkAbort(options.signal);\n await pruneAndCleanupOrphans();\n\n const session = await registerSession(options, apiEndpoint);\n const context: CfExecContext = { cfHome: session.cfHomeDir };\n let child: ChildProcess | undefined;\n let tunnelClosed = false;\n let exitResolve: (code: number | null) => void = (_code) => {\n throw new Error(\"Exit resolver was used before initialization\");\n };\n const exitPromise = new Promise<number | null>((resolve) => {\n exitResolve = resolve;\n });\n\n const finalize = async (): Promise<void> => {\n if (!tunnelClosed) {\n tunnelClosed = true;\n if (child) {\n await killProcessGroupOrProc(child);\n }\n setTimeout(() => {\n void killProcessOnPort(session.localPort);\n }, PORT_CLEANUP_DELAY_MS);\n }\n await removeSession(session.sessionId);\n await cleanupFilesystem(session.cfHomeDir);\n emit(\"stopped\");\n };\n\n try {\n await mkdir(session.cfHomeDir, { recursive: true });\n await loginAndTarget(options, apiEndpoint, email, password, context, session.sessionId, emit);\n await killProcessOnPort(session.localPort);\n await new Promise<void>((resolve) => {\n setTimeout(resolve, 200);\n });\n await signalRemoteNode(options, context, session.sessionId, emit);\n await waitAfterSignal(options.signal);\n\n emit(\"tunneling\");\n await updateSessionStatus(session.sessionId, \"tunneling\");\n const tunnel = await openReadyTunnel(\n options,\n session,\n context,\n tunnelReadyTimeoutMs,\n (tunnelChild) => {\n child = tunnelChild;\n attachTunnelEvents(tunnelChild, () => {\n tunnelClosed = true;\n }, exitResolve, emit);\n },\n );\n child = tunnel.child;\n\n emit(\"ready\");\n const readySession = await updateSessionStatus(session.sessionId, \"ready\");\n const activeSession = readySession ?? { ...session, pid: tunnel.activePid, status: \"ready\" };\n return createHandle(activeSession, emit, finalize, exitPromise);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n emit(\"error\", message);\n await finalize();\n throw err;\n }\n}\n\nasync function cleanupFilesystem(cfHomeDir: string): Promise<void> {\n try {\n await rm(cfHomeDir, { recursive: true, force: true });\n } catch {\n // best-effort\n }\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport const SAPTOOLS_DIR_NAME = \".saptools\";\nexport const CF_DEBUGGER_STATE_FILENAME = \"cf-debugger-state.json\";\nexport const CF_DEBUGGER_LOCK_FILENAME = \"cf-debugger-state.lock\";\nexport const CF_DEBUGGER_HOMES_DIRNAME = \"cf-debugger-homes\";\n\nexport function saptoolsDir(): string {\n return join(homedir(), SAPTOOLS_DIR_NAME);\n}\n\nexport function stateFilePath(): string {\n return join(saptoolsDir(), CF_DEBUGGER_STATE_FILENAME);\n}\n\nexport function stateLockPath(): string {\n return join(saptoolsDir(), CF_DEBUGGER_LOCK_FILENAME);\n}\n\nexport function sessionCfHomeDir(sessionId: string): string {\n return join(saptoolsDir(), CF_DEBUGGER_HOMES_DIRNAME, sessionId);\n}\n","import { execFile } from \"node:child_process\";\nimport { readdir, readFile, readlink } from \"node:fs/promises\";\nimport { createConnection, createServer } from \"node:net\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nasync function findListeningPidsWithNetstat(port: number): Promise<readonly number[]> {\n try {\n const { stdout } = await execFileAsync(\"netstat\", [\"-ano\"]);\n const pids = new Set<number>();\n for (const line of stdout.split(\"\\n\")) {\n if (!line.includes(`:${port.toString()}`) || !line.includes(\"LISTENING\")) {\n continue;\n }\n const parts = line.trim().split(/\\s+/);\n const last = parts[parts.length - 1];\n if (last === undefined) {\n continue;\n }\n const pid = Number.parseInt(last, 10);\n if (!Number.isNaN(pid)) {\n pids.add(pid);\n }\n }\n return [...pids];\n } catch {\n return [];\n }\n}\n\nasync function findListeningPidsWithLsof(port: number): Promise<readonly number[]> {\n try {\n const { stdout } = await execFileAsync(\"lsof\", [\"-nP\", \"-t\", \"-i\", `tcp:${port.toString()}`, \"-sTCP:LISTEN\"]);\n return stdout\n .trim()\n .split(\"\\n\")\n .filter((line) => line.length > 0)\n .map((line) => Number.parseInt(line, 10))\n .filter((pid) => !Number.isNaN(pid));\n } catch {\n return [];\n }\n}\n\nasync function findListeningPidsWithProc(port: number): Promise<readonly number[]> {\n const inodes = await findListeningSocketInodesWithProc(port);\n if (inodes.size === 0) {\n return [];\n }\n\n try {\n const entries = await readdir(\"/proc\", { withFileTypes: true });\n const pids = new Set<number>();\n for (const entry of entries) {\n if (!entry.isDirectory() || !/^\\d+$/.test(entry.name)) {\n continue;\n }\n if (await processHasSocketInode(entry.name, inodes)) {\n pids.add(Number.parseInt(entry.name, 10));\n }\n }\n return [...pids];\n } catch {\n return [];\n }\n}\n\nasync function findListeningSocketInodesWithProc(port: number): Promise<ReadonlySet<string>> {\n const inodes = new Set<string>();\n await collectListeningSocketInodes(\"/proc/net/tcp\", port, inodes);\n await collectListeningSocketInodes(\"/proc/net/tcp6\", port, inodes);\n return inodes;\n}\n\nasync function collectListeningSocketInodes(\n path: string,\n port: number,\n inodes: Set<string>,\n): Promise<void> {\n try {\n const content = await readFile(path, \"utf8\");\n for (const line of content.split(\"\\n\").slice(1)) {\n const fields = line.trim().split(/\\s+/);\n const localAddress = fields[1];\n const state = fields[3];\n const inode = fields[9];\n if (localAddress === undefined || state === undefined || inode === undefined) {\n continue;\n }\n const localPort = Number.parseInt(localAddress.split(\":\")[1] ?? \"\", 16);\n if (localPort === port && state === \"0A\") {\n inodes.add(inode);\n }\n }\n } catch {\n // /proc/net/tcp* is Linux-specific; callers fall back to other strategies.\n }\n}\n\nasync function processHasSocketInode(pid: string, inodes: ReadonlySet<string>): Promise<boolean> {\n try {\n const descriptors = await readdir(`/proc/${pid}/fd`);\n for (const descriptor of descriptors) {\n try {\n const link = await readlink(`/proc/${pid}/fd/${descriptor}`);\n const match = /^socket:\\[(\\d+)\\]$/.exec(link);\n if (match?.[1] !== undefined && inodes.has(match[1])) {\n return true;\n }\n } catch {\n // The process may close descriptors while we scan them.\n }\n }\n } catch {\n // The process may exit, or permissions may prevent fd inspection.\n }\n return false;\n}\n\nasync function findListeningPids(port: number): Promise<readonly number[]> {\n if (process.platform === \"win32\") {\n return await findListeningPidsWithNetstat(port);\n }\n const lsofPids = await findListeningPidsWithLsof(port);\n return lsofPids.length > 0 ? lsofPids : await findListeningPidsWithProc(port);\n}\n\nexport async function isPortFree(port: number): Promise<boolean> {\n return await new Promise<boolean>((resolve) => {\n const server = createServer();\n server.once(\"error\", () => {\n resolve(false);\n });\n server.once(\"listening\", () => {\n server.close(() => {\n resolve(true);\n });\n });\n server.listen(port, \"127.0.0.1\");\n });\n}\n\nexport async function isPortListening(port: number, timeoutMs = 200): Promise<boolean> {\n return await new Promise<boolean>((resolve) => {\n const socket = createConnection({ port, host: \"127.0.0.1\" });\n socket.setTimeout(timeoutMs);\n socket.once(\"connect\", () => {\n socket.destroy();\n resolve(true);\n });\n socket.once(\"error\", () => {\n socket.destroy();\n resolve(false);\n });\n socket.once(\"timeout\", () => {\n socket.destroy();\n resolve(false);\n });\n });\n}\n\nexport async function probeTunnelReady(port: number, timeoutMs: number): Promise<boolean> {\n const pollIntervalMs = 250;\n const started = Date.now();\n\n while (Date.now() - started < timeoutMs) {\n const connected = await isPortListening(port);\n\n if (connected) {\n return true;\n }\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, pollIntervalMs);\n });\n }\n\n return false;\n}\n\nexport async function findListeningProcessId(port: number): Promise<number | undefined> {\n const pids = await findListeningPids(port);\n return pids[0];\n}\n\nexport async function killProcessOnPort(port: number): Promise<void> {\n const portStr = port.toString();\n if (process.platform === \"win32\") {\n try {\n const pids = await findListeningPidsWithNetstat(port);\n for (const pid of pids) {\n try {\n // cspell:ignore taskkill\n await execFileAsync(\"taskkill\", [\"/F\", \"/PID\", pid.toString()]);\n } catch {\n // ignore\n }\n }\n } catch {\n // ignore\n }\n return;\n }\n\n try {\n const { stdout } = await execFileAsync(\"lsof\", [\"-t\", \"-i\", `tcp:${portStr}`]);\n const lines = stdout.trim().split(\"\\n\").filter((line) => line.length > 0);\n for (const line of lines) {\n const pid = Number.parseInt(line, 10);\n if (Number.isNaN(pid)) {\n continue;\n }\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {\n // already dead\n }\n }\n } catch {\n // lsof missing or no match — ignore\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { hostname as getHostname } from \"node:os\";\nimport { dirname } from \"node:path\";\nimport process from \"node:process\";\n\nimport { withFileLock } from \"../lock.js\";\nimport { stateFilePath, stateLockPath } from \"../paths.js\";\nimport { findListeningProcessId, isPortListening } from \"../port.js\";\nimport { CfDebuggerError } from \"../types.js\";\nimport type { ActiveSession, SessionKey, StateFile } from \"../types.js\";\n\nasync function readJsonFile<T>(path: string): Promise<T | undefined> {\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch (err: unknown) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n return undefined;\n }\n throw err;\n }\n try {\n return JSON.parse(raw) as T;\n } catch {\n process.stderr.write(\n `[cf-debugger] warning: state file at ${path} is not valid JSON; resetting to empty.\\n`,\n );\n return undefined;\n }\n}\n\nasync function writeJsonFileAtomic(path: string, value: unknown): Promise<void> {\n const tempPath = `${path}.${randomUUID()}.tmp`;\n await mkdir(dirname(path), { recursive: true });\n await writeFile(tempPath, `${JSON.stringify(value, null, 2)}\\n`, \"utf8\");\n await rename(tempPath, path);\n}\n\nfunction emptyState(): StateFile {\n return { version: \"1\", sessions: [] };\n}\n\nfunction isValidState(value: unknown): value is StateFile {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n const candidate = value as Partial<StateFile>;\n return candidate.version === \"1\" && Array.isArray(candidate.sessions);\n}\n\nexport function isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err: unknown) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ESRCH\") {\n return false;\n }\n return true;\n }\n}\n\nasync function isSessionHealthy(session: ActiveSession, host: string): Promise<boolean> {\n if (session.hostname !== host) {\n return true;\n }\n if (!isPidAlive(session.pid)) {\n return false;\n }\n if (session.status !== \"ready\") {\n return true;\n }\n if (!(await isPortListening(session.localPort))) {\n return false;\n }\n const listeningPid = await findListeningProcessId(session.localPort);\n return listeningPid === undefined || listeningPid === session.pid;\n}\n\nasync function filterStaleSessions(\n sessions: readonly ActiveSession[],\n): Promise<readonly ActiveSession[]> {\n const host = getHostname();\n const checks = await Promise.all(\n sessions.map(async (session): Promise<readonly [ActiveSession, boolean]> => [\n session,\n await isSessionHealthy(session, host),\n ]),\n );\n return checks.filter(([, healthy]) => healthy).map(([session]) => session);\n}\n\nasync function readStateRaw(): Promise<StateFile> {\n const parsed = await readJsonFile<unknown>(stateFilePath());\n if (!isValidState(parsed)) {\n return emptyState();\n }\n return parsed;\n}\n\nasync function writeState(state: StateFile): Promise<void> {\n await writeJsonFileAtomic(stateFilePath(), state);\n}\n\nexport interface StateReaderResult {\n readonly sessions: readonly ActiveSession[];\n readonly removed: readonly ActiveSession[];\n}\n\nasync function readAndPruneLocked(): Promise<StateReaderResult> {\n const raw = await readStateRaw();\n const pruned = await filterStaleSessions(raw.sessions);\n const removed = raw.sessions.filter(\n (session) => !pruned.some((active) => active.sessionId === session.sessionId),\n );\n\n if (removed.length > 0) {\n await writeState({ version: \"1\", sessions: pruned });\n }\n\n return { sessions: pruned, removed };\n}\n\nexport async function readActiveSessions(): Promise<readonly ActiveSession[]> {\n const result = await withFileLock(stateLockPath(), readAndPruneLocked);\n return result.sessions;\n}\n\nexport async function readSessionSnapshot(): Promise<readonly ActiveSession[]> {\n return await withFileLock(stateLockPath(), async (): Promise<readonly ActiveSession[]> => {\n const raw = await readStateRaw();\n return raw.sessions;\n });\n}\n\nexport async function readAndPruneActiveSessions(): Promise<StateReaderResult> {\n return await withFileLock(stateLockPath(), readAndPruneLocked);\n}\n\nexport function sessionKeyString(key: SessionKey): string {\n return `${key.region}:${key.org}:${key.space}:${key.app}`;\n}\n\nexport function matchesKey(session: SessionKey, key: SessionKey): boolean {\n return (\n session.region === key.region &&\n session.org === key.org &&\n session.space === key.space &&\n session.app === key.app\n );\n}\n\nexport interface RegisterSessionResult {\n readonly session: ActiveSession;\n readonly existing?: ActiveSession;\n}\n\nexport interface RegisterSessionInput extends SessionKey {\n readonly apiEndpoint: string;\n readonly preferredPort?: number;\n readonly portProbe: (port: number) => Promise<boolean>;\n readonly sessionIdFactory?: () => string;\n readonly cfHomeForSession: (sessionId: string) => string;\n readonly basePort?: number;\n readonly maxPort?: number;\n}\n\nconst DEFAULT_BASE_PORT = 20_000;\nconst DEFAULT_MAX_PORT = 20_999;\n\nasync function pickPort(\n preferred: number | undefined,\n reserved: ReadonlySet<number>,\n probe: (port: number) => Promise<boolean>,\n basePort: number,\n maxPort: number,\n): Promise<number> {\n const tryOrder: number[] = [];\n if (preferred !== undefined) {\n tryOrder.push(preferred);\n }\n for (let port = basePort; port <= maxPort; port++) {\n if (port !== preferred) {\n tryOrder.push(port);\n }\n }\n\n for (const port of tryOrder) {\n if (reserved.has(port)) {\n continue;\n }\n const free = await probe(port);\n if (free) {\n return port;\n }\n }\n throw new CfDebuggerError(\n \"PORT_UNAVAILABLE\",\n `No free local port available in range ${basePort.toString()}–${maxPort.toString()}`,\n );\n}\n\nexport async function registerNewSession(\n input: RegisterSessionInput,\n): Promise<RegisterSessionResult> {\n return await withFileLock(stateLockPath(), async (): Promise<RegisterSessionResult> => {\n const pruneResult = await readAndPruneLocked();\n const existing = pruneResult.sessions.find((session) => matchesKey(session, input));\n if (existing) {\n return { session: existing, existing };\n }\n\n const reservedPorts = new Set(pruneResult.sessions.map((session) => session.localPort));\n const localPort = await pickPort(\n input.preferredPort,\n reservedPorts,\n input.portProbe,\n input.basePort ?? DEFAULT_BASE_PORT,\n input.maxPort ?? DEFAULT_MAX_PORT,\n );\n\n const sessionId = (input.sessionIdFactory ?? randomUUID)();\n const cfHomeDir = input.cfHomeForSession(sessionId);\n\n const session: ActiveSession = {\n sessionId,\n pid: process.pid,\n hostname: getHostname(),\n region: input.region,\n org: input.org,\n space: input.space,\n app: input.app,\n apiEndpoint: input.apiEndpoint,\n localPort,\n remotePort: 9229,\n cfHomeDir,\n startedAt: new Date().toISOString(),\n status: \"starting\",\n };\n\n const nextSessions: readonly ActiveSession[] = [...pruneResult.sessions, session];\n await writeState({ version: \"1\", sessions: nextSessions });\n\n return { session };\n });\n}\n\nexport async function updateSessionStatus(\n sessionId: string,\n status: ActiveSession[\"status\"],\n message?: string,\n): Promise<ActiveSession | undefined> {\n return await withFileLock(stateLockPath(), async (): Promise<ActiveSession | undefined> => {\n const raw = await readStateRaw();\n let updated: ActiveSession | undefined;\n const nextSessions = raw.sessions.map((session): ActiveSession => {\n if (session.sessionId !== sessionId) {\n return session;\n }\n const base: ActiveSession = {\n sessionId: session.sessionId,\n pid: session.pid,\n hostname: session.hostname,\n region: session.region,\n org: session.org,\n space: session.space,\n app: session.app,\n apiEndpoint: session.apiEndpoint,\n localPort: session.localPort,\n remotePort: session.remotePort,\n cfHomeDir: session.cfHomeDir,\n startedAt: session.startedAt,\n status,\n };\n const next: ActiveSession = message === undefined ? base : { ...base, message };\n updated = next;\n return next;\n });\n\n if (updated) {\n await writeState({ version: \"1\", sessions: nextSessions });\n }\n return updated;\n });\n}\n\nexport async function updateSessionPid(\n sessionId: string,\n pid: number,\n): Promise<ActiveSession | undefined> {\n return await withFileLock(stateLockPath(), async (): Promise<ActiveSession | undefined> => {\n const raw = await readStateRaw();\n let updated: ActiveSession | undefined;\n const nextSessions = raw.sessions.map((session): ActiveSession => {\n if (session.sessionId !== sessionId) {\n return session;\n }\n const next: ActiveSession = {\n sessionId: session.sessionId,\n pid,\n hostname: session.hostname,\n region: session.region,\n org: session.org,\n space: session.space,\n app: session.app,\n apiEndpoint: session.apiEndpoint,\n localPort: session.localPort,\n remotePort: session.remotePort,\n cfHomeDir: session.cfHomeDir,\n startedAt: session.startedAt,\n status: session.status,\n ...(session.message === undefined ? {} : { message: session.message }),\n };\n updated = next;\n return next;\n });\n\n if (updated !== undefined) {\n await writeState({ version: \"1\", sessions: nextSessions });\n }\n return updated;\n });\n}\n\nexport async function removeSession(sessionId: string): Promise<ActiveSession | undefined> {\n return await withFileLock(stateLockPath(), async (): Promise<ActiveSession | undefined> => {\n const raw = await readStateRaw();\n const target = raw.sessions.find((session) => session.sessionId === sessionId);\n if (!target) {\n return undefined;\n }\n const remaining = raw.sessions.filter((session) => session.sessionId !== sessionId);\n await writeState({ version: \"1\", sessions: remaining });\n return target;\n });\n}\n","import { mkdir, open, unlink } from \"node:fs/promises\";\nimport type { FileHandle } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nconst DEFAULT_POLL_MS = 50;\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nasync function acquireFileLock(\n lockPath: string,\n timeoutMs: number,\n pollMs: number,\n): Promise<FileHandle> {\n const deadline = Date.now() + timeoutMs;\n await mkdir(dirname(lockPath), { recursive: true });\n\n for (;;) {\n try {\n return await open(lockPath, \"wx\");\n } catch (err: unknown) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") {\n throw err;\n }\n }\n\n if (Date.now() > deadline) {\n throw new Error(`Timed out acquiring file lock at ${lockPath}`);\n }\n\n await sleep(pollMs);\n }\n}\n\nasync function releaseFileLock(lockPath: string, handle: FileHandle): Promise<void> {\n await handle.close();\n await unlink(lockPath).catch((err: unknown) => {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\") {\n throw err;\n }\n });\n}\n\nexport interface WithLockOptions {\n readonly timeoutMs?: number;\n readonly pollMs?: number;\n}\n\nexport async function withFileLock<T>(\n lockPath: string,\n work: () => Promise<T>,\n options?: WithLockOptions,\n): Promise<T> {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const pollMs = options?.pollMs ?? DEFAULT_POLL_MS;\n const handle = await acquireFileLock(lockPath, timeoutMs, pollMs);\n try {\n return await work();\n } finally {\n await releaseFileLock(lockPath, handle);\n }\n}\n","export const DEFAULT_TUNNEL_READY_TIMEOUT_MS = 180_000;\nexport const POST_USR1_DELAY_MS = 300;\nexport const PORT_CLEANUP_DELAY_MS = 600;\nexport const CHILD_SIGTERM_GRACE_MS = 2_000;\nexport const PORT_RECLAIM_DELAY_MS = 250;\nexport const PID_TERMINATION_POLL_MS = 100;\n","import { hostname as getHostname } from \"node:os\";\n\nimport { killProcessOnPort } from \"../port.js\";\nimport { readAndPruneActiveSessions } from \"../state.js\";\nimport type { ActiveSession } from \"../types.js\";\n\nexport interface PruneCleanupResult {\n readonly sessions: readonly ActiveSession[];\n readonly removed: readonly ActiveSession[];\n}\n\nexport async function pruneAndCleanupOrphans(): Promise<PruneCleanupResult> {\n const result = await readAndPruneActiveSessions();\n const host = getHostname();\n for (const removed of result.removed) {\n if (removed.hostname === host) {\n void killProcessOnPort(removed.localPort);\n }\n }\n return result;\n}\n","import type { ChildProcess } from \"node:child_process\";\nimport process from \"node:process\";\n\nimport { isPidAlive } from \"../state.js\";\n\nimport { CHILD_SIGTERM_GRACE_MS, PID_TERMINATION_POLL_MS } from \"./constants.js\";\n\nfunction signalPidOrGroup(pid: number, signal: NodeJS.Signals): void {\n const isWindows = process.platform === \"win32\";\n if (!isWindows) {\n try {\n process.kill(-pid, signal);\n return;\n } catch {\n // fall through to direct pid signal\n }\n }\n try {\n process.kill(pid, signal);\n } catch {\n // already gone\n }\n}\n\nexport async function terminatePidOrGroup(\n pid: number,\n timeoutMs: number = CHILD_SIGTERM_GRACE_MS,\n): Promise<void> {\n if (!isPidAlive(pid)) {\n return;\n }\n\n signalPidOrGroup(pid, \"SIGTERM\");\n const startedAt = Date.now();\n while (Date.now() - startedAt < timeoutMs) {\n if (!isPidAlive(pid)) {\n return;\n }\n await new Promise<void>((resolve) => {\n setTimeout(resolve, PID_TERMINATION_POLL_MS);\n });\n }\n\n signalPidOrGroup(pid, \"SIGKILL\");\n}\n\nexport async function killProcessGroupOrProc(\n child: ChildProcess,\n timeoutMs: number = CHILD_SIGTERM_GRACE_MS,\n): Promise<void> {\n if (child.pid === undefined) {\n return;\n }\n if (child.exitCode !== null || child.signalCode !== null) {\n return;\n }\n await terminatePidOrGroup(child.pid, timeoutMs);\n}\n","import { rm } from \"node:fs/promises\";\nimport process from \"node:process\";\n\nimport { killProcessOnPort } from \"../port.js\";\nimport { matchesKey, readActiveSessions, removeSession } from \"../state.js\";\nimport type { ActiveSession, SessionKey } from \"../types.js\";\n\nimport { PORT_CLEANUP_DELAY_MS } from \"./constants.js\";\nimport { pruneAndCleanupOrphans } from \"./orphans.js\";\nimport { terminatePidOrGroup } from \"./processes.js\";\n\nexport interface StopOptions {\n readonly sessionId?: string;\n readonly key?: SessionKey;\n}\n\nexport interface StopDebuggerResult extends ActiveSession {\n readonly stale: boolean;\n}\n\nfunction findMatchingSession(\n sessions: readonly ActiveSession[],\n options: StopOptions,\n): ActiveSession | undefined {\n if (options.sessionId !== undefined) {\n return sessions.find((s) => s.sessionId === options.sessionId);\n }\n if (options.key !== undefined) {\n const key = options.key;\n return sessions.find((s) => matchesKey(s, key));\n }\n return undefined;\n}\n\nasync function cleanupSession(target: ActiveSession, stale: boolean): Promise<StopDebuggerResult> {\n if (!stale && target.pid !== process.pid) {\n try {\n await terminatePidOrGroup(target.pid);\n } catch {\n // process already gone — cleanup below\n }\n }\n setTimeout(() => {\n void killProcessOnPort(target.localPort);\n }, PORT_CLEANUP_DELAY_MS);\n const removed = stale ? undefined : await removeSession(target.sessionId);\n try {\n await rm(target.cfHomeDir, { recursive: true, force: true });\n } catch {\n // best-effort\n }\n return { ...(removed ?? target), stale };\n}\n\nexport async function stopDebugger(options: StopOptions): Promise<StopDebuggerResult | undefined> {\n const pruneResult = await pruneAndCleanupOrphans();\n const activeTarget = findMatchingSession(pruneResult.sessions, options);\n if (activeTarget !== undefined) {\n return await cleanupSession(activeTarget, false);\n }\n\n const staleTarget = findMatchingSession(pruneResult.removed, options);\n if (staleTarget !== undefined) {\n return await cleanupSession(staleTarget, true);\n }\n\n return undefined;\n}\n\nexport async function stopAllDebuggers(): Promise<number> {\n const pruneResult = await pruneAndCleanupOrphans();\n let stopped = pruneResult.removed.length;\n for (const session of pruneResult.sessions) {\n const result = await stopDebugger({ sessionId: session.sessionId });\n if (result) {\n stopped += 1;\n }\n }\n return stopped;\n}\n\nexport async function listSessions(): Promise<readonly ActiveSession[]> {\n return await readActiveSessions();\n}\n\nexport async function getSession(key: SessionKey): Promise<ActiveSession | undefined> {\n const sessions = await readActiveSessions();\n return sessions.find((s) => matchesKey(s, key));\n}\n"],"mappings":"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","names":["process","execFile","promisify","execFileAsync","promisify","execFile","execFileAsync","mkdir","process","execFile","promisify","execFileAsync","mkdir","readFile","dirname","process","readFile","process","mkdir","dirname","session","process","getHostname","getHostname","process","process","process","mkdir","rm","process","process","rm","process"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/cloud-foundry/commands.ts","../src/regions.ts","../src/types.ts","../src/cloud-foundry/execute.ts","../src/cloud-foundry/ssh.ts","../src/cloud-foundry/node-process.ts","../src/debug-session/start.ts","../src/paths.ts","../src/network/ports.ts","../src/session-state/store.ts","../src/lock.ts","../src/session-state/decoder.ts","../src/debug-session/constants.ts","../src/debug-session/orphans.ts","../src/debug-session/processes.ts","../src/debug-session/startup-cancellation.ts","../src/debug-session/sessions.ts"],"sourcesContent":["import process from \"node:process\";\n\nimport { Command } from \"commander\";\n\nimport { readCurrentCfTarget, requireCurrentCfRegion } from \"./cf.js\";\nimport { resolveNodeTarget } from \"./cloud-foundry/node-process.js\";\nimport {\n getSession,\n listSessions,\n startDebugger,\n stopAllDebuggers,\n stopDebugger,\n} from \"./debugger.js\";\nimport type { ResolvedSessionKey, SessionStatus } from \"./types.js\";\nimport { CfDebuggerError } from \"./types.js\";\n\nfunction readRequiredOption(value: string | undefined, flag: string): string {\n if (value === undefined || value === \"\") {\n process.stderr.write(`Missing required option ${flag}\\n`);\n process.exit(1);\n }\n return value;\n}\n\nfunction parseOptionalPort(raw: string | undefined): number | undefined {\n if (raw === undefined) {\n return undefined;\n }\n const port = Number.parseInt(raw, 10);\n if (Number.isNaN(port) || port <= 0 || port > 65_535) {\n process.stderr.write(`Invalid port: ${raw}\\n`);\n process.exit(1);\n }\n return port;\n}\n\nfunction parseOptionalTimeout(raw: string | undefined): number | undefined {\n if (raw === undefined) {\n return undefined;\n }\n const seconds = Number.parseInt(raw, 10);\n if (Number.isNaN(seconds) || seconds <= 0) {\n process.stderr.write(`Invalid timeout: ${raw}\\n`);\n process.exit(1);\n }\n return seconds * 1000;\n}\n\nfunction parseOptionalInteger(\n raw: string | undefined,\n label: string,\n minimum: number,\n): number | undefined {\n if (raw === undefined) {\n return undefined;\n }\n if (!/^\\d+$/.test(raw)) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", `${label} must be an integer.`);\n }\n const value = Number(raw);\n if (!Number.isSafeInteger(value) || value < minimum) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n `${label} must be at least ${minimum.toString()} and within the safe integer range.`,\n );\n }\n return value;\n}\n\ninterface TargetCommandOptions {\n readonly process?: string;\n readonly instance?: string;\n}\n\ninterface StartCommandOptions extends TargetCommandOptions {\n readonly region?: string;\n readonly org?: string;\n readonly space?: string;\n readonly app?: string;\n readonly port?: string;\n readonly timeout?: string;\n readonly nodePid?: string;\n readonly verbose?: boolean;\n}\n\ninterface StopCommandOptions extends TargetCommandOptions {\n readonly region?: string;\n readonly org?: string;\n readonly space?: string;\n readonly app?: string;\n readonly sessionId?: string;\n readonly all?: boolean;\n}\n\ninterface StatusCommandOptions extends TargetCommandOptions {\n readonly region?: string;\n readonly org?: string;\n readonly space?: string;\n readonly app?: string;\n}\n\nfunction logStatus(verbose: boolean, status: SessionStatus, message?: string): void {\n if (verbose) {\n const suffix = message === undefined ? \"\" : `: ${message}`;\n process.stdout.write(`[cf-debugger] ${status}${suffix}\\n`);\n }\n}\n\nfunction mergeSelector<T extends { region?: string; org?: string; space?: string; app?: string }>(selector: string | undefined, opts: T): T {\n if (selector === undefined) {\n return opts;\n }\n const parts = selector.split(\"/\");\n if (parts.length === 4) {\n return { ...opts, region: opts.region ?? parts[0], org: opts.org ?? parts[1], space: opts.space ?? parts[2], app: opts.app ?? parts[3] };\n }\n if (parts.length === 1) {\n return { ...opts, app: opts.app ?? parts[0] };\n }\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Invalid app selector format. Expected <app> or <region>/<org>/<space>/<app>.\");\n}\n\ninterface StartupAbort {\n readonly signal: AbortSignal;\n dispose(): void;\n}\n\nfunction startupAbort(app: string): StartupAbort {\n const controller = new AbortController();\n const handler = (exitCode: number) => (): void => {\n controller.abort();\n process.stderr.write(`\\nAborting startup for ${app}...\\n`);\n setTimeout(() => { process.exit(exitCode); }, 5_000).unref();\n };\n const onSigint = handler(130);\n const onSigterm = handler(143);\n process.on(\"SIGINT\", onSigint);\n process.on(\"SIGTERM\", onSigterm);\n return {\n signal: controller.signal,\n dispose: (): void => {\n process.off(\"SIGINT\", onSigint);\n process.off(\"SIGTERM\", onSigterm);\n },\n };\n}\n\nfunction writeReady(\n app: string,\n key: ResolvedSessionKey,\n handle: Awaited<ReturnType<typeof startDebugger>>,\n): void {\n process.stdout.write(\n `Debugger ready for ${app} (${key.region}/${key.org}/${key.space}).\\n` +\n ` Process: ${key.process}\\n` +\n ` Instance: ${key.instance.toString()}\\n` +\n ` Local port: ${handle.session.localPort.toString()}\\n` +\n ` Remote port: ${handle.session.remotePort.toString()}\\n` +\n ` Session id: ${handle.session.sessionId}\\n` +\n ` Tunnel PID: ${handle.session.pid.toString()}\\n` +\n ` Node PID: ${handle.session.remoteNodePid?.toString() ?? \"unknown\"}\\n` +\n \"Press Ctrl+C to stop.\\n\",\n );\n}\n\nfunction handleDisposer(\n app: string,\n handle: Awaited<ReturnType<typeof startDebugger>>,\n): () => Promise<void> {\n let pending: Promise<void> | undefined;\n return async (): Promise<void> => {\n pending ??= (async (): Promise<void> => {\n process.stdout.write(`\\nStopping debugger for ${app}...\\n`);\n try {\n await handle.dispose();\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error during stop: ${message}\\n`);\n }\n })();\n await pending;\n };\n}\n\nasync function waitForHandle(\n app: string,\n handle: Awaited<ReturnType<typeof startDebugger>>,\n): Promise<void> {\n const dispose = handleDisposer(app, handle);\n const stop = (exitCode: number) => (): void => {\n void dispose().then(() => { process.exit(exitCode); });\n };\n process.on(\"SIGINT\", stop(130));\n process.on(\"SIGTERM\", stop(143));\n const code = await handle.waitForExit();\n await dispose();\n process.exit(code ?? 0);\n}\n\nasync function handleStart(selector: string | undefined, rawOpts: StartCommandOptions): Promise<void> {\n const opts = mergeSelector(selector, rawOpts);\n const app = readRequiredOption(opts.app, \"--app or selector\");\n const key = await resolveSessionKey({ ...opts, app });\n const verbose = opts.verbose ?? false;\n\n const preferredPort = parseOptionalPort(opts.port);\n const tunnelReadyTimeoutMs = parseOptionalTimeout(opts.timeout);\n const nodePid = parseOptionalInteger(opts.nodePid, \"nodePid\", 1);\n\n const abort = startupAbort(app);\n\n let handle;\n try {\n handle = await startDebugger({\n region: key.region,\n org: key.org,\n space: key.space,\n app,\n process: key.process,\n instance: key.instance,\n verbose,\n signal: abort.signal,\n ...(preferredPort === undefined ? {} : { preferredPort }),\n ...(tunnelReadyTimeoutMs === undefined ? {} : { tunnelReadyTimeoutMs }),\n ...(nodePid === undefined ? {} : { nodePid }),\n onStatus: (status, message) => {\n logStatus(verbose, status, message);\n },\n });\n } finally {\n abort.dispose();\n }\n writeReady(app, key, handle);\n await waitForHandle(app, handle);\n}\n\nfunction hasText(value: string | undefined): boolean {\n return optionalText(value) !== undefined;\n}\n\nfunction optionalText(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed === undefined || trimmed.length === 0 ? undefined : trimmed;\n}\n\nfunction currentCfOptions(): { readonly command?: string } | undefined {\n const command = process.env[\"CF_DEBUGGER_CF_BIN\"];\n return command === undefined ? undefined : { command };\n}\n\nasync function resolveSessionKey(opts: StopCommandOptions): Promise<ResolvedSessionKey> {\n const app = readRequiredOption(opts.app, \"--app or selector\");\n const region = optionalText(opts.region);\n const org = optionalText(opts.org);\n const space = optionalText(opts.space);\n const processName = opts.process;\n const instance = parseOptionalInteger(opts.instance, \"instance\", 0);\n const target = resolveNodeTarget({\n ...(processName === undefined ? {} : { process: processName }),\n ...(instance === undefined ? {} : { instance }),\n });\n if (region !== undefined && org !== undefined && space !== undefined) {\n return {\n region,\n org,\n space,\n app,\n process: target.process,\n instance: target.instance,\n };\n }\n\n const current = await readCurrentCfTarget(currentCfOptions()).catch((error: unknown) => {\n throw new CfDebuggerError(\n \"CF_TARGET_FAILED\",\n \"No current CF target found. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.\",\n error instanceof Error ? error.message : String(error),\n );\n });\n if (current === undefined) {\n throw new CfDebuggerError(\n \"CF_TARGET_FAILED\",\n \"No current CF target found. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.\",\n );\n }\n\n return {\n region: region ?? requireCurrentCfRegion(current),\n org: org ?? current.org,\n space: space ?? current.space,\n app,\n process: target.process,\n instance: target.instance,\n };\n}\n\nasync function resolveOptionalSessionKey(\n opts: StopCommandOptions,\n): Promise<ResolvedSessionKey | undefined> {\n if (!hasText(opts.app)) {\n if (hasText(opts.region) || hasText(opts.org) || hasText(opts.space)) {\n readRequiredOption(opts.app, \"--app\");\n }\n return undefined;\n }\n return await resolveSessionKey(opts);\n}\n\nasync function handleStop(selector: string | undefined, rawOpts: StopCommandOptions): Promise<void> {\n const opts = mergeSelector(selector, rawOpts);\n if (opts.all === true) {\n const count = await stopAllDebuggers();\n process.stdout.write(`Stop requested for ${count.toString()} session(s).\\n`);\n return;\n }\n const key = await resolveOptionalSessionKey(opts);\n const result = await stopDebugger({\n ...(opts.sessionId === undefined ? {} : { sessionId: opts.sessionId }),\n ...(key === undefined ? {} : { key }),\n });\n if (result === undefined) {\n process.stderr.write(\n \"No matching session found. Use `cf-debugger list` and pass --session-id or \" +\n \"region/org/space/app if the current CF target differs.\\n\",\n );\n process.exit(1);\n }\n if (result.pending) {\n process.stdout.write(\n `Stop requested for session ${result.sessionId} ` +\n `(${result.app}, startup phase ${result.status}).\\n`,\n );\n return;\n }\n if (result.stale) {\n process.stdout.write(\n `Removed stale session ${result.sessionId} (${result.app}, port ${result.localPort.toString()}).\\n`,\n );\n return;\n }\n process.stdout.write(\n `Stopped session ${result.sessionId} (${result.app}, port ${result.localPort.toString()}).\\n`,\n );\n}\n\nasync function handleList(): Promise<void> {\n const sessions = await listSessions();\n process.stdout.write(`${JSON.stringify(sessions, null, 2)}\\n`);\n}\n\nasync function handleStatus(selector: string | undefined, rawOpts: StatusCommandOptions): Promise<void> {\n const opts = mergeSelector(selector, rawOpts);\n const session = await getSession(await resolveSessionKey(opts));\n process.stdout.write(`${JSON.stringify(session ?? null, null, 2)}\\n`);\n}\n\nfunction registerStartCommand(program: Command): void {\n program\n .command(\"start\")\n .description(\"Open a debug tunnel for one app\")\n .argument(\"[selector]\", \"Optional app selector: `<app>` or `region/org/space/app`\")\n .option(\"--region <key>\", \"CF region key (default: current cf target)\")\n .option(\"--org <name>\", \"CF org name (default: current cf target)\")\n .option(\"--space <name>\", \"CF space name (default: current cf target)\")\n .option(\"--app <name>\", \"CF app name\")\n .option(\"--process <name>\", \"CF process name\", \"web\")\n .option(\"-i, --instance <index>\", \"CF process instance index\", \"0\")\n .option(\"--node-pid <pid>\", \"Explicit remote Node.js PID\")\n .option(\"--port <number>\", \"Preferred local port (auto-assigned if omitted)\")\n .option(\"--timeout <seconds>\", \"Tunnel-ready timeout in seconds (default: 180)\")\n .option(\"--verbose\", \"Print status transitions\", false)\n .action(async (selector: string | undefined, opts: StartCommandOptions): Promise<void> => {\n await handleStart(selector, opts);\n });\n}\n\nfunction registerStopCommand(program: Command): void {\n program\n .command(\"stop\")\n .description(\"Stop one session (by key or id) or all sessions with --all\")\n .argument(\"[selector]\", \"Optional app selector: `<app>` or `region/org/space/app`\")\n .option(\"--region <key>\")\n .option(\"--org <name>\")\n .option(\"--space <name>\")\n .option(\"--app <name>\")\n .option(\"--process <name>\", \"CF process name\", \"web\")\n .option(\"-i, --instance <index>\", \"CF process instance index\", \"0\")\n .option(\"--session-id <id>\")\n .option(\"--all\", \"Stop every active session\", false)\n .action(async (selector: string | undefined, opts: StopCommandOptions): Promise<void> => {\n await handleStop(selector, opts);\n });\n}\n\nfunction registerReadCommands(program: Command): void {\n program\n .command(\"list\")\n .description(\"Print every active debugger session as JSON\")\n .action(async (): Promise<void> => {\n await handleList();\n });\n\n program\n .command(\"status\")\n .description(\"Print one session by key as JSON (null if not active)\")\n .argument(\"[selector]\", \"Optional app selector: `<app>` or `region/org/space/app`\")\n .option(\"--region <key>\")\n .option(\"--org <name>\")\n .option(\"--space <name>\")\n .option(\"--app <name>\")\n .option(\"--process <name>\", \"CF process name\", \"web\")\n .option(\"-i, --instance <index>\", \"CF process instance index\", \"0\")\n .action(async (selector: string | undefined, opts: StatusCommandOptions): Promise<void> => {\n await handleStatus(selector, opts);\n });\n}\n\nexport async function main(argv: readonly string[]): Promise<void> {\n const program = new Command()\n .name(\"cf-debugger\")\n .description(\"Open an SSH debug tunnel to a SAP BTP Cloud Foundry app's Node.js inspector\");\n registerStartCommand(program);\n registerStopCommand(program);\n registerReadCommands(program);\n\n await program.parseAsync([...argv]);\n}\n\ntry {\n await main(process.argv);\n} catch (err: unknown) {\n if (err instanceof CfDebuggerError) {\n if (err.code === \"ABORTED\") {\n process.stderr.write(`Aborted: ${err.message}\\n`);\n process.exit(130);\n }\n process.stderr.write(`Error [${err.code}]: ${err.message}\\n`);\n } else {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`Error: ${msg}\\n`);\n }\n process.exit(1);\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nimport { listKnownRegionKeys, resolveApiEndpoint } from \"../regions.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nimport { type CfExecContext, runCf } from \"./execute.js\";\nimport { parseAppNames, parseNameTable } from \"./parsers.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst CF_AUTH_MAX_ATTEMPTS = 3;\nconst CURRENT_TARGET_TIMEOUT_MS = 30_000;\n\nfunction rethrowCallerAbort(error: unknown): void {\n if (error instanceof CfDebuggerError && error.code === \"ABORTED\") {\n throw error;\n }\n}\n\nfunction waitForAuthRetry(delayMs: number, signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\"));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\"));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, delayMs);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nexport interface CurrentCfTargetReadOptions {\n readonly command?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly timeoutMs?: number;\n}\n\nexport interface CurrentCfTarget {\n readonly apiEndpoint: string;\n readonly region?: string;\n readonly org: string;\n readonly space: string;\n}\n\nexport async function cfApi(apiEndpoint: string, context: CfExecContext): Promise<void> {\n await runCf([\"api\", apiEndpoint], context);\n}\n\nexport async function cfAuth(\n email: string,\n password: string,\n context: CfExecContext,\n): Promise<void> {\n let lastError: unknown;\n for (let attempt = 0; attempt < CF_AUTH_MAX_ATTEMPTS; attempt++) {\n try {\n await runCf([\"auth\"], context, {\n env: { CF_PASSWORD: password, CF_USERNAME: email },\n sensitiveValues: [email, password],\n });\n return;\n } catch (err: unknown) {\n lastError = err;\n if (err instanceof CfDebuggerError && err.code === \"ABORTED\") {\n throw err;\n }\n if (attempt < CF_AUTH_MAX_ATTEMPTS - 1) {\n await waitForAuthRetry(1000 * (attempt + 1), context.signal);\n }\n }\n }\n if (lastError instanceof Error) {\n throw lastError;\n }\n throw new CfDebuggerError(\"CF_AUTH_FAILED\", `cf auth failed: ${String(lastError)}`);\n}\n\nexport async function cfLogin(\n apiEndpoint: string,\n email: string,\n password: string,\n context: CfExecContext,\n): Promise<void> {\n try {\n await cfApi(apiEndpoint, context);\n await cfAuth(email, password, context);\n } catch (err: unknown) {\n rethrowCallerAbort(err);\n if (err instanceof CfDebuggerError) {\n throw new CfDebuggerError(\"CF_LOGIN_FAILED\", err.message, err.stderr);\n }\n throw err;\n }\n}\n\nexport async function cfTarget(\n org: string,\n space: string,\n context: CfExecContext,\n): Promise<void> {\n try {\n await runCf([\"target\", \"-o\", org, \"-s\", space], context);\n } catch (err: unknown) {\n rethrowCallerAbort(err);\n if (err instanceof CfDebuggerError) {\n throw new CfDebuggerError(\"CF_TARGET_FAILED\", err.message, err.stderr);\n }\n throw err;\n }\n}\n\nexport async function cfAppExists(appName: string, context: CfExecContext): Promise<boolean> {\n try {\n await runCf([\"app\", appName], context);\n return true;\n } catch (err: unknown) {\n const stderr = (err as CfDebuggerError).stderr ?? \"\";\n if (stderr.toLowerCase().includes(\"not found\")) {\n return false;\n }\n throw err;\n }\n}\n\nexport async function cfSshEnabled(appName: string, context: CfExecContext): Promise<boolean> {\n try {\n const stdout = await runCf([\"ssh-enabled\", appName], context);\n return stdout.toLowerCase().includes(\"ssh support is enabled\");\n } catch (err: unknown) {\n rethrowCallerAbort(err);\n return false;\n }\n}\n\nexport async function cfEnableSsh(appName: string, context: CfExecContext): Promise<void> {\n try {\n await runCf([\"enable-ssh\", appName], context);\n } catch (err: unknown) {\n rethrowCallerAbort(err);\n if (err instanceof CfDebuggerError) {\n throw new CfDebuggerError(\"SSH_NOT_ENABLED\", err.message, err.stderr);\n }\n throw err;\n }\n}\n\nexport async function cfRestartApp(appName: string, context: CfExecContext): Promise<void> {\n await runCf([\"restart\", appName], context);\n}\n\nexport async function cfApps(context: CfExecContext): Promise<readonly string[]> {\n const stdout = await runCf([\"apps\"], context);\n return parseAppNames(stdout);\n}\n\nexport async function cfOrgs(context: CfExecContext): Promise<readonly string[]> {\n const stdout = await runCf([\"orgs\"], context);\n return parseNameTable(stdout);\n}\n\nexport async function cfSpaces(context: CfExecContext): Promise<readonly string[]> {\n const stdout = await runCf([\"spaces\"], context);\n return parseNameTable(stdout);\n}\n\nexport async function readCurrentCfTarget(\n options: CurrentCfTargetReadOptions = {},\n): Promise<CurrentCfTarget | undefined> {\n try {\n const { stdout } = await execFileAsync(options.command ?? process.env[\"CF_DEBUGGER_CF_BIN\"] ?? \"cf\", [\"target\"], {\n env: options.env ?? process.env,\n maxBuffer: 16 * 1024 * 1024,\n timeout: options.timeoutMs ?? CURRENT_TARGET_TIMEOUT_MS,\n });\n return parseCurrentCfTarget(stdout);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n throw new CfDebuggerError(\"CF_TARGET_FAILED\", `cf target failed: ${message}`);\n }\n}\n\nexport function parseCurrentCfTarget(stdout: string): CurrentCfTarget | undefined {\n const fields = parseTargetFields(stdout);\n const apiEndpoint = fields.get(\"api endpoint\");\n const org = fields.get(\"org\");\n const space = fields.get(\"space\");\n if (!isPresent(apiEndpoint) || !isPresent(org) || !isPresent(space)) {\n return undefined;\n }\n\n const region = regionKeyForApiEndpoint(apiEndpoint);\n return {\n apiEndpoint,\n ...(region === undefined ? {} : { region }),\n org,\n space,\n };\n}\n\nexport function requireCurrentCfRegion(\n target: Pick<CurrentCfTarget, \"apiEndpoint\" | \"region\">,\n instruction = \"Pass --region explicitly.\",\n): string {\n if (target.region !== undefined) {\n return target.region;\n }\n throw new CfDebuggerError(\n \"CF_TARGET_FAILED\",\n `Current CF API endpoint \"${target.apiEndpoint}\" does not match a known SAP region. ${instruction}`,\n );\n}\n\nfunction parseTargetFields(stdout: string): Map<string, string> {\n return new Map(\n stdout\n .split(\"\\n\")\n .map((line): readonly [string, string] | undefined => {\n const separator = line.indexOf(\":\");\n if (separator < 0) {\n return undefined;\n }\n return [\n line.slice(0, separator).trim().toLowerCase(),\n line.slice(separator + 1).trim(),\n ];\n })\n .filter((field): field is readonly [string, string] => field !== undefined),\n );\n}\n\nfunction regionKeyForApiEndpoint(apiEndpoint: string): string | undefined {\n const normalized = normalizeApiEndpoint(apiEndpoint);\n const known = listKnownRegionKeys().find((key) => normalizeApiEndpoint(resolveApiEndpoint(key)) === normalized);\n if (known !== undefined) {\n return known;\n }\n return regionKeyFromSapApiEndpoint(normalized);\n}\n\nfunction normalizeApiEndpoint(apiEndpoint: string): string {\n return apiEndpoint.trim().replace(/\\/+$/, \"\").toLowerCase();\n}\n\nfunction regionKeyFromSapApiEndpoint(apiEndpoint: string): string | undefined {\n const match = /^https:\\/\\/api\\.cf\\.([a-z]{2}\\d{2}(?:-\\d{3})?)\\.(?:hana\\.ondemand\\.com|platform\\.sapcloud\\.cn)$/.exec(apiEndpoint);\n return match?.[1];\n}\n\nfunction isPresent(value: string | undefined): value is string {\n return value !== undefined && value.length > 0;\n}\n","export interface RegionInfo {\n readonly key: string;\n readonly apiEndpoint: string;\n}\n\nconst REGION_API_ENDPOINTS: Readonly<Record<string, string>> = {\n ae01: \"https://api.cf.ae01.hana.ondemand.com\",\n ap01: \"https://api.cf.ap01.hana.ondemand.com\",\n ap10: \"https://api.cf.ap10.hana.ondemand.com\",\n ap11: \"https://api.cf.ap11.hana.ondemand.com\",\n ap12: \"https://api.cf.ap12.hana.ondemand.com\",\n ap20: \"https://api.cf.ap20.hana.ondemand.com\",\n ap21: \"https://api.cf.ap21.hana.ondemand.com\",\n ap30: \"https://api.cf.ap30.hana.ondemand.com\",\n br10: \"https://api.cf.br10.hana.ondemand.com\",\n br20: \"https://api.cf.br20.hana.ondemand.com\",\n br30: \"https://api.cf.br30.hana.ondemand.com\",\n ca10: \"https://api.cf.ca10.hana.ondemand.com\",\n ca20: \"https://api.cf.ca20.hana.ondemand.com\",\n ch20: \"https://api.cf.ch20.hana.ondemand.com\",\n cn20: \"https://api.cf.cn20.platform.sapcloud.cn\",\n cn40: \"https://api.cf.cn40.platform.sapcloud.cn\",\n eu01: \"https://api.cf.eu01.hana.ondemand.com\",\n eu02: \"https://api.cf.eu02.hana.ondemand.com\",\n eu10: \"https://api.cf.eu10.hana.ondemand.com\",\n \"eu10-002\": \"https://api.cf.eu10-002.hana.ondemand.com\",\n \"eu10-003\": \"https://api.cf.eu10-003.hana.ondemand.com\",\n \"eu10-004\": \"https://api.cf.eu10-004.hana.ondemand.com\",\n \"eu10-005\": \"https://api.cf.eu10-005.hana.ondemand.com\",\n eu11: \"https://api.cf.eu11.hana.ondemand.com\",\n eu13: \"https://api.cf.eu13.hana.ondemand.com\",\n eu20: \"https://api.cf.eu20.hana.ondemand.com\",\n \"eu20-001\": \"https://api.cf.eu20-001.hana.ondemand.com\",\n \"eu20-002\": \"https://api.cf.eu20-002.hana.ondemand.com\",\n eu22: \"https://api.cf.eu22.hana.ondemand.com\",\n eu30: \"https://api.cf.eu30.hana.ondemand.com\",\n il30: \"https://api.cf.il30.hana.ondemand.com\",\n in30: \"https://api.cf.in30.hana.ondemand.com\",\n jp01: \"https://api.cf.jp01.hana.ondemand.com\",\n jp10: \"https://api.cf.jp10.hana.ondemand.com\",\n jp20: \"https://api.cf.jp20.hana.ondemand.com\",\n jp30: \"https://api.cf.jp30.hana.ondemand.com\",\n jp31: \"https://api.cf.jp31.hana.ondemand.com\",\n sa30: \"https://api.cf.sa30.hana.ondemand.com\",\n sa31: \"https://api.cf.sa31.hana.ondemand.com\",\n uk20: \"https://api.cf.uk20.hana.ondemand.com\",\n us01: \"https://api.cf.us01.hana.ondemand.com\",\n us02: \"https://api.cf.us02.hana.ondemand.com\",\n us10: \"https://api.cf.us10.hana.ondemand.com\",\n \"us10-001\": \"https://api.cf.us10-001.hana.ondemand.com\",\n \"us10-002\": \"https://api.cf.us10-002.hana.ondemand.com\",\n us11: \"https://api.cf.us11.hana.ondemand.com\",\n us20: \"https://api.cf.us20.hana.ondemand.com\",\n us21: \"https://api.cf.us21.hana.ondemand.com\",\n us30: \"https://api.cf.us30.hana.ondemand.com\",\n};\n\nexport function resolveApiEndpoint(regionKey: string, override?: string): string {\n if (override !== undefined && override !== \"\") {\n return override;\n }\n const endpoint = REGION_API_ENDPOINTS[regionKey];\n if (endpoint === undefined) {\n throw new Error(\n `Unknown region key: ${regionKey}. Pass \\`apiEndpoint\\` explicitly to override.`,\n );\n }\n return endpoint;\n}\n\nexport function listKnownRegionKeys(): readonly string[] {\n return Object.keys(REGION_API_ENDPOINTS);\n}\n","export interface SessionKey {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n readonly process?: string;\n readonly instance?: number;\n readonly apiEndpoint?: string;\n readonly nodePid?: number;\n}\n\nexport interface ResolvedSessionKey extends SessionKey {\n readonly process: string;\n readonly instance: number;\n}\n\nexport type SessionStatus =\n | \"starting\"\n | \"logging-in\"\n | \"targeting\"\n | \"ssh-enabling\"\n | \"ssh-restarting\"\n | \"signaling\"\n | \"tunneling\"\n | \"ready\"\n | \"stopping\"\n | \"stopped\"\n | \"error\";\n\nexport interface ActiveSession extends SessionKey {\n readonly sessionId: string;\n /** Compatibility alias for the currently active controller or tunnel PID. */\n readonly pid: number;\n readonly controllerPid?: number;\n readonly tunnelPid?: number;\n readonly hostname: string;\n readonly localPort: number;\n readonly remotePort: number;\n readonly apiEndpoint: string;\n readonly cfHomeDir: string;\n readonly startedAt: string;\n readonly status: SessionStatus;\n readonly remoteNodePid?: number;\n readonly stopRequestedAt?: string;\n readonly message?: string;\n}\n\nexport interface StartDebuggerOptions extends SessionKey {\n readonly email?: string;\n readonly password?: string;\n readonly preferredPort?: number;\n readonly tunnelReadyTimeoutMs?: number;\n /** Set false when the caller must not enable SSH or restart the deployed app. Defaults to true. */\n readonly allowSshEnableRestart?: boolean;\n readonly verbose?: boolean;\n readonly onStatus?: (status: SessionStatus, message?: string) => void;\n readonly signal?: AbortSignal;\n}\n\nexport interface DebuggerHandle {\n readonly session: ActiveSession;\n dispose(): Promise<void>;\n waitForExit(): Promise<number | null>;\n}\n\nexport interface StateFile {\n readonly version: \"2\";\n readonly sessions: readonly ActiveSession[];\n}\n\nexport class CfDebuggerError extends Error {\n public readonly code: string;\n public readonly stderr?: string;\n\n public constructor(code: string, message: string, stderr?: string) {\n super(message);\n this.name = \"CfDebuggerError\";\n this.code = code;\n if (stderr !== undefined) {\n this.stderr = stderr;\n }\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nimport { CfDebuggerError } from \"../types.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst MAX_BUFFER = 16 * 1024 * 1024;\nexport const DEFAULT_CF_COMMAND_TIMEOUT_MS = 300_000;\nconst REDACTED_ARG = \"<redacted>\";\nconst MAX_RETRIES = 3;\n\nexport interface CfExecContext {\n readonly cfHome: string;\n readonly command?: string;\n readonly signal?: AbortSignal;\n}\n\nexport interface CfRunOptions {\n readonly env?: NodeJS.ProcessEnv;\n readonly sensitiveValues?: readonly string[];\n readonly timeoutMs?: number;\n}\n\ninterface CfFailureDetails {\n readonly code: string | undefined;\n readonly killed: boolean;\n readonly message: string;\n readonly stderr: string | undefined;\n readonly stdout: string | undefined;\n}\n\ninterface ResolvedCfRunOptions {\n readonly env: NodeJS.ProcessEnv | undefined;\n readonly redactionValues: readonly string[];\n readonly timeoutMs: number;\n}\n\nexport function buildEnv(cfHome: string): NodeJS.ProcessEnv {\n return { ...process.env, CF_HOME: cfHome };\n}\n\nexport function resolveBin(context: CfExecContext): string {\n return context.command ?? process.env[\"CF_DEBUGGER_CF_BIN\"] ?? \"cf\";\n}\n\nfunction sensitiveArgs(args: readonly string[]): readonly string[] {\n if (args[0] !== \"auth\") {\n return [];\n }\n return args.slice(1).filter((arg) => arg.length > 0);\n}\n\nfunction redactText(text: string, values: readonly string[]): string {\n return values.reduce((current, value) => current.split(value).join(REDACTED_ARG), text);\n}\n\nfunction normalizeSensitiveValues(values: readonly string[]): readonly string[] {\n return [...new Set(values.filter((value) => value.length > 0))]\n .sort((left, right) => right.length - left.length);\n}\n\nfunction waitForRetry(delayMs: number, signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\"));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\"));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, delayMs);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction formatArgsForError(args: readonly string[]): string {\n if (args[0] !== \"auth\") {\n return args.join(\" \");\n }\n return args.map((arg, index) => (index === 0 ? arg : REDACTED_ARG)).join(\" \");\n}\n\nfunction optionalString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction readFailureDetails(error: unknown): CfFailureDetails {\n const errorObject = typeof error === \"object\" && error !== null ? error : undefined;\n const field = (key: string): unknown => errorObject === undefined ? undefined : Reflect.get(errorObject, key);\n return {\n code: optionalString(field(\"code\")),\n killed: field(\"killed\") === true,\n message: error instanceof Error ? error.message : String(error),\n stderr: optionalString(field(\"stderr\")),\n stdout: optionalString(field(\"stdout\")),\n };\n}\n\nfunction isTransientNetworkError(error: CfFailureDetails): boolean {\n if (error.killed && error.code === undefined) {\n // execFile reports a timeout as a killed process without an errno code.\n return true;\n }\n\n const code = error.code ?? \"\";\n const networkCodes = [\"ETIMEDOUT\", \"ECONNRESET\", \"ENOTFOUND\", \"ECONNREFUSED\", \"EHOSTUNREACH\", \"ENETUNREACH\"];\n if (networkCodes.includes(code)) {\n return true;\n }\n\n const output = `${error.message} ${error.stderr ?? \"\"} ${error.stdout ?? \"\"}`.toLowerCase();\n const transientPhrases = [\n \"error performing request\",\n \"timeout exceeded\",\n \"connection reset by peer\",\n \"service unavailable\",\n \"bad gateway\",\n \"gateway timeout\",\n \"dial tcp\",\n \"i/o timeout\"\n ];\n if (transientPhrases.some((phrase) => output.includes(phrase))) {\n return true;\n }\n\n const transientRegexes = [/\\b502\\b/, /\\b503\\b/, /\\b504\\b/, /\\btimeout\\b/];\n return transientRegexes.some((regex) => regex.test(output));\n}\n\nfunction resolveRunOptions(\n args: readonly string[],\n input: number | CfRunOptions,\n): ResolvedCfRunOptions {\n const options = typeof input === \"number\" ? { timeoutMs: input } : input;\n return {\n env: options.env,\n redactionValues: normalizeSensitiveValues([\n ...sensitiveArgs(args),\n ...(options.sensitiveValues ?? []),\n ]),\n timeoutMs: options.timeoutMs ?? DEFAULT_CF_COMMAND_TIMEOUT_MS,\n };\n}\n\nasync function executeCfAttempt(\n args: readonly string[],\n context: CfExecContext,\n options: ResolvedCfRunOptions,\n): Promise<string> {\n const { stdout } = await execFileAsync(resolveBin(context), [...args], {\n env: { ...buildEnv(context.cfHome), ...options.env },\n maxBuffer: MAX_BUFFER,\n ...(context.signal === undefined ? {} : { signal: context.signal }),\n timeout: options.timeoutMs,\n });\n return stdout;\n}\n\nfunction retryDelayMs(failure: CfFailureDetails, attempt: number): number | undefined {\n if (!isTransientNetworkError(failure) || attempt > MAX_RETRIES) {\n return undefined;\n }\n return Math.min(1000 * (2 ** (attempt - 1)), 10_000);\n}\n\nfunction createCfCliError(\n args: readonly string[],\n failure: CfFailureDetails,\n redactionValues: readonly string[],\n): CfDebuggerError {\n const stderr = redactText(failure.stderr?.trim() ?? \"\", redactionValues);\n const fallbackMessage = redactText(failure.message, redactionValues);\n const detail = stderr.length > 0 ? stderr : fallbackMessage;\n return new CfDebuggerError(\n \"CF_CLI_FAILED\",\n `cf ${formatArgsForError(args)} failed: ${detail}`,\n stderr,\n );\n}\n\nexport async function runCf(\n args: readonly string[],\n context: CfExecContext,\n input: number | CfRunOptions = {},\n): Promise<string> {\n if (context.signal?.aborted) {\n throw new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\");\n }\n const options = resolveRunOptions(args, input);\n let attempt = 0;\n\n for (;;) {\n try {\n return await executeCfAttempt(args, context, options);\n } catch (err: unknown) {\n attempt += 1;\n const failure = readFailureDetails(err);\n if (context.signal?.aborted || failure.code === \"ABORT_ERR\") {\n throw new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\");\n }\n const delayMs = retryDelayMs(failure, attempt);\n if (delayMs !== undefined) {\n await waitForRetry(delayMs, context.signal);\n continue;\n }\n throw createCfCliError(args, failure, options.redactionValues);\n }\n }\n}\n","import { spawn, type ChildProcessByStdio } from \"node:child_process\";\nimport type { Readable } from \"node:stream\";\n\nimport { CfDebuggerError } from \"../types.js\";\n\nimport {\n buildEnv,\n DEFAULT_CF_COMMAND_TIMEOUT_MS,\n resolveBin,\n type CfExecContext,\n} from \"./execute.js\";\nimport {\n DEFAULT_CF_PROCESS,\n resolveNodeTarget,\n type NodeTargetSelectors,\n} from \"./node-process.js\";\n\nconst DEFAULT_MAX_OUTPUT_BYTES = 65_536;\n\nexport interface CfSshSignalResult {\n readonly exitCode: number | null;\n readonly stdout: string;\n readonly stderr: string;\n readonly outputTruncated: boolean;\n readonly signal?: NodeJS.Signals;\n readonly timedOutAfterMs?: number;\n}\n\nexport interface CfSshOptions extends NodeTargetSelectors {\n readonly timeoutMs?: number;\n readonly maxOutputBytes?: number;\n}\n\ninterface ResolvedSshOptions {\n readonly target: NodeTargetSelectors;\n readonly timeoutMs: number;\n readonly maxOutputBytes: number;\n}\n\ninterface BoundedOutput {\n chunks: Buffer[];\n bytes: number;\n truncated: boolean;\n}\n\ninterface SshExecutionState {\n readonly stdout: BoundedOutput;\n readonly stderr: BoundedOutput;\n settled: boolean;\n aborted: boolean;\n timedOut: boolean;\n timeoutTimer?: NodeJS.Timeout;\n forceKillTimer?: NodeJS.Timeout;\n}\n\nexport function buildCfSshArgs(\n appName: string,\n target: NodeTargetSelectors,\n tail: readonly string[],\n): readonly string[] {\n const resolved = resolveNodeTarget(target);\n const processArgs = resolved.process === DEFAULT_CF_PROCESS\n ? []\n : [\"--process\", resolved.process];\n return [\n \"ssh\",\n appName,\n ...processArgs,\n \"-i\",\n resolved.instance.toString(),\n ...tail,\n ];\n}\n\nexport async function cfSshOneShot(\n appName: string,\n command: string,\n context: CfExecContext,\n rawOptions: number | CfSshOptions = DEFAULT_CF_COMMAND_TIMEOUT_MS,\n): Promise<CfSshSignalResult> {\n const options = resolveSshOptions(rawOptions);\n const args = buildCfSshArgs(appName, options.target, [\n \"--disable-pseudo-tty\",\n \"-c\",\n command,\n ]);\n return await runSshOneShot(args, context, options);\n}\n\nfunction resolveSshOptions(raw: number | CfSshOptions): ResolvedSshOptions {\n const input = typeof raw === \"number\" ? { timeoutMs: raw } : raw;\n const timeoutMs = input.timeoutMs ?? DEFAULT_CF_COMMAND_TIMEOUT_MS;\n const maxOutputBytes = input.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;\n if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0) {\n throw new RangeError(\"timeoutMs must be a positive safe integer\");\n }\n if (!Number.isSafeInteger(maxOutputBytes) || maxOutputBytes <= 0) {\n throw new RangeError(\"maxOutputBytes must be a positive safe integer\");\n }\n return { target: input, timeoutMs, maxOutputBytes };\n}\n\nfunction createBoundedOutput(): BoundedOutput {\n return { chunks: [], bytes: 0, truncated: false };\n}\n\nfunction appendBounded(output: BoundedOutput, data: Buffer | string, limit: number): void {\n const incoming = Buffer.isBuffer(data) ? data : Buffer.from(data);\n const remaining = Math.max(0, limit - output.bytes);\n if (incoming.byteLength > remaining) {\n output.truncated = true;\n }\n if (remaining === 0) {\n return;\n }\n const next = incoming.subarray(0, remaining);\n output.chunks.push(next);\n output.bytes += next.byteLength;\n}\n\nfunction outputText(output: BoundedOutput): string {\n return Buffer.concat(output.chunks, output.bytes).toString(\"utf8\");\n}\n\nfunction createResult(\n exitCode: number | null,\n stdout: BoundedOutput,\n stderr: BoundedOutput,\n): CfSshSignalResult {\n return {\n exitCode,\n stdout: outputText(stdout),\n stderr: outputText(stderr),\n outputTruncated: stdout.truncated || stderr.truncated,\n };\n}\n\nfunction createSshExecutionState(): SshExecutionState {\n return {\n stdout: createBoundedOutput(),\n stderr: createBoundedOutput(),\n settled: false,\n aborted: false,\n timedOut: false,\n };\n}\n\nfunction terminateSshExecution(\n child: ReturnType<typeof spawn>,\n state: SshExecutionState,\n): void {\n signalChild(child, \"SIGTERM\");\n state.forceKillTimer ??= setTimeout(() => {\n signalChild(child, \"SIGKILL\");\n }, 1000);\n}\n\nfunction createSshSettler(\n state: SshExecutionState,\n options: ResolvedSshOptions,\n signal: AbortSignal | undefined,\n onAbort: () => void,\n resolve: (result: CfSshSignalResult) => void,\n reject: (reason?: unknown) => void,\n): (result: CfSshSignalResult) => void {\n return (result): void => {\n if (state.settled) {\n return;\n }\n state.settled = true;\n if (state.timeoutTimer !== undefined) {\n clearTimeout(state.timeoutTimer);\n }\n if (state.forceKillTimer !== undefined) {\n clearTimeout(state.forceKillTimer);\n }\n signal?.removeEventListener(\"abort\", onAbort);\n if (state.aborted) {\n reject(new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\"));\n return;\n }\n resolve(state.timedOut ? { ...result, timedOutAfterMs: options.timeoutMs } : result);\n };\n}\n\nfunction attachSshExecution(\n child: ChildProcessByStdio<null, Readable, Readable>,\n context: CfExecContext,\n options: ResolvedSshOptions,\n resolve: (result: CfSshSignalResult) => void,\n reject: (reason?: unknown) => void,\n): void {\n const state = createSshExecutionState();\n const onAbort = (): void => {\n state.aborted = true;\n terminateSshExecution(child, state);\n };\n const settle = createSshSettler(state, options, context.signal, onAbort, resolve, reject);\n state.timeoutTimer = setTimeout(() => {\n state.timedOut = true;\n terminateSshExecution(child, state);\n }, options.timeoutMs);\n if (context.signal?.aborted) {\n onAbort();\n } else {\n context.signal?.addEventListener(\"abort\", onAbort, { once: true });\n }\n child.stdout.on(\"data\", (data: Buffer | string) => {\n appendBounded(state.stdout, data, options.maxOutputBytes);\n });\n child.stderr.on(\"data\", (data: Buffer | string) => {\n appendBounded(state.stderr, data, options.maxOutputBytes);\n });\n child.on(\"close\", (code, signal) => {\n const base = createResult(code, state.stdout, state.stderr);\n settle(state.timedOut || signal === null ? base : { ...base, signal });\n });\n child.on(\"error\", (error: Error) => {\n appendBounded(state.stderr, error.message, options.maxOutputBytes);\n settle(createResult(null, state.stdout, state.stderr));\n });\n}\n\nfunction runSshOneShot(\n args: readonly string[],\n context: CfExecContext,\n options: ResolvedSshOptions,\n): Promise<CfSshSignalResult> {\n if (context.signal?.aborted) {\n return Promise.reject(new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\"));\n }\n return new Promise<CfSshSignalResult>((resolve, reject) => {\n const child = spawn(resolveBin(context), [...args], {\n env: buildEnv(context.cfHome),\n detached: process.platform !== \"win32\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n attachSshExecution(child, context, options, resolve, reject);\n });\n}\n\nfunction signalChild(child: ReturnType<typeof spawn>, signal: NodeJS.Signals): void {\n if (process.platform !== \"win32\" && child.pid !== undefined) {\n try {\n process.kill(-child.pid, signal);\n return;\n } catch {\n // The process may not have established its group before termination.\n }\n }\n try {\n child.kill(signal);\n } catch {\n // The child already exited between the termination request and signal.\n }\n}\n\nexport function isSshDisabledError(stderr: string): boolean {\n const lower = stderr.toLowerCase();\n return lower.includes(\"not authorized\") || lower.includes(\"ssh support is disabled\");\n}\n\nexport function spawnSshTunnel(\n appName: string,\n localPort: number,\n remotePort: number,\n context: CfExecContext,\n target: NodeTargetSelectors = {},\n): ReturnType<typeof spawn> {\n const tunnelArg = `${localPort.toString()}:localhost:${remotePort.toString()}`;\n const args = buildCfSshArgs(appName, target, [\"-N\", \"-L\", tunnelArg]);\n const child = spawn(resolveBin(context), [...args], {\n env: buildEnv(context.cfHome),\n detached: process.platform !== \"win32\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n child.stdout.resume();\n child.stderr.resume();\n return child;\n}\n","import { CfDebuggerError } from \"../types.js\";\n\nexport const DEFAULT_CF_PROCESS = \"web\";\nexport const DEFAULT_CF_INSTANCE = 0;\n\nconst MAX_MARKER_BYTES = 65_536;\nconst PID_LIST_PATTERN = /^\\d+(?:,\\d+)*$/;\nconst PID_PATTERN = /^\\d+$/;\n\nexport interface NodeTargetSelectors {\n readonly process?: string;\n readonly instance?: number;\n readonly nodePid?: number;\n}\n\nexport interface ResolvedNodeTarget {\n readonly process: string;\n readonly instance: number;\n readonly nodePid?: number;\n}\n\nexport interface NodeProcessSelection {\n readonly remoteNodePid: number;\n}\n\nfunction validateProcessName(processName: string): void {\n if (processName.length === 0 || processName.startsWith(\"-\") || hasControlCharacter(processName)) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n \"process must be non-empty, must not start with a hyphen, and must contain no control characters.\",\n );\n }\n}\n\nfunction validateInstance(instance: number): void {\n if (!Number.isSafeInteger(instance) || instance < 0) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"instance must be a non-negative safe integer.\");\n }\n}\n\nfunction validateNodePid(nodePid: number | undefined): void {\n if (nodePid !== undefined && (!Number.isSafeInteger(nodePid) || nodePid <= 0)) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"nodePid must be a positive safe integer.\");\n }\n}\n\nexport function resolveNodeTarget(input: NodeTargetSelectors): ResolvedNodeTarget {\n const processName = (input.process ?? DEFAULT_CF_PROCESS).trim();\n const instance = input.instance ?? DEFAULT_CF_INSTANCE;\n validateProcessName(processName);\n validateInstance(instance);\n validateNodePid(input.nodePid);\n return input.nodePid === undefined\n ? { process: processName, instance }\n : { process: processName, instance, nodePid: input.nodePid };\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code < 32 || code === 127) {\n return true;\n }\n }\n return false;\n}\n\nexport function buildNodeInspectorCommand(nodePid?: number): string {\n if (nodePid !== undefined && (!Number.isSafeInteger(nodePid) || nodePid <= 0)) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"nodePid must be a positive safe integer.\");\n }\n return NODE_INSPECTOR_SCRIPT.replace(\"__REQUESTED_NODE_PID__\", nodePid?.toString() ?? \"\");\n}\n\nexport function parseNodeInspectorMarkers(stdout: string): NodeProcessSelection {\n if (Buffer.byteLength(stdout, \"utf8\") > MAX_MARKER_BYTES) {\n throw new CfDebuggerError(\"INSPECTOR_OUTPUT_TOO_LARGE\", \"Inspector startup output exceeded 65536 bytes.\");\n }\n const markers = parseMarkers(stdout);\n throwForFailureMarker(markers);\n const remoteNodePid = readMarkerPid(markers, \"saptools-inspector-node-pid\");\n const ownerPid = readMarkerPid(markers, \"saptools-inspector-owner-pid\");\n if (!markers.has(\"saptools-inspector-ready\") || remoteNodePid === undefined || ownerPid !== remoteNodePid) {\n throw new CfDebuggerError(\"INSPECTOR_NOT_READY\", \"Remote Node inspector did not report a verified owner.\");\n }\n return { remoteNodePid };\n}\n\nfunction parseMarkers(stdout: string): ReadonlyMap<string, string> {\n const markers = new Map<string, string>();\n for (const rawLine of stdout.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line.startsWith(\"saptools-inspector-\")) {\n continue;\n }\n const separator = line.indexOf(\"=\");\n markers.set(separator < 0 ? line : line.slice(0, separator), separator < 0 ? \"\" : line.slice(separator + 1));\n }\n return markers;\n}\n\nfunction throwForFailureMarker(markers: ReadonlyMap<string, string>): void {\n if (markers.has(\"saptools-inspector-node-not-found\")) {\n throw new CfDebuggerError(\"NODE_PROCESS_NOT_FOUND\", \"No Node.js process was found in the selected CF instance.\");\n }\n const ambiguous = markers.get(\"saptools-inspector-node-ambiguous\");\n if (ambiguous !== undefined) {\n const candidates = PID_LIST_PATTERN.test(ambiguous) ? ambiguous.split(\",\").join(\", \") : \"unknown\";\n throw new CfDebuggerError(\"NODE_PROCESS_AMBIGUOUS\", `Multiple Node.js processes were found: ${candidates}. Pass nodePid explicitly.`);\n }\n const invalid = markers.get(\"saptools-inspector-node-invalid\");\n if (invalid !== undefined) {\n throw new CfDebuggerError(\"NODE_PID_INVALID\", `Remote PID ${safePidText(invalid)} is not a Node.js process.`);\n }\n throwForRuntimeFailure(markers);\n}\n\nfunction throwForRuntimeFailure(markers: ReadonlyMap<string, string>): void {\n const mismatch = markers.get(\"saptools-inspector-owner-mismatch\");\n if (mismatch !== undefined) {\n const [selected = \"unknown\", owner = \"unknown\"] = mismatch.split(\":\", 2).map(safePidText);\n throw new CfDebuggerError(\"INSPECTOR_OWNER_MISMATCH\", `Selected Node PID ${selected}, but inspector port 9229 is owned by PID ${owner}.`);\n }\n const signalFailed = markers.get(\"saptools-inspector-signal-failed\");\n if (signalFailed !== undefined) {\n throw new CfDebuggerError(\"USR1_SIGNAL_FAILED\", `Failed to signal remote Node PID ${safePidText(signalFailed)}.`);\n }\n if (markers.has(\"saptools-inspector-not-ready\")) {\n throw new CfDebuggerError(\"INSPECTOR_NOT_READY\", \"Remote Node inspector did not become ready on port 9229.\");\n }\n}\n\nfunction readMarkerPid(markers: ReadonlyMap<string, string>, name: string): number | undefined {\n const raw = markers.get(name);\n if (raw === undefined || !PID_PATTERN.test(raw)) {\n return undefined;\n }\n const value = Number.parseInt(raw, 10);\n return Number.isSafeInteger(value) && value > 0 ? value : undefined;\n}\n\nfunction safePidText(raw: string): string {\n return PID_PATTERN.test(raw) ? raw : \"unknown\";\n}\n\nconst NODE_INSPECTOR_SCRIPT = [\n \"requested_node_pid=__REQUESTED_NODE_PID__\",\n \"is_node_pid() {\",\n \" candidate_pid=\\\"$1\\\"\",\n \" candidate_exe=\\\"$(readlink \\\"/proc/$candidate_pid/exe\\\" 2>/dev/null || true)\\\"\",\n \" [ \\\"${candidate_exe##*/}\\\" = node ] || [ \\\"${candidate_exe##*/}\\\" = nodejs ]\",\n \"}\",\n \"find_inspector_owner() {\",\n \" socket_inode=\\\"$(awk '$2 ~ /:240D$/ && $4 == \\\"0A\\\" { print $10; exit }' /proc/net/tcp /proc/net/tcp6 2>/dev/null)\\\"\",\n \" [ -n \\\"$socket_inode\\\" ] || return 0\",\n \" for pid_dir in /proc/[0-9]*; do\",\n \" [ -d \\\"$pid_dir/fd\\\" ] || continue\",\n \" for fd_path in \\\"$pid_dir\\\"/fd/*; do\",\n \" fd_target=\\\"$(readlink \\\"$fd_path\\\" 2>/dev/null || true)\\\"\",\n \" if [ \\\"$fd_target\\\" = \\\"socket:[$socket_inode]\\\" ]; then\",\n \" printf '%s' \\\"${pid_dir##*/}\\\"\",\n \" return 0\",\n \" fi\",\n \" done\",\n \" done\",\n \"}\",\n \"owner_pid=\\\"$(find_inspector_owner)\\\"\",\n \"selected_pid=\\\"\\\"\",\n \"if [ -n \\\"$requested_node_pid\\\" ]; then\",\n \" if ! is_node_pid \\\"$requested_node_pid\\\"; then\",\n \" echo \\\"saptools-inspector-node-invalid=$requested_node_pid\\\"\",\n \" exit 0\",\n \" fi\",\n \" selected_pid=\\\"$requested_node_pid\\\"\",\n \"elif [ -n \\\"$owner_pid\\\" ] && is_node_pid \\\"$owner_pid\\\"; then\",\n \" selected_pid=\\\"$owner_pid\\\"\",\n \"else\",\n \" candidate_pids=\\\"\\\"\",\n \" candidate_count=0\",\n \" for pid_dir in /proc/[0-9]*; do\",\n \" candidate_pid=\\\"${pid_dir##*/}\\\"\",\n \" is_node_pid \\\"$candidate_pid\\\" || continue\",\n \" candidate_count=$((candidate_count + 1))\",\n \" candidate_pids=\\\"${candidate_pids}${candidate_pids:+,}$candidate_pid\\\"\",\n \" selected_pid=\\\"$candidate_pid\\\"\",\n \" done\",\n \" if [ \\\"$candidate_count\\\" -eq 0 ]; then echo saptools-inspector-node-not-found; exit 0; fi\",\n \" if [ \\\"$candidate_count\\\" -ne 1 ]; then echo \\\"saptools-inspector-node-ambiguous=$candidate_pids\\\"; exit 0; fi\",\n \"fi\",\n \"if [ -n \\\"$owner_pid\\\" ]; then\",\n \" if [ \\\"$owner_pid\\\" != \\\"$selected_pid\\\" ]; then echo \\\"saptools-inspector-owner-mismatch=$selected_pid:$owner_pid\\\"; exit 0; fi\",\n \" echo \\\"saptools-inspector-node-pid=$selected_pid\\\"\",\n \" echo \\\"saptools-inspector-owner-pid=$owner_pid\\\"\",\n \" echo saptools-inspector-ready\",\n \" exit 0\",\n \"fi\",\n \"if ! kill -USR1 \\\"$selected_pid\\\" 2>/dev/null; then echo \\\"saptools-inspector-signal-failed=$selected_pid\\\"; exit 0; fi\",\n \"attempt=0\",\n \"while [ \\\"$attempt\\\" -lt 20 ]; do\",\n \" owner_pid=\\\"$(find_inspector_owner)\\\"\",\n \" if [ -n \\\"$owner_pid\\\" ]; then\",\n \" if [ \\\"$owner_pid\\\" != \\\"$selected_pid\\\" ]; then echo \\\"saptools-inspector-owner-mismatch=$selected_pid:$owner_pid\\\"; exit 0; fi\",\n \" echo \\\"saptools-inspector-node-pid=$selected_pid\\\"\",\n \" echo \\\"saptools-inspector-owner-pid=$owner_pid\\\"\",\n \" echo saptools-inspector-ready\",\n \" exit 0\",\n \" fi\",\n \" attempt=$((attempt + 1))\",\n \" sleep 0.25\",\n \"done\",\n \"echo \\\"saptools-inspector-not-ready=$selected_pid\\\"\",\n].join(\"\\n\");\n","import type { ChildProcess } from \"node:child_process\";\nimport { chmod, mkdir, rm } from \"node:fs/promises\";\nimport process from \"node:process\";\n\nimport {\n cfEnableSsh,\n cfLogin,\n cfRestartApp,\n cfSshEnabled,\n cfSshOneShot,\n cfTarget,\n isSshDisabledError,\n spawnSshTunnel,\n type CfExecContext,\n} from \"../cf.js\";\nimport {\n buildNodeInspectorCommand,\n parseNodeInspectorMarkers,\n resolveNodeTarget,\n type ResolvedNodeTarget,\n} from \"../cloud-foundry/node-process.js\";\nimport { sessionCfHomeDir } from \"../paths.js\";\nimport {\n findListeningProcessId,\n isPortFree,\n isPortListening,\n probeTunnelReady,\n} from \"../port.js\";\nimport { resolveApiEndpoint } from \"../regions.js\";\nimport {\n registerNewSession,\n removeSession,\n sessionKeyString,\n updateSessionPid,\n updateSessionRemoteNodePid,\n updateSessionStatus,\n} from \"../state.js\";\nimport type { ActiveSession, DebuggerHandle, SessionStatus, StartDebuggerOptions } from \"../types.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nimport {\n DEFAULT_TUNNEL_READY_TIMEOUT_MS,\n POST_USR1_DELAY_MS,\n} from \"./constants.js\";\nimport { pruneAndCleanupOrphans } from \"./orphans.js\";\nimport { killProcessGroupOrProc } from \"./processes.js\";\nimport { createStartupCancellation } from \"./startup-cancellation.js\";\n\ntype StatusEmitter = (status: SessionStatus, message?: string) => void;\n\ninterface TunnelLifecycle {\n readonly exitPromise: Promise<number | null>;\n readonly finalize: () => Promise<void>;\n readonly observeChild: (child: ChildProcess) => void;\n}\n\ninterface StartupInputs {\n readonly options: StartDebuggerOptions;\n readonly target: ResolvedNodeTarget;\n readonly session: ActiveSession;\n readonly context: CfExecContext;\n readonly credentials: { readonly email: string; readonly password: string };\n readonly timeoutMs: number;\n readonly lifecycle: TunnelLifecycle;\n readonly emit: StatusEmitter;\n}\n\ntype SignalResult = Awaited<ReturnType<typeof cfSshOneShot>>;\n\nfunction signalFailureDetail(result: SignalResult): string {\n if (result.timedOutAfterMs !== undefined) {\n return `timed out after ${(result.timedOutAfterMs / 1000).toString()}s`;\n }\n const stderr = result.stderr.trim();\n if (stderr.length > 0) {\n return stderr;\n }\n if (result.signal !== undefined) {\n return `terminated by signal ${result.signal}`;\n }\n return `exit code ${String(result.exitCode)}`;\n}\n\nfunction checkAbort(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\");\n }\n}\n\nfunction requireStartupState(\n state: ActiveSession | undefined,\n expectedStatus?: SessionStatus,\n): ActiveSession {\n if (state === undefined) {\n throw new CfDebuggerError(\n \"SESSION_STATE_LOST\",\n \"Debugger session ownership state disappeared during startup.\",\n );\n }\n if (state.stopRequestedAt !== undefined || state.status === \"stopping\") {\n throw new CfDebuggerError(\"ABORTED\", \"Debugger session stop was requested during startup.\");\n }\n if (expectedStatus !== undefined && state.status !== expectedStatus) {\n throw new CfDebuggerError(\n \"SESSION_STATE_CONFLICT\",\n `Debugger session state did not transition to ${expectedStatus}.`,\n );\n }\n return state;\n}\n\nasync function transitionStartupStatus(\n sessionId: string,\n status: SessionStatus,\n message?: string,\n): Promise<ActiveSession> {\n return requireStartupState(await updateSessionStatus(sessionId, status, message), status);\n}\n\nfunction requireCredentials(options: StartDebuggerOptions): {\n readonly email: string;\n readonly password: string;\n} {\n const email = options.email ?? process.env[\"SAP_EMAIL\"];\n const password = options.password ?? process.env[\"SAP_PASSWORD\"];\n if (email === undefined || email === \"\") {\n throw new CfDebuggerError(\n \"MISSING_CREDENTIALS\",\n \"SAP email is required. Pass `email` or set SAP_EMAIL env var.\",\n );\n }\n if (password === undefined || password === \"\") {\n throw new CfDebuggerError(\n \"MISSING_CREDENTIALS\",\n \"SAP password is required. Pass `password` or set SAP_PASSWORD env var.\",\n );\n }\n return { email, password };\n}\n\nasync function registerSession(\n options: StartDebuggerOptions,\n target: ResolvedNodeTarget,\n apiEndpoint: string,\n): Promise<ActiveSession> {\n const registration = await registerNewSession({\n region: options.region,\n org: options.org,\n space: options.space,\n app: options.app,\n process: target.process,\n instance: target.instance,\n ...(target.nodePid === undefined ? {} : { nodePid: target.nodePid }),\n apiEndpoint,\n ...(options.preferredPort === undefined ? {} : { preferredPort: options.preferredPort }),\n portProbe: isPortFree,\n cfHomeForSession: sessionCfHomeDir,\n });\n\n if (registration.existing) {\n throw new CfDebuggerError(\n \"SESSION_ALREADY_RUNNING\",\n `A debugger session is already running for ${sessionKeyString(options)} ` +\n `on port ${registration.existing.localPort.toString()} ` +\n `(pid ${registration.existing.pid.toString()}, sessionId ${registration.existing.sessionId}). ` +\n `Stop it first with \\`cf-debugger stop\\`.`,\n );\n }\n return registration.session;\n}\n\nasync function loginAndTarget(\n options: StartDebuggerOptions,\n apiEndpoint: string,\n email: string,\n password: string,\n context: CfExecContext,\n sessionId: string,\n emit: StatusEmitter,\n): Promise<void> {\n emit(\"logging-in\");\n await transitionStartupStatus(sessionId, \"logging-in\");\n await cfLogin(apiEndpoint, email, password, context);\n checkAbort(context.signal);\n\n emit(\"targeting\");\n await transitionStartupStatus(sessionId, \"targeting\");\n await cfTarget(options.org, options.space, context);\n checkAbort(context.signal);\n}\n\nasync function signalRemoteNode(\n options: StartDebuggerOptions,\n target: ResolvedNodeTarget,\n context: CfExecContext,\n sessionId: string,\n emit: StatusEmitter,\n): Promise<number> {\n emit(\"signaling\");\n await transitionStartupStatus(sessionId, \"signaling\");\n const signalResult = await executeRemoteSignal(options.app, target, context);\n\n if (!isSshDisabledError(signalResult.stderr)) {\n return parseSignalResult(options.app, signalResult);\n }\n\n if (options.allowSshEnableRestart === false) {\n throw new CfDebuggerError(\n \"SSH_NOT_ENABLED\",\n `SSH is disabled for ${options.app}; automatic SSH enable and app restart are not allowed.`,\n signalResult.stderr,\n );\n }\n await enableSshAndRestart(options, target, context, sessionId, emit);\n return await retryRemoteSignal(options, target, context, sessionId, emit);\n}\n\nasync function enableSshAndRestart(\n options: StartDebuggerOptions,\n target: ResolvedNodeTarget,\n context: CfExecContext,\n sessionId: string,\n emit: StatusEmitter,\n): Promise<void> {\n if (target.nodePid !== undefined) {\n throw new CfDebuggerError(\n \"NODE_PID_RESTART_UNSAFE\",\n `Cannot automatically restart ${options.app} while targeting remote Node PID ` +\n `${target.nodePid.toString()}. Enable SSH and restart the app first, then retry with its new PID.`,\n );\n }\n\n const alreadyEnabled = await cfSshEnabled(options.app, context);\n if (!alreadyEnabled) {\n emit(\"ssh-enabling\", \"Enabling SSH on the app\");\n await transitionStartupStatus(sessionId, \"ssh-enabling\");\n await cfEnableSsh(options.app, context);\n }\n emit(\"ssh-restarting\", \"Restarting app so SSH becomes active\");\n await transitionStartupStatus(sessionId, \"ssh-restarting\");\n await cfRestartApp(options.app, context);\n checkAbort(context.signal);\n}\n\nasync function retryRemoteSignal(\n options: StartDebuggerOptions,\n target: ResolvedNodeTarget,\n context: CfExecContext,\n sessionId: string,\n emit: StatusEmitter,\n): Promise<number> {\n emit(\"signaling\");\n await transitionStartupStatus(sessionId, \"signaling\");\n const retrySignalResult = await executeRemoteSignal(options.app, target, context);\n if (retrySignalResult.exitCode === 0) {\n return parseSignalResult(options.app, retrySignalResult);\n }\n throw new CfDebuggerError(\n \"USR1_SIGNAL_FAILED\",\n `Failed to send SIGUSR1 to the Node.js process on ${options.app} after enabling SSH: ${\n signalFailureDetail(retrySignalResult)\n }`,\n retrySignalResult.stderr,\n );\n}\n\nasync function executeRemoteSignal(\n appName: string,\n target: ResolvedNodeTarget,\n context: CfExecContext,\n): Promise<SignalResult> {\n return await cfSshOneShot(appName, buildNodeInspectorCommand(target.nodePid), context, {\n process: target.process,\n instance: target.instance,\n });\n}\n\nfunction parseSignalResult(appName: string, result: SignalResult): number {\n if (result.exitCode !== 0) {\n throw new CfDebuggerError(\n \"USR1_SIGNAL_FAILED\",\n `Failed to send SIGUSR1 to the Node.js process on ${appName}: ${signalFailureDetail(result)}`,\n result.stderr,\n );\n }\n if (result.outputTruncated) {\n throw new CfDebuggerError(\n \"INSPECTOR_OUTPUT_TOO_LARGE\",\n \"Inspector startup output exceeded the configured capture limit.\",\n );\n }\n return parseNodeInspectorMarkers(result.stdout).remoteNodePid;\n}\n\nasync function waitAfterSignal(signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) {\n throw new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\");\n }\n await new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\"));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, POST_USR1_DELAY_MS);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nasync function ensurePortAvailable(localPort: number): Promise<void> {\n if (!(await isPortFree(localPort))) {\n throw new CfDebuggerError(\n \"PORT_UNAVAILABLE\",\n `Local port ${localPort.toString()} was taken before the tunnel could start.`,\n );\n }\n}\n\nasync function openReadyTunnel(\n options: StartDebuggerOptions,\n target: ResolvedNodeTarget,\n session: ActiveSession,\n context: CfExecContext,\n tunnelReadyTimeoutMs: number,\n onChild: (child: ChildProcess) => void,\n): Promise<void> {\n await ensurePortAvailable(session.localPort);\n checkAbort(context.signal);\n const child = spawnSshTunnel(options.app, session.localPort, session.remotePort, context, {\n process: target.process,\n instance: target.instance,\n });\n onChild(child);\n const childPid = child.pid;\n if (childPid === undefined) {\n throw new CfDebuggerError(\"TUNNEL_PROCESS_MISSING\", \"The CF SSH tunnel process did not expose a PID.\");\n }\n const pidState = requireStartupState(await updateSessionPid(session.sessionId, childPid));\n if (pidState.tunnelPid !== childPid || pidState.pid !== childPid) {\n throw new CfDebuggerError(\n \"SESSION_STATE_CONFLICT\",\n \"Debugger session did not retain ownership of the spawned tunnel process.\",\n );\n }\n\n const ready = await probeTunnelReady(\n session.localPort,\n tunnelReadyTimeoutMs,\n context.signal,\n );\n checkAbort(context.signal);\n if (!ready) {\n throw new CfDebuggerError(\n \"TUNNEL_NOT_READY\",\n `SSH tunnel on port ${session.localPort.toString()} did not become ready within ` +\n `${Math.round(tunnelReadyTimeoutMs / 1000).toString()}s.`,\n );\n }\n\n const listeningPid = await findListeningProcessId(session.localPort);\n if (listeningPid === undefined) {\n throw new CfDebuggerError(\n \"TUNNEL_OWNER_UNVERIFIED\",\n `Could not verify the owner of local tunnel port ${session.localPort.toString()}.`,\n );\n }\n if (listeningPid !== childPid) {\n throw new CfDebuggerError(\n \"TUNNEL_OWNER_MISMATCH\",\n `Local tunnel port ${session.localPort.toString()} is owned by an unexpected process.`,\n );\n }\n}\n\nfunction attachTunnelEvents(\n child: ChildProcess,\n resolveExit: (code: number | null) => void,\n emit: StatusEmitter,\n): void {\n child.on(\"close\", (code) => {\n resolveExit(code);\n });\n\n child.on(\"error\", (err: Error) => {\n emit(\"error\", err.message);\n });\n}\n\nfunction createHandle(\n session: ActiveSession,\n emit: StatusEmitter,\n finalize: () => Promise<void>,\n exitPromise: Promise<number | null>,\n): DebuggerHandle {\n let disposePromise: Promise<void> | undefined;\n return {\n session,\n dispose: async (): Promise<void> => {\n const attempt = disposePromise ?? (async (): Promise<void> => {\n await runCleanupActions([\n (): void => {\n emit(\"stopping\");\n },\n async (): Promise<void> => {\n await updateSessionStatus(session.sessionId, \"stopping\");\n },\n finalize,\n ], \"Debugger disposal failed\");\n })();\n disposePromise = attempt;\n try {\n await attempt;\n } catch (error: unknown) {\n if (disposePromise === attempt) {\n disposePromise = undefined;\n }\n throw error;\n }\n },\n waitForExit: async (): Promise<number | null> => {\n return await exitPromise;\n },\n };\n}\n\nasync function runCleanupActions(\n actions: readonly (() => void | Promise<void>)[],\n aggregateMessage: string,\n): Promise<void> {\n let errors: readonly unknown[] = [];\n for (const action of actions) {\n try {\n await action();\n } catch (error: unknown) {\n errors = [...errors, error];\n }\n }\n if (errors.length === 1) {\n throw errors[0];\n }\n if (errors.length > 1) {\n throw new AggregateError(errors, aggregateMessage);\n }\n}\n\nasync function prepareCfHome(cfHomeDir: string): Promise<void> {\n await mkdir(cfHomeDir, { recursive: true, mode: 0o700 });\n await chmod(cfHomeDir, 0o700);\n}\n\nfunction createTunnelLifecycle(session: ActiveSession, emit: StatusEmitter): TunnelLifecycle {\n let child: ChildProcess | undefined;\n let exitResolve: (code: number | null) => void = (_code) => {\n throw new Error(\"Exit resolver was used before initialization\");\n };\n const exitPromise = new Promise<number | null>((resolve) => {\n exitResolve = resolve;\n });\n const observeChild = (tunnelChild: ChildProcess): void => {\n child = tunnelChild;\n attachTunnelEvents(tunnelChild, exitResolve, emit);\n };\n const finalize = async (): Promise<void> => {\n const termination = child === undefined\n ? \"terminated\"\n : await killProcessGroupOrProc(child);\n const portListening = child !== undefined && await isPortListening(session.localPort);\n if (termination === \"still-alive\" || portListening) {\n throw new CfDebuggerError(\n \"TUNNEL_TERMINATION_FAILED\",\n `Tunnel for session ${session.sessionId} did not terminate; state and CF home were retained.`,\n );\n }\n await runCleanupActions([\n async (): Promise<void> => {\n await removeSession(session.sessionId);\n },\n async (): Promise<void> => {\n await cleanupFilesystem(session.cfHomeDir);\n },\n ], \"Debugger resource cleanup failed\");\n emit(\"stopped\");\n };\n return { exitPromise, finalize, observeChild };\n}\n\nasync function establishDebuggerSession(inputs: StartupInputs): Promise<ActiveSession> {\n const { options, target, session, context, credentials, timeoutMs, lifecycle, emit } = inputs;\n await prepareCfHome(session.cfHomeDir);\n await loginAndTarget(\n options,\n session.apiEndpoint,\n credentials.email,\n credentials.password,\n context,\n session.sessionId,\n emit,\n );\n await ensurePortAvailable(session.localPort);\n const remoteNodePid = await signalRemoteNode(options, target, context, session.sessionId, emit);\n const remoteState = requireStartupState(\n await updateSessionRemoteNodePid(session.sessionId, remoteNodePid),\n );\n if (remoteState.remoteNodePid !== remoteNodePid) {\n throw new CfDebuggerError(\n \"SESSION_STATE_CONFLICT\",\n \"Debugger session did not retain the selected remote Node PID.\",\n );\n }\n await waitAfterSignal(context.signal);\n\n emit(\"tunneling\");\n await transitionStartupStatus(session.sessionId, \"tunneling\");\n await openReadyTunnel(\n options, target, session, context, timeoutMs, lifecycle.observeChild,\n );\n emit(\"ready\");\n return await transitionStartupStatus(session.sessionId, \"ready\");\n}\n\nasync function failAfterStartupCleanup(\n error: unknown,\n finalize: () => Promise<void>,\n emit: StatusEmitter,\n): Promise<never> {\n try {\n await runCleanupActions([\n (): void => {\n emit(\"error\", error instanceof Error ? error.message : String(error));\n },\n finalize,\n ], \"Debugger startup failure reporting and cleanup failed\");\n } catch (cleanupError: unknown) {\n throw new AggregateError(\n [error, cleanupError],\n \"Debugger startup failed and resource cleanup was incomplete\",\n { cause: cleanupError },\n );\n }\n throw error;\n}\n\nexport async function startDebugger(options: StartDebuggerOptions): Promise<DebuggerHandle> {\n const target = resolveNodeTarget(options);\n const credentials = requireCredentials(options);\n const apiEndpoint = resolveApiEndpoint(options.region, options.apiEndpoint);\n const tunnelReadyTimeoutMs = options.tunnelReadyTimeoutMs ?? DEFAULT_TUNNEL_READY_TIMEOUT_MS;\n const emit = (status: SessionStatus, message?: string): void => {\n options.onStatus?.(status, message);\n };\n\n checkAbort(options.signal);\n await pruneAndCleanupOrphans();\n\n const session = await registerSession(options, target, apiEndpoint);\n const cancellation = createStartupCancellation(session.sessionId, options.signal);\n const context: CfExecContext = {\n cfHome: session.cfHomeDir,\n signal: cancellation.signal,\n };\n const lifecycle = createTunnelLifecycle(session, emit);\n\n try {\n const activeSession = await establishDebuggerSession({\n options,\n target,\n session,\n context,\n credentials,\n timeoutMs: tunnelReadyTimeoutMs,\n lifecycle,\n emit,\n });\n cancellation.dispose();\n return createHandle(activeSession, emit, lifecycle.finalize, lifecycle.exitPromise);\n } catch (err: unknown) {\n cancellation.dispose();\n return await failAfterStartupCleanup(err, lifecycle.finalize, emit);\n }\n}\n\nasync function cleanupFilesystem(cfHomeDir: string): Promise<void> {\n await rm(cfHomeDir, { recursive: true, force: true });\n}\n","import { homedir } from \"node:os\";\nimport { isAbsolute, join } from \"node:path\";\n\nexport const SAPTOOLS_DIR_NAME = \".saptools\";\nexport const CF_DEBUGGER_STATE_FILENAME = \"cf-debugger-state-v2.json\";\nexport const CF_DEBUGGER_LOCK_FILENAME = \"cf-debugger-state-v2.lock\";\nexport const CF_DEBUGGER_HOMES_DIRNAME = \"cf-debugger-homes-v2\";\nconst SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\n\nexport function saptoolsDir(): string {\n return join(homedir(), SAPTOOLS_DIR_NAME);\n}\n\nexport function stateFilePath(): string {\n return join(saptoolsDir(), CF_DEBUGGER_STATE_FILENAME);\n}\n\nexport function stateLockPath(): string {\n return join(saptoolsDir(), CF_DEBUGGER_LOCK_FILENAME);\n}\n\nexport function isSafeSessionId(sessionId: string): boolean {\n return SESSION_ID_PATTERN.test(sessionId);\n}\n\nexport function sessionCfHomeDir(sessionId: string): string {\n if (!isSafeSessionId(sessionId)) {\n throw new Error(\"Invalid debugger session ID.\");\n }\n return join(saptoolsDir(), CF_DEBUGGER_HOMES_DIRNAME, sessionId);\n}\n\nexport function isOwnedSessionCfHomeDir(sessionId: string, candidate: string): boolean {\n if (!isSafeSessionId(sessionId) || !isAbsolute(candidate)) {\n return false;\n }\n return candidate === sessionCfHomeDir(sessionId);\n}\n","import { execFile } from \"node:child_process\";\nimport { readdir, readFile, readlink } from \"node:fs/promises\";\nimport { createConnection, createServer } from \"node:net\";\nimport { promisify } from \"node:util\";\n\nimport { CfDebuggerError } from \"../types.js\";\n\nconst execFileAsync = promisify(execFile);\n\nasync function findListeningPidsWithNetstat(port: number): Promise<readonly number[]> {\n try {\n const { stdout } = await execFileAsync(\"netstat\", [\"-ano\"]);\n const pids = new Set<number>();\n for (const line of stdout.split(\"\\n\")) {\n if (!line.includes(`:${port.toString()}`) || !line.includes(\"LISTENING\")) {\n continue;\n }\n const parts = line.trim().split(/\\s+/);\n const last = parts[parts.length - 1];\n if (last === undefined) {\n continue;\n }\n const pid = Number.parseInt(last, 10);\n if (!Number.isNaN(pid)) {\n pids.add(pid);\n }\n }\n return [...pids];\n } catch {\n return [];\n }\n}\n\nasync function findListeningPidsWithLsof(port: number): Promise<readonly number[]> {\n try {\n const { stdout } = await execFileAsync(\"lsof\", [\"-nP\", \"-t\", \"-i\", `tcp:${port.toString()}`, \"-sTCP:LISTEN\"]);\n return stdout\n .trim()\n .split(\"\\n\")\n .filter((line) => line.length > 0)\n .map((line) => Number.parseInt(line, 10))\n .filter((pid) => !Number.isNaN(pid));\n } catch {\n return [];\n }\n}\n\nasync function findListeningPidsWithProc(port: number): Promise<readonly number[]> {\n const inodes = await findListeningSocketInodesWithProc(port);\n if (inodes.size === 0) {\n return [];\n }\n\n try {\n const entries = await readdir(\"/proc\", { withFileTypes: true });\n const pids = new Set<number>();\n for (const entry of entries) {\n if (!entry.isDirectory() || !/^\\d+$/.test(entry.name)) {\n continue;\n }\n if (await processHasSocketInode(entry.name, inodes)) {\n pids.add(Number.parseInt(entry.name, 10));\n }\n }\n return [...pids];\n } catch {\n return [];\n }\n}\n\nasync function findListeningSocketInodesWithProc(port: number): Promise<ReadonlySet<string>> {\n const inodes = new Set<string>();\n await collectListeningSocketInodes(\"/proc/net/tcp\", port, inodes);\n await collectListeningSocketInodes(\"/proc/net/tcp6\", port, inodes);\n return inodes;\n}\n\nasync function collectListeningSocketInodes(\n path: string,\n port: number,\n inodes: Set<string>,\n): Promise<void> {\n try {\n const content = await readFile(path, \"utf8\");\n for (const line of content.split(\"\\n\").slice(1)) {\n const fields = line.trim().split(/\\s+/);\n const localAddress = fields[1];\n const state = fields[3];\n const inode = fields[9];\n if (localAddress === undefined || state === undefined || inode === undefined) {\n continue;\n }\n const localPort = Number.parseInt(localAddress.split(\":\")[1] ?? \"\", 16);\n if (localPort === port && state === \"0A\") {\n inodes.add(inode);\n }\n }\n } catch {\n // /proc/net/tcp* is Linux-specific; callers fall back to other strategies.\n }\n}\n\nasync function processHasSocketInode(pid: string, inodes: ReadonlySet<string>): Promise<boolean> {\n try {\n const descriptors = await readdir(`/proc/${pid}/fd`);\n for (const descriptor of descriptors) {\n try {\n const link = await readlink(`/proc/${pid}/fd/${descriptor}`);\n const match = /^socket:\\[(\\d+)\\]$/.exec(link);\n if (match?.[1] !== undefined && inodes.has(match[1])) {\n return true;\n }\n } catch {\n // The process may close descriptors while we scan them.\n }\n }\n } catch {\n // The process may exit, or permissions may prevent fd inspection.\n }\n return false;\n}\n\nasync function findListeningPids(port: number): Promise<readonly number[]> {\n if (process.platform === \"win32\") {\n return await findListeningPidsWithNetstat(port);\n }\n const lsofPids = await findListeningPidsWithLsof(port);\n return lsofPids.length > 0 ? lsofPids : await findListeningPidsWithProc(port);\n}\n\nexport async function isPortFree(port: number): Promise<boolean> {\n return await new Promise<boolean>((resolve) => {\n const server = createServer();\n server.once(\"error\", () => {\n resolve(false);\n });\n server.once(\"listening\", () => {\n server.close(() => {\n resolve(true);\n });\n });\n server.listen(port, \"127.0.0.1\");\n });\n}\n\nexport async function isPortListening(port: number, timeoutMs = 200): Promise<boolean> {\n return await new Promise<boolean>((resolve) => {\n const socket = createConnection({ port, host: \"127.0.0.1\" });\n socket.setTimeout(timeoutMs);\n socket.once(\"connect\", () => {\n socket.destroy();\n resolve(true);\n });\n socket.once(\"error\", () => {\n socket.destroy();\n resolve(false);\n });\n socket.once(\"timeout\", () => {\n socket.destroy();\n resolve(false);\n });\n });\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\");\n }\n}\n\nfunction waitForNextProbe(delayMs: number, signal: AbortSignal | undefined): Promise<void> {\n throwIfAborted(signal);\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\"));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, delayMs);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nexport async function probeTunnelReady(\n port: number,\n timeoutMs: number,\n signal?: AbortSignal,\n): Promise<boolean> {\n const pollIntervalMs = 250;\n const started = Date.now();\n throwIfAborted(signal);\n\n while (Date.now() - started < timeoutMs) {\n const connected = await isPortListening(port);\n if (connected) {\n return true;\n }\n const remainingMs = timeoutMs - (Date.now() - started);\n await waitForNextProbe(Math.min(pollIntervalMs, Math.max(0, remainingMs)), signal);\n }\n\n throwIfAborted(signal);\n return false;\n}\n\nexport async function findListeningProcessId(port: number): Promise<number | undefined> {\n const pids = await findListeningPids(port);\n return pids[0];\n}\n","import { randomUUID } from \"node:crypto\";\nimport { chmod, mkdir, readFile, rename, unlink, writeFile } from \"node:fs/promises\";\nimport { hostname as getHostname } from \"node:os\";\nimport { dirname, isAbsolute } from \"node:path\";\nimport process from \"node:process\";\n\nimport { resolveNodeTarget } from \"../cloud-foundry/node-process.js\";\nimport { withFileLock } from \"../lock.js\";\nimport { isSafeSessionId, stateFilePath, stateLockPath } from \"../paths.js\";\nimport { isPortListening } from \"../port.js\";\nimport { CfDebuggerError } from \"../types.js\";\nimport type { ActiveSession, SessionKey, StateFile } from \"../types.js\";\n\nimport { decodeStateFile } from \"./decoder.js\";\n\nfunction errorCode(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null) {\n return undefined;\n }\n const code: unknown = Reflect.get(error, \"code\");\n return typeof code === \"string\" ? code : undefined;\n}\n\nasync function readJsonFile(path: string): Promise<unknown> {\n let raw: string;\n try {\n await chmod(path, 0o600);\n raw = await readFile(path, \"utf8\");\n } catch (err: unknown) {\n if (errorCode(err) === \"ENOENT\") {\n return undefined;\n }\n throw err;\n }\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n process.stderr.write(\n `[cf-debugger] warning: state file at ${path} is not valid JSON; resetting to empty.\\n`,\n );\n return undefined;\n }\n}\n\nasync function writeJsonFileAtomic(path: string, value: unknown): Promise<void> {\n const tempPath = `${path}.${randomUUID()}.tmp`;\n const parentDir = dirname(path);\n await mkdir(parentDir, { recursive: true, mode: 0o700 });\n await chmod(parentDir, 0o700);\n let renamed = false;\n try {\n await writeFile(tempPath, `${JSON.stringify(value, null, 2)}\\n`, {\n encoding: \"utf8\",\n flag: \"wx\",\n mode: 0o600,\n });\n await rename(tempPath, path);\n renamed = true;\n await chmod(path, 0o600);\n } finally {\n if (!renamed) {\n await unlink(tempPath).catch(() => false);\n }\n }\n}\n\nfunction emptyState(): StateFile {\n return { version: \"2\", sessions: [] };\n}\n\nexport function isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err: unknown) {\n if (errorCode(err) === \"ESRCH\") {\n return false;\n }\n return true;\n }\n}\n\nexport function isPidOrGroupAlive(pid: number): boolean {\n if (isPidAlive(pid)) {\n return true;\n }\n return isProcessGroupAlive(pid);\n}\n\nexport function isProcessGroupAlive(pid: number): boolean {\n return process.platform !== \"win32\" && isPidAlive(-pid);\n}\n\nasync function isSessionHealthy(session: ActiveSession, host: string): Promise<boolean> {\n if (session.hostname !== host) {\n return false;\n }\n if (session.status !== \"ready\" && isPidAlive(session.controllerPid ?? session.pid)) {\n return true;\n }\n if (session.tunnelPid !== undefined && isPidOrGroupAlive(session.tunnelPid)) {\n return true;\n }\n return await isPortListening(session.localPort);\n}\n\nasync function filterStaleSessions(\n sessions: readonly ActiveSession[],\n): Promise<readonly ActiveSession[]> {\n const host = getHostname();\n const checks = await Promise.all(\n sessions.map(async (session): Promise<readonly [ActiveSession, boolean]> => [\n session,\n await isSessionHealthy(session, host),\n ]),\n );\n return checks.filter(([, healthy]) => healthy).map(([session]) => session);\n}\n\nasync function readStateRaw(): Promise<StateFile> {\n const path = stateFilePath();\n const parsed = await readJsonFile(path);\n if (parsed === undefined) {\n return emptyState();\n }\n const decoded = decodeStateFile(parsed);\n if (decoded !== undefined) {\n return decoded;\n }\n process.stderr.write(\n `[cf-debugger] warning: state file at ${path} has an invalid structure; resetting to empty.\\n`,\n );\n return emptyState();\n}\n\nasync function writeState(state: StateFile): Promise<void> {\n await writeJsonFileAtomic(stateFilePath(), state);\n}\n\nexport interface StateReaderResult {\n readonly sessions: readonly ActiveSession[];\n readonly removed: readonly ActiveSession[];\n}\n\nasync function readAndPruneLocked(): Promise<StateReaderResult> {\n const raw = await readStateRaw();\n const host = getHostname();\n const remote = raw.sessions.filter((session) => session.hostname !== host);\n const local = raw.sessions.filter((session) => session.hostname === host);\n const pruned = await filterStaleSessions(local);\n const removed = local.filter(\n (session) => !pruned.some((active) => active.sessionId === session.sessionId),\n );\n\n if (removed.length > 0) {\n await writeState({ version: \"2\", sessions: [...remote, ...pruned] });\n }\n\n return { sessions: pruned, removed };\n}\n\nexport async function readActiveSessions(): Promise<readonly ActiveSession[]> {\n const result = await withFileLock(stateLockPath(), readAndPruneLocked);\n return result.sessions;\n}\n\nexport async function readSessionSnapshot(): Promise<readonly ActiveSession[]> {\n return await withFileLock(stateLockPath(), async (): Promise<readonly ActiveSession[]> => {\n const raw = await readStateRaw();\n return raw.sessions;\n });\n}\n\nexport async function readAndPruneActiveSessions(): Promise<StateReaderResult> {\n return await withFileLock(stateLockPath(), readAndPruneLocked);\n}\n\nexport function sessionKeyString(key: SessionKey): string {\n const base = `${key.region}:${key.org}:${key.space}:${key.app}`;\n if (key.process === undefined && key.instance === undefined) {\n return base;\n }\n const target = resolveNodeTarget(key);\n return `${base}:${target.process}:${target.instance.toString()}`;\n}\n\nexport function matchesKey(session: SessionKey, key: SessionKey): boolean {\n const sessionTarget = resolveNodeTarget(session);\n const keyTarget = resolveNodeTarget(key);\n return (\n session.region === key.region &&\n session.org === key.org &&\n session.space === key.space &&\n session.app === key.app &&\n sessionTarget.process === keyTarget.process &&\n sessionTarget.instance === keyTarget.instance &&\n (key.apiEndpoint === undefined || session.apiEndpoint === key.apiEndpoint) &&\n (key.nodePid === undefined || sessionTarget.nodePid === keyTarget.nodePid)\n );\n}\n\nfunction matchesRegistrationTarget(\n session: ActiveSession,\n input: RegisterSessionInput,\n target: ReturnType<typeof resolveNodeTarget>,\n): boolean {\n return matchesKey(session, {\n region: input.region,\n org: input.org,\n space: input.space,\n app: input.app,\n process: target.process,\n instance: target.instance,\n apiEndpoint: input.apiEndpoint,\n });\n}\n\nexport interface RegisterSessionResult {\n readonly session: ActiveSession;\n readonly existing?: ActiveSession;\n}\n\nexport interface RegisterSessionInput extends SessionKey {\n readonly apiEndpoint: string;\n readonly preferredPort?: number;\n readonly portProbe: (port: number) => Promise<boolean>;\n readonly sessionIdFactory?: () => string;\n readonly cfHomeForSession: (sessionId: string) => string;\n readonly basePort?: number;\n readonly maxPort?: number;\n}\n\nconst DEFAULT_BASE_PORT = 20_000;\nconst DEFAULT_MAX_PORT = 20_999;\n\nasync function pickPort(\n preferred: number | undefined,\n reserved: ReadonlySet<number>,\n probe: (port: number) => Promise<boolean>,\n basePort: number,\n maxPort: number,\n): Promise<number> {\n const tryOrder: number[] = [];\n if (preferred !== undefined) {\n tryOrder.push(preferred);\n }\n for (let port = basePort; port <= maxPort; port++) {\n if (port !== preferred) {\n tryOrder.push(port);\n }\n }\n\n for (const port of tryOrder) {\n if (reserved.has(port)) {\n continue;\n }\n const free = await probe(port);\n if (free) {\n return port;\n }\n }\n throw new CfDebuggerError(\n \"PORT_UNAVAILABLE\",\n `No free local port available in range ${basePort.toString()}–${maxPort.toString()}`,\n );\n}\n\nexport async function registerNewSession(\n input: RegisterSessionInput,\n): Promise<RegisterSessionResult> {\n const target = resolveNodeTarget(input);\n return await withFileLock(stateLockPath(), async (): Promise<RegisterSessionResult> => {\n const pruneResult = await readAndPruneLocked();\n const persisted = await readStateRaw();\n const host = getHostname();\n const remoteSessions = persisted.sessions.filter((session) => session.hostname !== host);\n const existing = pruneResult.sessions.find((session) => matchesRegistrationTarget(session, input, target));\n if (existing) {\n return { session: existing, existing };\n }\n\n const reservedPorts = new Set(pruneResult.sessions.map((session) => session.localPort));\n const localPort = await pickPort(\n input.preferredPort,\n reservedPorts,\n input.portProbe,\n input.basePort ?? DEFAULT_BASE_PORT,\n input.maxPort ?? DEFAULT_MAX_PORT,\n );\n\n const session = createRegisteredSession(input, target, localPort);\n\n const nextSessions: readonly ActiveSession[] = [...remoteSessions, ...pruneResult.sessions, session];\n await writeState({ version: \"2\", sessions: nextSessions });\n\n return { session };\n });\n}\n\nfunction createRegisteredSession(\n input: RegisterSessionInput,\n target: ReturnType<typeof resolveNodeTarget>,\n localPort: number,\n): ActiveSession {\n const sessionId = (input.sessionIdFactory ?? randomUUID)();\n if (!isSafeSessionId(sessionId)) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Generated debugger session ID is invalid.\");\n }\n const cfHomeDir = input.cfHomeForSession(sessionId);\n if (!isAbsolute(cfHomeDir)) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Debugger CF home must be an absolute path.\");\n }\n return {\n sessionId,\n pid: process.pid,\n controllerPid: process.pid,\n hostname: getHostname(),\n region: input.region,\n org: input.org,\n space: input.space,\n app: input.app,\n process: target.process,\n instance: target.instance,\n ...(target.nodePid === undefined ? {} : { nodePid: target.nodePid }),\n apiEndpoint: input.apiEndpoint,\n localPort,\n remotePort: 9229,\n cfHomeDir,\n startedAt: new Date().toISOString(),\n status: \"starting\",\n };\n}\n\nexport async function updateSessionStatus(\n sessionId: string,\n status: ActiveSession[\"status\"],\n message?: string,\n): Promise<ActiveSession | undefined> {\n return await withFileLock(stateLockPath(), async (): Promise<ActiveSession | undefined> => {\n const raw = await readStateRaw();\n let updated: ActiveSession | undefined;\n const nextSessions = raw.sessions.map((session): ActiveSession => {\n if (session.sessionId !== sessionId) {\n return session;\n }\n if (status !== \"stopping\" && startupMutationBlocked(session)) {\n updated = session;\n return session;\n }\n if (status === \"ready\" && session.tunnelPid === undefined) {\n throw new CfDebuggerError(\n \"SESSION_STATE_CONFLICT\",\n \"A debugger session cannot become ready before its tunnel PID is recorded.\",\n );\n }\n const base = withoutMessage(session);\n const next: ActiveSession = message === undefined\n ? { ...base, status }\n : { ...base, status, message };\n updated = next;\n return next;\n });\n\n if (updated) {\n await writeState({ version: \"2\", sessions: nextSessions });\n }\n return updated;\n });\n}\n\nexport async function updateSessionPid(\n sessionId: string,\n pid: number,\n): Promise<ActiveSession | undefined> {\n if (!Number.isSafeInteger(pid) || pid <= 0) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Tunnel PID must be a positive safe integer.\");\n }\n return await withFileLock(stateLockPath(), async (): Promise<ActiveSession | undefined> => {\n const raw = await readStateRaw();\n let updated: ActiveSession | undefined;\n const nextSessions = raw.sessions.map((session): ActiveSession => {\n if (session.sessionId !== sessionId) {\n return session;\n }\n if (startupMutationBlocked(session)) {\n updated = session;\n return session;\n }\n const next: ActiveSession = { ...session, pid, tunnelPid: pid };\n updated = next;\n return next;\n });\n\n if (updated !== undefined) {\n await writeState({ version: \"2\", sessions: nextSessions });\n }\n return updated;\n });\n}\n\nfunction withoutMessage(session: ActiveSession): ActiveSession {\n const { message, ...clone } = session;\n void message;\n return clone;\n}\n\nfunction startupMutationBlocked(session: ActiveSession): boolean {\n return session.status === \"stopping\" || session.stopRequestedAt !== undefined;\n}\n\nexport async function updateSessionRemoteNodePid(\n sessionId: string,\n remoteNodePid: number,\n): Promise<ActiveSession | undefined> {\n resolveNodeTarget({ nodePid: remoteNodePid });\n return await withFileLock(stateLockPath(), async (): Promise<ActiveSession | undefined> => {\n const raw = await readStateRaw();\n let updated: ActiveSession | undefined;\n const nextSessions = raw.sessions.map((session): ActiveSession => {\n if (session.sessionId !== sessionId) {\n return session;\n }\n if (startupMutationBlocked(session)) {\n updated = session;\n return session;\n }\n const next: ActiveSession = { ...session, remoteNodePid };\n updated = next;\n return next;\n });\n if (updated !== undefined) {\n await writeState({ version: \"2\", sessions: nextSessions });\n }\n return updated;\n });\n}\n\nexport async function removeSession(sessionId: string): Promise<ActiveSession | undefined> {\n return await withFileLock(stateLockPath(), async (): Promise<ActiveSession | undefined> => {\n const raw = await readStateRaw();\n const target = raw.sessions.find((session) => session.sessionId === sessionId);\n if (!target) {\n return undefined;\n }\n const remaining = raw.sessions.filter((session) => session.sessionId !== sessionId);\n await writeState({ version: \"2\", sessions: remaining });\n return target;\n });\n}\n\nexport interface SessionStopClaim {\n readonly session: ActiveSession;\n readonly previousStatus: ActiveSession[\"status\"];\n}\n\nexport async function requestSessionStop(sessionId: string): Promise<SessionStopClaim | undefined> {\n return await withFileLock(stateLockPath(), async (): Promise<SessionStopClaim | undefined> => {\n const raw = await readStateRaw();\n const target = raw.sessions.find((session) => session.sessionId === sessionId);\n if (target === undefined) {\n return undefined;\n }\n if (target.status === \"ready\" || target.stopRequestedAt !== undefined) {\n return { session: target, previousStatus: target.status };\n }\n const requested: ActiveSession = { ...target, stopRequestedAt: new Date().toISOString() };\n const sessions = raw.sessions.map((session) =>\n session.sessionId === sessionId ? requested : session\n );\n await writeState({ version: \"2\", sessions });\n return { session: requested, previousStatus: target.status };\n });\n}\n","import { randomUUID } from \"node:crypto\";\nimport { chmod, mkdir, open, readFile, stat, unlink } from \"node:fs/promises\";\nimport type { FileHandle } from \"node:fs/promises\";\nimport { hostname } from \"node:os\";\nimport { dirname } from \"node:path\";\nimport process from \"node:process\";\n\nconst DEFAULT_POLL_MS = 50;\nconst DEFAULT_STALE_MS = 60_000;\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\ninterface FileLock {\n readonly handle: FileHandle;\n readonly token: string;\n}\n\ninterface LockOwner {\n readonly hostname: string;\n readonly pid: number;\n readonly token: string;\n readonly version: \"1\";\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise<void>((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction errorCode(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null) {\n return undefined;\n }\n const code: unknown = Reflect.get(error, \"code\");\n return typeof code === \"string\" ? code : undefined;\n}\n\nfunction field(value: object, key: string): unknown {\n return Reflect.get(value, key);\n}\n\nfunction parseLockOwner(raw: string): LockOwner | undefined {\n let value: unknown;\n try {\n value = JSON.parse(raw) as unknown;\n } catch {\n return undefined;\n }\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n const lockHostname = field(value, \"hostname\");\n const pid = field(value, \"pid\");\n const token = field(value, \"token\");\n const version = field(value, \"version\");\n if (typeof lockHostname !== \"string\" || typeof pid !== \"number\" || !Number.isSafeInteger(pid) || pid <= 0) {\n return undefined;\n }\n if (typeof token !== \"string\" || version !== \"1\") {\n return undefined;\n }\n return { hostname: lockHostname, pid, token, version };\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error: unknown) {\n return errorCode(error) !== \"ESRCH\";\n }\n}\n\nasync function readLockOwner(lockPath: string): Promise<LockOwner | undefined> {\n try {\n await chmod(lockPath, 0o600);\n return parseLockOwner(await readFile(lockPath, \"utf8\"));\n } catch (error: unknown) {\n if (errorCode(error) === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n\nasync function isStaleLock(lockPath: string, staleMs: number): Promise<boolean> {\n let modifiedAt: number;\n try {\n modifiedAt = (await stat(lockPath)).mtimeMs;\n } catch (error: unknown) {\n if (errorCode(error) === \"ENOENT\") {\n return true;\n }\n throw error;\n }\n const owner = await readLockOwner(lockPath);\n if (owner?.hostname === hostname()) {\n return !isProcessAlive(owner.pid);\n }\n return owner === undefined && Date.now() - modifiedAt > staleMs;\n}\n\nasync function reclaimAbandonedRecoveryLock(\n recoveryPath: string,\n staleMs: number,\n): Promise<void> {\n if (!(await isStaleLock(recoveryPath, staleMs))) {\n return;\n }\n const owner = await readLockOwner(recoveryPath);\n if (owner !== undefined) {\n await removeOwnedLock(recoveryPath, owner.token);\n return;\n }\n await unlink(recoveryPath).catch((error: unknown) => {\n if (errorCode(error) !== \"ENOENT\") {\n throw error;\n }\n });\n}\n\nasync function reclaimStaleLock(lockPath: string, staleMs: number): Promise<boolean> {\n const recoveryPath = `${lockPath}.recovery`;\n let recoveryLock: FileLock;\n try {\n recoveryLock = await createFileLock(recoveryPath);\n } catch (error: unknown) {\n if (errorCode(error) === \"EEXIST\") {\n await reclaimAbandonedRecoveryLock(recoveryPath, staleMs);\n return false;\n }\n throw error;\n }\n try {\n if (!(await isStaleLock(lockPath, staleMs))) {\n return false;\n }\n try {\n await unlink(lockPath);\n } catch (error: unknown) {\n if (errorCode(error) !== \"ENOENT\") {\n throw error;\n }\n }\n return true;\n } finally {\n await releaseFileLock(recoveryPath, recoveryLock);\n }\n}\n\nasync function removeOwnedLock(lockPath: string, token: string): Promise<void> {\n const owner = await readLockOwner(lockPath);\n if (owner?.token !== token) {\n return;\n }\n await unlink(lockPath).catch((error: unknown) => {\n if (errorCode(error) !== \"ENOENT\") {\n throw error;\n }\n });\n}\n\nasync function createFileLock(lockPath: string): Promise<FileLock> {\n const handle = await open(lockPath, \"wx\", 0o600);\n const token = randomUUID();\n try {\n await handle.writeFile(`${JSON.stringify({ hostname: hostname(), pid: process.pid, token, version: \"1\" })}\\n`, \"utf8\");\n return { handle, token };\n } catch (error: unknown) {\n await handle.close();\n await unlink(lockPath).catch(() => false);\n throw error;\n }\n}\n\nasync function acquireFileLock(\n lockPath: string,\n timeoutMs: number,\n pollMs: number,\n staleMs: number,\n): Promise<FileLock> {\n const deadline = Date.now() + timeoutMs;\n const parentDir = dirname(lockPath);\n await mkdir(parentDir, { recursive: true, mode: 0o700 });\n await chmod(parentDir, 0o700);\n\n for (;;) {\n try {\n return await createFileLock(lockPath);\n } catch (error: unknown) {\n if (errorCode(error) !== \"EEXIST\") {\n throw error;\n }\n }\n if (await reclaimStaleLock(lockPath, staleMs)) {\n continue;\n }\n if (Date.now() > deadline) {\n throw new Error(`Timed out acquiring file lock at ${lockPath}`);\n }\n await sleep(pollMs);\n }\n}\n\nasync function releaseFileLock(lockPath: string, lock: FileLock): Promise<void> {\n await lock.handle.close();\n await removeOwnedLock(lockPath, lock.token);\n}\n\nexport interface WithLockOptions {\n readonly pollMs?: number;\n readonly staleMs?: number;\n readonly timeoutMs?: number;\n}\n\nexport async function withFileLock<T>(\n lockPath: string,\n work: () => Promise<T>,\n options?: WithLockOptions,\n): Promise<T> {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const pollMs = options?.pollMs ?? DEFAULT_POLL_MS;\n const staleMs = options?.staleMs ?? DEFAULT_STALE_MS;\n const lock = await acquireFileLock(lockPath, timeoutMs, pollMs, staleMs);\n try {\n return await work();\n } finally {\n await releaseFileLock(lockPath, lock);\n }\n}\n","import { isAbsolute } from \"node:path\";\n\nimport { resolveNodeTarget } from \"../cloud-foundry/node-process.js\";\nimport { isSafeSessionId } from \"../paths.js\";\nimport type { ActiveSession, SessionStatus, StateFile } from \"../types.js\";\n\nconst INVALID_SESSION = new Error(\"Invalid persisted debugger session\");\nconst VALID_STATUSES: ReadonlySet<string> = new Set<SessionStatus>([\n \"starting\",\n \"logging-in\",\n \"targeting\",\n \"ssh-enabling\",\n \"ssh-restarting\",\n \"signaling\",\n \"tunneling\",\n \"ready\",\n \"stopping\",\n \"stopped\",\n \"error\",\n]);\n\nfunction field(value: object, key: string): unknown {\n return Reflect.get(value, key);\n}\n\nfunction requireString(value: object, key: string): string {\n const candidate = field(value, key);\n if (typeof candidate !== \"string\" || candidate.length === 0) {\n throw INVALID_SESSION;\n }\n return candidate;\n}\n\nfunction optionalString(value: object, key: string): string | undefined {\n const candidate = field(value, key);\n if (candidate === undefined) {\n return undefined;\n }\n if (typeof candidate !== \"string\") {\n throw INVALID_SESSION;\n }\n return candidate;\n}\n\nfunction requireInteger(value: object, key: string, minimum: number, maximum: number): number {\n const candidate = field(value, key);\n if (!Number.isSafeInteger(candidate) || typeof candidate !== \"number\") {\n throw INVALID_SESSION;\n }\n if (candidate < minimum || candidate > maximum) {\n throw INVALID_SESSION;\n }\n return candidate;\n}\n\nfunction optionalInteger(value: object, key: string, minimum: number): number | undefined {\n const candidate = field(value, key);\n if (candidate === undefined) {\n return undefined;\n }\n if (!Number.isSafeInteger(candidate) || typeof candidate !== \"number\" || candidate < minimum) {\n throw INVALID_SESSION;\n }\n return candidate;\n}\n\nfunction requireSessionId(value: object): string {\n const sessionId = requireString(value, \"sessionId\");\n if (!isSafeSessionId(sessionId)) {\n throw INVALID_SESSION;\n }\n return sessionId;\n}\n\nfunction requireAbsolutePath(value: object, key: string): string {\n const path = requireString(value, key);\n if (!isAbsolute(path)) {\n throw INVALID_SESSION;\n }\n return path;\n}\n\nfunction requireTimestamp(value: object): string {\n const timestamp = requireString(value, \"startedAt\");\n if (Number.isNaN(Date.parse(timestamp))) {\n throw INVALID_SESSION;\n }\n return timestamp;\n}\n\nfunction optionalTimestamp(value: object, key: string): string | undefined {\n const timestamp = optionalString(value, key);\n if (timestamp !== undefined && Number.isNaN(Date.parse(timestamp))) {\n throw INVALID_SESSION;\n }\n return timestamp;\n}\n\nfunction isSessionStatus(value: string): value is SessionStatus {\n return VALID_STATUSES.has(value);\n}\n\nfunction requireStatus(value: object): SessionStatus {\n const status = requireString(value, \"status\");\n if (!isSessionStatus(status)) {\n throw INVALID_SESSION;\n }\n return status;\n}\n\nfunction decodeSession(value: unknown): ActiveSession | undefined {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n try {\n const processName = requireString(value, \"process\");\n const instance = requireInteger(value, \"instance\", 0, Number.MAX_SAFE_INTEGER);\n const nodePid = optionalInteger(value, \"nodePid\", 1);\n const target = resolveNodeTarget({\n process: processName,\n instance,\n ...(nodePid === undefined ? {} : { nodePid }),\n });\n const pid = requireInteger(value, \"pid\", 1, Number.MAX_SAFE_INTEGER);\n const controllerPid = requireInteger(value, \"controllerPid\", 1, Number.MAX_SAFE_INTEGER);\n const tunnelPid = optionalInteger(value, \"tunnelPid\", 1);\n const remoteNodePid = optionalInteger(value, \"remoteNodePid\", 1);\n const stopRequestedAt = optionalTimestamp(value, \"stopRequestedAt\");\n const message = optionalString(value, \"message\");\n const status = requireStatus(value);\n if (pid !== (tunnelPid ?? controllerPid) || (status === \"ready\" && tunnelPid === undefined)) {\n throw INVALID_SESSION;\n }\n return {\n sessionId: requireSessionId(value),\n pid,\n controllerPid,\n ...(tunnelPid === undefined ? {} : { tunnelPid }),\n hostname: requireString(value, \"hostname\"),\n region: requireString(value, \"region\"),\n org: requireString(value, \"org\"),\n space: requireString(value, \"space\"),\n app: requireString(value, \"app\"),\n process: target.process,\n instance: target.instance,\n ...(nodePid === undefined ? {} : { nodePid }),\n apiEndpoint: requireString(value, \"apiEndpoint\"),\n localPort: requireInteger(value, \"localPort\", 1, 65_535),\n remotePort: requireInteger(value, \"remotePort\", 1, 65_535),\n cfHomeDir: requireAbsolutePath(value, \"cfHomeDir\"),\n startedAt: requireTimestamp(value),\n status,\n ...(remoteNodePid === undefined ? {} : { remoteNodePid }),\n ...(stopRequestedAt === undefined ? {} : { stopRequestedAt }),\n ...(message === undefined ? {} : { message }),\n };\n } catch {\n return undefined;\n }\n}\n\nexport function decodeStateFile(value: unknown): StateFile | undefined {\n if (typeof value !== \"object\" || value === null || field(value, \"version\") !== \"2\") {\n return undefined;\n }\n const rawSessions = field(value, \"sessions\");\n if (!Array.isArray(rawSessions)) {\n return undefined;\n }\n const sessionIds = new Set<string>();\n const sessions: ActiveSession[] = [];\n for (const rawSession of rawSessions) {\n const session = decodeSession(rawSession);\n if (session === undefined || sessionIds.has(session.sessionId)) {\n return undefined;\n }\n sessionIds.add(session.sessionId);\n sessions.push(session);\n }\n return { version: \"2\", sessions };\n}\n","export const DEFAULT_TUNNEL_READY_TIMEOUT_MS = 180_000;\nexport const POST_USR1_DELAY_MS = 300;\nexport const CHILD_SIGTERM_GRACE_MS = 2_000;\nexport const CHILD_SIGKILL_GRACE_MS = 1_000;\nexport const PID_TERMINATION_POLL_MS = 100;\n","import { rm } from \"node:fs/promises\";\nimport { hostname as getHostname } from \"node:os\";\n\nimport { isOwnedSessionCfHomeDir } from \"../paths.js\";\nimport { readAndPruneActiveSessions } from \"../state.js\";\nimport type { ActiveSession } from \"../types.js\";\n\nexport interface PruneCleanupResult {\n readonly sessions: readonly ActiveSession[];\n readonly removed: readonly ActiveSession[];\n}\n\nexport async function pruneAndCleanupOrphans(): Promise<PruneCleanupResult> {\n const result = await readAndPruneActiveSessions();\n const host = getHostname();\n for (const removed of result.removed) {\n if (removed.hostname === host && isOwnedSessionCfHomeDir(removed.sessionId, removed.cfHomeDir)) {\n try {\n await rm(removed.cfHomeDir, { recursive: true, force: true });\n } catch {\n // A stale credential cache must not prevent cleanup of the state record.\n }\n }\n }\n return result;\n}\n","import type { ChildProcess } from \"node:child_process\";\nimport process from \"node:process\";\n\nimport { isPidAlive, isProcessGroupAlive } from \"../state.js\";\n\nimport {\n CHILD_SIGKILL_GRACE_MS,\n CHILD_SIGTERM_GRACE_MS,\n PID_TERMINATION_POLL_MS,\n} from \"./constants.js\";\n\ntype TerminationTargetKind = \"group\" | \"pid\";\nexport type TerminationOutcome = \"still-alive\" | \"terminated\";\n\nexport async function terminatePidOrGroup(\n pid: number,\n timeoutMs: number = CHILD_SIGTERM_GRACE_MS,\n pinnedTarget?: TerminationTargetKind,\n): Promise<TerminationOutcome> {\n const targetKind = pinnedTarget ?? (isProcessGroupAlive(pid) ? \"group\" : \"pid\");\n const targetAlive = (): boolean => targetKind === \"group\"\n ? isProcessGroupAlive(pid)\n : isPidAlive(pid);\n if (!targetAlive()) {\n return \"terminated\";\n }\n\n try {\n process.kill(targetKind === \"group\" ? -pid : pid, \"SIGTERM\");\n } catch {\n // target already gone\n }\n const startedAt = Date.now();\n while (Date.now() - startedAt < timeoutMs) {\n if (!targetAlive()) {\n return \"terminated\";\n }\n await new Promise<void>((resolve) => {\n setTimeout(resolve, PID_TERMINATION_POLL_MS);\n });\n }\n\n try {\n process.kill(targetKind === \"group\" ? -pid : pid, \"SIGKILL\");\n } catch {\n // target already gone\n }\n const forceStartedAt = Date.now();\n while (Date.now() - forceStartedAt < CHILD_SIGKILL_GRACE_MS) {\n if (!targetAlive()) {\n return \"terminated\";\n }\n await new Promise<void>((resolve) => {\n setTimeout(resolve, PID_TERMINATION_POLL_MS);\n });\n }\n return targetAlive() ? \"still-alive\" : \"terminated\";\n}\n\nexport async function killProcessGroupOrProc(\n child: ChildProcess,\n timeoutMs: number = CHILD_SIGTERM_GRACE_MS,\n): Promise<TerminationOutcome> {\n if (child.pid === undefined) {\n return \"terminated\";\n }\n const childClosed = child.exitCode !== null || child.signalCode !== null;\n if (childClosed && process.platform === \"win32\") {\n return \"terminated\";\n }\n return await terminatePidOrGroup(child.pid, timeoutMs, childClosed ? \"group\" : undefined);\n}\n","import { readSessionSnapshot } from \"../state.js\";\nimport type { ActiveSession } from \"../types.js\";\n\nconst STOP_REQUEST_POLL_MS = 50;\n\nexport interface StartupCancellation {\n readonly signal: AbortSignal;\n dispose(): void;\n}\n\nfunction cancellationRequested(\n sessions: readonly ActiveSession[],\n sessionId: string,\n): boolean {\n const session = sessions.find((candidate) => candidate.sessionId === sessionId);\n return session === undefined || session.stopRequestedAt !== undefined;\n}\n\nexport function createStartupCancellation(\n sessionId: string,\n callerSignal?: AbortSignal,\n): StartupCancellation {\n const controller = new AbortController();\n let active = true;\n let timer: NodeJS.Timeout | undefined;\n const onCallerAbort = (): void => {\n controller.abort();\n };\n const schedule = (): void => {\n timer = setTimeout(() => { void poll(); }, STOP_REQUEST_POLL_MS);\n timer.unref();\n };\n const poll = async (): Promise<void> => {\n try {\n const sessions = await readSessionSnapshot();\n if (active && cancellationRequested(sessions, sessionId)) {\n controller.abort();\n }\n } catch {\n // A lifecycle transition still validates state under the lock after transient read failures.\n }\n if (active && !controller.signal.aborted) {\n schedule();\n }\n };\n\n callerSignal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n if (callerSignal?.aborted === true) {\n controller.abort();\n } else {\n void poll();\n }\n return {\n signal: controller.signal,\n dispose: (): void => {\n active = false;\n clearTimeout(timer);\n callerSignal?.removeEventListener(\"abort\", onCallerAbort);\n },\n };\n}\n","import { rm } from \"node:fs/promises\";\nimport { hostname as getHostname } from \"node:os\";\nimport process from \"node:process\";\n\nimport { isOwnedSessionCfHomeDir } from \"../paths.js\";\nimport { findListeningProcessId, isPortListening } from \"../port.js\";\nimport {\n isPidAlive,\n isPidOrGroupAlive,\n matchesKey,\n readActiveSessions,\n readSessionSnapshot,\n removeSession,\n requestSessionStop,\n} from \"../state.js\";\nimport type { ActiveSession, SessionKey } from \"../types.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nimport { terminatePidOrGroup, type TerminationOutcome } from \"./processes.js\";\n\nexport interface StopOptions {\n readonly sessionId?: string;\n readonly key?: SessionKey;\n}\n\nexport interface StopDebuggerResult extends ActiveSession {\n readonly stale: boolean;\n readonly pending: boolean;\n}\n\nfunction findMatchingSession(\n sessions: readonly ActiveSession[],\n options: StopOptions,\n): ActiveSession | undefined {\n if (options.sessionId !== undefined) {\n return sessions.find((s) => s.sessionId === options.sessionId);\n }\n if (options.key !== undefined) {\n const key = options.key;\n const matches = sessions.filter((session) => matchesKey(session, key));\n if (matches.length > 1) {\n throw new CfDebuggerError(\n \"SESSION_AMBIGUOUS\",\n \"Multiple debugger sessions match this target. Pass an exact session ID, API endpoint, or Node PID.\",\n );\n }\n return matches[0];\n }\n return undefined;\n}\n\nasync function ownsRecordedTunnel(target: ActiveSession): Promise<boolean> {\n if (target.tunnelPid === undefined || !(await isPortListening(target.localPort))) {\n return false;\n }\n return await findListeningProcessId(target.localPort) === target.tunnelPid;\n}\n\nasync function terminateVerifiedTunnel(target: ActiveSession): Promise<TerminationOutcome> {\n if (target.tunnelPid !== undefined && target.tunnelPid !== process.pid) {\n try {\n return await terminatePidOrGroup(target.tunnelPid);\n } catch {\n return \"still-alive\";\n }\n }\n return target.tunnelPid === process.pid ? \"still-alive\" : \"terminated\";\n}\n\nasync function terminateVerifiedTunnelAndConfirm(target: ActiveSession): Promise<void> {\n const termination = await terminateVerifiedTunnel(target);\n if (termination === \"still-alive\" || await ownsRecordedTunnel(target)) {\n throw new CfDebuggerError(\n \"TUNNEL_TERMINATION_FAILED\",\n `Tunnel process for session ${target.sessionId} did not terminate; state was retained.`,\n );\n }\n}\n\nasync function cleanupOwnedCfHome(target: ActiveSession, locallyOwned: boolean): Promise<void> {\n if (locallyOwned && isOwnedSessionCfHomeDir(target.sessionId, target.cfHomeDir)) {\n try {\n await rm(target.cfHomeDir, { recursive: true, force: true });\n } catch {\n // best-effort\n }\n }\n}\n\nasync function removeOwnedSession(\n target: ActiveSession,\n stale: boolean,\n): Promise<StopDebuggerResult> {\n const removed = await removeSession(target.sessionId);\n await cleanupOwnedCfHome(target, true);\n return { ...(removed ?? target), stale, pending: false };\n}\n\nfunction ownershipError(target: ActiveSession): CfDebuggerError {\n return new CfDebuggerError(\n \"TUNNEL_OWNERSHIP_UNVERIFIED\",\n `Cannot safely stop session ${target.sessionId}: local tunnel ownership could not be verified.`,\n );\n}\n\nasync function stopReadySession(target: ActiveSession): Promise<StopDebuggerResult> {\n if (await ownsRecordedTunnel(target)) {\n await terminateVerifiedTunnelAndConfirm(target);\n return await removeOwnedSession(target, false);\n }\n const tunnelDead = target.tunnelPid !== undefined && !isPidOrGroupAlive(target.tunnelPid);\n if (tunnelDead && !(await isPortListening(target.localPort))) {\n return await removeOwnedSession(target, true);\n }\n throw ownershipError(target);\n}\n\nasync function stopStartingSession(target: ActiveSession): Promise<StopDebuggerResult> {\n if (\n target.status === \"stopping\" &&\n target.tunnelPid !== undefined &&\n !isPidOrGroupAlive(target.tunnelPid) &&\n !(await isPortListening(target.localPort))\n ) {\n return await removeOwnedSession(target, true);\n }\n if (isPidAlive(target.controllerPid ?? target.pid)) {\n return { ...target, stale: false, pending: true };\n }\n if (await ownsRecordedTunnel(target)) {\n await terminateVerifiedTunnelAndConfirm(target);\n return await removeOwnedSession(target, false);\n }\n const tunnelAlive = target.tunnelPid !== undefined && isPidOrGroupAlive(target.tunnelPid);\n if (!tunnelAlive && !(await isPortListening(target.localPort))) {\n return await removeOwnedSession(target, true);\n }\n throw ownershipError(target);\n}\n\nexport async function stopDebugger(options: StopOptions): Promise<StopDebuggerResult | undefined> {\n const localSessions = (await readSessionSnapshot()).filter(\n (session) => session.hostname === getHostname(),\n );\n const target = findMatchingSession(localSessions, options);\n if (target === undefined) {\n return undefined;\n }\n const claim = await requestSessionStop(target.sessionId);\n if (claim === undefined) {\n return undefined;\n }\n return claim.previousStatus === \"ready\"\n ? await stopReadySession(claim.session)\n : await stopStartingSession(claim.session);\n}\n\nexport async function stopAllDebuggers(): Promise<number> {\n const sessions = (await readSessionSnapshot()).filter(\n (session) => session.hostname === getHostname(),\n );\n let stopped = 0;\n for (const session of sessions) {\n const result = await stopDebugger({ sessionId: session.sessionId });\n if (result) {\n stopped += 1;\n }\n }\n return stopped;\n}\n\nexport async function listSessions(): Promise<readonly ActiveSession[]> {\n return await readActiveSessions();\n}\n\nexport async function getSession(key: SessionKey): Promise<ActiveSession | undefined> {\n const sessions = await readActiveSessions();\n return findMatchingSession(sessions, { key });\n}\n"],"mappings":"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","names":["process","execFile","promisify","field","execFileAsync","promisify","execFile","execFileAsync","field","chmod","mkdir","rm","process","execFile","promisify","execFileAsync","promisify","execFile","randomUUID","chmod","mkdir","readFile","unlink","dirname","isAbsolute","process","readFile","process","isAbsolute","field","optionalString","isAbsolute","errorCode","chmod","readFile","process","randomUUID","dirname","mkdir","unlink","session","isAbsolute","getHostname","getHostname","process","process","process","mkdir","chmod","rm","rm","getHostname","process","process","rm","getHostname","process"]}